Add a copy of OSSL_SELF_TEST_get_callback() to the fips module.
authorShane Lontis <shane.lontis@oracle.com>
Tue, 15 Sep 2020 04:32:40 +0000 (14:32 +1000)
committerShane Lontis <shane.lontis@oracle.com>
Sat, 19 Sep 2020 08:21:09 +0000 (18:21 +1000)
The user can set up a self test callback that should be activated when a keygen operation (e.g ec) occurs for the fips module.
The callback information is stored inside the applications library context, but this was not being triggered since the
library context used for the key generation operation was the internal library context used by the fips module (which is not
the same as the application's library context). During the keygen operation the OSSL_SELF_TEST_get_callback() function is used
to retrieve the callback info.
By having a seperate copy of OSSL_SELF_TEST_get_callback() for the fips module we can ensure that the parent library context
is used instead.
The core OSSL_SELF_TEST_get_callback() function pointer is passed across the boundary during the fips modules entry point
such that the fips version of the function can call it after changing the libctx.

Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12877)

crypto/self_test_core.c
providers/fips/fipsprov.c
test/acvp_test.c
test/evp_libctx_test.c

index ca8925abe50be92ddbd1102843bb93a7357c6745..7aa8490ddf47da5e5b78b99c5ccc161d233414e9 100644 (file)
@@ -31,6 +31,7 @@ struct ossl_self_test_st
     void *cb_arg;
 };
 
+#ifndef FIPS_MODULE
 static void *self_test_set_callback_new(OPENSSL_CTX *ctx)
 {
     SELF_TEST_CB *stcb;
@@ -55,7 +56,6 @@ static SELF_TEST_CB *get_self_test_callback(OPENSSL_CTX *libctx)
                                 &self_test_set_callback_method);
 }
 
-#ifndef FIPS_MODULE
 void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb,
                                  void *cbarg)
 {
@@ -66,7 +66,6 @@ void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb,
         stcb->cbarg = cbarg;
     }
 }
-#endif /* FIPS_MODULE */
 
 void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
                                  void **cbarg)
@@ -78,6 +77,7 @@ void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
     if (cbarg != NULL)
         *cbarg = (stcb != NULL ? stcb->cbarg : NULL);
 }
+#endif /* FIPS_MODULE */
 
 static void self_test_setparams(OSSL_SELF_TEST *st)
 {
index 9cf43eb49190bd9568dd2c42feb68d10e42de7c1..d2ea505230c3b9cdb3d25526f1d3c153da8b61b0 100644 (file)
@@ -886,3 +886,20 @@ int FIPS_security_check_enabled(void)
 {
     return fips_security_checks;
 }
+
+void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
+                                 void **cbarg)
+{
+    if (libctx == NULL)
+        libctx = selftest_params.libctx;
+
+    if (c_stcbfn != NULL && c_get_libctx != NULL) {
+        /* Get the parent libctx */
+        c_stcbfn(c_get_libctx(FIPS_get_core_handle(libctx)), cb, cbarg);
+    } else {
+        if (cb != NULL)
+            *cb = NULL;
+        if (cbarg != NULL)
+            *cbarg = NULL;
+    }
+}
index b33881d4dbf621ef0311a61479607881000a0edd..3e9631065ad08c1ec5a30dcb8ed0dc364468ffce 100644 (file)
@@ -14,6 +14,7 @@
  * providers/fips/self_test_kats.c
  */
 
+#include <string.h>
 #include <openssl/opensslconf.h> /* To see if OPENSSL_NO_EC is defined */
 #include <openssl/core_names.h>
 #include <openssl/evp.h>
 #include <openssl/rsa.h>
 #include <openssl/param_build.h>
 #include <openssl/provider.h>
+#include <openssl/self_test.h>
 #include "testutil.h"
 #include "testutil/output.h"
 #include "acvp_test.inc"
 #include "internal/nelem.h"
 
-static OSSL_PROVIDER *prov_null = NULL;
-static OPENSSL_CTX *libctx = NULL;
-
 typedef enum OPTION_choice {
     OPT_ERR = -1,
     OPT_EOF = 0,
@@ -38,6 +37,16 @@ typedef enum OPTION_choice {
     OPT_TEST_ENUM
 } OPTION_CHOICE;
 
+typedef struct st_args {
+    int enable;
+    int called;
+} SELF_TEST_ARGS;
+
+static OSSL_PROVIDER *prov_null = NULL;
+static OPENSSL_CTX *libctx = NULL;
+static SELF_TEST_ARGS self_test_args = { 0 };
+static OSSL_CALLBACK self_test_events;
+
 const OPTIONS *test_get_options(void)
 {
     static const OPTIONS test_options[] = {
@@ -119,10 +128,13 @@ static int ecdsa_keygen_test(int id)
     size_t priv_len = 0, pubx_len = 0, puby_len = 0;
     const struct ecdsa_keygen_st *tst = &ecdsa_keygen_data[id];
 
+    self_test_args.called = 0;
+    self_test_args.enable = 1;
     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL))
         || !TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0)
         || !TEST_true(EVP_PKEY_CTX_set_group_name(ctx, tst->curve_name))
         || !TEST_int_gt(EVP_PKEY_keygen(ctx, &pkey), 0)
+        || !TEST_int_eq(self_test_args.called, 3)
         || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv,
                                         &priv_len))
         || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &pubx,
@@ -136,6 +148,8 @@ static int ecdsa_keygen_test(int id)
     test_output_memory("d", priv, priv_len);
     ret = 1;
 err:
+    self_test_args.enable = 0;
+    self_test_args.called = 0;
     OPENSSL_clear_free(priv, priv_len);
     OPENSSL_free(pubx);
     OPENSSL_free(puby);
@@ -1292,6 +1306,37 @@ err:
 }
 #endif /* OPENSSL_NO_RSA */
 
+static int self_test_events(const OSSL_PARAM params[], void *varg)
+{
+    SELF_TEST_ARGS *args = varg;
+    const OSSL_PARAM *p = NULL;
+    const char *phase = NULL, *type = NULL, *desc = NULL;
+    int ret = 0;
+
+    if (!args->enable)
+        return 1;
+
+    args->called++;
+    p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);
+    if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+        goto err;
+    phase = (const char *)p->data;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC);
+    if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+        goto err;
+    desc = (const char *)p->data;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);
+    if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
+        goto err;
+    type = (const char *)p->data;
+
+    BIO_printf(bio_out, "%s %s %s\n", phase, desc, type);
+    ret = 1;
+err:
+    return ret;
+}
 
 int setup_tests(void)
 {
@@ -1324,6 +1369,7 @@ int setup_tests(void)
         opt_printf_stderr("Failed to load config\n");
         return 0;
     }
+    OSSL_SELF_TEST_set_callback(libctx, self_test_events, &self_test_args);
 
     ADD_ALL_TESTS(cipher_enc_dec_test, OSSL_NELEM(cipher_enc_data));
     ADD_ALL_TESTS(aes_ccm_enc_dec_test, OSSL_NELEM(aes_ccm_enc_data));
index e42d6683e7083fb4e5ee8db8dc62b65f9d2fb134..4325cc272fabaeb95ac6049dba5aac4930d76d3f 100644 (file)
@@ -644,14 +644,11 @@ int setup_tests(void)
         return 0;
 
     libctx = OPENSSL_CTX_new();
-
     if (!TEST_ptr(libctx))
         return 0;
-
-    if (config_file != NULL) {
-        if (!TEST_true(OPENSSL_CTX_load_config(libctx, config_file)))
-            return 0;
-    }
+    if (config_file != NULL
+        && !TEST_true(OPENSSL_CTX_load_config(libctx, config_file)))
+        return 0;
 
     libprov = OSSL_PROVIDER_load(libctx, prov_name);
     if (!TEST_ptr(libprov))