cef825be2b12483b9b582fde0a908be5cf25bf53
[openssl.git] / 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 #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 *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 static int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
107         {
108         EVP_PKEY *pkey = ri->d.ktri->pkey;
109         int i;
110         if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
111                 return 1;
112         i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri);
113         if (i == -2)
114                 {
115                 CMSerr(CMS_F_CMS_ENV_ASN1_CTRL,
116                                 CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
117                 return 0;
118                 }
119         if (i <= 0)
120                 {
121                 CMSerr(CMS_F_CMS_ENV_ASN1_CTRL, CMS_R_CTRL_FAILURE);
122                 return 0;
123                 }
124         return 1;
125         }
126
127 STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
128         {
129         CMS_EnvelopedData *env;
130         env = cms_get0_enveloped(cms);
131         if (!env)
132                 return NULL;
133         return env->recipientInfos;
134         }
135
136 int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
137         {
138         return ri->type;
139         }
140
141 EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri)
142         {
143         if (ri->type == CMS_RECIPINFO_TRANS)
144                 return ri->d.ktri->pctx;
145         return NULL;
146         }
147
148 CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
149         {
150         CMS_ContentInfo *cms;
151         CMS_EnvelopedData *env;
152         cms = CMS_ContentInfo_new();
153         if (!cms)
154                 goto merr;
155         env = cms_enveloped_data_init(cms);
156         if (!env)
157                 goto merr;
158         if (!cms_EncryptedContent_init(env->encryptedContentInfo,
159                                         cipher, NULL, 0))
160                 goto merr;
161         return cms;
162         merr:
163         if (cms)
164                 CMS_ContentInfo_free(cms);
165         CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);
166         return NULL;
167         }
168
169 /* Key Transport Recipient Info (KTRI) routines */
170
171 /* Add a recipient certificate. For now only handle key transport.
172  * If we ever handle key agreement will need updating.
173  */
174
175 CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
176                                         X509 *recip, unsigned int flags)
177         {
178         CMS_RecipientInfo *ri = NULL;
179         CMS_KeyTransRecipientInfo *ktri;
180         CMS_EnvelopedData *env;
181         EVP_PKEY *pk = NULL;
182         int type;
183         env = cms_get0_enveloped(cms);
184         if (!env)
185                 goto err;
186
187         /* Initialize recipient info */
188         ri = M_ASN1_new_of(CMS_RecipientInfo);
189         if (!ri)
190                 goto merr;
191
192         /* Initialize and add key transport recipient info */
193
194         ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
195         if (!ri->d.ktri)
196                 goto merr;
197         ri->type = CMS_RECIPINFO_TRANS;
198
199         ktri = ri->d.ktri;
200
201         X509_check_purpose(recip, -1, -1);
202         pk = X509_get_pubkey(recip);
203         if (!pk)
204                 {
205                 CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
206                                 CMS_R_ERROR_GETTING_PUBLIC_KEY);
207                 goto err;
208                 }
209         CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509);
210         ktri->pkey = pk;
211         ktri->recip = recip;
212
213         if (flags & CMS_USE_KEYID)
214                 {
215                 ktri->version = 2;
216                 type = CMS_RECIPINFO_KEYIDENTIFIER;
217                 }
218         else
219                 {
220                 ktri->version = 0;
221                 type = CMS_RECIPINFO_ISSUER_SERIAL;
222                 }
223
224         /* Not a typo: RecipientIdentifier and SignerIdentifier are the
225          * same structure.
226          */
227
228         if (!cms_set1_SignerIdentifier(ktri->rid, recip, type))
229                 goto err;
230
231         if (flags & CMS_KEY_PARAM)
232                 {
233                 ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
234                 if (!ktri->pctx)
235                         return 0;
236                 if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0)
237                         goto err;
238                 }
239         else if (!cms_env_asn1_ctrl(ri, 0))
240                 goto err;
241
242         if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
243                 goto merr;
244
245         return ri;
246
247         merr:
248         CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE);
249         err:
250         if (ri)
251                 M_ASN1_free_of(ri, CMS_RecipientInfo);
252         return NULL;
253
254         }
255
256 int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
257                                         EVP_PKEY **pk, X509 **recip,
258                                         X509_ALGOR **palg)
259         {
260         CMS_KeyTransRecipientInfo *ktri;
261         if (ri->type != CMS_RECIPINFO_TRANS)
262                 {
263                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS,
264                         CMS_R_NOT_KEY_TRANSPORT);
265                 return 0;
266                 }
267
268         ktri = ri->d.ktri;
269
270         if (pk)
271                 *pk = ktri->pkey;
272         if (recip)
273                 *recip = ktri->recip;
274         if (palg)
275                 *palg = ktri->keyEncryptionAlgorithm;
276         return 1;
277         }
278
279 int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
280                                         ASN1_OCTET_STRING **keyid,
281                                         X509_NAME **issuer, ASN1_INTEGER **sno)
282         {
283         CMS_KeyTransRecipientInfo *ktri;
284         if (ri->type != CMS_RECIPINFO_TRANS)
285                 {
286                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID,
287                         CMS_R_NOT_KEY_TRANSPORT);
288                 return 0;
289                 }
290         ktri = ri->d.ktri;
291
292         return cms_SignerIdentifier_get0_signer_id(ktri->rid,
293                                                         keyid, issuer, sno);
294         }
295
296 int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
297         {
298         if (ri->type != CMS_RECIPINFO_TRANS)
299                 {
300                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP,
301                         CMS_R_NOT_KEY_TRANSPORT);
302                 return -2;
303                 }
304         return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
305         }
306
307 int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)
308         {
309         if (ri->type != CMS_RECIPINFO_TRANS)
310                 {
311                 CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY,
312                         CMS_R_NOT_KEY_TRANSPORT);
313                 return 0;
314                 }
315         ri->d.ktri->pkey = pkey;
316         return 1;
317         }
318
319 /* Encrypt content key in key transport recipient info */
320
321 static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
322                                         CMS_RecipientInfo *ri)
323         {
324         CMS_KeyTransRecipientInfo *ktri;
325         CMS_EncryptedContentInfo *ec;
326         EVP_PKEY_CTX *pctx;
327         unsigned char *ek = NULL;
328         size_t eklen;
329
330         int ret = 0;
331
332         if (ri->type != CMS_RECIPINFO_TRANS)
333                 {
334                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
335                         CMS_R_NOT_KEY_TRANSPORT);
336                 return 0;
337                 }
338         ktri = ri->d.ktri;
339         ec = cms->d.envelopedData->encryptedContentInfo;
340
341         pctx = ktri->pctx;
342
343         if (pctx)
344                 {
345                 if (!cms_env_asn1_ctrl(ri, 0))
346                         goto err;
347                 }
348         else
349                 {
350                 pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
351                 if (!pctx)
352                         return 0;
353
354                 if (EVP_PKEY_encrypt_init(pctx) <= 0)
355                         goto err;
356                 }
357
358         if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
359                                 EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0)
360                 {
361                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR);
362                 goto err;
363                 }
364
365         if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
366                 goto err;
367
368         ek = OPENSSL_malloc(eklen);
369
370         if (ek == NULL)
371                 {
372                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
373                                                         ERR_R_MALLOC_FAILURE);
374                 goto err;
375                 }
376
377         if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0)
378                 goto err;
379
380         ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
381         ek = NULL;
382
383         ret = 1;
384
385         err:
386         if (pctx)
387                 {
388                 EVP_PKEY_CTX_free(pctx);
389                 ktri->pctx = NULL;
390                 }
391         if (ek)
392                 OPENSSL_free(ek);
393         return ret;
394
395         }
396
397 /* Decrypt content key from KTRI */
398
399 static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
400                                                         CMS_RecipientInfo *ri)
401         {
402         CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
403         EVP_PKEY *pkey = ktri->pkey;
404         unsigned char *ek = NULL;
405         size_t eklen;
406         int ret = 0;
407         CMS_EncryptedContentInfo *ec;
408         ec = cms->d.envelopedData->encryptedContentInfo;
409
410         if (ktri->pkey == NULL)
411                 {
412                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT,
413                         CMS_R_NO_PRIVATE_KEY);
414                 return 0;
415                 }
416
417         ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL);
418         if (!ktri->pctx)
419                 return 0;
420
421         if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0)
422                 goto err;
423
424         if (!cms_env_asn1_ctrl(ri, 1))
425                 goto err;
426
427         if (EVP_PKEY_CTX_ctrl(ktri->pctx, -1, EVP_PKEY_OP_DECRYPT,
428                                 EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0)
429                 {
430                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR);
431                 goto err;
432                 }
433
434         if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen,
435                                 ktri->encryptedKey->data,
436                                 ktri->encryptedKey->length) <= 0)
437                 goto err;
438
439         ek = OPENSSL_malloc(eklen);
440
441         if (ek == NULL)
442                 {
443                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT,
444                                                         ERR_R_MALLOC_FAILURE);
445                 goto err;
446                 }
447
448         if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen,
449                                 ktri->encryptedKey->data,
450                                 ktri->encryptedKey->length) <= 0)
451                 {
452                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB);
453                 goto err;
454                 }
455
456         ret = 1;
457
458         if (ec->key)
459                 {
460                 OPENSSL_cleanse(ec->key, ec->keylen);
461                 OPENSSL_free(ec->key);
462                 }
463
464         ec->key = ek;
465         ec->keylen = eklen;
466
467         err:
468         if (ktri->pctx)
469                 {
470                 EVP_PKEY_CTX_free(ktri->pctx);
471                 ktri->pctx = NULL;
472                 }
473         if (!ret && ek)
474                 OPENSSL_free(ek);
475
476         return ret;
477         }
478
479 /* Key Encrypted Key (KEK) RecipientInfo routines */
480
481 int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, 
482                                         const unsigned char *id, size_t idlen)
483         {
484         ASN1_OCTET_STRING tmp_os;
485         CMS_KEKRecipientInfo *kekri;
486         if (ri->type != CMS_RECIPINFO_KEK)
487                 {
488                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK);
489                 return -2;
490                 }
491         kekri = ri->d.kekri;
492         tmp_os.type = V_ASN1_OCTET_STRING;
493         tmp_os.flags = 0;
494         tmp_os.data = (unsigned char *)id;
495         tmp_os.length = (int)idlen;
496         return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);
497         }
498
499 /* For now hard code AES key wrap info */
500
501 static size_t aes_wrap_keylen(int nid)
502         {
503         switch (nid)
504                 {
505                 case NID_id_aes128_wrap:
506                 return 16;
507
508                 case NID_id_aes192_wrap:
509                 return  24;
510
511                 case NID_id_aes256_wrap:
512                 return  32;
513
514                 default:
515                 return 0;
516                 }
517         }
518
519 CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
520                                         unsigned char *key, size_t keylen,
521                                         unsigned char *id, size_t idlen,
522                                         ASN1_GENERALIZEDTIME *date,
523                                         ASN1_OBJECT *otherTypeId,
524                                         ASN1_TYPE *otherType)
525         {
526         CMS_RecipientInfo *ri = NULL;
527         CMS_EnvelopedData *env;
528         CMS_KEKRecipientInfo *kekri;
529         env = cms_get0_enveloped(cms);
530         if (!env)
531                 goto err;
532
533         if (nid == NID_undef)
534                 {
535                 switch (keylen)
536                         {
537                         case 16:
538                         nid = NID_id_aes128_wrap;
539                         break;
540
541                         case  24:
542                         nid = NID_id_aes192_wrap;
543                         break;
544
545                         case  32:
546                         nid = NID_id_aes256_wrap;
547                         break;
548
549                         default:
550                         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
551                                                 CMS_R_INVALID_KEY_LENGTH);
552                         goto err;
553                         }
554
555                 }
556         else
557                 {
558
559                 size_t exp_keylen = aes_wrap_keylen(nid);
560
561                 if (!exp_keylen)
562                         {
563                         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
564                                         CMS_R_UNSUPPORTED_KEK_ALGORITHM);
565                         goto err;
566                         }
567
568                 if (keylen != exp_keylen)
569                         {
570                         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
571                                         CMS_R_INVALID_KEY_LENGTH);
572                         goto err;
573                         }
574
575                 }
576
577         /* Initialize recipient info */
578         ri = M_ASN1_new_of(CMS_RecipientInfo);
579         if (!ri)
580                 goto merr;
581
582         ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo);
583         if (!ri->d.kekri)
584                 goto merr;
585         ri->type = CMS_RECIPINFO_KEK;
586
587         kekri = ri->d.kekri;
588
589         if (otherTypeId)
590                 {
591                 kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute);
592                 if (kekri->kekid->other == NULL)
593                         goto merr;
594                 }
595
596         if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
597                 goto merr;
598
599
600         /* After this point no calls can fail */
601
602         kekri->version = 4;
603
604         kekri->key = key;
605         kekri->keylen = keylen;
606
607         ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen);
608
609         kekri->kekid->date = date;
610
611         if (kekri->kekid->other)
612                 {
613                 kekri->kekid->other->keyAttrId = otherTypeId;
614                 kekri->kekid->other->keyAttr = otherType;
615                 }
616
617         X509_ALGOR_set0(kekri->keyEncryptionAlgorithm,
618                                 OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
619
620         return ri;
621
622         merr:
623         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE);
624         err:
625         if (ri)
626                 M_ASN1_free_of(ri, CMS_RecipientInfo);
627         return NULL;
628
629         }
630
631 int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
632                                         X509_ALGOR **palg,
633                                         ASN1_OCTET_STRING **pid,
634                                         ASN1_GENERALIZEDTIME **pdate,
635                                         ASN1_OBJECT **potherid,
636                                         ASN1_TYPE **pothertype)
637         {
638         CMS_KEKIdentifier *rkid;
639         if (ri->type != CMS_RECIPINFO_KEK)
640                 {
641                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK);
642                 return 0;
643                 }
644         rkid =  ri->d.kekri->kekid;
645         if (palg)
646                 *palg = ri->d.kekri->keyEncryptionAlgorithm;
647         if (pid)
648                 *pid = rkid->keyIdentifier;
649         if (pdate)
650                 *pdate = rkid->date;
651         if (potherid)
652                 {
653                 if (rkid->other)
654                         *potherid = rkid->other->keyAttrId;
655                 else
656                         *potherid = NULL;
657                 }
658         if (pothertype)
659                 {
660                 if (rkid->other)
661                         *pothertype = rkid->other->keyAttr;
662                 else
663                         *pothertype = NULL;
664                 }
665         return 1;
666         }
667
668 int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, 
669                                 unsigned char *key, size_t keylen)
670         {
671         CMS_KEKRecipientInfo *kekri;
672         if (ri->type != CMS_RECIPINFO_KEK)
673                 {
674                 CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK);
675                 return 0;
676                 }
677
678         kekri = ri->d.kekri;
679         kekri->key = key;
680         kekri->keylen = keylen;
681         return 1;
682         }
683
684
685 /* Encrypt content key in KEK recipient info */
686
687 static int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms,
688                                         CMS_RecipientInfo *ri)
689         {
690         CMS_EncryptedContentInfo *ec;
691         CMS_KEKRecipientInfo *kekri;
692         AES_KEY actx;
693         unsigned char *wkey = NULL;
694         int wkeylen;
695         int r = 0;
696
697         ec = cms->d.envelopedData->encryptedContentInfo;
698
699         kekri = ri->d.kekri;
700
701         if (!kekri->key)
702                 {
703                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY);
704                 return 0;
705                 }
706
707         if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx))
708                 { 
709                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,
710                                                 CMS_R_ERROR_SETTING_KEY);
711                 goto err;
712                 }
713
714         wkey = OPENSSL_malloc(ec->keylen + 8);
715
716         if (!wkey)
717                 { 
718                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,
719                                                 ERR_R_MALLOC_FAILURE);
720                 goto err;
721                 }
722
723         wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen);
724
725         if (wkeylen <= 0)
726                 {
727                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR);
728                 goto err;
729                 }
730
731         ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen);
732
733         r = 1;
734
735         err:
736
737         if (!r && wkey)
738                 OPENSSL_free(wkey);
739         OPENSSL_cleanse(&actx, sizeof(actx));
740
741         return r;
742
743         }
744
745 /* Decrypt content key in KEK recipient info */
746
747 static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
748                                         CMS_RecipientInfo *ri)
749         {
750         CMS_EncryptedContentInfo *ec;
751         CMS_KEKRecipientInfo *kekri;
752         AES_KEY actx;
753         unsigned char *ukey = NULL;
754         int ukeylen;
755         int r = 0, wrap_nid;
756
757         ec = cms->d.envelopedData->encryptedContentInfo;
758
759         kekri = ri->d.kekri;
760
761         if (!kekri->key)
762                 {
763                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY);
764                 return 0;
765                 }
766
767         wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
768         if (aes_wrap_keylen(wrap_nid) != kekri->keylen)
769                 {
770                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
771                         CMS_R_INVALID_KEY_LENGTH);
772                 return 0;
773                 }
774
775         /* If encrypted key length is invalid don't bother */
776
777         if (kekri->encryptedKey->length < 16)
778                 { 
779                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
780                                         CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);
781                 goto err;
782                 }
783
784         if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx))
785                 { 
786                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
787                                                 CMS_R_ERROR_SETTING_KEY);
788                 goto err;
789                 }
790
791         ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8);
792
793         if (!ukey)
794                 { 
795                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
796                                                 ERR_R_MALLOC_FAILURE);
797                 goto err;
798                 }
799
800         ukeylen = AES_unwrap_key(&actx, NULL, ukey,
801                                         kekri->encryptedKey->data,
802                                         kekri->encryptedKey->length);
803
804         if (ukeylen <= 0)
805                 {
806                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
807                                                         CMS_R_UNWRAP_ERROR);
808                 goto err;
809                 }
810
811         ec->key = ukey;
812         ec->keylen = ukeylen;
813
814         r = 1;
815
816         err:
817
818         if (!r && ukey)
819                 OPENSSL_free(ukey);
820         OPENSSL_cleanse(&actx, sizeof(actx));
821
822         return r;
823
824         }
825
826 int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
827         {
828         switch(ri->type)
829                 {
830                 case CMS_RECIPINFO_TRANS:
831                 return cms_RecipientInfo_ktri_decrypt(cms, ri);
832
833                 case CMS_RECIPINFO_KEK:
834                 return cms_RecipientInfo_kekri_decrypt(cms, ri);
835
836                 case CMS_RECIPINFO_PASS:
837                 return cms_RecipientInfo_pwri_crypt(cms, ri, 0);
838
839                 default:
840                 CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT,
841                         CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE);
842                 return 0;
843                 }
844         }
845
846 int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
847         {
848         switch (ri->type)
849                 {
850                 case CMS_RECIPINFO_TRANS:
851                 return cms_RecipientInfo_ktri_encrypt(cms, ri);
852
853                 case CMS_RECIPINFO_KEK:
854                 return cms_RecipientInfo_kekri_encrypt(cms, ri);
855                 break;
856
857                 case CMS_RECIPINFO_PASS:
858                 return cms_RecipientInfo_pwri_crypt(cms, ri, 1);
859                 break;
860
861                 default:
862                 CMSerr(CMS_F_CMS_RECIPIENTINFO_ENCRYPT,
863                                 CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
864                 return 0;
865                 }
866         }
867
868 /* Check structures and fixup version numbers (if necessary) */
869
870 static void cms_env_set_originfo_version(CMS_EnvelopedData *env)
871         {
872         CMS_OriginatorInfo *org = env->originatorInfo;
873         int i;
874         if (org == NULL)
875                 return;
876         for (i = 0; i < sk_CMS_CertificateChoices_num(org->certificates); i++)
877                 {
878                 CMS_CertificateChoices *cch;
879                 cch = sk_CMS_CertificateChoices_value(org->certificates, i);
880                 if (cch->type == CMS_CERTCHOICE_OTHER)
881                         {
882                         env->version = 4;
883                         return;
884                         }
885                 else if (cch->type == CMS_CERTCHOICE_V2ACERT)
886                         {
887                         if (env->version < 3)
888                                 env->version = 3;
889                         }
890                 }
891
892         for (i = 0; i < sk_CMS_RevocationInfoChoice_num(org->crls); i++)
893                 {
894                 CMS_RevocationInfoChoice *rch;
895                 rch = sk_CMS_RevocationInfoChoice_value(org->crls, i);
896                 if (rch->type == CMS_REVCHOICE_OTHER)
897                         {
898                         env->version = 4;
899                         return;
900                         }
901                 }
902         }
903
904 static void cms_env_set_version(CMS_EnvelopedData *env)
905         {
906         int i;
907         CMS_RecipientInfo *ri;
908
909         /* Can't set version higher than 4 so if 4 or more already nothing
910          * to do.
911          */
912         if (env->version >= 4)
913                 return;
914
915         cms_env_set_originfo_version(env);
916
917         if (env->version >= 3)
918                 return;
919
920         for (i = 0; i < sk_CMS_RecipientInfo_num(env->recipientInfos); i++)
921                 {
922                 ri = sk_CMS_RecipientInfo_value(env->recipientInfos, i);
923                 if (ri->type == CMS_RECIPINFO_PASS || ri->type == CMS_RECIPINFO_OTHER)
924                         {
925                         env->version = 3;
926                         return;
927                         }
928                 else if (ri->type != CMS_RECIPINFO_TRANS)
929                         {
930                         env->version = 2;
931                         }
932                 }
933         if (env->version == 2)
934                 return;
935         if (env->originatorInfo || env->unprotectedAttrs)
936                 env->version = 2;
937         env->version = 0;
938         }
939
940 BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
941         {
942         CMS_EncryptedContentInfo *ec;
943         STACK_OF(CMS_RecipientInfo) *rinfos;
944         CMS_RecipientInfo *ri;
945         int i, ok = 0;
946         BIO *ret;
947
948         /* Get BIO first to set up key */
949
950         ec = cms->d.envelopedData->encryptedContentInfo;
951         ret = cms_EncryptedContent_init_bio(ec);
952
953         /* If error or no cipher end of processing */
954
955         if (!ret || !ec->cipher)
956                 return ret;
957
958         /* Now encrypt content key according to each RecipientInfo type */
959
960         rinfos = cms->d.envelopedData->recipientInfos;
961
962         for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++)
963                 {
964                 ri = sk_CMS_RecipientInfo_value(rinfos, i);
965                 if (CMS_RecipientInfo_encrypt(cms, ri) <= 0)
966                         {
967                         CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
968                                 CMS_R_ERROR_SETTING_RECIPIENTINFO);
969                         goto err;
970                         }
971                 }
972         cms_env_set_version(cms->d.envelopedData);
973
974         ok = 1;
975
976         err:
977         ec->cipher = NULL;
978         if (ec->key)
979                 {
980                 OPENSSL_cleanse(ec->key, ec->keylen);
981                 OPENSSL_free(ec->key);
982                 ec->key = NULL;
983                 ec->keylen = 0;
984                 }
985         if (ok)
986                 return ret;
987         BIO_free(ret);
988         return NULL;
989
990         }