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 "e_os.h" /* strcasecmp */
29 SN_ffdhe##sz, NID_ffdhe##sz, \
31 &_bignum_ffdhe##sz##_p, &_bignum_ffdhe##sz##_q, &_bignum_const_2 \
35 SN_modp_##sz, NID_modp_##sz, \
37 &_bignum_modp_##sz##_p, &_bignum_modp_##sz##_q, &_bignum_const_2 \
40 #define RFC5114(name, uid, sz, tag) { \
43 &_bignum_dh##tag##_p, &_bignum_dh##tag##_q, &_bignum_dh##tag##_g \
46 typedef struct dh_named_group_st
{
56 static const DH_NAMED_GROUP dh_named_groups
[] = {
71 * Additional dh named groups from RFC 5114 that have a different g.
72 * The uid can be any unique identifier.
75 RFC5114("dh_1024_160", 1, 1024, 1024_160
),
76 RFC5114("dh_2048_224", 2, 2048, 2048_224
),
77 RFC5114("dh_2048_256", 3, 2048, 2048_256
),
81 int ffc_named_group_to_uid(const char *name
)
85 for (i
= 0; i
< OSSL_NELEM(dh_named_groups
); ++i
) {
86 if (strcasecmp(dh_named_groups
[i
].name
, name
) == 0)
87 return dh_named_groups
[i
].uid
;
92 const char *ffc_named_group_from_uid(int uid
)
96 for (i
= 0; i
< OSSL_NELEM(dh_named_groups
); ++i
) {
97 if (dh_named_groups
[i
].uid
== uid
)
98 return dh_named_groups
[i
].name
;
103 static DH
*dh_param_init(OPENSSL_CTX
*libctx
, int uid
, const BIGNUM
*p
,
104 const BIGNUM
*q
, const BIGNUM
*g
)
106 DH
*dh
= dh_new_ex(libctx
);
111 dh
->params
.nid
= uid
;
112 dh
->params
.p
= (BIGNUM
*)p
;
113 dh
->params
.q
= (BIGNUM
*)q
;
114 dh
->params
.g
= (BIGNUM
*)g
;
115 dh
->length
= BN_num_bits(q
);
120 static DH
*dh_new_by_group_name(OPENSSL_CTX
*libctx
, const char *name
)
127 for (i
= 0; i
< (int)OSSL_NELEM(dh_named_groups
); ++i
) {
128 if (strcasecmp(dh_named_groups
[i
].name
, name
) == 0) {
129 return dh_param_init(libctx
, dh_named_groups
[i
].uid
,
130 dh_named_groups
[i
].p
,
131 dh_named_groups
[i
].q
,
132 dh_named_groups
[i
].g
);
135 DHerr(0, DH_R_INVALID_PARAMETER_NID
);
139 DH
*dh_new_by_nid_ex(OPENSSL_CTX
*libctx
, int nid
)
141 const char *name
= ffc_named_group_from_uid(nid
);
143 return dh_new_by_group_name(libctx
, name
);
146 DH
*DH_new_by_nid(int nid
)
148 return dh_new_by_nid_ex(NULL
, nid
);
151 int ffc_set_group_pqg(FFC_PARAMS
*ffc
, const char *group_name
)
159 for (i
= 0; i
< (int)OSSL_NELEM(dh_named_groups
); ++i
) {
160 if (strcasecmp(dh_named_groups
[i
].name
, group_name
) == 0) {
161 ffc_params_set0_pqg(ffc
,
162 (BIGNUM
*)dh_named_groups
[i
].p
,
163 (BIGNUM
*)dh_named_groups
[i
].q
,
164 (BIGNUM
*)dh_named_groups
[i
].g
);
165 /* flush the cached nid, The DH layer is responsible for caching */
166 ffc
->nid
= NID_undef
;
170 /* gets here on error or if the name was not found */
175 void dh_cache_named_group(DH
*dh
)
182 dh
->params
.nid
= NID_undef
; /* flush cached value */
184 /* Exit if p or g is not set */
185 if (dh
->params
.p
== NULL
186 || dh
->params
.g
== NULL
)
189 for (i
= 0; i
< (int)OSSL_NELEM(dh_named_groups
); ++i
) {
190 /* Keep searching until a matching p and g is found */
191 if (BN_cmp(dh
->params
.p
, dh_named_groups
[i
].p
) == 0
192 && BN_cmp(dh
->params
.g
, dh_named_groups
[i
].g
) == 0) {
193 /* Verify q is correct if it exists */
194 if (dh
->params
.q
!= NULL
) {
195 if (BN_cmp(dh
->params
.q
, dh_named_groups
[i
].q
) != 0)
196 continue; /* ignore if q does not match */
198 dh
->params
.q
= (BIGNUM
*)dh_named_groups
[i
].q
;
200 dh
->params
.nid
= dh_named_groups
[i
].uid
; /* cache the nid */
201 dh
->length
= BN_num_bits(dh
->params
.q
);
208 int DH_get_nid(const DH
*dh
)
213 return dh
->params
.nid
;