From: Shane Lontis Date: Fri, 24 Jan 2020 04:09:33 +0000 (+1000) Subject: Modify DSA and DH keys to use a shared FFC_PARAMS struct X-Git-Tag: openssl-3.0.0-alpha1~613 X-Git-Url: https://git.openssl.org/?p=openssl.git;a=commitdiff_plain;h=dc8de3e6f1eed18617dc42d41dec6c6566c2ac0c Modify DSA and DH keys to use a shared FFC_PARAMS struct This is required in order to share code for FIPS related parameter generation and validation routinues. Note the 'counter' field is now stored as a integer (as that is the form required for generation/validation functions). Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/10860) --- diff --git a/crypto/build.info b/crypto/build.info index daa26b8ed4..6906c54db2 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -5,7 +5,8 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 conf \ md2 md4 md5 sha mdc2 hmac ripemd whrlpool poly1305 \ siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \ seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \ - err comp ocsp cms ts srp cmac ct async ess crmf cmp serializer + err comp ocsp cms ts srp cmac ct async ess crmf cmp serializer \ + ffc LIBS=../libcrypto diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 174bd04cef..fd241831dc 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -282,7 +282,7 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype) else pub_key = NULL; - if (x->p == NULL || (ptype == 2 && priv_key == NULL) + if (x->params.p == NULL || (ptype == 2 && priv_key == NULL) || (ptype > 0 && pub_key == NULL)) { reason = ERR_R_PASSED_NULL_PARAMETER; goto err; @@ -296,7 +296,7 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype) ktype = "DH Parameters"; if (!BIO_indent(bp, indent, 128) - || BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) + || BIO_printf(bp, "%s: (%d bit)\n", ktype, DH_bits(x)) <= 0) goto err; indent += 4; @@ -305,35 +305,9 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype) if (!ASN1_bn_print(bp, "public-key:", pub_key, NULL, indent)) goto err; - if (!ASN1_bn_print(bp, "prime:", x->p, NULL, indent)) + if (!ffc_params_print(bp, &x->params, indent)) goto err; - if (!ASN1_bn_print(bp, "generator:", x->g, NULL, indent)) - goto err; - if (x->q && !ASN1_bn_print(bp, "subgroup order:", x->q, NULL, indent)) - goto err; - if (x->j && !ASN1_bn_print(bp, "subgroup factor:", x->j, NULL, indent)) - goto err; - if (x->seed) { - int i; - if (!BIO_indent(bp, indent, 128) - || BIO_puts(bp, "seed:") <= 0) - goto err; - for (i = 0; i < x->seedlen; i++) { - if ((i % 15) == 0) { - if (BIO_puts(bp, "\n") <= 0 - || !BIO_indent(bp, indent + 4, 128)) - goto err; - } - if (BIO_printf(bp, "%02x%s", x->seed[i], - ((i + 1) == x->seedlen) ? "" : ":") <= 0) - goto err; - } - if (BIO_write(bp, "\n", 1) <= 0) - return 0; - } - if (x->counter && !ASN1_bn_print(bp, "counter:", x->counter, NULL, indent)) - goto err; if (x->length != 0) { if (!BIO_indent(bp, indent, 128) || BIO_printf(bp, "recommended-private-length: %d bits\n", @@ -355,7 +329,7 @@ static int int_dh_size(const EVP_PKEY *pkey) static int dh_bits(const EVP_PKEY *pkey) { - return BN_num_bits(pkey->pkey.dh->p); + return DH_bits(pkey->pkey.dh); } static int dh_security_bits(const EVP_PKEY *pkey) @@ -365,59 +339,17 @@ static int dh_security_bits(const EVP_PKEY *pkey) static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { - if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) || - BN_cmp(a->pkey.dh->g, b->pkey.dh->g)) - return 0; - else if (a->ameth == &dhx_asn1_meth) { - if (BN_cmp(a->pkey.dh->q, b->pkey.dh->q)) - return 0; - } - return 1; -} - -static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src) -{ - BIGNUM *a; - - /* - * If source is read only just copy the pointer, so - * we don't have to reallocate it. - */ - if (src == NULL) - a = NULL; - else if (BN_get_flags(src, BN_FLG_STATIC_DATA) - && !BN_get_flags(src, BN_FLG_MALLOCED)) - a = (BIGNUM *)src; - else if ((a = BN_dup(src)) == NULL) - return 0; - BN_clear_free(*dst); - *dst = a; - return 1; + return ffc_params_cmp(&a->pkey.dh->params, &a->pkey.dh->params, + a->ameth != &dhx_asn1_meth); } static int int_dh_param_copy(DH *to, const DH *from, int is_x942) { if (is_x942 == -1) - is_x942 = ! !from->q; - if (!int_dh_bn_cpy(&to->p, from->p)) + is_x942 = (from->params.q != NULL); + if (!ffc_params_copy(&to->params, &from->params)) return 0; - if (!int_dh_bn_cpy(&to->g, from->g)) - return 0; - if (is_x942) { - if (!int_dh_bn_cpy(&to->q, from->q)) - return 0; - if (!int_dh_bn_cpy(&to->j, from->j)) - return 0; - OPENSSL_free(to->seed); - to->seed = NULL; - to->seedlen = 0; - if (from->seed) { - to->seed = OPENSSL_memdup(from->seed, from->seedlen); - if (!to->seed) - return 0; - to->seedlen = from->seedlen; - } - } else + if (!is_x942) to->length = from->length; to->dirty_cnt++; return 1; @@ -449,9 +381,9 @@ static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) static int dh_missing_parameters(const EVP_PKEY *a) { - if (a->pkey.dh == NULL || a->pkey.dh->p == NULL || a->pkey.dh->g == NULL) - return 1; - return 0; + return a->pkey.dh == NULL + || a->pkey.dh->params.p == NULL + || a->pkey.dh->params.g == NULL; } static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) @@ -820,6 +752,7 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) static int dh_cms_decrypt(CMS_RecipientInfo *ri) { EVP_PKEY_CTX *pctx; + pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (pctx == NULL) diff --git a/crypto/dh/dh_asn1.c b/crypto/dh/dh_asn1.c index 2708a81cd0..75f2dd5bde 100644 --- a/crypto/dh/dh_asn1.c +++ b/crypto/dh/dh_asn1.c @@ -34,8 +34,8 @@ static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, } ASN1_SEQUENCE_cb(DHparams, dh_cb) = { - ASN1_SIMPLE(DH, p, BIGNUM), - ASN1_SIMPLE(DH, g, BIGNUM), + ASN1_SIMPLE(DH, params.p, BIGNUM), + ASN1_SIMPLE(DH, params.g, BIGNUM), ASN1_OPT_EMBED(DH, length, ZINT32), } ASN1_SEQUENCE_END_cb(DH, DHparams) @@ -82,6 +82,7 @@ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(int_dhx942_dh, DHxparams, int_dhx) DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length) { + FFC_PARAMS *params; int_dhx942_dh *dhx = NULL; DH *dh = NULL; dh = DH_new(); @@ -93,22 +94,22 @@ DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length) return NULL; } - if (a) { + if (a != NULL) { DH_free(*a); *a = dh; } - dh->p = dhx->p; - dh->q = dhx->q; - dh->g = dhx->g; - dh->j = dhx->j; + params = &dh->params; + ffc_params_set0_pqg(params, dhx->p, dhx->q, dhx->g); + ffc_params_set0_j(params, dhx->j); - if (dhx->vparams) { - dh->seed = dhx->vparams->seed->data; - dh->seedlen = dhx->vparams->seed->length; - dh->counter = dhx->vparams->counter; - dhx->vparams->seed->data = NULL; + if (dhx->vparams != NULL) { + /* The counter has a maximum value of 4 * numbits(p) - 1 */ + size_t counter = (size_t)BN_get_word(dhx->vparams->counter); + ffc_params_set_validate_params(params, dhx->vparams->seed->data, + dhx->vparams->seed->length, counter); ASN1_BIT_STRING_free(dhx->vparams->seed); + BN_free(dhx->vparams->counter); OPENSSL_free(dhx->vparams); dhx->vparams = NULL; } @@ -119,22 +120,34 @@ DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length) int i2d_DHxparams(const DH *dh, unsigned char **pp) { + int ret = 0; int_dhx942_dh dhx; - int_dhvparams dhv; - ASN1_BIT_STRING bs; - dhx.p = dh->p; - dhx.g = dh->g; - dhx.q = dh->q; - dhx.j = dh->j; - if (dh->counter && dh->seed && dh->seedlen > 0) { - bs.flags = ASN1_STRING_FLAG_BITS_LEFT; - bs.data = dh->seed; - bs.length = dh->seedlen; - dhv.seed = &bs; - dhv.counter = dh->counter; + int_dhvparams dhv = { NULL, NULL }; + ASN1_BIT_STRING seed; + size_t seedlen = 0; + const FFC_PARAMS *params = &dh->params; + int counter; + + ffc_params_get0_pqg(params, (const BIGNUM **)&dhx.p, + (const BIGNUM **)&dhx.q, (const BIGNUM **)&dhx.g); + dhx.j = params->j; + ffc_params_get_validate_params(params, &seed.data, &seedlen, &counter); + seed.length = (int)seedlen; + + if (counter != -1 && seed.data != NULL && seed.length > 0) { + seed.flags = ASN1_STRING_FLAG_BITS_LEFT; + dhv.seed = &seed; + dhv.counter = BN_new(); + if (dhv.counter == NULL) + return 0; + if (!BN_set_word(dhv.counter, (BN_ULONG)counter)) + goto err; dhx.vparams = &dhv; - } else + } else { dhx.vparams = NULL; - - return i2d_int_dhx(&dhx, pp); + } + ret = i2d_int_dhx(&dhx, pp); +err: + BN_free(dhv.counter); + return ret; } diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index 70f083603f..8bb245207b 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -52,17 +52,19 @@ int DH_check_params(const DH *dh, int *ret) if (tmp == NULL) goto err; - if (!BN_is_odd(dh->p)) + if (!BN_is_odd(dh->params.p)) *ret |= DH_CHECK_P_NOT_PRIME; - if (BN_is_negative(dh->g) || BN_is_zero(dh->g) || BN_is_one(dh->g)) + if (BN_is_negative(dh->params.g) + || BN_is_zero(dh->params.g) + || BN_is_one(dh->params.g)) *ret |= DH_NOT_SUITABLE_GENERATOR; - if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1)) + if (BN_copy(tmp, dh->params.p) == NULL || !BN_sub_word(tmp, 1)) goto err; - if (BN_cmp(dh->g, tmp) >= 0) + if (BN_cmp(dh->params.g, tmp) >= 0) *ret |= DH_NOT_SUITABLE_GENERATOR; - if (BN_num_bits(dh->p) < DH_MIN_MODULUS_BITS) + if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) *ret |= DH_MODULUS_TOO_SMALL; - if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) + if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) *ret |= DH_MODULUS_TOO_LARGE; ok = 1; @@ -123,39 +125,40 @@ int DH_check(const DH *dh, int *ret) if (t2 == NULL) goto err; - if (dh->q) { - if (BN_cmp(dh->g, BN_value_one()) <= 0) + if (dh->params.q != NULL) { + if (BN_cmp(dh->params.g, BN_value_one()) <= 0) *ret |= DH_NOT_SUITABLE_GENERATOR; - else if (BN_cmp(dh->g, dh->p) >= 0) + else if (BN_cmp(dh->params.g, dh->params.p) >= 0) *ret |= DH_NOT_SUITABLE_GENERATOR; else { /* Check g^q == 1 mod p */ - if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) + if (!BN_mod_exp(t1, dh->params.g, dh->params.q, dh->params.p, ctx)) goto err; if (!BN_is_one(t1)) *ret |= DH_NOT_SUITABLE_GENERATOR; } - r = BN_check_prime(dh->q, ctx, NULL); + r = BN_check_prime(dh->params.q, ctx, NULL); if (r < 0) goto err; if (!r) *ret |= DH_CHECK_Q_NOT_PRIME; /* Check p == 1 mod q i.e. q divides p - 1 */ - if (!BN_div(t1, t2, dh->p, dh->q, ctx)) + if (!BN_div(t1, t2, dh->params.p, dh->params.q, ctx)) goto err; if (!BN_is_one(t2)) *ret |= DH_CHECK_INVALID_Q_VALUE; - if (dh->j && BN_cmp(dh->j, t1)) + if (dh->params.j != NULL + && BN_cmp(dh->params.j, t1)) *ret |= DH_CHECK_INVALID_J_VALUE; } - r = BN_check_prime(dh->p, ctx, NULL); + r = BN_check_prime(dh->params.p, ctx, NULL); if (r < 0) goto err; if (!r) *ret |= DH_CHECK_P_NOT_PRIME; - else if (!dh->q) { - if (!BN_rshift1(t1, dh->p)) + else if (dh->params.q == NULL) { + if (!BN_rshift1(t1, dh->params.p)) goto err; r = BN_check_prime(t1, ctx, NULL); if (r < 0) @@ -203,14 +206,14 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) goto err; if (BN_cmp(pub_key, tmp) <= 0) *ret |= DH_CHECK_PUBKEY_TOO_SMALL; - if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1)) + if (BN_copy(tmp, dh->params.p) == NULL || !BN_sub_word(tmp, 1)) goto err; if (BN_cmp(pub_key, tmp) >= 0) *ret |= DH_CHECK_PUBKEY_TOO_LARGE; - if (dh->q != NULL) { + if (dh->params.q != NULL) { /* Check pub_key^q == 1 mod p */ - if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) + if (!BN_mod_exp(tmp, pub_key, dh->params.q, dh->params.p, ctx)) goto err; if (!BN_is_one(tmp)) *ret |= DH_CHECK_PUBKEY_INVALID; diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c index 0506bbe2e5..75548592b8 100644 --- a/crypto/dh/dh_gen.c +++ b/crypto/dh/dh_gen.c @@ -81,9 +81,9 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator, goto err; /* Make sure 'ret' has the necessary elements */ - if (!ret->p && ((ret->p = BN_new()) == NULL)) + if (ret->params.p == NULL && ((ret->params.p = BN_new()) == NULL)) goto err; - if (!ret->g && ((ret->g = BN_new()) == NULL)) + if (ret->params.g == NULL && ((ret->params.g = BN_new()) == NULL)) goto err; if (generator <= 1) { @@ -115,11 +115,11 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator, g = generator; } - if (!BN_generate_prime_ex(ret->p, prime_len, 1, t1, t2, cb)) + if (!BN_generate_prime_ex(ret->params.p, prime_len, 1, t1, t2, cb)) goto err; if (!BN_GENCB_call(cb, 3, 0)) goto err; - if (!BN_set_word(ret->g, g)) + if (!BN_set_word(ret->params.g, g)) goto err; ret->dirty_cnt++; ok = 1; diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c index bd9b5c824b..4c5d78a19f 100644 --- a/crypto/dh/dh_key.c +++ b/crypto/dh/dh_key.c @@ -34,12 +34,12 @@ int dh_compute_key(OPENSSL_CTX *libctx, unsigned char *key, int check_result; #endif - if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { + if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) { DHerr(0, DH_R_MODULUS_TOO_LARGE); goto err; } - if (BN_num_bits(dh->p) < DH_MIN_MODULUS_BITS) { + if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) { DHerr(0, DH_R_MODULUS_TOO_SMALL); return 0; } @@ -59,7 +59,7 @@ int dh_compute_key(OPENSSL_CTX *libctx, unsigned char *key, if (dh->flags & DH_FLAG_CACHE_MONT_P) { mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, - dh->lock, dh->p, ctx); + dh->lock, dh->params.p, ctx); BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME); if (!mont) goto err; @@ -71,7 +71,7 @@ int dh_compute_key(OPENSSL_CTX *libctx, unsigned char *key, goto err; } #endif - if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, + if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->params.p, ctx, mont)) { DHerr(0, ERR_R_BN_LIB); goto err; @@ -101,7 +101,7 @@ int dh_compute_key_padded(OPENSSL_CTX *libctx, unsigned char *key, #endif if (rv <= 0) return rv; - pad = BN_num_bytes(dh->p) - rv; + pad = BN_num_bytes(dh->params.p) - rv; if (pad > 0) { memmove(key + pad, key, rv); memset(key, 0, pad); @@ -159,6 +159,7 @@ static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, static int dh_init(DH *dh) { dh->flags |= DH_FLAG_CACHE_MONT_P; + ffc_params_init(&dh->params); return 1; } @@ -189,12 +190,12 @@ static int generate_key(DH *dh) BN_MONT_CTX *mont = NULL; BIGNUM *pub_key = NULL, *priv_key = NULL; - if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { + if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) { DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE); return 0; } - if (BN_num_bits(dh->p) < DH_MIN_MODULUS_BITS) { + if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) { DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_SMALL); return 0; } @@ -220,28 +221,29 @@ static int generate_key(DH *dh) if (dh->flags & DH_FLAG_CACHE_MONT_P) { mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, - dh->lock, dh->p, ctx); + dh->lock, dh->params.p, ctx); if (!mont) goto err; } if (generate_new_key) { - if (dh->q) { + if (dh->params.q != NULL) { do { - if (!BN_priv_rand_range(priv_key, dh->q)) + if (!BN_priv_rand_range(priv_key, dh->params.q)) goto err; } while (BN_is_zero(priv_key) || BN_is_one(priv_key)); } else { /* secret exponent length */ - l = dh->length ? dh->length : BN_num_bits(dh->p) - 1; + l = dh->length ? dh->length : BN_num_bits(dh->params.p) - 1; if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) goto err; /* * We handle just one known case where g is a quadratic non-residue: * for g = 2: p % 8 == 3 */ - if (BN_is_word(dh->g, DH_GENERATOR_2) && !BN_is_bit_set(dh->p, 2)) { + if (BN_is_word(dh->params.g, DH_GENERATOR_2) + && !BN_is_bit_set(dh->params.p, 2)) { /* clear bit 0, since it won't be a secret anyway */ if (!BN_clear_bit(priv_key, 0)) goto err; @@ -256,7 +258,8 @@ static int generate_key(DH *dh) goto err; BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); - if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) { + if (!dh->meth->bn_mod_exp(dh, pub_key, dh->params.g, prk, dh->params.p, + ctx, mont)) { BN_clear_free(prk); goto err; } @@ -280,6 +283,7 @@ static int generate_key(DH *dh) return ok; } + 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 c9679d7e52..2f5aa10401 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -14,6 +14,7 @@ #include "dh_local.h" #include "crypto/dh.h" #include +#include "crypto/dh.h" #ifndef FIPS_MODE int DH_set_method(DH *dh, const DH_METHOD *meth) @@ -122,12 +123,7 @@ void DH_free(DH *r) CRYPTO_THREAD_lock_free(r->lock); - BN_clear_free(r->p); - BN_clear_free(r->g); - BN_clear_free(r->q); - BN_clear_free(r->j); - OPENSSL_free(r->seed); - BN_clear_free(r->counter); + ffc_params_cleanup(&r->params); BN_clear_free(r->pub_key); BN_clear_free(r->priv_key); OPENSSL_free(r); @@ -159,35 +155,30 @@ void *DH_get_ex_data(DH *d, int idx) int DH_bits(const DH *dh) { - return BN_num_bits(dh->p); + return BN_num_bits(dh->params.p); } int DH_size(const DH *dh) { - return BN_num_bytes(dh->p); + return BN_num_bytes(dh->params.p); } int DH_security_bits(const DH *dh) { int N; - if (dh->q) - N = BN_num_bits(dh->q); + if (dh->params.q != NULL) + N = BN_num_bits(dh->params.q); else if (dh->length) N = dh->length; else N = -1; - return BN_security_bits(BN_num_bits(dh->p), N); + return BN_security_bits(BN_num_bits(dh->params.p), N); } void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { - if (p != NULL) - *p = dh->p; - if (q != NULL) - *q = dh->q; - if (g != NULL) - *g = dh->g; + ffc_params_get0_pqg(&dh->params, p, q, g); } int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) @@ -195,26 +186,14 @@ int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) /* If the fields p and g in d are NULL, the corresponding input * parameters MUST be non-NULL. q may remain NULL. */ - if ((dh->p == NULL && p == NULL) - || (dh->g == NULL && g == NULL)) + if ((dh->params.p == NULL && p == NULL) + || (dh->params.g == NULL && g == NULL)) return 0; - if (p != NULL) { - BN_free(dh->p); - dh->p = p; - } - if (q != NULL) { - BN_free(dh->q); - dh->q = q; - } - if (g != NULL) { - BN_free(dh->g); - dh->g = g; - } + ffc_params_set0_pqg(&dh->params, p, q, g); - if (q != NULL) { + if (q != NULL) dh->length = BN_num_bits(q); - } dh->dirty_cnt++; return 1; @@ -256,17 +235,17 @@ int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) const BIGNUM *DH_get0_p(const DH *dh) { - return dh->p; + return dh->params.p; } const BIGNUM *DH_get0_q(const DH *dh) { - return dh->q; + return dh->params.q; } const BIGNUM *DH_get0_g(const DH *dh) { - return dh->g; + return dh->params.g; } const BIGNUM *DH_get0_priv_key(const DH *dh) @@ -300,3 +279,8 @@ ENGINE *DH_get0_engine(DH *dh) return dh->engine; } #endif /*FIPS_MODE */ + +FFC_PARAMS *dh_get0_params(DH *dh) +{ + return &dh->params; +} diff --git a/crypto/dh/dh_local.h b/crypto/dh/dh_local.h index 2a200c748e..57d9d3489f 100644 --- a/crypto/dh/dh_local.h +++ b/crypto/dh/dh_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-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 @@ -9,6 +9,7 @@ #include #include "internal/refcount.h" +#include "internal/ffc.h" #define DH_MIN_MODULUS_BITS 512 @@ -19,19 +20,12 @@ struct dh_st { */ int pad; int version; - BIGNUM *p; - BIGNUM *g; - int32_t length; /* optional */ + FFC_PARAMS params; + int32_t length; /* optional value of N (if there is no q) */ BIGNUM *pub_key; /* g^x % p */ BIGNUM *priv_key; /* x */ int flags; BN_MONT_CTX *method_mont_p; - /* Place holders if we want to do X9.42 DH */ - BIGNUM *q; - BIGNUM *j; - unsigned char *seed; - int seedlen; - BIGNUM *counter; CRYPTO_REF_COUNT references; #ifndef FIPS_MODE CRYPTO_EX_DATA ex_data; diff --git a/crypto/dh/dh_rfc5114.c b/crypto/dh/dh_rfc5114.c index 823f6d92e3..3bbfea12d3 100644 --- a/crypto/dh/dh_rfc5114.c +++ b/crypto/dh/dh_rfc5114.c @@ -26,10 +26,10 @@ DH *DH_get_##x(void) \ \ if (dh == NULL) \ return NULL; \ - dh->p = BN_dup(&_bignum_dh##x##_p); \ - dh->g = BN_dup(&_bignum_dh##x##_g); \ - dh->q = BN_dup(&_bignum_dh##x##_q); \ - if (dh->p == NULL || dh->q == NULL || dh->g == NULL) {\ + dh->params.p = BN_dup(&_bignum_dh##x##_p); \ + dh->params.g = BN_dup(&_bignum_dh##x##_g); \ + dh->params.q = BN_dup(&_bignum_dh##x##_q); \ + if (dh->params.p == NULL || dh->params.q == NULL || dh->params.g == NULL) {\ DH_free(dh); \ return NULL; \ } \ diff --git a/crypto/dh/dh_rfc7919.c b/crypto/dh/dh_rfc7919.c index e36712facf..92e5000e28 100644 --- a/crypto/dh/dh_rfc7919.c +++ b/crypto/dh/dh_rfc7919.c @@ -19,8 +19,8 @@ static DH *dh_param_init(const BIGNUM *p, int32_t nbits) DH *dh = DH_new(); if (dh == NULL) return NULL; - dh->p = (BIGNUM *)p; - dh->g = (BIGNUM *)&_bignum_const_2; + dh->params.p = (BIGNUM *)p; + dh->params.g = (BIGNUM *)&_bignum_const_2; dh->length = nbits; dh->dirty_cnt++; return dh; @@ -49,25 +49,25 @@ int DH_get_nid(const DH *dh) { int nid; - if (BN_get_word(dh->g) != 2) + if (BN_get_word(dh->params.g) != 2) return NID_undef; - if (!BN_cmp(dh->p, &_bignum_ffdhe2048_p)) + if (!BN_cmp(dh->params.p, &_bignum_ffdhe2048_p)) nid = NID_ffdhe2048; - else if (!BN_cmp(dh->p, &_bignum_ffdhe3072_p)) + else if (!BN_cmp(dh->params.p, &_bignum_ffdhe3072_p)) nid = NID_ffdhe3072; - else if (!BN_cmp(dh->p, &_bignum_ffdhe4096_p)) + else if (!BN_cmp(dh->params.p, &_bignum_ffdhe4096_p)) nid = NID_ffdhe4096; - else if (!BN_cmp(dh->p, &_bignum_ffdhe6144_p)) + else if (!BN_cmp(dh->params.p, &_bignum_ffdhe6144_p)) nid = NID_ffdhe6144; - else if (!BN_cmp(dh->p, &_bignum_ffdhe8192_p)) + else if (!BN_cmp(dh->params.p, &_bignum_ffdhe8192_p)) nid = NID_ffdhe8192; else return NID_undef; - if (dh->q != NULL) { - BIGNUM *q = BN_dup(dh->p); + if (dh->params.q != NULL) { + BIGNUM *q = BN_dup(dh->params.p); /* Check q = p * 2 + 1 we already know q is odd, so just shift right */ - if (q == NULL || !BN_rshift1(q, q) || !BN_cmp(dh->q, q)) + if (q == NULL || !BN_rshift1(q, q) || !BN_cmp(dh->params.q, q)) nid = NID_undef; BN_free(q); } diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index ddd262bdde..510b204b2d 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -88,7 +88,10 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) ASN1_OBJECT *aobj; dsa = pkey->pkey.dsa; - if (pkey->save_parameters && dsa->p && dsa->q && dsa->g) { + if (pkey->save_parameters + && dsa->params.p != NULL + && dsa->params.q != NULL + && dsa->params.g != NULL) { str = ASN1_STRING_new(); if (str == NULL) { DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE); @@ -183,7 +186,8 @@ static int dsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) } BN_set_flags(dsa->priv_key, BN_FLG_CONSTTIME); - if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) { + if (!BN_mod_exp(dsa->pub_key, dsa->params.g, dsa->priv_key, dsa->params.p, + ctx)) { DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_BN_ERROR); goto dsaerr; } @@ -275,55 +279,34 @@ static int dsa_missing_parameters(const EVP_PKEY *pkey) { DSA *dsa; dsa = pkey->pkey.dsa; - if (dsa == NULL || dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) - return 1; - return 0; + return dsa == NULL + || dsa->params.p == NULL + || dsa->params.q == NULL + || dsa->params.g == NULL; } static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { - BIGNUM *a; - if (to->pkey.dsa == NULL) { to->pkey.dsa = DSA_new(); if (to->pkey.dsa == NULL) return 0; } - - if ((a = BN_dup(from->pkey.dsa->p)) == NULL) + if (!ffc_params_copy(&to->pkey.dsa->params, &from->pkey.dsa->params)) return 0; - BN_free(to->pkey.dsa->p); - to->pkey.dsa->p = a; - if ((a = BN_dup(from->pkey.dsa->q)) == NULL) - return 0; - BN_free(to->pkey.dsa->q); - to->pkey.dsa->q = a; - - if ((a = BN_dup(from->pkey.dsa->g)) == NULL) - return 0; - BN_free(to->pkey.dsa->g); - to->pkey.dsa->g = a; to->pkey.dsa->dirty_cnt++; return 1; } static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { - if (BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) || - BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) || - BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g)) - return 0; - else - return 1; + return ffc_params_cmp(&a->pkey.dsa->params, &b->pkey.dsa->params, 1); } static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { - if (BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) != 0) - return 0; - else - return 1; + return BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) == 0; } static void int_dsa_free(EVP_PKEY *pkey) @@ -338,8 +321,8 @@ static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) const BIGNUM *priv_key, *pub_key; int mod_len = 0; - if (x->p != NULL) - mod_len = BN_num_bits(x->p); + if (x->params.p != NULL) + mod_len = DSA_bits(x); if (ptype == 2) priv_key = x->priv_key; @@ -358,11 +341,10 @@ static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) else ktype = "DSA-Parameters"; - if (priv_key) { + if (priv_key != NULL) { if (!BIO_indent(bp, off, 128)) goto err; - if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) - <= 0) + if (BIO_printf(bp, "%s: (%d bit)\n", ktype, mod_len) <= 0) goto err; } else { if (BIO_printf(bp, "Public-Key: (%d bit)\n", mod_len) <= 0) @@ -373,11 +355,7 @@ static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) goto err; if (!ASN1_bn_print(bp, "pub: ", pub_key, NULL, off)) goto err; - if (!ASN1_bn_print(bp, "P: ", x->p, NULL, off)) - goto err; - if (!ASN1_bn_print(bp, "Q: ", x->q, NULL, off)) - goto err; - if (!ASN1_bn_print(bp, "G: ", x->g, NULL, off)) + if (!ffc_params_print(bp, &x->params, off)) goto err; ret = 1; err: @@ -446,7 +424,7 @@ static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, DSA_SIG *dsa_sig; const unsigned char *p; - if (!sig) { + if (sig == NULL) { if (BIO_puts(bp, "\n") <= 0) return 0; else @@ -454,7 +432,7 @@ static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, } p = sig->data; dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length); - if (dsa_sig) { + if (dsa_sig != NULL) { int rv = 0; const BIGNUM *r, *s; diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c index 20bf2518c8..ba1cbad2ae 100644 --- a/crypto/dsa/dsa_asn1.c +++ b/crypto/dsa/dsa_asn1.c @@ -34,9 +34,9 @@ static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = { ASN1_EMBED(DSA, version, INT32), - ASN1_SIMPLE(DSA, p, BIGNUM), - ASN1_SIMPLE(DSA, q, BIGNUM), - ASN1_SIMPLE(DSA, g, BIGNUM), + ASN1_SIMPLE(DSA, params.p, BIGNUM), + ASN1_SIMPLE(DSA, params.q, BIGNUM), + ASN1_SIMPLE(DSA, params.g, BIGNUM), ASN1_SIMPLE(DSA, pub_key, BIGNUM), ASN1_SIMPLE(DSA, priv_key, CBIGNUM) } static_ASN1_SEQUENCE_END_cb(DSA, DSAPrivateKey) @@ -44,18 +44,18 @@ ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = { IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAPrivateKey, DSAPrivateKey) ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = { - ASN1_SIMPLE(DSA, p, BIGNUM), - ASN1_SIMPLE(DSA, q, BIGNUM), - ASN1_SIMPLE(DSA, g, BIGNUM), + ASN1_SIMPLE(DSA, params.p, BIGNUM), + ASN1_SIMPLE(DSA, params.q, BIGNUM), + ASN1_SIMPLE(DSA, params.g, BIGNUM), } static_ASN1_SEQUENCE_END_cb(DSA, DSAparams) IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAparams, DSAparams) ASN1_SEQUENCE_cb(DSAPublicKey, dsa_cb) = { ASN1_SIMPLE(DSA, pub_key, BIGNUM), - ASN1_SIMPLE(DSA, p, BIGNUM), - ASN1_SIMPLE(DSA, q, BIGNUM), - ASN1_SIMPLE(DSA, g, BIGNUM) + ASN1_SIMPLE(DSA, params.p, BIGNUM), + ASN1_SIMPLE(DSA, params.q, BIGNUM), + ASN1_SIMPLE(DSA, params.g, BIGNUM) } static_ASN1_SEQUENCE_END_cb(DSA, DSAPublicKey) IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAPublicKey, DSAPublicKey) diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index 67551e545b..02c2bd8083 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -274,14 +274,16 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, ok = 1; err: if (ok) { - BN_free(ret->p); - BN_free(ret->q); - BN_free(ret->g); - ret->p = BN_dup(p); - ret->q = BN_dup(q); - ret->g = BN_dup(g); + BN_free(ret->params.p); + BN_free(ret->params.q); + BN_free(ret->params.g); + ret->params.p = BN_dup(p); + ret->params.q = BN_dup(q); + ret->params.g = BN_dup(g); ret->dirty_cnt++; - if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { + if (ret->params.p == NULL + || ret->params.q == NULL + || ret->params.g == NULL) { ok = 0; goto err; } @@ -343,7 +345,7 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, mdsize = EVP_MD_size(evpmd); /* If unverifiable g generation only don't need seed */ - if (!ret->p || !ret->q || idx >= 0) { + if (!ret->params.p || !ret->params.q || idx >= 0) { if (seed_len == 0) seed_len = mdsize; @@ -379,9 +381,9 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, goto err; /* if p, q already supplied generate g only */ - if (ret->p && ret->q) { - p = ret->p; - q = ret->q; + if (ret->params.p && ret->params.q) { + p = ret->params.p; + q = ret->params.q; if (idx >= 0) memcpy(seed_tmp, seed, seed_len); goto g_only; @@ -583,17 +585,19 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, ok = 1; err: if (ok == 1) { - if (p != ret->p) { - BN_free(ret->p); - ret->p = BN_dup(p); + if (p != ret->params.p) { + BN_free(ret->params.p); + ret->params.p = BN_dup(p); } - if (q != ret->q) { - BN_free(ret->q); - ret->q = BN_dup(q); + if (q != ret->params.q) { + BN_free(ret->params.q); + ret->params.q = BN_dup(q); } - BN_free(ret->g); - ret->g = BN_dup(g); - if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { + BN_free(ret->params.g); + ret->params.g = BN_dup(g); + if (ret->params.p == NULL + || ret->params.q == NULL + || ret->params.g == NULL) { ok = -1; goto err; } diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index 6e5039a696..efc125253e 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -38,7 +38,7 @@ static int dsa_builtin_keygen(DSA *dsa) priv_key = dsa->priv_key; do - if (!BN_priv_rand_range(priv_key, dsa->q)) + if (!BN_priv_rand_range(priv_key, dsa->params.q)) goto err; while (BN_is_zero(priv_key)) ; @@ -55,7 +55,7 @@ static int dsa_builtin_keygen(DSA *dsa) goto err; BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); - if (!BN_mod_exp(pub_key, dsa->g, prk, dsa->p, ctx)) { + if (!BN_mod_exp(pub_key, dsa->params.g, prk, dsa->params.p, ctx)) { BN_free(prk); goto err; } diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index 976eb622aa..469746e65d 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-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 @@ -11,11 +11,11 @@ #include "internal/cryptlib.h" #include "internal/refcount.h" #include -#include "dsa_local.h" #include #include -#include +#include "dsa_local.h" #include "crypto/dsa.h" +#include "crypto/dh.h" /* required by DSA_dup_DH() */ #ifndef FIPS_MODE @@ -29,34 +29,25 @@ void *DSA_get_ex_data(DSA *d, int idx) return CRYPTO_get_ex_data(&d->ex_data, idx); } -#ifndef OPENSSL_NO_DH +# ifndef OPENSSL_NO_DH DH *DSA_dup_DH(const DSA *r) { /* - * DSA has p, q, g, optional pub_key, optional priv_key. DH has p, - * optional length, g, optional pub_key, optional priv_key, optional q. + * DSA has p, q, g, optional pub_key, optional priv_key. + * DH has p, optional length, g, optional pub_key, + * optional priv_key, optional q. */ - DH *ret = NULL; - BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL; if (r == NULL) goto err; ret = DH_new(); if (ret == NULL) goto err; - if (r->p != NULL || r->g != NULL || r->q != NULL) { - if (r->p == NULL || r->g == NULL || r->q == NULL) { - /* Shouldn't happen */ - goto err; - } - p = BN_dup(r->p); - g = BN_dup(r->g); - q = BN_dup(r->q); - if (p == NULL || g == NULL || q == NULL || !DH_set0_pqg(ret, p, q, g)) - goto err; - p = g = q = NULL; - } + + if (!ffc_params_copy(dh_get0_params(ret), &r->params)) + goto err; if (r->pub_key != NULL) { pub_key = BN_dup(r->pub_key); @@ -77,29 +68,26 @@ DH *DSA_dup_DH(const DSA *r) return ret; err: - BN_free(p); - BN_free(g); - BN_free(q); BN_free(pub_key); BN_free(priv_key); DH_free(ret); return NULL; } -#endif +# endif /* OPENSSL_NO_DH */ const BIGNUM *DSA_get0_p(const DSA *d) { - return d->p; + return d->params.p; } const BIGNUM *DSA_get0_q(const DSA *d) { - return d->q; + return d->params.q; } const BIGNUM *DSA_get0_g(const DSA *d) { - return d->g; + return d->params.g; } const BIGNUM *DSA_get0_pub_key(const DSA *d) @@ -250,9 +238,7 @@ void DSA_free(DSA *r) CRYPTO_THREAD_lock_free(r->lock); - BN_clear_free(r->p); - BN_clear_free(r->q); - BN_clear_free(r->g); + ffc_params_cleanup(&r->params); BN_clear_free(r->pub_key); BN_clear_free(r->priv_key); OPENSSL_free(r); @@ -273,12 +259,7 @@ int DSA_up_ref(DSA *r) void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { - if (p != NULL) - *p = d->p; - if (q != NULL) - *q = d->q; - if (g != NULL) - *g = d->g; + ffc_params_get0_pqg(&d->params, p, q, g); } int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) @@ -286,23 +267,12 @@ int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) /* If the fields p, q and g in d are NULL, the corresponding input * parameters MUST be non-NULL. */ - if ((d->p == NULL && p == NULL) - || (d->q == NULL && q == NULL) - || (d->g == NULL && g == NULL)) + if ((d->params.p == NULL && p == NULL) + || (d->params.q == NULL && q == NULL) + || (d->params.g == NULL && g == NULL)) return 0; - if (p != NULL) { - BN_free(d->p); - d->p = p; - } - if (q != NULL) { - BN_free(d->q); - d->q = q; - } - if (g != NULL) { - BN_free(d->g); - d->g = g; - } + ffc_params_set0_pqg(&d->params, p, q, g); d->dirty_cnt++; return 1; @@ -341,12 +311,13 @@ int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) int DSA_security_bits(const DSA *d) { - if (d->p && d->q) - return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q)); + if (d->params.p != NULL && d->params.q != NULL) + return BN_security_bits(BN_num_bits(d->params.p), + BN_num_bits(d->params.q)); return -1; } int DSA_bits(const DSA *dsa) { - return BN_num_bits(dsa->p); + return BN_num_bits(dsa->params.p); } diff --git a/crypto/dsa/dsa_local.h b/crypto/dsa/dsa_local.h index f0ec73410b..49b36c5f77 100644 --- a/crypto/dsa/dsa_local.h +++ b/crypto/dsa/dsa_local.h @@ -9,6 +9,7 @@ #include #include "internal/refcount.h" +#include "internal/ffc.h" struct dsa_st { /* @@ -17,9 +18,7 @@ struct dsa_st { */ int pad; int32_t version; - BIGNUM *p; - BIGNUM *q; /* == 20 */ - BIGNUM *g; + FFC_PARAMS params; BIGNUM *pub_key; /* y public key */ BIGNUM *priv_key; /* x private key */ int flags; diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index af0fa6b566..8de5a364f5 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -71,7 +71,9 @@ DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst, DSA_SIG *ret = NULL; int rv = 0; - if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) { + if (dsa->params.p == NULL + || dsa->params.q == NULL + || dsa->params.g == NULL) { reason = DSA_R_MISSING_PARAMETERS; goto err; } @@ -102,13 +104,13 @@ DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst, if (!dsa_sign_setup(dsa, ctx, &kinv, &ret->r, dgst, dlen)) goto err; - if (dlen > BN_num_bytes(dsa->q)) + if (dlen > BN_num_bytes(dsa->params.q)) /* * if the digest length is greater than the size of q use the * BN_num_bits(dsa->q) leftmost bits of the digest, see fips 186-3, * 4.2 */ - dlen = BN_num_bytes(dsa->q); + dlen = BN_num_bytes(dsa->params.q); if (BN_bin2bn(dgst, dlen, m) == NULL) goto err; @@ -124,7 +126,7 @@ DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst, /* Generate a blinding value */ do { - if (!BN_priv_rand_ex(blind, BN_num_bits(dsa->q) - 1, + if (!BN_priv_rand_ex(blind, BN_num_bits(dsa->params.q) - 1, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, ctx)) goto err; } while (BN_is_zero(blind)); @@ -133,27 +135,27 @@ DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst, BN_set_flags(tmp, BN_FLG_CONSTTIME); /* tmp := blind * priv_key * r mod q */ - if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->q, ctx)) + if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->params.q, ctx)) goto err; - if (!BN_mod_mul(tmp, tmp, ret->r, dsa->q, ctx)) + if (!BN_mod_mul(tmp, tmp, ret->r, dsa->params.q, ctx)) goto err; /* blindm := blind * m mod q */ - if (!BN_mod_mul(blindm, blind, m, dsa->q, ctx)) + if (!BN_mod_mul(blindm, blind, m, dsa->params.q, ctx)) goto err; /* s : = (blind * priv_key * r) + (blind * m) mod q */ - if (!BN_mod_add_quick(ret->s, tmp, blindm, dsa->q)) + if (!BN_mod_add_quick(ret->s, tmp, blindm, dsa->params.q)) goto err; /* s := s * k^-1 mod q */ - if (!BN_mod_mul(ret->s, ret->s, kinv, dsa->q, ctx)) + if (!BN_mod_mul(ret->s, ret->s, kinv, dsa->params.q, ctx)) goto err; /* s:= s * blind^-1 mod q */ - if (BN_mod_inverse(blind, blind, dsa->q, ctx) == NULL) + if (BN_mod_inverse(blind, blind, dsa->params.q, ctx) == NULL) goto err; - if (!BN_mod_mul(ret->s, ret->s, blind, dsa->q, ctx)) + if (!BN_mod_mul(ret->s, ret->s, blind, dsa->params.q, ctx)) goto err; /* @@ -197,13 +199,15 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, int ret = 0; int q_bits, q_words; - if (!dsa->p || !dsa->q || !dsa->g) { + if (!dsa->params.p || !dsa->params.q || !dsa->params.g) { DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS); return 0; } /* Reject obviously invalid parameters */ - if (BN_is_zero(dsa->p) || BN_is_zero(dsa->q) || BN_is_zero(dsa->g)) { + if (BN_is_zero(dsa->params.p) + || BN_is_zero(dsa->params.q) + || BN_is_zero(dsa->params.g)) { DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_PARAMETERS); return 0; } @@ -225,8 +229,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, ctx = ctx_in; /* Preallocate space */ - q_bits = BN_num_bits(dsa->q); - q_words = bn_get_top(dsa->q); + q_bits = BN_num_bits(dsa->params.q); + q_words = bn_get_top(dsa->params.q); if (!bn_wexpand(k, q_words + 2) || !bn_wexpand(l, q_words + 2)) goto err; @@ -238,10 +242,10 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, * We calculate k from SHA512(private_key + H(message) + random). * This protects the private key from a weak PRNG. */ - if (!BN_generate_dsa_nonce(k, dsa->q, dsa->priv_key, dgst, + if (!BN_generate_dsa_nonce(k, dsa->params.q, dsa->priv_key, dgst, dlen, ctx)) goto err; - } else if (!BN_priv_rand_range_ex(k, dsa->q, ctx)) + } else if (!BN_priv_rand_range_ex(k, dsa->params.q, ctx)) goto err; } while (BN_is_zero(k)); @@ -250,7 +254,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, if (dsa->flags & DSA_FLAG_CACHE_MONT_P) { if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, - dsa->lock, dsa->p, ctx)) + dsa->lock, dsa->params.p, ctx)) goto err; } @@ -269,26 +273,27 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, * https://github.com/openssl/openssl/pull/7486#discussion_r228323705 * The fix is to rework BN so these gymnastics aren't required. */ - if (!BN_add(l, k, dsa->q) - || !BN_add(k, l, dsa->q)) + if (!BN_add(l, k, dsa->params.q) + || !BN_add(k, l, dsa->params.q)) goto err; BN_consttime_swap(BN_is_bit_set(l, q_bits), k, l, q_words + 2); if ((dsa)->meth->bn_mod_exp != NULL) { - if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, k, dsa->p, ctx, - dsa->method_mont_p)) + if (!dsa->meth->bn_mod_exp(dsa, r, dsa->params.g, k, dsa->params.p, + ctx, dsa->method_mont_p)) goto err; } else { - if (!BN_mod_exp_mont(r, dsa->g, k, dsa->p, ctx, dsa->method_mont_p)) + if (!BN_mod_exp_mont(r, dsa->params.g, k, dsa->params.p, ctx, + dsa->method_mont_p)) goto err; } - if (!BN_mod(r, r, dsa->q, ctx)) + if (!BN_mod(r, r, dsa->params.q, ctx)) goto err; /* Compute part of 's = inv(k) (m + xr) mod q' */ - if ((kinv = dsa_mod_inverse_fermat(k, dsa->q, ctx)) == NULL) + if ((kinv = dsa_mod_inverse_fermat(k, dsa->params.q, ctx)) == NULL) goto err; BN_clear_free(*kinvp); @@ -313,19 +318,21 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, BN_MONT_CTX *mont = NULL; const BIGNUM *r, *s; int ret = -1, i; - if (!dsa->p || !dsa->q || !dsa->g) { + if (dsa->params.p == NULL + || dsa->params.q == NULL + || dsa->params.g == NULL) { DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MISSING_PARAMETERS); return -1; } - i = BN_num_bits(dsa->q); + i = BN_num_bits(dsa->params.q); /* fips 186-3 allows only different sizes for q */ if (i != 160 && i != 224 && i != 256) { DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_BAD_Q_VALUE); return -1; } - if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) { + if (BN_num_bits(dsa->params.p) > OPENSSL_DSA_MAX_MODULUS_BITS) { DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MODULUS_TOO_LARGE); return -1; } @@ -339,12 +346,12 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG_get0(sig, &r, &s); if (BN_is_zero(r) || BN_is_negative(r) || - BN_ucmp(r, dsa->q) >= 0) { + BN_ucmp(r, dsa->params.q) >= 0) { ret = 0; goto err; } if (BN_is_zero(s) || BN_is_negative(s) || - BN_ucmp(s, dsa->q) >= 0) { + BN_ucmp(s, dsa->params.q) >= 0) { ret = 0; goto err; } @@ -352,7 +359,7 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, /* * Calculate W = inv(S) mod Q save W in u2 */ - if ((BN_mod_inverse(u2, s, dsa->q, ctx)) == NULL) + if ((BN_mod_inverse(u2, s, dsa->params.q, ctx)) == NULL) goto err; /* save M in u1 */ @@ -367,32 +374,32 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, goto err; /* u1 = M * w mod q */ - if (!BN_mod_mul(u1, u1, u2, dsa->q, ctx)) + if (!BN_mod_mul(u1, u1, u2, dsa->params.q, ctx)) goto err; /* u2 = r * w mod q */ - if (!BN_mod_mul(u2, r, u2, dsa->q, ctx)) + if (!BN_mod_mul(u2, r, u2, dsa->params.q, ctx)) goto err; if (dsa->flags & DSA_FLAG_CACHE_MONT_P) { mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p, - dsa->lock, dsa->p, ctx); + dsa->lock, dsa->params.p, ctx); if (!mont) goto err; } if (dsa->meth->dsa_mod_exp != NULL) { - if (!dsa->meth->dsa_mod_exp(dsa, t1, dsa->g, u1, dsa->pub_key, u2, - dsa->p, ctx, mont)) + if (!dsa->meth->dsa_mod_exp(dsa, t1, dsa->params.g, u1, dsa->pub_key, u2, + dsa->params.p, ctx, mont)) goto err; } else { - if (!BN_mod_exp2_mont(t1, dsa->g, u1, dsa->pub_key, u2, dsa->p, ctx, - mont)) + if (!BN_mod_exp2_mont(t1, dsa->params.g, u1, dsa->pub_key, u2, + dsa->params.p, ctx, mont)) goto err; } /* let u1 = u1 mod q */ - if (!BN_mod(u1, t1, dsa->q, ctx)) + if (!BN_mod(u1, t1, dsa->params.q, ctx)) goto err; /* @@ -413,6 +420,7 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, static int dsa_init(DSA *dsa) { dsa->flags |= DSA_FLAG_CACHE_MONT_P; + ffc_params_init(&dsa->params); return 1; } diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c index d09aaea6db..d3e8cfa1ff 100644 --- a/crypto/dsa/dsa_sign.c +++ b/crypto/dsa/dsa_sign.c @@ -115,7 +115,7 @@ int DSA_size(const DSA *dsa) int ret; DSA_SIG sig; - sig.r = sig.s = dsa->q; + sig.r = sig.s = dsa->params.q; ret = i2d_DSA_SIG(&sig, NULL); if (ret < 0) diff --git a/crypto/ffc/build.info b/crypto/ffc/build.info new file mode 100644 index 0000000000..154d3c2510 --- /dev/null +++ b/crypto/ffc/build.info @@ -0,0 +1,6 @@ +LIBS=../../libcrypto + +$COMMON=ffc_params.c + +SOURCE[../../libcrypto]=$COMMON +SOURCE[../../providers/libfips.a]=$COMMON diff --git a/crypto/ffc/ffc_params.c b/crypto/ffc/ffc_params.c new file mode 100644 index 0000000000..838ace3827 --- /dev/null +++ b/crypto/ffc/ffc_params.c @@ -0,0 +1,191 @@ +/* + * 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 /* memset */ +#include "internal/ffc.h" +#ifndef FIPS_MODE +# include /* ffc_params_print */ +#endif + +void ffc_params_init(FFC_PARAMS *params) +{ + memset(params, 0, sizeof(FFC_PARAMS)); + params->pcounter = -1; +} + +void ffc_params_cleanup(FFC_PARAMS *params) +{ + BN_free(params->p); + BN_free(params->q); + BN_free(params->g); + BN_free(params->j); + OPENSSL_free(params->seed); + ffc_params_init(params); +} + +void ffc_params_set0_pqg(FFC_PARAMS *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + if (p != NULL && p != d->p) { + BN_free(d->p); + d->p = p; + } + if (q != NULL && q != d->q) { + BN_free(d->q); + d->q = q; + } + if (g != NULL && g != d->g) { + BN_free(d->g); + d->g = g; + } +} + +void ffc_params_get0_pqg(const FFC_PARAMS *d, const BIGNUM **p, + const BIGNUM **q, const BIGNUM **g) +{ + if (p != NULL) + *p = d->p; + if (q != NULL) + *q = d->q; + if (g != NULL) + *g = d->g; +} + + +/* j is the 'cofactor' that is optionally output for ASN1. */ +void ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *j) +{ + BN_free(d->j); + d->j = NULL; + if (j != NULL) + d->j = j; +} + +int ffc_params_set_validate_params(FFC_PARAMS *params, + const unsigned char *seed, size_t seedlen, + int counter) +{ + if (params == NULL) + return 0; + + if (params->seed != NULL) + OPENSSL_free(params->seed); + + if (seed != NULL && seedlen > 0) { + params->seed = OPENSSL_memdup(seed, seedlen); + if (params->seed == NULL) + return 0; + params->seedlen = seedlen; + } else { + params->seed = NULL; + params->seedlen = 0; + } + params->pcounter = counter; + return 1; +} + +void ffc_params_get_validate_params(const FFC_PARAMS *params, + unsigned char **seed, size_t *seedlen, + int *pcounter) +{ + if (seed != NULL) + *seed = params->seed; + if (seedlen != NULL) + *seedlen = params->seedlen; + if (pcounter != NULL) + *pcounter = params->pcounter; +} + +static int ffc_bn_cpy(BIGNUM **dst, const BIGNUM *src) +{ + BIGNUM *a; + + /* + * If source is read only just copy the pointer, so + * we don't have to reallocate it. + */ + if (src == NULL) + a = NULL; + else if (BN_get_flags(src, BN_FLG_STATIC_DATA) + && !BN_get_flags(src, BN_FLG_MALLOCED)) + a = (BIGNUM *)src; + else if ((a = BN_dup(src)) == NULL) + return 0; + BN_clear_free(*dst); + *dst = a; + return 1; +} + +int ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src) +{ + if (!ffc_bn_cpy(&dst->p, src->p) + || !ffc_bn_cpy(&dst->g, src->g) + || !ffc_bn_cpy(&dst->q, src->q) + || !ffc_bn_cpy(&dst->j, src->j)) + return 0; + + OPENSSL_free(dst->seed); + dst->seedlen = src->seedlen; + if (src->seed != NULL) { + dst->seed = OPENSSL_memdup(src->seed, src->seedlen); + if (dst->seed == NULL) + return 0; + } else { + dst->seed = NULL; + } + dst->pcounter = src->pcounter; + return 1; +} + +int ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q) +{ + return BN_cmp(a->p, b->p) == 0 + && BN_cmp(a->g, b->g) == 0 + && (ignore_q || BN_cmp(a->q, b->q) == 0); /* Note: q may be NULL */ +} + +#ifndef FIPS_MODE +int ffc_params_print(BIO *bp, const FFC_PARAMS *ffc, int indent) +{ + if (!ASN1_bn_print(bp, "prime P:", ffc->p, NULL, indent)) + goto err; + if (!ASN1_bn_print(bp, "generator G:", ffc->g, NULL, indent)) + goto err; + if (ffc->q != NULL + && !ASN1_bn_print(bp, "subgroup order Q:", ffc->q, NULL, indent)) + goto err; + if (ffc->j != NULL + && !ASN1_bn_print(bp, "subgroup factor:", ffc->j, NULL, indent)) + goto err; + if (ffc->seed != NULL) { + size_t i; + BIO_indent(bp, indent, 128); + BIO_puts(bp, "seed:"); + for (i = 0; i < ffc->seedlen; i++) { + if ((i % 15) == 0) { + if (BIO_puts(bp, "\n") <= 0 + || !BIO_indent(bp, indent + 4, 128)) + goto err; + } + if (BIO_printf(bp, "%02x%s", ffc->seed[i], + ((i + 1) == ffc->seedlen) ? "" : ":") <= 0) + goto err; + } + if (BIO_write(bp, "\n", 1) <= 0) + return 0; + } + if (ffc->pcounter != -1) { + BIO_indent(bp, indent, 128); + if (BIO_printf(bp, "counter: %d\n", ffc->pcounter) <= 0) + goto err; + } + return 1; +err: + return 0; +} +#endif /* FIPS_MODE */ diff --git a/include/crypto/dh.h b/include/crypto/dh.h index 4032bdc10e..b1f37c6018 100644 --- a/include/crypto/dh.h +++ b/include/crypto/dh.h @@ -8,8 +8,10 @@ */ #include +#include "internal/ffc.h" 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); diff --git a/include/internal/ffc.h b/include/internal/ffc.h new file mode 100644 index 0000000000..56703fb2e8 --- /dev/null +++ b/include/internal/ffc.h @@ -0,0 +1,57 @@ +/* + * 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 + */ + +#ifndef OSSL_INTERNAL_FFC_H +# define OSSL_INTERNAL_FFC_H + +# include + +/* + * Finite field cryptography (FFC) domain parameters are used by DH and DSA. + * Refer to FIPS186_4 Appendix A & B. + */ +typedef struct ffc_params_st { + /* Primes */ + BIGNUM *p; + BIGNUM *q; + /* Generator */ + BIGNUM *g; + /* DH X9.42 Optional Subgroup factor j >= 2 where p = j * q + 1 */ + BIGNUM *j; + + /* Required for FIPS186_4 validation of p, q and optionally canonical g */ + unsigned char *seed; + /* If this value is zero the hash size is used as the seed length */ + size_t seedlen; + /* Required for FIPS186_4 validation of p and q */ + int pcounter; + +} FFC_PARAMS; + +void ffc_params_init(FFC_PARAMS *params); +void ffc_params_cleanup(FFC_PARAMS *params); +void ffc_params_set0_pqg(FFC_PARAMS *params, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void ffc_params_get0_pqg(const FFC_PARAMS *params, const BIGNUM **p, + const BIGNUM **q, const BIGNUM **g); +void ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *j); +int ffc_params_set_validate_params(FFC_PARAMS *params, + const unsigned char *seed, size_t seedlen, + int counter); +void ffc_params_get_validate_params(const FFC_PARAMS *params, + unsigned char **seed, size_t *seedlen, + int *pcounter); + +int ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src); +int ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q); + +#ifndef FIPS_MODE +int ffc_params_print(BIO *bp, const FFC_PARAMS *ffc, int indent); +#endif /* FIPS_MODE */ + +#endif /* OSSL_INTERNAL_FFC_H */