VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.2/crypto/dh/dh_pmeth.c@ 101021

Last change on this file since 101021 was 101021, checked in by vboxsync, 15 months ago

openssl-3.1.2: Applied and adjusted our OpenSSL changes to 3.1.0. bugref:10519

File size: 13.1 KB
Line 
1/*
2 * Copyright 2006-2022 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
29typedef 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
54static 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
74static 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
86static 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
117static 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
224static 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
276static 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
322static 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
376static 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
398static 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
466static 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
500const EVP_PKEY_METHOD *ossl_dh_pkey_method(void)
501{
502 return &dh_pkey_meth;
503}
504
505static 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
539const EVP_PKEY_METHOD *ossl_dhx_pkey_method(void)
540{
541 return &dhx_pkey_meth;
542}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette