Coverity: fix 1506298: negative returns
[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 (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_MALLOC_FAILURE);
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 };