]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/cms/cms_enc.c
Standardise our style for checking malloc failures
[thirdparty/openssl.git] / crypto / cms / cms_enc.c
CommitLineData
5c4436c9 1/* crypto/cms/cms_enc.c */
0f113f3e
MC
2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
5c4436c9
DSH
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
0f113f3e 14 * notice, this list of conditions and the following disclaimer.
5c4436c9
DSH
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
b39fc560 55#include "internal/cryptlib.h"
5c4436c9
DSH
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 "cms_lcl.h"
5c4436c9
DSH
63
64/* CMS EncryptedData Utilities */
65
320bfc1b
DSH
66/* Return BIO based on EncryptedContentInfo and key */
67
68BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
0f113f3e
MC
69{
70 BIO *b;
71 EVP_CIPHER_CTX *ctx;
72 const EVP_CIPHER *ciph;
73 X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
74 unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
75 unsigned char *tkey = NULL;
76 size_t tkeylen = 0;
5c4436c9 77
0f113f3e 78 int ok = 0;
d9f5f07e 79
0f113f3e 80 int enc, keep_key = 0;
5c4436c9 81
0f113f3e 82 enc = ec->cipher ? 1 : 0;
5c4436c9 83
0f113f3e
MC
84 b = BIO_new(BIO_f_cipher());
85 if (!b) {
86 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
87 return NULL;
88 }
5c4436c9 89
0f113f3e 90 BIO_get_cipher_ctx(b, &ctx);
5c4436c9 91
0f113f3e
MC
92 if (enc) {
93 ciph = ec->cipher;
94 /*
95 * If not keeping key set cipher to NULL so subsequent calls decrypt.
96 */
97 if (ec->key)
98 ec->cipher = NULL;
99 } else {
100 ciph = EVP_get_cipherbyobj(calg->algorithm);
5c4436c9 101
0f113f3e
MC
102 if (!ciph) {
103 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER);
104 goto err;
105 }
106 }
5c4436c9 107
0f113f3e
MC
108 if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) {
109 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
110 CMS_R_CIPHER_INITIALISATION_ERROR);
111 goto err;
112 }
5c4436c9 113
0f113f3e
MC
114 if (enc) {
115 int ivlen;
116 calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
117 /* Generate a random IV if we need one */
118 ivlen = EVP_CIPHER_CTX_iv_length(ctx);
119 if (ivlen > 0) {
266483d2 120 if (RAND_bytes(iv, ivlen) <= 0)
0f113f3e
MC
121 goto err;
122 piv = iv;
123 }
124 } else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) {
125 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
126 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
127 goto err;
128 }
129 tkeylen = EVP_CIPHER_CTX_key_length(ctx);
130 /* Generate random session key */
131 if (!enc || !ec->key) {
132 tkey = OPENSSL_malloc(tkeylen);
133 if (!tkey) {
134 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
135 goto err;
136 }
137 if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0)
138 goto err;
139 }
146b52ed 140
0f113f3e
MC
141 if (!ec->key) {
142 ec->key = tkey;
143 ec->keylen = tkeylen;
144 tkey = NULL;
145 if (enc)
146 keep_key = 1;
147 else
148 ERR_clear_error();
146b52ed 149
0f113f3e 150 }
e540d1cd 151
0f113f3e
MC
152 if (ec->keylen != tkeylen) {
153 /* If necessary set key length */
154 if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) {
155 /*
156 * Only reveal failure if debugging so we don't leak information
157 * which may be useful in MMA.
158 */
159 if (enc || ec->debug) {
160 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
161 CMS_R_INVALID_KEY_LENGTH);
162 goto err;
163 } else {
164 /* Use random key */
4b45c6e5 165 OPENSSL_clear_free(ec->key, ec->keylen);
0f113f3e
MC
166 ec->key = tkey;
167 ec->keylen = tkeylen;
168 tkey = NULL;
169 ERR_clear_error();
170 }
171 }
172 }
5c4436c9 173
0f113f3e
MC
174 if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) {
175 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
176 CMS_R_CIPHER_INITIALISATION_ERROR);
177 goto err;
178 }
5c4436c9 179
0f113f3e
MC
180 if (piv) {
181 calg->parameter = ASN1_TYPE_new();
182 if (!calg->parameter) {
183 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
184 goto err;
185 }
186 if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) {
187 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
188 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
189 goto err;
190 }
191 }
192 ok = 1;
5c4436c9 193
0f113f3e 194 err:
891eac46 195 if (!keep_key || !ok) {
4b45c6e5 196 OPENSSL_clear_free(ec->key, ec->keylen);
0f113f3e
MC
197 ec->key = NULL;
198 }
4b45c6e5 199 OPENSSL_clear_free(tkey, tkeylen);
0f113f3e
MC
200 if (ok)
201 return b;
202 BIO_free(b);
203 return NULL;
204}
205
206int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
207 const EVP_CIPHER *cipher,
208 const unsigned char *key, size_t keylen)
209{
210 ec->cipher = cipher;
211 if (key) {
212 ec->key = OPENSSL_malloc(keylen);
213 if (!ec->key)
214 return 0;
215 memcpy(ec->key, key, keylen);
216 }
217 ec->keylen = keylen;
218 if (cipher)
219 ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
220 return 1;
221}
320bfc1b
DSH
222
223int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
0f113f3e
MC
224 const unsigned char *key, size_t keylen)
225{
226 CMS_EncryptedContentInfo *ec;
227 if (!key || !keylen) {
228 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY);
229 return 0;
230 }
231 if (ciph) {
232 cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData);
233 if (!cms->d.encryptedData) {
234 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, ERR_R_MALLOC_FAILURE);
235 return 0;
236 }
237 cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted);
238 cms->d.encryptedData->version = 0;
239 } else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) {
240 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NOT_ENCRYPTED_DATA);
241 return 0;
242 }
243 ec = cms->d.encryptedData->encryptedContentInfo;
244 return cms_EncryptedContent_init(ec, ciph, key, keylen);
245}
320bfc1b
DSH
246
247BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms)
0f113f3e
MC
248{
249 CMS_EncryptedData *enc = cms->d.encryptedData;
250 if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
251 enc->version = 2;
252 return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
253}