diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-06-17 11:33:16 +1000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2020-06-17 11:33:16 +1000 |
commit | 4f2271d58a36b2aee125062ffb9626c6208fa394 (patch) | |
tree | 122e6de930647c37a35b5f457448a031e51969b8 /providers | |
parent | 5a147abd790075cdc97b36ff5084e2eb1d779b95 (diff) |
Add ACVP fips module tests
For FIPS validation purposes - Automated Cryptographic Validation Protocol (ACVP) tests need to be
performed. (See https://github.com/usnistgov/ACVP). These tests are very similiar to the old CAVS tests.
This PR uses a hardwired subset of these test vectors to perform similiar operations,
to show the usage and prove that the API's are able to perform the required operations.
It may also help with communication with the lab (i.e- The lab could add a test here to show
a unworking use case - which we can then address).
The EVP layer performs these tests instead of calling lower level API's
as was done in the old FOM.
Some of these tests require access to internals that are not normally allowed/required.
The config option 'acvp_tests' (enabled by default) has been added so that this
access may be removed.
The mechanism has been implemented as additional OSSL_PARAM values that can be set and get.
A callback mechanism did not seem to add any additional benefit.
These params will not be added to the gettables lists.
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11572)
Diffstat (limited to 'providers')
-rw-r--r-- | providers/implementations/keymgmt/dh_kmgmt.c | 29 | ||||
-rw-r--r-- | providers/implementations/keymgmt/dsa_kmgmt.c | 29 | ||||
-rw-r--r-- | providers/implementations/keymgmt/ec_kmgmt.c | 47 | ||||
-rw-r--r-- | providers/implementations/keymgmt/rsa_kmgmt.c | 23 | ||||
-rw-r--r-- | providers/implementations/signature/build.info | 4 | ||||
-rw-r--r-- | providers/implementations/signature/dsa.c | 18 | ||||
-rw-r--r-- | providers/implementations/signature/ecdsa.c | 25 | ||||
-rw-r--r-- | providers/implementations/signature/rsa.c | 19 |
8 files changed, 128 insertions, 66 deletions
diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index 0dd1796dc0..c81d437dae 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -59,7 +59,6 @@ struct dh_gen_ctx { int group_nid; size_t pbits; size_t qbits; - EVP_MD *md; unsigned char *seed; /* optional FIPS186-4 param for testing */ size_t seedlen; int gindex; /* optional FIPS186-4 generator index (ignored if -1) */ @@ -69,6 +68,8 @@ struct dh_gen_ctx { int hindex; int priv_len; + const char *mdname; + const char *mdprops; OSSL_CALLBACK *cb; void *cbarg; }; @@ -411,7 +412,7 @@ static void *dh_gen_init(void *provctx, int selection) gctx->libctx = libctx; gctx->pbits = 2048; gctx->qbits = 224; - gctx->md = NULL; + gctx->mdname = NULL; gctx->gen_type = DH_PARAMGEN_TYPE_FIPS_186_4; gctx->gindex = -1; gctx->hindex = 0; @@ -498,20 +499,15 @@ static int dh_gen_set_params(void *genctx, const OSSL_PARAM params[]) return 0; p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST); if (p != NULL) { - const OSSL_PARAM *p1; - char mdprops[OSSL_MAX_PROPQUERY_SIZE] = { '\0' }; - char *str = mdprops; - if (p->data_type != OSSL_PARAM_UTF8_STRING) return 0; - p1 = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS); - if (p1 != NULL - && !OSSL_PARAM_get_utf8_string(p1, &str, sizeof(mdprops))) - return 0; - EVP_MD_free(gctx->md); - gctx->md = EVP_MD_fetch(gctx->libctx, p->data, mdprops); - if (gctx->md == NULL) + gctx->mdname = p->data; + } + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) return 0; + gctx->mdprops = p->data; } p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN); if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->priv_len)) @@ -592,6 +588,10 @@ static void *dh_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) } else if (gctx->hindex != 0) { ffc_params_set_h(ffc, gctx->hindex); } + if (gctx->mdname != NULL) { + if (!ffc_set_digest(ffc, gctx->mdname, gctx->mdprops)) + goto end; + } gctx->cb = osslcb; gctx->cbarg = cbarg; gencb = BN_GENCB_new(); @@ -609,7 +609,7 @@ static void *dh_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) gctx->generator, gencb); else ret = dh_generate_ffc_parameters(dh, gctx->gen_type, gctx->pbits, - gctx->qbits, gctx->md, gencb); + gctx->qbits, gencb); if (ret <= 0) goto end; } @@ -641,7 +641,6 @@ static void dh_gen_cleanup(void *genctx) return; OPENSSL_clear_free(gctx->seed, gctx->seedlen); - EVP_MD_free(gctx->md); OPENSSL_free(gctx); } diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c index af8361fb28..5fa3e08af9 100644 --- a/providers/implementations/keymgmt/dsa_kmgmt.c +++ b/providers/implementations/keymgmt/dsa_kmgmt.c @@ -56,13 +56,14 @@ struct dsa_gen_ctx { /* All these parameters are used for parameter generation only */ size_t pbits; size_t qbits; - EVP_MD *md; unsigned char *seed; /* optional FIPS186-4 param for testing */ size_t seedlen; int gindex; /* optional FIPS186-4 generator index (ignored if -1) */ int gen_type; /* DSA_PARAMGEN_TYPE_FIPS_186_2 or DSA_PARAMGEN_TYPE_FIPS_186_4 */ int pcounter; int hindex; + const char *mdname; + const char *mdprops; OSSL_CALLBACK *cb; void *cbarg; }; @@ -364,7 +365,6 @@ static void *dsa_gen_init(void *provctx, int selection) gctx->libctx = libctx; gctx->pbits = 2048; gctx->qbits = 224; - gctx->md = NULL; gctx->gen_type = DSA_PARAMGEN_TYPE_FIPS_186_4; gctx->gindex = -1; gctx->pcounter = -1; @@ -440,21 +440,15 @@ static int dsa_gen_set_params(void *genctx, const OSSL_PARAM params[]) return 0; p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST); if (p != NULL) { - const OSSL_PARAM *p1; - char mdprops[OSSL_MAX_PROPQUERY_SIZE] = { '\0' }; - char *str = mdprops; - if (p->data_type != OSSL_PARAM_UTF8_STRING) return 0; - p1 = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS); - if (p1 != NULL) { - if (!OSSL_PARAM_get_utf8_string(p1, &str, sizeof(mdprops))) - return 0; - } - EVP_MD_free(gctx->md); - gctx->md = EVP_MD_fetch(gctx->libctx, p->data, mdprops); - if (gctx->md == NULL) + gctx->mdname = p->data; + } + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) return 0; + gctx->mdprops = p->data; } return 1; } @@ -523,10 +517,14 @@ static void *dsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) } else if (gctx->hindex != 0) { ffc_params_set_h(ffc, gctx->hindex); } + if (gctx->mdname != NULL) { + if (!ffc_set_digest(ffc, gctx->mdname, gctx->mdprops)) + goto end; + } if ((gctx->selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { if (dsa_generate_ffc_parameters(dsa, gctx->gen_type, - gctx->pbits, gctx->qbits, gctx->md, + gctx->pbits, gctx->qbits, gencb) <= 0) goto end; } @@ -556,7 +554,6 @@ static void dsa_gen_cleanup(void *genctx) return; OPENSSL_clear_free(gctx->seed, gctx->seedlen); - EVP_MD_free(gctx->md); OPENSSL_free(gctx); } diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index 7e3220739f..d926ec2bd2 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -110,6 +110,7 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, OSSL_PARAM params[], int include_private, unsigned char **pub_key) { + BIGNUM *x = NULL, *y = NULL; const BIGNUM *priv_key = NULL; const EC_POINT *pub_point = NULL; const EC_GROUP *ecg = NULL; @@ -125,6 +126,7 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, pub_point = EC_KEY_get0_public_key(eckey); if (pub_point != NULL) { + OSSL_PARAM *p = NULL, *px = NULL, *py = NULL; /* * EC_POINT_point2buf() can generate random numbers in some * implementations so we need to ensure we use the correct libctx. @@ -133,14 +135,41 @@ int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, if (bnctx == NULL) goto err; - /* convert pub_point to a octet string according to the SECG standard */ - if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point, - POINT_CONVERSION_COMPRESSED, - pub_key, bnctx)) == 0 - || !ossl_param_build_set_octet_string(tmpl, params, - OSSL_PKEY_PARAM_PUB_KEY, - *pub_key, pub_key_len)) - goto err; + + /* If we are doing a get then check first before decoding the point */ + if (tmpl == NULL) { + p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY); + px = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_X); + py = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_Y); + } + + if (p != NULL || tmpl != NULL) { + /* convert pub_point to a octet string according to the SECG standard */ + if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point, + POINT_CONVERSION_COMPRESSED, + pub_key, bnctx)) == 0 + || !ossl_param_build_set_octet_string(tmpl, p, + OSSL_PKEY_PARAM_PUB_KEY, + *pub_key, pub_key_len)) + goto err; + } + if (px != NULL || py != NULL) { + if (px != NULL) + x = BN_CTX_get(bnctx); + if (py != NULL) + y = BN_CTX_get(bnctx); + + if (!EC_POINT_get_affine_coordinates(ecg, pub_point, x, y, bnctx)) + goto err; + if (px != NULL + && !ossl_param_build_set_bn(tmpl, px, + OSSL_PKEY_PARAM_EC_PUB_X, x)) + goto err; + if (py != NULL + && !ossl_param_build_set_bn(tmpl, py, + OSSL_PKEY_PARAM_EC_PUB_Y, y)) + goto err; + } } if (priv_key != NULL && include_private) { @@ -532,6 +561,8 @@ static const OSSL_PARAM ec_known_gettable_params[] = { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_TLS_ENCODED_PT, NULL, 0), EC_IMEXPORTABLE_DOM_PARAMETERS, EC_IMEXPORTABLE_PUBLIC_KEY, + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0), + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0), EC_IMEXPORTABLE_PRIVATE_KEY, EC_IMEXPORTABLE_OTHER_PARAMETERS, OSSL_PARAM_END diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c index 3091c1dee0..313b9c292d 100644 --- a/providers/implementations/keymgmt/rsa_kmgmt.c +++ b/providers/implementations/keymgmt/rsa_kmgmt.c @@ -380,6 +380,11 @@ struct rsa_gen_ctx { /* For generation callback */ OSSL_CALLBACK *cb; void *cbarg; + +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) + /* ACVP test parameters */ + OSSL_PARAM *acvp_test_params; +#endif }; static int rsa_gencb(int p, int n, BN_GENCB *cb) @@ -389,7 +394,6 @@ static int rsa_gencb(int p, int n, BN_GENCB *cb) params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p); params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n); - return gctx->cb(params, gctx->cbarg); } @@ -451,6 +455,11 @@ static int rsa_gen_set_params(void *genctx, const OSSL_PARAM params[]) && !pss_params_fromdata(&gctx->pss_params, params, gctx->rsa_type, gctx->libctx)) return 0; +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) + /* Any ACVP test related parameters are copied into a params[] */ + if (!rsa_acvp_test_gen_params_new(&gctx->acvp_test_params, params)) + return 0; +#endif return 1; } @@ -525,6 +534,13 @@ static void *rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) if (gencb != NULL) BN_GENCB_set(gencb, rsa_gencb, genctx); +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) + if (gctx->acvp_test_params != NULL) { + if (!rsa_acvp_test_set_params(rsa_tmp, gctx->acvp_test_params)) + goto err; + } +#endif + if (!RSA_generate_multi_prime_key(rsa_tmp, (int)gctx->nbits, (int)gctx->primes, gctx->pub_exp, gencb)) @@ -551,7 +567,10 @@ static void rsa_gen_cleanup(void *genctx) if (gctx == NULL) return; - +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) + rsa_acvp_test_gen_params_free(gctx->acvp_test_params); + gctx->acvp_test_params = NULL; +#endif BN_clear_free(gctx->pub_exp); OPENSSL_free(gctx); } diff --git a/providers/implementations/signature/build.info b/providers/implementations/signature/build.info index dbe0876a0e..0e7765ae24 100644 --- a/providers/implementations/signature/build.info +++ b/providers/implementations/signature/build.info @@ -3,7 +3,6 @@ $DSA_GOAL=../../libimplementations.a $EC_GOAL=../../libimplementations.a -$ECDSA_GOAL=../../libimplementations.a IF[{- !$disabled{dsa} -}] SOURCE[$DSA_GOAL]=dsa.c @@ -11,7 +10,8 @@ ENDIF IF[{- !$disabled{ec} -}] SOURCE[$EC_GOAL]=eddsa.c - SOURCE[$ECDSA_GOAL]=ecdsa.c + SOURCE[../../libfips.a]=ecdsa.c + SOURCE[../../libnonfips.a]=ecdsa.c ENDIF SOURCE[../../libfips.a]=rsa.c diff --git a/providers/implementations/signature/dsa.c b/providers/implementations/signature/dsa.c index de6aac670b..a4902babcb 100644 --- a/providers/implementations/signature/dsa.c +++ b/providers/implementations/signature/dsa.c @@ -338,13 +338,17 @@ int dsa_digest_verify_final(void *vpdsactx, const unsigned char *sig, static void dsa_freectx(void *vpdsactx) { - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - - DSA_free(pdsactx->dsa); - EVP_MD_CTX_free(pdsactx->mdctx); - EVP_MD_free(pdsactx->md); - - OPENSSL_free(pdsactx); + PROV_DSA_CTX *ctx = (PROV_DSA_CTX *)vpdsactx; + + OPENSSL_free(ctx->propq); + EVP_MD_CTX_free(ctx->mdctx); + EVP_MD_free(ctx->md); + ctx->propq = NULL; + ctx->mdctx = NULL; + ctx->md = NULL; + ctx->mdsize = 0; + DSA_free(ctx->dsa); + OPENSSL_free(ctx); } static void *dsa_dupctx(void *vpdsactx) diff --git a/providers/implementations/signature/ecdsa.c b/providers/implementations/signature/ecdsa.c index d96f597a92..61a13f4f2f 100644 --- a/providers/implementations/signature/ecdsa.c +++ b/providers/implementations/signature/ecdsa.c @@ -73,14 +73,6 @@ typedef struct { EVP_MD *md; EVP_MD_CTX *mdctx; /* - * This indicates that KAT (CAVS) test is running. Externally an app will - * override the random callback such that the generated private key and k - * are known. - * Normal operation will loop to choose a new k if the signature is not - * valid - but for this mode of operation it forces a failure instead. - */ - unsigned int kattest; - /* * Internally used to cache the results of calling the EC group * sign_setup() methods which are then passed to the sign operation. * This is used by CAVS failure tests to terminate a loop if the signature @@ -89,6 +81,16 @@ typedef struct { */ BIGNUM *kinv; BIGNUM *r; +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) + /* + * This indicates that KAT (CAVS) test is running. Externally an app will + * override the random callback such that the generated private key and k + * are known. + * Normal operation will loop to choose a new k if the signature is not + * valid - but for this mode of operation it forces a failure instead. + */ + unsigned int kattest; +#endif } PROV_ECDSA_CTX; static void *ecdsa_newctx(void *provctx, const char *propq) @@ -131,8 +133,10 @@ static int ecdsa_sign(void *vctx, unsigned char *sig, size_t *siglen, return 1; } +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) if (ctx->kattest && !ECDSA_sign_setup(ctx->ec, NULL, &ctx->kinv, &ctx->r)) return 0; +#endif if (sigsize < (size_t)ecsize) return 0; @@ -201,8 +205,10 @@ static int get_md_nid(const EVP_MD *md) static void free_md(PROV_ECDSA_CTX *ctx) { + OPENSSL_free(ctx->propq); EVP_MD_CTX_free(ctx->mdctx); EVP_MD_free(ctx->md); + ctx->propq = NULL; ctx->mdctx = NULL; ctx->md = NULL; ctx->mdsize = 0; @@ -414,10 +420,11 @@ static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[]) */ return 1; } - +#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_KAT); if (p != NULL && !OSSL_PARAM_get_uint(p, &ctx->kattest)) return 0; +#endif p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); if (p != NULL && !OSSL_PARAM_get_size_t(p, &ctx->mdsize)) diff --git a/providers/implementations/signature/rsa.c b/providers/implementations/signature/rsa.c index 81611bb4f0..5af64d2a90 100644 --- a/providers/implementations/signature/rsa.c +++ b/providers/implementations/signature/rsa.c @@ -594,13 +594,15 @@ static int rsa_verify_recover(void *vprsactx, } *routlen = ret; - if (routsize < (size_t)ret) { - ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL, - "buffer size is %d, should be %d", - routsize, ret); - return 0; + if (rout != prsactx->tbuf) { + if (routsize < (size_t)ret) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL, + "buffer size is %d, should be %d", + routsize, ret); + return 0; + } + memcpy(rout, prsactx->tbuf, ret); } - memcpy(rout, prsactx->tbuf, ret); break; case RSA_PKCS1_PADDING: @@ -655,7 +657,10 @@ static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen, } return 1; case RSA_X931_PADDING: - if (rsa_verify_recover(prsactx, NULL, &rslen, 0, sig, siglen) <= 0) + if (!setup_tbuf(prsactx)) + return 0; + if (rsa_verify_recover(prsactx, prsactx->tbuf, &rslen, 0, + sig, siglen) <= 0) return 0; break; case RSA_PKCS1_PSS_PADDING: |