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