]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/dh/dh_ameth.c
rand: remove unimplemented librandom stub code
[thirdparty/openssl.git] / crypto / dh / dh_ameth.c
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 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 <openssl/x509.h>
18 #include <openssl/asn1.h>
19 #include <openssl/bn.h>
20 #include <openssl/core_names.h>
21 #include <openssl/param_build.h>
22 #include "internal/ffc.h"
23 #include "internal/cryptlib.h"
24 #include "crypto/asn1.h"
25 #include "crypto/dh.h"
26 #include "crypto/evp.h"
27 #include "dh_local.h"
28
29 /*
30 * i2d/d2i like DH parameter functions which use the appropriate routine for
31 * PKCS#3 DH or X9.42 DH.
32 */
33
34 static DH *d2i_dhp(const EVP_PKEY *pkey, const unsigned char **pp,
35 long length)
36 {
37 DH *dh = NULL;
38 int is_dhx = (pkey->ameth == &ossl_dhx_asn1_meth);
39
40 if (is_dhx)
41 dh = d2i_DHxparams(NULL, pp, length);
42 else
43 dh = d2i_DHparams(NULL, pp, length);
44
45 return dh;
46 }
47
48 static int i2d_dhp(const EVP_PKEY *pkey, const DH *a, unsigned char **pp)
49 {
50 if (pkey->ameth == &ossl_dhx_asn1_meth)
51 return i2d_DHxparams(a, pp);
52 return i2d_DHparams(a, pp);
53 }
54
55 static void int_dh_free(EVP_PKEY *pkey)
56 {
57 DH_free(pkey->pkey.dh);
58 }
59
60 static int dh_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
61 {
62 const unsigned char *p, *pm;
63 int pklen, pmlen;
64 int ptype;
65 const void *pval;
66 const ASN1_STRING *pstr;
67 X509_ALGOR *palg;
68 ASN1_INTEGER *public_key = NULL;
69
70 DH *dh = NULL;
71
72 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
73 return 0;
74 X509_ALGOR_get0(NULL, &ptype, &pval, palg);
75
76 if (ptype != V_ASN1_SEQUENCE) {
77 ERR_raise(ERR_LIB_DH, DH_R_PARAMETER_ENCODING_ERROR);
78 goto err;
79 }
80
81 pstr = pval;
82 pm = pstr->data;
83 pmlen = pstr->length;
84
85 if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL) {
86 ERR_raise(ERR_LIB_DH, DH_R_DECODE_ERROR);
87 goto err;
88 }
89
90 if ((public_key = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) {
91 ERR_raise(ERR_LIB_DH, DH_R_DECODE_ERROR);
92 goto err;
93 }
94
95 /* We have parameters now set public key */
96 if ((dh->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) {
97 ERR_raise(ERR_LIB_DH, DH_R_BN_DECODE_ERROR);
98 goto err;
99 }
100
101 ASN1_INTEGER_free(public_key);
102 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
103 return 1;
104
105 err:
106 ASN1_INTEGER_free(public_key);
107 DH_free(dh);
108 return 0;
109 }
110
111 static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
112 {
113 DH *dh;
114 int ptype;
115 unsigned char *penc = NULL;
116 int penclen;
117 ASN1_STRING *str;
118 ASN1_INTEGER *pub_key = NULL;
119
120 dh = pkey->pkey.dh;
121
122 str = ASN1_STRING_new();
123 if (str == NULL) {
124 ERR_raise(ERR_LIB_DH, ERR_R_ASN1_LIB);
125 goto err;
126 }
127 str->length = i2d_dhp(pkey, dh, &str->data);
128 if (str->length <= 0) {
129 ERR_raise(ERR_LIB_DH, ERR_R_ASN1_LIB);
130 goto err;
131 }
132 ptype = V_ASN1_SEQUENCE;
133
134 pub_key = BN_to_ASN1_INTEGER(dh->pub_key, NULL);
135 if (pub_key == NULL)
136 goto err;
137
138 penclen = i2d_ASN1_INTEGER(pub_key, &penc);
139
140 ASN1_INTEGER_free(pub_key);
141
142 if (penclen <= 0) {
143 ERR_raise(ERR_LIB_DH, ERR_R_ASN1_LIB);
144 goto err;
145 }
146
147 if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
148 ptype, str, penc, penclen))
149 return 1;
150
151 err:
152 OPENSSL_free(penc);
153 ASN1_STRING_free(str);
154
155 return 0;
156 }
157
158 /*
159 * PKCS#8 DH is defined in PKCS#11 of all places. It is similar to DH in that
160 * the AlgorithmIdentifier contains the parameters, the private key is
161 * explicitly included and the pubkey must be recalculated.
162 */
163
164 static int dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
165 {
166 int ret = 0;
167 DH *dh = ossl_dh_key_from_pkcs8(p8, NULL, NULL);
168
169 if (dh != NULL) {
170 ret = 1;
171 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
172 }
173
174 return ret;
175 }
176
177 static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
178 {
179 ASN1_STRING *params = NULL;
180 ASN1_INTEGER *prkey = NULL;
181 unsigned char *dp = NULL;
182 int dplen;
183
184 params = ASN1_STRING_new();
185
186 if (params == NULL) {
187 ERR_raise(ERR_LIB_DH, ERR_R_ASN1_LIB);
188 goto err;
189 }
190
191 params->length = i2d_dhp(pkey, pkey->pkey.dh, &params->data);
192 if (params->length <= 0) {
193 ERR_raise(ERR_LIB_DH, ERR_R_ASN1_LIB);
194 goto err;
195 }
196 params->type = V_ASN1_SEQUENCE;
197
198 /* Get private key into integer */
199 prkey = BN_to_ASN1_INTEGER(pkey->pkey.dh->priv_key, NULL);
200
201 if (prkey == NULL) {
202 ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);
203 goto err;
204 }
205
206 dplen = i2d_ASN1_INTEGER(prkey, &dp);
207
208 ASN1_STRING_clear_free(prkey);
209
210 if (dplen <= 0) {
211 ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);
212 goto err;
213 }
214
215 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
216 V_ASN1_SEQUENCE, params, dp, dplen)) {
217 OPENSSL_clear_free(dp, dplen);
218 goto err;
219 }
220 return 1;
221
222 err:
223 ASN1_STRING_free(params);
224 return 0;
225 }
226
227 static int dh_param_decode(EVP_PKEY *pkey,
228 const unsigned char **pder, int derlen)
229 {
230 DH *dh;
231
232 if ((dh = d2i_dhp(pkey, pder, derlen)) == NULL)
233 return 0;
234 dh->dirty_cnt++;
235 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
236 return 1;
237 }
238
239 static int dh_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
240 {
241 return i2d_dhp(pkey, pkey->pkey.dh, pder);
242 }
243
244 static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype)
245 {
246 int reason = ERR_R_BUF_LIB;
247 const char *ktype = NULL;
248 BIGNUM *priv_key, *pub_key;
249
250 if (ptype == 2)
251 priv_key = x->priv_key;
252 else
253 priv_key = NULL;
254
255 if (ptype > 0)
256 pub_key = x->pub_key;
257 else
258 pub_key = NULL;
259
260 if (x->params.p == NULL || (ptype == 2 && priv_key == NULL)
261 || (ptype > 0 && pub_key == NULL)) {
262 reason = ERR_R_PASSED_NULL_PARAMETER;
263 goto err;
264 }
265
266 if (ptype == 2)
267 ktype = "DH Private-Key";
268 else if (ptype == 1)
269 ktype = "DH Public-Key";
270 else
271 ktype = "DH Parameters";
272
273 if (!BIO_indent(bp, indent, 128)
274 || BIO_printf(bp, "%s: (%d bit)\n", ktype, DH_bits(x)) <= 0)
275 goto err;
276 indent += 4;
277
278 if (!ASN1_bn_print(bp, "private-key:", priv_key, NULL, indent))
279 goto err;
280 if (!ASN1_bn_print(bp, "public-key:", pub_key, NULL, indent))
281 goto err;
282
283 if (!ossl_ffc_params_print(bp, &x->params, indent))
284 goto err;
285
286 if (x->length != 0) {
287 if (!BIO_indent(bp, indent, 128)
288 || BIO_printf(bp, "recommended-private-length: %d bits\n",
289 (int)x->length) <= 0)
290 goto err;
291 }
292
293 return 1;
294
295 err:
296 ERR_raise(ERR_LIB_DH, reason);
297 return 0;
298 }
299
300 static int int_dh_size(const EVP_PKEY *pkey)
301 {
302 return DH_size(pkey->pkey.dh);
303 }
304
305 static int dh_bits(const EVP_PKEY *pkey)
306 {
307 return DH_bits(pkey->pkey.dh);
308 }
309
310 static int dh_security_bits(const EVP_PKEY *pkey)
311 {
312 return DH_security_bits(pkey->pkey.dh);
313 }
314
315 static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
316 {
317 return ossl_ffc_params_cmp(&a->pkey.dh->params, &b->pkey.dh->params,
318 a->ameth != &ossl_dhx_asn1_meth);
319 }
320
321 static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
322 {
323 if (is_x942 == -1)
324 is_x942 = (from->params.q != NULL);
325 if (!ossl_ffc_params_copy(&to->params, &from->params))
326 return 0;
327 if (!is_x942)
328 to->length = from->length;
329 to->dirty_cnt++;
330 return 1;
331 }
332
333 DH *DHparams_dup(const DH *dh)
334 {
335 DH *ret;
336 ret = DH_new();
337 if (ret == NULL)
338 return NULL;
339 if (!int_dh_param_copy(ret, dh, -1)) {
340 DH_free(ret);
341 return NULL;
342 }
343 return ret;
344 }
345
346 static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
347 {
348 if (to->pkey.dh == NULL) {
349 to->pkey.dh = DH_new();
350 if (to->pkey.dh == NULL)
351 return 0;
352 }
353 return int_dh_param_copy(to->pkey.dh, from->pkey.dh,
354 from->ameth == &ossl_dhx_asn1_meth);
355 }
356
357 static int dh_missing_parameters(const EVP_PKEY *a)
358 {
359 return a->pkey.dh == NULL
360 || a->pkey.dh->params.p == NULL
361 || a->pkey.dh->params.g == NULL;
362 }
363
364 static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
365 {
366 if (dh_cmp_parameters(a, b) == 0)
367 return 0;
368 if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0)
369 return 0;
370 else
371 return 1;
372 }
373
374 static int dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
375 ASN1_PCTX *ctx)
376 {
377 return do_dh_print(bp, pkey->pkey.dh, indent, 0);
378 }
379
380 static int dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent,
381 ASN1_PCTX *ctx)
382 {
383 return do_dh_print(bp, pkey->pkey.dh, indent, 1);
384 }
385
386 static int dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent,
387 ASN1_PCTX *ctx)
388 {
389 return do_dh_print(bp, pkey->pkey.dh, indent, 2);
390 }
391
392 int DHparams_print(BIO *bp, const DH *x)
393 {
394 return do_dh_print(bp, x, 4, 0);
395 }
396
397 static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
398 {
399 DH *dh;
400 switch (op) {
401 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
402 /* We should only be here if we have a legacy key */
403 if (!ossl_assert(evp_pkey_is_legacy(pkey)))
404 return 0;
405 dh = (DH *) evp_pkey_get0_DH_int(pkey);
406 if (dh == NULL)
407 return 0;
408 return ossl_dh_buf2key(dh, arg2, arg1);
409 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
410 dh = (DH *) EVP_PKEY_get0_DH(pkey);
411 if (dh == NULL)
412 return 0;
413 return ossl_dh_key2buf(dh, arg2, 0, 1);
414 default:
415 return -2;
416 }
417 }
418
419 static int dhx_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
420 {
421 switch (op) {
422 default:
423 return -2;
424 }
425
426 }
427
428 static int dh_pkey_public_check(const EVP_PKEY *pkey)
429 {
430 DH *dh = pkey->pkey.dh;
431
432 if (dh->pub_key == NULL) {
433 ERR_raise(ERR_LIB_DH, DH_R_MISSING_PUBKEY);
434 return 0;
435 }
436
437 return DH_check_pub_key_ex(dh, dh->pub_key);
438 }
439
440 static int dh_pkey_param_check(const EVP_PKEY *pkey)
441 {
442 DH *dh = pkey->pkey.dh;
443
444 return DH_check_ex(dh);
445 }
446
447 static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey)
448 {
449 return pkey->pkey.dh->dirty_cnt;
450 }
451
452 static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
453 OSSL_FUNC_keymgmt_import_fn *importer,
454 OSSL_LIB_CTX *libctx, const char *propq)
455 {
456 DH *dh = from->pkey.dh;
457 OSSL_PARAM_BLD *tmpl;
458 const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh);
459 long l = DH_get_length(dh);
460 const BIGNUM *pub_key = DH_get0_pub_key(dh);
461 const BIGNUM *priv_key = DH_get0_priv_key(dh);
462 OSSL_PARAM *params = NULL;
463 int selection = 0;
464 int rv = 0;
465
466 if (p == NULL || g == NULL)
467 return 0;
468
469 tmpl = OSSL_PARAM_BLD_new();
470 if (tmpl == NULL)
471 return 0;
472 if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
473 || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g))
474 goto err;
475 if (q != NULL) {
476 if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
477 goto err;
478 }
479 selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
480 if (l > 0) {
481 if (!OSSL_PARAM_BLD_push_long(tmpl, OSSL_PKEY_PARAM_DH_PRIV_LEN, l))
482 goto err;
483 selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
484 }
485 if (pub_key != NULL) {
486 if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
487 goto err;
488 selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
489 }
490 if (priv_key != NULL) {
491 if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
492 priv_key))
493 goto err;
494 selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
495 }
496
497 if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
498 goto err;
499
500 /* We export, the provider imports */
501 rv = importer(to_keydata, selection, params);
502
503 OSSL_PARAM_free(params);
504 err:
505 OSSL_PARAM_BLD_free(tmpl);
506 return rv;
507 }
508
509 static int dh_pkey_import_from_type(const OSSL_PARAM params[], void *vpctx,
510 int type)
511 {
512 EVP_PKEY_CTX *pctx = vpctx;
513 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
514 DH *dh = ossl_dh_new_ex(pctx->libctx);
515
516 if (dh == NULL) {
517 ERR_raise(ERR_LIB_DH, ERR_R_DH_LIB);
518 return 0;
519 }
520 DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
521 DH_set_flags(dh, type == EVP_PKEY_DH ? DH_FLAG_TYPE_DH : DH_FLAG_TYPE_DHX);
522
523 if (!ossl_dh_params_fromdata(dh, params)
524 || !ossl_dh_key_fromdata(dh, params, 1)
525 || !EVP_PKEY_assign(pkey, type, dh)) {
526 DH_free(dh);
527 return 0;
528 }
529 return 1;
530 }
531
532 static int dh_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
533 {
534 return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DH);
535 }
536
537 static int dhx_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
538 {
539 return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DHX);
540 }
541
542 static int dh_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
543 {
544 DH *dh = from->pkey.dh;
545 DH *dupkey = NULL;
546 int ret;
547
548 if (dh != NULL) {
549 dupkey = ossl_dh_dup(dh, OSSL_KEYMGMT_SELECT_ALL);
550 if (dupkey == NULL)
551 return 0;
552 }
553
554 ret = EVP_PKEY_assign(to, from->type, dupkey);
555 if (!ret)
556 DH_free(dupkey);
557 return ret;
558 }
559
560 const EVP_PKEY_ASN1_METHOD ossl_dh_asn1_meth = {
561 EVP_PKEY_DH,
562 EVP_PKEY_DH,
563 0,
564
565 "DH",
566 "OpenSSL PKCS#3 DH method",
567
568 dh_pub_decode,
569 dh_pub_encode,
570 dh_pub_cmp,
571 dh_public_print,
572
573 dh_priv_decode,
574 dh_priv_encode,
575 dh_private_print,
576
577 int_dh_size,
578 dh_bits,
579 dh_security_bits,
580
581 dh_param_decode,
582 dh_param_encode,
583 dh_missing_parameters,
584 dh_copy_parameters,
585 dh_cmp_parameters,
586 dh_param_print,
587 0,
588
589 int_dh_free,
590 dh_pkey_ctrl,
591
592 0, 0, 0, 0, 0,
593
594 0,
595 dh_pkey_public_check,
596 dh_pkey_param_check,
597
598 0, 0, 0, 0,
599
600 dh_pkey_dirty_cnt,
601 dh_pkey_export_to,
602 dh_pkey_import_from,
603 dh_pkey_copy
604 };
605
606 const EVP_PKEY_ASN1_METHOD ossl_dhx_asn1_meth = {
607 EVP_PKEY_DHX,
608 EVP_PKEY_DHX,
609 0,
610
611 "X9.42 DH",
612 "OpenSSL X9.42 DH method",
613
614 dh_pub_decode,
615 dh_pub_encode,
616 dh_pub_cmp,
617 dh_public_print,
618
619 dh_priv_decode,
620 dh_priv_encode,
621 dh_private_print,
622
623 int_dh_size,
624 dh_bits,
625 dh_security_bits,
626
627 dh_param_decode,
628 dh_param_encode,
629 dh_missing_parameters,
630 dh_copy_parameters,
631 dh_cmp_parameters,
632 dh_param_print,
633 0,
634
635 int_dh_free,
636 dhx_pkey_ctrl,
637
638 0, 0, 0, 0, 0,
639
640 0,
641 dh_pkey_public_check,
642 dh_pkey_param_check,
643 0, 0, 0, 0,
644 dh_pkey_dirty_cnt,
645 dh_pkey_export_to,
646 dhx_pkey_import_from,
647 dh_pkey_copy
648 };