1183234Ssimon/* crypto/cms/cms_env.c */
2183234Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3183234Ssimon * project.
4183234Ssimon */
5183234Ssimon/* ====================================================================
6183234Ssimon * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
7183234Ssimon *
8183234Ssimon * Redistribution and use in source and binary forms, with or without
9183234Ssimon * modification, are permitted provided that the following conditions
10183234Ssimon * are met:
11183234Ssimon *
12183234Ssimon * 1. Redistributions of source code must retain the above copyright
13183234Ssimon *    notice, this list of conditions and the following disclaimer.
14183234Ssimon *
15183234Ssimon * 2. Redistributions in binary form must reproduce the above copyright
16183234Ssimon *    notice, this list of conditions and the following disclaimer in
17183234Ssimon *    the documentation and/or other materials provided with the
18183234Ssimon *    distribution.
19183234Ssimon *
20183234Ssimon * 3. All advertising materials mentioning features or use of this
21183234Ssimon *    software must display the following acknowledgment:
22183234Ssimon *    "This product includes software developed by the OpenSSL Project
23183234Ssimon *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24183234Ssimon *
25183234Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26183234Ssimon *    endorse or promote products derived from this software without
27183234Ssimon *    prior written permission. For written permission, please contact
28183234Ssimon *    licensing@OpenSSL.org.
29183234Ssimon *
30183234Ssimon * 5. Products derived from this software may not be called "OpenSSL"
31183234Ssimon *    nor may "OpenSSL" appear in their names without prior written
32183234Ssimon *    permission of the OpenSSL Project.
33183234Ssimon *
34183234Ssimon * 6. Redistributions of any form whatsoever must retain the following
35183234Ssimon *    acknowledgment:
36183234Ssimon *    "This product includes software developed by the OpenSSL Project
37183234Ssimon *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38183234Ssimon *
39183234Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40183234Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41183234Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42183234Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43183234Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44183234Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45183234Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46183234Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47183234Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48183234Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49183234Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50183234Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
51183234Ssimon * ====================================================================
52183234Ssimon */
53183234Ssimon
54183234Ssimon#include "cryptlib.h"
55183234Ssimon#include <openssl/asn1t.h>
56183234Ssimon#include <openssl/pem.h>
57183234Ssimon#include <openssl/x509v3.h>
58183234Ssimon#include <openssl/err.h>
59183234Ssimon#include <openssl/cms.h>
60183234Ssimon#include <openssl/rand.h>
61183234Ssimon#include <openssl/aes.h>
62183234Ssimon#include "cms_lcl.h"
63238405Sjkim#include "asn1_locl.h"
64183234Ssimon
65183234Ssimon/* CMS EnvelopedData Utilities */
66183234Ssimon
67183234SsimonDECLARE_ASN1_ITEM(CMS_EnvelopedData)
68183234SsimonDECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
69183234SsimonDECLARE_ASN1_ITEM(CMS_KEKRecipientInfo)
70183234SsimonDECLARE_ASN1_ITEM(CMS_OtherKeyAttribute)
71183234Ssimon
72183234SsimonDECLARE_STACK_OF(CMS_RecipientInfo)
73183234Ssimon
74238405SjkimCMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
75183234Ssimon	{
76183234Ssimon	if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped)
77183234Ssimon		{
78183234Ssimon		CMSerr(CMS_F_CMS_GET0_ENVELOPED,
79183234Ssimon				CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
80183234Ssimon		return NULL;
81183234Ssimon		}
82183234Ssimon	return cms->d.envelopedData;
83183234Ssimon	}
84183234Ssimon
85183234Ssimonstatic CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)
86183234Ssimon	{
87183234Ssimon	if (cms->d.other == NULL)
88183234Ssimon		{
89183234Ssimon		cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData);
90183234Ssimon		if (!cms->d.envelopedData)
91183234Ssimon			{
92183234Ssimon			CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT,
93183234Ssimon							ERR_R_MALLOC_FAILURE);
94183234Ssimon			return NULL;
95183234Ssimon			}
96183234Ssimon		cms->d.envelopedData->version = 0;
97183234Ssimon		cms->d.envelopedData->encryptedContentInfo->contentType =
98183234Ssimon						OBJ_nid2obj(NID_pkcs7_data);
99183234Ssimon		ASN1_OBJECT_free(cms->contentType);
100183234Ssimon		cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped);
101183234Ssimon		return cms->d.envelopedData;
102183234Ssimon		}
103183234Ssimon	return cms_get0_enveloped(cms);
104183234Ssimon	}
105183234Ssimon
106183234SsimonSTACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
107183234Ssimon	{
108183234Ssimon	CMS_EnvelopedData *env;
109183234Ssimon	env = cms_get0_enveloped(cms);
110183234Ssimon	if (!env)
111183234Ssimon		return NULL;
112183234Ssimon	return env->recipientInfos;
113183234Ssimon	}
114183234Ssimon
115183234Ssimonint CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
116183234Ssimon	{
117183234Ssimon	return ri->type;
118183234Ssimon	}
119183234Ssimon
120183234SsimonCMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
121183234Ssimon	{
122183234Ssimon	CMS_ContentInfo *cms;
123183234Ssimon	CMS_EnvelopedData *env;
124183234Ssimon	cms = CMS_ContentInfo_new();
125183234Ssimon	if (!cms)
126183234Ssimon		goto merr;
127183234Ssimon	env = cms_enveloped_data_init(cms);
128183234Ssimon	if (!env)
129183234Ssimon		goto merr;
130183234Ssimon	if (!cms_EncryptedContent_init(env->encryptedContentInfo,
131183234Ssimon					cipher, NULL, 0))
132183234Ssimon		goto merr;
133183234Ssimon	return cms;
134183234Ssimon	merr:
135183234Ssimon	if (cms)
136183234Ssimon		CMS_ContentInfo_free(cms);
137183234Ssimon	CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);
138183234Ssimon	return NULL;
139183234Ssimon	}
140183234Ssimon
141183234Ssimon/* Key Transport Recipient Info (KTRI) routines */
142183234Ssimon
143183234Ssimon/* Add a recipient certificate. For now only handle key transport.
144183234Ssimon * If we ever handle key agreement will need updating.
145183234Ssimon */
146183234Ssimon
147183234SsimonCMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
148183234Ssimon					X509 *recip, unsigned int flags)
149183234Ssimon	{
150183234Ssimon	CMS_RecipientInfo *ri = NULL;
151183234Ssimon	CMS_KeyTransRecipientInfo *ktri;
152183234Ssimon	CMS_EnvelopedData *env;
153183234Ssimon	EVP_PKEY *pk = NULL;
154238405Sjkim	int i, type;
155183234Ssimon	env = cms_get0_enveloped(cms);
156183234Ssimon	if (!env)
157183234Ssimon		goto err;
158183234Ssimon
159183234Ssimon	/* Initialize recipient info */
160183234Ssimon	ri = M_ASN1_new_of(CMS_RecipientInfo);
161183234Ssimon	if (!ri)
162183234Ssimon		goto merr;
163183234Ssimon
164183234Ssimon	/* Initialize and add key transport recipient info */
165183234Ssimon
166183234Ssimon	ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
167183234Ssimon	if (!ri->d.ktri)
168183234Ssimon		goto merr;
169183234Ssimon	ri->type = CMS_RECIPINFO_TRANS;
170183234Ssimon
171183234Ssimon	ktri = ri->d.ktri;
172183234Ssimon
173183234Ssimon	X509_check_purpose(recip, -1, -1);
174183234Ssimon	pk = X509_get_pubkey(recip);
175183234Ssimon	if (!pk)
176183234Ssimon		{
177183234Ssimon		CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
178183234Ssimon				CMS_R_ERROR_GETTING_PUBLIC_KEY);
179183234Ssimon		goto err;
180183234Ssimon		}
181183234Ssimon	CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509);
182183234Ssimon	ktri->pkey = pk;
183183234Ssimon	ktri->recip = recip;
184183234Ssimon
185183234Ssimon	if (flags & CMS_USE_KEYID)
186183234Ssimon		{
187183234Ssimon		ktri->version = 2;
188279264Sdelphij		if (env->version < 2)
189279264Sdelphij			env->version = 2;
190183234Ssimon		type = CMS_RECIPINFO_KEYIDENTIFIER;
191183234Ssimon		}
192183234Ssimon	else
193183234Ssimon		{
194183234Ssimon		ktri->version = 0;
195183234Ssimon		type = CMS_RECIPINFO_ISSUER_SERIAL;
196183234Ssimon		}
197183234Ssimon
198183234Ssimon	/* Not a typo: RecipientIdentifier and SignerIdentifier are the
199183234Ssimon	 * same structure.
200183234Ssimon	 */
201183234Ssimon
202183234Ssimon	if (!cms_set1_SignerIdentifier(ktri->rid, recip, type))
203183234Ssimon		goto err;
204183234Ssimon
205238405Sjkim	if (pk->ameth && pk->ameth->pkey_ctrl)
206183234Ssimon		{
207238405Sjkim		i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_ENVELOPE,
208238405Sjkim						0, ri);
209238405Sjkim		if (i == -2)
210238405Sjkim			{
211238405Sjkim			CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
212183234Ssimon				CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
213238405Sjkim			goto err;
214238405Sjkim			}
215238405Sjkim		if (i <= 0)
216238405Sjkim			{
217238405Sjkim			CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
218238405Sjkim				CMS_R_CTRL_FAILURE);
219238405Sjkim			goto err;
220238405Sjkim			}
221183234Ssimon		}
222183234Ssimon
223183234Ssimon	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
224183234Ssimon		goto merr;
225183234Ssimon
226183234Ssimon	return ri;
227183234Ssimon
228183234Ssimon	merr:
229183234Ssimon	CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE);
230183234Ssimon	err:
231183234Ssimon	if (ri)
232183234Ssimon		M_ASN1_free_of(ri, CMS_RecipientInfo);
233183234Ssimon	return NULL;
234183234Ssimon
235183234Ssimon	}
236183234Ssimon
237183234Ssimonint CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
238183234Ssimon					EVP_PKEY **pk, X509 **recip,
239183234Ssimon					X509_ALGOR **palg)
240183234Ssimon	{
241183234Ssimon	CMS_KeyTransRecipientInfo *ktri;
242183234Ssimon	if (ri->type != CMS_RECIPINFO_TRANS)
243183234Ssimon		{
244183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS,
245183234Ssimon			CMS_R_NOT_KEY_TRANSPORT);
246183234Ssimon		return 0;
247183234Ssimon		}
248183234Ssimon
249183234Ssimon	ktri = ri->d.ktri;
250183234Ssimon
251183234Ssimon	if (pk)
252183234Ssimon		*pk = ktri->pkey;
253183234Ssimon	if (recip)
254183234Ssimon		*recip = ktri->recip;
255183234Ssimon	if (palg)
256183234Ssimon		*palg = ktri->keyEncryptionAlgorithm;
257183234Ssimon	return 1;
258183234Ssimon	}
259183234Ssimon
260183234Ssimonint CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
261183234Ssimon					ASN1_OCTET_STRING **keyid,
262183234Ssimon					X509_NAME **issuer, ASN1_INTEGER **sno)
263183234Ssimon	{
264183234Ssimon	CMS_KeyTransRecipientInfo *ktri;
265183234Ssimon	if (ri->type != CMS_RECIPINFO_TRANS)
266183234Ssimon		{
267183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID,
268183234Ssimon			CMS_R_NOT_KEY_TRANSPORT);
269183234Ssimon		return 0;
270183234Ssimon		}
271183234Ssimon	ktri = ri->d.ktri;
272183234Ssimon
273183234Ssimon	return cms_SignerIdentifier_get0_signer_id(ktri->rid,
274183234Ssimon							keyid, issuer, sno);
275183234Ssimon	}
276183234Ssimon
277183234Ssimonint CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
278183234Ssimon	{
279183234Ssimon	if (ri->type != CMS_RECIPINFO_TRANS)
280183234Ssimon		{
281183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP,
282183234Ssimon			CMS_R_NOT_KEY_TRANSPORT);
283183234Ssimon		return -2;
284183234Ssimon		}
285183234Ssimon	return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
286183234Ssimon	}
287183234Ssimon
288183234Ssimonint CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)
289183234Ssimon	{
290183234Ssimon	if (ri->type != CMS_RECIPINFO_TRANS)
291183234Ssimon		{
292183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY,
293183234Ssimon			CMS_R_NOT_KEY_TRANSPORT);
294183234Ssimon		return 0;
295183234Ssimon		}
296183234Ssimon	ri->d.ktri->pkey = pkey;
297183234Ssimon	return 1;
298183234Ssimon	}
299183234Ssimon
300183234Ssimon/* Encrypt content key in key transport recipient info */
301183234Ssimon
302183234Ssimonstatic int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
303183234Ssimon					CMS_RecipientInfo *ri)
304183234Ssimon	{
305183234Ssimon	CMS_KeyTransRecipientInfo *ktri;
306183234Ssimon	CMS_EncryptedContentInfo *ec;
307238405Sjkim	EVP_PKEY_CTX *pctx = NULL;
308183234Ssimon	unsigned char *ek = NULL;
309238405Sjkim	size_t eklen;
310183234Ssimon
311183234Ssimon	int ret = 0;
312183234Ssimon
313183234Ssimon	if (ri->type != CMS_RECIPINFO_TRANS)
314183234Ssimon		{
315183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
316183234Ssimon			CMS_R_NOT_KEY_TRANSPORT);
317183234Ssimon		return 0;
318183234Ssimon		}
319183234Ssimon	ktri = ri->d.ktri;
320183234Ssimon	ec = cms->d.envelopedData->encryptedContentInfo;
321183234Ssimon
322238405Sjkim	pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
323238405Sjkim	if (!pctx)
324238405Sjkim		return 0;
325183234Ssimon
326238405Sjkim	if (EVP_PKEY_encrypt_init(pctx) <= 0)
327238405Sjkim		goto err;
328238405Sjkim
329238405Sjkim	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
330238405Sjkim				EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0)
331238405Sjkim		{
332238405Sjkim		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR);
333238405Sjkim		goto err;
334238405Sjkim		}
335238405Sjkim
336238405Sjkim	if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
337238405Sjkim		goto err;
338238405Sjkim
339183234Ssimon	ek = OPENSSL_malloc(eklen);
340183234Ssimon
341183234Ssimon	if (ek == NULL)
342183234Ssimon		{
343183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
344183234Ssimon							ERR_R_MALLOC_FAILURE);
345183234Ssimon		goto err;
346183234Ssimon		}
347183234Ssimon
348238405Sjkim	if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0)
349183234Ssimon		goto err;
350183234Ssimon
351183234Ssimon	ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
352183234Ssimon	ek = NULL;
353183234Ssimon
354183234Ssimon	ret = 1;
355183234Ssimon
356183234Ssimon	err:
357238405Sjkim	if (pctx)
358238405Sjkim		EVP_PKEY_CTX_free(pctx);
359183234Ssimon	if (ek)
360183234Ssimon		OPENSSL_free(ek);
361183234Ssimon	return ret;
362183234Ssimon
363183234Ssimon	}
364183234Ssimon
365183234Ssimon/* Decrypt content key from KTRI */
366183234Ssimon
367183234Ssimonstatic int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
368183234Ssimon							CMS_RecipientInfo *ri)
369183234Ssimon	{
370183234Ssimon	CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
371238405Sjkim	EVP_PKEY_CTX *pctx = NULL;
372183234Ssimon	unsigned char *ek = NULL;
373238405Sjkim	size_t eklen;
374183234Ssimon	int ret = 0;
375237657Sjkim	CMS_EncryptedContentInfo *ec;
376237657Sjkim	ec = cms->d.envelopedData->encryptedContentInfo;
377183234Ssimon
378183234Ssimon	if (ktri->pkey == NULL)
379183234Ssimon		{
380183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT,
381183234Ssimon			CMS_R_NO_PRIVATE_KEY);
382183234Ssimon		return 0;
383183234Ssimon		}
384183234Ssimon
385238405Sjkim	pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
386238405Sjkim	if (!pctx)
387238405Sjkim		return 0;
388183234Ssimon
389238405Sjkim	if (EVP_PKEY_decrypt_init(pctx) <= 0)
390238405Sjkim		goto err;
391238405Sjkim
392238405Sjkim	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
393238405Sjkim				EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0)
394238405Sjkim		{
395238405Sjkim		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR);
396238405Sjkim		goto err;
397238405Sjkim		}
398238405Sjkim
399238405Sjkim	if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
400238405Sjkim				ktri->encryptedKey->data,
401238405Sjkim				ktri->encryptedKey->length) <= 0)
402238405Sjkim		goto err;
403238405Sjkim
404183234Ssimon	ek = OPENSSL_malloc(eklen);
405183234Ssimon
406183234Ssimon	if (ek == NULL)
407183234Ssimon		{
408183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT,
409183234Ssimon							ERR_R_MALLOC_FAILURE);
410183234Ssimon		goto err;
411183234Ssimon		}
412183234Ssimon
413238405Sjkim	if (EVP_PKEY_decrypt(pctx, ek, &eklen,
414183234Ssimon				ktri->encryptedKey->data,
415238405Sjkim				ktri->encryptedKey->length) <= 0)
416183234Ssimon		{
417183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB);
418183234Ssimon		goto err;
419183234Ssimon		}
420183234Ssimon
421183234Ssimon	ret = 1;
422183234Ssimon
423237657Sjkim	if (ec->key)
424237657Sjkim		{
425237657Sjkim		OPENSSL_cleanse(ec->key, ec->keylen);
426237657Sjkim		OPENSSL_free(ec->key);
427237657Sjkim		}
428183234Ssimon
429237657Sjkim	ec->key = ek;
430237657Sjkim	ec->keylen = eklen;
431237657Sjkim
432183234Ssimon	err:
433238405Sjkim	if (pctx)
434238405Sjkim		EVP_PKEY_CTX_free(pctx);
435183234Ssimon	if (!ret && ek)
436183234Ssimon		OPENSSL_free(ek);
437183234Ssimon
438183234Ssimon	return ret;
439183234Ssimon	}
440183234Ssimon
441183234Ssimon/* Key Encrypted Key (KEK) RecipientInfo routines */
442183234Ssimon
443183234Ssimonint CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
444183234Ssimon					const unsigned char *id, size_t idlen)
445183234Ssimon	{
446183234Ssimon	ASN1_OCTET_STRING tmp_os;
447183234Ssimon	CMS_KEKRecipientInfo *kekri;
448183234Ssimon	if (ri->type != CMS_RECIPINFO_KEK)
449183234Ssimon		{
450183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK);
451183234Ssimon		return -2;
452183234Ssimon		}
453183234Ssimon	kekri = ri->d.kekri;
454183234Ssimon	tmp_os.type = V_ASN1_OCTET_STRING;
455183234Ssimon	tmp_os.flags = 0;
456183234Ssimon	tmp_os.data = (unsigned char *)id;
457183234Ssimon	tmp_os.length = (int)idlen;
458183234Ssimon	return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);
459183234Ssimon	}
460183234Ssimon
461183234Ssimon/* For now hard code AES key wrap info */
462183234Ssimon
463183234Ssimonstatic size_t aes_wrap_keylen(int nid)
464183234Ssimon	{
465183234Ssimon	switch (nid)
466183234Ssimon		{
467183234Ssimon		case NID_id_aes128_wrap:
468183234Ssimon		return 16;
469183234Ssimon
470183234Ssimon		case NID_id_aes192_wrap:
471183234Ssimon		return  24;
472183234Ssimon
473183234Ssimon		case NID_id_aes256_wrap:
474183234Ssimon		return  32;
475183234Ssimon
476183234Ssimon		default:
477183234Ssimon		return 0;
478183234Ssimon		}
479183234Ssimon	}
480183234Ssimon
481183234SsimonCMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
482183234Ssimon					unsigned char *key, size_t keylen,
483183234Ssimon					unsigned char *id, size_t idlen,
484183234Ssimon					ASN1_GENERALIZEDTIME *date,
485183234Ssimon					ASN1_OBJECT *otherTypeId,
486183234Ssimon					ASN1_TYPE *otherType)
487183234Ssimon	{
488183234Ssimon	CMS_RecipientInfo *ri = NULL;
489183234Ssimon	CMS_EnvelopedData *env;
490183234Ssimon	CMS_KEKRecipientInfo *kekri;
491183234Ssimon	env = cms_get0_enveloped(cms);
492183234Ssimon	if (!env)
493183234Ssimon		goto err;
494183234Ssimon
495183234Ssimon	if (nid == NID_undef)
496183234Ssimon		{
497183234Ssimon		switch (keylen)
498183234Ssimon			{
499183234Ssimon			case 16:
500183234Ssimon			nid = NID_id_aes128_wrap;
501183234Ssimon			break;
502183234Ssimon
503183234Ssimon			case  24:
504183234Ssimon			nid = NID_id_aes192_wrap;
505183234Ssimon			break;
506183234Ssimon
507183234Ssimon			case  32:
508183234Ssimon			nid = NID_id_aes256_wrap;
509183234Ssimon			break;
510183234Ssimon
511183234Ssimon			default:
512183234Ssimon			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
513183234Ssimon						CMS_R_INVALID_KEY_LENGTH);
514183234Ssimon			goto err;
515183234Ssimon			}
516183234Ssimon
517183234Ssimon		}
518183234Ssimon	else
519183234Ssimon		{
520183234Ssimon
521183234Ssimon		size_t exp_keylen = aes_wrap_keylen(nid);
522183234Ssimon
523183234Ssimon		if (!exp_keylen)
524183234Ssimon			{
525183234Ssimon			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
526183234Ssimon					CMS_R_UNSUPPORTED_KEK_ALGORITHM);
527183234Ssimon			goto err;
528183234Ssimon			}
529183234Ssimon
530183234Ssimon		if (keylen != exp_keylen)
531183234Ssimon			{
532183234Ssimon			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
533183234Ssimon					CMS_R_INVALID_KEY_LENGTH);
534183234Ssimon			goto err;
535183234Ssimon			}
536183234Ssimon
537183234Ssimon		}
538183234Ssimon
539183234Ssimon	/* Initialize recipient info */
540183234Ssimon	ri = M_ASN1_new_of(CMS_RecipientInfo);
541183234Ssimon	if (!ri)
542183234Ssimon		goto merr;
543183234Ssimon
544183234Ssimon	ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo);
545183234Ssimon	if (!ri->d.kekri)
546183234Ssimon		goto merr;
547183234Ssimon	ri->type = CMS_RECIPINFO_KEK;
548183234Ssimon
549183234Ssimon	kekri = ri->d.kekri;
550183234Ssimon
551183234Ssimon	if (otherTypeId)
552183234Ssimon		{
553183234Ssimon		kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute);
554183234Ssimon		if (kekri->kekid->other == NULL)
555183234Ssimon			goto merr;
556183234Ssimon		}
557183234Ssimon
558183234Ssimon	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
559183234Ssimon		goto merr;
560183234Ssimon
561183234Ssimon
562183234Ssimon	/* After this point no calls can fail */
563183234Ssimon
564183234Ssimon	kekri->version = 4;
565183234Ssimon
566183234Ssimon	kekri->key = key;
567183234Ssimon	kekri->keylen = keylen;
568183234Ssimon
569183234Ssimon	ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen);
570183234Ssimon
571183234Ssimon	kekri->kekid->date = date;
572183234Ssimon
573183234Ssimon	if (kekri->kekid->other)
574183234Ssimon		{
575183234Ssimon		kekri->kekid->other->keyAttrId = otherTypeId;
576183234Ssimon		kekri->kekid->other->keyAttr = otherType;
577183234Ssimon		}
578183234Ssimon
579183234Ssimon	X509_ALGOR_set0(kekri->keyEncryptionAlgorithm,
580183234Ssimon				OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
581183234Ssimon
582183234Ssimon	return ri;
583183234Ssimon
584183234Ssimon	merr:
585183234Ssimon	CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE);
586183234Ssimon	err:
587183234Ssimon	if (ri)
588183234Ssimon		M_ASN1_free_of(ri, CMS_RecipientInfo);
589183234Ssimon	return NULL;
590183234Ssimon
591183234Ssimon	}
592183234Ssimon
593183234Ssimonint CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
594183234Ssimon					X509_ALGOR **palg,
595183234Ssimon					ASN1_OCTET_STRING **pid,
596183234Ssimon					ASN1_GENERALIZEDTIME **pdate,
597183234Ssimon					ASN1_OBJECT **potherid,
598183234Ssimon					ASN1_TYPE **pothertype)
599183234Ssimon	{
600183234Ssimon	CMS_KEKIdentifier *rkid;
601183234Ssimon	if (ri->type != CMS_RECIPINFO_KEK)
602183234Ssimon		{
603183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK);
604183234Ssimon		return 0;
605183234Ssimon		}
606183234Ssimon	rkid =  ri->d.kekri->kekid;
607183234Ssimon	if (palg)
608183234Ssimon		*palg = ri->d.kekri->keyEncryptionAlgorithm;
609183234Ssimon	if (pid)
610183234Ssimon		*pid = rkid->keyIdentifier;
611183234Ssimon	if (pdate)
612183234Ssimon		*pdate = rkid->date;
613183234Ssimon	if (potherid)
614183234Ssimon		{
615183234Ssimon		if (rkid->other)
616183234Ssimon			*potherid = rkid->other->keyAttrId;
617183234Ssimon		else
618183234Ssimon			*potherid = NULL;
619183234Ssimon		}
620183234Ssimon	if (pothertype)
621183234Ssimon		{
622183234Ssimon		if (rkid->other)
623183234Ssimon			*pothertype = rkid->other->keyAttr;
624183234Ssimon		else
625183234Ssimon			*pothertype = NULL;
626183234Ssimon		}
627183234Ssimon	return 1;
628183234Ssimon	}
629183234Ssimon
630183234Ssimonint CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
631183234Ssimon				unsigned char *key, size_t keylen)
632183234Ssimon	{
633183234Ssimon	CMS_KEKRecipientInfo *kekri;
634183234Ssimon	if (ri->type != CMS_RECIPINFO_KEK)
635183234Ssimon		{
636183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK);
637183234Ssimon		return 0;
638183234Ssimon		}
639183234Ssimon
640183234Ssimon	kekri = ri->d.kekri;
641183234Ssimon	kekri->key = key;
642183234Ssimon	kekri->keylen = keylen;
643183234Ssimon	return 1;
644183234Ssimon	}
645183234Ssimon
646183234Ssimon
647183234Ssimon/* Encrypt content key in KEK recipient info */
648183234Ssimon
649183234Ssimonstatic int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms,
650183234Ssimon					CMS_RecipientInfo *ri)
651183234Ssimon	{
652183234Ssimon	CMS_EncryptedContentInfo *ec;
653183234Ssimon	CMS_KEKRecipientInfo *kekri;
654183234Ssimon	AES_KEY actx;
655183234Ssimon	unsigned char *wkey = NULL;
656183234Ssimon	int wkeylen;
657183234Ssimon	int r = 0;
658183234Ssimon
659183234Ssimon	ec = cms->d.envelopedData->encryptedContentInfo;
660183234Ssimon
661183234Ssimon	kekri = ri->d.kekri;
662183234Ssimon
663183234Ssimon	if (!kekri->key)
664183234Ssimon		{
665183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY);
666183234Ssimon		return 0;
667183234Ssimon		}
668183234Ssimon
669183234Ssimon	if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx))
670183234Ssimon		{
671183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,
672183234Ssimon						CMS_R_ERROR_SETTING_KEY);
673183234Ssimon		goto err;
674183234Ssimon		}
675183234Ssimon
676183234Ssimon	wkey = OPENSSL_malloc(ec->keylen + 8);
677183234Ssimon
678183234Ssimon	if (!wkey)
679183234Ssimon		{
680183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,
681183234Ssimon						ERR_R_MALLOC_FAILURE);
682183234Ssimon		goto err;
683183234Ssimon		}
684183234Ssimon
685183234Ssimon	wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen);
686183234Ssimon
687183234Ssimon	if (wkeylen <= 0)
688183234Ssimon		{
689183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR);
690183234Ssimon		goto err;
691183234Ssimon		}
692183234Ssimon
693183234Ssimon	ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen);
694183234Ssimon
695183234Ssimon	r = 1;
696183234Ssimon
697183234Ssimon	err:
698183234Ssimon
699183234Ssimon	if (!r && wkey)
700183234Ssimon		OPENSSL_free(wkey);
701183234Ssimon	OPENSSL_cleanse(&actx, sizeof(actx));
702183234Ssimon
703183234Ssimon	return r;
704183234Ssimon
705183234Ssimon	}
706183234Ssimon
707183234Ssimon/* Decrypt content key in KEK recipient info */
708183234Ssimon
709183234Ssimonstatic int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
710183234Ssimon					CMS_RecipientInfo *ri)
711183234Ssimon	{
712183234Ssimon	CMS_EncryptedContentInfo *ec;
713183234Ssimon	CMS_KEKRecipientInfo *kekri;
714183234Ssimon	AES_KEY actx;
715183234Ssimon	unsigned char *ukey = NULL;
716183234Ssimon	int ukeylen;
717183234Ssimon	int r = 0, wrap_nid;
718183234Ssimon
719183234Ssimon	ec = cms->d.envelopedData->encryptedContentInfo;
720183234Ssimon
721183234Ssimon	kekri = ri->d.kekri;
722183234Ssimon
723183234Ssimon	if (!kekri->key)
724183234Ssimon		{
725183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY);
726183234Ssimon		return 0;
727183234Ssimon		}
728183234Ssimon
729183234Ssimon	wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
730183234Ssimon	if (aes_wrap_keylen(wrap_nid) != kekri->keylen)
731183234Ssimon		{
732183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
733183234Ssimon			CMS_R_INVALID_KEY_LENGTH);
734183234Ssimon		return 0;
735183234Ssimon		}
736183234Ssimon
737183234Ssimon	/* If encrypted key length is invalid don't bother */
738183234Ssimon
739183234Ssimon	if (kekri->encryptedKey->length < 16)
740183234Ssimon		{
741183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
742183234Ssimon					CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);
743183234Ssimon		goto err;
744183234Ssimon		}
745183234Ssimon
746183234Ssimon	if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx))
747183234Ssimon		{
748183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
749183234Ssimon						CMS_R_ERROR_SETTING_KEY);
750183234Ssimon		goto err;
751183234Ssimon		}
752183234Ssimon
753183234Ssimon	ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8);
754183234Ssimon
755183234Ssimon	if (!ukey)
756183234Ssimon		{
757183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
758183234Ssimon						ERR_R_MALLOC_FAILURE);
759183234Ssimon		goto err;
760183234Ssimon		}
761183234Ssimon
762183234Ssimon	ukeylen = AES_unwrap_key(&actx, NULL, ukey,
763183234Ssimon					kekri->encryptedKey->data,
764183234Ssimon					kekri->encryptedKey->length);
765183234Ssimon
766183234Ssimon	if (ukeylen <= 0)
767183234Ssimon		{
768183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
769183234Ssimon							CMS_R_UNWRAP_ERROR);
770183234Ssimon		goto err;
771183234Ssimon		}
772183234Ssimon
773183234Ssimon	ec->key = ukey;
774183234Ssimon	ec->keylen = ukeylen;
775183234Ssimon
776183234Ssimon	r = 1;
777183234Ssimon
778183234Ssimon	err:
779183234Ssimon
780183234Ssimon	if (!r && ukey)
781183234Ssimon		OPENSSL_free(ukey);
782183234Ssimon	OPENSSL_cleanse(&actx, sizeof(actx));
783183234Ssimon
784183234Ssimon	return r;
785183234Ssimon
786183234Ssimon	}
787183234Ssimon
788183234Ssimonint CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
789183234Ssimon	{
790183234Ssimon	switch(ri->type)
791183234Ssimon		{
792183234Ssimon		case CMS_RECIPINFO_TRANS:
793183234Ssimon		return cms_RecipientInfo_ktri_decrypt(cms, ri);
794183234Ssimon
795183234Ssimon		case CMS_RECIPINFO_KEK:
796183234Ssimon		return cms_RecipientInfo_kekri_decrypt(cms, ri);
797183234Ssimon
798238405Sjkim		case CMS_RECIPINFO_PASS:
799238405Sjkim		return cms_RecipientInfo_pwri_crypt(cms, ri, 0);
800238405Sjkim
801183234Ssimon		default:
802183234Ssimon		CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT,
803183234Ssimon			CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE);
804183234Ssimon		return 0;
805183234Ssimon		}
806183234Ssimon	}
807183234Ssimon
808183234SsimonBIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
809183234Ssimon	{
810183234Ssimon	CMS_EncryptedContentInfo *ec;
811183234Ssimon	STACK_OF(CMS_RecipientInfo) *rinfos;
812183234Ssimon	CMS_RecipientInfo *ri;
813183234Ssimon	int i, r, ok = 0;
814183234Ssimon	BIO *ret;
815183234Ssimon
816183234Ssimon	/* Get BIO first to set up key */
817183234Ssimon
818183234Ssimon	ec = cms->d.envelopedData->encryptedContentInfo;
819183234Ssimon	ret = cms_EncryptedContent_init_bio(ec);
820183234Ssimon
821183234Ssimon	/* If error or no cipher end of processing */
822183234Ssimon
823183234Ssimon	if (!ret || !ec->cipher)
824183234Ssimon		return ret;
825183234Ssimon
826183234Ssimon	/* Now encrypt content key according to each RecipientInfo type */
827183234Ssimon
828183234Ssimon	rinfos = cms->d.envelopedData->recipientInfos;
829183234Ssimon
830183234Ssimon	for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++)
831183234Ssimon		{
832183234Ssimon		ri = sk_CMS_RecipientInfo_value(rinfos, i);
833183234Ssimon
834183234Ssimon		switch (ri->type)
835183234Ssimon			{
836183234Ssimon			case CMS_RECIPINFO_TRANS:
837183234Ssimon			r = cms_RecipientInfo_ktri_encrypt(cms, ri);
838183234Ssimon			break;
839183234Ssimon
840183234Ssimon			case CMS_RECIPINFO_KEK:
841183234Ssimon			r = cms_RecipientInfo_kekri_encrypt(cms, ri);
842183234Ssimon			break;
843183234Ssimon
844238405Sjkim			case CMS_RECIPINFO_PASS:
845238405Sjkim			r = cms_RecipientInfo_pwri_crypt(cms, ri, 1);
846238405Sjkim			break;
847238405Sjkim
848183234Ssimon			default:
849183234Ssimon			CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
850183234Ssimon				CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
851183234Ssimon			goto err;
852183234Ssimon			}
853183234Ssimon
854183234Ssimon		if (r <= 0)
855183234Ssimon			{
856183234Ssimon			CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
857183234Ssimon				CMS_R_ERROR_SETTING_RECIPIENTINFO);
858183234Ssimon			goto err;
859183234Ssimon			}
860183234Ssimon		}
861183234Ssimon
862183234Ssimon	ok = 1;
863183234Ssimon
864183234Ssimon	err:
865183234Ssimon	ec->cipher = NULL;
866183234Ssimon	if (ec->key)
867183234Ssimon		{
868183234Ssimon		OPENSSL_cleanse(ec->key, ec->keylen);
869183234Ssimon		OPENSSL_free(ec->key);
870183234Ssimon		ec->key = NULL;
871183234Ssimon		ec->keylen = 0;
872183234Ssimon		}
873183234Ssimon	if (ok)
874183234Ssimon		return ret;
875183234Ssimon	BIO_free(ret);
876183234Ssimon	return NULL;
877183234Ssimon
878183234Ssimon	}
879