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