xref: /openbsd/lib/libcrypto/cms/cms_kari.c (revision 2fa2cfa4)
1 /* $OpenBSD: cms_kari.c,v 1.16 2024/02/02 14:11:45 tb Exp $ */
2 /*
3  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4  * project.
5  */
6 /* ====================================================================
7  * Copyright (c) 2013 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/aes.h>
64 #include "cms_local.h"
65 #include "asn1/asn1_local.h"
66 
67 /* Key Agreement Recipient Info (KARI) routines */
68 
69 int
CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo * ri,X509_ALGOR ** palg,ASN1_OCTET_STRING ** pukm)70 CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, X509_ALGOR **palg,
71     ASN1_OCTET_STRING **pukm)
72 {
73 	if (ri->type != CMS_RECIPINFO_AGREE) {
74 		CMSerror(CMS_R_NOT_KEY_AGREEMENT);
75 		return 0;
76 	}
77 	if (palg)
78 		*palg = ri->d.kari->keyEncryptionAlgorithm;
79 	if (pukm)
80 		*pukm = ri->d.kari->ukm;
81 
82 	return 1;
83 }
84 LCRYPTO_ALIAS(CMS_RecipientInfo_kari_get0_alg);
85 
86 /* Retrieve recipient encrypted keys from a kari */
87 
STACK_OF(CMS_RecipientEncryptedKey)88 STACK_OF(CMS_RecipientEncryptedKey) *
89 CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri)
90 {
91 	if (ri->type != CMS_RECIPINFO_AGREE) {
92 		CMSerror(CMS_R_NOT_KEY_AGREEMENT);
93 		return NULL;
94 	}
95 	return ri->d.kari->recipientEncryptedKeys;
96 }
97 LCRYPTO_ALIAS(CMS_RecipientInfo_kari_get0_reks);
98 
99 int
CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo * ri,X509_ALGOR ** pubalg,ASN1_BIT_STRING ** pubkey,ASN1_OCTET_STRING ** keyid,X509_NAME ** issuer,ASN1_INTEGER ** sno)100 CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, X509_ALGOR **pubalg,
101     ASN1_BIT_STRING **pubkey, ASN1_OCTET_STRING **keyid, X509_NAME **issuer,
102     ASN1_INTEGER **sno)
103 {
104 	CMS_OriginatorIdentifierOrKey *oik;
105 
106 	if (ri->type != CMS_RECIPINFO_AGREE) {
107 		CMSerror(CMS_R_NOT_KEY_AGREEMENT);
108 		return 0;
109 	}
110 	oik = ri->d.kari->originator;
111 	if (issuer)
112 		*issuer = NULL;
113 	if (sno)
114 		*sno = NULL;
115 	if (keyid)
116 		*keyid = NULL;
117 	if (pubalg)
118 		*pubalg = NULL;
119 	if (pubkey)
120 		*pubkey = NULL;
121 	if (oik->type == CMS_OIK_ISSUER_SERIAL) {
122 		if (issuer)
123 			*issuer = oik->d.issuerAndSerialNumber->issuer;
124 		if (sno)
125 			*sno = oik->d.issuerAndSerialNumber->serialNumber;
126 	} else if (oik->type == CMS_OIK_KEYIDENTIFIER) {
127 		if (keyid)
128 			*keyid = oik->d.subjectKeyIdentifier;
129 	} else if (oik->type == CMS_OIK_PUBKEY) {
130 		if (pubalg)
131 			*pubalg = oik->d.originatorKey->algorithm;
132 		if (pubkey)
133 			*pubkey = oik->d.originatorKey->publicKey;
134 	} else
135 		return 0;
136 
137 	return 1;
138 }
139 LCRYPTO_ALIAS(CMS_RecipientInfo_kari_get0_orig_id);
140 
141 int
CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo * ri,X509 * cert)142 CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert)
143 {
144 	CMS_OriginatorIdentifierOrKey *oik;
145 
146 	if (ri->type != CMS_RECIPINFO_AGREE) {
147 		CMSerror(CMS_R_NOT_KEY_AGREEMENT);
148 		return -2;
149 	}
150 	oik = ri->d.kari->originator;
151 	if (oik->type == CMS_OIK_ISSUER_SERIAL)
152 		return cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert);
153 	else if (oik->type == CMS_OIK_KEYIDENTIFIER)
154 		return cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert);
155 
156 	return -1;
157 }
158 LCRYPTO_ALIAS(CMS_RecipientInfo_kari_orig_id_cmp);
159 
160 int
CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey * rek,ASN1_OCTET_STRING ** keyid,ASN1_GENERALIZEDTIME ** tm,CMS_OtherKeyAttribute ** other,X509_NAME ** issuer,ASN1_INTEGER ** sno)161 CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
162     ASN1_OCTET_STRING **keyid, ASN1_GENERALIZEDTIME **tm,
163     CMS_OtherKeyAttribute **other, X509_NAME **issuer, ASN1_INTEGER **sno)
164 {
165 	CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
166 
167 	if (rid->type == CMS_REK_ISSUER_SERIAL) {
168 		if (issuer)
169 			*issuer = rid->d.issuerAndSerialNumber->issuer;
170 		if (sno)
171 			*sno = rid->d.issuerAndSerialNumber->serialNumber;
172 		if (keyid)
173 			*keyid = NULL;
174 		if (tm)
175 			*tm = NULL;
176 		if (other)
177 			*other = NULL;
178 	} else if (rid->type == CMS_REK_KEYIDENTIFIER) {
179 		if (keyid)
180 			*keyid = rid->d.rKeyId->subjectKeyIdentifier;
181 		if (tm)
182 			*tm = rid->d.rKeyId->date;
183 		if (other)
184 			*other = rid->d.rKeyId->other;
185 		if (issuer)
186 			*issuer = NULL;
187 		if (sno)
188 			*sno = NULL;
189 	} else
190 		return 0;
191 
192 	return 1;
193 }
194 LCRYPTO_ALIAS(CMS_RecipientEncryptedKey_get0_id);
195 
196 int
CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey * rek,X509 * cert)197 CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, X509 *cert)
198 {
199 	CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
200 
201 	if (rid->type == CMS_REK_ISSUER_SERIAL)
202 		return cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert);
203 	else if (rid->type == CMS_REK_KEYIDENTIFIER)
204 		return cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier, cert);
205 	else
206 		return -1;
207 }
208 LCRYPTO_ALIAS(CMS_RecipientEncryptedKey_cert_cmp);
209 
210 int
CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo * ri,EVP_PKEY * pk)211 CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
212 {
213 	EVP_PKEY_CTX *pctx;
214 	CMS_KeyAgreeRecipientInfo *kari = ri->d.kari;
215 
216 	EVP_PKEY_CTX_free(kari->pctx);
217 	kari->pctx = NULL;
218 	if (!pk)
219 		return 1;
220 	pctx = EVP_PKEY_CTX_new(pk, NULL);
221 	if (!pctx || !EVP_PKEY_derive_init(pctx))
222 		goto err;
223 	kari->pctx = pctx;
224 	return 1;
225 
226  err:
227 	EVP_PKEY_CTX_free(pctx);
228 	return 0;
229 }
230 LCRYPTO_ALIAS(CMS_RecipientInfo_kari_set0_pkey);
231 
232 EVP_CIPHER_CTX *
CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo * ri)233 CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri)
234 {
235 	if (ri->type == CMS_RECIPINFO_AGREE)
236 		return ri->d.kari->ctx;
237 	return NULL;
238 }
239 LCRYPTO_ALIAS(CMS_RecipientInfo_kari_get0_ctx);
240 
241 /*
242  * Derive KEK and decrypt/encrypt with it to produce either the original CEK
243  * or the encrypted CEK.
244  */
245 
246 static int
cms_kek_cipher(unsigned char ** pout,size_t * poutlen,const unsigned char * in,size_t inlen,CMS_KeyAgreeRecipientInfo * kari,int enc)247 cms_kek_cipher(unsigned char **pout, size_t *poutlen, const unsigned char *in,
248     size_t inlen, CMS_KeyAgreeRecipientInfo *kari, int enc)
249 {
250 	/* Key encryption key */
251 	unsigned char kek[EVP_MAX_KEY_LENGTH];
252 	size_t keklen;
253 	int rv = 0;
254 	unsigned char *out = NULL;
255 	int outlen;
256 
257 	keklen = EVP_CIPHER_CTX_key_length(kari->ctx);
258 	if (keklen > EVP_MAX_KEY_LENGTH)
259 		return 0;
260 	/* Derive KEK */
261 	if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0)
262 		goto err;
263 	/* Set KEK in context */
264 	if (!EVP_CipherInit_ex(kari->ctx, NULL, NULL, kek, NULL, enc))
265 		goto err;
266 	/* obtain output length of ciphered key */
267 	if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen))
268 		goto err;
269 	out = malloc(outlen);
270 	if (out == NULL)
271 		goto err;
272 	if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen))
273 		goto err;
274 	*pout = out;
275 	*poutlen = (size_t)outlen;
276 	rv = 1;
277 
278  err:
279 	explicit_bzero(kek, keklen);
280 	if (!rv)
281 		free(out);
282 	(void)EVP_CIPHER_CTX_reset(kari->ctx);
283 	/* FIXME: WHY IS kari->pctx freed here?  /RL */
284 	EVP_PKEY_CTX_free(kari->pctx);
285 	kari->pctx = NULL;
286 
287 	return rv;
288 }
289 
290 int
CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo * cms,CMS_RecipientInfo * ri,CMS_RecipientEncryptedKey * rek)291 CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
292     CMS_RecipientEncryptedKey *rek)
293 {
294 	int rv = 0;
295 	unsigned char *enckey = NULL, *cek = NULL;
296 	size_t enckeylen;
297 	size_t ceklen;
298 	CMS_EncryptedContentInfo *ec;
299 
300 	enckeylen = rek->encryptedKey->length;
301 	enckey = rek->encryptedKey->data;
302 	/* Setup all parameters to derive KEK */
303 	if (!cms_env_asn1_ctrl(ri, 1))
304 		goto err;
305 	/* Attempt to decrypt CEK */
306 	if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0))
307 		goto err;
308 	ec = cms->d.envelopedData->encryptedContentInfo;
309 	freezero(ec->key, ec->keylen);
310 	ec->key = cek;
311 	ec->keylen = ceklen;
312 	cek = NULL;
313 	rv = 1;
314 
315  err:
316 	free(cek);
317 
318 	return rv;
319 }
320 LCRYPTO_ALIAS(CMS_RecipientInfo_kari_decrypt);
321 
322 /* Create ephemeral key and initialise context based on it */
323 static int
cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo * kari,EVP_PKEY * pk)324 cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari, EVP_PKEY *pk)
325 {
326 	EVP_PKEY_CTX *pctx = NULL;
327 	EVP_PKEY *ekey = NULL;
328 	int rv = 0;
329 
330 	pctx = EVP_PKEY_CTX_new(pk, NULL);
331 	if (!pctx)
332 		goto err;
333 	if (EVP_PKEY_keygen_init(pctx) <= 0)
334 		goto err;
335 	if (EVP_PKEY_keygen(pctx, &ekey) <= 0)
336 		goto err;
337 	EVP_PKEY_CTX_free(pctx);
338 	pctx = EVP_PKEY_CTX_new(ekey, NULL);
339 	if (!pctx)
340 		goto err;
341 	if (EVP_PKEY_derive_init(pctx) <= 0)
342 		goto err;
343 	kari->pctx = pctx;
344 	rv = 1;
345 
346  err:
347 	if (!rv)
348 		EVP_PKEY_CTX_free(pctx);
349 	EVP_PKEY_free(ekey);
350 
351 	return rv;
352 }
353 
354 /* Initialise a kari based on passed certificate and key */
355 
356 int
cms_RecipientInfo_kari_init(CMS_RecipientInfo * ri,X509 * recip,EVP_PKEY * pk,unsigned int flags)357 cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *pk,
358     unsigned int flags)
359 {
360 	CMS_KeyAgreeRecipientInfo *kari;
361 	CMS_RecipientEncryptedKey *rek = NULL;
362 
363 	ri->d.kari = (CMS_KeyAgreeRecipientInfo *)ASN1_item_new(&CMS_KeyAgreeRecipientInfo_it);
364 	if (!ri->d.kari)
365 		return 0;
366 	ri->type = CMS_RECIPINFO_AGREE;
367 
368 	kari = ri->d.kari;
369 	kari->version = 3;
370 
371 	rek = (CMS_RecipientEncryptedKey *)ASN1_item_new(&CMS_RecipientEncryptedKey_it);
372 	if (rek == NULL)
373 		return 0;
374 
375 	if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) {
376 		ASN1_item_free((ASN1_VALUE *)rek, &CMS_RecipientEncryptedKey_it);
377 		return 0;
378 	}
379 
380 	if (flags & CMS_USE_KEYID) {
381 		rek->rid->type = CMS_REK_KEYIDENTIFIER;
382 		rek->rid->d.rKeyId = (CMS_RecipientKeyIdentifier *)ASN1_item_new(&CMS_RecipientKeyIdentifier_it);
383 		if (rek->rid->d.rKeyId == NULL)
384 			return 0;
385 		if (!cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip))
386 			return 0;
387 	} else {
388 		rek->rid->type = CMS_REK_ISSUER_SERIAL;
389 		if (!cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip))
390 			return 0;
391 	}
392 
393 	/* Create ephemeral key */
394 	if (!cms_kari_create_ephemeral_key(kari, pk))
395 		return 0;
396 
397 	EVP_PKEY_up_ref(pk);
398 	rek->pkey = pk;
399 
400 	return 1;
401 }
402 
403 static int
cms_wrap_init(CMS_KeyAgreeRecipientInfo * kari,const EVP_CIPHER * cipher)404 cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari, const EVP_CIPHER *cipher)
405 {
406 	EVP_CIPHER_CTX *ctx = kari->ctx;
407 	const EVP_CIPHER *kekcipher;
408 	int keylen = EVP_CIPHER_key_length(cipher);
409 
410 	/* If a suitable wrap algorithm is already set nothing to do */
411 	kekcipher = EVP_CIPHER_CTX_cipher(ctx);
412 
413 	if (kekcipher) {
414 		if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE)
415 			return 0;
416 		return 1;
417 	}
418 	/*
419 	 * Pick a cipher based on content encryption cipher. If it is DES3 use
420 	 * DES3 wrap otherwise use AES wrap similar to key size.
421 	 */
422 #ifndef OPENSSL_NO_DES
423 #if 0
424 	/*
425 	 * XXX - we do not currently support DES3 wrap and probably should just
426 	 * drop this code.
427 	 */
428 	if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc)
429 		kekcipher = EVP_des_ede3_wrap();
430 	else
431 #endif
432 #endif
433 	if (keylen <= 16)
434 		kekcipher = EVP_aes_128_wrap();
435 	else if (keylen <= 24)
436 		kekcipher = EVP_aes_192_wrap();
437 	else
438 		kekcipher = EVP_aes_256_wrap();
439 
440 	return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL);
441 }
442 
443 /* Encrypt content key in key agreement recipient info */
444 
445 int
cms_RecipientInfo_kari_encrypt(CMS_ContentInfo * cms,CMS_RecipientInfo * ri)446 cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
447 {
448 	CMS_KeyAgreeRecipientInfo *kari;
449 	CMS_EncryptedContentInfo *ec;
450 	CMS_RecipientEncryptedKey *rek;
451 	STACK_OF(CMS_RecipientEncryptedKey) *reks;
452 	int i;
453 
454 	if (ri->type != CMS_RECIPINFO_AGREE) {
455 		CMSerror(CMS_R_NOT_KEY_AGREEMENT);
456 		return 0;
457 	}
458 	kari = ri->d.kari;
459 	reks = kari->recipientEncryptedKeys;
460 	ec = cms->d.envelopedData->encryptedContentInfo;
461 	/* Initialise wrap algorithm parameters */
462 	if (!cms_wrap_init(kari, ec->cipher))
463 		return 0;
464 	/*
465 	 * If no originator key set up initialise for ephemeral key the public key
466 	 * ASN1 structure will set the actual public key value.
467 	 */
468 	if (kari->originator->type == -1) {
469 		CMS_OriginatorIdentifierOrKey *oik = kari->originator;
470 		oik->type = CMS_OIK_PUBKEY;
471 		oik->d.originatorKey = (CMS_OriginatorPublicKey *)ASN1_item_new(&CMS_OriginatorPublicKey_it);
472 		if (!oik->d.originatorKey)
473 			return 0;
474 	}
475 	/* Initialise KDF algorithm */
476 	if (!cms_env_asn1_ctrl(ri, 0))
477 		return 0;
478 	/* For each rek, derive KEK, encrypt CEK */
479 	for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
480 		unsigned char *enckey;
481 		size_t enckeylen;
482 		rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
483 		if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0)
484 			return 0;
485 		if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen,
486 			                kari, 1))
487 			return 0;
488 		ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen);
489 	}
490 
491 	return 1;
492 }
493