xref: /openbsd-src/lib/libcrypto/cms/cms_env.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /* $OpenBSD: cms_env.c,v 1.7 2014/07/12 16:03:37 miod Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2008 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 
54 #include <openssl/aes.h>
55 #include <openssl/asn1t.h>
56 #include <openssl/cms.h>
57 #include <openssl/err.h>
58 #include <openssl/pem.h>
59 #include <openssl/rand.h>
60 #include <openssl/x509v3.h>
61 
62 #include "cms_lcl.h"
63 #include "asn1_locl.h"
64 
65 /* CMS EnvelopedData Utilities */
66 
67 DECLARE_ASN1_ITEM(CMS_EnvelopedData)
68 DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
69 DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo)
70 DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute)
71 
72 DECLARE_STACK_OF(CMS_RecipientInfo)
73 
74 CMS_EnvelopedData *
75 cms_get0_enveloped(CMS_ContentInfo *cms)
76 {
77 	if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) {
78 		CMSerr(CMS_F_CMS_GET0_ENVELOPED,
79 		    CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
80 		return NULL;
81 	}
82 	return cms->d.envelopedData;
83 }
84 
85 static CMS_EnvelopedData *
86 cms_enveloped_data_init(CMS_ContentInfo *cms)
87 {
88 	if (cms->d.other == NULL) {
89 		cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData);
90 		if (!cms->d.envelopedData) {
91 			CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT,
92 			    ERR_R_MALLOC_FAILURE);
93 			return NULL;
94 		}
95 		cms->d.envelopedData->version = 0;
96 		cms->d.envelopedData->encryptedContentInfo->contentType =
97 		    OBJ_nid2obj(NID_pkcs7_data);
98 		ASN1_OBJECT_free(cms->contentType);
99 		cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped);
100 		return cms->d.envelopedData;
101 	}
102 	return cms_get0_enveloped(cms);
103 }
104 
105 STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
106 {
107 	CMS_EnvelopedData *env;
108 
109 	env = cms_get0_enveloped(cms);
110 	if (!env)
111 		return NULL;
112 	return env->recipientInfos;
113 }
114 
115 int
116 CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
117 {
118 	return ri->type;
119 }
120 
121 CMS_ContentInfo *
122 CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
123 {
124 	CMS_ContentInfo *cms;
125 	CMS_EnvelopedData *env;
126 
127 	cms = CMS_ContentInfo_new();
128 	if (!cms)
129 		goto merr;
130 	env = cms_enveloped_data_init(cms);
131 	if (!env)
132 		goto merr;
133 	if (!cms_EncryptedContent_init(env->encryptedContentInfo,
134 	    cipher, NULL, 0))
135 		goto merr;
136 	return cms;
137 
138 merr:
139 	if (cms)
140 		CMS_ContentInfo_free(cms);
141 	CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);
142 	return NULL;
143 }
144 
145 /* Key Transport Recipient Info (KTRI) routines */
146 
147 /* Add a recipient certificate. For now only handle key transport.
148  * If we ever handle key agreement will need updating.
149  */
150 
151 CMS_RecipientInfo *
152 CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags)
153 {
154 	CMS_RecipientInfo *ri = NULL;
155 	CMS_KeyTransRecipientInfo *ktri;
156 	CMS_EnvelopedData *env;
157 	EVP_PKEY *pk = NULL;
158 	int i, type;
159 
160 	env = cms_get0_enveloped(cms);
161 	if (!env)
162 		goto err;
163 
164 	/* Initialize recipient info */
165 	ri = M_ASN1_new_of(CMS_RecipientInfo);
166 	if (!ri)
167 		goto merr;
168 
169 	/* Initialize and add key transport recipient info */
170 
171 	ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
172 	if (!ri->d.ktri)
173 		goto merr;
174 	ri->type = CMS_RECIPINFO_TRANS;
175 
176 	ktri = ri->d.ktri;
177 
178 	X509_check_purpose(recip, -1, -1);
179 	pk = X509_get_pubkey(recip);
180 	if (!pk) {
181 		CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
182 		    CMS_R_ERROR_GETTING_PUBLIC_KEY);
183 		goto err;
184 	}
185 	CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509);
186 	ktri->pkey = pk;
187 	ktri->recip = recip;
188 
189 	if (flags & CMS_USE_KEYID) {
190 		ktri->version = 2;
191 		type = CMS_RECIPINFO_KEYIDENTIFIER;
192 	} else {
193 		ktri->version = 0;
194 		type = CMS_RECIPINFO_ISSUER_SERIAL;
195 	}
196 
197 	/* Not a typo: RecipientIdentifier and SignerIdentifier are the
198 	 * same structure.
199 	 */
200 
201 	if (!cms_set1_SignerIdentifier(ktri->rid, recip, type))
202 		goto err;
203 
204 	if (pk->ameth && pk->ameth->pkey_ctrl) {
205 		i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_ENVELOPE,
206 		    0, ri);
207 		if (i == -2) {
208 			CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
209 			    CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
210 			goto err;
211 		}
212 		if (i <= 0) {
213 			CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
214 			    CMS_R_CTRL_FAILURE);
215 			goto err;
216 		}
217 	}
218 
219 	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
220 		goto merr;
221 
222 	return ri;
223 
224 merr:
225 	CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE);
226 err:
227 	if (ri)
228 		M_ASN1_free_of(ri, CMS_RecipientInfo);
229 	return NULL;
230 }
231 
232 int
233 CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, EVP_PKEY **pk,
234     X509 **recip, X509_ALGOR **palg)
235 {
236 	CMS_KeyTransRecipientInfo *ktri;
237 
238 	if (ri->type != CMS_RECIPINFO_TRANS) {
239 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS,
240 		    CMS_R_NOT_KEY_TRANSPORT);
241 		return 0;
242 	}
243 
244 	ktri = ri->d.ktri;
245 
246 	if (pk)
247 		*pk = ktri->pkey;
248 	if (recip)
249 		*recip = ktri->recip;
250 	if (palg)
251 		*palg = ktri->keyEncryptionAlgorithm;
252 	return 1;
253 }
254 
255 int
256 CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
257     ASN1_OCTET_STRING **keyid, X509_NAME **issuer, ASN1_INTEGER **sno)
258 {
259 	CMS_KeyTransRecipientInfo *ktri;
260 
261 	if (ri->type != CMS_RECIPINFO_TRANS) {
262 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID,
263 		    CMS_R_NOT_KEY_TRANSPORT);
264 		return 0;
265 	}
266 	ktri = ri->d.ktri;
267 
268 	return cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid,
269 	    issuer, sno);
270 }
271 
272 int
273 CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
274 {
275 	if (ri->type != CMS_RECIPINFO_TRANS) {
276 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP,
277 		    CMS_R_NOT_KEY_TRANSPORT);
278 		return -2;
279 	}
280 	return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
281 }
282 
283 int
284 CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)
285 {
286 	if (ri->type != CMS_RECIPINFO_TRANS) {
287 		CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY,
288 		    CMS_R_NOT_KEY_TRANSPORT);
289 		return 0;
290 	}
291 	ri->d.ktri->pkey = pkey;
292 	return 1;
293 }
294 
295 /* Encrypt content key in key transport recipient info */
296 
297 static int
298 cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
299 {
300 	CMS_KeyTransRecipientInfo *ktri;
301 	CMS_EncryptedContentInfo *ec;
302 	EVP_PKEY_CTX *pctx = NULL;
303 	unsigned char *ek = NULL;
304 	size_t eklen;
305 
306 	int ret = 0;
307 
308 	if (ri->type != CMS_RECIPINFO_TRANS) {
309 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
310 		    CMS_R_NOT_KEY_TRANSPORT);
311 		return 0;
312 	}
313 	ktri = ri->d.ktri;
314 	ec = cms->d.envelopedData->encryptedContentInfo;
315 
316 	pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
317 	if (!pctx)
318 		return 0;
319 
320 	if (EVP_PKEY_encrypt_init(pctx) <= 0)
321 		goto err;
322 
323 	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
324 	    EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) {
325 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR);
326 		goto err;
327 	}
328 
329 	if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
330 		goto err;
331 
332 	ek = malloc(eklen);
333 
334 	if (ek == NULL) {
335 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
336 		    ERR_R_MALLOC_FAILURE);
337 		goto err;
338 	}
339 
340 	if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0)
341 		goto err;
342 
343 	ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
344 	ek = NULL;
345 
346 	ret = 1;
347 
348 err:
349 	EVP_PKEY_CTX_free(pctx);
350 	free(ek);
351 	return ret;
352 }
353 
354 /* Decrypt content key from KTRI */
355 
356 static int
357 cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
358 {
359 	CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
360 	EVP_PKEY_CTX *pctx = NULL;
361 	unsigned char *ek = NULL;
362 	size_t eklen;
363 	int ret = 0;
364 	CMS_EncryptedContentInfo *ec;
365 
366 	ec = cms->d.envelopedData->encryptedContentInfo;
367 
368 	if (ktri->pkey == NULL) {
369 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT,
370 		    CMS_R_NO_PRIVATE_KEY);
371 		return 0;
372 	}
373 
374 	pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
375 	if (!pctx)
376 		return 0;
377 
378 	if (EVP_PKEY_decrypt_init(pctx) <= 0)
379 		goto err;
380 
381 	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
382 	    EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) {
383 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR);
384 		goto err;
385 	}
386 
387 	if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
388 	    ktri->encryptedKey->data,
389 	    ktri->encryptedKey->length) <= 0)
390 		goto err;
391 
392 	ek = malloc(eklen);
393 
394 	if (ek == NULL) {
395 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT,
396 		    ERR_R_MALLOC_FAILURE);
397 		goto err;
398 	}
399 
400 	if (EVP_PKEY_decrypt(pctx, ek, &eklen,
401 	    ktri->encryptedKey->data,
402 	    ktri->encryptedKey->length) <= 0) {
403 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB);
404 		goto err;
405 	}
406 
407 	ret = 1;
408 
409 	if (ec->key) {
410 		OPENSSL_cleanse(ec->key, ec->keylen);
411 		free(ec->key);
412 	}
413 
414 	ec->key = ek;
415 	ec->keylen = eklen;
416 
417 err:
418 	EVP_PKEY_CTX_free(pctx);
419 	if (!ret && ek)
420 		free(ek);
421 
422 	return ret;
423 }
424 
425 /* Key Encrypted Key (KEK) RecipientInfo routines */
426 
427 int
428 CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, const unsigned char *id,
429     size_t idlen)
430 {
431 	ASN1_OCTET_STRING tmp_os;
432 	CMS_KEKRecipientInfo *kekri;
433 
434 	if (ri->type != CMS_RECIPINFO_KEK) {
435 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK);
436 		return -2;
437 	}
438 	kekri = ri->d.kekri;
439 	tmp_os.type = V_ASN1_OCTET_STRING;
440 	tmp_os.flags = 0;
441 	tmp_os.data = (unsigned char *)id;
442 	tmp_os.length = (int)idlen;
443 	return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);
444 }
445 
446 /* For now hard code AES key wrap info */
447 
448 static size_t
449 aes_wrap_keylen(int nid)
450 {
451 	switch (nid) {
452 	case NID_id_aes128_wrap:
453 		return 16;
454 	case NID_id_aes192_wrap:
455 		return 24;
456 	case NID_id_aes256_wrap:
457 		return 32;
458 	default:
459 		return 0;
460 	}
461 }
462 
463 CMS_RecipientInfo *
464 CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, unsigned char *key,
465     size_t keylen, unsigned char *id, size_t idlen, ASN1_GENERALIZEDTIME *date,
466     ASN1_OBJECT *otherTypeId, ASN1_TYPE *otherType)
467 {
468 	CMS_RecipientInfo *ri = NULL;
469 	CMS_EnvelopedData *env;
470 	CMS_KEKRecipientInfo *kekri;
471 
472 	env = cms_get0_enveloped(cms);
473 	if (!env)
474 		goto err;
475 
476 	if (nid == NID_undef) {
477 		switch (keylen) {
478 		case 16:
479 			nid = NID_id_aes128_wrap;
480 			break;
481 		case  24:
482 			nid = NID_id_aes192_wrap;
483 			break;
484 		case  32:
485 			nid = NID_id_aes256_wrap;
486 			break;
487 		default:
488 			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
489 			    CMS_R_INVALID_KEY_LENGTH);
490 			goto err;
491 		}
492 	} else {
493 		size_t exp_keylen = aes_wrap_keylen(nid);
494 
495 		if (!exp_keylen) {
496 			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
497 			    CMS_R_UNSUPPORTED_KEK_ALGORITHM);
498 			goto err;
499 		}
500 
501 		if (keylen != exp_keylen) {
502 			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
503 			    CMS_R_INVALID_KEY_LENGTH);
504 			goto err;
505 		}
506 
507 	}
508 
509 	/* Initialize recipient info */
510 	ri = M_ASN1_new_of(CMS_RecipientInfo);
511 	if (!ri)
512 		goto merr;
513 
514 	ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo);
515 	if (!ri->d.kekri)
516 		goto merr;
517 	ri->type = CMS_RECIPINFO_KEK;
518 
519 	kekri = ri->d.kekri;
520 
521 	if (otherTypeId) {
522 		kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute);
523 		if (kekri->kekid->other == NULL)
524 			goto merr;
525 	}
526 
527 	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
528 		goto merr;
529 
530 	/* After this point no calls can fail */
531 
532 	kekri->version = 4;
533 
534 	kekri->key = key;
535 	kekri->keylen = keylen;
536 
537 	ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen);
538 
539 	kekri->kekid->date = date;
540 
541 	if (kekri->kekid->other) {
542 		kekri->kekid->other->keyAttrId = otherTypeId;
543 		kekri->kekid->other->keyAttr = otherType;
544 	}
545 
546 	X509_ALGOR_set0(kekri->keyEncryptionAlgorithm,
547 	    OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
548 
549 	return ri;
550 
551 merr:
552 	CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE);
553 err:
554 	if (ri)
555 		M_ASN1_free_of(ri, CMS_RecipientInfo);
556 	return NULL;
557 }
558 
559 int
560 CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, X509_ALGOR **palg,
561     ASN1_OCTET_STRING **pid, ASN1_GENERALIZEDTIME **pdate,
562     ASN1_OBJECT **potherid, ASN1_TYPE **pothertype)
563 {
564 	CMS_KEKIdentifier *rkid;
565 
566 	if (ri->type != CMS_RECIPINFO_KEK) {
567 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK);
568 		return 0;
569 	}
570 	rkid = ri->d.kekri->kekid;
571 	if (palg)
572 		*palg = ri->d.kekri->keyEncryptionAlgorithm;
573 	if (pid)
574 		*pid = rkid->keyIdentifier;
575 	if (pdate)
576 		*pdate = rkid->date;
577 	if (potherid) {
578 		if (rkid->other)
579 			*potherid = rkid->other->keyAttrId;
580 		else
581 			*potherid = NULL;
582 	}
583 	if (pothertype) {
584 		if (rkid->other)
585 			*pothertype = rkid->other->keyAttr;
586 		else
587 			*pothertype = NULL;
588 	}
589 	return 1;
590 }
591 
592 int
593 CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, unsigned char *key,
594     size_t keylen)
595 {
596 	CMS_KEKRecipientInfo *kekri;
597 
598 	if (ri->type != CMS_RECIPINFO_KEK) {
599 		CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK);
600 		return 0;
601 	}
602 
603 	kekri = ri->d.kekri;
604 	kekri->key = key;
605 	kekri->keylen = keylen;
606 	return 1;
607 }
608 
609 /* Encrypt content key in KEK recipient info */
610 
611 static int
612 cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
613 {
614 	CMS_EncryptedContentInfo *ec;
615 	CMS_KEKRecipientInfo *kekri;
616 	AES_KEY actx;
617 	unsigned char *wkey = NULL;
618 	int wkeylen;
619 	int r = 0;
620 
621 	ec = cms->d.envelopedData->encryptedContentInfo;
622 
623 	kekri = ri->d.kekri;
624 
625 	if (!kekri->key) {
626 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY);
627 		return 0;
628 	}
629 
630 	if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) {
631 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,
632 		    CMS_R_ERROR_SETTING_KEY);
633 		goto err;
634 	}
635 
636 	wkey = malloc(ec->keylen + 8);
637 
638 	if (!wkey) {
639 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,
640 		    ERR_R_MALLOC_FAILURE);
641 		goto err;
642 	}
643 
644 	wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen);
645 
646 	if (wkeylen <= 0) {
647 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR);
648 		goto err;
649 	}
650 
651 	ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen);
652 
653 	r = 1;
654 
655 err:
656 	if (!r && wkey)
657 		free(wkey);
658 	OPENSSL_cleanse(&actx, sizeof(actx));
659 
660 	return r;
661 }
662 
663 /* Decrypt content key in KEK recipient info */
664 
665 static int
666 cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
667 {
668 	CMS_EncryptedContentInfo *ec;
669 	CMS_KEKRecipientInfo *kekri;
670 	AES_KEY actx;
671 	unsigned char *ukey = NULL;
672 	int ukeylen;
673 	int r = 0, wrap_nid;
674 
675 	ec = cms->d.envelopedData->encryptedContentInfo;
676 
677 	kekri = ri->d.kekri;
678 
679 	if (!kekri->key) {
680 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY);
681 		return 0;
682 	}
683 
684 	wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
685 	if (aes_wrap_keylen(wrap_nid) != kekri->keylen) {
686 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
687 		    CMS_R_INVALID_KEY_LENGTH);
688 		return 0;
689 	}
690 
691 	/* If encrypted key length is invalid don't bother */
692 
693 	if (kekri->encryptedKey->length < 16) {
694 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
695 		    CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);
696 		goto err;
697 	}
698 
699 	if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) {
700 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
701 		    CMS_R_ERROR_SETTING_KEY);
702 		goto err;
703 	}
704 
705 	ukey = malloc(kekri->encryptedKey->length - 8);
706 
707 	if (!ukey) {
708 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
709 		    ERR_R_MALLOC_FAILURE);
710 		goto err;
711 	}
712 
713 	ukeylen = AES_unwrap_key(&actx, NULL, ukey,
714 	    kekri->encryptedKey->data,
715 	    kekri->encryptedKey->length);
716 
717 	if (ukeylen <= 0) {
718 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
719 		    CMS_R_UNWRAP_ERROR);
720 		goto err;
721 	}
722 
723 	ec->key = ukey;
724 	ec->keylen = ukeylen;
725 
726 	r = 1;
727 
728 err:
729 	if (!r && ukey)
730 		free(ukey);
731 	OPENSSL_cleanse(&actx, sizeof(actx));
732 
733 	return r;
734 }
735 
736 int
737 CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
738 {
739 	switch (ri->type) {
740 	case CMS_RECIPINFO_TRANS:
741 		return cms_RecipientInfo_ktri_decrypt(cms, ri);
742 	case CMS_RECIPINFO_KEK:
743 		return cms_RecipientInfo_kekri_decrypt(cms, ri);
744 	case CMS_RECIPINFO_PASS:
745 		return cms_RecipientInfo_pwri_crypt(cms, ri, 0);
746 	default:
747 		CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT,
748 		    CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE);
749 		return 0;
750 	}
751 }
752 
753 BIO *
754 cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
755 {
756 	CMS_EncryptedContentInfo *ec;
757 	STACK_OF(CMS_RecipientInfo) *rinfos;
758 	CMS_RecipientInfo *ri;
759 	int i, r, ok = 0;
760 	BIO *ret;
761 
762 	/* Get BIO first to set up key */
763 
764 	ec = cms->d.envelopedData->encryptedContentInfo;
765 	ret = cms_EncryptedContent_init_bio(ec);
766 
767 	/* If error or no cipher end of processing */
768 
769 	if (!ret || !ec->cipher)
770 		return ret;
771 
772 	/* Now encrypt content key according to each RecipientInfo type */
773 
774 	rinfos = cms->d.envelopedData->recipientInfos;
775 
776 	for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
777 		ri = sk_CMS_RecipientInfo_value(rinfos, i);
778 
779 		switch (ri->type) {
780 		case CMS_RECIPINFO_TRANS:
781 			r = cms_RecipientInfo_ktri_encrypt(cms, ri);
782 			break;
783 
784 		case CMS_RECIPINFO_KEK:
785 			r = cms_RecipientInfo_kekri_encrypt(cms, ri);
786 			break;
787 
788 		case CMS_RECIPINFO_PASS:
789 			r = cms_RecipientInfo_pwri_crypt(cms, ri, 1);
790 			break;
791 
792 		default:
793 			CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
794 			    CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
795 			goto err;
796 		}
797 
798 		if (r <= 0) {
799 			CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
800 			    CMS_R_ERROR_SETTING_RECIPIENTINFO);
801 			goto err;
802 		}
803 	}
804 
805 	ok = 1;
806 
807 err:
808 	ec->cipher = NULL;
809 	if (ec->key) {
810 		OPENSSL_cleanse(ec->key, ec->keylen);
811 		free(ec->key);
812 		ec->key = NULL;
813 		ec->keylen = 0;
814 	}
815 	if (ok)
816 		return ret;
817 	BIO_free(ret);
818 	return NULL;
819 }
820