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