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