From 7806a782c87f8ce07bc710f480a1db9511d11506 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Tue, 30 May 2017 01:16:56 +0100 Subject: [PATCH] DH named parameter support Add functions to return DH parameters using NID and to return the NID if parameters match a named set. Currently this supports only RFC7919 parameters but could be expanded in future. Reviewed-by: Andy Polyakov (Merged from https://github.com/openssl/openssl/pull/4485) --- crypto/bn/bn_dh.c | 4 ++ crypto/dh/build.info | 3 +- crypto/dh/dh_rfc7919.c | 75 +++++++++++++++++++++++++++++++++ crypto/include/internal/bn_dh.h | 7 +++ include/openssl/dh.h | 4 ++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 crypto/dh/dh_rfc7919.c diff --git a/crypto/bn/bn_dh.c b/crypto/bn/bn_dh.c index 652545d89c..38acdee234 100644 --- a/crypto/bn/bn_dh.c +++ b/crypto/bn/bn_dh.c @@ -487,6 +487,10 @@ static const BN_ULONG ffdhe8192_p[] = { OSSL_NELEM(x),\ 0, BN_FLG_STATIC_DATA }; +static const BN_ULONG value_2 = 2; + +const BIGNUM _bignum_const_2 = + { (BN_ULONG *)&value_2, 1, 1, 0, BN_FLG_STATIC_DATA }; make_dh_bn(dh1024_160_p) make_dh_bn(dh1024_160_g) diff --git a/crypto/dh/build.info b/crypto/dh/build.info index dba93066ae..b19ff6dbac 100644 --- a/crypto/dh/build.info +++ b/crypto/dh/build.info @@ -1,4 +1,5 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=\ dh_asn1.c dh_gen.c dh_key.c dh_lib.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_ameth.c dh_pmeth.c dh_prn.c dh_rfc5114.c dh_kdf.c dh_meth.c \ + dh_rfc7919.c diff --git a/crypto/dh/dh_rfc7919.c b/crypto/dh/dh_rfc7919.c new file mode 100644 index 0000000000..d01ba6fdf3 --- /dev/null +++ b/crypto/dh/dh_rfc7919.c @@ -0,0 +1,75 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include "dh_locl.h" +#include +#include +#include "internal/bn_dh.h" + +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->length = nbits; + 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->g) != 2) + return NID_undef; + if (!BN_cmp(dh->p, &_bignum_ffdhe2048_p)) + nid = NID_ffdhe2048; + else if (!BN_cmp(dh->p, &_bignum_ffdhe3072_p)) + nid = NID_ffdhe3072; + else if (!BN_cmp(dh->p, &_bignum_ffdhe4096_p)) + nid = NID_ffdhe4096; + else if (!BN_cmp(dh->p, &_bignum_ffdhe6144_p)) + nid = NID_ffdhe6144; + else if (!BN_cmp(dh->p, &_bignum_ffdhe8192_p)) + nid = NID_ffdhe8192; + else + return NID_undef; + if (dh->q != NULL) { + BIGNUM *q = BN_dup(dh->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)) { + BN_free(q); + return NID_undef; + } + } + return nid; +} diff --git a/crypto/include/internal/bn_dh.h b/crypto/include/internal/bn_dh.h index f49f039835..70ebca2875 100644 --- a/crypto/include/internal/bn_dh.h +++ b/crypto/include/internal/bn_dh.h @@ -15,3 +15,10 @@ declare_dh_bn(1024_160) declare_dh_bn(2048_224) declare_dh_bn(2048_256) + +extern const BIGNUM _bignum_ffdhe2048_p; +extern const BIGNUM _bignum_ffdhe3072_p; +extern const BIGNUM _bignum_ffdhe4096_p; +extern const BIGNUM _bignum_ffdhe6144_p; +extern const BIGNUM _bignum_ffdhe8192_p; +extern const BIGNUM _bignum_const_2; diff --git a/include/openssl/dh.h b/include/openssl/dh.h index ebd936a90b..95c708188d 100644 --- a/include/openssl/dh.h +++ b/include/openssl/dh.h @@ -162,6 +162,10 @@ DH *DH_get_1024_160(void); DH *DH_get_2048_224(void); DH *DH_get_2048_256(void); +/* Named parameters, currently RFC7919 */ +DH *DH_new_by_nid(int nid); +int DH_get_nid(const DH *dh); + # ifndef OPENSSL_NO_CMS /* RFC2631 KDF */ int DH_KDF_X9_42(unsigned char *out, size_t outlen, -- 2.34.1