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