5ac3e125dc4d088dc400263574d2e7d0689c5bc2
[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 "cms_lcl.h"
62 #include "asn1_locl.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 /* Add a recipient certificate. For now only handle key transport.
142  * If we ever handle key agreement will need updating.
143  */
144 CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
145                                         X509 *recip, unsigned int flags)
146         {
147         CMS_RecipientInfo *ri = NULL;
148         CMS_KeyTransRecipientInfo *ktri;
149         CMS_EnvelopedData *env;
150         EVP_PKEY *pk = NULL;
151         int i, type;
152         env = cms_get0_enveloped(cms);
153         if (!env)
154                 goto err;
155
156         /* Initialize recipient info */
157         ri = M_ASN1_new_of(CMS_RecipientInfo);
158         if (!ri)
159                 goto merr;
160
161         /* Initialize and add key transport recipient info */
162
163         ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
164         if (!ri->d.ktri)
165                 goto merr;
166         ri->type = CMS_RECIPINFO_TRANS;
167
168         ktri = ri->d.ktri;
169
170         X509_check_purpose(recip, -1, -1);
171         pk = X509_get_pubkey(recip);
172         if (!pk)
173                 {
174                 CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
175                                 CMS_R_ERROR_GETTING_PUBLIC_KEY);
176                 goto err;
177                 }
178         CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509);
179         ktri->pkey = pk;
180         ktri->recip = recip;
181
182         if (flags & CMS_USE_KEYID)
183                 {
184                 ktri->version = 2;
185                 type = CMS_RECIPINFO_KEYIDENTIFIER;
186                 }
187         else
188                 {
189                 ktri->version = 0;
190                 type = CMS_RECIPINFO_ISSUER_SERIAL;
191                 }
192
193         /* Not a typo: RecipientIdentifier and SignerIdentifier are the
194          * same structure.
195          */
196
197         if (!cms_set1_SignerIdentifier(ktri->rid, recip, type))
198                 goto err;
199
200         if (pk->ameth && pk->ameth->pkey_ctrl)
201                 {
202                 i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_ENVELOPE,
203                                                 0, ri);
204                 if (i == -2)
205                         {
206                         CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
207                                 CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
208                         goto err;
209                         }
210                 if (i <= 0)
211                         {
212                         CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
213                                 CMS_R_CTRL_FAILURE);
214                         goto err;
215                         }
216                 }
217
218         if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
219                 goto merr;
220
221         return ri;
222
223         merr:
224         CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE);
225         err:
226         if (ri)
227                 M_ASN1_free_of(ri, CMS_RecipientInfo);
228         return NULL;
229
230         }
231
232 int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
233                                         X509_ALGOR **palg,
234                                         ASN1_OCTET_STRING **pid,
235                                         ASN1_GENERALIZEDTIME **pdate,
236                                         ASN1_OBJECT **potherid,
237                                         ASN1_TYPE **pothertype)
238         {
239         CMS_KEKIdentifier *rkid;
240         if (ri->type != CMS_RECIPINFO_KEK)
241                 {
242                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK);
243                 return 0;
244                 }
245         rkid =  ri->d.kekri->kekid;
246         if (palg)
247                 *palg = ri->d.kekri->keyEncryptionAlgorithm;
248         if (pid)
249                 *pid = rkid->keyIdentifier;
250         if (pdate)
251                 *pdate = rkid->date;
252         if (potherid)
253                 {
254                 if (rkid->other)
255                         *potherid = rkid->other->keyAttrId;
256                 else
257                         *potherid = NULL;
258                 }
259         if (pothertype)
260                 {
261                 if (rkid->other)
262                         *pothertype = rkid->other->keyAttr;
263                 else
264                         *pothertype = NULL;
265                 }
266         return 1;
267         }
268
269
270 CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
271                                         unsigned char *key, size_t keylen,
272                                         unsigned char *id, size_t idlen,
273                                         ASN1_GENERALIZEDTIME *date,
274                                         ASN1_OBJECT *otherTypeId,
275                                         ASN1_TYPE *otherType)
276         {
277         CMS_RecipientInfo *ri = NULL;
278         CMS_EnvelopedData *env;
279         CMS_KEKRecipientInfo *kekri;
280         size_t exp_keylen = 0;
281         env = cms_get0_enveloped(cms);
282         if (!env)
283                 goto err;
284
285         /* For now hard code checks on nids */
286         switch (nid)
287                 {
288                 case NID_id_aes128_wrap:
289                 exp_keylen = 16;
290                 break;
291
292                 case NID_id_aes192_wrap:
293                 exp_keylen = 24;
294                 break;
295
296                 case NID_id_aes256_wrap:
297                 exp_keylen = 32;
298                 break;
299
300                 default:
301                 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
302                                 CMS_R_UNSUPPORTED_KEK_ALGORITHM);
303                 goto err;
304                 }
305
306         if (exp_keylen && (keylen != exp_keylen))
307                 {
308                 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,
309                                 CMS_R_INVALID_KEY_LENGTH);
310                 goto err;
311                 }
312
313         /* Initialize recipient info */
314         ri = M_ASN1_new_of(CMS_RecipientInfo);
315         if (!ri)
316                 goto merr;
317
318         ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo);
319         if (!ri->d.kekri)
320                 goto merr;
321         ri->type = CMS_RECIPINFO_KEK;
322
323         kekri = ri->d.kekri;
324
325         if (otherTypeId)
326                 {
327                 kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute);
328                 if (kekri->kekid->other == NULL)
329                         goto merr;
330                 }
331
332         if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
333                 goto merr;
334
335         /* After this point no calls can fail */
336
337         kekri->version = 4;
338
339         kekri->key = key;
340         kekri->keylen = keylen;
341
342         ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen);
343
344         kekri->kekid->date = date;
345
346         kekri->kekid->other->keyAttrId = otherTypeId;
347         kekri->kekid->other->keyAttr = otherType;
348
349         X509_ALGOR_set0(kekri->keyEncryptionAlgorithm,
350                                 OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
351
352         return ri;
353
354         merr:
355         CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE);
356         err:
357         if (ri)
358                 M_ASN1_free_of(ri, CMS_RecipientInfo);
359         return NULL;
360
361         }
362
363 int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
364                                         EVP_PKEY **pk, X509 **recip,
365                                         X509_ALGOR **palg)
366         {
367         CMS_KeyTransRecipientInfo *ktri;
368         if (ri->type != CMS_RECIPINFO_TRANS)
369                 {
370                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS,
371                         CMS_R_NOT_KEY_TRANSPORT);
372                 return 0;
373                 }
374
375         ktri = ri->d.ktri;
376
377         if (pk)
378                 *pk = ktri->pkey;
379         if (recip)
380                 *recip = ktri->recip;
381         if (palg)
382                 *palg = ktri->keyEncryptionAlgorithm;
383         return 1;
384         }
385
386 int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
387                                         ASN1_OCTET_STRING **keyid,
388                                         X509_NAME **issuer, ASN1_INTEGER **sno)
389         {
390         CMS_KeyTransRecipientInfo *ktri;
391         if (ri->type != CMS_RECIPINFO_TRANS)
392                 {
393                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID,
394                         CMS_R_NOT_KEY_TRANSPORT);
395                 return 0;
396                 }
397         ktri = ri->d.ktri;
398
399         return cms_SignerIdentifier_get0_signer_id(ktri->rid,
400                                                         keyid, issuer, sno);
401         }
402
403 int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
404         {
405         if (ri->type != CMS_RECIPINFO_TRANS)
406                 {
407                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP,
408                         CMS_R_NOT_KEY_TRANSPORT);
409                 return -2;
410                 }
411
412         return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
413         }
414
415 /* Encrypt content key in key transport recipient info */
416
417 static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
418                                         CMS_RecipientInfo *ri)
419         {
420         CMS_KeyTransRecipientInfo *ktri;
421         CMS_EncryptedContentInfo *ec;
422         EVP_PKEY_CTX *pctx = NULL;
423         unsigned char *ek = NULL;
424         size_t eklen;
425
426         int ret = 0;
427
428         if (ri->type != CMS_RECIPINFO_TRANS)
429                 {
430                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
431                         CMS_R_NOT_KEY_TRANSPORT);
432                 return 0;
433                 }
434         ktri = ri->d.ktri;
435         ec = cms->d.envelopedData->encryptedContentInfo;
436
437         pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
438         if (!pctx)
439                 return 0;
440
441         if (EVP_PKEY_encrypt_init(pctx) <= 0)
442                 goto err;
443
444         if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
445                                 EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0)
446                 {
447                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR);
448                 goto err;
449                 }
450
451         if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
452                 goto err;
453
454         ek = OPENSSL_malloc(eklen);
455
456         if (ek == NULL)
457                 {
458                 CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
459                                                         ERR_R_MALLOC_FAILURE);
460                 goto err;
461                 }
462
463         if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0)
464                 goto err;
465
466         ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
467         ek = NULL;
468
469         ret = 1;
470
471         err:
472         if (pctx)
473                 EVP_PKEY_CTX_free(pctx);
474         if (ek)
475                 OPENSSL_free(ek);
476         return ret;
477
478         }
479
480 int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
481                                EVP_PKEY *pkey)
482         {
483         CMS_KeyTransRecipientInfo *ktri;
484         EVP_PKEY_CTX *pctx = NULL;
485         unsigned char *ek = NULL;
486         size_t eklen;
487
488         int ret = 0;
489
490         if (ri->type != CMS_RECIPINFO_TRANS)
491                 {
492                 CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT,
493                         CMS_R_NOT_KEY_TRANSPORT);
494                 return 0;
495                 }
496         ktri = ri->d.ktri;
497
498         pctx = EVP_PKEY_CTX_new(pkey, NULL);
499         if (!pctx)
500                 return 0;
501
502         if (EVP_PKEY_decrypt_init(pctx) <= 0)
503                 goto err;
504
505         if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
506                                 EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0)
507                 {
508                 CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, CMS_R_CTRL_ERROR);
509                 goto err;
510                 }
511
512         if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
513                                 ktri->encryptedKey->data,
514                                 ktri->encryptedKey->length) <= 0)
515                 goto err;
516
517         ek = OPENSSL_malloc(eklen);
518
519         if (ek == NULL)
520                 {
521                 CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, ERR_R_MALLOC_FAILURE);
522                 goto err;
523                 }
524
525         if (EVP_PKEY_decrypt(pctx, ek, &eklen,
526                                 ktri->encryptedKey->data,
527                                 ktri->encryptedKey->length) <= 0)
528                 {
529                 CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, CMS_R_CMS_LIB);
530                 goto err;
531                 }
532
533         ret = 1;
534
535         cms->d.envelopedData->encryptedContentInfo->key = ek;
536         cms->d.envelopedData->encryptedContentInfo->keylen = eklen;
537
538         err:
539         if (pctx)
540                 EVP_PKEY_CTX_free(pctx);
541         if (!ret && ek)
542                 OPENSSL_free(ek);
543
544         return ret;
545         }
546
547 BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
548         {
549         CMS_EncryptedContentInfo *ec;
550         STACK_OF(CMS_RecipientInfo) *rinfos;
551         CMS_RecipientInfo *ri;
552         int i, r, ok = 0;
553         BIO *ret;
554
555         /* Get BIO first to set up key */
556
557         ec = cms->d.envelopedData->encryptedContentInfo;
558         ret = cms_EncryptedContent_init_bio(ec);
559
560         /* If error or no cipher end of processing */
561
562         if (!ret || !ec->cipher)
563                 return ret;
564
565
566         rinfos = cms->d.envelopedData->recipientInfos;
567
568         for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++)
569                 {
570                 ri = sk_CMS_RecipientInfo_value(rinfos, i);
571                 if (ri->type == CMS_RECIPINFO_TRANS)
572                         r = cms_RecipientInfo_ktri_encrypt(cms, ri);
573                 else
574                         {
575                         CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
576                                 CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
577                         goto err;
578                         }
579                 if (r <= 0)
580                         {
581                         CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
582                                 CMS_R_ERROR_SETTING_RECIPIENTINFO);
583                         goto err;
584                         }
585                 }
586
587         ok = 1;
588
589         err:
590         ec->cipher = NULL;
591         if (ec->key)
592                 {
593                 OPENSSL_cleanse(ec->key, ec->keylen);
594                 OPENSSL_free(ec->key);
595                 ec->key = NULL;
596                 ec->keylen = 0;
597                 }
598         if (ok)
599                 return ret;
600         BIO_free(ret);
601         return NULL;
602
603         }