xref: /openssl/crypto/dh/dh_pmeth.c (revision eb7a5cc3)
1 /*
2  * Copyright 2006-2021 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 /*
11  * DH & DSA low level APIs are deprecated for public use, but still ok for
12  * internal use.
13  */
14 #include "internal/deprecated.h"
15 
16 #include <stdio.h>
17 #include "internal/cryptlib.h"
18 #include <openssl/asn1t.h>
19 #include <openssl/x509.h>
20 #include <openssl/evp.h>
21 #include "dh_local.h"
22 #include <openssl/bn.h>
23 #include <openssl/dsa.h>
24 #include <openssl/objects.h>
25 #include "crypto/evp.h"
26 
27 /* DH pkey context structure */
28 
29 typedef struct {
30     /* Parameter gen parameters */
31     int prime_len;
32     int generator;
33     int paramgen_type;
34     int subprime_len;
35     int pad;
36     /* message digest used for parameter generation */
37     const EVP_MD *md;
38     int param_nid;
39     /* Keygen callback info */
40     int gentmp[2];
41     /* KDF (if any) to use for DH */
42     char kdf_type;
43     /* OID to use for KDF */
44     ASN1_OBJECT *kdf_oid;
45     /* Message digest to use for key derivation */
46     const EVP_MD *kdf_md;
47     /* User key material */
48     unsigned char *kdf_ukm;
49     size_t kdf_ukmlen;
50     /* KDF output length */
51     size_t kdf_outlen;
52 } DH_PKEY_CTX;
53 
pkey_dh_init(EVP_PKEY_CTX * ctx)54 static int pkey_dh_init(EVP_PKEY_CTX *ctx)
55 {
56     DH_PKEY_CTX *dctx;
57 
58     if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
59         ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
60         return 0;
61     }
62     dctx->prime_len = 2048;
63     dctx->subprime_len = -1;
64     dctx->generator = 2;
65     dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
66 
67     ctx->data = dctx;
68     ctx->keygen_info = dctx->gentmp;
69     ctx->keygen_info_count = 2;
70 
71     return 1;
72 }
73 
pkey_dh_cleanup(EVP_PKEY_CTX * ctx)74 static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
75 {
76     DH_PKEY_CTX *dctx = ctx->data;
77 
78     if (dctx != NULL) {
79         OPENSSL_free(dctx->kdf_ukm);
80         ASN1_OBJECT_free(dctx->kdf_oid);
81         OPENSSL_free(dctx);
82     }
83 }
84 
85 
pkey_dh_copy(EVP_PKEY_CTX * dst,const EVP_PKEY_CTX * src)86 static int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
87 {
88     DH_PKEY_CTX *dctx, *sctx;
89 
90     if (!pkey_dh_init(dst))
91         return 0;
92     sctx = src->data;
93     dctx = dst->data;
94     dctx->prime_len = sctx->prime_len;
95     dctx->subprime_len = sctx->subprime_len;
96     dctx->generator = sctx->generator;
97     dctx->paramgen_type = sctx->paramgen_type;
98     dctx->pad = sctx->pad;
99     dctx->md = sctx->md;
100     dctx->param_nid = sctx->param_nid;
101 
102     dctx->kdf_type = sctx->kdf_type;
103     dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
104     if (dctx->kdf_oid == NULL)
105         return 0;
106     dctx->kdf_md = sctx->kdf_md;
107     if (sctx->kdf_ukm != NULL) {
108         dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
109         if (dctx->kdf_ukm == NULL)
110           return 0;
111         dctx->kdf_ukmlen = sctx->kdf_ukmlen;
112     }
113     dctx->kdf_outlen = sctx->kdf_outlen;
114     return 1;
115 }
116 
pkey_dh_ctrl(EVP_PKEY_CTX * ctx,int type,int p1,void * p2)117 static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
118 {
119     DH_PKEY_CTX *dctx = ctx->data;
120     switch (type) {
121     case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
122         if (p1 < 256)
123             return -2;
124         dctx->prime_len = p1;
125         return 1;
126 
127     case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
128         if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR)
129             return -2;
130         dctx->subprime_len = p1;
131         return 1;
132 
133     case EVP_PKEY_CTRL_DH_PAD:
134         dctx->pad = p1;
135         return 1;
136 
137     case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
138         if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR)
139             return -2;
140         dctx->generator = p1;
141         return 1;
142 
143     case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
144 #ifdef OPENSSL_NO_DSA
145         if (p1 != DH_PARAMGEN_TYPE_GENERATOR)
146             return -2;
147 #else
148         if (p1 < 0 || p1 > 2)
149             return -2;
150 #endif
151         dctx->paramgen_type = p1;
152         return 1;
153 
154     case EVP_PKEY_CTRL_DH_RFC5114:
155         if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
156             return -2;
157         dctx->param_nid = p1;
158         return 1;
159 
160     case EVP_PKEY_CTRL_DH_NID:
161         if (p1 <= 0 || dctx->param_nid != NID_undef)
162             return -2;
163         dctx->param_nid = p1;
164         return 1;
165 
166     case EVP_PKEY_CTRL_PEER_KEY:
167         /* Default behaviour is OK */
168         return 1;
169 
170     case EVP_PKEY_CTRL_DH_KDF_TYPE:
171         if (p1 == -2)
172             return dctx->kdf_type;
173         if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
174             return -2;
175         dctx->kdf_type = p1;
176         return 1;
177 
178     case EVP_PKEY_CTRL_DH_KDF_MD:
179         dctx->kdf_md = p2;
180         return 1;
181 
182     case EVP_PKEY_CTRL_GET_DH_KDF_MD:
183         *(const EVP_MD **)p2 = dctx->kdf_md;
184         return 1;
185 
186     case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
187         if (p1 <= 0)
188             return -2;
189         dctx->kdf_outlen = (size_t)p1;
190         return 1;
191 
192     case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
193         *(int *)p2 = dctx->kdf_outlen;
194         return 1;
195 
196     case EVP_PKEY_CTRL_DH_KDF_UKM:
197         OPENSSL_free(dctx->kdf_ukm);
198         dctx->kdf_ukm = p2;
199         if (p2)
200             dctx->kdf_ukmlen = p1;
201         else
202             dctx->kdf_ukmlen = 0;
203         return 1;
204 
205     case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
206         *(unsigned char **)p2 = dctx->kdf_ukm;
207         return dctx->kdf_ukmlen;
208 
209     case EVP_PKEY_CTRL_DH_KDF_OID:
210         ASN1_OBJECT_free(dctx->kdf_oid);
211         dctx->kdf_oid = p2;
212         return 1;
213 
214     case EVP_PKEY_CTRL_GET_DH_KDF_OID:
215         *(ASN1_OBJECT **)p2 = dctx->kdf_oid;
216         return 1;
217 
218     default:
219         return -2;
220 
221     }
222 }
223 
pkey_dh_ctrl_str(EVP_PKEY_CTX * ctx,const char * type,const char * value)224 static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
225                             const char *type, const char *value)
226 {
227     if (strcmp(type, "dh_paramgen_prime_len") == 0) {
228         int len;
229         len = atoi(value);
230         return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
231     }
232     if (strcmp(type, "dh_rfc5114") == 0) {
233         DH_PKEY_CTX *dctx = ctx->data;
234         int id;
235 
236         id = atoi(value);
237         if (id < 0 || id > 3)
238             return -2;
239         dctx->param_nid = id;
240         return 1;
241     }
242     if (strcmp(type, "dh_param") == 0) {
243         DH_PKEY_CTX *dctx = ctx->data;
244         int nid = OBJ_sn2nid(value);
245 
246         if (nid == NID_undef) {
247             ERR_raise(ERR_LIB_DH, DH_R_INVALID_PARAMETER_NAME);
248             return -2;
249         }
250         dctx->param_nid = nid;
251         return 1;
252     }
253     if (strcmp(type, "dh_paramgen_generator") == 0) {
254         int len;
255         len = atoi(value);
256         return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
257     }
258     if (strcmp(type, "dh_paramgen_subprime_len") == 0) {
259         int len;
260         len = atoi(value);
261         return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
262     }
263     if (strcmp(type, "dh_paramgen_type") == 0) {
264         int typ;
265         typ = atoi(value);
266         return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
267     }
268     if (strcmp(type, "dh_pad") == 0) {
269         int pad;
270         pad = atoi(value);
271         return EVP_PKEY_CTX_set_dh_pad(ctx, pad);
272     }
273     return -2;
274 }
275 
ffc_params_generate(OSSL_LIB_CTX * libctx,DH_PKEY_CTX * dctx,BN_GENCB * pcb)276 static DH *ffc_params_generate(OSSL_LIB_CTX *libctx, DH_PKEY_CTX *dctx,
277                                BN_GENCB *pcb)
278 {
279     DH *ret;
280     int rv = 0;
281     int res;
282     int prime_len = dctx->prime_len;
283     int subprime_len = dctx->subprime_len;
284 
285     if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4)
286         return NULL;
287     ret = DH_new();
288     if (ret == NULL)
289         return NULL;
290 
291     if (subprime_len == -1) {
292         if (prime_len >= 2048)
293             subprime_len = 256;
294         else
295             subprime_len = 160;
296     }
297 
298     if (dctx->md != NULL)
299         ossl_ffc_set_digest(&ret->params, EVP_MD_get0_name(dctx->md), NULL);
300 
301 # ifndef FIPS_MODULE
302     if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2)
303         rv = ossl_ffc_params_FIPS186_2_generate(libctx, &ret->params,
304                                                 FFC_PARAM_TYPE_DH,
305                                                 prime_len, subprime_len, &res,
306                                                 pcb);
307     else
308 # endif
309     /* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */
310     if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2)
311         rv = ossl_ffc_params_FIPS186_4_generate(libctx, &ret->params,
312                                                 FFC_PARAM_TYPE_DH,
313                                                 prime_len, subprime_len, &res,
314                                                 pcb);
315     if (rv <= 0) {
316         DH_free(ret);
317         return NULL;
318     }
319     return ret;
320 }
321 
pkey_dh_paramgen(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)322 static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx,
323                             EVP_PKEY *pkey)
324 {
325     DH *dh = NULL;
326     DH_PKEY_CTX *dctx = ctx->data;
327     BN_GENCB *pcb = NULL;
328     int ret;
329 
330     /*
331      * Look for a safe prime group for key establishment. Which uses
332      * either RFC_3526 (modp_XXXX) or RFC_7919 (ffdheXXXX).
333      * RFC_5114 is also handled here for param_nid = (1..3)
334      */
335     if (dctx->param_nid != NID_undef) {
336         int type = dctx->param_nid <= 3 ? EVP_PKEY_DHX : EVP_PKEY_DH;
337 
338         if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL)
339             return 0;
340         EVP_PKEY_assign(pkey, type, dh);
341         return 1;
342     }
343 
344     if (ctx->pkey_gencb != NULL) {
345         pcb = BN_GENCB_new();
346         if (pcb == NULL)
347             return 0;
348         evp_pkey_set_cb_translate(pcb, ctx);
349     }
350 # ifdef FIPS_MODULE
351     dctx->paramgen_type = DH_PARAMGEN_TYPE_FIPS_186_4;
352 # endif /* FIPS_MODULE */
353     if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) {
354         dh = ffc_params_generate(NULL, dctx, pcb);
355         BN_GENCB_free(pcb);
356         if (dh == NULL)
357             return 0;
358         EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
359         return 1;
360     }
361     dh = DH_new();
362     if (dh == NULL) {
363         BN_GENCB_free(pcb);
364         return 0;
365     }
366     ret = DH_generate_parameters_ex(dh,
367                                     dctx->prime_len, dctx->generator, pcb);
368     BN_GENCB_free(pcb);
369     if (ret)
370         EVP_PKEY_assign_DH(pkey, dh);
371     else
372         DH_free(dh);
373     return ret;
374 }
375 
pkey_dh_keygen(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)376 static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
377 {
378     DH_PKEY_CTX *dctx = ctx->data;
379     DH *dh = NULL;
380 
381     if (ctx->pkey == NULL && dctx->param_nid == NID_undef) {
382         ERR_raise(ERR_LIB_DH, DH_R_NO_PARAMETERS_SET);
383         return 0;
384     }
385     if (dctx->param_nid != NID_undef)
386         dh = DH_new_by_nid(dctx->param_nid);
387     else
388         dh = DH_new();
389     if (dh == NULL)
390         return 0;
391     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
392     /* Note: if error return, pkey is freed by parent routine */
393     if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
394         return 0;
395     return DH_generate_key((DH *)EVP_PKEY_get0_DH(pkey));
396 }
397 
pkey_dh_derive(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)398 static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
399                           size_t *keylen)
400 {
401     int ret;
402     DH *dh;
403     const DH *dhpub;
404     DH_PKEY_CTX *dctx = ctx->data;
405     BIGNUM *dhpubbn;
406 
407     if (ctx->pkey == NULL || ctx->peerkey == NULL) {
408         ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
409         return 0;
410     }
411     dh = (DH *)EVP_PKEY_get0_DH(ctx->pkey);
412     dhpub = EVP_PKEY_get0_DH(ctx->peerkey);
413     if (dhpub == NULL) {
414         ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
415         return 0;
416     }
417     dhpubbn = dhpub->pub_key;
418     if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
419         if (key == NULL) {
420             *keylen = DH_size(dh);
421             return 1;
422         }
423         if (dctx->pad)
424             ret = DH_compute_key_padded(key, dhpubbn, dh);
425         else
426             ret = DH_compute_key(key, dhpubbn, dh);
427         if (ret < 0)
428             return ret;
429         *keylen = ret;
430         return 1;
431     }
432     else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
433 
434         unsigned char *Z = NULL;
435         int Zlen = 0;
436 
437         if (!dctx->kdf_outlen || !dctx->kdf_oid)
438             return 0;
439         if (key == NULL) {
440             *keylen = dctx->kdf_outlen;
441             return 1;
442         }
443         if (*keylen != dctx->kdf_outlen)
444             return 0;
445         ret = 0;
446         if ((Zlen = DH_size(dh)) <= 0)
447             return 0;
448         if ((Z = OPENSSL_malloc(Zlen)) == NULL) {
449             ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
450             return 0;
451         }
452         if (DH_compute_key_padded(Z, dhpubbn, dh) <= 0)
453             goto err;
454         if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
455                           dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
456             goto err;
457         *keylen = dctx->kdf_outlen;
458         ret = 1;
459  err:
460         OPENSSL_clear_free(Z, Zlen);
461         return ret;
462     }
463     return 0;
464 }
465 
466 static const EVP_PKEY_METHOD dh_pkey_meth = {
467     EVP_PKEY_DH,
468     0,
469     pkey_dh_init,
470     pkey_dh_copy,
471     pkey_dh_cleanup,
472 
473     0,
474     pkey_dh_paramgen,
475 
476     0,
477     pkey_dh_keygen,
478 
479     0,
480     0,
481 
482     0,
483     0,
484 
485     0, 0,
486 
487     0, 0, 0, 0,
488 
489     0, 0,
490 
491     0, 0,
492 
493     0,
494     pkey_dh_derive,
495 
496     pkey_dh_ctrl,
497     pkey_dh_ctrl_str
498 };
499 
ossl_dh_pkey_method(void)500 const EVP_PKEY_METHOD *ossl_dh_pkey_method(void)
501 {
502     return &dh_pkey_meth;
503 }
504 
505 static const EVP_PKEY_METHOD dhx_pkey_meth = {
506     EVP_PKEY_DHX,
507     0,
508     pkey_dh_init,
509     pkey_dh_copy,
510     pkey_dh_cleanup,
511 
512     0,
513     pkey_dh_paramgen,
514 
515     0,
516     pkey_dh_keygen,
517 
518     0,
519     0,
520 
521     0,
522     0,
523 
524     0, 0,
525 
526     0, 0, 0, 0,
527 
528     0, 0,
529 
530     0, 0,
531 
532     0,
533     pkey_dh_derive,
534 
535     pkey_dh_ctrl,
536     pkey_dh_ctrl_str
537 };
538 
ossl_dhx_pkey_method(void)539 const EVP_PKEY_METHOD *ossl_dhx_pkey_method(void)
540 {
541     return &dhx_pkey_meth;
542 }
543