]>
Commit | Line | Data |
---|---|---|
ca2bf555 SL |
1 | /* |
2 | * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
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 | |
8 | */ | |
9 | ||
10 | /* DH parameters from RFC7919 and RFC3526 */ | |
11 | ||
ada66e78 P |
12 | /* |
13 | * DH low level APIs are deprecated for public use, but still ok for | |
14 | * internal use. | |
15 | */ | |
16 | #include "internal/deprecated.h" | |
17 | ||
ca2bf555 SL |
18 | #include <stdio.h> |
19 | #include "internal/cryptlib.h" | |
7165593c | 20 | #include "internal/ffc.h" |
ca2bf555 SL |
21 | #include "dh_local.h" |
22 | #include <openssl/bn.h> | |
23 | #include <openssl/objects.h> | |
24 | #include "crypto/bn_dh.h" | |
8083fd3a | 25 | #include "crypto/dh.h" |
b03ec3b5 | 26 | #include "e_os.h" /* strcasecmp */ |
55f02cb6 | 27 | |
7165593c SL |
28 | #define FFDHE(sz) { \ |
29 | SN_ffdhe##sz, NID_ffdhe##sz, \ | |
30 | sz, \ | |
738ee181 | 31 | &_bignum_ffdhe##sz##_p, &_bignum_ffdhe##sz##_q, &_bignum_const_2 \ |
7165593c SL |
32 | } |
33 | ||
34 | #define MODP(sz) { \ | |
35 | SN_modp_##sz, NID_modp_##sz, \ | |
36 | sz, \ | |
738ee181 | 37 | &_bignum_modp_##sz##_p, &_bignum_modp_##sz##_q, &_bignum_const_2 \ |
7165593c | 38 | } |
55f02cb6 | 39 | |
7165593c SL |
40 | #define RFC5114(name, uid, sz, tag) { \ |
41 | name, uid, \ | |
42 | sz, \ | |
43 | &_bignum_dh##tag##_p, &_bignum_dh##tag##_q, &_bignum_dh##tag##_g \ | |
44 | } | |
55f02cb6 | 45 | |
7165593c | 46 | typedef struct dh_named_group_st { |
b03ec3b5 | 47 | const char *name; |
7165593c | 48 | int uid; |
55f02cb6 SL |
49 | int32_t nbits; |
50 | const BIGNUM *p; | |
7165593c SL |
51 | const BIGNUM *q; |
52 | const BIGNUM *g; | |
53 | } DH_NAMED_GROUP; | |
54 | ||
55f02cb6 | 55 | |
7165593c | 56 | static const DH_NAMED_GROUP dh_named_groups[] = { |
55f02cb6 SL |
57 | FFDHE(2048), |
58 | FFDHE(3072), | |
59 | FFDHE(4096), | |
60 | FFDHE(6144), | |
61 | FFDHE(8192), | |
f844f9eb | 62 | #ifndef FIPS_MODULE |
55f02cb6 SL |
63 | MODP(1536), |
64 | #endif | |
65 | MODP(2048), | |
66 | MODP(3072), | |
67 | MODP(4096), | |
68 | MODP(6144), | |
69 | MODP(8192), | |
7165593c SL |
70 | /* |
71 | * Additional dh named groups from RFC 5114 that have a different g. | |
72 | * The uid can be any unique identifier. | |
73 | */ | |
f844f9eb | 74 | #ifndef FIPS_MODULE |
7165593c SL |
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), | |
78 | #endif | |
55f02cb6 | 79 | }; |
ca2bf555 | 80 | |
7165593c | 81 | int ffc_named_group_to_uid(const char *name) |
b03ec3b5 SL |
82 | { |
83 | size_t i; | |
84 | ||
7165593c SL |
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; | |
b03ec3b5 SL |
88 | } |
89 | return NID_undef; | |
90 | } | |
91 | ||
7165593c | 92 | const char *ffc_named_group_from_uid(int uid) |
b03ec3b5 SL |
93 | { |
94 | size_t i; | |
95 | ||
7165593c SL |
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; | |
b03ec3b5 SL |
99 | } |
100 | return NULL; | |
101 | } | |
102 | ||
7165593c | 103 | static DH *dh_param_init(OPENSSL_CTX *libctx, int uid, const BIGNUM *p, |
738ee181 | 104 | const BIGNUM *q, const BIGNUM *g) |
ca2bf555 | 105 | { |
7165593c | 106 | DH *dh = dh_new_with_libctx(libctx); |
ca2bf555 SL |
107 | |
108 | if (dh == NULL) | |
109 | return NULL; | |
110 | ||
7165593c | 111 | dh->params.nid = uid; |
ca2bf555 | 112 | dh->params.p = (BIGNUM *)p; |
738ee181 | 113 | dh->params.q = (BIGNUM *)q; |
7165593c | 114 | dh->params.g = (BIGNUM *)g; |
738ee181 | 115 | dh->length = BN_num_bits(q); |
ca2bf555 SL |
116 | dh->dirty_cnt++; |
117 | return dh; | |
118 | } | |
119 | ||
7165593c | 120 | static DH *dh_new_by_group_name(OPENSSL_CTX *libctx, const char *name) |
ca2bf555 | 121 | { |
55f02cb6 SL |
122 | int i; |
123 | ||
7165593c SL |
124 | if (name == NULL) |
125 | return NULL; | |
126 | ||
127 | for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) { | |
128 | if (strcasecmp(dh_named_groups[i].name, name) == 0) { | |
7165593c SL |
129 | return dh_param_init(libctx, dh_named_groups[i].uid, |
130 | dh_named_groups[i].p, | |
131 | dh_named_groups[i].q, | |
738ee181 | 132 | dh_named_groups[i].g); |
55f02cb6 | 133 | } |
ca2bf555 | 134 | } |
55f02cb6 SL |
135 | DHerr(0, DH_R_INVALID_PARAMETER_NID); |
136 | return NULL; | |
ca2bf555 SL |
137 | } |
138 | ||
7165593c SL |
139 | DH *dh_new_by_nid_with_libctx(OPENSSL_CTX *libctx, int nid) |
140 | { | |
141 | const char *name = ffc_named_group_from_uid(nid); | |
142 | ||
143 | return dh_new_by_group_name(libctx, name); | |
144 | } | |
145 | ||
8083fd3a SL |
146 | DH *DH_new_by_nid(int nid) |
147 | { | |
7165593c SL |
148 | return dh_new_by_nid_with_libctx(NULL, nid); |
149 | } | |
150 | ||
151 | int ffc_set_group_pqg(FFC_PARAMS *ffc, const char *group_name) | |
152 | { | |
153 | int i; | |
154 | BIGNUM *q = NULL; | |
155 | ||
156 | if (ffc == NULL) | |
157 | return 0; | |
158 | ||
159 | for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) { | |
160 | if (strcasecmp(dh_named_groups[i].name, group_name) == 0) { | |
738ee181 SL |
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); | |
7165593c SL |
165 | /* flush the cached nid, The DH layer is responsible for caching */ |
166 | ffc->nid = NID_undef; | |
167 | return 1; | |
168 | } | |
169 | } | |
170 | /* gets here on error or if the name was not found */ | |
171 | BN_free(q); | |
172 | return 0; | |
8083fd3a | 173 | } |
8083fd3a | 174 | |
738ee181 | 175 | void dh_cache_named_group(DH *dh) |
ca2bf555 | 176 | { |
738ee181 | 177 | int i; |
55f02cb6 SL |
178 | |
179 | if (dh == NULL) | |
738ee181 SL |
180 | return; |
181 | ||
182 | dh->params.nid = NID_undef; /* flush cached value */ | |
ca2bf555 | 183 | |
738ee181 SL |
184 | /* Exit if p or g is not set */ |
185 | if (dh->params.p == NULL | |
186 | || dh->params.g == NULL) | |
187 | return; | |
ca2bf555 | 188 | |
7165593c | 189 | for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) { |
738ee181 SL |
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 */ | |
197 | } else { | |
198 | dh->params.q = (BIGNUM *)dh_named_groups[i].q; | |
199 | } | |
200 | dh->params.nid = dh_named_groups[i].uid; /* cache the nid */ | |
201 | dh->length = BN_num_bits(dh->params.q); | |
202 | dh->dirty_cnt++; | |
203 | break; | |
55f02cb6 | 204 | } |
ca2bf555 | 205 | } |
738ee181 SL |
206 | } |
207 | ||
208 | int DH_get_nid(const DH *dh) | |
209 | { | |
210 | if (dh == NULL) | |
211 | return NID_undef; | |
212 | ||
213 | return dh->params.nid; | |
ca2bf555 | 214 | } |