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