2 * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 /* DH parameters from RFC7919 and RFC3526 */
13 * DH low level APIs are deprecated for public use, but still ok for
16 #include "internal/deprecated.h"
19 #include "internal/cryptlib.h"
20 #include "internal/ffc.h"
22 #include <openssl/bn.h>
23 #include <openssl/objects.h>
24 #include "crypto/bn_dh.h"
25 #include "crypto/dh.h"
26 #include "crypto/security_bits.h"
27 #include "e_os.h" /* strcasecmp */
30 SN_ffdhe##sz, NID_ffdhe##sz, \
32 &_bignum_ffdhe##sz##_p, NULL, &_bignum_const_2 \
36 SN_modp_##sz, NID_modp_##sz, \
38 &_bignum_modp_##sz##_p, NULL, &_bignum_const_2 \
41 #define RFC5114(name, uid, sz, tag) { \
44 &_bignum_dh##tag##_p, &_bignum_dh##tag##_q, &_bignum_dh##tag##_g \
47 typedef struct dh_named_group_st {
57 static const DH_NAMED_GROUP dh_named_groups[] = {
72 * Additional dh named groups from RFC 5114 that have a different g.
73 * The uid can be any unique identifier.
76 RFC5114("dh_1024_160", 1, 1024, 1024_160),
77 RFC5114("dh_2048_224", 2, 2048, 2048_224),
78 RFC5114("dh_2048_256", 3, 2048, 2048_256),
82 int ffc_named_group_to_uid(const char *name)
86 for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
87 if (strcasecmp(dh_named_groups[i].name, name) == 0)
88 return dh_named_groups[i].uid;
93 const char *ffc_named_group_from_uid(int uid)
97 for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
98 if (dh_named_groups[i].uid == uid)
99 return dh_named_groups[i].name;
104 static DH *dh_param_init(OPENSSL_CTX *libctx, int uid, const BIGNUM *p,
105 const BIGNUM *q, const BIGNUM *g,
109 DH *dh = dh_new_with_libctx(libctx);
116 /* Set q = (p - 1) / 2 (p is known to be odd so just shift right ) */
117 if (qtmp == NULL || !BN_rshift1(qtmp, qtmp)) {
123 dh->params.nid = uid;
124 dh->params.p = (BIGNUM *)p;
125 dh->params.q = (q != NULL ? (BIGNUM *)q : qtmp);
126 dh->params.g = (BIGNUM *)g;
127 /* Private key length = 2 * max_target_security_strength */
133 static DH *dh_new_by_group_name(OPENSSL_CTX *libctx, const char *name)
140 for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) {
141 if (strcasecmp(dh_named_groups[i].name, name) == 0) {
142 int max_target_security_strength =
143 ifc_ffc_compute_security_bits(dh_named_groups[i].nbits);
146 * The last parameter specified here is
147 * 2 * max_target_security_strength.
148 * See SP800-56Ar3 Table(s) 25 & 26.
150 return dh_param_init(libctx, dh_named_groups[i].uid,
151 dh_named_groups[i].p,
152 dh_named_groups[i].q,
153 dh_named_groups[i].g,
154 2 * max_target_security_strength);
157 DHerr(0, DH_R_INVALID_PARAMETER_NID);
161 DH *dh_new_by_nid_with_libctx(OPENSSL_CTX *libctx, int nid)
163 const char *name = ffc_named_group_from_uid(nid);
165 return dh_new_by_group_name(libctx, name);
168 DH *DH_new_by_nid(int nid)
170 return dh_new_by_nid_with_libctx(NULL, nid);
173 int ffc_set_group_pqg(FFC_PARAMS *ffc, const char *group_name)
181 for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) {
182 if (strcasecmp(dh_named_groups[i].name, group_name) == 0) {
183 if (dh_named_groups[i].q != NULL) {
184 /* For groups with a q */
185 ffc_params_set0_pqg(ffc,
186 (BIGNUM *)dh_named_groups[i].p,
187 (BIGNUM *)dh_named_groups[i].q,
188 (BIGNUM *)dh_named_groups[i].g);
190 /* For SAFE PRIME GROUPS */
191 /* Set q = (p - 1) / 2 (p is known to be odd so just shift right) */
192 q = BN_dup(dh_named_groups[i].p);
193 if (q == NULL || !BN_rshift1(q, q))
194 break; /* exit with failure */
196 ffc_params_set0_pqg(ffc,
197 (BIGNUM *)dh_named_groups[i].p, q,
198 (BIGNUM *)dh_named_groups[i].g);
200 /* flush the cached nid, The DH layer is responsible for caching */
201 ffc->nid = NID_undef;
205 /* gets here on error or if the name was not found */
210 int DH_get_nid(DH *dh)
218 nid = dh->params.nid;
219 /* Just return if it is already cached */
220 if (nid != NID_undef)
223 for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) {
224 /* Keep searching until a matching p is found */
225 if (BN_cmp(dh->params.p, dh_named_groups[i].p) != 0)
228 /* Return an error if g is not matching */
229 if (BN_cmp(dh->params.g, dh_named_groups[i].g) != 0)
231 if (dh_named_groups[i].q != NULL) {
232 /* RFC5114 NAMED GROUPS have q defined */
234 /* Verify q is correct if it exists */
235 if (dh->params.q != NULL) {
236 if (BN_cmp(dh->params.q, dh_named_groups[i].q) != 0)
237 break; /* returns nid = NID_undef if q does not match */
239 dh->params.q = (BIGNUM *)dh_named_groups[i].q;
242 /* For SAFE PRIME GROUPS */
244 /* Set q = (p - 1) / 2 (p is known to be odd so just shift right) */
245 q = BN_dup(dh->params.p);
247 if (q == NULL || !BN_rshift1(q, q))
248 break; /* returns nid = NID_undef on failure */
250 /* Verify q is correct if it exists */
251 if (dh->params.q != NULL) {
252 if (BN_cmp(dh->params.q, q) != 0)
253 break; /* returns nid = NID_undef if q does not match */
255 /* assign the calculated q */
257 q = NULL; /* set to NULL so it is not freed */
260 nid = dh->params.nid = dh_named_groups[i].uid; /* cache the nid */
262 2 * ifc_ffc_compute_security_bits(dh_named_groups[i].nbits);
264 /* A matching p was found so break out of the loop */