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