]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/dh/dh_ameth.c
DH: Move the code to set the DH sub-type
[thirdparty/openssl.git] / crypto / dh / dh_ameth.c
1 /*
2 * Copyright 2006-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 /*
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 == &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 == &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 DHerr(DH_F_DH_PUB_DECODE, 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 DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR);
87 goto err;
88 }
89
90 if ((public_key = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) {
91 DHerr(DH_F_DH_PUB_DECODE, 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 DHerr(DH_F_DH_PUB_DECODE, 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 DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
125 goto err;
126 }
127 str->length = i2d_dhp(pkey, dh, &str->data);
128 if (str->length <= 0) {
129 DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
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 DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
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 const unsigned char *p, *pm;
167 int pklen, pmlen;
168 int ptype;
169 const void *pval;
170 const ASN1_STRING *pstr;
171 const X509_ALGOR *palg;
172 ASN1_INTEGER *privkey = NULL;
173 DH *dh = NULL;
174
175 if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
176 return 0;
177
178 X509_ALGOR_get0(NULL, &ptype, &pval, palg);
179
180 if (ptype != V_ASN1_SEQUENCE)
181 goto decerr;
182 if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
183 goto decerr;
184
185 pstr = pval;
186 pm = pstr->data;
187 pmlen = pstr->length;
188 if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL)
189 goto decerr;
190
191 /* We have parameters now set private key */
192 if ((dh->priv_key = BN_secure_new()) == NULL
193 || !ASN1_INTEGER_to_BN(privkey, dh->priv_key)) {
194 DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR);
195 goto dherr;
196 }
197 /* Calculate public key, increments dirty_cnt */
198 if (!DH_generate_key(dh))
199 goto dherr;
200
201 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
202
203 ASN1_STRING_clear_free(privkey);
204
205 return 1;
206
207 decerr:
208 DHerr(DH_F_DH_PRIV_DECODE, EVP_R_DECODE_ERROR);
209 dherr:
210 DH_free(dh);
211 ASN1_STRING_clear_free(privkey);
212 return 0;
213 }
214
215 static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
216 {
217 ASN1_STRING *params = NULL;
218 ASN1_INTEGER *prkey = NULL;
219 unsigned char *dp = NULL;
220 int dplen;
221
222 params = ASN1_STRING_new();
223
224 if (params == NULL) {
225 DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
226 goto err;
227 }
228
229 params->length = i2d_dhp(pkey, pkey->pkey.dh, &params->data);
230 if (params->length <= 0) {
231 DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
232 goto err;
233 }
234 params->type = V_ASN1_SEQUENCE;
235
236 /* Get private key into integer */
237 prkey = BN_to_ASN1_INTEGER(pkey->pkey.dh->priv_key, NULL);
238
239 if (prkey == NULL) {
240 DHerr(DH_F_DH_PRIV_ENCODE, DH_R_BN_ERROR);
241 goto err;
242 }
243
244 dplen = i2d_ASN1_INTEGER(prkey, &dp);
245
246 ASN1_STRING_clear_free(prkey);
247 prkey = NULL;
248
249 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
250 V_ASN1_SEQUENCE, params, dp, dplen))
251 goto err;
252
253 return 1;
254
255 err:
256 OPENSSL_free(dp);
257 ASN1_STRING_free(params);
258 ASN1_STRING_clear_free(prkey);
259 return 0;
260 }
261
262 static int dh_param_decode(EVP_PKEY *pkey,
263 const unsigned char **pder, int derlen)
264 {
265 DH *dh;
266
267 if ((dh = d2i_dhp(pkey, pder, derlen)) == NULL)
268 return 0;
269 dh->dirty_cnt++;
270 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
271 return 1;
272 }
273
274 static int dh_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
275 {
276 return i2d_dhp(pkey, pkey->pkey.dh, pder);
277 }
278
279 static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype)
280 {
281 int reason = ERR_R_BUF_LIB;
282 const char *ktype = NULL;
283 BIGNUM *priv_key, *pub_key;
284
285 if (ptype == 2)
286 priv_key = x->priv_key;
287 else
288 priv_key = NULL;
289
290 if (ptype > 0)
291 pub_key = x->pub_key;
292 else
293 pub_key = NULL;
294
295 if (x->params.p == NULL || (ptype == 2 && priv_key == NULL)
296 || (ptype > 0 && pub_key == NULL)) {
297 reason = ERR_R_PASSED_NULL_PARAMETER;
298 goto err;
299 }
300
301 if (ptype == 2)
302 ktype = "DH Private-Key";
303 else if (ptype == 1)
304 ktype = "DH Public-Key";
305 else
306 ktype = "DH Parameters";
307
308 if (!BIO_indent(bp, indent, 128)
309 || BIO_printf(bp, "%s: (%d bit)\n", ktype, DH_bits(x)) <= 0)
310 goto err;
311 indent += 4;
312
313 if (!ASN1_bn_print(bp, "private-key:", priv_key, NULL, indent))
314 goto err;
315 if (!ASN1_bn_print(bp, "public-key:", pub_key, NULL, indent))
316 goto err;
317
318 if (!ossl_ffc_params_print(bp, &x->params, indent))
319 goto err;
320
321 if (x->length != 0) {
322 if (!BIO_indent(bp, indent, 128)
323 || BIO_printf(bp, "recommended-private-length: %d bits\n",
324 (int)x->length) <= 0)
325 goto err;
326 }
327
328 return 1;
329
330 err:
331 DHerr(DH_F_DO_DH_PRINT, reason);
332 return 0;
333 }
334
335 static int int_dh_size(const EVP_PKEY *pkey)
336 {
337 return DH_size(pkey->pkey.dh);
338 }
339
340 static int dh_bits(const EVP_PKEY *pkey)
341 {
342 return DH_bits(pkey->pkey.dh);
343 }
344
345 static int dh_security_bits(const EVP_PKEY *pkey)
346 {
347 return DH_security_bits(pkey->pkey.dh);
348 }
349
350 static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
351 {
352 return ossl_ffc_params_cmp(&a->pkey.dh->params, &a->pkey.dh->params,
353 a->ameth != &dhx_asn1_meth);
354 }
355
356 static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
357 {
358 if (is_x942 == -1)
359 is_x942 = (from->params.q != NULL);
360 if (!ossl_ffc_params_copy(&to->params, &from->params))
361 return 0;
362 if (!is_x942)
363 to->length = from->length;
364 to->dirty_cnt++;
365 return 1;
366 }
367
368 DH *DHparams_dup(const DH *dh)
369 {
370 DH *ret;
371 ret = DH_new();
372 if (ret == NULL)
373 return NULL;
374 if (!int_dh_param_copy(ret, dh, -1)) {
375 DH_free(ret);
376 return NULL;
377 }
378 return ret;
379 }
380
381 static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
382 {
383 if (to->pkey.dh == NULL) {
384 to->pkey.dh = DH_new();
385 if (to->pkey.dh == NULL)
386 return 0;
387 }
388 return int_dh_param_copy(to->pkey.dh, from->pkey.dh,
389 from->ameth == &dhx_asn1_meth);
390 }
391
392 static int dh_missing_parameters(const EVP_PKEY *a)
393 {
394 return a->pkey.dh == NULL
395 || a->pkey.dh->params.p == NULL
396 || a->pkey.dh->params.g == NULL;
397 }
398
399 static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
400 {
401 if (dh_cmp_parameters(a, b) == 0)
402 return 0;
403 if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0)
404 return 0;
405 else
406 return 1;
407 }
408
409 static int dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
410 ASN1_PCTX *ctx)
411 {
412 return do_dh_print(bp, pkey->pkey.dh, indent, 0);
413 }
414
415 static int dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent,
416 ASN1_PCTX *ctx)
417 {
418 return do_dh_print(bp, pkey->pkey.dh, indent, 1);
419 }
420
421 static int dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent,
422 ASN1_PCTX *ctx)
423 {
424 return do_dh_print(bp, pkey->pkey.dh, indent, 2);
425 }
426
427 int DHparams_print(BIO *bp, const DH *x)
428 {
429 return do_dh_print(bp, x, 4, 0);
430 }
431
432 static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
433 {
434 switch (op) {
435 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
436 return dh_buf2key(EVP_PKEY_get0_DH(pkey), arg2, arg1);
437 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
438 return dh_key2buf(EVP_PKEY_get0_DH(pkey), arg2, 0, 1);
439 default:
440 return -2;
441 }
442 }
443
444 static int dhx_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
445 {
446 switch (op) {
447 default:
448 return -2;
449 }
450
451 }
452
453 static int dh_pkey_public_check(const EVP_PKEY *pkey)
454 {
455 DH *dh = pkey->pkey.dh;
456
457 if (dh->pub_key == NULL) {
458 DHerr(DH_F_DH_PKEY_PUBLIC_CHECK, DH_R_MISSING_PUBKEY);
459 return 0;
460 }
461
462 return DH_check_pub_key_ex(dh, dh->pub_key);
463 }
464
465 static int dh_pkey_param_check(const EVP_PKEY *pkey)
466 {
467 DH *dh = pkey->pkey.dh;
468
469 return DH_check_ex(dh);
470 }
471
472 static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey)
473 {
474 return pkey->pkey.dh->dirty_cnt;
475 }
476
477 static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
478 EVP_KEYMGMT *to_keymgmt, OSSL_LIB_CTX *libctx,
479 const char *propq)
480 {
481 DH *dh = from->pkey.dh;
482 OSSL_PARAM_BLD *tmpl;
483 const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh);
484 long l = DH_get_length(dh);
485 const BIGNUM *pub_key = DH_get0_pub_key(dh);
486 const BIGNUM *priv_key = DH_get0_priv_key(dh);
487 OSSL_PARAM *params = NULL;
488 int selection = 0;
489 int rv = 0;
490
491 /*
492 * If the DH method is foreign, then we can't be sure of anything, and
493 * can therefore not export or pretend to export.
494 */
495 if (dh_get_method(dh) != DH_OpenSSL())
496 return 0;
497
498 if (p == NULL || g == NULL)
499 return 0;
500
501 tmpl = OSSL_PARAM_BLD_new();
502 if (tmpl == NULL)
503 return 0;
504 if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
505 || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g))
506 goto err;
507 if (q != NULL) {
508 if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
509 goto err;
510 }
511 selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
512 if (l > 0) {
513 if (!OSSL_PARAM_BLD_push_long(tmpl, OSSL_PKEY_PARAM_DH_PRIV_LEN, l))
514 goto err;
515 selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
516 }
517 if (pub_key != NULL) {
518 if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
519 goto err;
520 selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
521 }
522 if (priv_key != NULL) {
523 if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
524 priv_key))
525 goto err;
526 selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
527 }
528
529 if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
530 goto err;
531
532 /* We export, the provider imports */
533 rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
534
535 OSSL_PARAM_BLD_free_params(params);
536 err:
537 OSSL_PARAM_BLD_free(tmpl);
538 return rv;
539 }
540
541 static int dh_pkey_import_from_type(const OSSL_PARAM params[], void *vpctx,
542 int type)
543 {
544 EVP_PKEY_CTX *pctx = vpctx;
545 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
546 DH *dh = dh_new_ex(pctx->libctx);
547
548 if (dh == NULL) {
549 ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
550 return 0;
551 }
552 DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
553 DH_set_flags(dh, type == EVP_PKEY_DH ? DH_FLAG_TYPE_DH : DH_FLAG_TYPE_DHX);
554
555 if (!dh_params_fromdata(dh, params)
556 || !dh_key_fromdata(dh, params)
557 || !EVP_PKEY_assign(pkey, type, dh)) {
558 DH_free(dh);
559 return 0;
560 }
561 return 1;
562 }
563
564 static int dh_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
565 {
566 return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DH);
567 }
568
569 static int dhx_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
570 {
571 return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DHX);
572 }
573
574 const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
575 EVP_PKEY_DH,
576 EVP_PKEY_DH,
577 0,
578
579 "DH",
580 "OpenSSL PKCS#3 DH method",
581
582 dh_pub_decode,
583 dh_pub_encode,
584 dh_pub_cmp,
585 dh_public_print,
586
587 dh_priv_decode,
588 dh_priv_encode,
589 dh_private_print,
590
591 int_dh_size,
592 dh_bits,
593 dh_security_bits,
594
595 dh_param_decode,
596 dh_param_encode,
597 dh_missing_parameters,
598 dh_copy_parameters,
599 dh_cmp_parameters,
600 dh_param_print,
601 0,
602
603 int_dh_free,
604 dh_pkey_ctrl,
605
606 0, 0, 0, 0, 0,
607
608 0,
609 dh_pkey_public_check,
610 dh_pkey_param_check,
611
612 0, 0, 0, 0,
613
614 dh_pkey_dirty_cnt,
615 dh_pkey_export_to,
616 dh_pkey_import_from,
617 };
618
619 const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
620 EVP_PKEY_DHX,
621 EVP_PKEY_DHX,
622 0,
623
624 "X9.42 DH",
625 "OpenSSL X9.42 DH method",
626
627 dh_pub_decode,
628 dh_pub_encode,
629 dh_pub_cmp,
630 dh_public_print,
631
632 dh_priv_decode,
633 dh_priv_encode,
634 dh_private_print,
635
636 int_dh_size,
637 dh_bits,
638 dh_security_bits,
639
640 dh_param_decode,
641 dh_param_encode,
642 dh_missing_parameters,
643 dh_copy_parameters,
644 dh_cmp_parameters,
645 dh_param_print,
646 0,
647
648 int_dh_free,
649 dhx_pkey_ctrl,
650
651 0, 0, 0, 0, 0,
652
653 0,
654 dh_pkey_public_check,
655 dh_pkey_param_check,
656 0, 0, 0, 0,
657 dh_pkey_dirty_cnt,
658 dh_pkey_export_to,
659 dhx_pkey_import_from,
660 };