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