~ubuntu-branches/ubuntu/lucid/openssl/lucid-security

« back to all changes in this revision

Viewing changes to crypto/cms/cms_env.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-06-13 18:15:46 UTC
  • mto: (11.1.5 squeeze)
  • mto: This revision was merged to the branch mainline in revision 34.
  • Revision ID: james.westby@ubuntu.com-20090613181546-vbfntai3b009dl1u
Tags: upstream-0.9.8k
ImportĀ upstreamĀ versionĀ 0.9.8k

Show diffs side-by-side

added added

removed removed

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