summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/fipsinstall.c77
-rw-r--r--crypto/build.info2
-rw-r--r--crypto/provider_core.c5
-rw-r--r--crypto/self_test_core.c62
-rw-r--r--doc/man1/openssl-fipsinstall.pod25
-rw-r--r--doc/man3/OSSL_SELF_TEST_set_callback.pod50
-rw-r--r--doc/man7/OSSL_PROVIDER-FIPS.pod260
-rw-r--r--doc/man7/provider-base.pod3
-rw-r--r--include/internal/cryptlib.h3
-rw-r--r--include/internal/provider.h1
-rw-r--r--include/openssl/core_names.h35
-rw-r--r--include/openssl/core_numbers.h5
-rw-r--r--include/openssl/self_test.h68
-rw-r--r--providers/fips/build.info3
-rw-r--r--providers/fips/fipsprov.c20
-rw-r--r--providers/fips/self_test.c (renamed from providers/fips/selftest.c)21
-rw-r--r--providers/fips/self_test.h (renamed from providers/fips/selftest.h)24
-rw-r--r--providers/fips/self_test_data.inc191
-rw-r--r--providers/fips/self_test_event.c93
-rw-r--r--providers/fips/self_test_kats.c246
-rw-r--r--test/recipes/03-test_fipsinstall.t23
-rw-r--r--util/libcrypto.num2
22 files changed, 1181 insertions, 38 deletions
diff --git a/apps/fipsinstall.c b/apps/fipsinstall.c
index 739df23d44..564b208230 100644
--- a/apps/fipsinstall.c
+++ b/apps/fipsinstall.c
@@ -13,6 +13,8 @@
#include <openssl/provider.h>
#include <openssl/params.h>
#include <openssl/fips_names.h>
+#include <openssl/core_names.h>
+#include <openssl/self_test.h>
#include "apps.h"
#include "progs.h"
@@ -25,10 +27,16 @@
#define VERSION_VAL "1"
#define INSTALL_STATUS_VAL "INSTALL_SELF_TEST_KATS_RUN"
+static OSSL_CALLBACK self_test_events;
+static char *self_test_corrupt_desc = NULL;
+static char *self_test_corrupt_type = NULL;
+static int self_test_log = 1;
+
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_IN, OPT_OUT, OPT_MODULE,
- OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY
+ OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY,
+ OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE
} OPTION_CHOICE;
const OPTIONS fipsinstall_options[] = {
@@ -49,6 +57,9 @@ const OPTIONS fipsinstall_options[] = {
{"mac_name", OPT_MAC_NAME, 's', "MAC name"},
{"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. "
"See 'PARAMETER NAMES' in the EVP_MAC_ docs"},
+ {"noout", OPT_NO_LOG, '-', "Disable logging of self test events"},
+ {"corrupt_desc", OPT_CORRUPT_DESC, 's', "Corrupt a self test by description"},
+ {"corrupt_type", OPT_CORRUPT_TYPE, 's', "Corrupt a self test by type"},
{NULL}
};
@@ -287,6 +298,15 @@ opthelp:
case OPT_OUT:
out_fname = opt_arg();
break;
+ case OPT_NO_LOG:
+ self_test_log = 0;
+ break;
+ case OPT_CORRUPT_DESC:
+ self_test_corrupt_desc = opt_arg();
+ break;
+ case OPT_CORRUPT_TYPE:
+ self_test_corrupt_type = opt_arg();
+ break;
case OPT_PROV_NAME:
prov_name = opt_arg();
break;
@@ -318,6 +338,11 @@ opthelp:
|| argc != 0)
goto opthelp;
+ if (self_test_log
+ || self_test_corrupt_desc != NULL
+ || self_test_corrupt_type != NULL)
+ OSSL_SELF_TEST_set_callback(NULL, self_test_events, NULL);
+
module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY);
if (module_bio == NULL) {
BIO_printf(bio_err, "Failed to open module file\n");
@@ -420,3 +445,53 @@ end:
free_config_and_unload(conf);
return ret;
}
+
+static int self_test_events(const OSSL_PARAM params[], void *arg)
+{
+ const OSSL_PARAM *p = NULL;
+ const char *phase = NULL, *type = NULL, *desc = NULL;
+ int ret = 0;
+
+ 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;
+
+ if (self_test_log) {
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)
+ BIO_printf(bio_out, "%s : (%s) : ", desc, type);
+ else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0
+ || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)
+ BIO_printf(bio_out, "%s\n", phase);
+ }
+ /*
+ * The self test code will internally corrupt the KAT test result if an
+ * error is returned during the corrupt phase.
+ */
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0
+ && (self_test_corrupt_desc != NULL
+ || self_test_corrupt_type != NULL)) {
+ if (self_test_corrupt_desc != NULL
+ && strcmp(self_test_corrupt_desc, desc) != 0)
+ goto end;
+ if (self_test_corrupt_type != NULL
+ && strcmp(self_test_corrupt_type, type) != 0)
+ goto end;
+ BIO_printf(bio_out, "%s ", phase);
+ goto err;
+ }
+end:
+ ret = 1;
+err:
+ return ret;
+}
diff --git a/crypto/build.info b/crypto/build.info
index ab10a1cfe6..daa26b8ed4 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -62,7 +62,7 @@ ENDIF
$CORE_COMMON=provider_core.c provider_predefined.c \
core_fetch.c core_algorithm.c core_namemap.c
-SOURCE[../libcrypto]=$CORE_COMMON provider_conf.c
+SOURCE[../libcrypto]=$CORE_COMMON provider_conf.c self_test_core.c
SOURCE[../providers/libfips.a]=$CORE_COMMON
# Central utilities
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index c95615f882..2f2d69a0c3 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -18,6 +18,9 @@
#include "internal/provider.h"
#include "internal/refcount.h"
#include "provider_local.h"
+#ifndef FIPS_MODE
+# include <openssl/self_test.h>
+#endif
static OSSL_PROVIDER *provider_new(const char *name,
OSSL_provider_init_fn *init_function);
@@ -874,8 +877,8 @@ static const OSSL_DISPATCH core_dispatch_[] = {
{ OSSL_FUNC_BIO_READ_EX, (void (*)(void))BIO_read_ex },
{ OSSL_FUNC_BIO_FREE, (void (*)(void))BIO_free },
{ OSSL_FUNC_BIO_VPRINTF, (void (*)(void))BIO_vprintf },
+ { OSSL_FUNC_SELF_TEST_CB, (void (*)(void))OSSL_SELF_TEST_get_callback },
#endif
-
{ OSSL_FUNC_CRYPTO_MALLOC, (void (*)(void))CRYPTO_malloc },
{ OSSL_FUNC_CRYPTO_ZALLOC, (void (*)(void))CRYPTO_zalloc },
{ OSSL_FUNC_CRYPTO_FREE, (void (*)(void))CRYPTO_free },
diff --git a/crypto/self_test_core.c b/crypto/self_test_core.c
new file mode 100644
index 0000000000..77864a230b
--- /dev/null
+++ b/crypto/self_test_core.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2019 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/self_test.h>
+#include "internal/cryptlib.h"
+
+typedef struct self_test_cb_st
+{
+ OSSL_CALLBACK *cb;
+ void *cbarg;
+} SELF_TEST_CB;
+
+static void *self_test_set_callback_new(OPENSSL_CTX *ctx)
+{
+ SELF_TEST_CB *stcb;
+
+ stcb = OPENSSL_zalloc(sizeof(*stcb));
+ return stcb;
+}
+
+static void self_test_set_callback_free(void *stcb)
+{
+ OPENSSL_free(stcb);
+}
+
+static const OPENSSL_CTX_METHOD self_test_set_callback_method = {
+ self_test_set_callback_new,
+ self_test_set_callback_free,
+};
+
+static SELF_TEST_CB *get_self_test_callback(OPENSSL_CTX *libctx)
+{
+ return openssl_ctx_get_data(libctx, OPENSSL_CTX_SELF_TEST_CB_INDEX,
+ &self_test_set_callback_method);
+}
+
+void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb,
+ void *cbarg)
+{
+ SELF_TEST_CB *stcb = get_self_test_callback(libctx);
+
+ if (stcb != NULL) {
+ stcb->cb = cb;
+ stcb->cbarg = cbarg;
+ }
+}
+void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
+ void **cbarg)
+{
+ SELF_TEST_CB *stcb = get_self_test_callback(libctx);
+
+ if (cb != NULL)
+ *cb = (stcb != NULL ? stcb->cb : NULL);
+ if (cbarg != NULL)
+ *cbarg = (stcb != NULL ? stcb->cbarg : NULL);
+}
diff --git a/doc/man1/openssl-fipsinstall.pod b/doc/man1/openssl-fipsinstall.pod
index 44f6e0e410..7cad6091e1 100644
--- a/doc/man1/openssl-fipsinstall.pod
+++ b/doc/man1/openssl-fipsinstall.pod
@@ -16,6 +16,9 @@ B<openssl fipsinstall>
[B<-verify>]
[B<-mac_name> I<macname>]
[B<-macopt> I<nm>:I<v>]
+[B<-noout>]
+[B<-corrupt_desc> I<selftest_description>]
+[B<-corrupt_type> I<selftest_type>]
=head1 DESCRIPTION
@@ -106,6 +109,20 @@ C<openssl list -digest-commands>.
=back
+=item B<-noout>
+
+Disable logging of the self tests.
+
+=item B<-corrupt_desc> I<selftest_description>
+
+=item B<-corrupt_type> I<selftest_type>
+
+The corrupt options can be used to test failure of one or more self test(s) by
+name.
+Either option or both may be used to select the self test(s) to corrupt.
+Refer to the entries for "st-desc" and "st-type" in L<OSSL_PROVIDER-FIPS(7)> for
+values that can be used.
+
=back
=head1 EXAMPLES
@@ -123,6 +140,13 @@ Verify that the configuration file F<fips.conf> contains the correct info:
-section_name fips_install -mac_name HMAC -macopt digest:SHA256 \
-macopt hexkey:000102030405060708090A0B0C0D0E0F10111213 -verify
+Corrupt any self tests which have the description 'SHA1':
+
+ openssl fipsinstall -module ./fips.so -out fips.conf -provider_name fips \
+ -section_name fipsinstall -mac_name HMAC -macopt digest:SHA256 \
+ -macopt hexkey:000102030405060708090A0B0C0D0E0F10111213 \
+ -corrupt_desc', 'SHA1'
+
=head1 NOTES
The MAC mechanisms that are available will depend on the options
@@ -132,6 +156,7 @@ The command C<openssl list -mac-algorithms> command can be used to list them.
=head1 SEE ALSO
L<fips_config(5)>,
+L<OSSL_PROVIDER-FIPS(7)>,
L<EVP_MAC(3)>
=head1 COPYRIGHT
diff --git a/doc/man3/OSSL_SELF_TEST_set_callback.pod b/doc/man3/OSSL_SELF_TEST_set_callback.pod
new file mode 100644
index 0000000000..b2d38fbf7f
--- /dev/null
+++ b/doc/man3/OSSL_SELF_TEST_set_callback.pod
@@ -0,0 +1,50 @@
+=pod
+
+=head1 NAME
+
+OSSL_SELF_TEST_set_callback,
+OSSL_SELF_TEST_get_callback - specify a callback for processing self tests
+
+=head1 SYNOPSIS
+
+ #include <openssl/self_test.h>
+
+ void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *ctx, OSSL_CALLBACK *cb, void *cbarg);
+ void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *ctx, OSSL_CALLBACK **cb, void **cbarg);
+
+=head1 DESCRIPTION
+
+Set or gets the optional application callback (and the callback argument) that
+is called during self testing.
+The application callback B<OSSL_CALLBACK> is associated with a B<OPENSSL_CTX>.
+The application callback function receives information about a running self test,
+and may return a result to the calling self test.
+See L<openssl-core.h(7)> for further information on the callback.
+
+=head1 RETURN VALUES
+
+OSSL_SELF_TEST_get_callback() returns the callback and callback argument that
+has been set via OSSL_SELF_TEST_set_callback() for the given library context B<ctx>.
+These returned parameters will be NULL if OSSL_SELF_TEST_set_callback() has
+not been called.
+
+=head1 SEE ALSO
+
+L<openssl-core.h(7)>,
+L<OSSL_PROVIDER-FIPS(7)>
+L<OPENSSL_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019-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
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/OSSL_PROVIDER-FIPS.pod b/doc/man7/OSSL_PROVIDER-FIPS.pod
new file mode 100644
index 0000000000..a04ce4d6f2
--- /dev/null
+++ b/doc/man7/OSSL_PROVIDER-FIPS.pod
@@ -0,0 +1,260 @@
+=pod
+
+=head1 NAME
+
+OSSL_PROVIDER-FIPS - OPENSSL FIPS provider
+
+=head1 DESCRIPTION
+
+The OPENSSL FIPS provider is a special provider that conforms to the Federal
+Information Processing Standards (FIPS) specified in FIPS 140-2. This 'module'
+contains an approved set of cryptographic algorithms that is validated by an
+accredited testing laboratory.
+
+=head1 SELF TESTING
+
+One of the requirements for the FIPS module is self testing. An optional callback
+mechanism is available to return information to the user using
+L<OSSL_SELF_TEST_set_callback(7)>.
+
+The OPENSSL FIPS module uses the following mechanism to provide information
+about the self tests as they run.
+This is useful for debugging if a self test is failing.
+The callback also allows forcing any self test to fail, in order to check that
+it operates correctly on failure.
+
+The 'args' parameter of B<OSSL_CALLBACK> contains the B<OPENSSL_CTX> associated
+with the provider that is triggering the self test. This may be useful if
+multiple fips providers are present.
+
+The OSSL_PARAM names used are:
+
+=over 4
+
+=item "st-phase" (B<OSSL_PROV_PARAM_SELF_TEST_PHASE>) <UTF8 string>
+
+Each self test calls the callback 3 times with the following string values
+for the phase.
+
+=over 4
+
+=item "Start" (B<OSSL_SELF_TEST_PHASE_START>)
+
+This is the initial phase before the self test has run.
+This is used for informational purposes only.
+The value returned by the callback is ignored.
+
+=item "Corrupt" (B<OSSL_SELF_TEST_PHASE_CORRUPT>)
+
+The corrupt phase is run after the self test has calculated its known value.
+The callback may be used to force the self test to fail by returning a value
+of 0 from the callback during this phase.
+Returning any other value from the callback causes the self test to run normally.
+
+=item "Pass" (B<OSSL_SELF_TEST_PHASE_PASS>)
+
+=item "Fail" (B<OSSL_SELF_TEST_PHASE_FAIL>)
+
+The final phase runs after the self test is complete and indicates if a self
+test passed or failed. This is used for informational purposes only.
+The value returned by the callback is ignored.
+"Fail" should normally only be returned if any self test was forced to fail
+during the "Corrupt" phase (or if there was an error such as the integrity
+check of the module failed).
+
+Note that all self tests run even if a self test failure occurs.
+
+=back
+
+=item "st-type" (B<OSSL_PROV_PARAM_SELF_TEST_TYPE>) <UTF8 string>
+
+Used as a category to identify the type of self test being run.
+It includes the following string values:
+
+=over 4
+
+=item "Module_Integrity" (B<OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY>)
+
+Uses HMAC SHA256 on the module file to validate that the module has not been
+modified. The integrity value is compared to a value written to a configuration
+file during installation.
+
+=item "Install_Integrity" (B<OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY>)
+
+Uses HMAC SHA256 on a fixed string to validate that the installation process
+has already been performed and the self test KATS have already been tested,
+The integrity value is compared to a value written to a configuration
+file after successfully running the self tests during installation.
+
+=item "KAT_Cipher" (B<OSSL_SELF_TEST_TYPE_KAT_CIPHER>)
+
+Known answer test for a symmetric cipher.
+
+=item "KAT_Digest" (B<OSSL_SELF_TEST_TYPE_KAT_DIGEST>)
+
+Known answer test for a digest.
+
+=item "KAT_Signature" (B<OSSL_SELF_TEST_TYPE_KAT_SIGNATURE>)
+
+Known answer test for a signature.
+
+=item "KAT_KDF" (B<OSSL_SELF_TEST_TYPE_KAT_KDF>)
+
+Known answer test for a key derivation function.
+
+=item "KAT_KA" (B<OSSL_SELF_TEST_TYPE_KAT_KA>)
+
+Known answer test for key agreement.
+
+=item "DRBG" (B<OSSL_SELF_TEST_TYPE_DRBG>)
+
+Known answer test for a Deterministic Random Bit Generator.
+
+=item "Pairwise_Consistency_Test" (B<OSSL_SELF_TEST_TYPE_PCT>)
+
+Conditional test that is run during the generation of key pairs.
+
+=back
+
+The "Module_Integrity" self test is always run at startup.
+The "Install_Integrity" self test is used to check if the self tests have
+already been run at installation time. If they have already run then the
+self tests are not run on subsequent startups.
+All other self test categories are run once at installation time, except for the
+"Pairwise_Consistency_Test".
+
+There is only one instance of the "Module_Integrity" and "Install_Integrity"
+self tests. All other self tests may have multiple instances.
+
+=item "st-desc" (B<OSSL_PROV_PARAM_SELF_TEST_DESC>) <UTF8 string>
+
+Used as a sub category to identify an individual self test.
+The following description strings are used.
+
+=over 4
+
+=item "HMAC" (B<OSSL_SELF_TEST_DESC_INTEGRITY_HMAC>)
+
+"Module_Integrity" and "Install_Integrity" use this.
+
+=item "RSA" (B<OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1>)
+
+=item "ECDSA" (B<OSSL_SELF_TEST_DESC_PCT_ECDSA>)
+
+=item "DSA" (B<OSSL_SELF_TEST_DESC_PCT_DSA>)
+
+Key generation tests used with the "Pairwise_Consistency_Test" type.
+
+=item "AES_GCM" (B<OSSL_SELF_TEST_DESC_CIPHER_AES_GCM>)
+
+=item "TDES" (B<OSSL_SELF_TEST_DESC_CIPHER_TDES>)
+
+Symmetric cipher tests used with the "KAT_Cipher" type.
+
+=item "SHA1" (B<OSSL_SELF_TEST_DESC_MD_SHA1>)
+
+=item "SHA2" (B<OSSL_SELF_TEST_DESC_MD_SHA2>)
+
+=item "SHA3" (B<OSSL_SELF_TEST_DESC_MD_SHA3>)
+
+Digest tests used with the "KAT_Digest" type.
+
+=item "DSA" (B<OSSL_SELF_TEST_DESC_SIGN_DSA>)
+
+=item "RSA" (B<OSSL_SELF_TEST_DESC_SIGN_RSA>)
+
+=item "ECDSA" (B<OSSL_SELF_TEST_DESC_SIGN_ECDSA>)
+
+Signature tests used with the "KAT_Signature" type.
+
+=item "ECDH" (B<OSSL_SELF_TEST_DESC_KA_ECDH>)
+
+=item "ECDSA" (B<OSSL_SELF_TEST_DESC_KA_ECDSA>)
+
+Key agreement tests used with the "KAT_KA" type.
+
+=item "HKDF" (B<OSSL_SELF_TEST_DESC_KDF_HKDF>)
+
+Key Derivation Function tests used with the "KAT_KDF" type.
+
+=item "CTR" (B<OSSL_SELF_TEST_DESC_DRBG_CTR>)
+
+=item "HASH" (B<OSSL_SELF_TEST_DESC_DRBG_HASH>)
+
+=item "HMAC" (B<OSSL_SELF_TEST_DESC_DRBG_HMAC>)
+
+DRBG tests used with the "DRBG" type.
+
+=back
+
+=back
+
+=head1 EXAMPLES
+
+A simple self test callback is shown below for illustrative purposes.
+
+ #include <openssl/self_test.h>
+
+ static OSSL_CALLBACK self_test_cb;
+
+ static int self_test_cb(const OSSL_PARAM params[], void *arg)
+ {
+ int ret = 0;
+ const OSSL_PARAM *p = NULL;
+ const char *phase = NULL, *type = NULL, *desc = NULL;
+
+ 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;
+
+ /* Do some logging */
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)
+ BIO_printf(bio_out, "%s : (%s) : ", desc, type);
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0
+ || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)
+ BIO_printf(bio_out, "%s\n", phase);
+
+ /* Corrupt the SHA1 self test during the 'corrupt' phase by returning 0 */
+ if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0
+ && strcmp(desc, OSSL_SELF_TEST_DESC_MD_SHA1) == 0) {
+ BIO_printf(bio_out, "%s %s", phase, desc);
+ return 0;
+ }
+ ret = 1;
+ err:
+ return ret;
+ }
+
+=head1 SEE ALSO
+
+L<openssl-fipsinstall(1)>,
+L<fips_config(5)>,
+L<OSSL_SELF_TEST_set_callback(7)>,
+L<OSSL_PARAM(3)>,
+L<openssl-core.h(7)>
+
+=head1 HISTORY
+
+The type and functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019 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
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/provider-base.pod b/doc/man7/provider-base.pod
index ccc5bf309a..7e86b2b2ed 100644
--- a/doc/man7/provider-base.pod
+++ b/doc/man7/provider-base.pod
@@ -115,6 +115,7 @@ provider):
BIO_vprintf OSSL_FUNC_BIO_VPRINTF
OPENSSL_cleanse OSSL_FUNC_OPENSSL_CLEANSE
OPENSSL_hexstr2buf OSSL_FUNC_OPENSSL_HEXSTR2BUF
+ OSSL_SELF_TEST_set_callback OSSL_FUNC_SELF_TEST_CB
For I<*out> (the B<OSSL_DISPATCH> array passed from the provider to
F<libcrypto>):
@@ -188,6 +189,8 @@ BIO_vprintf(), OPENSSL_cleanse(), and OPENSSL_hexstr2buf()
correspond exactly to the public functions with the same name.
As a matter of fact, the pointers in the B<OSSL_DISPATCH> array are
direct pointers to those public functions.
+OSSL_SELF_TEST_set_callback() is used to set an optional callback that can be
+passed into a provider. This may be ignored by a provider.
=head2 Provider functions
diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h
index 8be3861d4f..dbb68f2c44 100644
--- a/include/internal/cryptlib.h
+++ b/include/internal/cryptlib.h
@@ -155,7 +155,8 @@ typedef struct ossl_ex_data_global_st {
# define OPENSSL_CTX_THREAD_EVENT_HANDLER_INDEX 8
# define OPENSSL_CTX_FIPS_PROV_INDEX 9
# define OPENSSL_CTX_SERIALIZER_STORE_INDEX 10
-# define OPENSSL_CTX_MAX_INDEXES 11
+# define OPENSSL_CTX_SELF_TEST_CB_INDEX 11
+# define OPENSSL_CTX_MAX_INDEXES 12
typedef struct openssl_ctx_method {
void *(*new_func)(OPENSSL_CTX *ctx);
diff --git a/include/internal/provider.h b/include/internal/provider.h
index a037233a30..8856d2fdd5 100644
--- a/include/internal/provider.h
+++ b/include/internal/provider.h
@@ -11,6 +11,7 @@
# define OSSL_INTERNAL_PROVIDER_H
# include <openssl/core.h>
+# include <openssl/core_numbers.h>
# include "internal/dso.h"
# include "internal/symhacks.h"
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index db9cb9ab2d..0bc51b3589 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -14,31 +14,16 @@
extern "C" {
# endif
-/*
- * Well known parameter names that Providers can define
- */
-
-/*
- * A printable name for this provider
- * Type: OSSL_PARAM_UTF8_STRING
- */
-#define OSSL_PROV_PARAM_NAME "name"
-/*
- * A version string for this provider
- * Type: OSSL_PARAM_UTF8_STRING
- */
-#define OSSL_PROV_PARAM_VERSION "version"
-/*
- * A string providing provider specific build information
- * Type: OSSL_PARAM_UTF8_STRING
- */
-#define OSSL_PROV_PARAM_BUILDINFO "buildinfo"
-
-/*
- * The module filename
- * Type: OSSL_PARAM_OCTET_STRING
- */
-#define OSSL_PROV_PARAM_MODULE_FILENAME "module-filename"
+/* Well known parameter names that Providers can define */
+#define OSSL_PROV_PARAM_NAME "name" /* utf8_string */
+#define OSSL_PROV_PARAM_VERSION "version" /* utf8_string */
+#define OSSL_PROV_PARAM_BUILDINFO "buildinfo" /* utf8_string */
+#define OSSL_PROV_PARAM_MODULE_FILENAME "module-filename" /* octet_string */
+
+/* Self test callback parameters */
+#define OSSL_PROV_PARAM_SELF_TEST_PHASE "st-phase" /* utf8_string */
+#define OSSL_PROV_PARAM_SELF_TEST_TYPE "st-type" /* utf8_string */
+#define OSSL_PROV_PARAM_SELF_TEST_DESC "st-desc" /* utf8_string */
/*
* Algorithm parameters
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index 9f49599dab..f41f7c02d0 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -12,6 +12,7 @@
# include <stdarg.h>
# include <openssl/core.h>
+# include <openssl/self_test.h>
# ifdef __cplusplus
extern "C" {
@@ -135,6 +136,10 @@ OSSL_CORE_MAKE_FUNC(int, BIO_free, (BIO *bio))
OSSL_CORE_MAKE_FUNC(int, BIO_vprintf, (BIO *bio, const char *format,
va_list args))
+#define OSSL_FUNC_SELF_TEST_CB 28
+OSSL_CORE_MAKE_FUNC(void, self_test_cb, (OPENSSL_CTX *ctx, OSSL_CALLBACK **cb,
+ void **cbarg))
+
/* Functions provided by the provider to the Core, reserved numbers 1024-1535 */
# define OSSL_FUNC_PROVIDER_TEARDOWN 1024
OSSL_CORE_MAKE_FUNC(void,provider_teardown,(void *provctx))
diff --git a/include/openssl/self_test.h b/include/openssl/self_test.h
new file mode 100644
index 0000000000..31dd6bd6c5
--- /dev/null
+++ b/include/openssl/self_test.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_SELF_TEST_H
+# define OPENSSL_SELF_TEST_H
+
+# include <openssl/core.h> /* OSSL_CALLBACK */
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* The test event phases */
+# define OSSL_SELF_TEST_PHASE_NONE "None"
+# define OSSL_SELF_TEST_PHASE_START "Start"
+# define OSSL_SELF_TEST_PHASE_CORRUPT "Corrupt"
+# define OSSL_SELF_TEST_PHASE_PASS "Pass"
+# define OSSL_SELF_TEST_PHASE_FAIL "Fail"
+
+/* Test event categories */
+# define OSSL_SELF_TEST_TYPE_NONE "None"
+# define OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY "Module_Integrity"
+# define OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY "Install_Integrity"
+# define OSSL_SELF_TEST_TYPE_PCT "Pairwise_Consistency_Test"
+# define OSSL_SELF_TEST_TYPE_KAT_CIPHER "KAT_Cipher"
+# define OSSL_SELF_TEST_TYPE_KAT_DIGEST "KAT_Digest"
+# define OSSL_SELF_TEST_TYPE_KAT_SIGNATURE "KAT_Signature"
+# define OSSL_SELF_TEST_TYPE_KAT_KDF "KAT_KDF"
+# define OSSL_SELF_TEST_TYPE_KAT_KA "KAT_KA"
+# define OSSL_SELF_TEST_TYPE_DRBG "DRBG"
+
+/* Test event sub categories */
+# define OSSL_SELF_TEST_DESC_NONE "None"
+# define OSSL_SELF_TEST_DESC_INTEGRITY_HMAC "HMAC"
+# define OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1 "RSA"
+# define OSSL_SELF_TEST_DESC_PCT_ECDSA "ECDSA"
+# define OSSL_SELF_TEST_DESC_PCT_DSA "DSA"
+# define OSSL_SELF_TEST_DESC_CIPHER_AES_GCM "AES_GCM"
+# define OSSL_SELF_TEST_DESC_CIPHER_TDES "TDES"
+# define OSSL_SELF_TEST_DESC_MD_SHA1 "SHA1"
+# define OSSL_SELF_TEST_DESC_MD_SHA2 "SHA2"
+# define OSSL_SELF_TEST_DESC_MD_SHA3 "SHA3"
+# define OSSL_SELF_TEST_DESC_SIGN_DSA "DSA"
+# define OSSL_SELF_TEST_DESC_SIGN_RSA "RSA"
+# define OSSL_SELF_TEST_DESC_SIGN_ECDSA "ECDSA"
+# define OSSL_SELF_TEST_DESC_DRBG_CTR "CTR"
+# define OSSL_SELF_TEST_DESC_DRBG_HASH "HASH"
+# define OSSL_SELF_TEST_DESC_DRBG_HMAC "HMAC"
+# define OSSL_SELF_TEST_DESC_KA_ECDH "ECDH"
+# define OSSL_SELF_TEST_DESC_KA_ECDSA "ECDSA"
+# define OSSL_SELF_TEST_DESC_KDF_HKDF "HKDF"
+
+# ifdef __cplusplus
+}
+# endif
+
+void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb,
+ void *cbarg);
+void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
+ void **cbarg);
+
+#endif /* OPENSSL_SELF_TEST_H */
diff --git a/providers/fips/build.info b/providers/fips/build.info
index 12ca452073..d12849ebb0 100644
--- a/providers/fips/build.info
+++ b/providers/fips/build.info
@@ -1,3 +1,2 @@
-
-SOURCE[../fips]=fipsprov.c selftest.c
+SOURCE[../fips]=fipsprov.c self_test.c self_test_kats.c self_test_event.c
INCLUDE[../fips]=../implementations/include ../common/include ../..
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index 788963911b..cf4181dd2a 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -31,7 +31,7 @@
#include "prov/provider_ctx.h"
#include "prov/providercommon.h"
#include "prov/provider_util.h"
-#include "selftest.h"
+#include "self_test.h"
#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "fips=yes", FUNC }, CHECK }
#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
@@ -649,9 +649,14 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
{
FIPS_GLOBAL *fgbl;
OPENSSL_CTX *ctx;
+ OSSL_self_test_cb_fn *stcbfn = NULL;
+ OSSL_core_get_library_context_fn *c_get_libctx = NULL;
for (; in->function_id != 0; in++) {
switch (in->function_id) {
+ case OSSL_FUNC_CORE_GET_LIBRARY_CONTEXT:
+ c_get_libctx = OSSL_get_core_get_library_context(in);
+ break;
case OSSL_FUNC_CORE_GETTABLE_PARAMS:
c_gettable_params = OSSL_get_core_gettable_params(in);
break;
@@ -715,12 +720,25 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
case OSSL_FUNC_BIO_FREE:
selftest_params.bio_free_cb = OSSL_get_BIO_free(in);
break;
+ case OSSL_FUNC_SELF_TEST_CB: {
+ stcbfn = OSSL_get_self_test_cb(in);
+ break;
+ }
default:
/* Just ignore anything we don't understand */
break;
}
}
+ if (stcbfn != NULL && c_get_libctx != NULL) {
+ stcbfn(c_get_libctx(provider), &selftest_params.event_cb,
+ &selftest_params.event_cb_arg);
+ }
+ else {
+ selftest_params.event_cb = NULL;
+ selftest_params.event_cb_arg = NULL;
+ }
+
if (!c_get_params(provider, core_params))
return 0;
diff --git a/providers/fips/selftest.c b/providers/fips/self_test.c
index 91e4bb07f5..e486dd0db0 100644
--- a/providers/fips/selftest.c
+++ b/providers/fips/self_test.c
@@ -20,7 +20,7 @@
*/
#define ALLOW_RUN_ONCE_IN_FIPS
#include <internal/thread_once.h>
-#include "selftest.h"
+#include "self_test.h"
#define FIPS_STATE_INIT 0
#define FIPS_STATE_SELFTEST 1
@@ -132,7 +132,8 @@ DEP_FINI_ATTRIBUTE void cleanup(void)
*/
static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
unsigned char *expected, size_t expected_len,
- OPENSSL_CTX *libctx)
+ OPENSSL_CTX *libctx, OSSL_ST_EVENT *ev,
+ const char *event_type)
{
int ret = 0, status;
unsigned char out[MAX_MD_SIZE];
@@ -142,6 +143,8 @@ static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
EVP_MAC_CTX *ctx = NULL;
OSSL_PARAM params[3], *p = params;
+ SELF_TEST_EVENT_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
+
mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
ctx = EVP_MAC_CTX_new(mac);
if (mac == NULL || ctx == NULL)
@@ -167,11 +170,13 @@ static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
goto err;
+ SELF_TEST_EVENT_oncorrupt_byte(ev, out);
if (expected_len != out_len
|| memcmp(expected, out, out_len) != 0)
goto err;
ret = 1;
err:
+ SELF_TEST_EVENT_onend(ev, ret);
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
return ret;
@@ -187,6 +192,7 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
unsigned char *module_checksum = NULL;
unsigned char *indicator_checksum = NULL;
int loclstate;
+ OSSL_ST_EVENT ev;
if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
return 0;
@@ -217,6 +223,8 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
|| st->module_checksum_data == NULL)
goto end;
+ SELF_TEST_EVENT_init(&ev, st->event_cb, st->event_cb_arg);
+
module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
&checksum_len);
if (module_checksum == NULL)
@@ -226,7 +234,8 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
/* Always check the integrity of the fips module */
if (bio_module == NULL
|| !verify_integrity(bio_module, st->bio_read_ex_cb,
- module_checksum, checksum_len, st->libctx))
+ module_checksum, checksum_len, st->libctx,
+ &ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY))
goto end;
/* This will be NULL during installation - so the self test KATS will run */
@@ -248,7 +257,8 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
if (bio_indicator == NULL
|| !verify_integrity(bio_indicator, st->bio_read_ex_cb,
indicator_checksum, checksum_len,
- st->libctx))
+ st->libctx, &ev,
+ OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY))
goto end;
else
kats_already_passed = 1;
@@ -256,7 +266,8 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
/* Only runs the KAT's during installation OR on_demand() */
if (on_demand_test || kats_already_passed == 0) {
- /*TODO (3.0) Add self test KATS */
+ if (!SELF_TEST_kats(&ev, st->libctx))
+ goto end;
}
ok = 1;
end:
diff --git a/providers/fips/selftest.h b/providers/fips/self_test.h
index a56e42c7ab..5d995adac3 100644
--- a/providers/fips/selftest.h
+++ b/providers/fips/self_test.h
@@ -9,6 +9,7 @@
#include <openssl/core_numbers.h>
#include <openssl/types.h>
+#include <openssl/self_test.h>
typedef struct self_test_post_params_st {
/* FIPS module integrity check parameters */
@@ -25,8 +26,31 @@ typedef struct self_test_post_params_st {
OSSL_BIO_new_membuf_fn *bio_new_buffer_cb;
OSSL_BIO_read_ex_fn *bio_read_ex_cb;
OSSL_BIO_free_fn *bio_free_cb;
+ OSSL_CALLBACK *event_cb;
+ void *event_cb_arg;
OPENSSL_CTX *libctx;
} SELF_TEST_POST_PARAMS;
+typedef struct st_event_st
+{
+ /* local state variables */
+ const char *phase;
+ const char *type;
+ const char *desc;
+ OSSL_CALLBACK *cb;
+
+ /* callback related variables used to pass the state back to the user */
+ OSSL_PARAM params[4];
+ void *cb_arg;
+
+} OSSL_ST_EVENT;
+
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test);
+int SELF_TEST_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx);
+
+void SELF_TEST_EVENT_init(OSSL_ST_EVENT *ev, OSSL_CALLBACK *cb, void *cbarg);
+void SELF_TEST_EVENT_onbegin(OSSL_ST_EVENT *ev, const char *type,
+ const char *desc);
+void SELF_TEST_EVENT_onend(OSSL_ST_EVENT *ev, int ret);
+void SELF_TEST_EVENT_oncorrupt_byte(OSSL_ST_EVENT *ev, unsigned char *bytes);
diff --git a/providers/fips/self_test_data.inc b/providers/fips/self_test_data.inc
new file mode 100644
index 0000000000..28616a0079
--- /dev/null
+++ b/providers/fips/self_test_data.inc
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+typedef struct st_kat_st {
+ const char *desc;
+ const char *algorithm;
+ const unsigned char *pt;
+ size_t pt_len;
+ const unsigned char *expected;
+ size_t expected_len;
+} ST_KAT;
+
+typedef ST_KAT ST_KAT_DIGEST;
+typedef struct st_kat_cipher_st {
+ ST_KAT base;
+ const unsigned char *key;
+ size_t key_len;
+ const unsigned char *iv;
+ size_t iv_len;
+ const unsigned char *aad;
+ size_t aad_len;
+ const unsigned char *tag;
+ size_t tag_len;
+} ST_KAT_CIPHER;
+
+typedef struct st_kat_nvp_st {
+ const char *name;
+ const char *value;
+} ST_KAT_NVP;
+
+typedef struct st_kat_kdf_st {
+ const char *desc;
+ const char *algorithm;
+ const ST_KAT_NVP *ctrls;
+ const unsigned char *expected;
+ size_t expected_len;
+} ST_KAT_KDF;
+
+/* Macros to build Self test data */
+#define ITM(x) x, sizeof(x)
+#define ITM_STR(x) x, sizeof(x) - 1
+
+/*- DIGEST TEST DATA */
+static const unsigned char sha1_pt[] = "abc";
+static const unsigned char sha1_digest[] = {
+ 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 0x25, 0x71,
+ 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D
+};
+
+static const unsigned char sha512_pt[] = "abc";
+static const unsigned char sha512_digest[] = {
+ 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, 0xCC, 0x41, 0x73, 0x49,
+ 0xAE, 0x20, 0x41, 0x31, 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
+ 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, 0x21, 0x92, 0x99, 0x2A,
+ 0x27, 0x4F, 0xC1, 0xA8, 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
+ 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, 0x2A, 0x9A, 0xC9, 0x4F,
+ 0xA5, 0x4C, 0xA4, 0x9F
+};
+static const unsigned char sha3_256_pt[] = { 0xe7, 0x37, 0x21, 0x05 };
+static const unsigned char sha3_256_digest[] = {
+ 0x3a, 0x42, 0xb6, 0x8a, 0xb0, 0x79, 0xf2, 0x8c, 0x4c, 0xa3, 0xc7, 0x52,
+ 0x29, 0x6f, 0x27, 0x90, 0x06, 0xc4, 0xfe, 0x78, 0xb1, 0xeb, 0x79, 0xd9,
+ 0x89, 0x77, 0x7f, 0x05, 0x1e, 0x40, 0x46, 0xae
+};
+
+static const ST_KAT_DIGEST st_kat_digest_tests[] =
+{
+ {
+ OSSL_SELF_TEST_DESC_MD_SHA1,
+ "SHA1",
+ ITM_STR(sha1_pt),
+ ITM(sha1_digest),
+ },
+ {
+ OSSL_SELF_TEST_DESC_MD_SHA2,
+ "SHA512",
+ ITM_STR(sha512_pt),
+ ITM(sha512_digest),
+ },
+ {
+ OSSL_SELF_TEST_DESC_MD_SHA3,
+ "SHA3-256",
+ ITM(sha3_256_pt),
+ ITM(sha3_256_digest),
+ },
+};
+
+
+/*- CIPHER TEST DATA */
+
+/* DES3 test data */
+static const unsigned char des_ede3_cbc_pt[] = {
+ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11,
+ 0x73, 0x93, 0x17, 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51
+};
+
+static const unsigned char des_ede3_cbc_key[] = {
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+ 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+ 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+static const unsigned char des_ede3_cbc_iv[] = {
+ 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17
+};
+static const unsigned char des_ede3_cbc_ct[] = {
+ 0x20, 0x79, 0xC3, 0xD5, 0x3A, 0xA7, 0x63, 0xE1, 0x93, 0xB7, 0x9E, 0x25,
+ 0x69, 0xAB, 0x52, 0x62, 0x51, 0x65, 0x70, 0x48, 0x1F, 0x25, 0xB5, 0x0F,
+ 0x73, 0xC0, 0xBD, 0xA8, 0x5C, 0x8E, 0x0D, 0xA7
+};
+
+static const unsigned char aes_256_gcm_key[] = {
+ 0x92,0xe1,0x1d,0xcd,0xaa,0x86,0x6f,0x5c,0xe7,0x90,0xfd,0x24,
+ 0x50,0x1f,0x92,0x50,0x9a,0xac,0xf4,0xcb,0x8b,0x13,0x39,0xd5,
+ 0x0c,0x9c,0x12,0x40,0x93,0x5d,0xd0,0x8b
+};
+static const unsigned char aes_256_gcm_iv[] = {
+ 0xac,0x93,0xa1,0xa6,0x14,0x52,0x99,0xbd,0xe9,0x02,0xf2,0x1a
+};
+static const unsigned char aes_256_gcm_pt[] = {
+ 0x2d,0x71,0xbc,0xfa,0x91,0x4e,0x4a,0xc0,0x45,0xb2,0xaa,0x60,
+ 0x95,0x5f,0xad,0x24
+};
+static const unsigned char aes_256_gcm_aad[] = {
+ 0x1e,0x08,0x89,0x01,0x6f,0x67,0x60,0x1c,0x8e,0xbe,0xa4,0x94,
+ 0x3b,0xc2,0x3a,0xd6
+};
+static const unsigned char aes_256_gcm_ct[] = {
+ 0x89,0x95,0xae,0x2e,0x6d,0xf3,0xdb,0xf9,0x6f,0xac,0x7b,0x71,
+ 0x37,0xba,0xe6,0x7f
+};
+static const unsigned char aes_256_gcm_tag[] = {
+ 0xec,0xa5,0xaa,0x77,0xd5,0x1d,0x4a,0x0a,0x14,0xd9,0xc5,0x1e,
+ 0x1d,0xa4,0x74,0xab
+};
+
+static const ST_KAT_CIPHER st_kat_cipher_tests[] = {
+ {
+ {
+ OSSL_SELF_TEST_DESC_CIPHER_TDES,
+ "DES-EDE3-CBC",
+ ITM(des_ede3_cbc_pt),
+ ITM(des_ede3_cbc_ct)
+ },
+ ITM(des_ede3_cbc_key),
+ ITM(des_ede3_cbc_iv),
+ },
+ {
+ {
+ OSSL_SELF_TEST_DESC_CIPHER_AES_GCM,
+ "AES-256-GCM",
+ ITM(aes_256_gcm_pt),
+ ITM(aes_256_gcm_ct),
+ },
+ ITM(aes_256_gcm_key),
+ ITM(aes_256_gcm_iv),
+ ITM(aes_256_gcm_aad),
+ ITM(aes_256_gcm_tag)
+ }
+};
+
+/*- KDF TEST DATA */
+
+static const ST_KAT_NVP hkdf_ctrl[] =
+{
+ { "digest", "SHA256" },
+ { "key", "secret" },
+ { "salt", "salt" },
+ { "info", "label" },
+ { NULL, NULL }
+};
+static const unsigned char hkdf_expected[] = {
+ 0x2a, 0xc4, 0x36, 0x9f, 0x52, 0x59, 0x96, 0xf8, 0xde, 0x13
+};
+
+static const ST_KAT_KDF st_kat_kdf_tests[] =
+{
+ {
+ OSSL_SELF_TEST_DESC_KDF_HKDF,
+ "HKDF",
+ hkdf_ctrl,
+ ITM(hkdf_expected)
+ }
+};
+
diff --git a/providers/fips/self_test_event.c b/providers/fips/self_test_event.c
new file mode 100644
index 0000000000..887b9dd17d
--- /dev/null
+++ b/providers/fips/self_test_event.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include "self_test.h"
+
+static void self_test_event_setparams(OSSL_ST_EVENT *ev)
+{
+ size_t n = 0;
+
+ if (ev->cb != NULL) {
+ ev->params[n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_PHASE,
+ (char *)ev->phase, 0);
+ ev->params[n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_TYPE,
+ (char *)ev->type, 0);
+ ev->params[n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_DESC,
+ (char *)ev->desc, 0);
+ }
+ ev->params[n++] = OSSL_PARAM_construct_end();
+}
+
+void SELF_TEST_EVENT_init(OSSL_ST_EVENT *ev, OSSL_CALLBACK *cb, void *cbarg)
+{
+ if (ev == NULL)
+ return;
+
+ ev->cb = cb;
+ ev->cb_arg = cbarg;
+ ev->phase = "";
+ ev->type = "";
+ ev->desc = "";
+ self_test_event_setparams(ev);
+}
+
+/* Can be used during application testing to log that a test has started. */
+void SELF_TEST_EVENT_onbegin(OSSL_ST_EVENT *ev, const char *type,
+ const char *desc)
+{
+ if (ev != NULL && ev->cb != NULL) {
+ ev->phase = OSSL_SELF_TEST_PHASE_START;
+ ev->type = type;
+ ev->desc = desc;
+ self_test_event_setparams(ev);
+ (void)ev->cb(ev->params, ev->cb_arg);
+ }
+}
+
+/*
+ * Can be used during application testing to log that a test has either
+ * passed or failed.
+ */
+void SELF_TEST_EVENT_onend(OSSL_ST_EVENT *ev, int ret)
+{
+ if (ev != NULL && ev->cb != NULL) {
+ ev->phase =
+ (ret == 1 ? OSSL_SELF_TEST_PHASE_PASS : OSSL_SELF_TEST_PHASE_FAIL);
+ self_test_event_setparams(ev);
+ (void)ev->cb(ev->params, ev->cb_arg);
+
+ ev->phase = OSSL_SELF_TEST_PHASE_NONE;
+ ev->type = OSSL_SELF_TEST_TYPE_NONE;
+ ev->desc = OSSL_SELF_TEST_DESC_NONE;
+ }
+}
+
+/*
+ * Used for failure testing.
+ *
+ * Call the applications SELF_TEST_cb() if it exists.
+ * If the application callback decides to return 0 then the first byte of 'bytes'
+ * is modified (corrupted). This is used to modify output signatures or
+ * ciphertext before they are verified or decrypted.
+ */
+void SELF_TEST_EVENT_oncorrupt_byte(OSSL_ST_EVENT *ev, unsigned char *bytes)
+{
+ if (ev != NULL && ev->cb != NULL) {
+ ev->phase = OSSL_SELF_TEST_PHASE_CORRUPT;
+ self_test_event_setparams(ev);
+ if (!ev->cb(ev->params, ev->cb_arg))
+ bytes[0] ^= 1;
+ }
+}
+
diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c
new file mode 100644
index 0000000000..3ccd3f66ed
--- /dev/null
+++ b/providers/fips/self_test_kats.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include "internal/nelem.h"
+#include "self_test.h"
+#include "self_test_data.inc"
+
+static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_ST_EVENT *event,
+ OPENSSL_CTX *libctx)
+{
+ int ok = 0;
+ unsigned char out[EVP_MAX_MD_SIZE];
+ unsigned int out_len = 0;
+ EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+ EVP_MD *md = EVP_MD_fetch(libctx, t->algorithm, NULL);
+
+ SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_DIGEST, t->desc);
+
+ if (ctx == NULL
+ || md == NULL
+ || !EVP_DigestInit_ex(ctx, md, NULL)
+ || !EVP_DigestUpdate(ctx, t->pt, t->pt_len)
+ || !EVP_DigestFinal(ctx, out, &out_len))
+ goto err;
+
+ /* Optional corruption */
+ SELF_TEST_EVENT_oncorrupt_byte(event, out);
+
+ if (out_len != t->expected_len
+ || memcmp(out, t->expected, out_len) != 0)
+ goto err;
+ ok = 1;
+err:
+ SELF_TEST_EVENT_onend(event, ok);
+ EVP_MD_free(md);
+ EVP_MD_CTX_free(ctx);
+
+ return ok;
+}
+
+/*
+ * Helper function to setup a EVP_CipherInit
+ * Used to hide the complexity of Authenticated ciphers.
+ */
+static int cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const ST_KAT_CIPHER *t, int enc)
+{
+ unsigned char *in_tag = NULL;
+ int pad = 0, tmp;
+
+ /* Flag required for Key wrapping */
+ EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+ if (t->tag == NULL) {
+ /* Use a normal cipher init */
+ return EVP_CipherInit_ex(ctx, cipher, NULL, t->key, t->iv, enc)
+ && EVP_CIPHER_CTX_set_padding(ctx, pad);
+ }
+
+ /* The authenticated cipher init */
+ if (!enc)
+ in_tag = (unsigned char *)t->tag;
+
+ return EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)
+ && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, t->iv_len, NULL)
+ && (in_tag == NULL
+ || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, t->tag_len,
+ in_tag))
+ && EVP_CipherInit_ex(ctx, NULL, NULL, t->key, t->iv, enc)
+ && EVP_CIPHER_CTX_set_padding(ctx, pad)
+ && EVP_CipherUpdate(ctx, NULL, &tmp, t->aad, t->aad_len);
+}
+
+/* Test a single KAT for encrypt/decrypt */
+static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_ST_EVENT *event,
+ OPENSSL_CTX *libctx)
+{
+ int ret = 0, encrypt = 1, len, ct_len = 0, pt_len = 0;
+ EVP_CIPHER_CTX *ctx = NULL;
+ EVP_CIPHER *cipher = NULL;
+ unsigned char ct_buf[256] = { 0 };
+ unsigned char pt_buf[256] = { 0 };
+
+ SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->base.desc);
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL)
+ goto end;
+ cipher = EVP_CIPHER_fetch(libctx, t->base.algorithm, "");
+ if (cipher == NULL)
+ goto end;
+
+ /* Encrypt plain text message */
+ if (!cipher_init(ctx, cipher, t, encrypt)
+ || !EVP_CipherUpdate(ctx, ct_buf, &len, t->base.pt, t->base.pt_len)
+ || !EVP_CipherFinal_ex(ctx, ct_buf + len, &ct_len))
+ goto end;
+
+ SELF_TEST_EVENT_oncorrupt_byte(event, ct_buf);
+ ct_len += len;
+ if (ct_len != (int)t->base.expected_len
+ || memcmp(t->base.expected, ct_buf, ct_len) != 0)
+ goto end;
+
+ if (t->tag != NULL) {
+ unsigned char tag[16] = { 0 };
+
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, t->tag_len, tag)
+ || memcmp(tag, t->tag, t->tag_len) != 0)
+ goto end;
+ }
+
+ if (!(cipher_init(ctx, cipher, t, !encrypt)
+ && EVP_CipherUpdate(ctx, pt_buf, &len, ct_buf, ct_len)
+ && EVP_CipherFinal_ex(ctx, pt_buf + len, &pt_len)))
+ goto end;
+ pt_len += len;
+
+ if (pt_len != (int)t->base.pt_len
+ || memcmp(pt_buf, t->base.pt, pt_len) != 0)
+ goto end;
+
+ ret = 1;
+end:
+ EVP_CIPHER_free(cipher);
+ EVP_CIPHER_CTX_free(ctx);
+ SELF_TEST_EVENT_onend(event, ret);
+ return ret;
+}
+
+static int self_test_kdf(const ST_KAT_KDF *t, OSSL_ST_EVENT *event,
+ OPENSSL_CTX *libctx)
+{
+ int ret = 0;
+ int i;
+ unsigned char out[64];
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *ctx = NULL;
+ OSSL_PARAM params[16];
+ const OSSL_PARAM *settables = NULL;
+
+ SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_KDF, t->desc);
+
+ kdf = EVP_KDF_fetch(libctx, t->algorithm, "");
+ ctx = EVP_KDF_CTX_new(kdf);
+ if (ctx == NULL)
+ goto end;
+
+ settables = EVP_KDF_settable_ctx_params(kdf);
+ for (i = 0; t->ctrls[i].name != NULL; ++i) {
+ if (!OSSL_PARAM_allocate_from_text(&params[i], settables,
+ t->ctrls[i].name,
+ t->ctrls[i].value,
+ strlen(t->ctrls[i].value)))
+ goto end;
+ }
+ params[i] = OSSL_PARAM_construct_end();
+ if (!EVP_KDF_CTX_set_params(ctx, params))
+ goto end;
+
+ if (t->expected_len > sizeof(out))
+ goto end;
+ if (EVP_KDF_derive(ctx, out, t->expected_len) <= 0)
+ goto end;
+
+ SELF_TEST_EVENT_oncorrupt_byte(event, out);
+
+ if (memcmp(out, t->expected, t->expected_len) != 0)
+ goto end;
+
+ ret = 1;
+end:
+ for (i = 0; params[i].key != NULL; ++i)
+ OPENSSL_free(params[i].data);
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(ctx);
+ SELF_TEST_EVENT_onend(event, ret);
+ return ret;
+}
+
+/*
+ * Test a data driven list of KAT's for digest algorithms.
+ * All tests are run regardless of if they fail or not.
+ * Return 0 if any test fails.
+ */
+static int self_test_digests(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
+{
+ int i, ret = 1;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_digest_tests); ++i) {
+ if (!self_test_digest(&st_kat_digest_tests[i], event, libctx))
+ ret = 0;
+ }
+ return ret;
+}
+
+static int self_test_ciphers(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
+{
+ int i, ret = 1;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_cipher_tests); ++i) {
+ if (!self_test_cipher(&st_kat_cipher_tests[i], event, libctx))
+ ret = 0;
+ }
+ return ret;
+}
+
+static int self_test_kdfs(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
+{
+ int i, ret = 1;
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_kdf_tests); ++i) {
+ if (!self_test_kdf(&st_kat_kdf_tests[i], event, libctx))
+ ret = 0;
+ }
+ return ret;
+}
+
+/*
+ * Run the algorithm KAT's.
+ * Return 1 is successful, otherwise return 0.
+ * This runs all the tests regardless of if any fail.
+ *
+ * TODO(3.0) Add self tests for KA, DRBG, Sign/Verify when they become available
+ */
+int SELF_TEST_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
+{
+ int ret = 1;
+
+ if (!self_test_digests(event, libctx))
+ ret = 0;
+ if (!self_test_ciphers(event, libctx))
+ ret = 0;
+ if (!self_test_kdfs(event, libctx))
+ ret = 0;
+
+ return ret;
+}
diff --git a/test/recipes/03-test_fipsinstall.t b/test/recipes/03-test_fipsinstall.t
index 40a962253d..e77e09d550 100644
--- a/test/recipes/03-test_fipsinstall.t
+++ b/test/recipes/03-test_fipsinstall.t
@@ -24,7 +24,7 @@ use platform;
plan skip_all => "Test only supported in a fips build" if disabled("fips");
-plan tests => 6;
+plan tests => 9;
my $infile = bldtop_file('providers', platform->dso('fips'));
$ENV{OPENSSL_MODULES} = bldtop_dir("providers");
@@ -71,3 +71,24 @@ ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.conf', '-module', $infile,
'-macopt', 'digest:SHA512', '-macopt', 'hexkey:00',
'-section_name', 'fips_install', '-verify'])),
"fipsinstall verify fail incorrect digest");
+
+# corrupt the module hmac
+ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.conf', '-module', $infile,
+ '-provider_name', 'fips', '-mac_name', 'HMAC',
+ '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+ '-section_name', 'fips_install', '-corrupt_desc', 'HMAC'])),
+ "fipsinstall fails when the module integrity is corrupted");
+
+# corrupt the first digest
+ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.conf', '-module', $infile,
+ '-provider_name', 'fips', '-mac_name', 'HMAC',
+ '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+ '-section_name', 'fips_install', '-corrupt_desc', 'SHA1'])),
+ "fipsinstall fails when the digest result is corrupted");
+
+# corrupt another digest
+ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.conf', '-module', $infile,
+ '-provider_name', 'fips', '-mac_name', 'HMAC',
+ '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+ '-section_name', 'fips_install', '-corrupt_desc', 'SHA3'])),
+ "fipsinstall fails when the digest result is corrupted");
diff --git a/util/libcrypto.num b/util/libcrypto.num
index d18e1a3ebb..c2eff0edb9 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4913,3 +4913,5 @@ OSSL_CMP_MSG_get0_header ? 3_0_0 EXIST::FUNCTION:CMP
BIO_f_prefix ? 3_0_0 EXIST::FUNCTION:
EVP_PKEY_CTX_new_from_name ? 3_0_0 EXIST::FUNCTION:
EVP_PKEY_CTX_new_from_pkey ? 3_0_0 EXIST::FUNCTION:
+OSSL_SELF_TEST_set_callback ? 3_0_0 EXIST::FUNCTION:
+OSSL_SELF_TEST_get_callback ? 3_0_0 EXIST::FUNCTION: