diff options
author | Pauli <pauli@openssl.org> | 2022-10-26 11:48:58 +1100 |
---|---|---|
committer | Pauli <pauli@openssl.org> | 2022-11-02 08:41:05 +1100 |
commit | 18477977496bbb183e0ccb71b71b1a8a87321729 (patch) | |
tree | 1db8ee48129418bad1e231adc21f413f62e2f1f4 /providers/fips | |
parent | df8f8432eb10b2ed56e48b692f930991f9624453 (diff) |
Update FIPS KATs for 140-3
Co-authored-by: Randall Steck <rsteck@thinqsoft.com>
Co-authored-by: Mark J. Minnoch <mark@keypair.us>
Co-authored-by: Steve Weymann <steve@keypair.us>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/19486)
Diffstat (limited to 'providers/fips')
-rw-r--r-- | providers/fips/self_test.c | 62 | ||||
-rw-r--r-- | providers/fips/self_test_data.inc | 93 | ||||
-rw-r--r-- | providers/fips/self_test_kats.c | 144 |
3 files changed, 266 insertions, 33 deletions
diff --git a/providers/fips/self_test.c b/providers/fips/self_test.c index 80d048a847..bcb23344da 100644 --- a/providers/fips/self_test.c +++ b/providers/fips/self_test.c @@ -173,6 +173,64 @@ DEP_FINI_ATTRIBUTE void cleanup(void) #endif /* + * We need an explicit HMAC-SHA-256 KAT even though it is also + * checked as part of the KDF KATs. Refer IG 10.3. + */ +static const unsigned char hmac_kat_pt[] = { + 0xdd, 0x0c, 0x30, 0x33, 0x35, 0xf9, 0xe4, 0x2e, + 0xc2, 0xef, 0xcc, 0xbf, 0x07, 0x95, 0xee, 0xa2 +}; +static const unsigned char hmac_kat_key[] = { + 0xf4, 0x55, 0x66, 0x50, 0xac, 0x31, 0xd3, 0x54, + 0x61, 0x61, 0x0b, 0xac, 0x4e, 0xd8, 0x1b, 0x1a, + 0x18, 0x1b, 0x2d, 0x8a, 0x43, 0xea, 0x28, 0x54, + 0xcb, 0xae, 0x22, 0xca, 0x74, 0x56, 0x08, 0x13 +}; +static const unsigned char hmac_kat_digest[] = { + 0xf5, 0xf5, 0xe5, 0xf2, 0x66, 0x49, 0xe2, 0x40, + 0xfc, 0x9e, 0x85, 0x7f, 0x2b, 0x9a, 0xbe, 0x28, + 0x20, 0x12, 0x00, 0x92, 0x82, 0x21, 0x3e, 0x51, + 0x44, 0x5d, 0xe3, 0x31, 0x04, 0x01, 0x72, 0x6b +}; + +static int integrity_self_test(OSSL_SELF_TEST *ev, OSSL_LIB_CTX *libctx) +{ + int ok = 0; + unsigned char out[EVP_MAX_MD_SIZE]; + size_t out_len = 0; + + OSSL_PARAM params[2]; + EVP_MAC *mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL); + EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(mac); + + OSSL_SELF_TEST_onbegin(ev, OSSL_SELF_TEST_TYPE_KAT_INTEGRITY, + OSSL_SELF_TEST_DESC_INTEGRITY_HMAC); + + params[0] = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0); + params[1] = OSSL_PARAM_construct_end(); + + if (ctx == NULL + || mac == NULL + || !EVP_MAC_init(ctx, hmac_kat_key, sizeof(hmac_kat_key), params) + || !EVP_MAC_update(ctx, hmac_kat_pt, sizeof(hmac_kat_pt)) + || !EVP_MAC_final(ctx, out, &out_len, MAX_MD_SIZE)) + goto err; + + /* Optional corruption */ + OSSL_SELF_TEST_oncorrupt_byte(ev, out); + + if (out_len != sizeof(hmac_kat_digest) + || memcmp(out, hmac_kat_digest, out_len) != 0) + goto err; + ok = 1; +err: + OSSL_SELF_TEST_onend(ev, ok); + EVP_MAC_free(mac); + EVP_MAC_CTX_free(ctx); + return ok; +} + +/* * Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify * the result matches the expected value. * Return 1 if verified, or 0 if it fails. @@ -190,6 +248,9 @@ static int verify_integrity(OSSL_CORE_BIO *bio, OSSL_FUNC_BIO_read_ex_fn read_ex EVP_MAC_CTX *ctx = NULL; OSSL_PARAM params[2], *p = params; + if (!integrity_self_test(ev, libctx)) + goto err; + OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC); mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL); @@ -355,6 +416,7 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) goto end; } } + ok = 1; end: OSSL_SELF_TEST_free(ev); diff --git a/providers/fips/self_test_data.inc b/providers/fips/self_test_data.inc index 8ae8cd6f4a..5895a31a5b 100644 --- a/providers/fips/self_test_data.inc +++ b/providers/fips/self_test_data.inc @@ -106,6 +106,12 @@ typedef struct st_kat_sign_st { const char *algorithm; const char *mdalgorithm; const ST_KAT_PARAM *key; + const unsigned char *entropy; + size_t entropy_len; + const unsigned char *nonce; + size_t nonce_len; + const unsigned char *persstr; + size_t persstr_len; const unsigned char *sig_expected; /* Set to NULL if this value changes */ size_t sig_expected_len; } ST_KAT_SIGN; @@ -235,19 +241,6 @@ static const unsigned char aes_128_ecb_ct[] = { }; static const ST_KAT_CIPHER st_kat_cipher_tests[] = { -#ifndef OPENSSL_NO_DES - { - { - OSSL_SELF_TEST_DESC_CIPHER_TDES, - "DES-EDE3-CBC", - ITM(des_ede3_cbc_pt), - ITM(des_ede3_cbc_ct) - }, - CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT, - ITM(des_ede3_cbc_key), - ITM(des_ede3_cbc_iv), - }, -#endif { { OSSL_SELF_TEST_DESC_CIPHER_AES_GCM, @@ -1396,6 +1389,16 @@ static const unsigned char ecd_prime_pub[] = { 0xc4, 0xb7, 0x33, 0x68, 0xe4, 0x24, 0xa9, 0x12, 0x82 }; +static const unsigned char ecdsa_prime_expected_sig[] = { + 0x30, 0x3d, 0x02, 0x1d, 0x00, 0xd2, 0x4a, 0xc9, + 0x4f, 0xaf, 0xdb, 0x62, 0xfc, 0x41, 0x4a, 0x81, + 0x2a, 0x9f, 0xcf, 0xa3, 0xda, 0xfe, 0xa3, 0x49, + 0xbd, 0xea, 0xbf, 0x2a, 0x51, 0xb4, 0x0b, 0xc3, + 0xbc, 0x02, 0x1c, 0x7f, 0x30, 0xb7, 0xad, 0xab, + 0x09, 0x6e, 0x3c, 0xad, 0x7f, 0xf9, 0x5e, 0xaa, + 0xe2, 0x38, 0xe5, 0x29, 0x16, 0xc4, 0xc8, 0x77, + 0xa1, 0xf8, 0x60, 0x77, 0x39, 0x7a, 0xec +}; static const ST_KAT_PARAM ecdsa_prime_key[] = { ST_KAT_PARAM_UTF8STRING(OSSL_PKEY_PARAM_GROUP_NAME, ecd_prime_curve_name), ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PUB_KEY, ecd_prime_pub), @@ -1421,6 +1424,17 @@ static const unsigned char ecd_bin_pub[] = { 0x02, 0xa8, 0xe9, 0x6f, 0x54, 0xfd, 0x3a, 0x6b, 0x99, 0xb6, 0x8f, 0x80, 0x46 }; +static const unsigned char ecdsa_bin_expected_sig[] = { + 0x30, 0x3f, 0x02, 0x1d, 0x08, 0x11, 0x7c, 0xcd, + 0xf4, 0xa1, 0x31, 0x9a, 0xc1, 0xfd, 0x50, 0x0e, + 0x5d, 0xa9, 0xb6, 0x0e, 0x95, 0x49, 0xe1, 0xbd, + 0x44, 0xe3, 0x5b, 0xa9, 0x35, 0x94, 0xa5, 0x2f, + 0xae, 0x02, 0x1e, 0x00, 0xe3, 0xba, 0xb8, 0x8f, + 0x4b, 0x05, 0x76, 0x88, 0x1e, 0x49, 0xd6, 0x62, + 0x76, 0xd3, 0x22, 0x4d, 0xa3, 0x7b, 0x04, 0xcc, + 0xfa, 0x7b, 0x41, 0x9b, 0x8c, 0xaf, 0x1b, 0x6d, + 0xbd +}; static const ST_KAT_PARAM ecdsa_bin_key[] = { ST_KAT_PARAM_UTF8STRING(OSSL_PKEY_PARAM_GROUP_NAME, ecd_bin_curve_name), ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PUB_KEY, ecd_bin_pub), @@ -1546,6 +1560,16 @@ static const unsigned char dsa_priv[] = { 0x66, 0x35, 0xba, 0xc3, 0x94, 0x23, 0x50, 0x5e, 0x40, 0x7e, 0x5c, 0xb7 }; +static const unsigned char dsa_expected_sig[] = { + 0x30, 0x3c, 0x02, 0x1c, 0x70, 0xa4, 0x77, 0xb6, + 0x02, 0xb5, 0xd3, 0x07, 0x21, 0x22, 0x2d, 0xe3, + 0x4f, 0x7d, 0xfd, 0xfd, 0x6b, 0x4f, 0x03, 0x27, + 0x4c, 0xd3, 0xb2, 0x8c, 0x7c, 0xc5, 0xc4, 0xdf, + 0x02, 0x1c, 0x11, 0x52, 0x65, 0x16, 0x9f, 0xbd, + 0x4c, 0xe5, 0xab, 0xb2, 0x01, 0xd0, 0x7a, 0x30, + 0x5c, 0xc5, 0xba, 0x22, 0xc6, 0x62, 0x7e, 0xa6, + 0x7d, 0x98, 0x96, 0xc9, 0x77, 0x00 +}; static const ST_KAT_PARAM dsa_key[] = { ST_KAT_PARAM_BIGNUM(OSSL_PKEY_PARAM_FFC_P, dsa_p), @@ -1557,12 +1581,31 @@ static const ST_KAT_PARAM dsa_key[] = { }; #endif /* OPENSSL_NO_DSA */ +/* Hash DRBG inputs for signature KATs */ +static const unsigned char sig_kat_entropyin[] = { + 0x06, 0x6d, 0xc8, 0xce, 0x75, 0xb2, 0x89, 0x66, 0xa6, 0x85, 0x16, 0x3f, + 0xe2, 0xa4, 0xd4, 0x27, 0xfb, 0xdb, 0x61, 0x66, 0x50, 0x61, 0x6b, 0xa2, + 0x82, 0xfc, 0x33, 0x2b, 0x4e, 0x6f, 0x12, 0x20 +}; +static const unsigned char sig_kat_nonce[] = { + 0x55, 0x9f, 0x7c, 0x64, 0x89, 0x70, 0x83, 0xec, 0x2d, 0x73, 0x70, 0xd9, + 0xf0, 0xe5, 0x07, 0x1f +}; +static const unsigned char sig_kat_persstr[] = { + 0x88, 0x6f, 0x54, 0x9a, 0xad, 0x1a, 0xc6, 0x3d, 0x18, 0xcb, 0xcc, 0x66, + 0x85, 0xda, 0xa2, 0xc2, 0xf7, 0x9e, 0xb0, 0x89, 0x4c, 0xb4, 0xae, 0xf1, + 0xac, 0x54, 0x4f, 0xce, 0x57, 0xf1, 0x5e, 0x11 +}; + static const ST_KAT_SIGN st_kat_sign_tests[] = { { OSSL_SELF_TEST_DESC_SIGN_RSA, "RSA", "SHA-256", rsa_crt_key, + ITM(sig_kat_entropyin), + ITM(sig_kat_nonce), + ITM(sig_kat_persstr), ITM(rsa_expected_sig) }, #ifndef OPENSSL_NO_EC @@ -1571,10 +1614,10 @@ static const ST_KAT_SIGN st_kat_sign_tests[] = { "EC", "SHA-256", ecdsa_prime_key, - /* - * The ECDSA signature changes each time due to it using a random k. - * So there is no expected KAT for this case. - */ + ITM(sig_kat_entropyin), + ITM(sig_kat_nonce), + ITM(sig_kat_persstr), + ITM(ecdsa_prime_expected_sig) }, # ifndef OPENSSL_NO_EC2M { @@ -1582,10 +1625,10 @@ static const ST_KAT_SIGN st_kat_sign_tests[] = { "EC", "SHA-256", ecdsa_bin_key, - /* - * The ECDSA signature changes each time due to it using a random k. - * So there is no expected KAT for this case. - */ + ITM(sig_kat_entropyin), + ITM(sig_kat_nonce), + ITM(sig_kat_persstr), + ITM(ecdsa_bin_expected_sig) }, # endif #endif /* OPENSSL_NO_EC */ @@ -1595,10 +1638,10 @@ static const ST_KAT_SIGN st_kat_sign_tests[] = { "DSA", "SHA-256", dsa_key, - /* - * The DSA signature changes each time due to it using a random k. - * So there is no expected KAT for this case. - */ + ITM(sig_kat_entropyin), + ITM(sig_kat_nonce), + ITM(sig_kat_persstr), + ITM(dsa_expected_sig) }, #endif /* OPENSSL_NO_DSA */ }; diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c index ad896e40d2..74ee25dcb6 100644 --- a/providers/fips/self_test_kats.c +++ b/providers/fips/self_test_kats.c @@ -12,11 +12,18 @@ #include <openssl/kdf.h> #include <openssl/core_names.h> #include <openssl/param_build.h> +#include <openssl/rand.h> #include "internal/cryptlib.h" #include "internal/nelem.h" #include "self_test.h" #include "self_test_data.inc" +static int set_kat_drbg(OSSL_LIB_CTX *ctx, + const unsigned char *entropy, size_t entropy_len, + const unsigned char *nonce, size_t nonce_len, + const unsigned char *persstr, size_t persstr_len); +static int reset_original_drbg(OSSL_LIB_CTX *ctx); + static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { @@ -437,7 +444,7 @@ err: #endif /* !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC) */ static int self_test_sign(const ST_KAT_SIGN *t, - OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) + OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { int ret = 0; OSSL_PARAM *params = NULL, *params_sig = NULL; @@ -499,10 +506,6 @@ static int self_test_sign(const ST_KAT_SIGN *t, || EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) goto err; - /* - * Used by RSA, for other key types where the signature changes, we - * can only use the verify. - */ if (t->sig_expected != NULL && (siglen != t->sig_expected_len || memcmp(sig, t->sig_expected, t->sig_expected_len) != 0)) @@ -689,9 +692,16 @@ static int self_test_kas(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) static int self_test_signatures(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { int i, ret = 1; - - for (i = 0; i < (int)OSSL_NELEM(st_kat_sign_tests); ++i) { - if (!self_test_sign(&st_kat_sign_tests[i], st, libctx)) + const ST_KAT_SIGN *t; + + for (i = 0; ret && i < (int)OSSL_NELEM(st_kat_sign_tests); ++i) { + t = st_kat_sign_tests + i; + if (!set_kat_drbg(libctx, t->entropy, t->entropy_len, + t->nonce, t->nonce_len, t->persstr, t->persstr_len)) + return 0; + if (!self_test_sign(t, st, libctx)) + ret = 0; + if (!reset_original_drbg(libctx)) ret = 0; } return ret; @@ -723,3 +733,121 @@ int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) return ret; } + +/* + * Swap the library context DRBG for KAT testing + * + * In FIPS 140-3, the asymmetric POST must be a KAT, not a PCT. For DSA and ECDSA, + * the sign operation includes the random value 'k'. For a KAT to work, we + * have to have control of the DRBG to make sure it is in a "test" state, where + * its output is truly deterministic. + * + */ + +/* + * The default private DRBG of the library context, saved for the duration + * of KAT testing. + */ +static EVP_RAND_CTX *saved_rand = NULL; + +/* Replacement "random" source */ +static EVP_RAND_CTX *kat_rand = NULL; + +static int set_kat_drbg(OSSL_LIB_CTX *ctx, + const unsigned char *entropy, size_t entropy_len, + const unsigned char *nonce, size_t nonce_len, + const unsigned char *persstr, size_t persstr_len) { + EVP_RAND *rand; + unsigned int strength = 256; + EVP_RAND_CTX *parent_rand = NULL; + OSSL_PARAM drbg_params[3] = { + OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END + }; + + /* If not NULL, we didn't cleanup from last call: BAD */ + if (kat_rand != NULL || saved_rand != NULL) + return 0; + + rand = EVP_RAND_fetch(ctx, "TEST-RAND", NULL); + if (rand == NULL) + return 0; + + parent_rand = EVP_RAND_CTX_new(rand, NULL); + EVP_RAND_free(rand); + if (parent_rand == NULL) + goto err; + + drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, &strength); + if (!EVP_RAND_CTX_set_params(parent_rand, drbg_params)) + goto err; + + rand = EVP_RAND_fetch(ctx, "HASH-DRBG", NULL); + if (rand == NULL) + goto err; + + kat_rand = EVP_RAND_CTX_new(rand, parent_rand); + EVP_RAND_free(rand); + if (kat_rand == NULL) + goto err; + + drbg_params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA256", 0); + if (!EVP_RAND_CTX_set_params(kat_rand, drbg_params)) + goto err; + + /* Instantiate the RNGs */ + drbg_params[0] = + OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY, + (void *)entropy, entropy_len); + drbg_params[1] = + OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_NONCE, + (void *)nonce, nonce_len); + if (!EVP_RAND_instantiate(parent_rand, strength, 0, NULL, 0, drbg_params)) + goto err; + + EVP_RAND_CTX_free(parent_rand); + parent_rand = NULL; + + if (!EVP_RAND_instantiate(kat_rand, strength, 0, persstr, persstr_len, NULL)) + goto err; + + /* Update the library context DRBG */ + if ((saved_rand = RAND_get0_private(ctx)) != NULL) + /* Avoid freeing this since we replace it */ + if (!EVP_RAND_CTX_up_ref(saved_rand)) { + saved_rand = NULL; + goto err; + } + if (RAND_set0_private(ctx, kat_rand) > 0) { + /* Keeping a copy to verify zeroization */ + if (EVP_RAND_CTX_up_ref(kat_rand)) + return 1; + if (saved_rand != NULL) + RAND_set0_private(ctx, saved_rand); + } + + err: + EVP_RAND_CTX_free(parent_rand); + EVP_RAND_CTX_free(saved_rand); + EVP_RAND_CTX_free(kat_rand); + kat_rand = saved_rand = NULL; + return 0; +} + +static int reset_original_drbg(OSSL_LIB_CTX *ctx) { + int ret = 1; + + if (saved_rand != NULL) { + if (!RAND_set0_private(ctx, saved_rand)) + ret = 0; + saved_rand = NULL; + } + if (kat_rand != NULL) { + if (!EVP_RAND_uninstantiate(kat_rand) + || !EVP_RAND_verify_zeroization(kat_rand)) + ret = 0; + EVP_RAND_CTX_free(kat_rand); + kat_rand = NULL; + } + return ret; +} + |