]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/cms/cms_pwri.c
0393608fdb158a4f8ecf64ca3750383b715054cc
[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 int 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 }
37
38 CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
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 {
45 STACK_OF(CMS_RecipientInfo) *ris;
46 CMS_RecipientInfo *ri = NULL;
47 CMS_EncryptedContentInfo *ec;
48 CMS_PasswordRecipientInfo *pwri;
49 EVP_CIPHER_CTX *ctx = NULL;
50 X509_ALGOR *encalg = NULL;
51 unsigned char iv[EVP_MAX_IV_LENGTH];
52 int ivlen;
53 const CMS_CTX *cms_ctx = cms_get0_cmsctx(cms);
54
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)
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)
70 kekciph = ec->cipher;
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();
84 if (encalg == NULL) {
85 goto merr;
86 }
87 ctx = EVP_CIPHER_CTX_new();
88
89 if (EVP_EncryptInit_ex(ctx, kekciph, NULL, NULL, NULL) <= 0) {
90 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
91 goto err;
92 }
93
94 ivlen = EVP_CIPHER_CTX_iv_length(ctx);
95
96 if (ivlen > 0) {
97 if (RAND_bytes_ex(cms_ctx->libctx, iv, ivlen) <= 0)
98 goto err;
99 if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) <= 0) {
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 }
108 if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) {
109 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
110 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
111 goto err;
112 }
113 }
114
115 encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
116
117 EVP_CIPHER_CTX_free(ctx);
118 ctx = NULL;
119
120 /* Initialize recipient info */
121 ri = M_ASN1_new_of(CMS_RecipientInfo);
122 if (ri == NULL)
123 goto merr;
124
125 ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo);
126 if (ri->d.pwri == NULL)
127 goto merr;
128 ri->type = CMS_RECIPINFO_PASS;
129
130 pwri = ri->d.pwri;
131 pwri->cms_ctx = cms_ctx;
132 /* Since this is overwritten, free up empty structure already there */
133 X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
134 pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
135 if (pwri->keyEncryptionAlgorithm == NULL)
136 goto merr;
137 pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid);
138 pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new();
139 if (pwri->keyEncryptionAlgorithm->parameter == NULL)
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
155 if (pwri->keyDerivationAlgorithm == NULL)
156 goto err;
157
158 CMS_RecipientInfo_set0_password(ri, pass, passlen);
159 pwri->version = 0;
160
161 if (!sk_CMS_RecipientInfo_push(ris, ri))
162 goto merr;
163
164 return ri;
165
166 merr:
167 CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
168 err:
169 EVP_CIPHER_CTX_free(ctx);
170 if (ri)
171 M_ASN1_free_of(ri, CMS_RecipientInfo);
172 X509_ALGOR_free(encalg);
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.
180 */
181
182 static int kek_unwrap_key(unsigned char *out, size_t *outlen,
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 }
197 if ((tmp = OPENSSL_malloc(inlen)) == NULL) {
198 CMSerr(CMS_F_KEK_UNWRAP_KEY, ERR_R_MALLOC_FAILURE);
199 return 0;
200 }
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:
232 OPENSSL_clear_free(tmp, inlen);
233 return rv;
234
235 }
236
237 static int kek_wrap_key(unsigned char *out, size_t *outlen,
238 const unsigned char *in, size_t inlen,
239 EVP_CIPHER_CTX *ctx, const CMS_CTX *cms_ctx)
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 */
266 if (olen > inlen + 4
267 && RAND_bytes_ex(cms_ctx->libctx, out + 4 + inlen,
268 olen - 4 - inlen) <= 0)
269 return 0;
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 }
280
281 /* Encrypt/Decrypt content key in PWRI recipient info */
282
283 int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms,
284 CMS_RecipientInfo *ri, int en_de)
285 {
286 CMS_EncryptedContentInfo *ec;
287 CMS_PasswordRecipientInfo *pwri;
288 int r = 0;
289 X509_ALGOR *algtmp, *kekalg = NULL;
290 EVP_CIPHER_CTX *kekctx = NULL;
291 const char *name;
292 EVP_CIPHER *kekcipher;
293 unsigned char *key = NULL;
294 size_t keylen;
295 const CMS_CTX *cms_ctx = cms_get0_cmsctx(cms);
296
297 ec = cms_get0_env_enc_content(cms);
298
299 pwri = ri->d.pwri;
300
301 if (pwri->pass == NULL) {
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
313 kekalg = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
314 algtmp->parameter);
315
316 if (kekalg == NULL) {
317 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
318 CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
319 return 0;
320 }
321
322 name = OBJ_nid2sn(OBJ_obj2nid(kekalg->algorithm));
323 kekcipher = EVP_CIPHER_fetch(cms_ctx->libctx, name, cms_ctx->propq);
324
325 if (kekcipher == NULL) {
326 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNKNOWN_CIPHER);
327 goto err;
328 }
329
330 kekctx = EVP_CIPHER_CTX_new();
331 if (kekctx == NULL) {
332 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE);
333 goto err;
334 }
335 /* Fixup cipher based on AlgorithmIdentifier to set IV etc */
336 if (!EVP_CipherInit_ex(kekctx, kekcipher, NULL, NULL, NULL, en_de))
337 goto err;
338 EVP_CIPHER_CTX_set_padding(kekctx, 0);
339 if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) {
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,
351 algtmp->parameter, kekctx, en_de) < 0) {
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
360 if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx, cms_ctx))
361 goto err;
362
363 key = OPENSSL_malloc(keylen);
364
365 if (key == NULL)
366 goto err;
367
368 if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx, cms_ctx))
369 goto err;
370 pwri->encryptedKey->data = key;
371 pwri->encryptedKey->length = keylen;
372 } else {
373 key = OPENSSL_malloc(pwri->encryptedKey->length);
374
375 if (key == NULL) {
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,
381 pwri->encryptedKey->length, kekctx)) {
382 CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNWRAP_FAILURE);
383 goto err;
384 }
385
386 OPENSSL_clear_free(ec->key, ec->keylen);
387 ec->key = key;
388 ec->keylen = keylen;
389
390 }
391
392 r = 1;
393
394 err:
395 EVP_CIPHER_free(kekcipher);
396 EVP_CIPHER_CTX_free(kekctx);
397
398 if (!r)
399 OPENSSL_free(key);
400 X509_ALGOR_free(kekalg);
401
402 return r;
403
404 }