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