]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/cms/cms_pwri.c
Fix safestack issues in cms.h
[thirdparty/openssl.git] / crypto / cms / cms_pwri.c
CommitLineData
0f113f3e 1/*
454afd98 2 * Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
d2a53c22 3 *
08ddd302 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
b1322259
RS
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
d2a53c22
DSH
8 */
9
b39fc560 10#include "internal/cryptlib.h"
d2a53c22
DSH
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 <openssl/aes.h>
706457b7 18#include "cms_local.h"
25f2138b 19#include "crypto/asn1.h"
d2a53c22 20
0f113f3e
MC
21int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
22 unsigned char *pass, ossl_ssize_t passlen)
23{
24 CMS_PasswordRecipientInfo *pwri;
25 if (ri->type != CMS_RECIPINFO_PASS) {
26 CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI);
27 return 0;
28 }
29
30 pwri = ri->d.pwri;
31 pwri->pass = pass;
32 if (pass && passlen < 0)
33 passlen = strlen((char *)pass);
34 pwri->passlen = passlen;
35 return 1;
36}
d2a53c22
DSH
37
38CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
0f113f3e
MC
39 int iter, int wrap_nid,
40 int pbe_nid,
41 unsigned char *pass,
42 ossl_ssize_t passlen,
43 const EVP_CIPHER *kekciph)
44{
924663c3 45 STACK_OF(CMS_RecipientInfo) *ris;
0f113f3e 46 CMS_RecipientInfo *ri = NULL;
924663c3 47 CMS_EncryptedContentInfo *ec;
0f113f3e 48 CMS_PasswordRecipientInfo *pwri;
846ec07d 49 EVP_CIPHER_CTX *ctx = NULL;
0f113f3e
MC
50 X509_ALGOR *encalg = NULL;
51 unsigned char iv[EVP_MAX_IV_LENGTH];
52 int ivlen;
c1669f41 53 const CMS_CTX *cms_ctx = cms_get0_cmsctx(cms);
0f113f3e 54
924663c3
JZ
55 ec = cms_get0_env_enc_content(cms);
56 if (ec == NULL)
57 return NULL;
58 ris = CMS_get0_RecipientInfos(cms);
59 if (ris == NULL)
0f113f3e
MC
60 return NULL;
61
62 if (wrap_nid <= 0)
63 wrap_nid = NID_id_alg_PWRI_KEK;
64
65 if (pbe_nid <= 0)
66 pbe_nid = NID_id_pbkdf2;
67
68 /* Get from enveloped data */
69 if (kekciph == NULL)
924663c3 70 kekciph = ec->cipher;
0f113f3e
MC
71
72 if (kekciph == NULL) {
73 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER);
74 return NULL;
75 }
76 if (wrap_nid != NID_id_alg_PWRI_KEK) {
77 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
78 CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
79 return NULL;
80 }
81
82 /* Setup algorithm identifier for cipher */
83 encalg = X509_ALGOR_new();
90945fa3
MC
84 if (encalg == NULL) {
85 goto merr;
86 }
846ec07d 87 ctx = EVP_CIPHER_CTX_new();
0f113f3e 88
846ec07d 89 if (EVP_EncryptInit_ex(ctx, kekciph, NULL, NULL, NULL) <= 0) {
0f113f3e
MC
90 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
91 goto err;
92 }
93
846ec07d 94 ivlen = EVP_CIPHER_CTX_iv_length(ctx);
0f113f3e
MC
95
96 if (ivlen > 0) {
c1669f41 97 if (RAND_bytes_ex(cms_ctx->libctx, iv, ivlen) <= 0)
0f113f3e 98 goto err;
846ec07d 99 if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) <= 0) {
0f113f3e
MC
100 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
101 goto err;
102 }
103 encalg->parameter = ASN1_TYPE_new();
104 if (!encalg->parameter) {
105 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
106 goto err;
107 }
846ec07d 108 if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) {
0f113f3e
MC
109 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
110 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
111 goto err;
112 }
113 }
114
846ec07d 115 encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
0f113f3e 116
846ec07d
RL
117 EVP_CIPHER_CTX_free(ctx);
118 ctx = NULL;
0f113f3e
MC
119
120 /* Initialize recipient info */
121 ri = M_ASN1_new_of(CMS_RecipientInfo);
90945fa3 122 if (ri == NULL)
0f113f3e
MC
123 goto merr;
124
125 ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo);
90945fa3 126 if (ri->d.pwri == NULL)
0f113f3e
MC
127 goto merr;
128 ri->type = CMS_RECIPINFO_PASS;
129
130 pwri = ri->d.pwri;
c1669f41 131 pwri->cms_ctx = cms_ctx;
0f113f3e
MC
132 /* Since this is overwritten, free up empty structure already there */
133 X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
134 pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
90945fa3 135 if (pwri->keyEncryptionAlgorithm == NULL)
0f113f3e
MC
136 goto merr;
137 pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid);
138 pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new();
90945fa3 139 if (pwri->keyEncryptionAlgorithm->parameter == NULL)
0f113f3e
MC
140 goto merr;
141
142 if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR),
143 &pwri->keyEncryptionAlgorithm->parameter->
144 value.sequence))
145 goto merr;
146 pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE;
147
148 X509_ALGOR_free(encalg);
149 encalg = NULL;
150
151 /* Setup PBE algorithm */
152
153 pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1);
154
12a765a5 155 if (pwri->keyDerivationAlgorithm == NULL)
0f113f3e
MC
156 goto err;
157
158 CMS_RecipientInfo_set0_password(ri, pass, passlen);
159 pwri->version = 0;
160
924663c3 161 if (!sk_CMS_RecipientInfo_push(ris, ri))
0f113f3e
MC
162 goto merr;
163
164 return ri;
165
166 merr:
167 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
168 err:
846ec07d 169 EVP_CIPHER_CTX_free(ctx);
0f113f3e
MC
170 if (ri)
171 M_ASN1_free_of(ri, CMS_RecipientInfo);
222561fe 172 X509_ALGOR_free(encalg);
0f113f3e
MC
173 return NULL;
174
175}
176
177/*
178 * This is an implementation of the key wrapping mechanism in RFC3211, at
179 * some point this should go into EVP.
d2a53c22
DSH
180 */
181
182static int kek_unwrap_key(unsigned char *out, size_t *outlen,
0f113f3e
MC
183 const unsigned char *in, size_t inlen,
184 EVP_CIPHER_CTX *ctx)
185{
186 size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
187 unsigned char *tmp;
188 int outl, rv = 0;
189 if (inlen < 2 * blocklen) {
190 /* too small */
191 return 0;
192 }
193 if (inlen % blocklen) {
194 /* Invalid size */
195 return 0;
196 }
cdb10bae
RS
197 if ((tmp = OPENSSL_malloc(inlen)) == NULL) {
198 CMSerr(CMS_F_KEK_UNWRAP_KEY, ERR_R_MALLOC_FAILURE);
918bb865 199 return 0;
cdb10bae 200 }
0f113f3e
MC
201 /* setup IV by decrypting last two blocks */
202 if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl,
203 in + inlen - 2 * blocklen, blocklen * 2)
204 /*
205 * Do a decrypt of last decrypted block to set IV to correct value
206 * output it to start of buffer so we don't corrupt decrypted block
207 * this works because buffer is at least two block lengths long.
208 */
209 || !EVP_DecryptUpdate(ctx, tmp, &outl,
210 tmp + inlen - blocklen, blocklen)
211 /* Can now decrypt first n - 1 blocks */
212 || !EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen)
213
214 /* Reset IV to original value */
215 || !EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL)
216 /* Decrypt again */
217 || !EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen))
218 goto err;
219 /* Check check bytes */
220 if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff) {
221 /* Check byte failure */
222 goto err;
223 }
224 if (inlen < (size_t)(tmp[0] - 4)) {
225 /* Invalid length value */
226 goto err;
227 }
228 *outlen = (size_t)tmp[0];
229 memcpy(out, tmp + 4, *outlen);
230 rv = 1;
231 err:
4b45c6e5 232 OPENSSL_clear_free(tmp, inlen);
0f113f3e
MC
233 return rv;
234
235}
d2a53c22
DSH
236
237static int kek_wrap_key(unsigned char *out, size_t *outlen,
0f113f3e 238 const unsigned char *in, size_t inlen,
c1669f41 239 EVP_CIPHER_CTX *ctx, const CMS_CTX *cms_ctx)
0f113f3e
MC
240{
241 size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
242 size_t olen;
243 int dummy;
244 /*
245 * First decide length of output buffer: need header and round up to
246 * multiple of block length.
247 */
248 olen = (inlen + 4 + blocklen - 1) / blocklen;
249 olen *= blocklen;
250 if (olen < 2 * blocklen) {
251 /* Key too small */
252 return 0;
253 }
254 if (inlen > 0xFF) {
255 /* Key too large */
256 return 0;
257 }
258 if (out) {
259 /* Set header */
260 out[0] = (unsigned char)inlen;
261 out[1] = in[0] ^ 0xFF;
262 out[2] = in[1] ^ 0xFF;
263 out[3] = in[2] ^ 0xFF;
264 memcpy(out + 4, in, inlen);
265 /* Add random padding to end */
266483d2 266 if (olen > inlen + 4
c1669f41
SL
267 && RAND_bytes_ex(cms_ctx->libctx, out + 4 + inlen,
268 olen - 4 - inlen) <= 0)
266483d2 269 return 0;
0f113f3e
MC
270 /* Encrypt twice */
271 if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen)
272 || !EVP_EncryptUpdate(ctx, out, &dummy, out, olen))
273 return 0;
274 }
275
276 *outlen = olen;
277
278 return 1;
279}
d2a53c22
DSH
280
281/* Encrypt/Decrypt content key in PWRI recipient info */
282
c1669f41
SL
283int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms,
284 CMS_RecipientInfo *ri, int en_de)
0f113f3e
MC
285{
286 CMS_EncryptedContentInfo *ec;
287 CMS_PasswordRecipientInfo *pwri;
0f113f3e
MC
288 int r = 0;
289 X509_ALGOR *algtmp, *kekalg = NULL;
29f4c357 290 EVP_CIPHER_CTX *kekctx = NULL;
c1669f41
SL
291 const char *name;
292 EVP_CIPHER *kekcipher;
0f113f3e
MC
293 unsigned char *key = NULL;
294 size_t keylen;
c1669f41 295 const CMS_CTX *cms_ctx = cms_get0_cmsctx(cms);
0f113f3e 296
924663c3 297 ec = cms_get0_env_enc_content(cms);
0f113f3e
MC
298
299 pwri = ri->d.pwri;
0f113f3e 300
12a765a5 301 if (pwri->pass == NULL) {
0f113f3e
MC
302 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD);
303 return 0;
304 }
305 algtmp = pwri->keyEncryptionAlgorithm;
306
307 if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) {
308 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
309 CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
310 return 0;
311 }
312
e93c8748
DSH
313 kekalg = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
314 algtmp->parameter);
315
0f113f3e
MC
316 if (kekalg == NULL) {
317 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
318 CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
319 return 0;
320 }
321
c1669f41
SL
322 name = OBJ_nid2sn(OBJ_obj2nid(kekalg->algorithm));
323 kekcipher = EVP_CIPHER_fetch(cms_ctx->libctx, name, cms_ctx->propq);
0f113f3e 324
c1669f41 325 if (kekcipher == NULL) {
0f113f3e 326 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNKNOWN_CIPHER);
c1669f41 327 goto err;
0f113f3e
MC
328 }
329
29f4c357
MC
330 kekctx = EVP_CIPHER_CTX_new();
331 if (kekctx == NULL) {
332 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE);
c1669f41 333 goto err;
29f4c357 334 }
0f113f3e 335 /* Fixup cipher based on AlgorithmIdentifier to set IV etc */
846ec07d 336 if (!EVP_CipherInit_ex(kekctx, kekcipher, NULL, NULL, NULL, en_de))
0f113f3e 337 goto err;
846ec07d 338 EVP_CIPHER_CTX_set_padding(kekctx, 0);
49c9c1b3 339 if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) {
0f113f3e
MC
340 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
341 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
342 goto err;
343 }
344
345 algtmp = pwri->keyDerivationAlgorithm;
346
347 /* Finish password based key derivation to setup key in "ctx" */
348
349 if (EVP_PBE_CipherInit(algtmp->algorithm,
350 (char *)pwri->pass, pwri->passlen,
846ec07d 351 algtmp->parameter, kekctx, en_de) < 0) {
0f113f3e
MC
352 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB);
353 goto err;
354 }
355
356 /* Finally wrap/unwrap the key */
357
358 if (en_de) {
359
c1669f41 360 if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx, cms_ctx))
0f113f3e
MC
361 goto err;
362
363 key = OPENSSL_malloc(keylen);
364
90945fa3 365 if (key == NULL)
0f113f3e
MC
366 goto err;
367
c1669f41 368 if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx, cms_ctx))
0f113f3e
MC
369 goto err;
370 pwri->encryptedKey->data = key;
371 pwri->encryptedKey->length = keylen;
372 } else {
373 key = OPENSSL_malloc(pwri->encryptedKey->length);
374
90945fa3 375 if (key == NULL) {
0f113f3e
MC
376 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE);
377 goto err;
378 }
379 if (!kek_unwrap_key(key, &keylen,
380 pwri->encryptedKey->data,
846ec07d 381 pwri->encryptedKey->length, kekctx)) {
0f113f3e
MC
382 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNWRAP_FAILURE);
383 goto err;
384 }
385
4128136a 386 OPENSSL_clear_free(ec->key, ec->keylen);
0f113f3e
MC
387 ec->key = key;
388 ec->keylen = keylen;
389
390 }
391
392 r = 1;
393
394 err:
c1669f41 395 EVP_CIPHER_free(kekcipher);
846ec07d 396 EVP_CIPHER_CTX_free(kekctx);
0f113f3e 397
b548a1f1 398 if (!r)
0f113f3e
MC
399 OPENSSL_free(key);
400 X509_ALGOR_free(kekalg);
401
402 return r;
403
404}