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 <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10860)
This commit is contained in:
Shane Lontis 2020-01-24 14:09:33 +10:00
parent 21d08b9ee9
commit dc8de3e6f1
22 changed files with 524 additions and 376 deletions

View File

@ -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 \ md2 md4 md5 sha mdc2 hmac ripemd whrlpool poly1305 \
siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \ siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \
seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \ 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 LIBS=../libcrypto

View File

@ -282,7 +282,7 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype)
else else
pub_key = NULL; 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)) { || (ptype > 0 && pub_key == NULL)) {
reason = ERR_R_PASSED_NULL_PARAMETER; reason = ERR_R_PASSED_NULL_PARAMETER;
goto err; goto err;
@ -296,7 +296,7 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype)
ktype = "DH Parameters"; ktype = "DH Parameters";
if (!BIO_indent(bp, indent, 128) 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; goto err;
indent += 4; 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)) if (!ASN1_bn_print(bp, "public-key:", pub_key, NULL, indent))
goto err; goto err;
if (!ASN1_bn_print(bp, "prime:", x->p, NULL, indent)) if (!ffc_params_print(bp, &x->params, indent))
goto err; 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 (x->length != 0) {
if (!BIO_indent(bp, indent, 128) if (!BIO_indent(bp, indent, 128)
|| BIO_printf(bp, "recommended-private-length: %d bits\n", || 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) 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) 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) static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{ {
if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) || return ffc_params_cmp(&a->pkey.dh->params, &a->pkey.dh->params,
BN_cmp(a->pkey.dh->g, b->pkey.dh->g)) a->ameth != &dhx_asn1_meth);
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;
} }
static int int_dh_param_copy(DH *to, const DH *from, int is_x942) static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
{ {
if (is_x942 == -1) if (is_x942 == -1)
is_x942 = ! !from->q; is_x942 = (from->params.q != NULL);
if (!int_dh_bn_cpy(&to->p, from->p)) if (!ffc_params_copy(&to->params, &from->params))
return 0; return 0;
if (!int_dh_bn_cpy(&to->g, from->g)) if (!is_x942)
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
to->length = from->length; to->length = from->length;
to->dirty_cnt++; to->dirty_cnt++;
return 1; 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) 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 a->pkey.dh == NULL
return 1; || a->pkey.dh->params.p == NULL
return 0; || a->pkey.dh->params.g == NULL;
} }
static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) 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) static int dh_cms_decrypt(CMS_RecipientInfo *ri)
{ {
EVP_PKEY_CTX *pctx; EVP_PKEY_CTX *pctx;
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (pctx == NULL) if (pctx == NULL)

View File

@ -34,8 +34,8 @@ static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
} }
ASN1_SEQUENCE_cb(DHparams, dh_cb) = { ASN1_SEQUENCE_cb(DHparams, dh_cb) = {
ASN1_SIMPLE(DH, p, BIGNUM), ASN1_SIMPLE(DH, params.p, BIGNUM),
ASN1_SIMPLE(DH, g, BIGNUM), ASN1_SIMPLE(DH, params.g, BIGNUM),
ASN1_OPT_EMBED(DH, length, ZINT32), ASN1_OPT_EMBED(DH, length, ZINT32),
} ASN1_SEQUENCE_END_cb(DH, DHparams) } 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) DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length)
{ {
FFC_PARAMS *params;
int_dhx942_dh *dhx = NULL; int_dhx942_dh *dhx = NULL;
DH *dh = NULL; DH *dh = NULL;
dh = DH_new(); dh = DH_new();
@ -93,22 +94,22 @@ DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length)
return NULL; return NULL;
} }
if (a) { if (a != NULL) {
DH_free(*a); DH_free(*a);
*a = dh; *a = dh;
} }
dh->p = dhx->p; params = &dh->params;
dh->q = dhx->q; ffc_params_set0_pqg(params, dhx->p, dhx->q, dhx->g);
dh->g = dhx->g; ffc_params_set0_j(params, dhx->j);
dh->j = dhx->j;
if (dhx->vparams) { if (dhx->vparams != NULL) {
dh->seed = dhx->vparams->seed->data; /* The counter has a maximum value of 4 * numbits(p) - 1 */
dh->seedlen = dhx->vparams->seed->length; size_t counter = (size_t)BN_get_word(dhx->vparams->counter);
dh->counter = dhx->vparams->counter; ffc_params_set_validate_params(params, dhx->vparams->seed->data,
dhx->vparams->seed->data = NULL; dhx->vparams->seed->length, counter);
ASN1_BIT_STRING_free(dhx->vparams->seed); ASN1_BIT_STRING_free(dhx->vparams->seed);
BN_free(dhx->vparams->counter);
OPENSSL_free(dhx->vparams); OPENSSL_free(dhx->vparams);
dhx->vparams = NULL; 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 i2d_DHxparams(const DH *dh, unsigned char **pp)
{ {
int ret = 0;
int_dhx942_dh dhx; int_dhx942_dh dhx;
int_dhvparams dhv; int_dhvparams dhv = { NULL, NULL };
ASN1_BIT_STRING bs; ASN1_BIT_STRING seed;
dhx.p = dh->p; size_t seedlen = 0;
dhx.g = dh->g; const FFC_PARAMS *params = &dh->params;
dhx.q = dh->q; int counter;
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;
dhx.vparams = &dhv;
} else
dhx.vparams = NULL;
return i2d_int_dhx(&dhx, pp); 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 {
dhx.vparams = NULL;
}
ret = i2d_int_dhx(&dhx, pp);
err:
BN_free(dhv.counter);
return ret;
} }

View File

@ -52,17 +52,19 @@ int DH_check_params(const DH *dh, int *ret)
if (tmp == NULL) if (tmp == NULL)
goto err; goto err;
if (!BN_is_odd(dh->p)) if (!BN_is_odd(dh->params.p))
*ret |= DH_CHECK_P_NOT_PRIME; *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; *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; goto err;
if (BN_cmp(dh->g, tmp) >= 0) if (BN_cmp(dh->params.g, tmp) >= 0)
*ret |= DH_NOT_SUITABLE_GENERATOR; *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; *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; *ret |= DH_MODULUS_TOO_LARGE;
ok = 1; ok = 1;
@ -123,39 +125,40 @@ int DH_check(const DH *dh, int *ret)
if (t2 == NULL) if (t2 == NULL)
goto err; goto err;
if (dh->q) { if (dh->params.q != NULL) {
if (BN_cmp(dh->g, BN_value_one()) <= 0) if (BN_cmp(dh->params.g, BN_value_one()) <= 0)
*ret |= DH_NOT_SUITABLE_GENERATOR; *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; *ret |= DH_NOT_SUITABLE_GENERATOR;
else { else {
/* Check g^q == 1 mod p */ /* 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; goto err;
if (!BN_is_one(t1)) if (!BN_is_one(t1))
*ret |= DH_NOT_SUITABLE_GENERATOR; *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) if (r < 0)
goto err; goto err;
if (!r) if (!r)
*ret |= DH_CHECK_Q_NOT_PRIME; *ret |= DH_CHECK_Q_NOT_PRIME;
/* Check p == 1 mod q i.e. q divides p - 1 */ /* 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; goto err;
if (!BN_is_one(t2)) if (!BN_is_one(t2))
*ret |= DH_CHECK_INVALID_Q_VALUE; *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; *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) if (r < 0)
goto err; goto err;
if (!r) if (!r)
*ret |= DH_CHECK_P_NOT_PRIME; *ret |= DH_CHECK_P_NOT_PRIME;
else if (!dh->q) { else if (dh->params.q == NULL) {
if (!BN_rshift1(t1, dh->p)) if (!BN_rshift1(t1, dh->params.p))
goto err; goto err;
r = BN_check_prime(t1, ctx, NULL); r = BN_check_prime(t1, ctx, NULL);
if (r < 0) if (r < 0)
@ -203,14 +206,14 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
goto err; goto err;
if (BN_cmp(pub_key, tmp) <= 0) if (BN_cmp(pub_key, tmp) <= 0)
*ret |= DH_CHECK_PUBKEY_TOO_SMALL; *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; goto err;
if (BN_cmp(pub_key, tmp) >= 0) if (BN_cmp(pub_key, tmp) >= 0)
*ret |= DH_CHECK_PUBKEY_TOO_LARGE; *ret |= DH_CHECK_PUBKEY_TOO_LARGE;
if (dh->q != NULL) { if (dh->params.q != NULL) {
/* Check pub_key^q == 1 mod p */ /* 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; goto err;
if (!BN_is_one(tmp)) if (!BN_is_one(tmp))
*ret |= DH_CHECK_PUBKEY_INVALID; *ret |= DH_CHECK_PUBKEY_INVALID;

View File

@ -81,9 +81,9 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
goto err; goto err;
/* Make sure 'ret' has the necessary elements */ /* 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; goto err;
if (!ret->g && ((ret->g = BN_new()) == NULL)) if (ret->params.g == NULL && ((ret->params.g = BN_new()) == NULL))
goto err; goto err;
if (generator <= 1) { if (generator <= 1) {
@ -115,11 +115,11 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
g = 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; goto err;
if (!BN_GENCB_call(cb, 3, 0)) if (!BN_GENCB_call(cb, 3, 0))
goto err; goto err;
if (!BN_set_word(ret->g, g)) if (!BN_set_word(ret->params.g, g))
goto err; goto err;
ret->dirty_cnt++; ret->dirty_cnt++;
ok = 1; ok = 1;

View File

@ -34,12 +34,12 @@ int dh_compute_key(OPENSSL_CTX *libctx, unsigned char *key,
int check_result; int check_result;
#endif #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); DHerr(0, DH_R_MODULUS_TOO_LARGE);
goto err; 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); DHerr(0, DH_R_MODULUS_TOO_SMALL);
return 0; return 0;
} }
@ -59,7 +59,7 @@ int dh_compute_key(OPENSSL_CTX *libctx, unsigned char *key,
if (dh->flags & DH_FLAG_CACHE_MONT_P) { if (dh->flags & DH_FLAG_CACHE_MONT_P) {
mont = BN_MONT_CTX_set_locked(&dh->method_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); BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
if (!mont) if (!mont)
goto err; goto err;
@ -71,7 +71,7 @@ int dh_compute_key(OPENSSL_CTX *libctx, unsigned char *key,
goto err; goto err;
} }
#endif #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)) { mont)) {
DHerr(0, ERR_R_BN_LIB); DHerr(0, ERR_R_BN_LIB);
goto err; goto err;
@ -101,7 +101,7 @@ int dh_compute_key_padded(OPENSSL_CTX *libctx, unsigned char *key,
#endif #endif
if (rv <= 0) if (rv <= 0)
return rv; return rv;
pad = BN_num_bytes(dh->p) - rv; pad = BN_num_bytes(dh->params.p) - rv;
if (pad > 0) { if (pad > 0) {
memmove(key + pad, key, rv); memmove(key + pad, key, rv);
memset(key, 0, pad); 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) static int dh_init(DH *dh)
{ {
dh->flags |= DH_FLAG_CACHE_MONT_P; dh->flags |= DH_FLAG_CACHE_MONT_P;
ffc_params_init(&dh->params);
return 1; return 1;
} }
@ -189,12 +190,12 @@ static int generate_key(DH *dh)
BN_MONT_CTX *mont = NULL; BN_MONT_CTX *mont = NULL;
BIGNUM *pub_key = NULL, *priv_key = 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); DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE);
return 0; 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); DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_SMALL);
return 0; return 0;
} }
@ -220,28 +221,29 @@ static int generate_key(DH *dh)
if (dh->flags & DH_FLAG_CACHE_MONT_P) { if (dh->flags & DH_FLAG_CACHE_MONT_P) {
mont = BN_MONT_CTX_set_locked(&dh->method_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) if (!mont)
goto err; goto err;
} }
if (generate_new_key) { if (generate_new_key) {
if (dh->q) { if (dh->params.q != NULL) {
do { do {
if (!BN_priv_rand_range(priv_key, dh->q)) if (!BN_priv_rand_range(priv_key, dh->params.q))
goto err; goto err;
} }
while (BN_is_zero(priv_key) || BN_is_one(priv_key)); while (BN_is_zero(priv_key) || BN_is_one(priv_key));
} else { } else {
/* secret exponent length */ /* 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)) if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
goto err; goto err;
/* /*
* We handle just one known case where g is a quadratic non-residue: * We handle just one known case where g is a quadratic non-residue:
* for g = 2: p % 8 == 3 * 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 */ /* clear bit 0, since it won't be a secret anyway */
if (!BN_clear_bit(priv_key, 0)) if (!BN_clear_bit(priv_key, 0))
goto err; goto err;
@ -256,7 +258,8 @@ static int generate_key(DH *dh)
goto err; goto err;
BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); 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); BN_clear_free(prk);
goto err; goto err;
} }
@ -280,6 +283,7 @@ static int generate_key(DH *dh)
return ok; return ok;
} }
int dh_buf2key(DH *dh, const unsigned char *buf, size_t len) int dh_buf2key(DH *dh, const unsigned char *buf, size_t len)
{ {
int err_reason = DH_R_BN_ERROR; int err_reason = DH_R_BN_ERROR;

View File

@ -14,6 +14,7 @@
#include "dh_local.h" #include "dh_local.h"
#include "crypto/dh.h" #include "crypto/dh.h"
#include <openssl/engine.h> #include <openssl/engine.h>
#include "crypto/dh.h"
#ifndef FIPS_MODE #ifndef FIPS_MODE
int DH_set_method(DH *dh, const DH_METHOD *meth) 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); CRYPTO_THREAD_lock_free(r->lock);
BN_clear_free(r->p); ffc_params_cleanup(&r->params);
BN_clear_free(r->g);
BN_clear_free(r->q);
BN_clear_free(r->j);
OPENSSL_free(r->seed);
BN_clear_free(r->counter);
BN_clear_free(r->pub_key); BN_clear_free(r->pub_key);
BN_clear_free(r->priv_key); BN_clear_free(r->priv_key);
OPENSSL_free(r); OPENSSL_free(r);
@ -159,35 +155,30 @@ void *DH_get_ex_data(DH *d, int idx)
int DH_bits(const DH *dh) 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) 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 DH_security_bits(const DH *dh)
{ {
int N; int N;
if (dh->q) if (dh->params.q != NULL)
N = BN_num_bits(dh->q); N = BN_num_bits(dh->params.q);
else if (dh->length) else if (dh->length)
N = dh->length; N = dh->length;
else else
N = -1; 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, void DH_get0_pqg(const DH *dh,
const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{ {
if (p != NULL) ffc_params_get0_pqg(&dh->params, p, q, g);
*p = dh->p;
if (q != NULL)
*q = dh->q;
if (g != NULL)
*g = dh->g;
} }
int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *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 /* If the fields p and g in d are NULL, the corresponding input
* parameters MUST be non-NULL. q may remain NULL. * parameters MUST be non-NULL. q may remain NULL.
*/ */
if ((dh->p == NULL && p == NULL) if ((dh->params.p == NULL && p == NULL)
|| (dh->g == NULL && g == NULL)) || (dh->params.g == NULL && g == NULL))
return 0; return 0;
if (p != NULL) { ffc_params_set0_pqg(&dh->params, p, q, g);
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;
}
if (q != NULL) { if (q != NULL)
dh->length = BN_num_bits(q); dh->length = BN_num_bits(q);
}
dh->dirty_cnt++; dh->dirty_cnt++;
return 1; 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) const BIGNUM *DH_get0_p(const DH *dh)
{ {
return dh->p; return dh->params.p;
} }
const BIGNUM *DH_get0_q(const DH *dh) const BIGNUM *DH_get0_q(const DH *dh)
{ {
return dh->q; return dh->params.q;
} }
const BIGNUM *DH_get0_g(const DH *dh) const BIGNUM *DH_get0_g(const DH *dh)
{ {
return dh->g; return dh->params.g;
} }
const BIGNUM *DH_get0_priv_key(const DH *dh) const BIGNUM *DH_get0_priv_key(const DH *dh)
@ -300,3 +279,8 @@ ENGINE *DH_get0_engine(DH *dh)
return dh->engine; return dh->engine;
} }
#endif /*FIPS_MODE */ #endif /*FIPS_MODE */
FFC_PARAMS *dh_get0_params(DH *dh)
{
return &dh->params;
}

View File

@ -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 * 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 * this file except in compliance with the License. You can obtain a copy
@ -9,6 +9,7 @@
#include <openssl/dh.h> #include <openssl/dh.h>
#include "internal/refcount.h" #include "internal/refcount.h"
#include "internal/ffc.h"
#define DH_MIN_MODULUS_BITS 512 #define DH_MIN_MODULUS_BITS 512
@ -19,19 +20,12 @@ struct dh_st {
*/ */
int pad; int pad;
int version; int version;
BIGNUM *p; FFC_PARAMS params;
BIGNUM *g; int32_t length; /* optional value of N (if there is no q) */
int32_t length; /* optional */
BIGNUM *pub_key; /* g^x % p */ BIGNUM *pub_key; /* g^x % p */
BIGNUM *priv_key; /* x */ BIGNUM *priv_key; /* x */
int flags; int flags;
BN_MONT_CTX *method_mont_p; 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; CRYPTO_REF_COUNT references;
#ifndef FIPS_MODE #ifndef FIPS_MODE
CRYPTO_EX_DATA ex_data; CRYPTO_EX_DATA ex_data;

View File

@ -26,10 +26,10 @@ DH *DH_get_##x(void) \
\ \
if (dh == NULL) \ if (dh == NULL) \
return NULL; \ return NULL; \
dh->p = BN_dup(&_bignum_dh##x##_p); \ dh->params.p = BN_dup(&_bignum_dh##x##_p); \
dh->g = BN_dup(&_bignum_dh##x##_g); \ dh->params.g = BN_dup(&_bignum_dh##x##_g); \
dh->q = BN_dup(&_bignum_dh##x##_q); \ dh->params.q = BN_dup(&_bignum_dh##x##_q); \
if (dh->p == NULL || dh->q == NULL || dh->g == NULL) {\ if (dh->params.p == NULL || dh->params.q == NULL || dh->params.g == NULL) {\
DH_free(dh); \ DH_free(dh); \
return NULL; \ return NULL; \
} \ } \

View File

@ -19,8 +19,8 @@ static DH *dh_param_init(const BIGNUM *p, int32_t nbits)
DH *dh = DH_new(); DH *dh = DH_new();
if (dh == NULL) if (dh == NULL)
return NULL; return NULL;
dh->p = (BIGNUM *)p; dh->params.p = (BIGNUM *)p;
dh->g = (BIGNUM *)&_bignum_const_2; dh->params.g = (BIGNUM *)&_bignum_const_2;
dh->length = nbits; dh->length = nbits;
dh->dirty_cnt++; dh->dirty_cnt++;
return dh; return dh;
@ -49,25 +49,25 @@ int DH_get_nid(const DH *dh)
{ {
int nid; int nid;
if (BN_get_word(dh->g) != 2) if (BN_get_word(dh->params.g) != 2)
return NID_undef; return NID_undef;
if (!BN_cmp(dh->p, &_bignum_ffdhe2048_p)) if (!BN_cmp(dh->params.p, &_bignum_ffdhe2048_p))
nid = NID_ffdhe2048; 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; 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; 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; 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; nid = NID_ffdhe8192;
else else
return NID_undef; return NID_undef;
if (dh->q != NULL) { if (dh->params.q != NULL) {
BIGNUM *q = BN_dup(dh->p); BIGNUM *q = BN_dup(dh->params.p);
/* Check q = p * 2 + 1 we already know q is odd, so just shift right */ /* 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; nid = NID_undef;
BN_free(q); BN_free(q);
} }

View File

@ -88,7 +88,10 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
ASN1_OBJECT *aobj; ASN1_OBJECT *aobj;
dsa = pkey->pkey.dsa; 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(); str = ASN1_STRING_new();
if (str == NULL) { if (str == NULL) {
DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE); 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); 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); DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_BN_ERROR);
goto dsaerr; goto dsaerr;
} }
@ -275,55 +279,34 @@ static int dsa_missing_parameters(const EVP_PKEY *pkey)
{ {
DSA *dsa; DSA *dsa;
dsa = pkey->pkey.dsa; dsa = pkey->pkey.dsa;
if (dsa == NULL || dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) return dsa == NULL
return 1; || dsa->params.p == NULL
return 0; || dsa->params.q == NULL
|| dsa->params.g == NULL;
} }
static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
{ {
BIGNUM *a;
if (to->pkey.dsa == NULL) { if (to->pkey.dsa == NULL) {
to->pkey.dsa = DSA_new(); to->pkey.dsa = DSA_new();
if (to->pkey.dsa == NULL) if (to->pkey.dsa == NULL)
return 0; return 0;
} }
if (!ffc_params_copy(&to->pkey.dsa->params, &from->pkey.dsa->params))
if ((a = BN_dup(from->pkey.dsa->p)) == NULL)
return 0; 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++; to->pkey.dsa->dirty_cnt++;
return 1; return 1;
} }
static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{ {
if (BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) || return ffc_params_cmp(&a->pkey.dsa->params, &b->pkey.dsa->params, 1);
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;
} }
static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) 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 BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) == 0;
return 0;
else
return 1;
} }
static void int_dsa_free(EVP_PKEY *pkey) 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; const BIGNUM *priv_key, *pub_key;
int mod_len = 0; int mod_len = 0;
if (x->p != NULL) if (x->params.p != NULL)
mod_len = BN_num_bits(x->p); mod_len = DSA_bits(x);
if (ptype == 2) if (ptype == 2)
priv_key = x->priv_key; priv_key = x->priv_key;
@ -358,11 +341,10 @@ static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype)
else else
ktype = "DSA-Parameters"; ktype = "DSA-Parameters";
if (priv_key) { if (priv_key != NULL) {
if (!BIO_indent(bp, off, 128)) if (!BIO_indent(bp, off, 128))
goto err; goto err;
if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) if (BIO_printf(bp, "%s: (%d bit)\n", ktype, mod_len) <= 0)
<= 0)
goto err; goto err;
} else { } else {
if (BIO_printf(bp, "Public-Key: (%d bit)\n", mod_len) <= 0) 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; goto err;
if (!ASN1_bn_print(bp, "pub: ", pub_key, NULL, off)) if (!ASN1_bn_print(bp, "pub: ", pub_key, NULL, off))
goto err; goto err;
if (!ASN1_bn_print(bp, "P: ", x->p, NULL, off)) if (!ffc_params_print(bp, &x->params, 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))
goto err; goto err;
ret = 1; ret = 1;
err: err:
@ -446,7 +424,7 @@ static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
DSA_SIG *dsa_sig; DSA_SIG *dsa_sig;
const unsigned char *p; const unsigned char *p;
if (!sig) { if (sig == NULL) {
if (BIO_puts(bp, "\n") <= 0) if (BIO_puts(bp, "\n") <= 0)
return 0; return 0;
else else
@ -454,7 +432,7 @@ static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
} }
p = sig->data; p = sig->data;
dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length); dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
if (dsa_sig) { if (dsa_sig != NULL) {
int rv = 0; int rv = 0;
const BIGNUM *r, *s; const BIGNUM *r, *s;

View File

@ -34,9 +34,9 @@ static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = { ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = {
ASN1_EMBED(DSA, version, INT32), ASN1_EMBED(DSA, version, INT32),
ASN1_SIMPLE(DSA, p, BIGNUM), ASN1_SIMPLE(DSA, params.p, BIGNUM),
ASN1_SIMPLE(DSA, q, BIGNUM), ASN1_SIMPLE(DSA, params.q, BIGNUM),
ASN1_SIMPLE(DSA, g, BIGNUM), ASN1_SIMPLE(DSA, params.g, BIGNUM),
ASN1_SIMPLE(DSA, pub_key, BIGNUM), ASN1_SIMPLE(DSA, pub_key, BIGNUM),
ASN1_SIMPLE(DSA, priv_key, CBIGNUM) ASN1_SIMPLE(DSA, priv_key, CBIGNUM)
} static_ASN1_SEQUENCE_END_cb(DSA, DSAPrivateKey) } 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) IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAPrivateKey, DSAPrivateKey)
ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = { ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = {
ASN1_SIMPLE(DSA, p, BIGNUM), ASN1_SIMPLE(DSA, params.p, BIGNUM),
ASN1_SIMPLE(DSA, q, BIGNUM), ASN1_SIMPLE(DSA, params.q, BIGNUM),
ASN1_SIMPLE(DSA, g, BIGNUM), ASN1_SIMPLE(DSA, params.g, BIGNUM),
} static_ASN1_SEQUENCE_END_cb(DSA, DSAparams) } static_ASN1_SEQUENCE_END_cb(DSA, DSAparams)
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAparams, DSAparams) IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAparams, DSAparams)
ASN1_SEQUENCE_cb(DSAPublicKey, dsa_cb) = { ASN1_SEQUENCE_cb(DSAPublicKey, dsa_cb) = {
ASN1_SIMPLE(DSA, pub_key, BIGNUM), ASN1_SIMPLE(DSA, pub_key, BIGNUM),
ASN1_SIMPLE(DSA, p, BIGNUM), ASN1_SIMPLE(DSA, params.p, BIGNUM),
ASN1_SIMPLE(DSA, q, BIGNUM), ASN1_SIMPLE(DSA, params.q, BIGNUM),
ASN1_SIMPLE(DSA, g, BIGNUM) ASN1_SIMPLE(DSA, params.g, BIGNUM)
} static_ASN1_SEQUENCE_END_cb(DSA, DSAPublicKey) } static_ASN1_SEQUENCE_END_cb(DSA, DSAPublicKey)
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAPublicKey, DSAPublicKey) IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA, DSAPublicKey, DSAPublicKey)

View File

@ -274,14 +274,16 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
ok = 1; ok = 1;
err: err:
if (ok) { if (ok) {
BN_free(ret->p); BN_free(ret->params.p);
BN_free(ret->q); BN_free(ret->params.q);
BN_free(ret->g); BN_free(ret->params.g);
ret->p = BN_dup(p); ret->params.p = BN_dup(p);
ret->q = BN_dup(q); ret->params.q = BN_dup(q);
ret->g = BN_dup(g); ret->params.g = BN_dup(g);
ret->dirty_cnt++; 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; ok = 0;
goto err; goto err;
} }
@ -343,7 +345,7 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
mdsize = EVP_MD_size(evpmd); mdsize = EVP_MD_size(evpmd);
/* If unverifiable g generation only don't need seed */ /* 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) if (seed_len == 0)
seed_len = mdsize; seed_len = mdsize;
@ -379,9 +381,9 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
goto err; goto err;
/* if p, q already supplied generate g only */ /* if p, q already supplied generate g only */
if (ret->p && ret->q) { if (ret->params.p && ret->params.q) {
p = ret->p; p = ret->params.p;
q = ret->q; q = ret->params.q;
if (idx >= 0) if (idx >= 0)
memcpy(seed_tmp, seed, seed_len); memcpy(seed_tmp, seed, seed_len);
goto g_only; goto g_only;
@ -583,17 +585,19 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
ok = 1; ok = 1;
err: err:
if (ok == 1) { if (ok == 1) {
if (p != ret->p) { if (p != ret->params.p) {
BN_free(ret->p); BN_free(ret->params.p);
ret->p = BN_dup(p); ret->params.p = BN_dup(p);
} }
if (q != ret->q) { if (q != ret->params.q) {
BN_free(ret->q); BN_free(ret->params.q);
ret->q = BN_dup(q); ret->params.q = BN_dup(q);
} }
BN_free(ret->g); BN_free(ret->params.g);
ret->g = BN_dup(g); ret->params.g = BN_dup(g);
if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { if (ret->params.p == NULL
|| ret->params.q == NULL
|| ret->params.g == NULL) {
ok = -1; ok = -1;
goto err; goto err;
} }

View File

@ -38,7 +38,7 @@ static int dsa_builtin_keygen(DSA *dsa)
priv_key = dsa->priv_key; priv_key = dsa->priv_key;
do do
if (!BN_priv_rand_range(priv_key, dsa->q)) if (!BN_priv_rand_range(priv_key, dsa->params.q))
goto err; goto err;
while (BN_is_zero(priv_key)) ; while (BN_is_zero(priv_key)) ;
@ -55,7 +55,7 @@ static int dsa_builtin_keygen(DSA *dsa)
goto err; goto err;
BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); 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); BN_free(prk);
goto err; goto err;
} }

View File

@ -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 * 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 * this file except in compliance with the License. You can obtain a copy
@ -11,11 +11,11 @@
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
#include "internal/refcount.h" #include "internal/refcount.h"
#include <openssl/bn.h> #include <openssl/bn.h>
#include "dsa_local.h"
#include <openssl/asn1.h> #include <openssl/asn1.h>
#include <openssl/engine.h> #include <openssl/engine.h>
#include <openssl/dh.h> #include "dsa_local.h"
#include "crypto/dsa.h" #include "crypto/dsa.h"
#include "crypto/dh.h" /* required by DSA_dup_DH() */
#ifndef FIPS_MODE #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); return CRYPTO_get_ex_data(&d->ex_data, idx);
} }
#ifndef OPENSSL_NO_DH # ifndef OPENSSL_NO_DH
DH *DSA_dup_DH(const DSA *r) DH *DSA_dup_DH(const DSA *r)
{ {
/* /*
* DSA has p, q, g, optional pub_key, optional priv_key. DH has p, * DSA has p, q, g, optional pub_key, optional priv_key.
* optional length, g, optional pub_key, optional priv_key, optional q. * DH has p, optional length, g, optional pub_key,
* optional priv_key, optional q.
*/ */
DH *ret = NULL; 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) if (r == NULL)
goto err; goto err;
ret = DH_new(); ret = DH_new();
if (ret == NULL) if (ret == NULL)
goto err; goto err;
if (r->p != NULL || r->g != NULL || r->q != NULL) {
if (r->p == NULL || r->g == NULL || r->q == NULL) { if (!ffc_params_copy(dh_get0_params(ret), &r->params))
/* Shouldn't happen */ goto err;
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 (r->pub_key != NULL) { if (r->pub_key != NULL) {
pub_key = BN_dup(r->pub_key); pub_key = BN_dup(r->pub_key);
@ -77,29 +68,26 @@ DH *DSA_dup_DH(const DSA *r)
return ret; return ret;
err: err:
BN_free(p);
BN_free(g);
BN_free(q);
BN_free(pub_key); BN_free(pub_key);
BN_free(priv_key); BN_free(priv_key);
DH_free(ret); DH_free(ret);
return NULL; return NULL;
} }
#endif # endif /* OPENSSL_NO_DH */
const BIGNUM *DSA_get0_p(const DSA *d) const BIGNUM *DSA_get0_p(const DSA *d)
{ {
return d->p; return d->params.p;
} }
const BIGNUM *DSA_get0_q(const DSA *d) const BIGNUM *DSA_get0_q(const DSA *d)
{ {
return d->q; return d->params.q;
} }
const BIGNUM *DSA_get0_g(const DSA *d) const BIGNUM *DSA_get0_g(const DSA *d)
{ {
return d->g; return d->params.g;
} }
const BIGNUM *DSA_get0_pub_key(const DSA *d) const BIGNUM *DSA_get0_pub_key(const DSA *d)
@ -250,9 +238,7 @@ void DSA_free(DSA *r)
CRYPTO_THREAD_lock_free(r->lock); CRYPTO_THREAD_lock_free(r->lock);
BN_clear_free(r->p); ffc_params_cleanup(&r->params);
BN_clear_free(r->q);
BN_clear_free(r->g);
BN_clear_free(r->pub_key); BN_clear_free(r->pub_key);
BN_clear_free(r->priv_key); BN_clear_free(r->priv_key);
OPENSSL_free(r); OPENSSL_free(r);
@ -273,12 +259,7 @@ int DSA_up_ref(DSA *r)
void DSA_get0_pqg(const DSA *d, void DSA_get0_pqg(const DSA *d,
const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{ {
if (p != NULL) ffc_params_get0_pqg(&d->params, p, q, g);
*p = d->p;
if (q != NULL)
*q = d->q;
if (g != NULL)
*g = d->g;
} }
int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *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 /* If the fields p, q and g in d are NULL, the corresponding input
* parameters MUST be non-NULL. * parameters MUST be non-NULL.
*/ */
if ((d->p == NULL && p == NULL) if ((d->params.p == NULL && p == NULL)
|| (d->q == NULL && q == NULL) || (d->params.q == NULL && q == NULL)
|| (d->g == NULL && g == NULL)) || (d->params.g == NULL && g == NULL))
return 0; return 0;
if (p != NULL) { ffc_params_set0_pqg(&d->params, p, q, g);
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;
}
d->dirty_cnt++; d->dirty_cnt++;
return 1; 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) int DSA_security_bits(const DSA *d)
{ {
if (d->p && d->q) if (d->params.p != NULL && d->params.q != NULL)
return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q)); return BN_security_bits(BN_num_bits(d->params.p),
BN_num_bits(d->params.q));
return -1; return -1;
} }
int DSA_bits(const DSA *dsa) int DSA_bits(const DSA *dsa)
{ {
return BN_num_bits(dsa->p); return BN_num_bits(dsa->params.p);
} }

View File

@ -9,6 +9,7 @@
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include "internal/refcount.h" #include "internal/refcount.h"
#include "internal/ffc.h"
struct dsa_st { struct dsa_st {
/* /*
@ -17,9 +18,7 @@ struct dsa_st {
*/ */
int pad; int pad;
int32_t version; int32_t version;
BIGNUM *p; FFC_PARAMS params;
BIGNUM *q; /* == 20 */
BIGNUM *g;
BIGNUM *pub_key; /* y public key */ BIGNUM *pub_key; /* y public key */
BIGNUM *priv_key; /* x private key */ BIGNUM *priv_key; /* x private key */
int flags; int flags;

View File

@ -71,7 +71,9 @@ DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst,
DSA_SIG *ret = NULL; DSA_SIG *ret = NULL;
int rv = 0; 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; reason = DSA_R_MISSING_PARAMETERS;
goto err; 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)) if (!dsa_sign_setup(dsa, ctx, &kinv, &ret->r, dgst, dlen))
goto err; 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 * 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, * BN_num_bits(dsa->q) leftmost bits of the digest, see fips 186-3,
* 4.2 * 4.2
*/ */
dlen = BN_num_bytes(dsa->q); dlen = BN_num_bytes(dsa->params.q);
if (BN_bin2bn(dgst, dlen, m) == NULL) if (BN_bin2bn(dgst, dlen, m) == NULL)
goto err; goto err;
@ -124,7 +126,7 @@ DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst,
/* Generate a blinding value */ /* Generate a blinding value */
do { 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)) BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, ctx))
goto err; goto err;
} while (BN_is_zero(blind)); } 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); BN_set_flags(tmp, BN_FLG_CONSTTIME);
/* tmp := blind * priv_key * r mod q */ /* 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; 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; goto err;
/* blindm := blind * m mod q */ /* 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; goto err;
/* s : = (blind * priv_key * r) + (blind * m) mod q */ /* 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; goto err;
/* s := s * k^-1 mod q */ /* 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; goto err;
/* s:= s * blind^-1 mod q */ /* 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; 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; goto err;
/* /*
@ -197,13 +199,15 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
int ret = 0; int ret = 0;
int q_bits, q_words; 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); DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS);
return 0; return 0;
} }
/* Reject obviously invalid parameters */ /* 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); DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_PARAMETERS);
return 0; return 0;
} }
@ -225,8 +229,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
ctx = ctx_in; ctx = ctx_in;
/* Preallocate space */ /* Preallocate space */
q_bits = BN_num_bits(dsa->q); q_bits = BN_num_bits(dsa->params.q);
q_words = bn_get_top(dsa->q); q_words = bn_get_top(dsa->params.q);
if (!bn_wexpand(k, q_words + 2) if (!bn_wexpand(k, q_words + 2)
|| !bn_wexpand(l, q_words + 2)) || !bn_wexpand(l, q_words + 2))
goto err; 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). * We calculate k from SHA512(private_key + H(message) + random).
* This protects the private key from a weak PRNG. * 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)) dlen, ctx))
goto err; 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; goto err;
} while (BN_is_zero(k)); } 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 (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
if (!BN_MONT_CTX_set_locked(&dsa->method_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; 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 * https://github.com/openssl/openssl/pull/7486#discussion_r228323705
* The fix is to rework BN so these gymnastics aren't required. * The fix is to rework BN so these gymnastics aren't required.
*/ */
if (!BN_add(l, k, dsa->q) if (!BN_add(l, k, dsa->params.q)
|| !BN_add(k, l, dsa->q)) || !BN_add(k, l, dsa->params.q))
goto err; goto err;
BN_consttime_swap(BN_is_bit_set(l, q_bits), k, l, q_words + 2); 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 != NULL) {
if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, k, dsa->p, ctx, if (!dsa->meth->bn_mod_exp(dsa, r, dsa->params.g, k, dsa->params.p,
dsa->method_mont_p)) ctx, dsa->method_mont_p))
goto err; goto err;
} else { } 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; goto err;
} }
if (!BN_mod(r, r, dsa->q, ctx)) if (!BN_mod(r, r, dsa->params.q, ctx))
goto err; goto err;
/* Compute part of 's = inv(k) (m + xr) mod q' */ /* 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; goto err;
BN_clear_free(*kinvp); 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; BN_MONT_CTX *mont = NULL;
const BIGNUM *r, *s; const BIGNUM *r, *s;
int ret = -1, i; 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); DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MISSING_PARAMETERS);
return -1; return -1;
} }
i = BN_num_bits(dsa->q); i = BN_num_bits(dsa->params.q);
/* fips 186-3 allows only different sizes for q */ /* fips 186-3 allows only different sizes for q */
if (i != 160 && i != 224 && i != 256) { if (i != 160 && i != 224 && i != 256) {
DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_BAD_Q_VALUE); DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_BAD_Q_VALUE);
return -1; 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); DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MODULUS_TOO_LARGE);
return -1; return -1;
} }
@ -339,12 +346,12 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG_get0(sig, &r, &s); DSA_SIG_get0(sig, &r, &s);
if (BN_is_zero(r) || BN_is_negative(r) || if (BN_is_zero(r) || BN_is_negative(r) ||
BN_ucmp(r, dsa->q) >= 0) { BN_ucmp(r, dsa->params.q) >= 0) {
ret = 0; ret = 0;
goto err; goto err;
} }
if (BN_is_zero(s) || BN_is_negative(s) || if (BN_is_zero(s) || BN_is_negative(s) ||
BN_ucmp(s, dsa->q) >= 0) { BN_ucmp(s, dsa->params.q) >= 0) {
ret = 0; ret = 0;
goto err; 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 * 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; goto err;
/* save M in u1 */ /* save M in u1 */
@ -367,32 +374,32 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
goto err; goto err;
/* u1 = M * w mod q */ /* 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; goto err;
/* u2 = r * w mod q */ /* 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; goto err;
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) { if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
mont = BN_MONT_CTX_set_locked(&dsa->method_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) if (!mont)
goto err; goto err;
} }
if (dsa->meth->dsa_mod_exp != NULL) { if (dsa->meth->dsa_mod_exp != NULL) {
if (!dsa->meth->dsa_mod_exp(dsa, t1, dsa->g, u1, dsa->pub_key, u2, if (!dsa->meth->dsa_mod_exp(dsa, t1, dsa->params.g, u1, dsa->pub_key, u2,
dsa->p, ctx, mont)) dsa->params.p, ctx, mont))
goto err; goto err;
} else { } else {
if (!BN_mod_exp2_mont(t1, dsa->g, u1, dsa->pub_key, u2, dsa->p, ctx, if (!BN_mod_exp2_mont(t1, dsa->params.g, u1, dsa->pub_key, u2,
mont)) dsa->params.p, ctx, mont))
goto err; goto err;
} }
/* let u1 = u1 mod q */ /* let u1 = u1 mod q */
if (!BN_mod(u1, t1, dsa->q, ctx)) if (!BN_mod(u1, t1, dsa->params.q, ctx))
goto err; goto err;
/* /*
@ -413,6 +420,7 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
static int dsa_init(DSA *dsa) static int dsa_init(DSA *dsa)
{ {
dsa->flags |= DSA_FLAG_CACHE_MONT_P; dsa->flags |= DSA_FLAG_CACHE_MONT_P;
ffc_params_init(&dsa->params);
return 1; return 1;
} }

View File

@ -115,7 +115,7 @@ int DSA_size(const DSA *dsa)
int ret; int ret;
DSA_SIG sig; DSA_SIG sig;
sig.r = sig.s = dsa->q; sig.r = sig.s = dsa->params.q;
ret = i2d_DSA_SIG(&sig, NULL); ret = i2d_DSA_SIG(&sig, NULL);
if (ret < 0) if (ret < 0)

6
crypto/ffc/build.info Normal file
View File

@ -0,0 +1,6 @@
LIBS=../../libcrypto
$COMMON=ffc_params.c
SOURCE[../../libcrypto]=$COMMON
SOURCE[../../providers/libfips.a]=$COMMON

191
crypto/ffc/ffc_params.c Normal file
View File

@ -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 <string.h> /* memset */
#include "internal/ffc.h"
#ifndef FIPS_MODE
# include <openssl/asn1.h> /* 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 */

View File

@ -8,8 +8,10 @@
*/ */
#include <openssl/dh.h> #include <openssl/dh.h>
#include "internal/ffc.h"
int dh_compute_key(OPENSSL_CTX *ctx, unsigned char *key, const BIGNUM *pub_key, int dh_compute_key(OPENSSL_CTX *ctx, unsigned char *key, const BIGNUM *pub_key,
DH *dh); DH *dh);
int dh_compute_key_padded(OPENSSL_CTX *ctx, unsigned char *key, int dh_compute_key_padded(OPENSSL_CTX *ctx, unsigned char *key,
const BIGNUM *pub_key, DH *dh); const BIGNUM *pub_key, DH *dh);
FFC_PARAMS *dh_get0_params(DH *dh);

57
include/internal/ffc.h Normal file
View File

@ -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 <openssl/bn.h>
/*
* 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 */