Add DH keygen to providers
[openssl.git] / crypto / dh / dh_group_params.c
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
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
18 #include <stdio.h>
19 #include "internal/cryptlib.h"
20 #include "internal/ffc.h"
21 #include "dh_local.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 */
28
29 #define FFDHE(sz) {                                                            \
30     SN_ffdhe##sz, NID_ffdhe##sz,                                               \
31     sz,                                                                        \
32     &_bignum_ffdhe##sz##_p, NULL, &_bignum_const_2                             \
33 }
34
35 #define MODP(sz)  {                                                            \
36     SN_modp_##sz, NID_modp_##sz,                                               \
37     sz,                                                                        \
38     &_bignum_modp_##sz##_p, NULL,  &_bignum_const_2                            \
39 }
40
41 #define RFC5114(name, uid, sz, tag)  {                                         \
42     name, uid,                                                                 \
43     sz,                                                                        \
44     &_bignum_dh##tag##_p, &_bignum_dh##tag##_q, &_bignum_dh##tag##_g           \
45 }
46
47 typedef struct dh_named_group_st {
48     const char *name;
49     int uid;
50     int32_t nbits;
51     const BIGNUM *p;
52     const BIGNUM *q;
53     const BIGNUM *g;
54 } DH_NAMED_GROUP;
55
56
57 static const DH_NAMED_GROUP dh_named_groups[] = {
58     FFDHE(2048),
59     FFDHE(3072),
60     FFDHE(4096),
61     FFDHE(6144),
62     FFDHE(8192),
63 #ifndef FIPS_MODE
64     MODP(1536),
65 #endif
66     MODP(2048),
67     MODP(3072),
68     MODP(4096),
69     MODP(6144),
70     MODP(8192),
71     /*
72      * Additional dh named groups from RFC 5114 that have a different g.
73      * The uid can be any unique identifier.
74      */
75 #ifndef FIPS_MODE
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),
79 #endif
80 };
81
82 int ffc_named_group_to_uid(const char *name)
83 {
84     size_t i;
85
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;
89     }
90     return NID_undef;
91 }
92
93 const char *ffc_named_group_from_uid(int uid)
94 {
95     size_t i;
96
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;
100     }
101     return NULL;
102 }
103
104 static DH *dh_param_init(OPENSSL_CTX *libctx, int uid, const BIGNUM *p,
105                          const BIGNUM *q, const BIGNUM *g,
106                          int32_t nbits)
107 {
108     BIGNUM *qtmp = NULL;
109     DH *dh = dh_new_with_libctx(libctx);
110
111     if (dh == NULL)
112         return NULL;
113
114     if (q == NULL) {
115         qtmp = BN_dup(p);
116         /* Set q = (p - 1) / 2 (p is known to be odd so just shift right ) */
117         if (qtmp == NULL || !BN_rshift1(qtmp, qtmp)) {
118             BN_free(qtmp);
119             DH_free(dh);
120             return NULL;
121         }
122     }
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 */
128     dh->length = nbits;
129     dh->dirty_cnt++;
130     return dh;
131 }
132
133 static DH *dh_new_by_group_name(OPENSSL_CTX *libctx, const char *name)
134 {
135     int i;
136
137     if (name == NULL)
138         return NULL;
139
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);
144
145             /*
146              * The last parameter specified here is
147              * 2 * max_target_security_strength.
148              * See SP800-56Ar3 Table(s) 25 & 26.
149              */
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);
155         }
156     }
157     DHerr(0, DH_R_INVALID_PARAMETER_NID);
158     return NULL;
159 }
160
161 DH *dh_new_by_nid_with_libctx(OPENSSL_CTX *libctx, int nid)
162 {
163     const char *name = ffc_named_group_from_uid(nid);
164
165     return dh_new_by_group_name(libctx, name);
166 }
167
168 DH *DH_new_by_nid(int nid)
169 {
170     return dh_new_by_nid_with_libctx(NULL, nid);
171 }
172
173 int ffc_set_group_pqg(FFC_PARAMS *ffc, const char *group_name)
174 {
175     int i;
176     BIGNUM *q = NULL;
177
178     if (ffc == NULL)
179         return 0;
180
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);
189             } else {
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 */
195
196                 ffc_params_set0_pqg(ffc,
197                                     (BIGNUM *)dh_named_groups[i].p, q,
198                                     (BIGNUM *)dh_named_groups[i].g);
199             }
200             /* flush the cached nid, The DH layer is responsible for caching */
201             ffc->nid = NID_undef;
202             return 1;
203         }
204     }
205     /* gets here on error or if the name was not found */
206     BN_free(q);
207     return 0;
208 }
209
210 int DH_get_nid(DH *dh)
211 {
212     BIGNUM *q = NULL;
213     int i, nid;
214
215     if (dh == NULL)
216         return NID_undef;
217
218     nid = dh->params.nid;
219     /* Just return if it is already cached */
220     if (nid != NID_undef)
221         return nid;
222
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)
226             continue;
227
228         /* Return an error if g is not matching */
229         if (BN_cmp(dh->params.g, dh_named_groups[i].g) != 0)
230             break;
231         if (dh_named_groups[i].q != NULL) {
232             /* RFC5114 NAMED GROUPS have q defined */
233
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 */
238             } else {
239                 dh->params.q = (BIGNUM *)dh_named_groups[i].q;
240             }
241         } else {
242             /* For SAFE PRIME GROUPS */
243
244             /* Set q = (p - 1) / 2 (p is known to be odd so just shift right) */
245             q = BN_dup(dh->params.p);
246
247             if (q == NULL || !BN_rshift1(q, q))
248                 break; /* returns nid = NID_undef on failure */
249
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 */
254             } else {
255                 /* assign the calculated q */
256                 dh->params.q = q;
257                 q = NULL; /* set to NULL so it is not freed */
258             }
259         }
260         nid = dh->params.nid = dh_named_groups[i].uid; /* cache the nid */
261         dh->length =
262             2 * ifc_ffc_compute_security_bits(dh_named_groups[i].nbits);
263         dh->dirty_cnt++;
264         /* A matching p was found so break out of the loop */
265         break;
266     }
267     BN_free(q);
268     return nid;
269 }