Reduce optimization in hppa builds
[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_MALLOC_FAILURE);
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_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         ERR_raise(ERR_LIB_DH, 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     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_MALLOC_FAILURE);
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_MALLOC_FAILURE);
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 (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
211                          V_ASN1_SEQUENCE, params, dp, dplen)) {
212         OPENSSL_clear_free(dp, dplen);
213         goto err;
214     }
215     return 1;
216
217  err:
218     ASN1_STRING_free(params);
219     return 0;
220 }
221
222 static int dh_param_decode(EVP_PKEY *pkey,
223                            const unsigned char **pder, int derlen)
224 {
225     DH *dh;
226
227     if ((dh = d2i_dhp(pkey, pder, derlen)) == NULL)
228         return 0;
229     dh->dirty_cnt++;
230     EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
231     return 1;
232 }
233
234 static int dh_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
235 {
236     return i2d_dhp(pkey, pkey->pkey.dh, pder);
237 }
238
239 static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype)
240 {
241     int reason = ERR_R_BUF_LIB;
242     const char *ktype = NULL;
243     BIGNUM *priv_key, *pub_key;
244
245     if (ptype == 2)
246         priv_key = x->priv_key;
247     else
248         priv_key = NULL;
249
250     if (ptype > 0)
251         pub_key = x->pub_key;
252     else
253         pub_key = NULL;
254
255     if (x->params.p == NULL || (ptype == 2 && priv_key == NULL)
256             || (ptype > 0 && pub_key == NULL)) {
257         reason = ERR_R_PASSED_NULL_PARAMETER;
258         goto err;
259     }
260
261     if (ptype == 2)
262         ktype = "DH Private-Key";
263     else if (ptype == 1)
264         ktype = "DH Public-Key";
265     else
266         ktype = "DH Parameters";
267
268     if (!BIO_indent(bp, indent, 128)
269             || BIO_printf(bp, "%s: (%d bit)\n", ktype, DH_bits(x)) <= 0)
270         goto err;
271     indent += 4;
272
273     if (!ASN1_bn_print(bp, "private-key:", priv_key, NULL, indent))
274         goto err;
275     if (!ASN1_bn_print(bp, "public-key:", pub_key, NULL, indent))
276         goto err;
277
278     if (!ossl_ffc_params_print(bp, &x->params, indent))
279         goto err;
280
281     if (x->length != 0) {
282         if (!BIO_indent(bp, indent, 128)
283                 || BIO_printf(bp, "recommended-private-length: %d bits\n",
284                               (int)x->length) <= 0)
285             goto err;
286     }
287
288     return 1;
289
290  err:
291     ERR_raise(ERR_LIB_DH, reason);
292     return 0;
293 }
294
295 static int int_dh_size(const EVP_PKEY *pkey)
296 {
297     return DH_size(pkey->pkey.dh);
298 }
299
300 static int dh_bits(const EVP_PKEY *pkey)
301 {
302     return DH_bits(pkey->pkey.dh);
303 }
304
305 static int dh_security_bits(const EVP_PKEY *pkey)
306 {
307     return DH_security_bits(pkey->pkey.dh);
308 }
309
310 static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
311 {
312     return ossl_ffc_params_cmp(&a->pkey.dh->params, &b->pkey.dh->params,
313                                a->ameth != &ossl_dhx_asn1_meth);
314 }
315
316 static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
317 {
318     if (is_x942 == -1)
319         is_x942 = (from->params.q != NULL);
320     if (!ossl_ffc_params_copy(&to->params, &from->params))
321         return 0;
322     if (!is_x942)
323         to->length = from->length;
324     to->dirty_cnt++;
325     return 1;
326 }
327
328 DH *DHparams_dup(const DH *dh)
329 {
330     DH *ret;
331     ret = DH_new();
332     if (ret == NULL)
333         return NULL;
334     if (!int_dh_param_copy(ret, dh, -1)) {
335         DH_free(ret);
336         return NULL;
337     }
338     return ret;
339 }
340
341 static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
342 {
343     if (to->pkey.dh == NULL) {
344         to->pkey.dh = DH_new();
345         if (to->pkey.dh == NULL)
346             return 0;
347     }
348     return int_dh_param_copy(to->pkey.dh, from->pkey.dh,
349                              from->ameth == &ossl_dhx_asn1_meth);
350 }
351
352 static int dh_missing_parameters(const EVP_PKEY *a)
353 {
354     return a->pkey.dh == NULL
355         || a->pkey.dh->params.p == NULL
356         || a->pkey.dh->params.g == NULL;
357 }
358
359 static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
360 {
361     if (dh_cmp_parameters(a, b) == 0)
362         return 0;
363     if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0)
364         return 0;
365     else
366         return 1;
367 }
368
369 static int dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
370                           ASN1_PCTX *ctx)
371 {
372     return do_dh_print(bp, pkey->pkey.dh, indent, 0);
373 }
374
375 static int dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent,
376                            ASN1_PCTX *ctx)
377 {
378     return do_dh_print(bp, pkey->pkey.dh, indent, 1);
379 }
380
381 static int dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent,
382                             ASN1_PCTX *ctx)
383 {
384     return do_dh_print(bp, pkey->pkey.dh, indent, 2);
385 }
386
387 int DHparams_print(BIO *bp, const DH *x)
388 {
389     return do_dh_print(bp, x, 4, 0);
390 }
391
392 static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
393 {
394     DH *dh;
395     switch (op) {
396     case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
397         /* We should only be here if we have a legacy key */
398         if (!ossl_assert(evp_pkey_is_legacy(pkey)))
399             return 0;
400         dh = (DH *) evp_pkey_get0_DH_int(pkey);
401         if (dh == NULL)
402             return 0;
403         return ossl_dh_buf2key(dh, arg2, arg1);
404     case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
405         dh = (DH *) EVP_PKEY_get0_DH(pkey);
406         if (dh == NULL)
407             return 0;
408         return ossl_dh_key2buf(dh, arg2, 0, 1);
409     default:
410         return -2;
411     }
412 }
413
414 static int dhx_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
415 {
416     switch (op) {
417     default:
418         return -2;
419     }
420
421 }
422
423 static int dh_pkey_public_check(const EVP_PKEY *pkey)
424 {
425     DH *dh = pkey->pkey.dh;
426
427     if (dh->pub_key == NULL) {
428         ERR_raise(ERR_LIB_DH, DH_R_MISSING_PUBKEY);
429         return 0;
430     }
431
432     return DH_check_pub_key_ex(dh, dh->pub_key);
433 }
434
435 static int dh_pkey_param_check(const EVP_PKEY *pkey)
436 {
437     DH *dh = pkey->pkey.dh;
438
439     return DH_check_ex(dh);
440 }
441
442 static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey)
443 {
444     return pkey->pkey.dh->dirty_cnt;
445 }
446
447 static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
448                              OSSL_FUNC_keymgmt_import_fn *importer,
449                              OSSL_LIB_CTX *libctx, const char *propq)
450 {
451     DH *dh = from->pkey.dh;
452     OSSL_PARAM_BLD *tmpl;
453     const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh);
454     long l = DH_get_length(dh);
455     const BIGNUM *pub_key = DH_get0_pub_key(dh);
456     const BIGNUM *priv_key = DH_get0_priv_key(dh);
457     OSSL_PARAM *params = NULL;
458     int selection = 0;
459     int rv = 0;
460
461     if (p == NULL || g == NULL)
462         return 0;
463
464     tmpl = OSSL_PARAM_BLD_new();
465     if (tmpl == NULL)
466         return 0;
467     if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
468         || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g))
469         goto err;
470     if (q != NULL) {
471         if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
472             goto err;
473     }
474     selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
475     if (l > 0) {
476         if (!OSSL_PARAM_BLD_push_long(tmpl, OSSL_PKEY_PARAM_DH_PRIV_LEN, l))
477             goto err;
478         selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
479     }
480     if (pub_key != NULL) {
481         if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
482             goto err;
483         selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
484     }
485     if (priv_key != NULL) {
486         if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
487                                     priv_key))
488             goto err;
489         selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
490     }
491
492     if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
493         goto err;
494
495     /* We export, the provider imports */
496     rv = importer(to_keydata, selection, params);
497
498     OSSL_PARAM_free(params);
499 err:
500     OSSL_PARAM_BLD_free(tmpl);
501     return rv;
502 }
503
504 static int dh_pkey_import_from_type(const OSSL_PARAM params[], void *vpctx,
505                                     int type)
506 {
507     EVP_PKEY_CTX *pctx = vpctx;
508     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
509     DH *dh = ossl_dh_new_ex(pctx->libctx);
510
511     if (dh == NULL) {
512         ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
513         return 0;
514     }
515     DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
516     DH_set_flags(dh, type == EVP_PKEY_DH ? DH_FLAG_TYPE_DH : DH_FLAG_TYPE_DHX);
517
518     if (!ossl_dh_params_fromdata(dh, params)
519         || !ossl_dh_key_fromdata(dh, params, 1)
520         || !EVP_PKEY_assign(pkey, type, dh)) {
521         DH_free(dh);
522         return 0;
523     }
524     return 1;
525 }
526
527 static int dh_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
528 {
529     return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DH);
530 }
531
532 static int dhx_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
533 {
534     return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DHX);
535 }
536
537 static int dh_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
538 {
539     DH *dh = from->pkey.dh;
540     DH *dupkey = NULL;
541     int ret;
542
543     if (dh != NULL) {
544         dupkey = ossl_dh_dup(dh, OSSL_KEYMGMT_SELECT_ALL);
545         if (dupkey == NULL)
546             return 0;
547     }
548
549     ret = EVP_PKEY_assign(to, from->type, dupkey);
550     if (!ret)
551         DH_free(dupkey);
552     return ret;
553 }
554
555 const EVP_PKEY_ASN1_METHOD ossl_dh_asn1_meth = {
556     EVP_PKEY_DH,
557     EVP_PKEY_DH,
558     0,
559
560     "DH",
561     "OpenSSL PKCS#3 DH method",
562
563     dh_pub_decode,
564     dh_pub_encode,
565     dh_pub_cmp,
566     dh_public_print,
567
568     dh_priv_decode,
569     dh_priv_encode,
570     dh_private_print,
571
572     int_dh_size,
573     dh_bits,
574     dh_security_bits,
575
576     dh_param_decode,
577     dh_param_encode,
578     dh_missing_parameters,
579     dh_copy_parameters,
580     dh_cmp_parameters,
581     dh_param_print,
582     0,
583
584     int_dh_free,
585     dh_pkey_ctrl,
586
587     0, 0, 0, 0, 0,
588
589     0,
590     dh_pkey_public_check,
591     dh_pkey_param_check,
592
593     0, 0, 0, 0,
594
595     dh_pkey_dirty_cnt,
596     dh_pkey_export_to,
597     dh_pkey_import_from,
598     dh_pkey_copy
599 };
600
601 const EVP_PKEY_ASN1_METHOD ossl_dhx_asn1_meth = {
602     EVP_PKEY_DHX,
603     EVP_PKEY_DHX,
604     0,
605
606     "X9.42 DH",
607     "OpenSSL X9.42 DH method",
608
609     dh_pub_decode,
610     dh_pub_encode,
611     dh_pub_cmp,
612     dh_public_print,
613
614     dh_priv_decode,
615     dh_priv_encode,
616     dh_private_print,
617
618     int_dh_size,
619     dh_bits,
620     dh_security_bits,
621
622     dh_param_decode,
623     dh_param_encode,
624     dh_missing_parameters,
625     dh_copy_parameters,
626     dh_cmp_parameters,
627     dh_param_print,
628     0,
629
630     int_dh_free,
631     dhx_pkey_ctrl,
632
633     0, 0, 0, 0, 0,
634
635     0,
636     dh_pkey_public_check,
637     dh_pkey_param_check,
638     0, 0, 0, 0,
639     dh_pkey_dirty_cnt,
640     dh_pkey_export_to,
641     dhx_pkey_import_from,
642     dh_pkey_copy
643 };