1238384Sjkim/* crypto/cms/cms_pwri.c */ 2238384Sjkim/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3238384Sjkim * project. 4238384Sjkim */ 5238384Sjkim/* ==================================================================== 6238384Sjkim * Copyright (c) 2009 The OpenSSL Project. All rights reserved. 7238384Sjkim * 8238384Sjkim * Redistribution and use in source and binary forms, with or without 9238384Sjkim * modification, are permitted provided that the following conditions 10238384Sjkim * are met: 11238384Sjkim * 12238384Sjkim * 1. Redistributions of source code must retain the above copyright 13238384Sjkim * notice, this list of conditions and the following disclaimer. 14238384Sjkim * 15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 16238384Sjkim * notice, this list of conditions and the following disclaimer in 17238384Sjkim * the documentation and/or other materials provided with the 18238384Sjkim * distribution. 19238384Sjkim * 20238384Sjkim * 3. All advertising materials mentioning features or use of this 21238384Sjkim * software must display the following acknowledgment: 22238384Sjkim * "This product includes software developed by the OpenSSL Project 23238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24238384Sjkim * 25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26238384Sjkim * endorse or promote products derived from this software without 27238384Sjkim * prior written permission. For written permission, please contact 28238384Sjkim * licensing@OpenSSL.org. 29238384Sjkim * 30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 31238384Sjkim * nor may "OpenSSL" appear in their names without prior written 32238384Sjkim * permission of the OpenSSL Project. 33238384Sjkim * 34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 35238384Sjkim * acknowledgment: 36238384Sjkim * "This product includes software developed by the OpenSSL Project 37238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38238384Sjkim * 39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 51238384Sjkim * ==================================================================== 52238384Sjkim */ 53238384Sjkim 54238384Sjkim#include "cryptlib.h" 55238384Sjkim#include <openssl/asn1t.h> 56238384Sjkim#include <openssl/pem.h> 57238384Sjkim#include <openssl/x509v3.h> 58238384Sjkim#include <openssl/err.h> 59238384Sjkim#include <openssl/cms.h> 60238384Sjkim#include <openssl/rand.h> 61238384Sjkim#include <openssl/aes.h> 62238384Sjkim#include "cms_lcl.h" 63238384Sjkim#include "asn1_locl.h" 64238384Sjkim 65238384Sjkimint CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, 66238384Sjkim unsigned char *pass, ossl_ssize_t passlen) 67238384Sjkim { 68238384Sjkim CMS_PasswordRecipientInfo *pwri; 69238384Sjkim if (ri->type != CMS_RECIPINFO_PASS) 70238384Sjkim { 71238384Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI); 72238384Sjkim return 0; 73238384Sjkim } 74238384Sjkim 75238384Sjkim pwri = ri->d.pwri; 76238384Sjkim pwri->pass = pass; 77238384Sjkim if (pass && passlen < 0) 78238384Sjkim passlen = strlen((char *)pass); 79238384Sjkim pwri->passlen = passlen; 80238384Sjkim return 1; 81238384Sjkim } 82238384Sjkim 83238384SjkimCMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, 84238384Sjkim int iter, int wrap_nid, int pbe_nid, 85238384Sjkim unsigned char *pass, 86238384Sjkim ossl_ssize_t passlen, 87238384Sjkim const EVP_CIPHER *kekciph) 88238384Sjkim { 89238384Sjkim CMS_RecipientInfo *ri = NULL; 90238384Sjkim CMS_EnvelopedData *env; 91238384Sjkim CMS_PasswordRecipientInfo *pwri; 92238384Sjkim EVP_CIPHER_CTX ctx; 93238384Sjkim X509_ALGOR *encalg = NULL; 94238384Sjkim unsigned char iv[EVP_MAX_IV_LENGTH]; 95238384Sjkim int ivlen; 96279264Sdelphij 97238384Sjkim env = cms_get0_enveloped(cms); 98238384Sjkim if (!env) 99279264Sdelphij return NULL; 100238384Sjkim 101238384Sjkim if (wrap_nid <= 0) 102238384Sjkim wrap_nid = NID_id_alg_PWRI_KEK; 103238384Sjkim 104238384Sjkim if (pbe_nid <= 0) 105238384Sjkim pbe_nid = NID_id_pbkdf2; 106238384Sjkim 107238384Sjkim /* Get from enveloped data */ 108238384Sjkim if (kekciph == NULL) 109238384Sjkim kekciph = env->encryptedContentInfo->cipher; 110238384Sjkim 111238384Sjkim if (kekciph == NULL) 112238384Sjkim { 113238384Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER); 114238384Sjkim return NULL; 115238384Sjkim } 116238384Sjkim if (wrap_nid != NID_id_alg_PWRI_KEK) 117238384Sjkim { 118238384Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, 119238384Sjkim CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); 120238384Sjkim return NULL; 121238384Sjkim } 122238384Sjkim 123238384Sjkim /* Setup algorithm identifier for cipher */ 124238384Sjkim encalg = X509_ALGOR_new(); 125238384Sjkim EVP_CIPHER_CTX_init(&ctx); 126238384Sjkim 127238384Sjkim if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0) 128238384Sjkim { 129238384Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB); 130238384Sjkim goto err; 131238384Sjkim } 132238384Sjkim 133238384Sjkim ivlen = EVP_CIPHER_CTX_iv_length(&ctx); 134238384Sjkim 135238384Sjkim if (ivlen > 0) 136238384Sjkim { 137238384Sjkim if (RAND_pseudo_bytes(iv, ivlen) <= 0) 138238384Sjkim goto err; 139238384Sjkim if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0) 140238384Sjkim { 141238384Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, 142238384Sjkim ERR_R_EVP_LIB); 143238384Sjkim goto err; 144238384Sjkim } 145238384Sjkim encalg->parameter = ASN1_TYPE_new(); 146238384Sjkim if (!encalg->parameter) 147238384Sjkim { 148238384Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, 149238384Sjkim ERR_R_MALLOC_FAILURE); 150238384Sjkim goto err; 151238384Sjkim } 152238384Sjkim if (EVP_CIPHER_param_to_asn1(&ctx, encalg->parameter) <= 0) 153238384Sjkim { 154238384Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, 155238384Sjkim CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 156238384Sjkim goto err; 157238384Sjkim } 158238384Sjkim } 159238384Sjkim 160238384Sjkim 161238384Sjkim encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(&ctx)); 162238384Sjkim 163238384Sjkim EVP_CIPHER_CTX_cleanup(&ctx); 164238384Sjkim 165238384Sjkim /* Initialize recipient info */ 166238384Sjkim ri = M_ASN1_new_of(CMS_RecipientInfo); 167238384Sjkim if (!ri) 168238384Sjkim goto merr; 169238384Sjkim 170238384Sjkim ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo); 171238384Sjkim if (!ri->d.pwri) 172238384Sjkim goto merr; 173238384Sjkim ri->type = CMS_RECIPINFO_PASS; 174238384Sjkim 175238384Sjkim pwri = ri->d.pwri; 176238384Sjkim /* Since this is overwritten, free up empty structure already there */ 177238384Sjkim X509_ALGOR_free(pwri->keyEncryptionAlgorithm); 178238384Sjkim pwri->keyEncryptionAlgorithm = X509_ALGOR_new(); 179238384Sjkim if (!pwri->keyEncryptionAlgorithm) 180238384Sjkim goto merr; 181238384Sjkim pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid); 182238384Sjkim pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new(); 183238384Sjkim if (!pwri->keyEncryptionAlgorithm->parameter) 184238384Sjkim goto merr; 185238384Sjkim 186238384Sjkim if(!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR), 187238384Sjkim &pwri->keyEncryptionAlgorithm->parameter->value.sequence)) 188238384Sjkim goto merr; 189238384Sjkim pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE; 190238384Sjkim 191238384Sjkim X509_ALGOR_free(encalg); 192238384Sjkim encalg = NULL; 193238384Sjkim 194238384Sjkim /* Setup PBE algorithm */ 195238384Sjkim 196238384Sjkim pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1); 197238384Sjkim 198238384Sjkim if (!pwri->keyDerivationAlgorithm) 199238384Sjkim goto err; 200238384Sjkim 201238384Sjkim CMS_RecipientInfo_set0_password(ri, pass, passlen); 202238384Sjkim pwri->version = 0; 203238384Sjkim 204238384Sjkim if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) 205238384Sjkim goto merr; 206238384Sjkim 207238384Sjkim return ri; 208238384Sjkim 209238384Sjkim merr: 210238384Sjkim CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE); 211238384Sjkim err: 212238384Sjkim EVP_CIPHER_CTX_cleanup(&ctx); 213238384Sjkim if (ri) 214238384Sjkim M_ASN1_free_of(ri, CMS_RecipientInfo); 215238384Sjkim if (encalg) 216238384Sjkim X509_ALGOR_free(encalg); 217238384Sjkim return NULL; 218238384Sjkim 219238384Sjkim } 220238384Sjkim 221238384Sjkim/* This is an implementation of the key wrapping mechanism in RFC3211, 222238384Sjkim * at some point this should go into EVP. 223238384Sjkim */ 224238384Sjkim 225238384Sjkimstatic int kek_unwrap_key(unsigned char *out, size_t *outlen, 226238384Sjkim const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx) 227238384Sjkim { 228238384Sjkim size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); 229238384Sjkim unsigned char *tmp; 230238384Sjkim int outl, rv = 0; 231238384Sjkim if (inlen < 2 * blocklen) 232238384Sjkim { 233238384Sjkim /* too small */ 234238384Sjkim return 0; 235238384Sjkim } 236238384Sjkim if (inlen % blocklen) 237238384Sjkim { 238238384Sjkim /* Invalid size */ 239238384Sjkim return 0; 240238384Sjkim } 241238384Sjkim tmp = OPENSSL_malloc(inlen); 242238384Sjkim /* setup IV by decrypting last two blocks */ 243238384Sjkim EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl, 244238384Sjkim in + inlen - 2 * blocklen, blocklen * 2); 245238384Sjkim /* Do a decrypt of last decrypted block to set IV to correct value 246238384Sjkim * output it to start of buffer so we don't corrupt decrypted block 247238384Sjkim * this works because buffer is at least two block lengths long. 248238384Sjkim */ 249238384Sjkim EVP_DecryptUpdate(ctx, tmp, &outl, 250238384Sjkim tmp + inlen - blocklen, blocklen); 251238384Sjkim /* Can now decrypt first n - 1 blocks */ 252238384Sjkim EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen); 253238384Sjkim 254238384Sjkim /* Reset IV to original value */ 255238384Sjkim EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL); 256238384Sjkim /* Decrypt again */ 257238384Sjkim EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen); 258238384Sjkim /* Check check bytes */ 259238384Sjkim if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff) 260238384Sjkim { 261238384Sjkim /* Check byte failure */ 262238384Sjkim goto err; 263238384Sjkim } 264238384Sjkim if (inlen < (size_t)(tmp[0] - 4 )) 265238384Sjkim { 266238384Sjkim /* Invalid length value */ 267238384Sjkim goto err; 268238384Sjkim } 269238384Sjkim *outlen = (size_t)tmp[0]; 270238384Sjkim memcpy(out, tmp + 4, *outlen); 271238384Sjkim rv = 1; 272238384Sjkim err: 273238384Sjkim OPENSSL_cleanse(tmp, inlen); 274238384Sjkim OPENSSL_free(tmp); 275238384Sjkim return rv; 276238384Sjkim 277238384Sjkim } 278238384Sjkim 279238384Sjkimstatic int kek_wrap_key(unsigned char *out, size_t *outlen, 280238384Sjkim const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx) 281238384Sjkim { 282238384Sjkim size_t blocklen = EVP_CIPHER_CTX_block_size(ctx); 283238384Sjkim size_t olen; 284238384Sjkim int dummy; 285238384Sjkim /* First decide length of output buffer: need header and round up to 286238384Sjkim * multiple of block length. 287238384Sjkim */ 288238384Sjkim olen = (inlen + 4 + blocklen - 1)/blocklen; 289238384Sjkim olen *= blocklen; 290238384Sjkim if (olen < 2 * blocklen) 291238384Sjkim { 292238384Sjkim /* Key too small */ 293238384Sjkim return 0; 294238384Sjkim } 295238384Sjkim if (inlen > 0xFF) 296238384Sjkim { 297238384Sjkim /* Key too large */ 298238384Sjkim return 0; 299238384Sjkim } 300238384Sjkim if (out) 301238384Sjkim { 302238384Sjkim /* Set header */ 303238384Sjkim out[0] = (unsigned char)inlen; 304238384Sjkim out[1] = in[0] ^ 0xFF; 305238384Sjkim out[2] = in[1] ^ 0xFF; 306238384Sjkim out[3] = in[2] ^ 0xFF; 307238384Sjkim memcpy(out + 4, in, inlen); 308238384Sjkim /* Add random padding to end */ 309238384Sjkim if (olen > inlen + 4) 310238384Sjkim RAND_pseudo_bytes(out + 4 + inlen, olen - 4 - inlen); 311238384Sjkim /* Encrypt twice */ 312238384Sjkim EVP_EncryptUpdate(ctx, out, &dummy, out, olen); 313238384Sjkim EVP_EncryptUpdate(ctx, out, &dummy, out, olen); 314238384Sjkim } 315238384Sjkim 316238384Sjkim *outlen = olen; 317238384Sjkim 318238384Sjkim return 1; 319238384Sjkim } 320238384Sjkim 321238384Sjkim/* Encrypt/Decrypt content key in PWRI recipient info */ 322238384Sjkim 323238384Sjkimint cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, 324238384Sjkim int en_de) 325238384Sjkim { 326238384Sjkim CMS_EncryptedContentInfo *ec; 327238384Sjkim CMS_PasswordRecipientInfo *pwri; 328238384Sjkim const unsigned char *p = NULL; 329238384Sjkim int plen; 330238384Sjkim int r = 0; 331238384Sjkim X509_ALGOR *algtmp, *kekalg = NULL; 332238384Sjkim EVP_CIPHER_CTX kekctx; 333238384Sjkim const EVP_CIPHER *kekcipher; 334238384Sjkim unsigned char *key = NULL; 335238384Sjkim size_t keylen; 336238384Sjkim 337238384Sjkim ec = cms->d.envelopedData->encryptedContentInfo; 338238384Sjkim 339238384Sjkim pwri = ri->d.pwri; 340238384Sjkim EVP_CIPHER_CTX_init(&kekctx); 341238384Sjkim 342238384Sjkim if (!pwri->pass) 343238384Sjkim { 344238384Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD); 345238384Sjkim return 0; 346238384Sjkim } 347238384Sjkim algtmp = pwri->keyEncryptionAlgorithm; 348238384Sjkim 349238384Sjkim if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) 350238384Sjkim { 351238384Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 352238384Sjkim CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); 353238384Sjkim return 0; 354238384Sjkim } 355238384Sjkim 356238384Sjkim if (algtmp->parameter->type == V_ASN1_SEQUENCE) 357238384Sjkim { 358238384Sjkim p = algtmp->parameter->value.sequence->data; 359238384Sjkim plen = algtmp->parameter->value.sequence->length; 360238384Sjkim kekalg = d2i_X509_ALGOR(NULL, &p, plen); 361238384Sjkim } 362238384Sjkim if (kekalg == NULL) 363238384Sjkim { 364238384Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 365238384Sjkim CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER); 366238384Sjkim return 0; 367238384Sjkim } 368238384Sjkim 369238384Sjkim kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); 370238384Sjkim 371238384Sjkim if(!kekcipher) 372238384Sjkim { 373238384Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 374238384Sjkim CMS_R_UNKNOWN_CIPHER); 375238384Sjkim goto err; 376238384Sjkim } 377238384Sjkim 378238384Sjkim /* Fixup cipher based on AlgorithmIdentifier to set IV etc */ 379238384Sjkim if (!EVP_CipherInit_ex(&kekctx, kekcipher, NULL, NULL, NULL, en_de)) 380238384Sjkim goto err; 381238384Sjkim EVP_CIPHER_CTX_set_padding(&kekctx, 0); 382238384Sjkim if(EVP_CIPHER_asn1_to_param(&kekctx, kekalg->parameter) < 0) 383238384Sjkim { 384238384Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 385238384Sjkim CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 386238384Sjkim goto err; 387238384Sjkim } 388238384Sjkim 389238384Sjkim algtmp = pwri->keyDerivationAlgorithm; 390238384Sjkim 391238384Sjkim /* Finish password based key derivation to setup key in "ctx" */ 392238384Sjkim 393238384Sjkim if (EVP_PBE_CipherInit(algtmp->algorithm, 394238384Sjkim (char *)pwri->pass, pwri->passlen, 395238384Sjkim algtmp->parameter, &kekctx, en_de) < 0) 396238384Sjkim { 397238384Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB); 398238384Sjkim goto err; 399238384Sjkim } 400238384Sjkim 401238384Sjkim /* Finally wrap/unwrap the key */ 402238384Sjkim 403238384Sjkim if (en_de) 404238384Sjkim { 405238384Sjkim 406238384Sjkim if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, &kekctx)) 407238384Sjkim goto err; 408238384Sjkim 409238384Sjkim key = OPENSSL_malloc(keylen); 410238384Sjkim 411238384Sjkim if (!key) 412238384Sjkim goto err; 413238384Sjkim 414238384Sjkim if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, &kekctx)) 415238384Sjkim goto err; 416238384Sjkim pwri->encryptedKey->data = key; 417238384Sjkim pwri->encryptedKey->length = keylen; 418238384Sjkim } 419238384Sjkim else 420238384Sjkim { 421238384Sjkim key = OPENSSL_malloc(pwri->encryptedKey->length); 422238384Sjkim 423238384Sjkim if (!key) 424238384Sjkim { 425238384Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 426238384Sjkim ERR_R_MALLOC_FAILURE); 427238384Sjkim goto err; 428238384Sjkim } 429238384Sjkim if (!kek_unwrap_key(key, &keylen, 430238384Sjkim pwri->encryptedKey->data, 431238384Sjkim pwri->encryptedKey->length, &kekctx)) 432238384Sjkim { 433238384Sjkim CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, 434238384Sjkim CMS_R_UNWRAP_FAILURE); 435238384Sjkim goto err; 436238384Sjkim } 437238384Sjkim 438238384Sjkim ec->key = key; 439238384Sjkim ec->keylen = keylen; 440238384Sjkim 441238384Sjkim } 442238384Sjkim 443238384Sjkim r = 1; 444238384Sjkim 445238384Sjkim err: 446238384Sjkim 447238384Sjkim EVP_CIPHER_CTX_cleanup(&kekctx); 448238384Sjkim 449238384Sjkim if (!r && key) 450238384Sjkim OPENSSL_free(key); 451238384Sjkim X509_ALGOR_free(kekalg); 452238384Sjkim 453238384Sjkim return r; 454238384Sjkim 455238384Sjkim } 456