1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2006-2023 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#include <assert.h> 11e1051a39Sopenharmony_ci#include <limits.h> 12e1051a39Sopenharmony_ci#include <openssl/cms.h> 13e1051a39Sopenharmony_ci#include <openssl/err.h> 14e1051a39Sopenharmony_ci#include <openssl/decoder.h> 15e1051a39Sopenharmony_ci#include "internal/sizes.h" 16e1051a39Sopenharmony_ci#include "crypto/evp.h" 17e1051a39Sopenharmony_ci#include "cms_local.h" 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_cistatic EVP_PKEY *pkey_type2param(int ptype, const void *pval, 20e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 21e1051a39Sopenharmony_ci{ 22e1051a39Sopenharmony_ci EVP_PKEY *pkey = NULL; 23e1051a39Sopenharmony_ci EVP_PKEY_CTX *pctx = NULL; 24e1051a39Sopenharmony_ci OSSL_DECODER_CTX *ctx = NULL; 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_ci if (ptype == V_ASN1_SEQUENCE) { 27e1051a39Sopenharmony_ci const ASN1_STRING *pstr = pval; 28e1051a39Sopenharmony_ci const unsigned char *pm = pstr->data; 29e1051a39Sopenharmony_ci size_t pmlen = (size_t)pstr->length; 30e1051a39Sopenharmony_ci int selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS; 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_ci ctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, "EC", 33e1051a39Sopenharmony_ci selection, libctx, propq); 34e1051a39Sopenharmony_ci if (ctx == NULL) 35e1051a39Sopenharmony_ci goto err; 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci if (!OSSL_DECODER_from_data(ctx, &pm, &pmlen)) { 38e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR); 39e1051a39Sopenharmony_ci goto err; 40e1051a39Sopenharmony_ci } 41e1051a39Sopenharmony_ci OSSL_DECODER_CTX_free(ctx); 42e1051a39Sopenharmony_ci return pkey; 43e1051a39Sopenharmony_ci } else if (ptype == V_ASN1_OBJECT) { 44e1051a39Sopenharmony_ci const ASN1_OBJECT *poid = pval; 45e1051a39Sopenharmony_ci char groupname[OSSL_MAX_NAME_SIZE]; 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_ci /* type == V_ASN1_OBJECT => the parameters are given by an asn1 OID */ 48e1051a39Sopenharmony_ci pctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", propq); 49e1051a39Sopenharmony_ci if (pctx == NULL || EVP_PKEY_paramgen_init(pctx) <= 0) 50e1051a39Sopenharmony_ci goto err; 51e1051a39Sopenharmony_ci if (OBJ_obj2txt(groupname, sizeof(groupname), poid, 0) <= 0 52e1051a39Sopenharmony_ci || EVP_PKEY_CTX_set_group_name(pctx, groupname) <= 0) { 53e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR); 54e1051a39Sopenharmony_ci goto err; 55e1051a39Sopenharmony_ci } 56e1051a39Sopenharmony_ci if (EVP_PKEY_paramgen(pctx, &pkey) <= 0) 57e1051a39Sopenharmony_ci goto err; 58e1051a39Sopenharmony_ci EVP_PKEY_CTX_free(pctx); 59e1051a39Sopenharmony_ci return pkey; 60e1051a39Sopenharmony_ci } 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_DECODE_ERROR); 63e1051a39Sopenharmony_ci return NULL; 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_ci err: 66e1051a39Sopenharmony_ci EVP_PKEY_free(pkey); 67e1051a39Sopenharmony_ci EVP_PKEY_CTX_free(pctx); 68e1051a39Sopenharmony_ci OSSL_DECODER_CTX_free(ctx); 69e1051a39Sopenharmony_ci return NULL; 70e1051a39Sopenharmony_ci} 71e1051a39Sopenharmony_ci 72e1051a39Sopenharmony_cistatic int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, 73e1051a39Sopenharmony_ci X509_ALGOR *alg, ASN1_BIT_STRING *pubkey) 74e1051a39Sopenharmony_ci{ 75e1051a39Sopenharmony_ci const ASN1_OBJECT *aoid; 76e1051a39Sopenharmony_ci int atype; 77e1051a39Sopenharmony_ci const void *aval; 78e1051a39Sopenharmony_ci int rv = 0; 79e1051a39Sopenharmony_ci EVP_PKEY *pkpeer = NULL; 80e1051a39Sopenharmony_ci const unsigned char *p; 81e1051a39Sopenharmony_ci int plen; 82e1051a39Sopenharmony_ci 83e1051a39Sopenharmony_ci X509_ALGOR_get0(&aoid, &atype, &aval, alg); 84e1051a39Sopenharmony_ci if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey) 85e1051a39Sopenharmony_ci goto err; 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci /* If absent parameters get group from main key */ 88e1051a39Sopenharmony_ci if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) { 89e1051a39Sopenharmony_ci EVP_PKEY *pk; 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci pk = EVP_PKEY_CTX_get0_pkey(pctx); 92e1051a39Sopenharmony_ci if (pk == NULL) 93e1051a39Sopenharmony_ci goto err; 94e1051a39Sopenharmony_ci 95e1051a39Sopenharmony_ci pkpeer = EVP_PKEY_new(); 96e1051a39Sopenharmony_ci if (pkpeer == NULL) 97e1051a39Sopenharmony_ci goto err; 98e1051a39Sopenharmony_ci if (!EVP_PKEY_copy_parameters(pkpeer, pk)) 99e1051a39Sopenharmony_ci goto err; 100e1051a39Sopenharmony_ci } else { 101e1051a39Sopenharmony_ci pkpeer = pkey_type2param(atype, aval, 102e1051a39Sopenharmony_ci EVP_PKEY_CTX_get0_libctx(pctx), 103e1051a39Sopenharmony_ci EVP_PKEY_CTX_get0_propq(pctx)); 104e1051a39Sopenharmony_ci if (pkpeer == NULL) 105e1051a39Sopenharmony_ci goto err; 106e1051a39Sopenharmony_ci } 107e1051a39Sopenharmony_ci /* We have parameters now set public key */ 108e1051a39Sopenharmony_ci plen = ASN1_STRING_length(pubkey); 109e1051a39Sopenharmony_ci p = ASN1_STRING_get0_data(pubkey); 110e1051a39Sopenharmony_ci if (p == NULL || plen == 0) 111e1051a39Sopenharmony_ci goto err; 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ci if (!EVP_PKEY_set1_encoded_public_key(pkpeer, p, plen)) 114e1051a39Sopenharmony_ci goto err; 115e1051a39Sopenharmony_ci 116e1051a39Sopenharmony_ci if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) 117e1051a39Sopenharmony_ci rv = 1; 118e1051a39Sopenharmony_ci err: 119e1051a39Sopenharmony_ci EVP_PKEY_free(pkpeer); 120e1051a39Sopenharmony_ci return rv; 121e1051a39Sopenharmony_ci} 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci/* Set KDF parameters based on KDF NID */ 124e1051a39Sopenharmony_cistatic int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid) 125e1051a39Sopenharmony_ci{ 126e1051a39Sopenharmony_ci int kdf_nid, kdfmd_nid, cofactor; 127e1051a39Sopenharmony_ci const EVP_MD *kdf_md; 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ci if (eckdf_nid == NID_undef) 130e1051a39Sopenharmony_ci return 0; 131e1051a39Sopenharmony_ci 132e1051a39Sopenharmony_ci /* Lookup KDF type, cofactor mode and digest */ 133e1051a39Sopenharmony_ci if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid)) 134e1051a39Sopenharmony_ci return 0; 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci if (kdf_nid == NID_dh_std_kdf) 137e1051a39Sopenharmony_ci cofactor = 0; 138e1051a39Sopenharmony_ci else if (kdf_nid == NID_dh_cofactor_kdf) 139e1051a39Sopenharmony_ci cofactor = 1; 140e1051a39Sopenharmony_ci else 141e1051a39Sopenharmony_ci return 0; 142e1051a39Sopenharmony_ci 143e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0) 144e1051a39Sopenharmony_ci return 0; 145e1051a39Sopenharmony_ci 146e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0) 147e1051a39Sopenharmony_ci return 0; 148e1051a39Sopenharmony_ci 149e1051a39Sopenharmony_ci kdf_md = EVP_get_digestbynid(kdfmd_nid); 150e1051a39Sopenharmony_ci if (!kdf_md) 151e1051a39Sopenharmony_ci return 0; 152e1051a39Sopenharmony_ci 153e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) 154e1051a39Sopenharmony_ci return 0; 155e1051a39Sopenharmony_ci return 1; 156e1051a39Sopenharmony_ci} 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_cistatic int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) 159e1051a39Sopenharmony_ci{ 160e1051a39Sopenharmony_ci int rv = 0; 161e1051a39Sopenharmony_ci X509_ALGOR *alg, *kekalg = NULL; 162e1051a39Sopenharmony_ci ASN1_OCTET_STRING *ukm; 163e1051a39Sopenharmony_ci const unsigned char *p; 164e1051a39Sopenharmony_ci unsigned char *der = NULL; 165e1051a39Sopenharmony_ci int plen, keylen; 166e1051a39Sopenharmony_ci EVP_CIPHER *kekcipher = NULL; 167e1051a39Sopenharmony_ci EVP_CIPHER_CTX *kekctx; 168e1051a39Sopenharmony_ci char name[OSSL_MAX_NAME_SIZE]; 169e1051a39Sopenharmony_ci 170e1051a39Sopenharmony_ci if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm)) 171e1051a39Sopenharmony_ci return 0; 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) { 174e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR); 175e1051a39Sopenharmony_ci return 0; 176e1051a39Sopenharmony_ci } 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ci if (alg->parameter->type != V_ASN1_SEQUENCE) 179e1051a39Sopenharmony_ci return 0; 180e1051a39Sopenharmony_ci 181e1051a39Sopenharmony_ci p = alg->parameter->value.sequence->data; 182e1051a39Sopenharmony_ci plen = alg->parameter->value.sequence->length; 183e1051a39Sopenharmony_ci kekalg = d2i_X509_ALGOR(NULL, &p, plen); 184e1051a39Sopenharmony_ci if (kekalg == NULL) 185e1051a39Sopenharmony_ci goto err; 186e1051a39Sopenharmony_ci kekctx = CMS_RecipientInfo_kari_get0_ctx(ri); 187e1051a39Sopenharmony_ci if (kekctx == NULL) 188e1051a39Sopenharmony_ci goto err; 189e1051a39Sopenharmony_ci OBJ_obj2txt(name, sizeof(name), kekalg->algorithm, 0); 190e1051a39Sopenharmony_ci kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, pctx->propquery); 191e1051a39Sopenharmony_ci if (kekcipher == NULL || EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE) 192e1051a39Sopenharmony_ci goto err; 193e1051a39Sopenharmony_ci if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL)) 194e1051a39Sopenharmony_ci goto err; 195e1051a39Sopenharmony_ci if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) 196e1051a39Sopenharmony_ci goto err; 197e1051a39Sopenharmony_ci 198e1051a39Sopenharmony_ci keylen = EVP_CIPHER_CTX_get_key_length(kekctx); 199e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) 200e1051a39Sopenharmony_ci goto err; 201e1051a39Sopenharmony_ci 202e1051a39Sopenharmony_ci plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen); 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ci if (plen <= 0) 205e1051a39Sopenharmony_ci goto err; 206e1051a39Sopenharmony_ci 207e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0) 208e1051a39Sopenharmony_ci goto err; 209e1051a39Sopenharmony_ci der = NULL; 210e1051a39Sopenharmony_ci 211e1051a39Sopenharmony_ci rv = 1; 212e1051a39Sopenharmony_ci err: 213e1051a39Sopenharmony_ci EVP_CIPHER_free(kekcipher); 214e1051a39Sopenharmony_ci X509_ALGOR_free(kekalg); 215e1051a39Sopenharmony_ci OPENSSL_free(der); 216e1051a39Sopenharmony_ci return rv; 217e1051a39Sopenharmony_ci} 218e1051a39Sopenharmony_ci 219e1051a39Sopenharmony_cistatic int ecdh_cms_decrypt(CMS_RecipientInfo *ri) 220e1051a39Sopenharmony_ci{ 221e1051a39Sopenharmony_ci EVP_PKEY_CTX *pctx; 222e1051a39Sopenharmony_ci 223e1051a39Sopenharmony_ci pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); 224e1051a39Sopenharmony_ci if (pctx == NULL) 225e1051a39Sopenharmony_ci return 0; 226e1051a39Sopenharmony_ci /* See if we need to set peer key */ 227e1051a39Sopenharmony_ci if (!EVP_PKEY_CTX_get0_peerkey(pctx)) { 228e1051a39Sopenharmony_ci X509_ALGOR *alg; 229e1051a39Sopenharmony_ci ASN1_BIT_STRING *pubkey; 230e1051a39Sopenharmony_ci 231e1051a39Sopenharmony_ci if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey, 232e1051a39Sopenharmony_ci NULL, NULL, NULL)) 233e1051a39Sopenharmony_ci return 0; 234e1051a39Sopenharmony_ci if (alg == NULL || pubkey == NULL) 235e1051a39Sopenharmony_ci return 0; 236e1051a39Sopenharmony_ci if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) { 237e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_PEER_KEY_ERROR); 238e1051a39Sopenharmony_ci return 0; 239e1051a39Sopenharmony_ci } 240e1051a39Sopenharmony_ci } 241e1051a39Sopenharmony_ci /* Set ECDH derivation parameters and initialise unwrap context */ 242e1051a39Sopenharmony_ci if (!ecdh_cms_set_shared_info(pctx, ri)) { 243e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_SHARED_INFO_ERROR); 244e1051a39Sopenharmony_ci return 0; 245e1051a39Sopenharmony_ci } 246e1051a39Sopenharmony_ci return 1; 247e1051a39Sopenharmony_ci} 248e1051a39Sopenharmony_ci 249e1051a39Sopenharmony_cistatic int ecdh_cms_encrypt(CMS_RecipientInfo *ri) 250e1051a39Sopenharmony_ci{ 251e1051a39Sopenharmony_ci EVP_PKEY_CTX *pctx; 252e1051a39Sopenharmony_ci EVP_PKEY *pkey; 253e1051a39Sopenharmony_ci EVP_CIPHER_CTX *ctx; 254e1051a39Sopenharmony_ci int keylen; 255e1051a39Sopenharmony_ci X509_ALGOR *talg, *wrap_alg = NULL; 256e1051a39Sopenharmony_ci const ASN1_OBJECT *aoid; 257e1051a39Sopenharmony_ci ASN1_BIT_STRING *pubkey; 258e1051a39Sopenharmony_ci ASN1_STRING *wrap_str; 259e1051a39Sopenharmony_ci ASN1_OCTET_STRING *ukm; 260e1051a39Sopenharmony_ci unsigned char *penc = NULL; 261e1051a39Sopenharmony_ci int penclen; 262e1051a39Sopenharmony_ci int rv = 0; 263e1051a39Sopenharmony_ci int ecdh_nid, kdf_type, kdf_nid, wrap_nid; 264e1051a39Sopenharmony_ci const EVP_MD *kdf_md; 265e1051a39Sopenharmony_ci 266e1051a39Sopenharmony_ci pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); 267e1051a39Sopenharmony_ci if (pctx == NULL) 268e1051a39Sopenharmony_ci return 0; 269e1051a39Sopenharmony_ci /* Get ephemeral key */ 270e1051a39Sopenharmony_ci pkey = EVP_PKEY_CTX_get0_pkey(pctx); 271e1051a39Sopenharmony_ci if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, 272e1051a39Sopenharmony_ci NULL, NULL, NULL)) 273e1051a39Sopenharmony_ci goto err; 274e1051a39Sopenharmony_ci X509_ALGOR_get0(&aoid, NULL, NULL, talg); 275e1051a39Sopenharmony_ci /* Is everything uninitialised? */ 276e1051a39Sopenharmony_ci if (aoid == OBJ_nid2obj(NID_undef)) { 277e1051a39Sopenharmony_ci /* Set the key */ 278e1051a39Sopenharmony_ci size_t enckeylen; 279e1051a39Sopenharmony_ci 280e1051a39Sopenharmony_ci enckeylen = EVP_PKEY_get1_encoded_public_key(pkey, &penc); 281e1051a39Sopenharmony_ci if (enckeylen > INT_MAX || enckeylen == 0) 282e1051a39Sopenharmony_ci goto err; 283e1051a39Sopenharmony_ci ASN1_STRING_set0(pubkey, penc, (int)enckeylen); 284e1051a39Sopenharmony_ci pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); 285e1051a39Sopenharmony_ci pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT; 286e1051a39Sopenharmony_ci 287e1051a39Sopenharmony_ci penc = NULL; 288e1051a39Sopenharmony_ci (void)X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 289e1051a39Sopenharmony_ci V_ASN1_UNDEF, NULL); /* cannot fail */ 290e1051a39Sopenharmony_ci } 291e1051a39Sopenharmony_ci 292e1051a39Sopenharmony_ci /* See if custom parameters set */ 293e1051a39Sopenharmony_ci kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx); 294e1051a39Sopenharmony_ci if (kdf_type <= 0) 295e1051a39Sopenharmony_ci goto err; 296e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md) <= 0) 297e1051a39Sopenharmony_ci goto err; 298e1051a39Sopenharmony_ci ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx); 299e1051a39Sopenharmony_ci if (ecdh_nid < 0) 300e1051a39Sopenharmony_ci goto err; 301e1051a39Sopenharmony_ci else if (ecdh_nid == 0) 302e1051a39Sopenharmony_ci ecdh_nid = NID_dh_std_kdf; 303e1051a39Sopenharmony_ci else if (ecdh_nid == 1) 304e1051a39Sopenharmony_ci ecdh_nid = NID_dh_cofactor_kdf; 305e1051a39Sopenharmony_ci 306e1051a39Sopenharmony_ci if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) { 307e1051a39Sopenharmony_ci kdf_type = EVP_PKEY_ECDH_KDF_X9_63; 308e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0) 309e1051a39Sopenharmony_ci goto err; 310e1051a39Sopenharmony_ci } else 311e1051a39Sopenharmony_ci /* Unknown KDF */ 312e1051a39Sopenharmony_ci goto err; 313e1051a39Sopenharmony_ci if (kdf_md == NULL) { 314e1051a39Sopenharmony_ci /* Fixme later for better MD */ 315e1051a39Sopenharmony_ci kdf_md = EVP_sha1(); 316e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) 317e1051a39Sopenharmony_ci goto err; 318e1051a39Sopenharmony_ci } 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_ci if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) 321e1051a39Sopenharmony_ci goto err; 322e1051a39Sopenharmony_ci 323e1051a39Sopenharmony_ci /* Lookup NID for KDF+cofactor+digest */ 324e1051a39Sopenharmony_ci 325e1051a39Sopenharmony_ci if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_get_type(kdf_md), ecdh_nid)) 326e1051a39Sopenharmony_ci goto err; 327e1051a39Sopenharmony_ci /* Get wrap NID */ 328e1051a39Sopenharmony_ci ctx = CMS_RecipientInfo_kari_get0_ctx(ri); 329e1051a39Sopenharmony_ci wrap_nid = EVP_CIPHER_CTX_get_type(ctx); 330e1051a39Sopenharmony_ci keylen = EVP_CIPHER_CTX_get_key_length(ctx); 331e1051a39Sopenharmony_ci 332e1051a39Sopenharmony_ci /* Package wrap algorithm in an AlgorithmIdentifier */ 333e1051a39Sopenharmony_ci 334e1051a39Sopenharmony_ci wrap_alg = X509_ALGOR_new(); 335e1051a39Sopenharmony_ci if (wrap_alg == NULL) 336e1051a39Sopenharmony_ci goto err; 337e1051a39Sopenharmony_ci wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); 338e1051a39Sopenharmony_ci wrap_alg->parameter = ASN1_TYPE_new(); 339e1051a39Sopenharmony_ci if (wrap_alg->parameter == NULL) 340e1051a39Sopenharmony_ci goto err; 341e1051a39Sopenharmony_ci if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) 342e1051a39Sopenharmony_ci goto err; 343e1051a39Sopenharmony_ci if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) { 344e1051a39Sopenharmony_ci ASN1_TYPE_free(wrap_alg->parameter); 345e1051a39Sopenharmony_ci wrap_alg->parameter = NULL; 346e1051a39Sopenharmony_ci } 347e1051a39Sopenharmony_ci 348e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) 349e1051a39Sopenharmony_ci goto err; 350e1051a39Sopenharmony_ci 351e1051a39Sopenharmony_ci penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen); 352e1051a39Sopenharmony_ci 353e1051a39Sopenharmony_ci if (penclen <= 0) 354e1051a39Sopenharmony_ci goto err; 355e1051a39Sopenharmony_ci 356e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0) 357e1051a39Sopenharmony_ci goto err; 358e1051a39Sopenharmony_ci penc = NULL; 359e1051a39Sopenharmony_ci 360e1051a39Sopenharmony_ci /* 361e1051a39Sopenharmony_ci * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter 362e1051a39Sopenharmony_ci * of another AlgorithmIdentifier. 363e1051a39Sopenharmony_ci */ 364e1051a39Sopenharmony_ci penclen = i2d_X509_ALGOR(wrap_alg, &penc); 365e1051a39Sopenharmony_ci if (penclen <= 0) 366e1051a39Sopenharmony_ci goto err; 367e1051a39Sopenharmony_ci wrap_str = ASN1_STRING_new(); 368e1051a39Sopenharmony_ci if (wrap_str == NULL) 369e1051a39Sopenharmony_ci goto err; 370e1051a39Sopenharmony_ci ASN1_STRING_set0(wrap_str, penc, penclen); 371e1051a39Sopenharmony_ci penc = NULL; 372e1051a39Sopenharmony_ci X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str); 373e1051a39Sopenharmony_ci 374e1051a39Sopenharmony_ci rv = 1; 375e1051a39Sopenharmony_ci 376e1051a39Sopenharmony_ci err: 377e1051a39Sopenharmony_ci OPENSSL_free(penc); 378e1051a39Sopenharmony_ci X509_ALGOR_free(wrap_alg); 379e1051a39Sopenharmony_ci return rv; 380e1051a39Sopenharmony_ci} 381e1051a39Sopenharmony_ci 382e1051a39Sopenharmony_ciint ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt) 383e1051a39Sopenharmony_ci{ 384e1051a39Sopenharmony_ci assert(decrypt == 0 || decrypt == 1); 385e1051a39Sopenharmony_ci 386e1051a39Sopenharmony_ci if (decrypt == 1) 387e1051a39Sopenharmony_ci return ecdh_cms_decrypt(ri); 388e1051a39Sopenharmony_ci 389e1051a39Sopenharmony_ci if (decrypt == 0) 390e1051a39Sopenharmony_ci return ecdh_cms_encrypt(ri); 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); 393e1051a39Sopenharmony_ci return 0; 394e1051a39Sopenharmony_ci} 395e1051a39Sopenharmony_ci 396e1051a39Sopenharmony_ci/* ECDSA and DSA implementation is the same */ 397e1051a39Sopenharmony_ciint ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify) 398e1051a39Sopenharmony_ci{ 399e1051a39Sopenharmony_ci assert(verify == 0 || verify == 1); 400e1051a39Sopenharmony_ci 401e1051a39Sopenharmony_ci if (verify == 0) { 402e1051a39Sopenharmony_ci int snid, hnid; 403e1051a39Sopenharmony_ci X509_ALGOR *alg1, *alg2; 404e1051a39Sopenharmony_ci EVP_PKEY *pkey = si->pkey; 405e1051a39Sopenharmony_ci 406e1051a39Sopenharmony_ci CMS_SignerInfo_get0_algs(si, NULL, NULL, &alg1, &alg2); 407e1051a39Sopenharmony_ci if (alg1 == NULL || alg1->algorithm == NULL) 408e1051a39Sopenharmony_ci return -1; 409e1051a39Sopenharmony_ci hnid = OBJ_obj2nid(alg1->algorithm); 410e1051a39Sopenharmony_ci if (hnid == NID_undef) 411e1051a39Sopenharmony_ci return -1; 412e1051a39Sopenharmony_ci if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_get_id(pkey))) 413e1051a39Sopenharmony_ci return -1; 414e1051a39Sopenharmony_ci X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); 415e1051a39Sopenharmony_ci } 416e1051a39Sopenharmony_ci return 1; 417e1051a39Sopenharmony_ci} 418