diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-01-31 08:18:46 +1000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2020-01-31 08:18:46 +1000 |
commit | ca2bf555cd64bc9624af1259ce3cd27f95a5763e (patch) | |
tree | e02beb157e56973ada62c679cb7b3b8756e86dfe /crypto/dh | |
parent | cd624ccd41ac3ac779c1c7a7a1e63427ce9588dd (diff) |
Add support for DH 'modp' group parameters (RFC 3526)
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10897)
Diffstat (limited to 'crypto/dh')
-rw-r--r-- | crypto/dh/build.info | 5 | ||||
-rw-r--r-- | crypto/dh/dh_asn1.c | 2 | ||||
-rw-r--r-- | crypto/dh/dh_group_params.c | 129 | ||||
-rw-r--r-- | crypto/dh/dh_lib.c | 6 | ||||
-rw-r--r-- | crypto/dh/dh_pmeth.c | 33 | ||||
-rw-r--r-- | crypto/dh/dh_rfc7919.c | 75 |
6 files changed, 158 insertions, 92 deletions
diff --git a/crypto/dh/build.info b/crypto/dh/build.info index 924ca8f92f..bb71f4a16b 100644 --- a/crypto/dh/build.info +++ b/crypto/dh/build.info @@ -1,10 +1,9 @@ LIBS=../../libcrypto -$COMMON=dh_lib.c dh_key.c +$COMMON=dh_lib.c dh_key.c dh_group_params.c SOURCE[../../libcrypto]=$COMMON\ dh_asn1.c dh_gen.c dh_check.c dh_err.c dh_depr.c \ - dh_ameth.c dh_pmeth.c dh_prn.c dh_rfc5114.c dh_kdf.c dh_meth.c \ - dh_rfc7919.c + dh_ameth.c dh_pmeth.c dh_prn.c dh_rfc5114.c dh_kdf.c dh_meth.c SOURCE[../../providers/libfips.a]=$COMMON diff --git a/crypto/dh/dh_asn1.c b/crypto/dh/dh_asn1.c index 75f2dd5bde..ec589757d0 100644 --- a/crypto/dh/dh_asn1.c +++ b/crypto/dh/dh_asn1.c @@ -100,7 +100,7 @@ DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length) } params = &dh->params; - ffc_params_set0_pqg(params, dhx->p, dhx->q, dhx->g); + DH_set0_pqg(dh, dhx->p, dhx->q, dhx->g); ffc_params_set0_j(params, dhx->j); if (dhx->vparams != NULL) { diff --git a/crypto/dh/dh_group_params.c b/crypto/dh/dh_group_params.c new file mode 100644 index 0000000000..4996e854f5 --- /dev/null +++ b/crypto/dh/dh_group_params.c @@ -0,0 +1,129 @@ +/* + * Copyright 2017-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 + */ + +/* DH parameters from RFC7919 and RFC3526 */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include "dh_local.h" +#include <openssl/bn.h> +#include <openssl/objects.h> +#include "crypto/bn_dh.h" + +static DH *dh_param_init(int nid, const BIGNUM *p, int32_t nbits) +{ + BIGNUM *q = NULL; + DH *dh = DH_new(); + + if (dh == NULL) + return NULL; + + q = BN_dup(p); + /* Set q = (p - 1) / 2 (p is known to be odd so just shift right ) */ + if (q == NULL || !BN_rshift1(q, q)) { + BN_free(q); + DH_free(dh); + return NULL; + } + dh->params.nid = nid; + dh->params.p = (BIGNUM *)p; + dh->params.q = (BIGNUM *)q; + dh->params.g = (BIGNUM *)&_bignum_const_2; + /* Private key length = 2 * max_target_security_strength */ + dh->length = nbits; + dh->dirty_cnt++; + return dh; +} + +DH *DH_new_by_nid(int nid) +{ + /* + * The last parameter specified in these fields is + * 2 * max_target_security_strength. + * See SP800-56Ar3 Table(s) 25 & 26. + */ + switch (nid) { + case NID_ffdhe2048: + return dh_param_init(nid, &_bignum_ffdhe2048_p, 225); + case NID_ffdhe3072: + return dh_param_init(nid, &_bignum_ffdhe3072_p, 275); + case NID_ffdhe4096: + return dh_param_init(nid, &_bignum_ffdhe4096_p, 325); + case NID_ffdhe6144: + return dh_param_init(nid, &_bignum_ffdhe6144_p, 375); + case NID_ffdhe8192: + return dh_param_init(nid, &_bignum_ffdhe8192_p, 400); +#ifndef FIPS_MODE + case NID_modp_1536: + return dh_param_init(nid, &_bignum_modp_1536_p, 190); +#endif + case NID_modp_2048: + return dh_param_init(nid, &_bignum_modp_2048_p, 225); + case NID_modp_3072: + return dh_param_init(nid, &_bignum_modp_3072_p, 275); + case NID_modp_4096: + return dh_param_init(nid, &_bignum_modp_4096_p, 325); + case NID_modp_6144: + return dh_param_init(nid, &_bignum_modp_6144_p, 375); + case NID_modp_8192: + return dh_param_init(nid, &_bignum_modp_8192_p, 400); + default: + DHerr(DH_F_DH_NEW_BY_NID, DH_R_INVALID_PARAMETER_NID); + return NULL; + } +} + +int DH_get_nid(DH *dh) +{ + int nid = dh->params.nid; + + if (nid != NID_undef) + return nid; + + if (BN_get_word(dh->params.g) != 2) + return NID_undef; + if (!BN_cmp(dh->params.p, &_bignum_ffdhe2048_p)) + nid = NID_ffdhe2048; + else if (!BN_cmp(dh->params.p, &_bignum_ffdhe3072_p)) + nid = NID_ffdhe3072; + else if (!BN_cmp(dh->params.p, &_bignum_ffdhe4096_p)) + nid = NID_ffdhe4096; + else if (!BN_cmp(dh->params.p, &_bignum_ffdhe6144_p)) + nid = NID_ffdhe6144; + else if (!BN_cmp(dh->params.p, &_bignum_ffdhe8192_p)) + nid = NID_ffdhe8192; +#ifndef FIPS_MODE + else if (!BN_cmp(dh->params.p, &_bignum_modp_1536_p)) + nid = NID_modp_1536; +#endif + else if (!BN_cmp(dh->params.p, &_bignum_modp_2048_p)) + nid = NID_modp_2048; + else if (!BN_cmp(dh->params.p, &_bignum_modp_3072_p)) + nid = NID_modp_3072; + else if (!BN_cmp(dh->params.p, &_bignum_modp_4096_p)) + nid = NID_modp_4096; + else if (!BN_cmp(dh->params.p, &_bignum_modp_6144_p)) + nid = NID_modp_6144; + else if (!BN_cmp(dh->params.p, &_bignum_modp_8192_p)) + nid = NID_modp_8192; + else + return NID_undef; + + /* Verify q is correct if it exists - reset the nid if it is not correct */ + 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->params.q, q) != 0)) + nid = NID_undef; + BN_free(q); + } + dh->params.nid = nid; /* cache the nid */ + return nid; +} diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index 2f5aa10401..f9fb1d9b71 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -191,6 +191,8 @@ int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) return 0; ffc_params_set0_pqg(&dh->params, p, q, g); + dh->params.nid = NID_undef; + DH_get_nid(dh); /* Check if this is a named group and cache it */ if (q != NULL) dh->length = BN_num_bits(q); @@ -284,3 +286,7 @@ FFC_PARAMS *dh_get0_params(DH *dh) { return &dh->params; } +int dh_get0_nid(const DH *dh) +{ + return dh->params.nid; +} diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c index 55d11d638b..4afedb95f6 100644 --- a/crypto/dh/dh_pmeth.c +++ b/crypto/dh/dh_pmeth.c @@ -329,8 +329,21 @@ static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { DH *dh = NULL; DH_PKEY_CTX *dctx = ctx->data; - BN_GENCB *pcb; + BN_GENCB *pcb = NULL; int ret; + + /* + * Look for a safe prime group for key establishment. Which uses + * either RFC_3526 (modp_XXXX) or RFC_7919 (ffdheXXXX). + */ + if (dctx->param_nid != NID_undef) { + if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL) + return 0; + EVP_PKEY_assign(pkey, EVP_PKEY_DH, dh); + return 1; + } + +#ifndef FIPS_MODE if (dctx->rfc5114_param) { switch (dctx->rfc5114_param) { case 1: @@ -351,24 +364,18 @@ static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); return 1; } +#endif /* FIPS_MODE */ - if (dctx->param_nid != 0) { - if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL) - return 0; - EVP_PKEY_assign(pkey, EVP_PKEY_DH, dh); - return 1; - } - - if (ctx->pkey_gencb) { + if (ctx->pkey_gencb != NULL) { pcb = BN_GENCB_new(); if (pcb == NULL) return 0; evp_pkey_set_cb_translate(pcb, ctx); - } else - pcb = NULL; + } #ifndef OPENSSL_NO_DSA if (dctx->use_dsa) { DSA *dsa_dh; + dsa_dh = dsa_dh_generate(dctx, pcb); BN_GENCB_free(pcb); if (dsa_dh == NULL) @@ -401,11 +408,11 @@ static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) DH_PKEY_CTX *dctx = ctx->data; DH *dh = NULL; - if (ctx->pkey == NULL && dctx->param_nid == 0) { + if (ctx->pkey == NULL && dctx->param_nid == NID_undef) { DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); return 0; } - if (dctx->param_nid != 0) + if (dctx->param_nid != NID_undef) dh = DH_new_by_nid(dctx->param_nid); else dh = DH_new(); diff --git a/crypto/dh/dh_rfc7919.c b/crypto/dh/dh_rfc7919.c deleted file mode 100644 index 92e5000e28..0000000000 --- a/crypto/dh/dh_rfc7919.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2017 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 <stdio.h> -#include "internal/cryptlib.h" -#include "dh_local.h" -#include <openssl/bn.h> -#include <openssl/objects.h> -#include "crypto/bn_dh.h" - -static DH *dh_param_init(const BIGNUM *p, int32_t nbits) -{ - DH *dh = DH_new(); - if (dh == NULL) - return NULL; - dh->params.p = (BIGNUM *)p; - dh->params.g = (BIGNUM *)&_bignum_const_2; - dh->length = nbits; - dh->dirty_cnt++; - return dh; -} - -DH *DH_new_by_nid(int nid) -{ - switch (nid) { - case NID_ffdhe2048: - return dh_param_init(&_bignum_ffdhe2048_p, 225); - case NID_ffdhe3072: - return dh_param_init(&_bignum_ffdhe3072_p, 275); - case NID_ffdhe4096: - return dh_param_init(&_bignum_ffdhe4096_p, 325); - case NID_ffdhe6144: - return dh_param_init(&_bignum_ffdhe6144_p, 375); - case NID_ffdhe8192: - return dh_param_init(&_bignum_ffdhe8192_p, 400); - default: - DHerr(DH_F_DH_NEW_BY_NID, DH_R_INVALID_PARAMETER_NID); - return NULL; - } -} - -int DH_get_nid(const DH *dh) -{ - int nid; - - if (BN_get_word(dh->params.g) != 2) - return NID_undef; - if (!BN_cmp(dh->params.p, &_bignum_ffdhe2048_p)) - nid = NID_ffdhe2048; - else if (!BN_cmp(dh->params.p, &_bignum_ffdhe3072_p)) - nid = NID_ffdhe3072; - else if (!BN_cmp(dh->params.p, &_bignum_ffdhe4096_p)) - nid = NID_ffdhe4096; - else if (!BN_cmp(dh->params.p, &_bignum_ffdhe6144_p)) - nid = NID_ffdhe6144; - else if (!BN_cmp(dh->params.p, &_bignum_ffdhe8192_p)) - nid = NID_ffdhe8192; - else - return NID_undef; - 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->params.q, q)) - nid = NID_undef; - BN_free(q); - } - return nid; -} |