Line data Source code
1 : /*
2 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3 : * 2006.
4 : */
5 : /* ====================================================================
6 : * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
7 : *
8 : * Redistribution and use in source and binary forms, with or without
9 : * modification, are permitted provided that the following conditions
10 : * are met:
11 : *
12 : * 1. Redistributions of source code must retain the above copyright
13 : * notice, this list of conditions and the following disclaimer.
14 : *
15 : * 2. Redistributions in binary form must reproduce the above copyright
16 : * notice, this list of conditions and the following disclaimer in
17 : * the documentation and/or other materials provided with the
18 : * distribution.
19 : *
20 : * 3. All advertising materials mentioning features or use of this
21 : * software must display the following acknowledgment:
22 : * "This product includes software developed by the OpenSSL Project
23 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 : *
25 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 : * endorse or promote products derived from this software without
27 : * prior written permission. For written permission, please contact
28 : * licensing@OpenSSL.org.
29 : *
30 : * 5. Products derived from this software may not be called "OpenSSL"
31 : * nor may "OpenSSL" appear in their names without prior written
32 : * permission of the OpenSSL Project.
33 : *
34 : * 6. Redistributions of any form whatsoever must retain the following
35 : * acknowledgment:
36 : * "This product includes software developed by the OpenSSL Project
37 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 : *
39 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 : * OF THE POSSIBILITY OF SUCH DAMAGE.
51 : * ====================================================================
52 : *
53 : * This product includes cryptographic software written by Eric Young
54 : * (eay@cryptsoft.com). This product includes software written by Tim
55 : * Hudson (tjh@cryptsoft.com).
56 : *
57 : */
58 :
59 : #include <stdio.h>
60 : #include "cryptlib.h"
61 : #include <openssl/x509.h>
62 : #include <openssl/asn1.h>
63 : #include <openssl/dh.h>
64 : #include <openssl/bn.h>
65 : #include "asn1_locl.h"
66 : #ifndef OPENSSL_NO_CMS
67 : # include <openssl/cms.h>
68 : #endif
69 :
70 : extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth;
71 :
72 : /*
73 : * i2d/d2i like DH parameter functions which use the appropriate routine for
74 : * PKCS#3 DH or X9.42 DH.
75 : */
76 :
77 0 : static DH *d2i_dhp(const EVP_PKEY *pkey, const unsigned char **pp,
78 : long length)
79 : {
80 0 : if (pkey->ameth == &dhx_asn1_meth)
81 0 : return d2i_DHxparams(NULL, pp, length);
82 0 : return d2i_DHparams(NULL, pp, length);
83 : }
84 :
85 0 : static int i2d_dhp(const EVP_PKEY *pkey, const DH *a, unsigned char **pp)
86 : {
87 0 : if (pkey->ameth == &dhx_asn1_meth)
88 0 : return i2d_DHxparams(a, pp);
89 0 : return i2d_DHparams(a, pp);
90 : }
91 :
92 0 : static void int_dh_free(EVP_PKEY *pkey)
93 : {
94 0 : DH_free(pkey->pkey.dh);
95 0 : }
96 :
97 0 : static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
98 : {
99 : const unsigned char *p, *pm;
100 : int pklen, pmlen;
101 : int ptype;
102 : void *pval;
103 : ASN1_STRING *pstr;
104 : X509_ALGOR *palg;
105 : ASN1_INTEGER *public_key = NULL;
106 :
107 : DH *dh = NULL;
108 :
109 0 : if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
110 : return 0;
111 0 : X509_ALGOR_get0(NULL, &ptype, &pval, palg);
112 :
113 0 : if (ptype != V_ASN1_SEQUENCE) {
114 0 : DHerr(DH_F_DH_PUB_DECODE, DH_R_PARAMETER_ENCODING_ERROR);
115 0 : goto err;
116 : }
117 :
118 0 : pstr = pval;
119 0 : pm = pstr->data;
120 0 : pmlen = pstr->length;
121 :
122 0 : if (!(dh = d2i_dhp(pkey, &pm, pmlen))) {
123 0 : DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR);
124 0 : goto err;
125 : }
126 :
127 0 : if (!(public_key = d2i_ASN1_INTEGER(NULL, &p, pklen))) {
128 0 : DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR);
129 0 : goto err;
130 : }
131 :
132 : /* We have parameters now set public key */
133 0 : if (!(dh->pub_key = ASN1_INTEGER_to_BN(public_key, NULL))) {
134 0 : DHerr(DH_F_DH_PUB_DECODE, DH_R_BN_DECODE_ERROR);
135 0 : goto err;
136 : }
137 :
138 0 : ASN1_INTEGER_free(public_key);
139 0 : EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
140 0 : return 1;
141 :
142 : err:
143 0 : if (public_key)
144 0 : ASN1_INTEGER_free(public_key);
145 0 : if (dh)
146 0 : DH_free(dh);
147 : return 0;
148 :
149 : }
150 :
151 0 : static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
152 : {
153 : DH *dh;
154 : int ptype;
155 0 : unsigned char *penc = NULL;
156 : int penclen;
157 : ASN1_STRING *str;
158 : ASN1_INTEGER *pub_key = NULL;
159 :
160 0 : dh = pkey->pkey.dh;
161 :
162 0 : str = ASN1_STRING_new();
163 0 : if (!str) {
164 0 : DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
165 0 : goto err;
166 : }
167 0 : str->length = i2d_dhp(pkey, dh, &str->data);
168 0 : if (str->length <= 0) {
169 0 : DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
170 0 : goto err;
171 : }
172 : ptype = V_ASN1_SEQUENCE;
173 :
174 0 : pub_key = BN_to_ASN1_INTEGER(dh->pub_key, NULL);
175 0 : if (!pub_key)
176 : goto err;
177 :
178 0 : penclen = i2d_ASN1_INTEGER(pub_key, &penc);
179 :
180 0 : ASN1_INTEGER_free(pub_key);
181 :
182 0 : if (penclen <= 0) {
183 0 : DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
184 0 : goto err;
185 : }
186 :
187 0 : if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
188 : ptype, str, penc, penclen))
189 : return 1;
190 :
191 : err:
192 0 : if (penc)
193 0 : OPENSSL_free(penc);
194 0 : if (str)
195 0 : ASN1_STRING_free(str);
196 :
197 : return 0;
198 : }
199 :
200 : /*
201 : * PKCS#8 DH is defined in PKCS#11 of all places. It is similar to DH in that
202 : * the AlgorithmIdentifier contains the paramaters, the private key is
203 : * explcitly included and the pubkey must be recalculated.
204 : */
205 :
206 0 : static int dh_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
207 : {
208 : const unsigned char *p, *pm;
209 : int pklen, pmlen;
210 : int ptype;
211 : void *pval;
212 : ASN1_STRING *pstr;
213 : X509_ALGOR *palg;
214 : ASN1_INTEGER *privkey = NULL;
215 :
216 : DH *dh = NULL;
217 :
218 0 : if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
219 : return 0;
220 :
221 0 : X509_ALGOR_get0(NULL, &ptype, &pval, palg);
222 :
223 0 : if (ptype != V_ASN1_SEQUENCE)
224 : goto decerr;
225 :
226 0 : if (!(privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)))
227 : goto decerr;
228 :
229 0 : pstr = pval;
230 0 : pm = pstr->data;
231 0 : pmlen = pstr->length;
232 0 : if (!(dh = d2i_dhp(pkey, &pm, pmlen)))
233 : goto decerr;
234 : /* We have parameters now set private key */
235 0 : if (!(dh->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) {
236 0 : DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR);
237 0 : goto dherr;
238 : }
239 : /* Calculate public key */
240 0 : if (!DH_generate_key(dh))
241 : goto dherr;
242 :
243 0 : EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
244 :
245 0 : ASN1_STRING_clear_free(privkey);
246 :
247 0 : return 1;
248 :
249 : decerr:
250 0 : DHerr(DH_F_DH_PRIV_DECODE, EVP_R_DECODE_ERROR);
251 : dherr:
252 0 : DH_free(dh);
253 0 : ASN1_STRING_clear_free(privkey);
254 0 : return 0;
255 : }
256 :
257 0 : static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
258 : {
259 : ASN1_STRING *params = NULL;
260 : ASN1_INTEGER *prkey = NULL;
261 0 : unsigned char *dp = NULL;
262 : int dplen;
263 :
264 0 : params = ASN1_STRING_new();
265 :
266 0 : if (!params) {
267 0 : DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
268 0 : goto err;
269 : }
270 :
271 0 : params->length = i2d_dhp(pkey, pkey->pkey.dh, ¶ms->data);
272 0 : if (params->length <= 0) {
273 0 : DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
274 0 : goto err;
275 : }
276 0 : params->type = V_ASN1_SEQUENCE;
277 :
278 : /* Get private key into integer */
279 0 : prkey = BN_to_ASN1_INTEGER(pkey->pkey.dh->priv_key, NULL);
280 :
281 0 : if (!prkey) {
282 0 : DHerr(DH_F_DH_PRIV_ENCODE, DH_R_BN_ERROR);
283 0 : goto err;
284 : }
285 :
286 0 : dplen = i2d_ASN1_INTEGER(prkey, &dp);
287 :
288 0 : ASN1_STRING_clear_free(prkey);
289 : prkey = NULL;
290 :
291 0 : if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
292 : V_ASN1_SEQUENCE, params, dp, dplen))
293 : goto err;
294 :
295 : return 1;
296 :
297 : err:
298 0 : if (dp != NULL)
299 0 : OPENSSL_free(dp);
300 0 : if (params != NULL)
301 0 : ASN1_STRING_free(params);
302 0 : if (prkey != NULL)
303 0 : ASN1_STRING_clear_free(prkey);
304 : return 0;
305 : }
306 :
307 0 : static void update_buflen(const BIGNUM *b, size_t *pbuflen)
308 : {
309 : size_t i;
310 0 : if (!b)
311 0 : return;
312 0 : if (*pbuflen < (i = (size_t)BN_num_bytes(b)))
313 0 : *pbuflen = i;
314 : }
315 :
316 0 : static int dh_param_decode(EVP_PKEY *pkey,
317 : const unsigned char **pder, int derlen)
318 : {
319 : DH *dh;
320 0 : if (!(dh = d2i_dhp(pkey, pder, derlen))) {
321 0 : DHerr(DH_F_DH_PARAM_DECODE, ERR_R_DH_LIB);
322 0 : return 0;
323 : }
324 0 : EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
325 0 : return 1;
326 : }
327 :
328 0 : static int dh_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
329 : {
330 0 : return i2d_dhp(pkey, pkey->pkey.dh, pder);
331 : }
332 :
333 0 : static int do_dh_print(BIO *bp, const DH *x, int indent,
334 : ASN1_PCTX *ctx, int ptype)
335 : {
336 : unsigned char *m = NULL;
337 : int reason = ERR_R_BUF_LIB, ret = 0;
338 0 : size_t buf_len = 0;
339 :
340 : const char *ktype = NULL;
341 :
342 : BIGNUM *priv_key, *pub_key;
343 :
344 0 : if (ptype == 2)
345 0 : priv_key = x->priv_key;
346 : else
347 : priv_key = NULL;
348 :
349 0 : if (ptype > 0)
350 0 : pub_key = x->pub_key;
351 : else
352 : pub_key = NULL;
353 :
354 0 : update_buflen(x->p, &buf_len);
355 :
356 0 : if (buf_len == 0) {
357 : reason = ERR_R_PASSED_NULL_PARAMETER;
358 : goto err;
359 : }
360 :
361 0 : update_buflen(x->g, &buf_len);
362 0 : update_buflen(x->q, &buf_len);
363 0 : update_buflen(x->j, &buf_len);
364 0 : update_buflen(x->counter, &buf_len);
365 0 : update_buflen(pub_key, &buf_len);
366 0 : update_buflen(priv_key, &buf_len);
367 :
368 0 : if (ptype == 2)
369 : ktype = "DH Private-Key";
370 0 : else if (ptype == 1)
371 : ktype = "DH Public-Key";
372 : else
373 : ktype = "DH Parameters";
374 :
375 0 : m = OPENSSL_malloc(buf_len + 10);
376 0 : if (m == NULL) {
377 : reason = ERR_R_MALLOC_FAILURE;
378 : goto err;
379 : }
380 :
381 0 : BIO_indent(bp, indent, 128);
382 0 : if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0)
383 : goto err;
384 0 : indent += 4;
385 :
386 0 : if (!ASN1_bn_print(bp, "private-key:", priv_key, m, indent))
387 : goto err;
388 0 : if (!ASN1_bn_print(bp, "public-key:", pub_key, m, indent))
389 : goto err;
390 :
391 0 : if (!ASN1_bn_print(bp, "prime:", x->p, m, indent))
392 : goto err;
393 0 : if (!ASN1_bn_print(bp, "generator:", x->g, m, indent))
394 : goto err;
395 0 : if (x->q && !ASN1_bn_print(bp, "subgroup order:", x->q, m, indent))
396 : goto err;
397 0 : if (x->j && !ASN1_bn_print(bp, "subgroup factor:", x->j, m, indent))
398 : goto err;
399 0 : if (x->seed) {
400 : int i;
401 0 : BIO_indent(bp, indent, 128);
402 0 : BIO_puts(bp, "seed:");
403 0 : for (i = 0; i < x->seedlen; i++) {
404 0 : if ((i % 15) == 0) {
405 0 : if (BIO_puts(bp, "\n") <= 0
406 0 : || !BIO_indent(bp, indent + 4, 128))
407 : goto err;
408 : }
409 0 : if (BIO_printf(bp, "%02x%s", x->seed[i],
410 0 : ((i + 1) == x->seedlen) ? "" : ":") <= 0)
411 : goto err;
412 : }
413 0 : if (BIO_write(bp, "\n", 1) <= 0)
414 : return (0);
415 : }
416 0 : if (x->counter && !ASN1_bn_print(bp, "counter:", x->counter, m, indent))
417 : goto err;
418 0 : if (x->length != 0) {
419 0 : BIO_indent(bp, indent, 128);
420 0 : if (BIO_printf(bp, "recommended-private-length: %d bits\n",
421 0 : (int)x->length) <= 0)
422 : goto err;
423 : }
424 :
425 : ret = 1;
426 : if (0) {
427 : err:
428 0 : DHerr(DH_F_DO_DH_PRINT, reason);
429 : }
430 0 : if (m != NULL)
431 0 : OPENSSL_free(m);
432 : return (ret);
433 : }
434 :
435 0 : static int int_dh_size(const EVP_PKEY *pkey)
436 : {
437 0 : return (DH_size(pkey->pkey.dh));
438 : }
439 :
440 0 : static int dh_bits(const EVP_PKEY *pkey)
441 : {
442 0 : return BN_num_bits(pkey->pkey.dh->p);
443 : }
444 :
445 0 : static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
446 : {
447 0 : if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) ||
448 0 : BN_cmp(a->pkey.dh->g, b->pkey.dh->g))
449 : return 0;
450 0 : else if (a->ameth == &dhx_asn1_meth) {
451 0 : if (BN_cmp(a->pkey.dh->q, b->pkey.dh->q))
452 : return 0;
453 : }
454 : return 1;
455 : }
456 :
457 0 : static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src)
458 : {
459 : BIGNUM *a;
460 0 : if (src) {
461 0 : a = BN_dup(src);
462 0 : if (!a)
463 : return 0;
464 : } else
465 : a = NULL;
466 0 : if (*dst)
467 0 : BN_free(*dst);
468 0 : *dst = a;
469 0 : return 1;
470 : }
471 :
472 0 : static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
473 : {
474 0 : if (is_x942 == -1)
475 0 : is_x942 = ! !from->q;
476 0 : if (!int_dh_bn_cpy(&to->p, from->p))
477 : return 0;
478 0 : if (!int_dh_bn_cpy(&to->g, from->g))
479 : return 0;
480 0 : if (is_x942) {
481 0 : if (!int_dh_bn_cpy(&to->q, from->q))
482 : return 0;
483 0 : if (!int_dh_bn_cpy(&to->j, from->j))
484 : return 0;
485 0 : if (to->seed) {
486 0 : OPENSSL_free(to->seed);
487 0 : to->seed = NULL;
488 0 : to->seedlen = 0;
489 : }
490 0 : if (from->seed) {
491 0 : to->seed = BUF_memdup(from->seed, from->seedlen);
492 0 : if (!to->seed)
493 : return 0;
494 0 : to->seedlen = from->seedlen;
495 : }
496 : } else
497 0 : to->length = from->length;
498 : return 1;
499 : }
500 :
501 0 : DH *DHparams_dup(DH *dh)
502 : {
503 : DH *ret;
504 0 : ret = DH_new();
505 0 : if (!ret)
506 : return NULL;
507 0 : if (!int_dh_param_copy(ret, dh, -1)) {
508 0 : DH_free(ret);
509 0 : return NULL;
510 : }
511 : return ret;
512 : }
513 :
514 0 : static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
515 : {
516 0 : return int_dh_param_copy(to->pkey.dh, from->pkey.dh,
517 0 : from->ameth == &dhx_asn1_meth);
518 : }
519 :
520 0 : static int dh_missing_parameters(const EVP_PKEY *a)
521 : {
522 0 : if (!a->pkey.dh->p || !a->pkey.dh->g)
523 : return 1;
524 0 : return 0;
525 : }
526 :
527 0 : static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
528 : {
529 0 : if (dh_cmp_parameters(a, b) == 0)
530 : return 0;
531 0 : if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0)
532 : return 0;
533 : else
534 0 : return 1;
535 : }
536 :
537 0 : static int dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
538 : ASN1_PCTX *ctx)
539 : {
540 0 : return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 0);
541 : }
542 :
543 0 : static int dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent,
544 : ASN1_PCTX *ctx)
545 : {
546 0 : return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 1);
547 : }
548 :
549 0 : static int dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent,
550 : ASN1_PCTX *ctx)
551 : {
552 0 : return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 2);
553 : }
554 :
555 0 : int DHparams_print(BIO *bp, const DH *x)
556 : {
557 0 : return do_dh_print(bp, x, 4, NULL, 0);
558 : }
559 :
560 : #ifndef OPENSSL_NO_CMS
561 : static int dh_cms_decrypt(CMS_RecipientInfo *ri);
562 : static int dh_cms_encrypt(CMS_RecipientInfo *ri);
563 : #endif
564 :
565 0 : static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
566 : {
567 0 : switch (op) {
568 : #ifndef OPENSSL_NO_CMS
569 :
570 : case ASN1_PKEY_CTRL_CMS_ENVELOPE:
571 0 : if (arg1 == 1)
572 0 : return dh_cms_decrypt(arg2);
573 0 : else if (arg1 == 0)
574 0 : return dh_cms_encrypt(arg2);
575 : return -2;
576 :
577 : case ASN1_PKEY_CTRL_CMS_RI_TYPE:
578 0 : *(int *)arg2 = CMS_RECIPINFO_AGREE;
579 0 : return 1;
580 : #endif
581 : default:
582 : return -2;
583 : }
584 :
585 : }
586 :
587 : const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
588 : EVP_PKEY_DH,
589 : EVP_PKEY_DH,
590 : 0,
591 :
592 : "DH",
593 : "OpenSSL PKCS#3 DH method",
594 :
595 : dh_pub_decode,
596 : dh_pub_encode,
597 : dh_pub_cmp,
598 : dh_public_print,
599 :
600 : dh_priv_decode,
601 : dh_priv_encode,
602 : dh_private_print,
603 :
604 : int_dh_size,
605 : dh_bits,
606 :
607 : dh_param_decode,
608 : dh_param_encode,
609 : dh_missing_parameters,
610 : dh_copy_parameters,
611 : dh_cmp_parameters,
612 : dh_param_print,
613 : 0,
614 :
615 : int_dh_free,
616 : 0
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 :
639 : dh_param_decode,
640 : dh_param_encode,
641 : dh_missing_parameters,
642 : dh_copy_parameters,
643 : dh_cmp_parameters,
644 : dh_param_print,
645 : 0,
646 :
647 : int_dh_free,
648 : dh_pkey_ctrl
649 : };
650 :
651 : #ifndef OPENSSL_NO_CMS
652 :
653 0 : static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
654 : X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
655 : {
656 : ASN1_OBJECT *aoid;
657 : int atype;
658 : void *aval;
659 : ASN1_INTEGER *public_key = NULL;
660 : int rv = 0;
661 : EVP_PKEY *pkpeer = NULL, *pk = NULL;
662 : DH *dhpeer = NULL;
663 : const unsigned char *p;
664 : int plen;
665 :
666 0 : X509_ALGOR_get0(&aoid, &atype, &aval, alg);
667 0 : if (OBJ_obj2nid(aoid) != NID_dhpublicnumber)
668 : goto err;
669 : /* Only absent parameters allowed in RFC XXXX */
670 0 : if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL)
671 : goto err;
672 :
673 0 : pk = EVP_PKEY_CTX_get0_pkey(pctx);
674 0 : if (!pk)
675 : goto err;
676 0 : if (pk->type != EVP_PKEY_DHX)
677 : goto err;
678 : /* Get parameters from parent key */
679 0 : dhpeer = DHparams_dup(pk->pkey.dh);
680 : /* We have parameters now set public key */
681 0 : plen = ASN1_STRING_length(pubkey);
682 0 : p = ASN1_STRING_data(pubkey);
683 0 : if (!p || !plen)
684 : goto err;
685 :
686 0 : if (!(public_key = d2i_ASN1_INTEGER(NULL, &p, plen))) {
687 0 : DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_DECODE_ERROR);
688 0 : goto err;
689 : }
690 :
691 : /* We have parameters now set public key */
692 0 : if (!(dhpeer->pub_key = ASN1_INTEGER_to_BN(public_key, NULL))) {
693 0 : DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_BN_DECODE_ERROR);
694 0 : goto err;
695 : }
696 :
697 0 : pkpeer = EVP_PKEY_new();
698 0 : if (!pkpeer)
699 : goto err;
700 0 : EVP_PKEY_assign(pkpeer, pk->ameth->pkey_id, dhpeer);
701 : dhpeer = NULL;
702 0 : if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
703 : rv = 1;
704 : err:
705 0 : if (public_key)
706 0 : ASN1_INTEGER_free(public_key);
707 0 : if (pkpeer)
708 0 : EVP_PKEY_free(pkpeer);
709 0 : if (dhpeer)
710 0 : DH_free(dhpeer);
711 0 : return rv;
712 : }
713 :
714 0 : static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
715 : {
716 : int rv = 0;
717 :
718 : X509_ALGOR *alg, *kekalg = NULL;
719 : ASN1_OCTET_STRING *ukm;
720 : const unsigned char *p;
721 : unsigned char *dukm = NULL;
722 : size_t dukmlen = 0;
723 : int keylen, plen;
724 : const EVP_CIPHER *kekcipher;
725 : EVP_CIPHER_CTX *kekctx;
726 :
727 0 : if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
728 : goto err;
729 :
730 : /*
731 : * For DH we only have one OID permissible. If ever any more get defined
732 : * we will need something cleverer.
733 : */
734 0 : if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) {
735 0 : DHerr(DH_F_DH_CMS_SET_SHARED_INFO, DH_R_KDF_PARAMETER_ERROR);
736 0 : goto err;
737 : }
738 :
739 0 : if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_X9_42) <= 0)
740 : goto err;
741 :
742 0 : if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0)
743 : goto err;
744 :
745 0 : if (alg->parameter->type != V_ASN1_SEQUENCE)
746 : goto err;
747 :
748 0 : p = alg->parameter->value.sequence->data;
749 0 : plen = alg->parameter->value.sequence->length;
750 0 : kekalg = d2i_X509_ALGOR(NULL, &p, plen);
751 0 : if (!kekalg)
752 : goto err;
753 0 : kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
754 0 : if (!kekctx)
755 : goto err;
756 0 : kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
757 0 : if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
758 : goto err;
759 0 : if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
760 : goto err;
761 0 : if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
762 : goto err;
763 :
764 0 : keylen = EVP_CIPHER_CTX_key_length(kekctx);
765 0 : if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
766 : goto err;
767 : /* Use OBJ_nid2obj to ensure we use built in OID that isn't freed */
768 0 : if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx,
769 : OBJ_nid2obj(EVP_CIPHER_type(kekcipher)))
770 : <= 0)
771 : goto err;
772 :
773 0 : if (ukm) {
774 0 : dukmlen = ASN1_STRING_length(ukm);
775 0 : dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen);
776 0 : if (!dukm)
777 : goto err;
778 : }
779 :
780 0 : if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
781 : goto err;
782 : dukm = NULL;
783 :
784 : rv = 1;
785 : err:
786 0 : if (kekalg)
787 0 : X509_ALGOR_free(kekalg);
788 0 : if (dukm)
789 0 : OPENSSL_free(dukm);
790 0 : return rv;
791 : }
792 :
793 0 : static int dh_cms_decrypt(CMS_RecipientInfo *ri)
794 : {
795 : EVP_PKEY_CTX *pctx;
796 0 : pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
797 0 : if (!pctx)
798 : return 0;
799 : /* See if we need to set peer key */
800 0 : if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
801 : X509_ALGOR *alg;
802 : ASN1_BIT_STRING *pubkey;
803 0 : if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
804 : NULL, NULL, NULL))
805 0 : return 0;
806 0 : if (!alg || !pubkey)
807 : return 0;
808 0 : if (!dh_cms_set_peerkey(pctx, alg, pubkey)) {
809 0 : DHerr(DH_F_DH_CMS_DECRYPT, DH_R_PEER_KEY_ERROR);
810 0 : return 0;
811 : }
812 : }
813 : /* Set DH derivation parameters and initialise unwrap context */
814 0 : if (!dh_cms_set_shared_info(pctx, ri)) {
815 0 : DHerr(DH_F_DH_CMS_DECRYPT, DH_R_SHARED_INFO_ERROR);
816 0 : return 0;
817 : }
818 : return 1;
819 : }
820 :
821 0 : static int dh_cms_encrypt(CMS_RecipientInfo *ri)
822 : {
823 : EVP_PKEY_CTX *pctx;
824 : EVP_PKEY *pkey;
825 : EVP_CIPHER_CTX *ctx;
826 : int keylen;
827 : X509_ALGOR *talg, *wrap_alg = NULL;
828 : ASN1_OBJECT *aoid;
829 : ASN1_BIT_STRING *pubkey;
830 : ASN1_STRING *wrap_str;
831 : ASN1_OCTET_STRING *ukm;
832 0 : unsigned char *penc = NULL, *dukm = NULL;
833 : int penclen;
834 : size_t dukmlen = 0;
835 : int rv = 0;
836 : int kdf_type, wrap_nid;
837 : const EVP_MD *kdf_md;
838 0 : pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
839 0 : if (!pctx)
840 : return 0;
841 : /* Get ephemeral key */
842 0 : pkey = EVP_PKEY_CTX_get0_pkey(pctx);
843 0 : if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
844 : NULL, NULL, NULL))
845 : goto err;
846 0 : X509_ALGOR_get0(&aoid, NULL, NULL, talg);
847 : /* Is everything uninitialised? */
848 0 : if (aoid == OBJ_nid2obj(NID_undef)) {
849 : ASN1_INTEGER *pubk;
850 0 : pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL);
851 0 : if (!pubk)
852 : goto err;
853 : /* Set the key */
854 :
855 0 : penclen = i2d_ASN1_INTEGER(pubk, &penc);
856 0 : ASN1_INTEGER_free(pubk);
857 0 : if (penclen <= 0)
858 : goto err;
859 0 : ASN1_STRING_set0(pubkey, penc, penclen);
860 0 : pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
861 0 : pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
862 :
863 0 : penc = NULL;
864 0 : X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber),
865 : V_ASN1_UNDEF, NULL);
866 : }
867 :
868 : /* See if custom paraneters set */
869 0 : kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx);
870 0 : if (kdf_type <= 0)
871 : goto err;
872 0 : if (!EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md))
873 : goto err;
874 :
875 0 : if (kdf_type == EVP_PKEY_DH_KDF_NONE) {
876 : kdf_type = EVP_PKEY_DH_KDF_X9_42;
877 0 : if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0)
878 : goto err;
879 0 : } else if (kdf_type != EVP_PKEY_DH_KDF_X9_42)
880 : /* Unknown KDF */
881 : goto err;
882 0 : if (kdf_md == NULL) {
883 : /* Only SHA1 supported */
884 0 : kdf_md = EVP_sha1();
885 0 : if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0)
886 : goto err;
887 0 : } else if (EVP_MD_type(kdf_md) != NID_sha1)
888 : /* Unsupported digest */
889 : goto err;
890 :
891 0 : if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
892 : goto err;
893 :
894 : /* Get wrap NID */
895 0 : ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
896 0 : wrap_nid = EVP_CIPHER_CTX_type(ctx);
897 0 : if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0)
898 : goto err;
899 0 : keylen = EVP_CIPHER_CTX_key_length(ctx);
900 :
901 : /* Package wrap algorithm in an AlgorithmIdentifier */
902 :
903 0 : wrap_alg = X509_ALGOR_new();
904 0 : if (!wrap_alg)
905 : goto err;
906 0 : wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
907 0 : wrap_alg->parameter = ASN1_TYPE_new();
908 0 : if (!wrap_alg->parameter)
909 : goto err;
910 0 : if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
911 : goto err;
912 0 : if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
913 0 : ASN1_TYPE_free(wrap_alg->parameter);
914 0 : wrap_alg->parameter = NULL;
915 : }
916 :
917 0 : if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0)
918 : goto err;
919 :
920 0 : if (ukm) {
921 0 : dukmlen = ASN1_STRING_length(ukm);
922 0 : dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen);
923 0 : if (!dukm)
924 : goto err;
925 : }
926 :
927 0 : if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0)
928 : goto err;
929 : dukm = NULL;
930 :
931 : /*
932 : * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
933 : * of another AlgorithmIdentifier.
934 : */
935 0 : penc = NULL;
936 0 : penclen = i2d_X509_ALGOR(wrap_alg, &penc);
937 0 : if (!penc || !penclen)
938 : goto err;
939 0 : wrap_str = ASN1_STRING_new();
940 0 : if (!wrap_str)
941 : goto err;
942 0 : ASN1_STRING_set0(wrap_str, penc, penclen);
943 0 : penc = NULL;
944 0 : X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH),
945 : V_ASN1_SEQUENCE, wrap_str);
946 :
947 : rv = 1;
948 :
949 : err:
950 0 : if (penc)
951 0 : OPENSSL_free(penc);
952 0 : if (wrap_alg)
953 0 : X509_ALGOR_free(wrap_alg);
954 0 : return rv;
955 : }
956 :
957 : #endif
|