cms_env.c revision 296465
1/* crypto/cms/cms_env.c */
2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4 * project.
5 */
6/* ====================================================================
7 * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 *    software must display the following acknowledgment:
23 *    "This product includes software developed by the OpenSSL Project
24 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 *    endorse or promote products derived from this software without
28 *    prior written permission. For written permission, please contact
29 *    licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 *    nor may "OpenSSL" appear in their names without prior written
33 *    permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 *    acknowledgment:
37 *    "This product includes software developed by the OpenSSL Project
38 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 */
54
55#include "cryptlib.h"
56#include <openssl/asn1t.h>
57#include <openssl/pem.h>
58#include <openssl/x509v3.h>
59#include <openssl/err.h>
60#include <openssl/cms.h>
61#include <openssl/rand.h>
62#include <openssl/aes.h>
63#include "cms_lcl.h"
64
65/* CMS EnvelopedData Utilities */
66
67DECLARE_ASN1_ITEM(CMS_EnvelopedData)
68DECLARE_ASN1_ITEM(CMS_RecipientInfo)
69DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
70DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo)
71DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute)
72
73DECLARE_STACK_OF(CMS_RecipientInfo)
74
75static CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
76{
77    if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) {
78        CMSerr(CMS_F_CMS_GET0_ENVELOPED,
79               CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
80        return NULL;
81    }
82    return cms->d.envelopedData;
83}
84
85static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)
86{
87    if (cms->d.other == NULL) {
88        cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData);
89        if (!cms->d.envelopedData) {
90            CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT, ERR_R_MALLOC_FAILURE);
91            return NULL;
92        }
93        cms->d.envelopedData->version = 0;
94        cms->d.envelopedData->encryptedContentInfo->contentType =
95            OBJ_nid2obj(NID_pkcs7_data);
96        ASN1_OBJECT_free(cms->contentType);
97        cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped);
98        return cms->d.envelopedData;
99    }
100    return cms_get0_enveloped(cms);
101}
102
103STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
104{
105    CMS_EnvelopedData *env;
106    env = cms_get0_enveloped(cms);
107    if (!env)
108        return NULL;
109    return env->recipientInfos;
110}
111
112int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
113{
114    return ri->type;
115}
116
117CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
118{
119    CMS_ContentInfo *cms;
120    CMS_EnvelopedData *env;
121    cms = CMS_ContentInfo_new();
122    if (!cms)
123        goto merr;
124    env = cms_enveloped_data_init(cms);
125    if (!env)
126        goto merr;
127    if (!cms_EncryptedContent_init(env->encryptedContentInfo,
128                                   cipher, NULL, 0))
129        goto merr;
130    return cms;
131 merr:
132    if (cms)
133        CMS_ContentInfo_free(cms);
134    CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);
135    return NULL;
136}
137
138/* Key Transport Recipient Info (KTRI) routines */
139
140/*
141 * Add a recipient certificate. For now only handle key transport. If we ever
142 * handle key agreement will need updating.
143 */
144
145CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
146                                           X509 *recip, unsigned int flags)
147{
148    CMS_RecipientInfo *ri = NULL;
149    CMS_KeyTransRecipientInfo *ktri;
150    CMS_EnvelopedData *env;
151    EVP_PKEY *pk = NULL;
152    int type;
153    env = cms_get0_enveloped(cms);
154    if (!env)
155        goto err;
156
157    /* Initialize recipient info */
158    ri = M_ASN1_new_of(CMS_RecipientInfo);
159    if (!ri)
160        goto merr;
161
162    /* Initialize and add key transport recipient info */
163
164    ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
165    if (!ri->d.ktri)
166        goto merr;
167    ri->type = CMS_RECIPINFO_TRANS;
168
169    ktri = ri->d.ktri;
170
171    X509_check_purpose(recip, -1, -1);
172    pk = X509_get_pubkey(recip);
173    if (!pk) {
174        CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY);
175        goto err;
176    }
177    CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509);
178    ktri->pkey = pk;
179    ktri->recip = recip;
180
181    if (flags & CMS_USE_KEYID) {
182        ktri->version = 2;
183        if (env->version < 2)
184            env->version = 2;
185        type = CMS_RECIPINFO_KEYIDENTIFIER;
186    } else {
187        ktri->version = 0;
188        type = CMS_RECIPINFO_ISSUER_SERIAL;
189    }
190
191    /*
192     * Not a typo: RecipientIdentifier and SignerIdentifier are the same
193     * structure.
194     */
195
196    if (!cms_set1_SignerIdentifier(ktri->rid, recip, type))
197        goto err;
198
199    /*
200     * Since we have no EVP_PKEY_ASN1_METHOD in OpenSSL 0.9.8, hard code
201     * algorithm parameters.
202     */
203
204    if (pk->type == EVP_PKEY_RSA) {
205        X509_ALGOR_set0(ktri->keyEncryptionAlgorithm,
206                        OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
207    } else {
208        CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
209               CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
210        goto err;
211    }
212
213    if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
214        goto merr;
215
216    return ri;
217
218 merr:
219    CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE);
220 err:
221    if (ri)
222        M_ASN1_free_of(ri, CMS_RecipientInfo);
223    return NULL;
224
225}
226
227int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
228                                     EVP_PKEY **pk, X509 **recip,
229                                     X509_ALGOR **palg)
230{
231    CMS_KeyTransRecipientInfo *ktri;
232    if (ri->type != CMS_RECIPINFO_TRANS) {
233        CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS,
234               CMS_R_NOT_KEY_TRANSPORT);
235        return 0;
236    }
237
238    ktri = ri->d.ktri;
239
240    if (pk)
241        *pk = ktri->pkey;
242    if (recip)
243        *recip = ktri->recip;
244    if (palg)
245        *palg = ktri->keyEncryptionAlgorithm;
246    return 1;
247}
248
249int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
250                                          ASN1_OCTET_STRING **keyid,
251                                          X509_NAME **issuer,
252                                          ASN1_INTEGER **sno)
253{
254    CMS_KeyTransRecipientInfo *ktri;
255    if (ri->type != CMS_RECIPINFO_TRANS) {
256        CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID,
257               CMS_R_NOT_KEY_TRANSPORT);
258        return 0;
259    }
260    ktri = ri->d.ktri;
261
262    return cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer, sno);
263}
264
265int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
266{
267    if (ri->type != CMS_RECIPINFO_TRANS) {
268        CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP,
269               CMS_R_NOT_KEY_TRANSPORT);
270        return -2;
271    }
272    return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
273}
274
275int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)
276{
277    if (ri->type != CMS_RECIPINFO_TRANS) {
278        CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY, CMS_R_NOT_KEY_TRANSPORT);
279        return 0;
280    }
281    ri->d.ktri->pkey = pkey;
282    return 1;
283}
284
285/* Encrypt content key in key transport recipient info */
286
287static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
288                                          CMS_RecipientInfo *ri)
289{
290    CMS_KeyTransRecipientInfo *ktri;
291    CMS_EncryptedContentInfo *ec;
292    unsigned char *ek = NULL;
293    int eklen;
294
295    int ret = 0;
296
297    if (ri->type != CMS_RECIPINFO_TRANS) {
298        CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_NOT_KEY_TRANSPORT);
299        return 0;
300    }
301    ktri = ri->d.ktri;
302    ec = cms->d.envelopedData->encryptedContentInfo;
303
304    eklen = EVP_PKEY_size(ktri->pkey);
305
306    ek = OPENSSL_malloc(eklen);
307
308    if (ek == NULL) {
309        CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, ERR_R_MALLOC_FAILURE);
310        goto err;
311    }
312
313    eklen = EVP_PKEY_encrypt(ek, ec->key, ec->keylen, ktri->pkey);
314
315    if (eklen <= 0)
316        goto err;
317
318    ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
319    ek = NULL;
320
321    ret = 1;
322
323 err:
324    if (ek)
325        OPENSSL_free(ek);
326    return ret;
327
328}
329
330/* Decrypt content key from KTRI */
331
332static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
333                                          CMS_RecipientInfo *ri)
334{
335    CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
336    unsigned char *ek = NULL;
337    int eklen;
338    int ret = 0;
339    CMS_EncryptedContentInfo *ec;
340    ec = cms->d.envelopedData->encryptedContentInfo;
341
342    if (ktri->pkey == NULL) {
343        CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_NO_PRIVATE_KEY);
344        return 0;
345    }
346
347    eklen = EVP_PKEY_size(ktri->pkey);
348
349    ek = OPENSSL_malloc(eklen);
350
351    if (ek == NULL) {
352        CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, ERR_R_MALLOC_FAILURE);
353        goto err;
354    }
355
356    eklen = EVP_PKEY_decrypt(ek,
357                             ktri->encryptedKey->data,
358                             ktri->encryptedKey->length, ktri->pkey);
359    if (eklen <= 0) {
360        CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB);
361        goto err;
362    }
363
364    ret = 1;
365
366    if (ec->key) {
367        OPENSSL_cleanse(ec->key, ec->keylen);
368        OPENSSL_free(ec->key);
369    }
370
371    ec->key = ek;
372    ec->keylen = eklen;
373
374 err:
375    if (!ret && ek)
376        OPENSSL_free(ek);
377
378    return ret;
379}
380
381/* Key Encrypted Key (KEK) RecipientInfo routines */
382
383int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
384                                   const unsigned char *id, size_t idlen)
385{
386    ASN1_OCTET_STRING tmp_os;
387    CMS_KEKRecipientInfo *kekri;
388    if (ri->type != CMS_RECIPINFO_KEK) {
389        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK);
390        return -2;
391    }
392    kekri = ri->d.kekri;
393    tmp_os.type = V_ASN1_OCTET_STRING;
394    tmp_os.flags = 0;
395    tmp_os.data = (unsigned char *)id;
396    tmp_os.length = (int)idlen;
397    return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);
398}
399
400/* For now hard code AES key wrap info */
401
402static size_t aes_wrap_keylen(int nid)
403{
404    switch (nid) {
405    case NID_id_aes128_wrap:
406        return 16;
407
408    case NID_id_aes192_wrap:
409        return 24;
410
411    case NID_id_aes256_wrap:
412        return 32;
413
414    default:
415        return 0;
416    }
417}
418
419CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
420                                          unsigned char *key, size_t keylen,
421                                          unsigned char *id, size_t idlen,
422                                          ASN1_GENERALIZEDTIME *date,
423                                          ASN1_OBJECT *otherTypeId,
424                                          ASN1_TYPE *otherType)
425{
426    CMS_RecipientInfo *ri = NULL;
427    CMS_EnvelopedData *env;
428    CMS_KEKRecipientInfo *kekri;
429    env = cms_get0_enveloped(cms);
430    if (!env)
431        goto err;
432
433    if (nid == NID_undef) {
434        switch (keylen) {
435        case 16:
436            nid = NID_id_aes128_wrap;
437            break;
438
439        case 24:
440            nid = NID_id_aes192_wrap;
441            break;
442
443        case 32:
444            nid = NID_id_aes256_wrap;
445            break;
446
447        default:
448            CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH);
449            goto err;
450        }
451
452    } else {
453
454        size_t exp_keylen = aes_wrap_keylen(nid);
455
456        if (!exp_keylen) {
457            CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
458                   CMS_R_UNSUPPORTED_KEK_ALGORITHM);
459            goto err;
460        }
461
462        if (keylen != exp_keylen) {
463            CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH);
464            goto err;
465        }
466
467    }
468
469    /* Initialize recipient info */
470    ri = M_ASN1_new_of(CMS_RecipientInfo);
471    if (!ri)
472        goto merr;
473
474    ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo);
475    if (!ri->d.kekri)
476        goto merr;
477    ri->type = CMS_RECIPINFO_KEK;
478
479    kekri = ri->d.kekri;
480
481    if (otherTypeId) {
482        kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute);
483        if (kekri->kekid->other == NULL)
484            goto merr;
485    }
486
487    if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
488        goto merr;
489
490    /* After this point no calls can fail */
491
492    kekri->version = 4;
493
494    kekri->key = key;
495    kekri->keylen = keylen;
496
497    ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen);
498
499    kekri->kekid->date = date;
500
501    if (kekri->kekid->other) {
502        kekri->kekid->other->keyAttrId = otherTypeId;
503        kekri->kekid->other->keyAttr = otherType;
504    }
505
506    X509_ALGOR_set0(kekri->keyEncryptionAlgorithm,
507                    OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
508
509    return ri;
510
511 merr:
512    CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE);
513 err:
514    if (ri)
515        M_ASN1_free_of(ri, CMS_RecipientInfo);
516    return NULL;
517
518}
519
520int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
521                                    X509_ALGOR **palg,
522                                    ASN1_OCTET_STRING **pid,
523                                    ASN1_GENERALIZEDTIME **pdate,
524                                    ASN1_OBJECT **potherid,
525                                    ASN1_TYPE **pothertype)
526{
527    CMS_KEKIdentifier *rkid;
528    if (ri->type != CMS_RECIPINFO_KEK) {
529        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK);
530        return 0;
531    }
532    rkid = ri->d.kekri->kekid;
533    if (palg)
534        *palg = ri->d.kekri->keyEncryptionAlgorithm;
535    if (pid)
536        *pid = rkid->keyIdentifier;
537    if (pdate)
538        *pdate = rkid->date;
539    if (potherid) {
540        if (rkid->other)
541            *potherid = rkid->other->keyAttrId;
542        else
543            *potherid = NULL;
544    }
545    if (pothertype) {
546        if (rkid->other)
547            *pothertype = rkid->other->keyAttr;
548        else
549            *pothertype = NULL;
550    }
551    return 1;
552}
553
554int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
555                               unsigned char *key, size_t keylen)
556{
557    CMS_KEKRecipientInfo *kekri;
558    if (ri->type != CMS_RECIPINFO_KEK) {
559        CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK);
560        return 0;
561    }
562
563    kekri = ri->d.kekri;
564    kekri->key = key;
565    kekri->keylen = keylen;
566    return 1;
567}
568
569/* Encrypt content key in KEK recipient info */
570
571static int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms,
572                                           CMS_RecipientInfo *ri)
573{
574    CMS_EncryptedContentInfo *ec;
575    CMS_KEKRecipientInfo *kekri;
576    AES_KEY actx;
577    unsigned char *wkey = NULL;
578    int wkeylen;
579    int r = 0;
580
581    ec = cms->d.envelopedData->encryptedContentInfo;
582
583    kekri = ri->d.kekri;
584
585    if (!kekri->key) {
586        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY);
587        return 0;
588    }
589
590    if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) {
591        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,
592               CMS_R_ERROR_SETTING_KEY);
593        goto err;
594    }
595
596    wkey = OPENSSL_malloc(ec->keylen + 8);
597
598    if (!wkey) {
599        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, ERR_R_MALLOC_FAILURE);
600        goto err;
601    }
602
603    wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen);
604
605    if (wkeylen <= 0) {
606        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR);
607        goto err;
608    }
609
610    ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen);
611
612    r = 1;
613
614 err:
615
616    if (!r && wkey)
617        OPENSSL_free(wkey);
618    OPENSSL_cleanse(&actx, sizeof(actx));
619
620    return r;
621
622}
623
624/* Decrypt content key in KEK recipient info */
625
626static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
627                                           CMS_RecipientInfo *ri)
628{
629    CMS_EncryptedContentInfo *ec;
630    CMS_KEKRecipientInfo *kekri;
631    AES_KEY actx;
632    unsigned char *ukey = NULL;
633    int ukeylen;
634    int r = 0, wrap_nid;
635
636    ec = cms->d.envelopedData->encryptedContentInfo;
637
638    kekri = ri->d.kekri;
639
640    if (!kekri->key) {
641        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY);
642        return 0;
643    }
644
645    wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
646    if (aes_wrap_keylen(wrap_nid) != kekri->keylen) {
647        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
648               CMS_R_INVALID_KEY_LENGTH);
649        return 0;
650    }
651
652    /* If encrypted key length is invalid don't bother */
653
654    if (kekri->encryptedKey->length < 16) {
655        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
656               CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);
657        goto err;
658    }
659
660    if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) {
661        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
662               CMS_R_ERROR_SETTING_KEY);
663        goto err;
664    }
665
666    ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8);
667
668    if (!ukey) {
669        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, ERR_R_MALLOC_FAILURE);
670        goto err;
671    }
672
673    ukeylen = AES_unwrap_key(&actx, NULL, ukey,
674                             kekri->encryptedKey->data,
675                             kekri->encryptedKey->length);
676
677    if (ukeylen <= 0) {
678        CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_UNWRAP_ERROR);
679        goto err;
680    }
681
682    ec->key = ukey;
683    ec->keylen = ukeylen;
684
685    r = 1;
686
687 err:
688
689    if (!r && ukey)
690        OPENSSL_free(ukey);
691    OPENSSL_cleanse(&actx, sizeof(actx));
692
693    return r;
694
695}
696
697int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
698{
699    switch (ri->type) {
700    case CMS_RECIPINFO_TRANS:
701        return cms_RecipientInfo_ktri_decrypt(cms, ri);
702
703    case CMS_RECIPINFO_KEK:
704        return cms_RecipientInfo_kekri_decrypt(cms, ri);
705
706    default:
707        CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT,
708               CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE);
709        return 0;
710    }
711}
712
713BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
714{
715    CMS_EncryptedContentInfo *ec;
716    STACK_OF(CMS_RecipientInfo) *rinfos;
717    CMS_RecipientInfo *ri;
718    int i, r, ok = 0;
719    BIO *ret;
720
721    /* Get BIO first to set up key */
722
723    ec = cms->d.envelopedData->encryptedContentInfo;
724    ret = cms_EncryptedContent_init_bio(ec);
725
726    /* If error or no cipher end of processing */
727
728    if (!ret || !ec->cipher)
729        return ret;
730
731    /* Now encrypt content key according to each RecipientInfo type */
732
733    rinfos = cms->d.envelopedData->recipientInfos;
734
735    for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
736        ri = sk_CMS_RecipientInfo_value(rinfos, i);
737
738        switch (ri->type) {
739        case CMS_RECIPINFO_TRANS:
740            r = cms_RecipientInfo_ktri_encrypt(cms, ri);
741            break;
742
743        case CMS_RECIPINFO_KEK:
744            r = cms_RecipientInfo_kekri_encrypt(cms, ri);
745            break;
746
747        default:
748            CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
749                   CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
750            goto err;
751        }
752
753        if (r <= 0) {
754            CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
755                   CMS_R_ERROR_SETTING_RECIPIENTINFO);
756            goto err;
757        }
758    }
759
760    ok = 1;
761
762 err:
763    ec->cipher = NULL;
764    if (ec->key) {
765        OPENSSL_cleanse(ec->key, ec->keylen);
766        OPENSSL_free(ec->key);
767        ec->key = NULL;
768        ec->keylen = 0;
769    }
770    if (ok)
771        return ret;
772    BIO_free(ret);
773    return NULL;
774
775}
776