From 8083fd3a183d4c881d6b15727cbc6cb7faeb3280 Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Sun, 16 Feb 2020 13:03:46 +1000 Subject: [PATCH] Add FFC param/key validation Embed libctx in dsa and dh objects and cleanup internal methods to not pass libctx (This makes it consistent with the rsa changes) Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/10910) --- crypto/dh/dh_check.c | 123 +++- crypto/dh/dh_gen.c | 5 +- crypto/dh/dh_group_params.c | 41 +- crypto/dh/dh_key.c | 104 ++- crypto/dh/dh_lib.c | 27 +- crypto/dh/dh_local.h | 1 + crypto/dsa/dsa_check.c | 85 +++ crypto/dsa/dsa_gen.c | 30 +- crypto/dsa/dsa_key.c | 49 +- crypto/dsa/dsa_lib.c | 26 +- crypto/dsa/dsa_local.h | 4 +- crypto/dsa/dsa_ossl.c | 7 +- crypto/dsa/dsa_sign.c | 8 +- crypto/ffc/build.info | 3 +- crypto/ffc/ffc_key_generate.c | 20 +- crypto/ffc/ffc_key_validate.c | 120 ++++ crypto/ffc/ffc_params_generate.c | 32 +- crypto/ffc/ffc_params_validate.c | 80 +++ include/crypto/dh.h | 14 +- include/crypto/dsa.h | 19 +- include/internal/ffc.h | 41 +- providers/implementations/exchange/dh_exch.c | 4 +- providers/implementations/keymgmt/dh_kmgmt.c | 5 +- providers/implementations/keymgmt/dsa_kmgmt.c | 2 +- providers/implementations/signature/dsa.c | 3 +- test/build.info | 7 +- test/ffc_internal_test.c | 650 ++++++++++++++++++ test/recipes/03-test_internal_ffc.t | 11 + 28 files changed, 1300 insertions(+), 221 deletions(-) create mode 100644 crypto/dsa/dsa_check.c create mode 100644 crypto/ffc/ffc_key_validate.c create mode 100644 crypto/ffc/ffc_params_validate.c create mode 100644 test/ffc_internal_test.c create mode 100644 test/recipes/03-test_internal_ffc.t diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index 8bb245207b..4832230f6c 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -11,6 +11,7 @@ #include "internal/cryptlib.h" #include #include "dh_local.h" +#include "crypto/dh.h" /*- * Check that p and g are suitable enough @@ -37,6 +38,28 @@ int DH_check_params_ex(const DH *dh) return errflags == 0; } +#ifdef FIPS_MODE +int DH_check_params(const DH *dh, int *ret) +{ + int nid; + + *ret = 0; + /* + * SP800-56A R3 Section 5.5.2 Assurances of Domain Parameter Validity + * (1a) The domain parameters correspond to any approved safe prime group. + */ + nid = DH_get_nid((DH *)dh); + if (nid != NID_undef) + return 1; + /* + * OR + * (2b) FFC domain params conform to FIPS-186-4 explicit domain param + * validity tests. + */ + return ffc_params_FIPS186_4_validate(&dh->params, FFC_PARAM_TYPE_DH, NULL, + FFC_PARAMS_VALIDATE_ALL, ret, NULL); +} +#else int DH_check_params(const DH *dh, int *ret) { int ok = 0; @@ -73,6 +96,7 @@ int DH_check_params(const DH *dh, int *ret) BN_CTX_free(ctx); return ok; } +#endif /* FIPS_MODE */ /*- * Check that p is a safe prime and @@ -107,11 +131,20 @@ int DH_check_ex(const DH *dh) return errflags == 0; } +/* Note: according to documentation - this only checks the params */ int DH_check(const DH *dh, int *ret) { +#ifdef FIPS_MODE + return DH_check_params(dh, ret); +#else int ok = 0, r; BN_CTX *ctx = NULL; BIGNUM *t1 = NULL, *t2 = NULL; + int nid = DH_get_nid((DH *)dh); + + *ret = 0; + if (nid != NID_undef) + return 1; if (!DH_check_params(dh, ret)) return 0; @@ -171,6 +204,7 @@ int DH_check(const DH *dh, int *ret) BN_CTX_end(ctx); BN_CTX_free(ctx); return ok; +#endif /* FIPS_MODE */ } int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key) @@ -190,38 +224,83 @@ int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key) return errflags == 0; } +/* + * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Full public key validation. + */ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) +{ + return ffc_validate_public_key(&dh->params, pub_key, ret); +} + +/* + * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Partial public key validation. + * To only be used with ephemeral FFC public keys generated using the approved + * safe-prime groups. + */ +int dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret) +{ + return ffc_validate_public_key_partial(&dh->params, pub_key, ret); +} + +int dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret) { int ok = 0; - BIGNUM *tmp = NULL; - BN_CTX *ctx = NULL; + BIGNUM *two_powN = NULL, *upper; *ret = 0; - ctx = BN_CTX_new(); - if (ctx == NULL) - goto err; - BN_CTX_start(ctx); - tmp = BN_CTX_get(ctx); - if (tmp == NULL || !BN_set_word(tmp, 1)) - goto err; - if (BN_cmp(pub_key, tmp) <= 0) - *ret |= DH_CHECK_PUBKEY_TOO_SMALL; - if (BN_copy(tmp, dh->params.p) == NULL || !BN_sub_word(tmp, 1)) + two_powN = BN_new(); + if (two_powN == NULL) + return 0; + if (dh->params.q == NULL) goto err; - if (BN_cmp(pub_key, tmp) >= 0) - *ret |= DH_CHECK_PUBKEY_TOO_LARGE; + upper = dh->params.q; - if (dh->params.q != NULL) { - /* Check pub_key^q == 1 mod p */ - if (!BN_mod_exp(tmp, pub_key, dh->params.q, dh->params.p, ctx)) + /* Is it from an approved Safe prime group ?*/ + if (DH_get_nid((DH *)dh) != NID_undef) { + if (!BN_lshift(two_powN, BN_value_one(), dh->length)) goto err; - if (!BN_is_one(tmp)) - *ret |= DH_CHECK_PUBKEY_INVALID; + if (BN_cmp(two_powN, dh->params.q) < 0) + upper = two_powN; } + if (!ffc_validate_private_key(upper, priv_key, ret)) + goto err; ok = 1; - err: - BN_CTX_end(ctx); - BN_CTX_free(ctx); +err: + BN_free(two_powN); return ok; } + +/* + * FFC pairwise check from SP800-56A R3. + * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency + */ +int dh_check_pairwise(DH *dh) +{ + int ret = 0; + BN_CTX *ctx = NULL; + BIGNUM *pub_key = NULL; + + if (dh->params.p == NULL + || dh->params.g == NULL + || dh->priv_key == NULL + || dh->pub_key == NULL) + return 0; + + ctx = BN_CTX_new_ex(dh->libctx); + if (ctx == NULL) + goto err; + pub_key = BN_new(); + if (pub_key == NULL) + goto err; + + /* recalculate the public key = (g ^ priv) mod p */ + if (!dh_generate_public_key(ctx, dh, dh->priv_key, pub_key)) + goto err; + /* check it matches the existing pubic_key */ + ret = BN_cmp(pub_key, dh->pub_key) == 0; +err: + BN_free(pub_key); + BN_CTX_free(ctx); + return ret; +} diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c index 3d3bcb22b2..89264e9fa8 100644 --- a/crypto/dh/dh_gen.c +++ b/crypto/dh/dh_gen.c @@ -27,7 +27,7 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator, * TODO(3.0): keygen should be able to use this method to do a FIPS186-4 style * paramgen. */ -int dh_generate_ffc_parameters(OPENSSL_CTX *libctx, DH *dh, int bits, +int dh_generate_ffc_parameters(DH *dh, int bits, int qbits, int gindex, BN_GENCB *cb) { int ret, res; @@ -38,7 +38,8 @@ int dh_generate_ffc_parameters(OPENSSL_CTX *libctx, DH *dh, int bits, qbits = EVP_MD_size(evpmd) * 8; } dh->params.gindex = gindex; - ret = ffc_params_FIPS186_4_generate(libctx, &dh->params, FFC_PARAM_TYPE_DH, + ret = ffc_params_FIPS186_4_generate(dh->libctx, &dh->params, + FFC_PARAM_TYPE_DH, bits, qbits, NULL, &res, cb); if (ret > 0) dh->dirty_cnt++; diff --git a/crypto/dh/dh_group_params.c b/crypto/dh/dh_group_params.c index 4996e854f5..6c057d1f1f 100644 --- a/crypto/dh/dh_group_params.c +++ b/crypto/dh/dh_group_params.c @@ -15,11 +15,16 @@ #include #include #include "crypto/bn_dh.h" +#include "crypto/dh.h" -static DH *dh_param_init(int nid, const BIGNUM *p, int32_t nbits) +#ifndef FIPS_MODE +static DH *dh_new_by_nid_with_ctx(OPENSSL_CTX *libctx, int nid); + +static DH *dh_param_init(OPENSSL_CTX *libctx, int nid, const BIGNUM *p, + int32_t nbits) { BIGNUM *q = NULL; - DH *dh = DH_new(); + DH *dh = dh_new_with_ctx(libctx); if (dh == NULL) return NULL; @@ -41,7 +46,7 @@ static DH *dh_param_init(int nid, const BIGNUM *p, int32_t nbits) return dh; } -DH *DH_new_by_nid(int nid) +static DH *dh_new_by_nid_with_ctx(OPENSSL_CTX *libctx, int nid) { /* * The last parameter specified in these fields is @@ -50,35 +55,41 @@ DH *DH_new_by_nid(int nid) */ switch (nid) { case NID_ffdhe2048: - return dh_param_init(nid, &_bignum_ffdhe2048_p, 225); + return dh_param_init(libctx, nid, &_bignum_ffdhe2048_p, 225); case NID_ffdhe3072: - return dh_param_init(nid, &_bignum_ffdhe3072_p, 275); + return dh_param_init(libctx, nid, &_bignum_ffdhe3072_p, 275); case NID_ffdhe4096: - return dh_param_init(nid, &_bignum_ffdhe4096_p, 325); + return dh_param_init(libctx, nid, &_bignum_ffdhe4096_p, 325); case NID_ffdhe6144: - return dh_param_init(nid, &_bignum_ffdhe6144_p, 375); + return dh_param_init(libctx, nid, &_bignum_ffdhe6144_p, 375); case NID_ffdhe8192: - return dh_param_init(nid, &_bignum_ffdhe8192_p, 400); + return dh_param_init(libctx, nid, &_bignum_ffdhe8192_p, 400); #ifndef FIPS_MODE case NID_modp_1536: - return dh_param_init(nid, &_bignum_modp_1536_p, 190); + return dh_param_init(libctx, nid, &_bignum_modp_1536_p, 190); #endif case NID_modp_2048: - return dh_param_init(nid, &_bignum_modp_2048_p, 225); + return dh_param_init(libctx, nid, &_bignum_modp_2048_p, 225); case NID_modp_3072: - return dh_param_init(nid, &_bignum_modp_3072_p, 275); + return dh_param_init(libctx, nid, &_bignum_modp_3072_p, 275); case NID_modp_4096: - return dh_param_init(nid, &_bignum_modp_4096_p, 325); + return dh_param_init(libctx, nid, &_bignum_modp_4096_p, 325); case NID_modp_6144: - return dh_param_init(nid, &_bignum_modp_6144_p, 375); + return dh_param_init(libctx, nid, &_bignum_modp_6144_p, 375); case NID_modp_8192: - return dh_param_init(nid, &_bignum_modp_8192_p, 400); + return dh_param_init(libctx, nid, &_bignum_modp_8192_p, 400); default: - DHerr(DH_F_DH_NEW_BY_NID, DH_R_INVALID_PARAMETER_NID); + DHerr(0, DH_R_INVALID_PARAMETER_NID); return NULL; } } +DH *DH_new_by_nid(int nid) +{ + return dh_new_by_nid_with_ctx(NULL, nid); +} +#endif + int DH_get_nid(DH *dh) { int nid = dh->params.nid; diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c index 0bee75c058..14d35466f1 100644 --- a/crypto/dh/dh_key.c +++ b/crypto/dh/dh_key.c @@ -20,8 +20,7 @@ static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, static int dh_init(DH *dh); static int dh_finish(DH *dh); -int dh_compute_key(OPENSSL_CTX *libctx, unsigned char *key, - const BIGNUM *pub_key, DH *dh) +static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) { BN_CTX *ctx = NULL; BN_MONT_CTX *mont = NULL; @@ -41,7 +40,7 @@ int dh_compute_key(OPENSSL_CTX *libctx, unsigned char *key, return 0; } - ctx = BN_CTX_new_ex(libctx); + ctx = BN_CTX_new_ex(dh->libctx); if (ctx == NULL) goto err; BN_CTX_start(ctx); @@ -81,18 +80,21 @@ int dh_compute_key(OPENSSL_CTX *libctx, unsigned char *key, return ret; } -static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) +int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) { - return dh_compute_key(NULL, key, pub_key, dh); +#ifdef FIPS_MODE + return compute_key(key, pub_key, dh); +#else + return dh->meth->compute_key(key, pub_key, dh); +#endif } -int dh_compute_key_padded(OPENSSL_CTX *libctx, unsigned char *key, - const BIGNUM *pub_key, DH *dh) +int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh) { int rv, pad; #ifdef FIPS_MODE - rv = dh_compute_key(libctx, key, pub_key, dh); + rv = compute_key(key, pub_key, dh); #else rv = dh->meth->compute_key(key, pub_key, dh); #endif @@ -106,18 +108,6 @@ int dh_compute_key_padded(OPENSSL_CTX *libctx, unsigned char *key, return rv + pad; } -#ifndef FIPS_MODE -int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) -{ - return dh->meth->compute_key(key, pub_key, dh); -} - -int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh) -{ - return dh_compute_key_padded(NULL, key, pub_key, dh); -} -#endif - static DH_METHOD dh_ossl = { "OpenSSL DH Method", generate_key, @@ -168,14 +158,46 @@ void DH_set_default_method(const DH_METHOD *meth) { default_DH_method = meth; } +#endif /* FIPS_MODE */ int DH_generate_key(DH *dh) { +#ifdef FIPS_MODE + return generate_key(dh); +#else return dh->meth->generate_key(dh); +#endif } -#endif /* FIPS_MODE */ -static int dh_generate_key(OPENSSL_CTX *libctx, DH *dh) +int dh_generate_public_key(BN_CTX *ctx, DH *dh, const BIGNUM *priv_key, + BIGNUM *pub_key) +{ + int ret = 0; + BIGNUM *prk = BN_new(); + BN_MONT_CTX *mont = NULL; + + if (prk == NULL) + return 0; + + if (dh->flags & DH_FLAG_CACHE_MONT_P) { + mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, + dh->lock, dh->params.p, ctx); + if (mont == NULL) + goto err; + } + BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); + + /* pub_key = g^priv_key mod p */ + if (!dh->meth->bn_mod_exp(dh, pub_key, dh->params.g, prk, dh->params.p, + ctx, mont)) + goto err; + ret = 1; +err: + BN_clear_free(prk); + return ret; +} + +static int generate_key(DH *dh) { int ok = 0; int generate_new_key = 0; @@ -183,7 +205,6 @@ static int dh_generate_key(OPENSSL_CTX *libctx, DH *dh) unsigned l; #endif BN_CTX *ctx = NULL; - BN_MONT_CTX *mont = NULL; BIGNUM *pub_key = NULL, *priv_key = NULL; if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) { @@ -196,7 +217,7 @@ static int dh_generate_key(OPENSSL_CTX *libctx, DH *dh) return 0; } - ctx = BN_CTX_new_ex(libctx); + ctx = BN_CTX_new_ex(dh->libctx); if (ctx == NULL) goto err; @@ -205,23 +226,17 @@ static int dh_generate_key(OPENSSL_CTX *libctx, DH *dh) if (priv_key == NULL) goto err; generate_new_key = 1; - } else + } else { priv_key = dh->priv_key; + } if (dh->pub_key == NULL) { pub_key = BN_new(); if (pub_key == NULL) goto err; - } else + } else { pub_key = dh->pub_key; - - if (dh->flags & DH_FLAG_CACHE_MONT_P) { - mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, - dh->lock, dh->params.p, ctx); - if (!mont) - goto err; } - if (generate_new_key) { /* Is it an approved safe prime ?*/ if (DH_get_nid(dh) != NID_undef) { @@ -274,22 +289,8 @@ static int dh_generate_key(OPENSSL_CTX *libctx, DH *dh) } } - { - BIGNUM *prk = BN_new(); - - if (prk == NULL) - goto err; - BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); - - /* pub_key = g^priv_key mod p */ - if (!dh->meth->bn_mod_exp(dh, pub_key, dh->params.g, prk, dh->params.p, - ctx, mont)) { - BN_clear_free(prk); - goto err; - } - /* We MUST free prk before any further use of priv_key */ - BN_clear_free(prk); - } + if (!dh_generate_public_key(ctx, dh, priv_key, pub_key)) + goto err; dh->pub_key = pub_key; dh->priv_key = priv_key; @@ -307,11 +308,6 @@ static int dh_generate_key(OPENSSL_CTX *libctx, DH *dh) return ok; } -static int generate_key(DH *dh) -{ - return dh_generate_key(NULL, dh); -} - int dh_buf2key(DH *dh, const unsigned char *buf, size_t len) { int err_reason = DH_R_BN_ERROR; diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index 0c1cccb5db..e6fc3ef2c5 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -16,6 +16,8 @@ #include "crypto/dh.h" #include "dh_local.h" +static DH *dh_new_intern(ENGINE *engine, OPENSSL_CTX *libctx); + #ifndef FIPS_MODE int DH_set_method(DH *dh, const DH_METHOD *meth) { @@ -36,36 +38,47 @@ int DH_set_method(DH *dh, const DH_METHOD *meth) meth->init(dh); return 1; } -#endif /* !FIPS_MODE */ DH *DH_new(void) { - return DH_new_method(NULL); + return dh_new_intern(NULL, NULL); } DH *DH_new_method(ENGINE *engine) +{ + return dh_new_intern(engine, NULL); +} +#endif /* !FIPS_MODE */ + +DH *dh_new_with_ctx(OPENSSL_CTX *libctx) +{ + return dh_new_intern(NULL, libctx); +} + +static DH *dh_new_intern(ENGINE *engine, OPENSSL_CTX *libctx) { DH *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - DHerr(DH_F_DH_NEW_METHOD, ERR_R_MALLOC_FAILURE); + DHerr(0, ERR_R_MALLOC_FAILURE); return NULL; } ret->references = 1; ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - DHerr(DH_F_DH_NEW_METHOD, ERR_R_MALLOC_FAILURE); + DHerr(0, ERR_R_MALLOC_FAILURE); OPENSSL_free(ret); return NULL; } + ret->libctx = libctx; ret->meth = DH_get_default_method(); #if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE) ret->flags = ret->meth->flags; /* early default init */ if (engine) { if (!ENGINE_init(engine)) { - DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB); + DHerr(0, ERR_R_ENGINE_LIB); goto err; } ret->engine = engine; @@ -74,7 +87,7 @@ DH *DH_new_method(ENGINE *engine) if (ret->engine) { ret->meth = ENGINE_get_DH(ret->engine); if (ret->meth == NULL) { - DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB); + DHerr(0, ERR_R_ENGINE_LIB); goto err; } } @@ -88,7 +101,7 @@ DH *DH_new_method(ENGINE *engine) #endif /* FIPS_MODE */ if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { - DHerr(DH_F_DH_NEW_METHOD, ERR_R_INIT_FAIL); + DHerr(0, ERR_R_INIT_FAIL); goto err; } diff --git a/crypto/dh/dh_local.h b/crypto/dh/dh_local.h index 57d9d3489f..7fefcf76f3 100644 --- a/crypto/dh/dh_local.h +++ b/crypto/dh/dh_local.h @@ -31,6 +31,7 @@ struct dh_st { CRYPTO_EX_DATA ex_data; ENGINE *engine; #endif + OPENSSL_CTX *libctx; const DH_METHOD *meth; CRYPTO_RWLOCK *lock; diff --git a/crypto/dsa/dsa_check.c b/crypto/dsa/dsa_check.c new file mode 100644 index 0000000000..3b86d2dc7a --- /dev/null +++ b/crypto/dsa/dsa_check.c @@ -0,0 +1,85 @@ +/* + * Copyright 1995-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 +#include "internal/cryptlib.h" +#include +#include "dsa_local.h" +#include "crypto/dsa.h" + +int dsa_check_params(const DSA *dsa, int *ret) +{ + int nid; + /* + * (2b) FFC domain params conform to FIPS-186-4 explicit domain param + * validity tests. + */ + return ffc_params_FIPS186_4_validate(&dsa->params, FFC_PARAM_TYPE_DSA, NULL, + FFC_PARAMS_VALIDATE_ALL, ret, NULL); +} + +/* + * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Full public key validation. + */ +int dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret) +{ + return ffc_validate_public_key(&dsa->params, pub_key, ret); +} + +/* + * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Partial public key validation. + * To only be used with ephemeral FFC public keys generated using the approved + * safe-prime groups. + */ +int dsa_check_pub_key_partial(const DSA *dsa, const BIGNUM *pub_key, int *ret) +{ + return ffc_validate_public_key_partial(&dsa->params, pub_key, ret); +} + +int dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret) +{ + *ret = 0; + + return (dsa->params.q != NULL + && ffc_validate_private_key(dsa->params.q, priv_key, ret)); +} + +/* + * FFC pairwise check from SP800-56A R3. + * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency + */ +int dsa_check_pairwise(const DSA *dsa) +{ + int ret = 0; + BN_CTX *ctx = NULL; + BIGNUM *pub_key = NULL; + + if (dsa->params.p == NULL + || dsa->params.g == NULL + || dsa->priv_key == NULL + || dsa->pub_key == NULL) + return 0; + + ctx = BN_CTX_new_ex(dsa->libctx); + if (ctx == NULL) + goto err; + pub_key = BN_new(); + if (pub_key == NULL) + goto err; + + /* recalculate the public key = (g ^ priv) mod p */ + if (!dsa_generate_public_key(ctx, dsa, dsa->priv_key, pub_key)) + goto err; + /* check it matches the existing pubic_key */ + ret = BN_cmp(pub_key, dsa->pub_key) == 0; +err: + BN_free(pub_key); + BN_CTX_free(ctx); + return ret; +} diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index ac5907c4f8..2148a1a487 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -23,7 +23,7 @@ #include "crypto/dsa.h" #include "dsa_local.h" -int dsa_generate_ffc_parameters(OPENSSL_CTX *libctx, DSA *dsa, int type, +int dsa_generate_ffc_parameters(DSA *dsa, int type, int pbits, int qbits, int gindex, BN_GENCB *cb) { @@ -37,12 +37,12 @@ int dsa_generate_ffc_parameters(OPENSSL_CTX *libctx, DSA *dsa, int type, dsa->params.gindex = gindex; #ifndef FIPS_MODE if (type == DSA_PARAMGEN_TYPE_FIPS_186_2) - ret = ffc_params_FIPS186_2_generate(libctx, &dsa->params, + ret = ffc_params_FIPS186_2_generate(dsa->libctx, &dsa->params, FFC_PARAM_TYPE_DSA, pbits, qbits, NULL, &res, cb); else #endif - ret = ffc_params_FIPS186_4_generate(libctx, &dsa->params, + ret = ffc_params_FIPS186_4_generate(dsa->libctx, &dsa->params, FFC_PARAM_TYPE_DSA, pbits, qbits, NULL, &res, cb); if (ret > 0) @@ -50,10 +50,10 @@ int dsa_generate_ffc_parameters(OPENSSL_CTX *libctx, DSA *dsa, int type, return ret; } -int dsa_generate_parameters_ctx(OPENSSL_CTX *libctx, DSA *dsa, int bits, - const unsigned char *seed_in, int seed_len, - int *counter_ret, unsigned long *h_ret, - BN_GENCB *cb) +int DSA_generate_parameters_ex(DSA *dsa, int bits, + const unsigned char *seed_in, int seed_len, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb) { #ifndef FIPS_MODE if (dsa->meth->dsa_paramgen) @@ -67,15 +67,13 @@ int dsa_generate_parameters_ctx(OPENSSL_CTX *libctx, DSA *dsa, int bits, #ifndef FIPS_MODE /* The old code used FIPS 186-2 DSA Parameter generation */ if (bits <= 1024 && seed_len == 20) { - if (!dsa_generate_ffc_parameters(libctx, dsa, - DSA_PARAMGEN_TYPE_FIPS_186_2, + if (!dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_2, bits, 160, -1, cb)) return 0; } else #endif { - if (!dsa_generate_ffc_parameters(libctx, dsa, - DSA_PARAMGEN_TYPE_FIPS_186_4, + if (!dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_4, bits, -1, -1, cb)) return 0; } @@ -86,13 +84,3 @@ int dsa_generate_parameters_ctx(OPENSSL_CTX *libctx, DSA *dsa, int bits, *h_ret = dsa->params.h; return 1; } - -int DSA_generate_parameters_ex(DSA *dsa, int bits, - const unsigned char *seed_in, int seed_len, - int *counter_ret, unsigned long *h_ret, - BN_GENCB *cb) -{ - return dsa_generate_parameters_ctx(NULL, dsa, bits, - seed_in, seed_len, - counter_ret, h_ret, cb); -} diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index 00e7213b97..c93ea15b76 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -20,31 +20,43 @@ #include "crypto/dsa.h" #include "dsa_local.h" -static int dsa_builtin_keygen(OPENSSL_CTX *libctx, DSA *dsa); +static int dsa_builtin_keygen(DSA *dsa); int DSA_generate_key(DSA *dsa) { +#ifndef FIPS_MODE if (dsa->meth->dsa_keygen != NULL) return dsa->meth->dsa_keygen(dsa); - return dsa_builtin_keygen(NULL, dsa); +#endif + return dsa_builtin_keygen(dsa); } -int dsa_generate_key_ctx(OPENSSL_CTX *libctx, DSA *dsa) +int dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa, const BIGNUM *priv_key, + BIGNUM *pub_key) { -#ifndef FIPS_MODE - if (dsa->meth->dsa_keygen != NULL) - return dsa->meth->dsa_keygen(dsa); -#endif - return dsa_builtin_keygen(libctx, dsa); + int ret = 0; + BIGNUM *prk = BN_new(); + + if (prk == NULL) + return 0; + BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); + + /* pub_key = g ^ priv_key mod p */ + if (!BN_mod_exp(pub_key, dsa->params.g, prk, dsa->params.p, ctx)) + goto err; + ret = 1; +err: + BN_clear_free(prk); + return ret; } -static int dsa_builtin_keygen(OPENSSL_CTX *libctx, DSA *dsa) +static int dsa_builtin_keygen(DSA *dsa) { int ok = 0; BN_CTX *ctx = NULL; BIGNUM *pub_key = NULL, *priv_key = NULL; - if ((ctx = BN_CTX_new_ex(libctx)) == NULL) + if ((ctx = BN_CTX_new_ex(dsa->libctx)) == NULL) goto err; if (dsa->priv_key == NULL) { @@ -65,21 +77,8 @@ static int dsa_builtin_keygen(OPENSSL_CTX *libctx, DSA *dsa) pub_key = dsa->pub_key; } - { - BIGNUM *prk = BN_new(); - - if (prk == NULL) - goto err; - BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); - - /* pub_key = g ^ priv_key mod p */ - if (!BN_mod_exp(pub_key, dsa->params.g, prk, dsa->params.p, ctx)) { - BN_free(prk); - goto err; - } - /* We MUST free prk before any further use of priv_key */ - BN_free(prk); - } + if (!dsa_generate_public_key(ctx, dsa, priv_key, pub_key)) + goto err; dsa->priv_key = priv_key; dsa->pub_key = pub_key; diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index 11f09891b2..4b048d48c5 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -23,6 +23,8 @@ #include "crypto/dsa.h" #include "crypto/dh.h" /* required by DSA_dup_DH() */ +static DSA *dsa_new_intern(ENGINE *engine, OPENSSL_CTX *libctx); + #ifndef FIPS_MODE int DSA_set_ex_data(DSA *d, int idx, void *arg) @@ -128,29 +130,30 @@ const DSA_METHOD *DSA_get_method(DSA *d) return d->meth; } -static DSA *dsa_new_method(OPENSSL_CTX *libctx, ENGINE *engine) +static DSA *dsa_new_intern(ENGINE *engine, OPENSSL_CTX *libctx) { DSA *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE); + DSAerr(0, ERR_R_MALLOC_FAILURE); return NULL; } ret->references = 1; ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE); + DSAerr(0, ERR_R_MALLOC_FAILURE); OPENSSL_free(ret); return NULL; } + ret->libctx = libctx; ret->meth = DSA_get_default_method(); #if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE) ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW; /* early default init */ if (engine) { if (!ENGINE_init(engine)) { - DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB); + DSAerr(0, ERR_R_ENGINE_LIB); goto err; } ret->engine = engine; @@ -159,7 +162,7 @@ static DSA *dsa_new_method(OPENSSL_CTX *libctx, ENGINE *engine) if (ret->engine) { ret->meth = ENGINE_get_DSA(ret->engine); if (ret->meth == NULL) { - DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB); + DSAerr(0, ERR_R_ENGINE_LIB); goto err; } } @@ -173,7 +176,7 @@ static DSA *dsa_new_method(OPENSSL_CTX *libctx, ENGINE *engine) #endif if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { - DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_INIT_FAIL); + DSAerr(0, ERR_R_INIT_FAIL); goto err; } @@ -186,13 +189,20 @@ static DSA *dsa_new_method(OPENSSL_CTX *libctx, ENGINE *engine) DSA *DSA_new_method(ENGINE *engine) { - return dsa_new_method(NULL, engine); + return dsa_new_intern(engine, NULL); +} + +DSA *dsa_new_with_ctx(OPENSSL_CTX *libctx) +{ + return dsa_new_intern(NULL, libctx); } +#ifndef FIPS_MODE DSA *DSA_new(void) { - return DSA_new_method(NULL); + return dsa_new_intern(NULL, NULL); } +#endif void DSA_free(DSA *r) { diff --git a/crypto/dsa/dsa_local.h b/crypto/dsa/dsa_local.h index f01b0aae8c..f68ae2d05b 100644 --- a/crypto/dsa/dsa_local.h +++ b/crypto/dsa/dsa_local.h @@ -32,6 +32,7 @@ struct dsa_st { /* functional reference if 'meth' is ENGINE-provided */ ENGINE *engine; CRYPTO_RWLOCK *lock; + OPENSSL_CTX *libctx; /* Provider data */ size_t dirty_cnt; /* If any key material changes, increment this */ @@ -68,5 +69,4 @@ struct dsa_method { int (*dsa_keygen) (DSA *dsa); }; -DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst, - int dlen, DSA *dsa); +DSA_SIG *dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa); diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index 6ff22e8c87..a87493a061 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -67,8 +67,7 @@ const DSA_METHOD *DSA_OpenSSL(void) return &openssl_dsa_meth; } -DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst, - int dlen, DSA *dsa) +DSA_SIG *dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa) { BIGNUM *kinv = NULL; BIGNUM *m, *blind, *blindm, *tmp; @@ -96,7 +95,7 @@ DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst, if (ret->r == NULL || ret->s == NULL) goto err; - ctx = BN_CTX_new_ex(libctx); + ctx = BN_CTX_new_ex(dsa->libctx); if (ctx == NULL) goto err; m = BN_CTX_get(ctx); @@ -186,7 +185,7 @@ DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst, static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { - return dsa_do_sign_int(NULL, dgst, dlen, dsa); + return dsa_do_sign_int(dgst, dlen, dsa); } static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c index 1ee9272ced..9ef8f30f1e 100644 --- a/crypto/dsa/dsa_sign.c +++ b/crypto/dsa/dsa_sign.c @@ -148,16 +148,16 @@ int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) return 1; } -int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst, +int dsa_sign_int(int type, const unsigned char *dgst, int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa) { DSA_SIG *s; /* legacy case uses the method table */ - if (libctx == NULL || dsa->meth != DSA_get_default_method()) + if (dsa->libctx == NULL || dsa->meth != DSA_get_default_method()) s = DSA_do_sign(dgst, dlen, dsa); else - s = dsa_do_sign_int(libctx, dgst, dlen, dsa); + s = dsa_do_sign_int(dgst, dlen, dsa); if (s == NULL) { *siglen = 0; return 0; @@ -170,7 +170,7 @@ int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst, int DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa) { - return dsa_sign_int(NULL, type, dgst, dlen, sig, siglen, dsa); + return dsa_sign_int(type, dgst, dlen, sig, siglen, dsa); } /* data has already been hashed (probably with SHA or SHA-1). */ diff --git a/crypto/ffc/build.info b/crypto/ffc/build.info index d3314c30d1..c8bc7e9018 100644 --- a/crypto/ffc/build.info +++ b/crypto/ffc/build.info @@ -1,6 +1,7 @@ LIBS=../../libcrypto -$COMMON=ffc_params.c ffc_params_generate.c ffc_key_generate.c +$COMMON=ffc_params.c ffc_params_generate.c ffc_key_generate.c\ + ffc_params_validate.c ffc_key_validate.c SOURCE[../../libcrypto]=$COMMON SOURCE[../../providers/libfips.a]=$COMMON diff --git a/crypto/ffc/ffc_key_generate.c b/crypto/ffc/ffc_key_generate.c index 186245cc87..b8c85480c1 100644 --- a/crypto/ffc/ffc_key_generate.c +++ b/crypto/ffc/ffc_key_generate.c @@ -23,6 +23,19 @@ int ffc_generate_private_key(BN_CTX *ctx, const FFC_PARAMS *params, int N, int s, BIGNUM *priv) { #ifdef FIPS_MODE + return ffc_generate_private_key_fips(ctx, params, N, s, priv); +#else + do { + if (!BN_priv_rand_range_ex(priv, params->q, ctx)) + return 0; + } while (BN_is_zero(priv) || BN_is_one(priv)); + return 1; +#endif /* FIPS_MODE */ +} + +int ffc_generate_private_key_fips(BN_CTX *ctx, const FFC_PARAMS *params, + int N, int s, BIGNUM *priv) +{ int ret = 0; BIGNUM *m, *two_powN = NULL; @@ -51,11 +64,4 @@ int ffc_generate_private_key(BN_CTX *ctx, const FFC_PARAMS *params, err: BN_free(two_powN); return ret; -#else - do { - if (!BN_priv_rand_range_ex(priv, params->q, ctx)) - return 0; - } while (BN_is_zero(priv) || BN_is_one(priv)); - return 1; -#endif /* FIPS_MODE */ } diff --git a/crypto/ffc/ffc_key_validate.c b/crypto/ffc/ffc_key_validate.c new file mode 100644 index 0000000000..a35f52e1b9 --- /dev/null +++ b/crypto/ffc/ffc_key_validate.c @@ -0,0 +1,120 @@ +/* + * 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 + * https://www.openssl.org/source/license.html + */ + +#include "internal/ffc.h" + +/* + * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Partial public key validation. + * To only be used with ephemeral FFC public keys generated using the approved + * safe-prime groups. (Checks that the public key is in the range [2, p - 1] + * + * ret contains 0 on success, or error flags (see FFC_ERROR_PUBKEY_TOO_SMALL) + */ +int ffc_validate_public_key_partial(const FFC_PARAMS *params, + const BIGNUM *pub_key, int *ret) +{ + int ok = 0; + BIGNUM *tmp = NULL; + BN_CTX *ctx = NULL; + + *ret = 0; + ctx = BN_CTX_new_ex(NULL); + if (ctx == NULL) + goto err; + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + /* Step(1): Verify pub_key >= 2 */ + if (tmp == NULL + || !BN_set_word(tmp, 1)) + goto err; + if (BN_cmp(pub_key, tmp) <= 0) { + *ret |= FFC_ERROR_PUBKEY_TOO_SMALL; + goto err; + } + /* Step(1): Verify pub_key <= p-2 */ + if (BN_copy(tmp, params->p) == NULL + || !BN_sub_word(tmp, 1)) + goto err; + if (BN_cmp(pub_key, tmp) >= 0) { + *ret |= FFC_ERROR_PUBKEY_TOO_LARGE; + goto err; + } + ok = 1; + err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; +} + +/* + * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Full public key validation. + */ +int ffc_validate_public_key(const FFC_PARAMS *params, const BIGNUM *pub_key, + int *ret) +{ + int ok = 0; + BIGNUM *tmp = NULL; + BN_CTX *ctx = NULL; + + if (!ffc_validate_public_key_partial(params, pub_key, ret)) + return 0; + + if (params->q != NULL) { + ctx = BN_CTX_new_ex(NULL); + if (ctx == NULL) + goto err; + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + + /* Check pub_key^q == 1 mod p */ + if (tmp == NULL + || !BN_mod_exp(tmp, pub_key, params->q, params->p, ctx)) + goto err; + if (!BN_is_one(tmp)) { + *ret |= FFC_ERROR_PUBKEY_INVALID; + goto err; + } + } + + ok = 1; + err: + if (ctx != NULL) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; +} + +/* + * See SP800-56Ar3 Section 5.6.2.1.2: Owner assurance of Private key validity. + * Verifies priv_key is in the range [1..upper-1]. The passed in value of upper + * is normally params->q but can be 2^N for approved safe prime groups. + * Note: This assumes that the domain parameters are valid. + */ +int ffc_validate_private_key(const BIGNUM *upper, const BIGNUM *priv, int *ret) +{ + int ok = 0; + + *ret = 0; + + if (BN_cmp(priv, BN_value_one()) < 0) { + *ret |= FFC_ERROR_PRIVKEY_TOO_SMALL; + goto err; + } + if (BN_cmp(priv, upper) >= 0) { + *ret |= FFC_ERROR_PRIVKEY_TOO_LARGE; + goto err; + } + ok = 1; +err: + return ok; +} diff --git a/crypto/ffc/ffc_params_generate.c b/crypto/ffc/ffc_params_generate.c index 54d5c58e09..cb51bf0e76 100644 --- a/crypto/ffc/ffc_params_generate.c +++ b/crypto/ffc/ffc_params_generate.c @@ -474,10 +474,10 @@ static EVP_MD *fetch_default_md(OPENSSL_CTX *libctx, size_t N) * - FFC_PARAMS_RET_STATUS_UNVERIFIABLE_G if the validation of G succeeded, * but G is unverifiable. */ -int ffc_param_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, - int type, size_t L, size_t N, - const EVP_MD *evpmd, int validate_flags, - int *res, BN_GENCB *cb) +int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, + int type, size_t L, size_t N, + const EVP_MD *evpmd, int validate_flags, + int *res, BN_GENCB *cb) { int ok = FFC_PARAMS_RET_STATUS_FAILED; unsigned char *seed = NULL, *seed_tmp = NULL; @@ -750,10 +750,10 @@ err: return ok; } -int ffc_param_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, - int type, size_t L, size_t N, - const EVP_MD *evpmd, int validate_flags, - int *res, BN_GENCB *cb) +int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, + int type, size_t L, size_t N, + const EVP_MD *evpmd, int validate_flags, + int *res, BN_GENCB *cb) { int ok = FFC_PARAMS_RET_STATUS_FAILED; unsigned char seed[SHA256_DIGEST_LENGTH]; @@ -977,8 +977,8 @@ int ffc_params_FIPS186_4_generate(OPENSSL_CTX *libctx, FFC_PARAMS *params, int type, size_t L, size_t N, const EVP_MD *evpmd, int *res, BN_GENCB *cb) { - return ffc_param_FIPS186_4_gen_verify(libctx, params, type, L, N, evpmd, 0, - res, cb); + return ffc_params_FIPS186_4_gen_verify(libctx, params, type, L, N, evpmd, 0, + res, cb); } /* This should no longer be used in FIPS mode */ @@ -986,14 +986,6 @@ int ffc_params_FIPS186_2_generate(OPENSSL_CTX *libctx, FFC_PARAMS *params, int type, size_t L, size_t N, const EVP_MD *evpmd, int *res, BN_GENCB *cb) { - return ffc_param_FIPS186_2_gen_verify(libctx, params, type, L, N, evpmd, - 0, res, cb); -} - -/* TODO(3.0) - Add this in another PR - just add a stub for now */ -int ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, - const BIGNUM *p, const BIGNUM *q, - const BIGNUM *g, BIGNUM *tmp, int *ret) -{ - return 1; + return ffc_params_FIPS186_2_gen_verify(libctx, params, type, L, N, evpmd, + 0, res, cb); } diff --git a/crypto/ffc/ffc_params_validate.c b/crypto/ffc/ffc_params_validate.c new file mode 100644 index 0000000000..4d0a4d837f --- /dev/null +++ b/crypto/ffc/ffc_params_validate.c @@ -0,0 +1,80 @@ +/* + * 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 + * https://www.openssl.org/source/license.html + */ + +/* + * Finite Field cryptography (FFC) is used for DSA and DH. + * This file contains methods for validation of FFC parameters. + * It calls the same functions as the generation as the code is very similar. + */ + +#include "internal/ffc.h" + +/* FIPS186-4 A.2.2 Unverifiable partial validation of Generator g */ +int ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, + const BIGNUM *p, const BIGNUM *q, + const BIGNUM *g, BIGNUM *tmp, int *ret) +{ + /* + * A.2.2 Step (1) AND + * A.2.4 Step (2) + * Verify that 2 <= g <= (p - 1) + */ + if (BN_cmp(g, BN_value_one()) <= 0 || BN_cmp(g, p) >= 0) { + *ret |= FFC_ERROR_NOT_SUITABLE_GENERATOR; + return 0; + } + + /* + * A.2.2 Step (2) AND + * A.2.4 Step (3) + * Check g^q mod p = 1 + */ + if (!BN_mod_exp_mont(tmp, g, q, p, ctx, mont)) + return 0; + if (BN_cmp(tmp, BN_value_one()) != 0) { + *ret |= FFC_ERROR_NOT_SUITABLE_GENERATOR; + return 0; + } + return 1; +} + +int ffc_params_FIPS186_4_validate(const FFC_PARAMS *params, int type, + const EVP_MD *evpmd, int validate_flags, + int *res, BN_GENCB *cb) +{ + size_t L, N; + + if (params == NULL || params->p == NULL || params->q == NULL) + return FFC_PARAMS_RET_STATUS_FAILED; + + /* A.1.1.3 Step (1..2) : L = len(p), N = len(q) */ + L = BN_num_bits(params->p); + N = BN_num_bits(params->q); + return ffc_params_FIPS186_4_gen_verify(NULL, (FFC_PARAMS *)params, type, L, N, + evpmd, validate_flags, res, cb); +} + +/* This may be used in FIPS mode to validate deprecated FIPS-186-2 Params */ +int ffc_params_FIPS186_2_validate(const FFC_PARAMS *params, int type, + const EVP_MD *evpmd, int validate_flags, + int *res, BN_GENCB *cb) +{ + size_t L, N; + + if (params->p == NULL || params->q == NULL) { + *res = FFC_CHECK_INVALID_PQ; + return FFC_PARAMS_RET_STATUS_FAILED; + } + + /* A.1.1.3 Step (1..2) : L = len(p), N = len(q) */ + L = BN_num_bits(params->p); + N = BN_num_bits(params->q); + return ffc_params_FIPS186_2_gen_verify(NULL, (FFC_PARAMS *)params, type, L, N, + evpmd, validate_flags, res, cb); +} diff --git a/include/crypto/dh.h b/include/crypto/dh.h index 2b48b5d905..3af3c5222e 100644 --- a/include/crypto/dh.h +++ b/include/crypto/dh.h @@ -10,12 +10,16 @@ #include #include "internal/ffc.h" -int dh_generate_ffc_parameters(OPENSSL_CTX *libctx, DH *dh, int bits, +DH *dh_new_with_ctx(OPENSSL_CTX *libctx); + +int dh_generate_ffc_parameters(DH *dh, int bits, int qbits, int gindex, BN_GENCB *cb); +int dh_generate_public_key(BN_CTX *ctx, DH *dh, const BIGNUM *priv_key, + BIGNUM *pub_key); -int dh_compute_key(OPENSSL_CTX *ctx, unsigned char *key, const BIGNUM *pub_key, - DH *dh); -int dh_compute_key_padded(OPENSSL_CTX *ctx, unsigned char *key, - const BIGNUM *pub_key, DH *dh); FFC_PARAMS *dh_get0_params(DH *dh); int dh_get0_nid(const DH *dh); + +int dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret); +int dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret); +int dh_check_pairwise(DH *dh); diff --git a/include/crypto/dsa.h b/include/crypto/dsa.h index 1865fe0f77..1da23a8a7b 100644 --- a/include/crypto/dsa.h +++ b/include/crypto/dsa.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * 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 @@ -12,16 +12,19 @@ #define DSA_PARAMGEN_TYPE_FIPS_186_2 1 /* Use legacy FIPS186-2 standard */ #define DSA_PARAMGEN_TYPE_FIPS_186_4 2 /* Use FIPS186-4 standard */ -int dsa_generate_parameters_ctx(OPENSSL_CTX *libctx, DSA *dsa, int bits, - const unsigned char *seed_in, int seed_len, - int *counter_ret, unsigned long *h_ret, - BN_GENCB *cb); +DSA *dsa_new_with_ctx(OPENSSL_CTX *libctx); -int dsa_generate_ffc_parameters(OPENSSL_CTX *libctx, DSA *dsa, int type, +int dsa_generate_ffc_parameters(DSA *dsa, int type, int pbits, int qbits, int gindex, BN_GENCB *cb); -int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst, +int dsa_sign_int(int type, const unsigned char *dgst, int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa); -int dsa_generate_key_ctx(OPENSSL_CTX *libctx, DSA *dsa); const unsigned char *dsa_algorithmidentifier_encoding(int md_nid, size_t *len); +int dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa, const BIGNUM *priv_key, + BIGNUM *pub_key); +int dsa_check_params(const DSA *dsa, int *ret); +int dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret); +int dsa_check_pub_key_partial(const DSA *dsa, const BIGNUM *pub_key, int *ret); +int dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret); +int dsa_check_pairwise(const DSA *dsa); diff --git a/include/internal/ffc.h b/include/internal/ffc.h index 67282fd807..006be73d8c 100644 --- a/include/internal/ffc.h +++ b/include/internal/ffc.h @@ -56,6 +56,14 @@ # define FFC_CHECK_G_MISMATCH 0x08000 # define FFC_CHECK_COUNTER_MISMATCH 0x10000 +/* Validation Return codes */ +# define FFC_ERROR_PUBKEY_TOO_SMALL 0x01 +# define FFC_ERROR_PUBKEY_TOO_LARGE 0x02 +# define FFC_ERROR_PUBKEY_INVALID 0x04 +# define FFC_ERROR_NOT_SUITABLE_GENERATOR 0x08 +# define FFC_ERROR_PRIVKEY_TOO_SMALL 0x10 +# define FFC_ERROR_PRIVKEY_TOO_LARGE 0x20 + /* * Finite field cryptography (FFC) domain parameters are used by DH and DSA. * Refer to FIPS186_4 Appendix A & B. @@ -113,20 +121,37 @@ int ffc_params_FIPS186_2_generate(OPENSSL_CTX *libctx, FFC_PARAMS *params, int type, size_t L, size_t N, const EVP_MD *evpmd, int *res, BN_GENCB *cb); -int ffc_param_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, - int type, size_t L, size_t N, - const EVP_MD *evpmd, int validate_flags, - int *res, BN_GENCB *cb); -int ffc_param_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, - int type, size_t L, size_t N, - const EVP_MD *evpmd, int validate_flags, - int *res, BN_GENCB *cb); +int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, + int type, size_t L, size_t N, + const EVP_MD *evpmd, int validate_flags, + int *res, BN_GENCB *cb); +int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params, + int type, size_t L, size_t N, + const EVP_MD *evpmd, int validate_flags, + int *res, BN_GENCB *cb); + +int ffc_params_FIPS186_4_validate(const FFC_PARAMS *params, int type, + const EVP_MD *evpmd, int validate_flags, + int *res, BN_GENCB *cb); +int ffc_params_FIPS186_2_validate(const FFC_PARAMS *params, int type, + const EVP_MD *evpmd, int validate_flags, + int *res, BN_GENCB *cb); + int ffc_generate_private_key(BN_CTX *ctx, const FFC_PARAMS *params, int N, int s, BIGNUM *priv); +int ffc_generate_private_key_fips(BN_CTX *ctx, const FFC_PARAMS *params, + int N, int s, BIGNUM *priv); int ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, BIGNUM *tmp, int *ret); +int ffc_validate_public_key(const FFC_PARAMS *params, const BIGNUM *pub_key, + int *ret); +int ffc_validate_public_key_partial(const FFC_PARAMS *params, + const BIGNUM *pub_key, int *ret); +int ffc_validate_private_key(const BIGNUM *upper, const BIGNUM *priv_key, + int *ret); + #endif /* OSSL_INTERNAL_FFC_H */ diff --git a/providers/implementations/exchange/dh_exch.c b/providers/implementations/exchange/dh_exch.c index 94c232965f..418896e46d 100644 --- a/providers/implementations/exchange/dh_exch.c +++ b/providers/implementations/exchange/dh_exch.c @@ -92,9 +92,9 @@ static int dh_derive(void *vpdhctx, unsigned char *secret, size_t *secretlen, DH_get0_key(pdhctx->dhpeer, &pub_key, NULL); if (pdhctx->pad) - ret = dh_compute_key_padded(pdhctx->libctx, secret, pub_key, pdhctx->dh); + ret = DH_compute_key_padded(secret, pub_key, pdhctx->dh); else - ret = dh_compute_key(pdhctx->libctx, secret, pub_key, pdhctx->dh); + ret = DH_compute_key(secret, pub_key, pdhctx->dh); if (ret <= 0) return 0; diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index 9a1734bd57..1694421c3c 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -10,12 +10,13 @@ #include #include #include -#include #include #include "internal/param_build.h" #include "crypto/dh.h" #include "prov/implementations.h" #include "prov/providercommon.h" +#include "prov/provider_ctx.h" +#include "crypto/dh.h" static OSSL_OP_keymgmt_new_fn dh_newdata; static OSSL_OP_keymgmt_free_fn dh_freedata; @@ -137,7 +138,7 @@ static int key_to_params(DH *dh, OSSL_PARAM_BLD *tmpl) static void *dh_newdata(void *provctx) { - return DH_new(); + return dh_new_with_ctx(PROV_LIBRARY_CONTEXT_OF(provctx)); } static void dh_freedata(void *keydata) diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c index 78c479e671..1855474c85 100644 --- a/providers/implementations/keymgmt/dsa_kmgmt.c +++ b/providers/implementations/keymgmt/dsa_kmgmt.c @@ -150,7 +150,7 @@ static int key_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl) static void *dsa_newdata(void *provctx) { - return DSA_new(); + return dsa_new_with_ctx(PROV_LIBRARY_CONTEXT_OF(provctx)); } static void dsa_freedata(void *keydata) diff --git a/providers/implementations/signature/dsa.c b/providers/implementations/signature/dsa.c index 6c5550bf42..99183e8f86 100644 --- a/providers/implementations/signature/dsa.c +++ b/providers/implementations/signature/dsa.c @@ -200,8 +200,7 @@ static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen, if (mdsize != 0 && tbslen != mdsize) return 0; - ret = dsa_sign_int(pdsactx->libctx, 0, tbs, tbslen, sig, &sltmp, - pdsactx->dsa); + ret = dsa_sign_int(0, tbs, tbslen, sig, &sltmp, pdsactx->dsa); if (ret <= 0) return 0; diff --git a/test/build.info b/test/build.info index dfeabdbc5d..c35bed086c 100644 --- a/test/build.info +++ b/test/build.info @@ -493,9 +493,10 @@ IF[{- !$disabled{tests} -}] tls13encryptiontest wpackettest ctype_internal_test \ rdrand_sanitytest property_test ideatest \ rsa_sp800_56b_test bn_internal_test ecdsatest \ - rc2test rc4test rc5test hmactest \ + rc2test rc4test rc5test hmactest ffc_internal_test \ asn1_dsa_internal_test dsatest dsa_no_digest_size_test + IF[{- !$disabled{poly1305} -}] PROGRAMS{noinst}=poly1305_internal_test ENDIF @@ -636,6 +637,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[keymgmt_internal_test]=.. ../include ../apps/include DEPEND[keymgmt_internal_test]=../libcrypto.a libtestutil.a + SOURCE[ffc_internal_test]=ffc_internal_test.c + INCLUDE[ffc_internal_test]=.. ../include ../apps/include ../crypto/include + DEPEND[ffc_internal_test]=../libcrypto.a libtestutil.a + IF[{- !$disabled{mdc2} -}] PROGRAMS{noinst}=mdc2_internal_test ENDIF diff --git a/test/ffc_internal_test.c b/test/ffc_internal_test.c new file mode 100644 index 0000000000..4aa23944af --- /dev/null +++ b/test/ffc_internal_test.c @@ -0,0 +1,650 @@ +/* + * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2019-2020, Oracle and/or its affiliates. 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 +#include +#include + +#include "internal/nelem.h" +#include +#include +#include +#include +#include +#include "testutil.h" + +#include "internal/ffc.h" + +#ifndef OPENSSL_NO_DSA +static const unsigned char dsa_2048_224_sha224_p[] = { + 0x93, 0x57, 0x93, 0x62, 0x1b, 0x9a, 0x10, 0x9b, 0xc1, 0x56, 0x0f, 0x24, + 0x71, 0x76, 0x4e, 0xd3, 0xed, 0x78, 0x78, 0x7a, 0xbf, 0x89, 0x71, 0x67, + 0x8e, 0x03, 0xd8, 0x5b, 0xcd, 0x22, 0x8f, 0x70, 0x74, 0xff, 0x22, 0x05, + 0x07, 0x0c, 0x4c, 0x60, 0xed, 0x41, 0xe1, 0x9e, 0x9c, 0xaa, 0x3e, 0x19, + 0x5c, 0x3d, 0x80, 0x58, 0xb2, 0x7f, 0x5f, 0x89, 0xec, 0xb5, 0x19, 0xdb, + 0x06, 0x11, 0xe9, 0x78, 0x5c, 0xf9, 0xa0, 0x9e, 0x70, 0x62, 0x14, 0x7b, + 0xda, 0x92, 0xbf, 0xb2, 0x6b, 0x01, 0x6f, 0xb8, 0x68, 0x9c, 0x89, 0x36, + 0x89, 0x72, 0x79, 0x49, 0x93, 0x3d, 0x14, 0xb2, 0x2d, 0xbb, 0xf0, 0xdf, + 0x94, 0x45, 0x0b, 0x5f, 0xf1, 0x75, 0x37, 0xeb, 0x49, 0xb9, 0x2d, 0xce, + 0xb7, 0xf4, 0x95, 0x77, 0xc2, 0xe9, 0x39, 0x1c, 0x4e, 0x0c, 0x40, 0x62, + 0x33, 0x0a, 0xe6, 0x29, 0x6f, 0xba, 0xef, 0x02, 0xdd, 0x0d, 0xe4, 0x04, + 0x01, 0x70, 0x40, 0xb9, 0xc9, 0x7e, 0x2f, 0x10, 0x37, 0xe9, 0xde, 0xb0, + 0xf6, 0xeb, 0x71, 0x7f, 0x9c, 0x35, 0x16, 0xf3, 0x0d, 0xc4, 0xe8, 0x02, + 0x37, 0x6c, 0xdd, 0xb3, 0x8d, 0x2d, 0x1e, 0x28, 0x13, 0x22, 0x89, 0x40, + 0xe5, 0xfa, 0x16, 0x67, 0xd6, 0xda, 0x12, 0xa2, 0x38, 0x83, 0x25, 0xcc, + 0x26, 0xc1, 0x27, 0x74, 0xfe, 0xf6, 0x7a, 0xb6, 0xa1, 0xe4, 0xe8, 0xdf, + 0x5d, 0xd2, 0x9c, 0x2f, 0xec, 0xea, 0x08, 0xca, 0x48, 0xdb, 0x18, 0x4b, + 0x12, 0xee, 0x16, 0x9b, 0xa6, 0x00, 0xa0, 0x18, 0x98, 0x7d, 0xce, 0x6c, + 0x6d, 0xf8, 0xfc, 0x95, 0x51, 0x1b, 0x0a, 0x40, 0xb6, 0xfc, 0xe5, 0xe2, + 0xb0, 0x26, 0x53, 0x4c, 0xd7, 0xfe, 0xaa, 0x6d, 0xbc, 0xdd, 0xc0, 0x61, + 0x65, 0xe4, 0x89, 0x44, 0x18, 0x6f, 0xd5, 0x39, 0xcf, 0x75, 0x6d, 0x29, + 0xcc, 0xf8, 0x40, 0xab +}; +static const unsigned char dsa_2048_224_sha224_q[] = { + 0xf2, 0x5e, 0x4e, 0x9a, 0x15, 0xa8, 0x13, 0xdf, 0xa3, 0x17, 0x90, 0xc6, + 0xd6, 0x5e, 0xb1, 0xfb, 0x31, 0xf8, 0xb5, 0xb1, 0x4b, 0xa7, 0x6d, 0xde, + 0x57, 0x76, 0x6f, 0x11 +}; +static const unsigned char dsa_2048_224_sha224_seed[] = { + 0xd2, 0xb1, 0x36, 0xd8, 0x5b, 0x8e, 0xa4, 0xb2, 0x6a, 0xab, 0x4e, 0x85, + 0x8b, 0x49, 0xf9, 0xdd, 0xe6, 0xa1, 0xcd, 0xad, 0x49, 0x52, 0xe9, 0xb3, + 0x36, 0x17, 0x06, 0xcf +}; +static const unsigned char dsa_2048_224_sha224_bad_seed[] = { + 0xd2, 0xb1, 0x36, 0xd8, 0x5b, 0x8e, 0xa4, 0xb2, 0x6a, 0xab, 0x4e, 0x85, + 0x8b, 0x49, 0xf9, 0xdd, 0xe6, 0xa1, 0xcd, 0xad, 0x49, 0x52, 0xe9, 0xb3, + 0x36, 0x17, 0x06, 0xd0 +}; +static int dsa_2048_224_sha224_counter = 2878; + +static const unsigned char dsa_3072_256_sha512_p[] = { + 0x9a, 0x82, 0x8b, 0x8d, 0xea, 0xd0, 0x56, 0x23, 0x88, 0x2d, 0x5d, 0x41, + 0x42, 0x4c, 0x13, 0x5a, 0x15, 0x81, 0x59, 0x02, 0xc5, 0x00, 0x82, 0x28, + 0x01, 0xee, 0x8f, 0x99, 0xfd, 0x6a, 0x95, 0xf2, 0x0f, 0xae, 0x34, 0x77, + 0x29, 0xcc, 0xc7, 0x50, 0x0e, 0x03, 0xef, 0xb0, 0x4d, 0xe5, 0x10, 0x00, + 0xa8, 0x7b, 0xce, 0x8c, 0xc6, 0xb2, 0x01, 0x74, 0x23, 0x1b, 0x7f, 0xe8, + 0xf9, 0x71, 0x28, 0x39, 0xcf, 0x18, 0x04, 0xb2, 0x95, 0x61, 0x2d, 0x11, + 0x71, 0x6b, 0xdd, 0x0d, 0x0b, 0xf0, 0xe6, 0x97, 0x52, 0x29, 0x9d, 0x45, + 0xb1, 0x23, 0xda, 0xb0, 0xd5, 0xcb, 0x51, 0x71, 0x8e, 0x40, 0x9c, 0x97, + 0x13, 0xea, 0x1f, 0x4b, 0x32, 0x5d, 0x27, 0x74, 0x81, 0x8d, 0x47, 0x8a, + 0x08, 0xce, 0xf4, 0xd1, 0x28, 0xa2, 0x0f, 0x9b, 0x2e, 0xc9, 0xa3, 0x0e, + 0x5d, 0xde, 0x47, 0x19, 0x6d, 0x5f, 0x98, 0xe0, 0x8e, 0x7f, 0x60, 0x8f, + 0x25, 0xa7, 0xa4, 0xeb, 0xb9, 0xf3, 0x24, 0xa4, 0x9e, 0xc1, 0xbd, 0x14, + 0x27, 0x7c, 0x27, 0xc8, 0x4f, 0x5f, 0xed, 0xfd, 0x86, 0xc8, 0xf1, 0xd7, + 0x82, 0xe2, 0xeb, 0xe5, 0xd2, 0xbe, 0xb0, 0x65, 0x28, 0xab, 0x99, 0x9e, + 0xcd, 0xd5, 0x22, 0xf8, 0x1b, 0x3b, 0x01, 0xe9, 0x20, 0x3d, 0xe4, 0x98, + 0x22, 0xfe, 0xfc, 0x09, 0x7e, 0x95, 0x20, 0xda, 0xb6, 0x12, 0x2c, 0x94, + 0x5c, 0xea, 0x74, 0x71, 0xbd, 0x19, 0xac, 0x78, 0x43, 0x02, 0x51, 0xb8, + 0x5f, 0x06, 0x1d, 0xea, 0xc8, 0xa4, 0x3b, 0xc9, 0x78, 0xa3, 0x2b, 0x09, + 0xdc, 0x76, 0x74, 0xc4, 0x23, 0x14, 0x48, 0x2e, 0x84, 0x2b, 0xa3, 0x82, + 0xc1, 0xba, 0x0b, 0x39, 0x2a, 0x9f, 0x24, 0x7b, 0xd6, 0xc2, 0xea, 0x5a, + 0xb6, 0xbd, 0x15, 0x82, 0x21, 0x85, 0xe0, 0x6b, 0x12, 0x4f, 0x8d, 0x64, + 0x75, 0xeb, 0x7e, 0xa1, 0xdb, 0xe0, 0x9d, 0x25, 0xae, 0x3b, 0xe9, 0x9b, + 0x21, 0x7f, 0x9a, 0x3d, 0x66, 0xd0, 0x52, 0x1d, 0x39, 0x8b, 0xeb, 0xfc, + 0xec, 0xbe, 0x72, 0x20, 0x5a, 0xdf, 0x1b, 0x00, 0xf1, 0x0e, 0xed, 0xc6, + 0x78, 0x6f, 0xc9, 0xab, 0xe4, 0xd6, 0x81, 0x8b, 0xcc, 0xf6, 0xd4, 0x6a, + 0x31, 0x62, 0x08, 0xd9, 0x38, 0x21, 0x8f, 0xda, 0x9e, 0xb1, 0x2b, 0x9c, + 0xc0, 0xbe, 0xf7, 0x9a, 0x43, 0x2d, 0x07, 0x59, 0x46, 0x0e, 0xd5, 0x23, + 0x4e, 0xaa, 0x4a, 0x04, 0xc2, 0xde, 0x33, 0xa6, 0x34, 0xba, 0xac, 0x4f, + 0x78, 0xd8, 0xca, 0x76, 0xce, 0x5e, 0xd4, 0xf6, 0x85, 0x4c, 0x6a, 0x60, + 0x08, 0x5d, 0x0e, 0x34, 0x8b, 0xf2, 0xb6, 0xe3, 0xb7, 0x51, 0xca, 0x43, + 0xaa, 0x68, 0x7b, 0x0a, 0x6e, 0xea, 0xce, 0x1e, 0x2c, 0x34, 0x8e, 0x0f, + 0xe2, 0xcc, 0x38, 0xf2, 0x9a, 0x98, 0xef, 0xe6, 0x7f, 0xf6, 0x62, 0xbb +}; +static const unsigned char dsa_3072_256_sha512_q[] = { + 0xc1, 0xdb, 0xc1, 0x21, 0x50, 0x49, 0x63, 0xa3, 0x77, 0x6d, 0x4c, 0x92, + 0xed, 0x58, 0x9e, 0x98, 0xea, 0xac, 0x7a, 0x90, 0x13, 0x24, 0xf7, 0xcd, + 0xd7, 0xe6, 0xd4, 0x8f, 0xf0, 0x45, 0x4b, 0xf7 +}; +static const unsigned char dsa_3072_256_sha512_seed[] = { + 0x35, 0x24, 0xb5, 0x59, 0xd5, 0x27, 0x58, 0x10, 0xf6, 0xa2, 0x7c, 0x9a, + 0x0d, 0xc2, 0x70, 0x8a, 0xb0, 0x41, 0x4a, 0x84, 0x0b, 0xfe, 0x66, 0xf5, + 0x3a, 0xbf, 0x4a, 0xa9, 0xcb, 0xfc, 0xa6, 0x22 +}; +static int dsa_3072_256_sha512_counter = 1604; + +static const unsigned char dsa_2048_224_sha256_p[] = { + 0xe9, 0x13, 0xbc, 0xf2, 0x14, 0x5d, 0xf9, 0x79, 0xd6, 0x6d, 0xf5, 0xc5, + 0xbe, 0x7b, 0x6f, 0x90, 0x63, 0xd0, 0xfd, 0xee, 0x4f, 0xc4, 0x65, 0x83, + 0xbf, 0xec, 0xc3, 0x2c, 0x5d, 0x30, 0xc8, 0xa4, 0x3b, 0x2f, 0x3b, 0x29, + 0x43, 0x69, 0xfb, 0x6e, 0xa9, 0xa4, 0x07, 0x6c, 0xcd, 0xb0, 0xd2, 0xd9, + 0xd3, 0xe6, 0xf4, 0x87, 0x16, 0xb7, 0xe5, 0x06, 0xb9, 0xba, 0xd6, 0x87, + 0xbc, 0x01, 0x9e, 0xba, 0xc2, 0xcf, 0x39, 0xb6, 0xec, 0xdc, 0x75, 0x07, + 0xc1, 0x39, 0x2d, 0x6a, 0x95, 0x31, 0x97, 0xda, 0x54, 0x20, 0x29, 0xe0, + 0x1b, 0xf9, 0x74, 0x65, 0xaa, 0xc1, 0x47, 0xd3, 0x9e, 0xb4, 0x3c, 0x1d, + 0xe0, 0xdc, 0x2d, 0x21, 0xab, 0x12, 0x3b, 0xa5, 0x51, 0x1e, 0xc6, 0xbc, + 0x6b, 0x4c, 0x22, 0xd1, 0x7c, 0xc6, 0xce, 0xcb, 0x8c, 0x1d, 0x1f, 0xce, + 0x1c, 0xe2, 0x75, 0x49, 0x6d, 0x2c, 0xee, 0x7f, 0x5f, 0xb8, 0x74, 0x42, + 0x5c, 0x96, 0x77, 0x13, 0xff, 0x80, 0xf3, 0x05, 0xc7, 0xfe, 0x08, 0x3b, + 0x25, 0x36, 0x46, 0xa2, 0xc4, 0x26, 0xb4, 0xb0, 0x3b, 0xd5, 0xb2, 0x4c, + 0x13, 0x29, 0x0e, 0x47, 0x31, 0x66, 0x7d, 0x78, 0x57, 0xe6, 0xc2, 0xb5, + 0x9f, 0x46, 0x17, 0xbc, 0xa9, 0x9a, 0x49, 0x1c, 0x0f, 0x45, 0xe0, 0x88, + 0x97, 0xa1, 0x30, 0x7c, 0x42, 0xb7, 0x2c, 0x0a, 0xce, 0xb3, 0xa5, 0x7a, + 0x61, 0x8e, 0xab, 0x44, 0xc1, 0xdc, 0x70, 0xe5, 0xda, 0x78, 0x2a, 0xb4, + 0xe6, 0x3c, 0xa0, 0x58, 0xda, 0x62, 0x0a, 0xb2, 0xa9, 0x3d, 0xaa, 0x49, + 0x7e, 0x7f, 0x9a, 0x19, 0x67, 0xee, 0xd6, 0xe3, 0x67, 0x13, 0xe8, 0x6f, + 0x79, 0x50, 0x76, 0xfc, 0xb3, 0x9d, 0x7e, 0x9e, 0x3e, 0x6e, 0x47, 0xb1, + 0x11, 0x5e, 0xc8, 0x83, 0x3a, 0x3c, 0xfc, 0x82, 0x5c, 0x9d, 0x34, 0x65, + 0x73, 0xb4, 0x56, 0xd5 +}; +static const unsigned char dsa_2048_224_sha256_q[] = { + 0xb0, 0xdf, 0xa1, 0x7b, 0xa4, 0x77, 0x64, 0x0e, 0xb9, 0x28, 0xbb, 0xbc, + 0xd4, 0x60, 0x02, 0xaf, 0x21, 0x8c, 0xb0, 0x69, 0x0f, 0x8a, 0x7b, 0xc6, + 0x80, 0xcb, 0x0a, 0x45 +}; +static const unsigned char dsa_2048_224_sha256_g[] = { + 0x11, 0x7c, 0x5f, 0xf6, 0x99, 0x44, 0x67, 0x5b, 0x69, 0xa3, 0x83, 0xef, + 0xb5, 0x85, 0xa2, 0x19, 0x35, 0x18, 0x2a, 0xf2, 0x58, 0xf4, 0xc9, 0x58, + 0x9e, 0xb9, 0xe8, 0x91, 0x17, 0x2f, 0xb0, 0x60, 0x85, 0x95, 0xa6, 0x62, + 0x36, 0xd0, 0xff, 0x94, 0xb9, 0xa6, 0x50, 0xad, 0xa6, 0xf6, 0x04, 0x28, + 0xc2, 0xc9, 0xb9, 0x75, 0xf3, 0x66, 0xb4, 0xeb, 0xf6, 0xd5, 0x06, 0x13, + 0x01, 0x64, 0x82, 0xa9, 0xf1, 0xd5, 0x41, 0xdc, 0xf2, 0x08, 0xfc, 0x2f, + 0xc4, 0xa1, 0x21, 0xee, 0x7d, 0xbc, 0xda, 0x5a, 0xa4, 0xa2, 0xb9, 0x68, + 0x87, 0x36, 0xba, 0x53, 0x9e, 0x14, 0x4e, 0x76, 0x5c, 0xba, 0x79, 0x3d, + 0x0f, 0xe5, 0x99, 0x1c, 0x27, 0xfc, 0xaf, 0x10, 0x63, 0x87, 0x68, 0x0e, + 0x3e, 0x6e, 0xaa, 0xf3, 0xdf, 0x76, 0x7e, 0x02, 0x9a, 0x41, 0x96, 0xa1, + 0x6c, 0xbb, 0x67, 0xee, 0x0c, 0xad, 0x72, 0x65, 0xf1, 0x70, 0xb0, 0x39, + 0x9b, 0x54, 0x5f, 0xd7, 0x6c, 0xc5, 0x9a, 0x90, 0x53, 0x18, 0xde, 0x5e, + 0x62, 0x89, 0xb9, 0x2f, 0x66, 0x59, 0x3a, 0x3d, 0x10, 0xeb, 0xa5, 0x99, + 0xf6, 0x21, 0x7d, 0xf2, 0x7b, 0x42, 0x15, 0x1c, 0x55, 0x79, 0x15, 0xaa, + 0xa4, 0x17, 0x2e, 0x48, 0xc3, 0xa8, 0x36, 0xf5, 0x1a, 0x97, 0xce, 0xbd, + 0x72, 0xef, 0x1d, 0x50, 0x5b, 0xb1, 0x60, 0x0a, 0x5c, 0x0b, 0xa6, 0x21, + 0x38, 0x28, 0x4e, 0x89, 0x33, 0x1d, 0xb5, 0x7e, 0x5c, 0xf1, 0x6b, 0x2c, + 0xbd, 0xad, 0x84, 0xb2, 0x8e, 0x96, 0xe2, 0x30, 0xe7, 0x54, 0xb8, 0xc9, + 0x70, 0xcb, 0x10, 0x30, 0x63, 0x90, 0xf4, 0x45, 0x64, 0x93, 0x09, 0x38, + 0x6a, 0x47, 0x58, 0x31, 0x04, 0x1a, 0x18, 0x04, 0x1a, 0xe0, 0xd7, 0x0b, + 0x3c, 0xbe, 0x2a, 0x9c, 0xec, 0xcc, 0x0d, 0x0c, 0xed, 0xde, 0x54, 0xbc, + 0xe6, 0x93, 0x59, 0xfc +}; + +static int ffc_params_validate_g_unverified_test(void) +{ + int ret = 0, res; + FFC_PARAMS params; + BIGNUM *p = NULL, *q = NULL, *g = NULL; + BIGNUM *p1 = NULL, *g1 = NULL; + + ffc_params_init(¶ms); + + if (!TEST_ptr(p = BN_bin2bn(dsa_2048_224_sha256_p, + sizeof(dsa_2048_224_sha256_p), NULL))) + goto err; + p1 = p; + if (!TEST_ptr(q = BN_bin2bn(dsa_2048_224_sha256_q, + sizeof(dsa_2048_224_sha256_q), NULL))) + goto err; + if (!TEST_ptr(g = BN_bin2bn(dsa_2048_224_sha256_g, + sizeof(dsa_2048_224_sha256_g), NULL))) + goto err; + g1 = g; + + /* Fail if g is NULL */ + ffc_params_set0_pqg(¶ms, p, q, NULL); + p = NULL; + q = NULL; + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha256(), + FFC_PARAMS_VALIDATE_G, &res, + NULL))) + goto err; + + ffc_params_set0_pqg(¶ms, p, q, g); + g = NULL; + if (!TEST_true(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha256(), + FFC_PARAMS_VALIDATE_G, &res, + NULL))) + goto err; + + /* incorrect g */ + BN_add_word(g1, 1); + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha256(), + FFC_PARAMS_VALIDATE_G, &res, + NULL))) + goto err; + + /* fail if g < 2 */ + BN_set_word(g1, 1); + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha256(), + FFC_PARAMS_VALIDATE_G, &res, + NULL))) + goto err; + + BN_copy(g1, p1); + /* Fail if g >= p */ + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha256(), + FFC_PARAMS_VALIDATE_G, &res, + NULL))) + goto err; + + ret = 1; +err: + ffc_params_cleanup(¶ms); + BN_free(p); + BN_free(q); + BN_free(g); + return ret; +} + +static int ffc_params_validate_pq_test(void) +{ + int ret = 0, res = -1; + FFC_PARAMS params; + BIGNUM *p = NULL, *q = NULL; + + ffc_params_init(¶ms); + if (!TEST_ptr(p = BN_bin2bn(dsa_2048_224_sha224_p, + sizeof(dsa_2048_224_sha224_p), + NULL))) + goto err; + if (!TEST_ptr(q = BN_bin2bn(dsa_2048_224_sha224_q, + sizeof(dsa_2048_224_sha224_q), + NULL))) + goto err; + + /* No p */ + ffc_params_set0_pqg(¶ms, NULL, q, NULL); + q = NULL; + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha224(), + FFC_PARAMS_VALIDATE_PQ, &res, + NULL))) + goto err; + + /* Test valid case */ + ffc_params_set0_pqg(¶ms, p, NULL, NULL); + p = NULL; + ffc_params_set_validate_params(¶ms, dsa_2048_224_sha224_seed, + sizeof(dsa_2048_224_sha224_seed), + dsa_2048_224_sha224_counter); + if (!TEST_true(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha224(), + FFC_PARAMS_VALIDATE_PQ, &res, + NULL))) + goto err; + + /* Bad counter - so p is not prime */ + ffc_params_set_validate_params(¶ms, dsa_2048_224_sha224_seed, + sizeof(dsa_2048_224_sha224_seed), + 1); + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha224(), + FFC_PARAMS_VALIDATE_PQ, &res, + NULL))) + goto err; + + /* seedlen smaller than N */ + ffc_params_set_validate_params(¶ms, dsa_2048_224_sha224_seed, + sizeof(dsa_2048_224_sha224_seed)-1, + dsa_2048_224_sha224_counter); + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha224(), + FFC_PARAMS_VALIDATE_PQ, &res, + NULL))) + goto err; + + /* Provided seed doesnt produce a valid prime q */ + ffc_params_set_validate_params(¶ms, dsa_2048_224_sha224_bad_seed, + sizeof(dsa_2048_224_sha224_bad_seed), + dsa_2048_224_sha224_counter); + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha224(), + FFC_PARAMS_VALIDATE_PQ, &res, + NULL))) + goto err; + + if (!TEST_ptr(p = BN_bin2bn(dsa_3072_256_sha512_p, + sizeof(dsa_3072_256_sha512_p), NULL))) + goto err; + if (!TEST_ptr(q = BN_bin2bn(dsa_3072_256_sha512_q, + sizeof(dsa_3072_256_sha512_q), + NULL))) + goto err; + + + ffc_params_set0_pqg(¶ms, p, q, NULL); + p = q = NULL; + ffc_params_set_validate_params(¶ms, dsa_3072_256_sha512_seed, + sizeof(dsa_3072_256_sha512_seed), + dsa_3072_256_sha512_counter); + /* Q doesn't div P-1 */ + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + EVP_sha512(), + FFC_PARAMS_VALIDATE_PQ, &res, + NULL))) + goto err; + + /* Bad L/N for FIPS DH */ + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DH, + EVP_sha512(), + FFC_PARAMS_VALIDATE_PQ, &res, + NULL))) + goto err; + + ret = 1; +err: + ffc_params_cleanup(¶ms); + BN_free(p); + BN_free(q); + return ret; +} +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH +static int ffc_params_gen_test(void) +{ + int ret = 0, res = -1; + FFC_PARAMS params; + + ffc_params_init(¶ms); + if (!TEST_true(ffc_params_FIPS186_4_generate(NULL, ¶ms, FFC_PARAM_TYPE_DH, + 2048, 256, NULL, &res, NULL))) + goto err; + if (!TEST_true(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DH, + NULL, + FFC_PARAMS_VALIDATE_ALL, &res, + NULL))) + goto err; + + ret = 1; +err: + ffc_params_cleanup(¶ms); + return ret; +} + +static int ffc_params_gen_canonicalg_test(void) +{ + int ret = 0, res = -1; + FFC_PARAMS params; + + ffc_params_init(¶ms); + params.gindex = 1; + if (!TEST_true(ffc_params_FIPS186_4_generate(NULL, ¶ms, FFC_PARAM_TYPE_DH, + 2048, 256, NULL, &res, NULL))) + goto err; + if (!TEST_true(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DH, + NULL, + FFC_PARAMS_VALIDATE_ALL, &res, + NULL))) + goto err; + + if (!TEST_true(ffc_params_print(bio_out, ¶ms, 4))) + goto err; + + ret = 1; +err: + ffc_params_cleanup(¶ms); + return ret; +} + +static int ffc_params_fips186_2_gen_validate_test(void) +{ + int ret = 0, res = -1; + FFC_PARAMS params; + BIGNUM *bn = NULL; + + if (!TEST_ptr(bn = BN_new())) + goto err; + ffc_params_init(¶ms); + if (!TEST_true(ffc_params_FIPS186_2_generate(NULL, ¶ms, FFC_PARAM_TYPE_DH, + 1024, 160, NULL, &res, NULL))) + goto err; + if (!TEST_true(ffc_params_FIPS186_2_validate(¶ms, FFC_PARAM_TYPE_DH, + NULL, + FFC_PARAMS_VALIDATE_ALL, &res, + NULL))) + goto err; + /* FIPS 186-4 L,N pair test will fail for DH */ + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DH, + NULL, + FFC_PARAMS_VALIDATE_ALL, &res, + NULL))) + goto err; + if (!TEST_int_eq(res, FFC_CHECK_BAD_LN_PAIR)) + goto err; + + /* + * The fips186-2 generation should produce a different q compared to + * fips 186-4 given the same seed value. So validation of q will fail. + */ + if (!TEST_false(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + NULL, + FFC_PARAMS_VALIDATE_ALL, &res, + NULL))) + goto err; + /* As the params are randomly generated the error is one of the following */ + if (!TEST_true(res == FFC_CHECK_Q_MISMATCH || res == FFC_CHECK_Q_NOT_PRIME)) + goto err; + + /* Partially valid g test will still pass */ + if (!TEST_int_eq(ffc_params_FIPS186_4_validate(¶ms, FFC_PARAM_TYPE_DSA, + NULL, + FFC_PARAMS_VALIDATE_G, &res, + NULL), 2)) + goto err; + + if (!TEST_true(ffc_params_print(bio_out, ¶ms, 4))) + goto err; + + ret = 1; +err: + BN_free(bn); + ffc_params_cleanup(¶ms); + return ret; +} + +extern FFC_PARAMS *dh_get0_params(DH *dh); + +static int ffc_public_validate_test(void) +{ + int ret = 0, res = -1; + FFC_PARAMS *params; + BIGNUM *pub = NULL; + DH *dh = NULL; + + if (!TEST_ptr(pub = BN_new())) + goto err; + + if (!TEST_ptr(dh = DH_new_by_nid(NID_ffdhe2048))) + goto err; + params = dh_get0_params(dh); + + if (!TEST_true(BN_set_word(pub, 1))) + goto err; + BN_set_negative(pub, 1); + /* Fail if public key is negative */ + if (!TEST_false(ffc_validate_public_key(params, pub, &res))) + goto err; + if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_SMALL, res)) + goto err; + if (!TEST_true(BN_set_word(pub, 0))) + goto err; + if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_SMALL, res)) + goto err; + /* Fail if public key is zero */ + if (!TEST_false(ffc_validate_public_key(params, pub, &res))) + goto err; + if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_SMALL, res)) + goto err; + /* Fail if public key is 1 */ + if (!TEST_false(ffc_validate_public_key(params, BN_value_one(), &res))) + goto err; + if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_SMALL, res)) + goto err; + if (!TEST_true(BN_add_word(pub, 2))) + goto err; + /* Pass if public key >= 2 */ + if (!TEST_true(ffc_validate_public_key(params, pub, &res))) + goto err; + + if (!TEST_ptr(BN_copy(pub, params->p))) + goto err; + /* Fail if public key = p */ + if (!TEST_false(ffc_validate_public_key(params, pub, &res))) + goto err; + if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_LARGE, res)) + goto err; + + if (!TEST_true(BN_sub_word(pub, 1))) + goto err; + /* Fail if public key = p - 1 */ + if (!TEST_false(ffc_validate_public_key(params, pub, &res))) + goto err; + if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_LARGE, res)) + goto err; + + if (!TEST_true(BN_sub_word(pub, 1))) + goto err; + /* Fail if public key is not related to p & q */ + if (!TEST_false(ffc_validate_public_key(params, pub, &res))) + goto err; + if (!TEST_int_eq(FFC_ERROR_PUBKEY_INVALID, res)) + goto err; + + if (!TEST_true(BN_sub_word(pub, 5))) + goto err; + /* Pass if public key is valid */ + if (!TEST_true(ffc_validate_public_key(params, pub, &res))) + goto err; + + ret = 1; +err: + DH_free(dh); + BN_free(pub); + return ret; +} + +static int ffc_private_validate_test(void) +{ + int ret = 0, res = -1; + FFC_PARAMS *params; + BIGNUM *priv = NULL; + DH *dh = NULL; + + if (!TEST_ptr(priv = BN_new())) + goto err; + + if (!TEST_ptr(dh = DH_new_by_nid(NID_ffdhe2048))) + goto err; + params = dh_get0_params(dh); + + if (!TEST_true(BN_set_word(priv, 1))) + goto err; + BN_set_negative(priv, 1); + /* Fail if priv key is negative */ + if (!TEST_false(ffc_validate_private_key(params->q, priv, &res))) + goto err; + if (!TEST_int_eq(FFC_ERROR_PRIVKEY_TOO_SMALL, res)) + goto err; + + if (!TEST_true(BN_set_word(priv, 0))) + goto err; + /* Fail if priv key is zero */ + if (!TEST_false(ffc_validate_private_key(params->q, priv, &res))) + goto err; + if (!TEST_int_eq(FFC_ERROR_PRIVKEY_TOO_SMALL, res)) + goto err; + + /* Pass if priv key >= 1 */ + if (!TEST_true(ffc_validate_private_key(params->q, BN_value_one(), &res))) + goto err; + + if (!TEST_ptr(BN_copy(priv, params->q))) + goto err; + /* Fail if priv key = upper */ + if (!TEST_false(ffc_validate_private_key(params->q, priv, &res))) + goto err; + if (!TEST_int_eq(FFC_ERROR_PRIVKEY_TOO_LARGE, res)) + goto err; + + if (!TEST_true(BN_sub_word(priv, 1))) + goto err; + /* Pass if priv key <= upper - 1 */ + if (!TEST_true(ffc_validate_private_key(params->q, priv, &res))) + goto err; + + ret = 1; +err: + DH_free(dh); + BN_free(priv); + return ret; +} + +static int ffc_private_gen_test(int index) +{ + int ret = 0, res = -1, N; + FFC_PARAMS *params; + BIGNUM *priv = NULL; + DH *dh = NULL; + BN_CTX *ctx = NULL; + + if (!TEST_ptr(ctx = BN_CTX_new_ex(NULL))) + goto err; + + if (!TEST_ptr(priv = BN_new())) + goto err; + + if (!TEST_ptr(dh = DH_new_by_nid(NID_ffdhe2048))) + goto err; + params = dh_get0_params(dh); + + N = BN_num_bits(params->q); + /* Fail since N < 2*s - where s = 112*/ + if (!TEST_false(ffc_generate_private_key_fips(ctx, params, 220, 112, priv))) + goto err; + /* fail since N > len(q) */ + if (!TEST_false(ffc_generate_private_key_fips(ctx, params, N + 1, 112, priv))) + goto err; + /* pass since 2s <= N <= len(q) */ + if (!TEST_true(ffc_generate_private_key_fips(ctx, params, N, 112, priv))) + goto err; + /* pass since N = len(q) */ + if (!TEST_true(ffc_validate_private_key(params->q, priv, &res))) + goto err; + /* pass since 2s <= N < len(q) */ + if (!TEST_true(ffc_generate_private_key_fips(ctx, params, N / 2, 112, priv))) + goto err; + if (!TEST_true(ffc_validate_private_key(params->q, priv, &res))) + goto err; + + /* N and s are ignored in this case */ + if (!TEST_true(ffc_generate_private_key(ctx, params, 0, 0, priv))) + goto err; + if (!TEST_true(ffc_validate_private_key(params->q, priv, &res))) + goto err; + + ret = 1; +err: + DH_free(dh); + BN_free(priv); + BN_CTX_free(ctx); + return ret; +} +#endif /* OPENSSL_NO_DH */ + +int setup_tests(void) +{ +#ifndef OPENSSL_NO_DSA + ADD_TEST(ffc_params_validate_pq_test); + ADD_TEST(ffc_params_validate_g_unverified_test); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + ADD_TEST(ffc_params_gen_test); + ADD_TEST(ffc_params_gen_canonicalg_test); + ADD_TEST(ffc_params_fips186_2_gen_validate_test); + ADD_TEST(ffc_public_validate_test); + ADD_TEST(ffc_private_validate_test); + ADD_ALL_TESTS(ffc_private_gen_test, 10); +#endif /* OPENSSL_NO_DH */ + return 1; +} diff --git a/test/recipes/03-test_internal_ffc.t b/test/recipes/03-test_internal_ffc.t new file mode 100644 index 0000000000..aa64213bc0 --- /dev/null +++ b/test/recipes/03-test_internal_ffc.t @@ -0,0 +1,11 @@ +#! /usr/bin/env perl +# 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 +# https://www.openssl.org/source/license.html + +use OpenSSL::Test::Simple; + +simple_test("test_internal_ffc", "ffc_internal_test"); -- 2.39.5