1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* 11e1051a39Sopenharmony_ci * Low level key APIs (DH etc) are deprecated for public use, but still ok for 12e1051a39Sopenharmony_ci * internal use. 13e1051a39Sopenharmony_ci */ 14e1051a39Sopenharmony_ci#include "internal/deprecated.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 17e1051a39Sopenharmony_ci#include <openssl/asn1t.h> 18e1051a39Sopenharmony_ci#include <openssl/pem.h> 19e1051a39Sopenharmony_ci#include <openssl/x509v3.h> 20e1051a39Sopenharmony_ci#include <openssl/err.h> 21e1051a39Sopenharmony_ci#include <openssl/cms.h> 22e1051a39Sopenharmony_ci#include <openssl/aes.h> 23e1051a39Sopenharmony_ci#include "cms_local.h" 24e1051a39Sopenharmony_ci#include "crypto/asn1.h" 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_ci/* Key Agreement Recipient Info (KARI) routines */ 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, 29e1051a39Sopenharmony_ci X509_ALGOR **palg, 30e1051a39Sopenharmony_ci ASN1_OCTET_STRING **pukm) 31e1051a39Sopenharmony_ci{ 32e1051a39Sopenharmony_ci if (ri->type != CMS_RECIPINFO_AGREE) { 33e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT); 34e1051a39Sopenharmony_ci return 0; 35e1051a39Sopenharmony_ci } 36e1051a39Sopenharmony_ci if (palg) 37e1051a39Sopenharmony_ci *palg = ri->d.kari->keyEncryptionAlgorithm; 38e1051a39Sopenharmony_ci if (pukm) 39e1051a39Sopenharmony_ci *pukm = ri->d.kari->ukm; 40e1051a39Sopenharmony_ci return 1; 41e1051a39Sopenharmony_ci} 42e1051a39Sopenharmony_ci 43e1051a39Sopenharmony_ci/* Retrieve recipient encrypted keys from a kari */ 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_ciSTACK_OF(CMS_RecipientEncryptedKey) 46e1051a39Sopenharmony_ci*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri) 47e1051a39Sopenharmony_ci{ 48e1051a39Sopenharmony_ci if (ri->type != CMS_RECIPINFO_AGREE) { 49e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT); 50e1051a39Sopenharmony_ci return NULL; 51e1051a39Sopenharmony_ci } 52e1051a39Sopenharmony_ci return ri->d.kari->recipientEncryptedKeys; 53e1051a39Sopenharmony_ci} 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, 56e1051a39Sopenharmony_ci X509_ALGOR **pubalg, 57e1051a39Sopenharmony_ci ASN1_BIT_STRING **pubkey, 58e1051a39Sopenharmony_ci ASN1_OCTET_STRING **keyid, 59e1051a39Sopenharmony_ci X509_NAME **issuer, 60e1051a39Sopenharmony_ci ASN1_INTEGER **sno) 61e1051a39Sopenharmony_ci{ 62e1051a39Sopenharmony_ci CMS_OriginatorIdentifierOrKey *oik; 63e1051a39Sopenharmony_ci 64e1051a39Sopenharmony_ci if (ri->type != CMS_RECIPINFO_AGREE) { 65e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT); 66e1051a39Sopenharmony_ci return 0; 67e1051a39Sopenharmony_ci } 68e1051a39Sopenharmony_ci oik = ri->d.kari->originator; 69e1051a39Sopenharmony_ci if (issuer) 70e1051a39Sopenharmony_ci *issuer = NULL; 71e1051a39Sopenharmony_ci if (sno) 72e1051a39Sopenharmony_ci *sno = NULL; 73e1051a39Sopenharmony_ci if (keyid) 74e1051a39Sopenharmony_ci *keyid = NULL; 75e1051a39Sopenharmony_ci if (pubalg) 76e1051a39Sopenharmony_ci *pubalg = NULL; 77e1051a39Sopenharmony_ci if (pubkey) 78e1051a39Sopenharmony_ci *pubkey = NULL; 79e1051a39Sopenharmony_ci if (oik->type == CMS_OIK_ISSUER_SERIAL) { 80e1051a39Sopenharmony_ci if (issuer) 81e1051a39Sopenharmony_ci *issuer = oik->d.issuerAndSerialNumber->issuer; 82e1051a39Sopenharmony_ci if (sno) 83e1051a39Sopenharmony_ci *sno = oik->d.issuerAndSerialNumber->serialNumber; 84e1051a39Sopenharmony_ci } else if (oik->type == CMS_OIK_KEYIDENTIFIER) { 85e1051a39Sopenharmony_ci if (keyid) 86e1051a39Sopenharmony_ci *keyid = oik->d.subjectKeyIdentifier; 87e1051a39Sopenharmony_ci } else if (oik->type == CMS_OIK_PUBKEY) { 88e1051a39Sopenharmony_ci if (pubalg) 89e1051a39Sopenharmony_ci *pubalg = oik->d.originatorKey->algorithm; 90e1051a39Sopenharmony_ci if (pubkey) 91e1051a39Sopenharmony_ci *pubkey = oik->d.originatorKey->publicKey; 92e1051a39Sopenharmony_ci } else 93e1051a39Sopenharmony_ci return 0; 94e1051a39Sopenharmony_ci return 1; 95e1051a39Sopenharmony_ci} 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert) 98e1051a39Sopenharmony_ci{ 99e1051a39Sopenharmony_ci CMS_OriginatorIdentifierOrKey *oik; 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci if (ri->type != CMS_RECIPINFO_AGREE) { 102e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT); 103e1051a39Sopenharmony_ci return -2; 104e1051a39Sopenharmony_ci } 105e1051a39Sopenharmony_ci oik = ri->d.kari->originator; 106e1051a39Sopenharmony_ci if (oik->type == CMS_OIK_ISSUER_SERIAL) 107e1051a39Sopenharmony_ci return ossl_cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert); 108e1051a39Sopenharmony_ci else if (oik->type == CMS_OIK_KEYIDENTIFIER) 109e1051a39Sopenharmony_ci return ossl_cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert); 110e1051a39Sopenharmony_ci return -1; 111e1051a39Sopenharmony_ci} 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ciint CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek, 114e1051a39Sopenharmony_ci ASN1_OCTET_STRING **keyid, 115e1051a39Sopenharmony_ci ASN1_GENERALIZEDTIME **tm, 116e1051a39Sopenharmony_ci CMS_OtherKeyAttribute **other, 117e1051a39Sopenharmony_ci X509_NAME **issuer, ASN1_INTEGER **sno) 118e1051a39Sopenharmony_ci{ 119e1051a39Sopenharmony_ci CMS_KeyAgreeRecipientIdentifier *rid = rek->rid; 120e1051a39Sopenharmony_ci 121e1051a39Sopenharmony_ci if (rid->type == CMS_REK_ISSUER_SERIAL) { 122e1051a39Sopenharmony_ci if (issuer) 123e1051a39Sopenharmony_ci *issuer = rid->d.issuerAndSerialNumber->issuer; 124e1051a39Sopenharmony_ci if (sno) 125e1051a39Sopenharmony_ci *sno = rid->d.issuerAndSerialNumber->serialNumber; 126e1051a39Sopenharmony_ci if (keyid) 127e1051a39Sopenharmony_ci *keyid = NULL; 128e1051a39Sopenharmony_ci if (tm) 129e1051a39Sopenharmony_ci *tm = NULL; 130e1051a39Sopenharmony_ci if (other) 131e1051a39Sopenharmony_ci *other = NULL; 132e1051a39Sopenharmony_ci } else if (rid->type == CMS_REK_KEYIDENTIFIER) { 133e1051a39Sopenharmony_ci if (keyid) 134e1051a39Sopenharmony_ci *keyid = rid->d.rKeyId->subjectKeyIdentifier; 135e1051a39Sopenharmony_ci if (tm) 136e1051a39Sopenharmony_ci *tm = rid->d.rKeyId->date; 137e1051a39Sopenharmony_ci if (other) 138e1051a39Sopenharmony_ci *other = rid->d.rKeyId->other; 139e1051a39Sopenharmony_ci if (issuer) 140e1051a39Sopenharmony_ci *issuer = NULL; 141e1051a39Sopenharmony_ci if (sno) 142e1051a39Sopenharmony_ci *sno = NULL; 143e1051a39Sopenharmony_ci } else 144e1051a39Sopenharmony_ci return 0; 145e1051a39Sopenharmony_ci return 1; 146e1051a39Sopenharmony_ci} 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_ciint CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, 149e1051a39Sopenharmony_ci X509 *cert) 150e1051a39Sopenharmony_ci{ 151e1051a39Sopenharmony_ci CMS_KeyAgreeRecipientIdentifier *rid = rek->rid; 152e1051a39Sopenharmony_ci 153e1051a39Sopenharmony_ci if (rid->type == CMS_REK_ISSUER_SERIAL) 154e1051a39Sopenharmony_ci return ossl_cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert); 155e1051a39Sopenharmony_ci else if (rid->type == CMS_REK_KEYIDENTIFIER) 156e1051a39Sopenharmony_ci return ossl_cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier, 157e1051a39Sopenharmony_ci cert); 158e1051a39Sopenharmony_ci else 159e1051a39Sopenharmony_ci return -1; 160e1051a39Sopenharmony_ci} 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri, 163e1051a39Sopenharmony_ci EVP_PKEY *pk, X509 *peer) 164e1051a39Sopenharmony_ci{ 165e1051a39Sopenharmony_ci EVP_PKEY_CTX *pctx; 166e1051a39Sopenharmony_ci CMS_KeyAgreeRecipientInfo *kari = ri->d.kari; 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci EVP_PKEY_CTX_free(kari->pctx); 169e1051a39Sopenharmony_ci kari->pctx = NULL; 170e1051a39Sopenharmony_ci if (pk == NULL) 171e1051a39Sopenharmony_ci return 1; 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(kari->cms_ctx), 174e1051a39Sopenharmony_ci pk, 175e1051a39Sopenharmony_ci ossl_cms_ctx_get0_propq(kari->cms_ctx)); 176e1051a39Sopenharmony_ci if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0) 177e1051a39Sopenharmony_ci goto err; 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci if (peer != NULL) { 180e1051a39Sopenharmony_ci EVP_PKEY *pub_pkey = X509_get0_pubkey(peer); 181e1051a39Sopenharmony_ci 182e1051a39Sopenharmony_ci if (EVP_PKEY_derive_set_peer(pctx, pub_pkey) <= 0) 183e1051a39Sopenharmony_ci goto err; 184e1051a39Sopenharmony_ci } 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci kari->pctx = pctx; 187e1051a39Sopenharmony_ci return 1; 188e1051a39Sopenharmony_ci err: 189e1051a39Sopenharmony_ci EVP_PKEY_CTX_free(pctx); 190e1051a39Sopenharmony_ci return 0; 191e1051a39Sopenharmony_ci} 192e1051a39Sopenharmony_ci 193e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk) 194e1051a39Sopenharmony_ci{ 195e1051a39Sopenharmony_ci return CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, NULL); 196e1051a39Sopenharmony_ci} 197e1051a39Sopenharmony_ci 198e1051a39Sopenharmony_ciEVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri) 199e1051a39Sopenharmony_ci{ 200e1051a39Sopenharmony_ci if (ri->type == CMS_RECIPINFO_AGREE) 201e1051a39Sopenharmony_ci return ri->d.kari->ctx; 202e1051a39Sopenharmony_ci return NULL; 203e1051a39Sopenharmony_ci} 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_ci/* 206e1051a39Sopenharmony_ci * Derive KEK and decrypt/encrypt with it to produce either the original CEK 207e1051a39Sopenharmony_ci * or the encrypted CEK. 208e1051a39Sopenharmony_ci */ 209e1051a39Sopenharmony_ci 210e1051a39Sopenharmony_cistatic int cms_kek_cipher(unsigned char **pout, size_t *poutlen, 211e1051a39Sopenharmony_ci const unsigned char *in, size_t inlen, 212e1051a39Sopenharmony_ci CMS_KeyAgreeRecipientInfo *kari, int enc) 213e1051a39Sopenharmony_ci{ 214e1051a39Sopenharmony_ci /* Key encryption key */ 215e1051a39Sopenharmony_ci unsigned char kek[EVP_MAX_KEY_LENGTH]; 216e1051a39Sopenharmony_ci size_t keklen; 217e1051a39Sopenharmony_ci int rv = 0; 218e1051a39Sopenharmony_ci unsigned char *out = NULL; 219e1051a39Sopenharmony_ci int outlen; 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ci keklen = EVP_CIPHER_CTX_get_key_length(kari->ctx); 222e1051a39Sopenharmony_ci if (keklen > EVP_MAX_KEY_LENGTH) 223e1051a39Sopenharmony_ci return 0; 224e1051a39Sopenharmony_ci /* Derive KEK */ 225e1051a39Sopenharmony_ci if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0) 226e1051a39Sopenharmony_ci goto err; 227e1051a39Sopenharmony_ci /* Set KEK in context */ 228e1051a39Sopenharmony_ci if (!EVP_CipherInit_ex(kari->ctx, NULL, NULL, kek, NULL, enc)) 229e1051a39Sopenharmony_ci goto err; 230e1051a39Sopenharmony_ci /* obtain output length of ciphered key */ 231e1051a39Sopenharmony_ci if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen)) 232e1051a39Sopenharmony_ci goto err; 233e1051a39Sopenharmony_ci out = OPENSSL_malloc(outlen); 234e1051a39Sopenharmony_ci if (out == NULL) 235e1051a39Sopenharmony_ci goto err; 236e1051a39Sopenharmony_ci if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen)) 237e1051a39Sopenharmony_ci goto err; 238e1051a39Sopenharmony_ci *pout = out; 239e1051a39Sopenharmony_ci *poutlen = (size_t)outlen; 240e1051a39Sopenharmony_ci rv = 1; 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ci err: 243e1051a39Sopenharmony_ci OPENSSL_cleanse(kek, keklen); 244e1051a39Sopenharmony_ci if (!rv) 245e1051a39Sopenharmony_ci OPENSSL_free(out); 246e1051a39Sopenharmony_ci EVP_CIPHER_CTX_reset(kari->ctx); 247e1051a39Sopenharmony_ci /* FIXME: WHY IS kari->pctx freed here? /RL */ 248e1051a39Sopenharmony_ci EVP_PKEY_CTX_free(kari->pctx); 249e1051a39Sopenharmony_ci kari->pctx = NULL; 250e1051a39Sopenharmony_ci return rv; 251e1051a39Sopenharmony_ci} 252e1051a39Sopenharmony_ci 253e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, 254e1051a39Sopenharmony_ci CMS_RecipientInfo *ri, 255e1051a39Sopenharmony_ci CMS_RecipientEncryptedKey *rek) 256e1051a39Sopenharmony_ci{ 257e1051a39Sopenharmony_ci int rv = 0; 258e1051a39Sopenharmony_ci unsigned char *enckey = NULL, *cek = NULL; 259e1051a39Sopenharmony_ci size_t enckeylen; 260e1051a39Sopenharmony_ci size_t ceklen; 261e1051a39Sopenharmony_ci CMS_EncryptedContentInfo *ec; 262e1051a39Sopenharmony_ci 263e1051a39Sopenharmony_ci enckeylen = rek->encryptedKey->length; 264e1051a39Sopenharmony_ci enckey = rek->encryptedKey->data; 265e1051a39Sopenharmony_ci /* Setup all parameters to derive KEK */ 266e1051a39Sopenharmony_ci if (!ossl_cms_env_asn1_ctrl(ri, 1)) 267e1051a39Sopenharmony_ci goto err; 268e1051a39Sopenharmony_ci /* Attempt to decrypt CEK */ 269e1051a39Sopenharmony_ci if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0)) 270e1051a39Sopenharmony_ci goto err; 271e1051a39Sopenharmony_ci ec = ossl_cms_get0_env_enc_content(cms); 272e1051a39Sopenharmony_ci OPENSSL_clear_free(ec->key, ec->keylen); 273e1051a39Sopenharmony_ci ec->key = cek; 274e1051a39Sopenharmony_ci ec->keylen = ceklen; 275e1051a39Sopenharmony_ci cek = NULL; 276e1051a39Sopenharmony_ci rv = 1; 277e1051a39Sopenharmony_ci err: 278e1051a39Sopenharmony_ci OPENSSL_free(cek); 279e1051a39Sopenharmony_ci return rv; 280e1051a39Sopenharmony_ci} 281e1051a39Sopenharmony_ci 282e1051a39Sopenharmony_ci/* Create ephemeral key and initialise context based on it */ 283e1051a39Sopenharmony_cistatic int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari, 284e1051a39Sopenharmony_ci EVP_PKEY *pk) 285e1051a39Sopenharmony_ci{ 286e1051a39Sopenharmony_ci EVP_PKEY_CTX *pctx = NULL; 287e1051a39Sopenharmony_ci EVP_PKEY *ekey = NULL; 288e1051a39Sopenharmony_ci int rv = 0; 289e1051a39Sopenharmony_ci const CMS_CTX *ctx = kari->cms_ctx; 290e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx); 291e1051a39Sopenharmony_ci const char *propq = ossl_cms_ctx_get0_propq(ctx); 292e1051a39Sopenharmony_ci 293e1051a39Sopenharmony_ci pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propq); 294e1051a39Sopenharmony_ci if (pctx == NULL) 295e1051a39Sopenharmony_ci goto err; 296e1051a39Sopenharmony_ci if (EVP_PKEY_keygen_init(pctx) <= 0) 297e1051a39Sopenharmony_ci goto err; 298e1051a39Sopenharmony_ci if (EVP_PKEY_keygen(pctx, &ekey) <= 0) 299e1051a39Sopenharmony_ci goto err; 300e1051a39Sopenharmony_ci EVP_PKEY_CTX_free(pctx); 301e1051a39Sopenharmony_ci pctx = EVP_PKEY_CTX_new_from_pkey(libctx, ekey, propq); 302e1051a39Sopenharmony_ci if (pctx == NULL) 303e1051a39Sopenharmony_ci goto err; 304e1051a39Sopenharmony_ci if (EVP_PKEY_derive_init(pctx) <= 0) 305e1051a39Sopenharmony_ci goto err; 306e1051a39Sopenharmony_ci kari->pctx = pctx; 307e1051a39Sopenharmony_ci rv = 1; 308e1051a39Sopenharmony_ci err: 309e1051a39Sopenharmony_ci if (!rv) 310e1051a39Sopenharmony_ci EVP_PKEY_CTX_free(pctx); 311e1051a39Sopenharmony_ci EVP_PKEY_free(ekey); 312e1051a39Sopenharmony_ci return rv; 313e1051a39Sopenharmony_ci} 314e1051a39Sopenharmony_ci 315e1051a39Sopenharmony_ci/* Set originator private key and initialise context based on it */ 316e1051a39Sopenharmony_cistatic int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari, 317e1051a39Sopenharmony_ci EVP_PKEY *originatorPrivKey ) 318e1051a39Sopenharmony_ci{ 319e1051a39Sopenharmony_ci EVP_PKEY_CTX *pctx = NULL; 320e1051a39Sopenharmony_ci int rv = 0; 321e1051a39Sopenharmony_ci const CMS_CTX *ctx = kari->cms_ctx; 322e1051a39Sopenharmony_ci 323e1051a39Sopenharmony_ci pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx), 324e1051a39Sopenharmony_ci originatorPrivKey, 325e1051a39Sopenharmony_ci ossl_cms_ctx_get0_propq(ctx)); 326e1051a39Sopenharmony_ci if (pctx == NULL) 327e1051a39Sopenharmony_ci goto err; 328e1051a39Sopenharmony_ci if (EVP_PKEY_derive_init(pctx) <= 0) 329e1051a39Sopenharmony_ci goto err; 330e1051a39Sopenharmony_ci 331e1051a39Sopenharmony_ci kari->pctx = pctx; 332e1051a39Sopenharmony_ci rv = 1; 333e1051a39Sopenharmony_ci err: 334e1051a39Sopenharmony_ci if (rv == 0) 335e1051a39Sopenharmony_ci EVP_PKEY_CTX_free(pctx); 336e1051a39Sopenharmony_ci return rv; 337e1051a39Sopenharmony_ci} 338e1051a39Sopenharmony_ci 339e1051a39Sopenharmony_ci/* Initialise a kari based on passed certificate and key */ 340e1051a39Sopenharmony_ci 341e1051a39Sopenharmony_ciint ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, 342e1051a39Sopenharmony_ci EVP_PKEY *recipPubKey, X509 *originator, 343e1051a39Sopenharmony_ci EVP_PKEY *originatorPrivKey, 344e1051a39Sopenharmony_ci unsigned int flags, const CMS_CTX *ctx) 345e1051a39Sopenharmony_ci{ 346e1051a39Sopenharmony_ci CMS_KeyAgreeRecipientInfo *kari; 347e1051a39Sopenharmony_ci CMS_RecipientEncryptedKey *rek = NULL; 348e1051a39Sopenharmony_ci 349e1051a39Sopenharmony_ci ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo); 350e1051a39Sopenharmony_ci if (ri->d.kari == NULL) 351e1051a39Sopenharmony_ci return 0; 352e1051a39Sopenharmony_ci ri->type = CMS_RECIPINFO_AGREE; 353e1051a39Sopenharmony_ci 354e1051a39Sopenharmony_ci kari = ri->d.kari; 355e1051a39Sopenharmony_ci kari->version = 3; 356e1051a39Sopenharmony_ci kari->cms_ctx = ctx; 357e1051a39Sopenharmony_ci 358e1051a39Sopenharmony_ci rek = M_ASN1_new_of(CMS_RecipientEncryptedKey); 359e1051a39Sopenharmony_ci if (rek == NULL) 360e1051a39Sopenharmony_ci return 0; 361e1051a39Sopenharmony_ci 362e1051a39Sopenharmony_ci if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) { 363e1051a39Sopenharmony_ci M_ASN1_free_of(rek, CMS_RecipientEncryptedKey); 364e1051a39Sopenharmony_ci return 0; 365e1051a39Sopenharmony_ci } 366e1051a39Sopenharmony_ci 367e1051a39Sopenharmony_ci if (flags & CMS_USE_KEYID) { 368e1051a39Sopenharmony_ci rek->rid->type = CMS_REK_KEYIDENTIFIER; 369e1051a39Sopenharmony_ci rek->rid->d.rKeyId = M_ASN1_new_of(CMS_RecipientKeyIdentifier); 370e1051a39Sopenharmony_ci if (rek->rid->d.rKeyId == NULL) 371e1051a39Sopenharmony_ci return 0; 372e1051a39Sopenharmony_ci if (!ossl_cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip)) 373e1051a39Sopenharmony_ci return 0; 374e1051a39Sopenharmony_ci } else { 375e1051a39Sopenharmony_ci rek->rid->type = CMS_REK_ISSUER_SERIAL; 376e1051a39Sopenharmony_ci if (!ossl_cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip)) 377e1051a39Sopenharmony_ci return 0; 378e1051a39Sopenharmony_ci } 379e1051a39Sopenharmony_ci 380e1051a39Sopenharmony_ci if (originatorPrivKey == NULL && originator == NULL) { 381e1051a39Sopenharmony_ci /* Create ephemeral key */ 382e1051a39Sopenharmony_ci if (!cms_kari_create_ephemeral_key(kari, recipPubKey)) 383e1051a39Sopenharmony_ci return 0; 384e1051a39Sopenharmony_ci } else { 385e1051a39Sopenharmony_ci /* Use originator key */ 386e1051a39Sopenharmony_ci CMS_OriginatorIdentifierOrKey *oik = ri->d.kari->originator; 387e1051a39Sopenharmony_ci 388e1051a39Sopenharmony_ci if (originatorPrivKey == NULL || originator == NULL) 389e1051a39Sopenharmony_ci return 0; 390e1051a39Sopenharmony_ci 391e1051a39Sopenharmony_ci if (flags & CMS_USE_ORIGINATOR_KEYID) { 392e1051a39Sopenharmony_ci oik->type = CMS_OIK_KEYIDENTIFIER; 393e1051a39Sopenharmony_ci oik->d.subjectKeyIdentifier = ASN1_OCTET_STRING_new(); 394e1051a39Sopenharmony_ci if (oik->d.subjectKeyIdentifier == NULL) 395e1051a39Sopenharmony_ci return 0; 396e1051a39Sopenharmony_ci if (!ossl_cms_set1_keyid(&oik->d.subjectKeyIdentifier, originator)) 397e1051a39Sopenharmony_ci return 0; 398e1051a39Sopenharmony_ci } else { 399e1051a39Sopenharmony_ci oik->type = CMS_REK_ISSUER_SERIAL; 400e1051a39Sopenharmony_ci if (!ossl_cms_set1_ias(&oik->d.issuerAndSerialNumber, originator)) 401e1051a39Sopenharmony_ci return 0; 402e1051a39Sopenharmony_ci } 403e1051a39Sopenharmony_ci 404e1051a39Sopenharmony_ci if (!cms_kari_set_originator_private_key(kari, originatorPrivKey)) 405e1051a39Sopenharmony_ci return 0; 406e1051a39Sopenharmony_ci } 407e1051a39Sopenharmony_ci 408e1051a39Sopenharmony_ci EVP_PKEY_up_ref(recipPubKey); 409e1051a39Sopenharmony_ci rek->pkey = recipPubKey; 410e1051a39Sopenharmony_ci return 1; 411e1051a39Sopenharmony_ci} 412e1051a39Sopenharmony_ci 413e1051a39Sopenharmony_cistatic int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari, 414e1051a39Sopenharmony_ci const EVP_CIPHER *cipher) 415e1051a39Sopenharmony_ci{ 416e1051a39Sopenharmony_ci const CMS_CTX *cms_ctx = kari->cms_ctx; 417e1051a39Sopenharmony_ci EVP_CIPHER_CTX *ctx = kari->ctx; 418e1051a39Sopenharmony_ci const EVP_CIPHER *kekcipher; 419e1051a39Sopenharmony_ci EVP_CIPHER *fetched_kekcipher; 420e1051a39Sopenharmony_ci const char *kekcipher_name; 421e1051a39Sopenharmony_ci int keylen; 422e1051a39Sopenharmony_ci int ret; 423e1051a39Sopenharmony_ci 424e1051a39Sopenharmony_ci /* If a suitable wrap algorithm is already set nothing to do */ 425e1051a39Sopenharmony_ci kekcipher = EVP_CIPHER_CTX_get0_cipher(ctx); 426e1051a39Sopenharmony_ci if (kekcipher != NULL) { 427e1051a39Sopenharmony_ci if (EVP_CIPHER_CTX_get_mode(ctx) != EVP_CIPH_WRAP_MODE) 428e1051a39Sopenharmony_ci return 0; 429e1051a39Sopenharmony_ci return 1; 430e1051a39Sopenharmony_ci } 431e1051a39Sopenharmony_ci if (cipher == NULL) 432e1051a39Sopenharmony_ci return 0; 433e1051a39Sopenharmony_ci keylen = EVP_CIPHER_get_key_length(cipher); 434e1051a39Sopenharmony_ci if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_GET_WRAP_CIPHER) != 0) { 435e1051a39Sopenharmony_ci ret = EVP_CIPHER_meth_get_ctrl(cipher)(NULL, EVP_CTRL_GET_WRAP_CIPHER, 436e1051a39Sopenharmony_ci 0, &kekcipher); 437e1051a39Sopenharmony_ci if (ret <= 0) 438e1051a39Sopenharmony_ci return 0; 439e1051a39Sopenharmony_ci 440e1051a39Sopenharmony_ci if (kekcipher != NULL) { 441e1051a39Sopenharmony_ci if (EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE) 442e1051a39Sopenharmony_ci return 0; 443e1051a39Sopenharmony_ci kekcipher_name = EVP_CIPHER_get0_name(kekcipher); 444e1051a39Sopenharmony_ci goto enc; 445e1051a39Sopenharmony_ci } 446e1051a39Sopenharmony_ci } 447e1051a39Sopenharmony_ci 448e1051a39Sopenharmony_ci /* 449e1051a39Sopenharmony_ci * Pick a cipher based on content encryption cipher. If it is DES3 use 450e1051a39Sopenharmony_ci * DES3 wrap otherwise use AES wrap similar to key size. 451e1051a39Sopenharmony_ci */ 452e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DES 453e1051a39Sopenharmony_ci if (EVP_CIPHER_get_type(cipher) == NID_des_ede3_cbc) 454e1051a39Sopenharmony_ci kekcipher_name = SN_id_smime_alg_CMS3DESwrap; 455e1051a39Sopenharmony_ci else 456e1051a39Sopenharmony_ci#endif 457e1051a39Sopenharmony_ci if (keylen <= 16) 458e1051a39Sopenharmony_ci kekcipher_name = SN_id_aes128_wrap; 459e1051a39Sopenharmony_ci else if (keylen <= 24) 460e1051a39Sopenharmony_ci kekcipher_name = SN_id_aes192_wrap; 461e1051a39Sopenharmony_ci else 462e1051a39Sopenharmony_ci kekcipher_name = SN_id_aes256_wrap; 463e1051a39Sopenharmony_cienc: 464e1051a39Sopenharmony_ci fetched_kekcipher = EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(cms_ctx), 465e1051a39Sopenharmony_ci kekcipher_name, 466e1051a39Sopenharmony_ci ossl_cms_ctx_get0_propq(cms_ctx)); 467e1051a39Sopenharmony_ci if (fetched_kekcipher == NULL) 468e1051a39Sopenharmony_ci return 0; 469e1051a39Sopenharmony_ci ret = EVP_EncryptInit_ex(ctx, fetched_kekcipher, NULL, NULL, NULL); 470e1051a39Sopenharmony_ci EVP_CIPHER_free(fetched_kekcipher); 471e1051a39Sopenharmony_ci return ret; 472e1051a39Sopenharmony_ci} 473e1051a39Sopenharmony_ci 474e1051a39Sopenharmony_ci/* Encrypt content key in key agreement recipient info */ 475e1051a39Sopenharmony_ci 476e1051a39Sopenharmony_ciint ossl_cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms, 477e1051a39Sopenharmony_ci CMS_RecipientInfo *ri) 478e1051a39Sopenharmony_ci{ 479e1051a39Sopenharmony_ci CMS_KeyAgreeRecipientInfo *kari; 480e1051a39Sopenharmony_ci CMS_EncryptedContentInfo *ec; 481e1051a39Sopenharmony_ci CMS_RecipientEncryptedKey *rek; 482e1051a39Sopenharmony_ci STACK_OF(CMS_RecipientEncryptedKey) *reks; 483e1051a39Sopenharmony_ci int i; 484e1051a39Sopenharmony_ci 485e1051a39Sopenharmony_ci if (ri->type != CMS_RECIPINFO_AGREE) { 486e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT); 487e1051a39Sopenharmony_ci return 0; 488e1051a39Sopenharmony_ci } 489e1051a39Sopenharmony_ci kari = ri->d.kari; 490e1051a39Sopenharmony_ci reks = kari->recipientEncryptedKeys; 491e1051a39Sopenharmony_ci ec = ossl_cms_get0_env_enc_content(cms); 492e1051a39Sopenharmony_ci /* Initialise wrap algorithm parameters */ 493e1051a39Sopenharmony_ci if (!cms_wrap_init(kari, ec->cipher)) 494e1051a39Sopenharmony_ci return 0; 495e1051a39Sopenharmony_ci /* 496e1051a39Sopenharmony_ci * If no originator key set up initialise for ephemeral key the public key 497e1051a39Sopenharmony_ci * ASN1 structure will set the actual public key value. 498e1051a39Sopenharmony_ci */ 499e1051a39Sopenharmony_ci if (kari->originator->type == -1) { 500e1051a39Sopenharmony_ci CMS_OriginatorIdentifierOrKey *oik = kari->originator; 501e1051a39Sopenharmony_ci oik->type = CMS_OIK_PUBKEY; 502e1051a39Sopenharmony_ci oik->d.originatorKey = M_ASN1_new_of(CMS_OriginatorPublicKey); 503e1051a39Sopenharmony_ci if (!oik->d.originatorKey) 504e1051a39Sopenharmony_ci return 0; 505e1051a39Sopenharmony_ci } 506e1051a39Sopenharmony_ci /* Initialise KDF algorithm */ 507e1051a39Sopenharmony_ci if (!ossl_cms_env_asn1_ctrl(ri, 0)) 508e1051a39Sopenharmony_ci return 0; 509e1051a39Sopenharmony_ci /* For each rek, derive KEK, encrypt CEK */ 510e1051a39Sopenharmony_ci for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) { 511e1051a39Sopenharmony_ci unsigned char *enckey; 512e1051a39Sopenharmony_ci size_t enckeylen; 513e1051a39Sopenharmony_ci rek = sk_CMS_RecipientEncryptedKey_value(reks, i); 514e1051a39Sopenharmony_ci if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0) 515e1051a39Sopenharmony_ci return 0; 516e1051a39Sopenharmony_ci if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen, 517e1051a39Sopenharmony_ci kari, 1)) 518e1051a39Sopenharmony_ci return 0; 519e1051a39Sopenharmony_ci ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen); 520e1051a39Sopenharmony_ci } 521e1051a39Sopenharmony_ci 522e1051a39Sopenharmony_ci return 1; 523e1051a39Sopenharmony_ci} 524