Add AES KW inverse ciphers to the EVP layer
[openssl.git] / crypto / ex_data.c
index d9dd3d2aed119f71f68bd00a6e007b4a4a7088c7..3b06c0b90efff8a127badc87ec383ddf906b6570 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -7,12 +7,12 @@
  * https://www.openssl.org/source/license.html
  */
 
-#include "internal/cryptlib_int.h"
+#include "crypto/cryptlib.h"
 #include "internal/thread_once.h"
 
-int do_ex_data_init(OPENSSL_CTX *ctx)
+int do_ex_data_init(OSSL_LIB_CTX *ctx)
 {
-    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ctx);
+    OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ctx);
 
     if (global == NULL)
         return 0;
@@ -24,33 +24,27 @@ int do_ex_data_init(OPENSSL_CTX *ctx)
 /*
  * Return the EX_CALLBACKS from the |ex_data| array that corresponds to
  * a given class.  On success, *holds the lock.*
+ * The |global| parameter is assumed to be non null (checked by the caller).
  */
-static EX_CALLBACKS *get_and_lock(OPENSSL_CTX *ctx, int class_index)
+static EX_CALLBACKS *get_and_lock(OSSL_EX_DATA_GLOBAL *global, int class_index)
 {
     EX_CALLBACKS *ip;
-    OSSL_EX_DATA_GLOBAL *global = NULL;
 
     if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT) {
         CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_PASSED_INVALID_ARGUMENT);
         return NULL;
     }
 
-    global = openssl_ctx_get_ex_data_global(ctx);
     if (global->ex_data_lock == NULL) {
         /*
-         * This can happen in normal operation when using CRYPTO_mem_leaks().
-         * The CRYPTO_mem_leaks() function calls OPENSSL_cleanup() which cleans
-         * up the locks. Subsequently the BIO that CRYPTO_mem_leaks() uses gets
-         * freed, which also attempts to free the ex_data. However
-         * CRYPTO_mem_leaks() ensures that the ex_data is freed early (i.e.
-         * before OPENSSL_cleanup() is called), so if we get here we can safely
-         * ignore this operation. We just treat it as an error.
+         * If we get here, someone (who?) cleaned up the lock, so just
+         * treat it as an error.
          */
          return NULL;
     }
 
-    ip = &global->ex_data[class_index];
     CRYPTO_THREAD_write_lock(global->ex_data_lock);
+    ip = &global->ex_data[class_index];
     return ip;
 }
 
@@ -65,10 +59,10 @@ static void cleanup_cb(EX_CALLBACK *funcs)
  * called under potential race-conditions anyway (it's for program shutdown
  * after all).
  */
-void crypto_cleanup_all_ex_data_int(OPENSSL_CTX *ctx)
+void crypto_cleanup_all_ex_data_int(OSSL_LIB_CTX *ctx)
 {
     int i;
-    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ctx);
+    OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ctx);
 
     if (global == NULL)
         return;
@@ -100,25 +94,26 @@ static void dummy_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
 }
 
 static int dummy_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
-                     void *from_d, int idx,
+                     void **from_d, int idx,
                      long argl, void *argp)
 {
     return 1;
 }
 
-int crypto_free_ex_index_ex(OPENSSL_CTX *ctx, int class_index, int idx)
+int crypto_free_ex_index_ex(OSSL_LIB_CTX *ctx, int class_index, int idx)
 {
-    EX_CALLBACKS *ip = get_and_lock(ctx, class_index);
+    EX_CALLBACKS *ip;
     EX_CALLBACK *a;
     int toret = 0;
-    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ctx);
+    OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ctx);
 
     if (global == NULL)
-        goto err;
+        return 0;
 
-    ip = get_and_lock(ctx, class_index);
+    ip = get_and_lock(global, class_index);
     if (ip == NULL)
         return 0;
+
     if (idx < 0 || idx >= sk_EX_CALLBACK_num(ip->meth))
         goto err;
     a = sk_EX_CALLBACK_value(ip->meth, idx);
@@ -141,7 +136,7 @@ int CRYPTO_free_ex_index(int class_index, int idx)
 /*
  * Register a new index.
  */
-int crypto_get_ex_new_index_ex(OPENSSL_CTX *ctx, int class_index, long argl,
+int crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index, long argl,
                                void *argp, CRYPTO_EX_new *new_func,
                                CRYPTO_EX_dup *dup_func,
                                CRYPTO_EX_free *free_func)
@@ -149,12 +144,12 @@ int crypto_get_ex_new_index_ex(OPENSSL_CTX *ctx, int class_index, long argl,
     int toret = -1;
     EX_CALLBACK *a;
     EX_CALLBACKS *ip;
-    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ctx);
+    OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ctx);
 
     if (global == NULL)
-        goto err;
+        return -1;
 
-    ip = get_and_lock(ctx, class_index);
+    ip = get_and_lock(global, class_index);
     if (ip == NULL)
         return -1;
 
@@ -208,7 +203,7 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
  * in the lock, then using them outside the lock. Note this only applies
  * to the global "ex_data" state (ie. class definitions), not 'ad' itself.
  */
-int crypto_new_ex_data_ex(OPENSSL_CTX *ctx, int class_index, void *obj,
+int crypto_new_ex_data_ex(OSSL_LIB_CTX *ctx, int class_index, void *obj,
                           CRYPTO_EX_DATA *ad)
 {
     int mx, i;
@@ -216,18 +211,17 @@ int crypto_new_ex_data_ex(OPENSSL_CTX *ctx, int class_index, void *obj,
     EX_CALLBACK **storage = NULL;
     EX_CALLBACK *stack[10];
     EX_CALLBACKS *ip;
-    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ctx);
+    OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ctx);
 
     if (global == NULL)
         return 0;
 
-    ip = get_and_lock(ctx, class_index);
+    ip = get_and_lock(global, class_index);
     if (ip == NULL)
         return 0;
 
     ad->ctx = ctx;
     ad->sk = NULL;
-
     mx = sk_EX_CALLBACK_num(ip->meth);
     if (mx > 0) {
         if (mx < (int)OSSL_NELEM(stack))
@@ -274,16 +268,19 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
     EX_CALLBACK **storage = NULL;
     EX_CALLBACKS *ip;
     int toret = 0;
-    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(from->ctx);
-
-    if (global == NULL)
-        return 0;
+    OSSL_EX_DATA_GLOBAL *global;
 
     to->ctx = from->ctx;
     if (from->sk == NULL)
         /* Nothing to copy over */
         return 1;
-    if ((ip = get_and_lock(from->ctx, class_index)) == NULL)
+
+    global = ossl_lib_ctx_get_ex_data_global(from->ctx);
+    if (global == NULL)
+        return 0;
+
+    ip = get_and_lock(global, class_index);
+    if (ip == NULL)
         return 0;
 
     mx = sk_EX_CALLBACK_num(ip->meth);
@@ -345,14 +342,15 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
     EX_CALLBACK *f;
     EX_CALLBACK *stack[10];
     EX_CALLBACK **storage = NULL;
-    OSSL_EX_DATA_GLOBAL *global;
+    OSSL_EX_DATA_GLOBAL *global = ossl_lib_ctx_get_ex_data_global(ad->ctx);
 
-    if ((ip = get_and_lock(ad->ctx, class_index)) == NULL)
-        goto err;
-    global = openssl_ctx_get_ex_data_global(ad->ctx);
     if (global == NULL)
         goto err;
 
+    ip = get_and_lock(global, class_index);
+    if (ip == NULL)
+        goto err;
+
     mx = sk_EX_CALLBACK_num(ip->meth);
     if (mx > 0) {
         if (mx < (int)OSSL_NELEM(stack))
@@ -397,18 +395,18 @@ int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
     EX_CALLBACK *f;
     EX_CALLBACKS *ip;
     void *curval;
-    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ad->ctx);
-
-    if (global == NULL)
-        return 0;
+    OSSL_EX_DATA_GLOBAL *global;
 
     curval = CRYPTO_get_ex_data(ad, idx);
-
     /* Already there, no need to allocate */
     if (curval != NULL)
         return 1;
 
-    ip = get_and_lock(ad->ctx, class_index);
+    global = ossl_lib_ctx_get_ex_data_global(ad->ctx);
+    if (global == NULL)
+        return 0;
+
+    ip = get_and_lock(global, class_index);
     if (ip == NULL)
         return 0;
     f = sk_EX_CALLBACK_value(ip->meth, idx);
@@ -421,7 +419,7 @@ int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
     if (f->new_func == NULL)
         return 0;
 
-    f->new_func(obj, curval, ad, idx, f->argl, f->argp);
+    f->new_func(obj, NULL, ad, idx, f->argl, f->argp);
 
     return 1;
 }
@@ -447,7 +445,11 @@ int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val)
             return 0;
         }
     }
-    sk_void_set(ad->sk, idx, val);
+    if (sk_void_set(ad->sk, idx, val) != val) {
+        /* Probably the index is out of bounds */
+        CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA, ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
     return 1;
 }
 
@@ -462,7 +464,7 @@ void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx)
     return sk_void_value(ad->sk, idx);
 }
 
-OPENSSL_CTX *crypto_ex_data_get_openssl_ctx(const CRYPTO_EX_DATA *ad)
+OSSL_LIB_CTX *crypto_ex_data_get_ossl_lib_ctx(const CRYPTO_EX_DATA *ad)
 {
     return ad->ctx;
 }