CMS: Fix NULL access if d2i_CMS_bio() is not passed a CMS_ContentInfo**.
[openssl.git] / crypto / cms / cms_enc.c
1 /*
2  * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include "internal/cryptlib.h"
11 #include <openssl/asn1t.h>
12 #include <openssl/pem.h>
13 #include <openssl/x509v3.h>
14 #include <openssl/err.h>
15 #include <openssl/cms.h>
16 #include <openssl/rand.h>
17 #include "crypto/evp.h"
18 #include "cms_local.h"
19
20 /* CMS EncryptedData Utilities */
21
22 /* Return BIO based on EncryptedContentInfo and key */
23
24 BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec,
25                                    const CMS_CTX *cms_ctx)
26 {
27     BIO *b;
28     EVP_CIPHER_CTX *ctx;
29     EVP_CIPHER *fetched_ciph = NULL;
30     const EVP_CIPHER *cipher = NULL;
31     X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
32     evp_cipher_aead_asn1_params aparams;
33     unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
34     unsigned char *tkey = NULL;
35     int len;
36     int ivlen = 0;
37     size_t tkeylen = 0;
38     int ok = 0;
39     int enc, keep_key = 0;
40     OSSL_LIB_CTX *libctx = cms_ctx_get0_libctx(cms_ctx);
41     const char *propq = cms_ctx_get0_propq(cms_ctx);
42
43     enc = ec->cipher ? 1 : 0;
44
45     b = BIO_new(BIO_f_cipher());
46     if (b == NULL) {
47         ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
48         return NULL;
49     }
50
51     BIO_get_cipher_ctx(b, &ctx);
52
53     (void)ERR_set_mark();
54     if (enc) {
55         cipher = ec->cipher;
56         /*
57          * If not keeping key set cipher to NULL so subsequent calls decrypt.
58          */
59         if (ec->key != NULL)
60             ec->cipher = NULL;
61     } else {
62         cipher = EVP_get_cipherbyobj(calg->algorithm);
63     }
64     if (cipher != NULL) {
65         fetched_ciph = EVP_CIPHER_fetch(libctx, EVP_CIPHER_name(cipher), propq);
66         if (fetched_ciph != NULL)
67             cipher = fetched_ciph;
68     }
69     if (cipher == NULL) {
70         (void)ERR_clear_last_mark();
71         ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER);
72         goto err;
73     }
74     (void)ERR_pop_to_mark();
75
76     if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc) <= 0) {
77         ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_INITIALISATION_ERROR);
78         goto err;
79     }
80
81     if (enc) {
82         calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
83         /* Generate a random IV if we need one */
84         ivlen = EVP_CIPHER_CTX_iv_length(ctx);
85         if (ivlen > 0) {
86             if (RAND_bytes_ex(libctx, iv, ivlen) <= 0)
87                 goto err;
88             piv = iv;
89         }
90     } else {
91         if (evp_cipher_asn1_to_param_ex(ctx, calg->parameter, &aparams) <= 0) {
92             ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
93             goto err;
94         }
95         if ((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) {
96             piv = aparams.iv;
97             if (ec->taglen > 0
98                     && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
99                                            ec->taglen, ec->tag) <= 0) {
100                 ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_AEAD_SET_TAG_ERROR);
101                 goto err;
102             }
103         }
104     }
105     len = EVP_CIPHER_CTX_key_length(ctx);
106     if (len <= 0)
107         goto err;
108     tkeylen = (size_t)len;
109
110     /* Generate random session key */
111     if (!enc || !ec->key) {
112         tkey = OPENSSL_malloc(tkeylen);
113         if (tkey == NULL) {
114             ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
115             goto err;
116         }
117         if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0)
118             goto err;
119     }
120
121     if (!ec->key) {
122         ec->key = tkey;
123         ec->keylen = tkeylen;
124         tkey = NULL;
125         if (enc)
126             keep_key = 1;
127         else
128             ERR_clear_error();
129
130     }
131
132     if (ec->keylen != tkeylen) {
133         /* If necessary set key length */
134         if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) {
135             /*
136              * Only reveal failure if debugging so we don't leak information
137              * which may be useful in MMA.
138              */
139             if (enc || ec->debug) {
140                 ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
141                 goto err;
142             } else {
143                 /* Use random key */
144                 OPENSSL_clear_free(ec->key, ec->keylen);
145                 ec->key = tkey;
146                 ec->keylen = tkeylen;
147                 tkey = NULL;
148                 ERR_clear_error();
149             }
150         }
151     }
152
153     if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) {
154         ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_INITIALISATION_ERROR);
155         goto err;
156     }
157     if (enc) {
158         calg->parameter = ASN1_TYPE_new();
159         if (calg->parameter == NULL) {
160             ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
161             goto err;
162         }
163         if ((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) {
164             memcpy(aparams.iv, piv, ivlen);
165             aparams.iv_len = ivlen;
166             aparams.tag_len = EVP_CIPHER_CTX_tag_length(ctx);
167             if (aparams.tag_len <= 0)
168                 goto err;
169         }
170
171         if (evp_cipher_param_to_asn1_ex(ctx, calg->parameter, &aparams) <= 0) {
172             ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
173             goto err;
174         }
175         /* If parameter type not set omit parameter */
176         if (calg->parameter->type == V_ASN1_UNDEF) {
177             ASN1_TYPE_free(calg->parameter);
178             calg->parameter = NULL;
179         }
180     }
181     ok = 1;
182
183  err:
184     EVP_CIPHER_free(fetched_ciph);
185     if (!keep_key || !ok) {
186         OPENSSL_clear_free(ec->key, ec->keylen);
187         ec->key = NULL;
188     }
189     OPENSSL_clear_free(tkey, tkeylen);
190     if (ok)
191         return b;
192     BIO_free(b);
193     return NULL;
194 }
195
196 int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
197                               const EVP_CIPHER *cipher,
198                               const unsigned char *key, size_t keylen,
199                               const CMS_CTX *cms_ctx)
200 {
201     ec->cipher = cipher;
202     if (key) {
203         if ((ec->key = OPENSSL_malloc(keylen)) == NULL) {
204             ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
205             return 0;
206         }
207         memcpy(ec->key, key, keylen);
208     }
209     ec->keylen = keylen;
210     if (cipher != NULL)
211         ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
212     return 1;
213 }
214
215 int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
216                                const unsigned char *key, size_t keylen)
217 {
218     CMS_EncryptedContentInfo *ec;
219
220     if (!key || !keylen) {
221         ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY);
222         return 0;
223     }
224     if (ciph) {
225         cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData);
226         if (!cms->d.encryptedData) {
227             ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
228             return 0;
229         }
230         cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted);
231         cms->d.encryptedData->version = 0;
232     } else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) {
233         ERR_raise(ERR_LIB_CMS, CMS_R_NOT_ENCRYPTED_DATA);
234         return 0;
235     }
236     ec = cms->d.encryptedData->encryptedContentInfo;
237     return cms_EncryptedContent_init(ec, ciph, key, keylen, cms_get0_cmsctx(cms));
238 }
239
240 BIO *cms_EncryptedData_init_bio(const CMS_ContentInfo *cms)
241 {
242     CMS_EncryptedData *enc = cms->d.encryptedData;
243     if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
244         enc->version = 2;
245     return cms_EncryptedContent_init_bio(enc->encryptedContentInfo,
246                                          cms_get0_cmsctx(cms));
247 }