Path: blob/main/crypto/heimdal/lib/hx509/crypto.c
107001 views
/*1* Copyright (c) 2004 - 2007 Kungliga Tekniska Hƶgskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* 3. Neither the name of the Institute nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233#include "hx_locl.h"3435struct hx509_crypto;3637struct signature_alg;3839struct hx509_generate_private_context {40const heim_oid *key_oid;41int isCA;42unsigned long num_bits;43};4445struct hx509_private_key_ops {46const char *pemtype;47const heim_oid *key_oid;48int (*available)(const hx509_private_key,49const AlgorithmIdentifier *);50int (*get_spki)(hx509_context,51const hx509_private_key,52SubjectPublicKeyInfo *);53int (*export)(hx509_context context,54const hx509_private_key,55hx509_key_format_t,56heim_octet_string *);57int (*import)(hx509_context, const AlgorithmIdentifier *,58const void *, size_t, hx509_key_format_t,59hx509_private_key);60int (*generate_private_key)(hx509_context,61struct hx509_generate_private_context *,62hx509_private_key);63BIGNUM *(*get_internal)(hx509_context, hx509_private_key, const char *);64};6566struct hx509_private_key {67unsigned int ref;68const struct signature_alg *md;69const heim_oid *signature_alg;70union {71RSA *rsa;72void *keydata;73#ifdef HAVE_OPENSSL74EC_KEY *ecdsa;75#endif76} private_key;77hx509_private_key_ops *ops;78};7980/*81*82*/8384struct signature_alg {85const char *name;86const heim_oid *sig_oid;87const AlgorithmIdentifier *sig_alg;88const heim_oid *key_oid;89const AlgorithmIdentifier *digest_alg;90int flags;91#define PROVIDE_CONF 0x192#define REQUIRE_SIGNER 0x293#define SELF_SIGNED_OK 0x49495#define SIG_DIGEST 0x10096#define SIG_PUBLIC_SIG 0x20097#define SIG_SECRET 0x4009899#define RA_RSA_USES_DIGEST_INFO 0x1000000100101time_t best_before; /* refuse signature made after best before date */102const EVP_MD *(*evp_md)(void);103int (*verify_signature)(hx509_context context,104const struct signature_alg *,105const Certificate *,106const AlgorithmIdentifier *,107const heim_octet_string *,108const heim_octet_string *);109int (*create_signature)(hx509_context,110const struct signature_alg *,111const hx509_private_key,112const AlgorithmIdentifier *,113const heim_octet_string *,114AlgorithmIdentifier *,115heim_octet_string *);116int digest_size;117};118119static const struct signature_alg *120find_sig_alg(const heim_oid *oid);121122/*123*124*/125126static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };127128static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };129const AlgorithmIdentifier _hx509_signature_sha512_data = {130{ 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid)131};132133static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };134const AlgorithmIdentifier _hx509_signature_sha384_data = {135{ 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid)136};137138static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };139const AlgorithmIdentifier _hx509_signature_sha256_data = {140{ 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)141};142143static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };144const AlgorithmIdentifier _hx509_signature_sha1_data = {145{ 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid)146};147148static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 };149const AlgorithmIdentifier _hx509_signature_md5_data = {150{ 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)151};152153static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };154const AlgorithmIdentifier _hx509_signature_ecPublicKey = {155{ 6, rk_UNCONST(ecPublicKey) }, NULL156};157158static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 };159const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = {160{ 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL161};162163static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 };164const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = {165{ 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL166};167168static const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 };169const AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = {170{ 7, rk_UNCONST(rsa_with_sha512_oid) }, NULL171};172173static const unsigned rsa_with_sha384_oid[] ={ 1, 2, 840, 113549, 1, 1, 12 };174const AlgorithmIdentifier _hx509_signature_rsa_with_sha384_data = {175{ 7, rk_UNCONST(rsa_with_sha384_oid) }, NULL176};177178static const unsigned rsa_with_sha256_oid[] ={ 1, 2, 840, 113549, 1, 1, 11 };179const AlgorithmIdentifier _hx509_signature_rsa_with_sha256_data = {180{ 7, rk_UNCONST(rsa_with_sha256_oid) }, NULL181};182183static const unsigned rsa_with_sha1_oid[] ={ 1, 2, 840, 113549, 1, 1, 5 };184const AlgorithmIdentifier _hx509_signature_rsa_with_sha1_data = {185{ 7, rk_UNCONST(rsa_with_sha1_oid) }, NULL186};187188static const unsigned rsa_with_md5_oid[] ={ 1, 2, 840, 113549, 1, 1, 4 };189const AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = {190{ 7, rk_UNCONST(rsa_with_md5_oid) }, NULL191};192193static const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 };194const AlgorithmIdentifier _hx509_signature_rsa_data = {195{ 7, rk_UNCONST(rsa_oid) }, NULL196};197198static const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 };199const AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = {200{ 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL201};202203static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 };204const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = {205{ 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL206};207208static const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 };209const AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = {210{ 9, rk_UNCONST(aes128_cbc_oid) }, NULL211};212213static const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 };214const AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = {215{ 9, rk_UNCONST(aes256_cbc_oid) }, NULL216};217218/*219*220*/221222static BIGNUM *223heim_int2BN(const heim_integer *i)224{225BIGNUM *bn;226227bn = BN_bin2bn(i->data, i->length, NULL);228if (bn != NULL)229BN_set_negative(bn, i->negative);230return bn;231}232233/*234*235*/236237static int238set_digest_alg(DigestAlgorithmIdentifier *id,239const heim_oid *oid,240const void *param, size_t length)241{242int ret;243if (param) {244id->parameters = malloc(sizeof(*id->parameters));245if (id->parameters == NULL)246return ENOMEM;247id->parameters->data = malloc(length);248if (id->parameters->data == NULL) {249free(id->parameters);250id->parameters = NULL;251return ENOMEM;252}253memcpy(id->parameters->data, param, length);254id->parameters->length = length;255} else256id->parameters = NULL;257ret = der_copy_oid(oid, &id->algorithm);258if (ret) {259if (id->parameters) {260free(id->parameters->data);261free(id->parameters);262id->parameters = NULL;263}264return ret;265}266return 0;267}268269#ifdef HAVE_OPENSSL270271static int272heim_oid2ecnid(heim_oid *oid)273{274/*275* Now map to openssl OID fun276*/277278if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP256R1) == 0)279return NID_X9_62_prime256v1;280else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R1) == 0)281return NID_secp160r1;282else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R2) == 0)283return NID_secp160r2;284285return -1;286}287288static int289parse_ECParameters(hx509_context context,290heim_octet_string *parameters, int *nid)291{292ECParameters ecparam;293size_t size;294int ret;295296if (parameters == NULL) {297ret = HX509_PARSING_KEY_FAILED;298hx509_set_error_string(context, 0, ret,299"EC parameters missing");300return ret;301}302303ret = decode_ECParameters(parameters->data, parameters->length,304&ecparam, &size);305if (ret) {306hx509_set_error_string(context, 0, ret,307"Failed to decode EC parameters");308return ret;309}310311if (ecparam.element != choice_ECParameters_namedCurve) {312free_ECParameters(&ecparam);313hx509_set_error_string(context, 0, ret,314"EC parameters is not a named curve");315return HX509_CRYPTO_SIG_INVALID_FORMAT;316}317318*nid = heim_oid2ecnid(&ecparam.u.namedCurve);319free_ECParameters(&ecparam);320if (*nid == -1) {321hx509_set_error_string(context, 0, ret,322"Failed to find matcing NID for EC curve");323return HX509_CRYPTO_SIG_INVALID_FORMAT;324}325return 0;326}327328329/*330*331*/332333static int334ecdsa_verify_signature(hx509_context context,335const struct signature_alg *sig_alg,336const Certificate *signer,337const AlgorithmIdentifier *alg,338const heim_octet_string *data,339const heim_octet_string *sig)340{341const AlgorithmIdentifier *digest_alg;342const SubjectPublicKeyInfo *spi;343heim_octet_string digest;344int ret;345EC_KEY *key = NULL;346int groupnid;347EC_GROUP *group;348const unsigned char *p;349long len;350351digest_alg = sig_alg->digest_alg;352353ret = _hx509_create_signature(context,354NULL,355digest_alg,356data,357NULL,358&digest);359if (ret)360return ret;361362/* set up EC KEY */363spi = &signer->tbsCertificate.subjectPublicKeyInfo;364365if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)366return HX509_CRYPTO_SIG_INVALID_FORMAT;367368#ifdef HAVE_OPENSSL369/*370* Find the group id371*/372373ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);374if (ret) {375der_free_octet_string(&digest);376return ret;377}378379/*380* Create group, key, parse key381*/382383key = EC_KEY_new();384group = EC_GROUP_new_by_curve_name(groupnid);385EC_KEY_set_group(key, group);386EC_GROUP_free(group);387388p = spi->subjectPublicKey.data;389len = spi->subjectPublicKey.length / 8;390391if (o2i_ECPublicKey(&key, &p, len) == NULL) {392EC_KEY_free(key);393return HX509_CRYPTO_SIG_INVALID_FORMAT;394}395#else396key = SubjectPublicKeyInfo2EC_KEY(spi);397#endif398399ret = ECDSA_verify(-1, digest.data, digest.length,400sig->data, sig->length, key);401der_free_octet_string(&digest);402EC_KEY_free(key);403if (ret != 1) {404ret = HX509_CRYPTO_SIG_INVALID_FORMAT;405return ret;406}407408return 0;409}410411static int412ecdsa_create_signature(hx509_context context,413const struct signature_alg *sig_alg,414const hx509_private_key signer,415const AlgorithmIdentifier *alg,416const heim_octet_string *data,417AlgorithmIdentifier *signatureAlgorithm,418heim_octet_string *sig)419{420const AlgorithmIdentifier *digest_alg;421heim_octet_string indata;422const heim_oid *sig_oid;423unsigned int siglen;424int ret;425426if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)427_hx509_abort("internal error passing private key to wrong ops");428429sig_oid = sig_alg->sig_oid;430digest_alg = sig_alg->digest_alg;431432if (signatureAlgorithm) {433ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);434if (ret) {435hx509_clear_error_string(context);436goto error;437}438}439440ret = _hx509_create_signature(context,441NULL,442digest_alg,443data,444NULL,445&indata);446if (ret) {447if (signatureAlgorithm)448free_AlgorithmIdentifier(signatureAlgorithm);449goto error;450}451452sig->length = ECDSA_size(signer->private_key.ecdsa);453sig->data = malloc(sig->length);454if (sig->data == NULL) {455der_free_octet_string(&indata);456ret = ENOMEM;457hx509_set_error_string(context, 0, ret, "out of memory");458goto error;459}460461siglen = sig->length;462463ret = ECDSA_sign(-1, indata.data, indata.length,464sig->data, &siglen, signer->private_key.ecdsa);465der_free_octet_string(&indata);466if (ret != 1) {467ret = HX509_CMS_FAILED_CREATE_SIGATURE;468hx509_set_error_string(context, 0, ret,469"ECDSA sign failed: %d", ret);470goto error;471}472if (siglen > sig->length)473_hx509_abort("ECDSA signature prelen longer the output len");474475sig->length = siglen;476477return 0;478error:479if (signatureAlgorithm)480free_AlgorithmIdentifier(signatureAlgorithm);481return ret;482}483484static int485ecdsa_available(const hx509_private_key signer,486const AlgorithmIdentifier *sig_alg)487{488const struct signature_alg *sig;489const EC_GROUP *group;490BN_CTX *bnctx = NULL;491BIGNUM *order = NULL;492int ret = 0;493494if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)495_hx509_abort("internal error passing private key to wrong ops");496497sig = find_sig_alg(&sig_alg->algorithm);498499if (sig == NULL || sig->digest_size == 0)500return 0;501502group = EC_KEY_get0_group(signer->private_key.ecdsa);503if (group == NULL)504return 0;505506bnctx = BN_CTX_new();507order = BN_new();508if (order == NULL)509goto err;510511if (EC_GROUP_get_order(group, order, bnctx) != 1)512goto err;513514if (BN_num_bytes(order) > sig->digest_size)515ret = 1;516err:517if (bnctx)518BN_CTX_free(bnctx);519if (order)520BN_clear_free(order);521522return ret;523}524525526#endif /* HAVE_OPENSSL */527528/*529*530*/531532static int533rsa_verify_signature(hx509_context context,534const struct signature_alg *sig_alg,535const Certificate *signer,536const AlgorithmIdentifier *alg,537const heim_octet_string *data,538const heim_octet_string *sig)539{540const SubjectPublicKeyInfo *spi;541DigestInfo di;542unsigned char *to;543int tosize, retsize;544int ret;545RSA *rsa;546size_t size;547const unsigned char *p;548549memset(&di, 0, sizeof(di));550551spi = &signer->tbsCertificate.subjectPublicKeyInfo;552553p = spi->subjectPublicKey.data;554size = spi->subjectPublicKey.length / 8;555556rsa = d2i_RSAPublicKey(NULL, &p, size);557if (rsa == NULL) {558ret = ENOMEM;559hx509_set_error_string(context, 0, ret, "out of memory");560goto out;561}562563tosize = RSA_size(rsa);564to = malloc(tosize);565if (to == NULL) {566ret = ENOMEM;567hx509_set_error_string(context, 0, ret, "out of memory");568goto out;569}570571retsize = RSA_public_decrypt(sig->length, (unsigned char *)sig->data,572to, rsa, RSA_PKCS1_PADDING);573if (retsize <= 0) {574ret = HX509_CRYPTO_SIG_INVALID_FORMAT;575hx509_set_error_string(context, 0, ret,576"RSA public decrypt failed: %d", retsize);577free(to);578goto out;579}580if (retsize > tosize)581_hx509_abort("internal rsa decryption failure: ret > tosize");582583if (sig_alg->flags & RA_RSA_USES_DIGEST_INFO) {584585ret = decode_DigestInfo(to, retsize, &di, &size);586free(to);587if (ret) {588goto out;589}590591/* Check for extra data inside the sigature */592if (size != (size_t)retsize) {593ret = HX509_CRYPTO_SIG_INVALID_FORMAT;594hx509_set_error_string(context, 0, ret, "size from decryption mismatch");595goto out;596}597598if (sig_alg->digest_alg &&599der_heim_oid_cmp(&di.digestAlgorithm.algorithm,600&sig_alg->digest_alg->algorithm) != 0)601{602ret = HX509_CRYPTO_OID_MISMATCH;603hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch");604goto out;605}606607/* verify that the parameters are NULL or the NULL-type */608if (di.digestAlgorithm.parameters != NULL &&609(di.digestAlgorithm.parameters->length != 2 ||610memcmp(di.digestAlgorithm.parameters->data, "\x05\x00", 2) != 0))611{612ret = HX509_CRYPTO_SIG_INVALID_FORMAT;613hx509_set_error_string(context, 0, ret, "Extra parameters inside RSA signature");614goto out;615}616617ret = _hx509_verify_signature(context,618NULL,619&di.digestAlgorithm,620data,621&di.digest);622} else {623if ((size_t)retsize != data->length ||624ct_memcmp(to, data->data, retsize) != 0)625{626ret = HX509_CRYPTO_SIG_INVALID_FORMAT;627hx509_set_error_string(context, 0, ret, "RSA Signature incorrect");628goto out;629}630free(to);631}632ret = 0;633634out:635free_DigestInfo(&di);636if (rsa)637RSA_free(rsa);638return ret;639}640641static int642rsa_create_signature(hx509_context context,643const struct signature_alg *sig_alg,644const hx509_private_key signer,645const AlgorithmIdentifier *alg,646const heim_octet_string *data,647AlgorithmIdentifier *signatureAlgorithm,648heim_octet_string *sig)649{650const AlgorithmIdentifier *digest_alg;651heim_octet_string indata;652const heim_oid *sig_oid;653size_t size;654int ret;655656if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0)657return HX509_ALG_NOT_SUPP;658659if (alg)660sig_oid = &alg->algorithm;661else662sig_oid = signer->signature_alg;663664if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION) == 0) {665digest_alg = hx509_signature_sha512();666} else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION) == 0) {667digest_alg = hx509_signature_sha384();668} else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION) == 0) {669digest_alg = hx509_signature_sha256();670} else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION) == 0) {671digest_alg = hx509_signature_sha1();672} else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) {673digest_alg = hx509_signature_md5();674} else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) {675digest_alg = hx509_signature_md5();676} else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_DSA_WITH_SHA1) == 0) {677digest_alg = hx509_signature_sha1();678} else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {679digest_alg = hx509_signature_sha1();680} else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_HEIM_RSA_PKCS1_X509) == 0) {681digest_alg = NULL;682} else683return HX509_ALG_NOT_SUPP;684685if (signatureAlgorithm) {686ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);687if (ret) {688hx509_clear_error_string(context);689return ret;690}691}692693if (digest_alg) {694DigestInfo di;695memset(&di, 0, sizeof(di));696697ret = _hx509_create_signature(context,698NULL,699digest_alg,700data,701&di.digestAlgorithm,702&di.digest);703if (ret)704return ret;705ASN1_MALLOC_ENCODE(DigestInfo,706indata.data,707indata.length,708&di,709&size,710ret);711free_DigestInfo(&di);712if (ret) {713hx509_set_error_string(context, 0, ret, "out of memory");714return ret;715}716if (indata.length != size)717_hx509_abort("internal ASN.1 encoder error");718} else {719indata = *data;720}721722sig->length = RSA_size(signer->private_key.rsa);723sig->data = malloc(sig->length);724if (sig->data == NULL) {725der_free_octet_string(&indata);726hx509_set_error_string(context, 0, ENOMEM, "out of memory");727return ENOMEM;728}729730ret = RSA_private_encrypt(indata.length, indata.data,731sig->data,732signer->private_key.rsa,733RSA_PKCS1_PADDING);734if (indata.data != data->data)735der_free_octet_string(&indata);736if (ret <= 0) {737ret = HX509_CMS_FAILED_CREATE_SIGATURE;738hx509_set_error_string(context, 0, ret,739"RSA private encrypt failed: %d", ret);740return ret;741}742if ((size_t)ret > sig->length)743_hx509_abort("RSA signature prelen longer the output len");744745sig->length = ret;746747return 0;748}749750static int751rsa_private_key_import(hx509_context context,752const AlgorithmIdentifier *keyai,753const void *data,754size_t len,755hx509_key_format_t format,756hx509_private_key private_key)757{758switch (format) {759case HX509_KEY_FORMAT_DER: {760const unsigned char *p = data;761762private_key->private_key.rsa =763d2i_RSAPrivateKey(NULL, &p, len);764if (private_key->private_key.rsa == NULL) {765hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,766"Failed to parse RSA key");767return HX509_PARSING_KEY_FAILED;768}769private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;770break;771772}773default:774return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;775}776777return 0;778}779780static int781rsa_private_key2SPKI(hx509_context context,782hx509_private_key private_key,783SubjectPublicKeyInfo *spki)784{785int len, ret;786787memset(spki, 0, sizeof(*spki));788789len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL);790791spki->subjectPublicKey.data = malloc(len);792if (spki->subjectPublicKey.data == NULL) {793hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");794return ENOMEM;795}796spki->subjectPublicKey.length = len * 8;797798ret = set_digest_alg(&spki->algorithm, ASN1_OID_ID_PKCS1_RSAENCRYPTION,799"\x05\x00", 2);800if (ret) {801hx509_set_error_string(context, 0, ret, "malloc - out of memory");802free(spki->subjectPublicKey.data);803spki->subjectPublicKey.data = NULL;804spki->subjectPublicKey.length = 0;805return ret;806}807808{809unsigned char *pp = spki->subjectPublicKey.data;810i2d_RSAPublicKey(private_key->private_key.rsa, &pp);811}812813return 0;814}815816static int817rsa_generate_private_key(hx509_context context,818struct hx509_generate_private_context *ctx,819hx509_private_key private_key)820{821BIGNUM *e;822int ret;823unsigned long bits;824825static const int default_rsa_e = 65537;826static const int default_rsa_bits = 2048;827828private_key->private_key.rsa = RSA_new();829if (private_key->private_key.rsa == NULL) {830hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,831"Failed to generate RSA key");832return HX509_PARSING_KEY_FAILED;833}834835e = BN_new();836BN_set_word(e, default_rsa_e);837838bits = default_rsa_bits;839840if (ctx->num_bits)841bits = ctx->num_bits;842843ret = RSA_generate_key_ex(private_key->private_key.rsa, bits, e, NULL);844BN_free(e);845if (ret != 1) {846hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,847"Failed to generate RSA key");848return HX509_PARSING_KEY_FAILED;849}850private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;851852return 0;853}854855static int856rsa_private_key_export(hx509_context context,857const hx509_private_key key,858hx509_key_format_t format,859heim_octet_string *data)860{861int ret;862863data->data = NULL;864data->length = 0;865866switch (format) {867case HX509_KEY_FORMAT_DER:868869ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL);870if (ret <= 0) {871ret = EINVAL;872hx509_set_error_string(context, 0, ret,873"Private key is not exportable");874return ret;875}876877data->data = malloc(ret);878if (data->data == NULL) {879ret = ENOMEM;880hx509_set_error_string(context, 0, ret, "malloc out of memory");881return ret;882}883data->length = ret;884885{886unsigned char *p = data->data;887i2d_RSAPrivateKey(key->private_key.rsa, &p);888}889break;890default:891return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;892}893894return 0;895}896897static BIGNUM *898rsa_get_internal(hx509_context context,899hx509_private_key key,900const char *type)901{902const BIGNUM *n;903904if (strcasecmp(type, "rsa-modulus") == 0) {905RSA_get0_key(key->private_key.rsa, &n, NULL, NULL);906} else if (strcasecmp(type, "rsa-exponent") == 0) {907RSA_get0_key(key->private_key.rsa, NULL, &n, NULL);908} else909return NULL;910return BN_dup(n);911}912913914915static hx509_private_key_ops rsa_private_key_ops = {916"RSA PRIVATE KEY",917ASN1_OID_ID_PKCS1_RSAENCRYPTION,918NULL,919rsa_private_key2SPKI,920rsa_private_key_export,921rsa_private_key_import,922rsa_generate_private_key,923rsa_get_internal924};925926#ifdef HAVE_OPENSSL927928static int929ecdsa_private_key2SPKI(hx509_context context,930hx509_private_key private_key,931SubjectPublicKeyInfo *spki)932{933memset(spki, 0, sizeof(*spki));934return ENOMEM;935}936937static int938ecdsa_private_key_export(hx509_context context,939const hx509_private_key key,940hx509_key_format_t format,941heim_octet_string *data)942{943return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;944}945946static int947ecdsa_private_key_import(hx509_context context,948const AlgorithmIdentifier *keyai,949const void *data,950size_t len,951hx509_key_format_t format,952hx509_private_key private_key)953{954const unsigned char *p = data;955EC_KEY **pkey = NULL;956957if (keyai->parameters) {958EC_GROUP *group;959int groupnid;960EC_KEY *key;961int ret;962963ret = parse_ECParameters(context, keyai->parameters, &groupnid);964if (ret)965return ret;966967key = EC_KEY_new();968if (key == NULL)969return ENOMEM;970971group = EC_GROUP_new_by_curve_name(groupnid);972if (group == NULL) {973EC_KEY_free(key);974return ENOMEM;975}976EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);977if (EC_KEY_set_group(key, group) == 0) {978EC_KEY_free(key);979EC_GROUP_free(group);980return ENOMEM;981}982EC_GROUP_free(group);983pkey = &key;984}985986switch (format) {987case HX509_KEY_FORMAT_DER:988989private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);990if (private_key->private_key.ecdsa == NULL) {991hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,992"Failed to parse EC private key");993return HX509_PARSING_KEY_FAILED;994}995private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;996break;997998default:999return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;1000}10011002return 0;1003}10041005static int1006ecdsa_generate_private_key(hx509_context context,1007struct hx509_generate_private_context *ctx,1008hx509_private_key private_key)1009{1010return ENOMEM;1011}10121013static BIGNUM *1014ecdsa_get_internal(hx509_context context,1015hx509_private_key key,1016const char *type)1017{1018return NULL;1019}102010211022static hx509_private_key_ops ecdsa_private_key_ops = {1023"EC PRIVATE KEY",1024ASN1_OID_ID_ECPUBLICKEY,1025ecdsa_available,1026ecdsa_private_key2SPKI,1027ecdsa_private_key_export,1028ecdsa_private_key_import,1029ecdsa_generate_private_key,1030ecdsa_get_internal1031};10321033#endif /* HAVE_OPENSSL */10341035/*1036*1037*/10381039static int1040dsa_verify_signature(hx509_context context,1041const struct signature_alg *sig_alg,1042const Certificate *signer,1043const AlgorithmIdentifier *alg,1044const heim_octet_string *data,1045const heim_octet_string *sig)1046{1047const SubjectPublicKeyInfo *spi;1048DSAPublicKey pk;1049DSAParams param;1050size_t size;1051BIGNUM *key, *p, *q, *g;1052DSA *dsa;1053int ret;10541055spi = &signer->tbsCertificate.subjectPublicKeyInfo;10561057dsa = DSA_new();1058if (dsa == NULL) {1059hx509_set_error_string(context, 0, ENOMEM, "out of memory");1060return ENOMEM;1061}10621063ret = decode_DSAPublicKey(spi->subjectPublicKey.data,1064spi->subjectPublicKey.length / 8,1065&pk, &size);1066if (ret)1067goto out;10681069key = heim_int2BN(&pk);10701071free_DSAPublicKey(&pk);10721073if (key == NULL) {1074ret = ENOMEM;1075hx509_set_error_string(context, 0, ret, "out of memory");1076goto out;1077}10781079ret = DSA_set0_key(dsa, key, NULL);10801081if (ret != 1) {1082BN_free(key);1083ret = EINVAL;1084hx509_set_error_string(context, 0, ret, "failed to set DSA key");1085goto out;1086}10871088if (spi->algorithm.parameters == NULL) {1089ret = HX509_CRYPTO_SIG_INVALID_FORMAT;1090hx509_set_error_string(context, 0, ret, "DSA parameters missing");1091goto out;1092}10931094ret = decode_DSAParams(spi->algorithm.parameters->data,1095spi->algorithm.parameters->length,1096¶m,1097&size);1098if (ret) {1099hx509_set_error_string(context, 0, ret, "DSA parameters failed to decode");1100goto out;1101}11021103p = heim_int2BN(¶m.p);1104q = heim_int2BN(¶m.q);1105g = heim_int2BN(¶m.g);11061107free_DSAParams(¶m);11081109if (p == NULL || q == NULL || g == NULL) {1110BN_free(p);1111BN_free(q);1112BN_free(g);1113ret = ENOMEM;1114hx509_set_error_string(context, 0, ret, "out of memory");1115goto out;1116}11171118ret = DSA_set0_pqg(dsa, p, q, g);11191120if (ret != 1) {1121BN_free(p);1122BN_free(q);1123BN_free(g);1124ret = EINVAL;1125hx509_set_error_string(context, 0, ret, "failed to set DSA parameters");1126goto out;1127}11281129ret = DSA_verify(-1, data->data, data->length,1130(unsigned char*)sig->data, sig->length,1131dsa);1132if (ret == 1)1133ret = 0;1134else if (ret == 0 || ret == -1) {1135ret = HX509_CRYPTO_BAD_SIGNATURE;1136hx509_set_error_string(context, 0, ret, "BAD DSA sigature");1137} else {1138ret = HX509_CRYPTO_SIG_INVALID_FORMAT;1139hx509_set_error_string(context, 0, ret, "Invalid format of DSA sigature");1140}11411142out:1143DSA_free(dsa);11441145return ret;1146}11471148#if 01149static int1150dsa_parse_private_key(hx509_context context,1151const void *data,1152size_t len,1153hx509_private_key private_key)1154{1155const unsigned char *p = data;11561157private_key->private_key.dsa =1158d2i_DSAPrivateKey(NULL, &p, len);1159if (private_key->private_key.dsa == NULL)1160return EINVAL;1161private_key->signature_alg = ASN1_OID_ID_DSA_WITH_SHA1;11621163return 0;1164/* else */1165hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,1166"No support to parse DSA keys");1167return HX509_PARSING_KEY_FAILED;1168}1169#endif11701171static int1172evp_md_create_signature(hx509_context context,1173const struct signature_alg *sig_alg,1174const hx509_private_key signer,1175const AlgorithmIdentifier *alg,1176const heim_octet_string *data,1177AlgorithmIdentifier *signatureAlgorithm,1178heim_octet_string *sig)1179{1180size_t sigsize = EVP_MD_size(sig_alg->evp_md());1181EVP_MD_CTX *ctx;11821183memset(sig, 0, sizeof(*sig));11841185if (signatureAlgorithm) {1186int ret;1187ret = set_digest_alg(signatureAlgorithm, sig_alg->sig_oid,1188"\x05\x00", 2);1189if (ret)1190return ret;1191}119211931194sig->data = malloc(sigsize);1195if (sig->data == NULL) {1196sig->length = 0;1197return ENOMEM;1198}1199sig->length = sigsize;12001201ctx = EVP_MD_CTX_create();1202EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL);1203EVP_DigestUpdate(ctx, data->data, data->length);1204EVP_DigestFinal_ex(ctx, sig->data, NULL);1205EVP_MD_CTX_destroy(ctx);120612071208return 0;1209}12101211static int1212evp_md_verify_signature(hx509_context context,1213const struct signature_alg *sig_alg,1214const Certificate *signer,1215const AlgorithmIdentifier *alg,1216const heim_octet_string *data,1217const heim_octet_string *sig)1218{1219unsigned char digest[EVP_MAX_MD_SIZE];1220EVP_MD_CTX *ctx;1221size_t sigsize = EVP_MD_size(sig_alg->evp_md());12221223if (sig->length != sigsize || sigsize > sizeof(digest)) {1224hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT,1225"SHA256 sigature have wrong length");1226return HX509_CRYPTO_SIG_INVALID_FORMAT;1227}12281229ctx = EVP_MD_CTX_create();1230EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL);1231EVP_DigestUpdate(ctx, data->data, data->length);1232EVP_DigestFinal_ex(ctx, digest, NULL);1233EVP_MD_CTX_destroy(ctx);12341235if (ct_memcmp(digest, sig->data, sigsize) != 0) {1236hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE,1237"Bad %s sigature", sig_alg->name);1238return HX509_CRYPTO_BAD_SIGNATURE;1239}12401241return 0;1242}12431244#ifdef HAVE_OPENSSL12451246static const struct signature_alg ecdsa_with_sha256_alg = {1247"ecdsa-with-sha256",1248ASN1_OID_ID_ECDSA_WITH_SHA256,1249&_hx509_signature_ecdsa_with_sha256_data,1250ASN1_OID_ID_ECPUBLICKEY,1251&_hx509_signature_sha256_data,1252PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,12530,1254NULL,1255ecdsa_verify_signature,1256ecdsa_create_signature,1257321258};12591260static const struct signature_alg ecdsa_with_sha1_alg = {1261"ecdsa-with-sha1",1262ASN1_OID_ID_ECDSA_WITH_SHA1,1263&_hx509_signature_ecdsa_with_sha1_data,1264ASN1_OID_ID_ECPUBLICKEY,1265&_hx509_signature_sha1_data,1266PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,12670,1268NULL,1269ecdsa_verify_signature,1270ecdsa_create_signature,1271201272};12731274#endif12751276static const struct signature_alg heim_rsa_pkcs1_x509 = {1277"rsa-pkcs1-x509",1278ASN1_OID_ID_HEIM_RSA_PKCS1_X509,1279&_hx509_signature_rsa_pkcs1_x509_data,1280ASN1_OID_ID_PKCS1_RSAENCRYPTION,1281NULL,1282PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,12830,1284NULL,1285rsa_verify_signature,1286rsa_create_signature,128701288};12891290static const struct signature_alg pkcs1_rsa_sha1_alg = {1291"rsa",1292ASN1_OID_ID_PKCS1_RSAENCRYPTION,1293&_hx509_signature_rsa_with_sha1_data,1294ASN1_OID_ID_PKCS1_RSAENCRYPTION,1295NULL,1296PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,12970,1298NULL,1299rsa_verify_signature,1300rsa_create_signature,130101302};13031304static const struct signature_alg rsa_with_sha512_alg = {1305"rsa-with-sha512",1306ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION,1307&_hx509_signature_rsa_with_sha512_data,1308ASN1_OID_ID_PKCS1_RSAENCRYPTION,1309&_hx509_signature_sha512_data,1310PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,13110,1312NULL,1313rsa_verify_signature,1314rsa_create_signature,131501316};13171318static const struct signature_alg rsa_with_sha384_alg = {1319"rsa-with-sha384",1320ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION,1321&_hx509_signature_rsa_with_sha384_data,1322ASN1_OID_ID_PKCS1_RSAENCRYPTION,1323&_hx509_signature_sha384_data,1324PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,13250,1326NULL,1327rsa_verify_signature,1328rsa_create_signature,132901330};13311332static const struct signature_alg rsa_with_sha256_alg = {1333"rsa-with-sha256",1334ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION,1335&_hx509_signature_rsa_with_sha256_data,1336ASN1_OID_ID_PKCS1_RSAENCRYPTION,1337&_hx509_signature_sha256_data,1338PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,13390,1340NULL,1341rsa_verify_signature,1342rsa_create_signature,134301344};13451346static const struct signature_alg rsa_with_sha1_alg = {1347"rsa-with-sha1",1348ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION,1349&_hx509_signature_rsa_with_sha1_data,1350ASN1_OID_ID_PKCS1_RSAENCRYPTION,1351&_hx509_signature_sha1_data,1352PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,13530,1354NULL,1355rsa_verify_signature,1356rsa_create_signature,135701358};13591360static const struct signature_alg rsa_with_sha1_alg_secsig = {1361"rsa-with-sha1",1362ASN1_OID_ID_SECSIG_SHA_1WITHRSAENCRYPTION,1363&_hx509_signature_rsa_with_sha1_data,1364ASN1_OID_ID_PKCS1_RSAENCRYPTION,1365&_hx509_signature_sha1_data,1366PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,13670,1368NULL,1369rsa_verify_signature,1370rsa_create_signature,137101372};13731374static const struct signature_alg rsa_with_md5_alg = {1375"rsa-with-md5",1376ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION,1377&_hx509_signature_rsa_with_md5_data,1378ASN1_OID_ID_PKCS1_RSAENCRYPTION,1379&_hx509_signature_md5_data,1380PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,13811230739889,1382NULL,1383rsa_verify_signature,1384rsa_create_signature,138501386};13871388static const struct signature_alg dsa_sha1_alg = {1389"dsa-with-sha1",1390ASN1_OID_ID_DSA_WITH_SHA1,1391NULL,1392ASN1_OID_ID_DSA,1393&_hx509_signature_sha1_data,1394PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,13950,1396NULL,1397dsa_verify_signature,1398/* create_signature */ NULL,139901400};14011402static const struct signature_alg sha512_alg = {1403"sha-512",1404ASN1_OID_ID_SHA512,1405&_hx509_signature_sha512_data,1406NULL,1407NULL,1408SIG_DIGEST,14090,1410EVP_sha512,1411evp_md_verify_signature,1412evp_md_create_signature,141301414};14151416static const struct signature_alg sha384_alg = {1417"sha-384",1418ASN1_OID_ID_SHA512,1419&_hx509_signature_sha384_data,1420NULL,1421NULL,1422SIG_DIGEST,14230,1424EVP_sha384,1425evp_md_verify_signature,1426evp_md_create_signature,142701428};14291430static const struct signature_alg sha256_alg = {1431"sha-256",1432ASN1_OID_ID_SHA256,1433&_hx509_signature_sha256_data,1434NULL,1435NULL,1436SIG_DIGEST,14370,1438EVP_sha256,1439evp_md_verify_signature,1440evp_md_create_signature,144101442};14431444static const struct signature_alg sha1_alg = {1445"sha1",1446ASN1_OID_ID_SECSIG_SHA_1,1447&_hx509_signature_sha1_data,1448NULL,1449NULL,1450SIG_DIGEST,14510,1452EVP_sha1,1453evp_md_verify_signature,1454evp_md_create_signature,145501456};14571458static const struct signature_alg md5_alg = {1459"rsa-md5",1460ASN1_OID_ID_RSA_DIGEST_MD5,1461&_hx509_signature_md5_data,1462NULL,1463NULL,1464SIG_DIGEST,14650,1466EVP_md5,1467evp_md_verify_signature,1468NULL,146901470};14711472/*1473* Order matter in this structure, "best" first for each "key1474* compatible" type (type is ECDSA, RSA, DSA, none, etc)1475*/14761477static const struct signature_alg *sig_algs[] = {1478#ifdef HAVE_OPENSSL1479&ecdsa_with_sha256_alg,1480&ecdsa_with_sha1_alg,1481#endif1482&rsa_with_sha512_alg,1483&rsa_with_sha384_alg,1484&rsa_with_sha256_alg,1485&rsa_with_sha1_alg,1486&rsa_with_sha1_alg_secsig,1487&pkcs1_rsa_sha1_alg,1488&rsa_with_md5_alg,1489&heim_rsa_pkcs1_x509,1490&dsa_sha1_alg,1491&sha512_alg,1492&sha384_alg,1493&sha256_alg,1494&sha1_alg,1495&md5_alg,1496NULL1497};14981499static const struct signature_alg *1500find_sig_alg(const heim_oid *oid)1501{1502unsigned int i;1503for (i = 0; sig_algs[i]; i++)1504if (der_heim_oid_cmp(sig_algs[i]->sig_oid, oid) == 0)1505return sig_algs[i];1506return NULL;1507}15081509static const AlgorithmIdentifier *1510alg_for_privatekey(const hx509_private_key pk, int type)1511{1512const heim_oid *keytype;1513unsigned int i;15141515if (pk->ops == NULL)1516return NULL;15171518keytype = pk->ops->key_oid;15191520for (i = 0; sig_algs[i]; i++) {1521if (sig_algs[i]->key_oid == NULL)1522continue;1523if (der_heim_oid_cmp(sig_algs[i]->key_oid, keytype) != 0)1524continue;1525if (pk->ops->available &&1526pk->ops->available(pk, sig_algs[i]->sig_alg) == 0)1527continue;1528if (type == HX509_SELECT_PUBLIC_SIG)1529return sig_algs[i]->sig_alg;1530if (type == HX509_SELECT_DIGEST)1531return sig_algs[i]->digest_alg;15321533return NULL;1534}1535return NULL;1536}15371538/*1539*1540*/15411542static struct hx509_private_key_ops *private_algs[] = {1543&rsa_private_key_ops,1544#ifdef HAVE_OPENSSL1545&ecdsa_private_key_ops,1546#endif1547NULL1548};15491550hx509_private_key_ops *1551hx509_find_private_alg(const heim_oid *oid)1552{1553int i;1554for (i = 0; private_algs[i]; i++) {1555if (private_algs[i]->key_oid == NULL)1556continue;1557if (der_heim_oid_cmp(private_algs[i]->key_oid, oid) == 0)1558return private_algs[i];1559}1560return NULL;1561}15621563/*1564* Check if the algorithm `alg' have a best before date, and if it1565* des, make sure the its before the time `t'.1566*/15671568int1569_hx509_signature_best_before(hx509_context context,1570const AlgorithmIdentifier *alg,1571time_t t)1572{1573const struct signature_alg *md;15741575md = find_sig_alg(&alg->algorithm);1576if (md == NULL) {1577hx509_clear_error_string(context);1578return HX509_SIG_ALG_NO_SUPPORTED;1579}1580if (md->best_before && md->best_before < t) {1581hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE,1582"Algorithm %s has passed it best before date",1583md->name);1584return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;1585}1586return 0;1587}15881589int1590_hx509_self_signed_valid(hx509_context context,1591const AlgorithmIdentifier *alg)1592{1593const struct signature_alg *md;15941595md = find_sig_alg(&alg->algorithm);1596if (md == NULL) {1597hx509_clear_error_string(context);1598return HX509_SIG_ALG_NO_SUPPORTED;1599}1600if ((md->flags & SELF_SIGNED_OK) == 0) {1601hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE,1602"Algorithm %s not trusted for self signatures",1603md->name);1604return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;1605}1606return 0;1607}160816091610int1611_hx509_verify_signature(hx509_context context,1612const hx509_cert cert,1613const AlgorithmIdentifier *alg,1614const heim_octet_string *data,1615const heim_octet_string *sig)1616{1617const struct signature_alg *md;1618const Certificate *signer = NULL;16191620if (cert)1621signer = _hx509_get_cert(cert);16221623md = find_sig_alg(&alg->algorithm);1624if (md == NULL) {1625hx509_clear_error_string(context);1626return HX509_SIG_ALG_NO_SUPPORTED;1627}1628if (signer && (md->flags & PROVIDE_CONF) == 0) {1629hx509_clear_error_string(context);1630return HX509_CRYPTO_SIG_NO_CONF;1631}1632if (signer == NULL && (md->flags & REQUIRE_SIGNER)) {1633hx509_clear_error_string(context);1634return HX509_CRYPTO_SIGNATURE_WITHOUT_SIGNER;1635}1636if (md->key_oid && signer) {1637const SubjectPublicKeyInfo *spi;1638spi = &signer->tbsCertificate.subjectPublicKeyInfo;16391640if (der_heim_oid_cmp(&spi->algorithm.algorithm, md->key_oid) != 0) {1641hx509_clear_error_string(context);1642return HX509_SIG_ALG_DONT_MATCH_KEY_ALG;1643}1644}1645return (*md->verify_signature)(context, md, signer, alg, data, sig);1646}16471648int1649_hx509_create_signature(hx509_context context,1650const hx509_private_key signer,1651const AlgorithmIdentifier *alg,1652const heim_octet_string *data,1653AlgorithmIdentifier *signatureAlgorithm,1654heim_octet_string *sig)1655{1656const struct signature_alg *md;16571658md = find_sig_alg(&alg->algorithm);1659if (md == NULL) {1660hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,1661"algorithm no supported");1662return HX509_SIG_ALG_NO_SUPPORTED;1663}16641665if (signer && (md->flags & PROVIDE_CONF) == 0) {1666hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,1667"algorithm provides no conf");1668return HX509_CRYPTO_SIG_NO_CONF;1669}16701671return (*md->create_signature)(context, md, signer, alg, data,1672signatureAlgorithm, sig);1673}16741675int1676_hx509_create_signature_bitstring(hx509_context context,1677const hx509_private_key signer,1678const AlgorithmIdentifier *alg,1679const heim_octet_string *data,1680AlgorithmIdentifier *signatureAlgorithm,1681heim_bit_string *sig)1682{1683heim_octet_string os;1684int ret;16851686ret = _hx509_create_signature(context, signer, alg,1687data, signatureAlgorithm, &os);1688if (ret)1689return ret;1690sig->data = os.data;1691sig->length = os.length * 8;1692return 0;1693}16941695int1696_hx509_public_encrypt(hx509_context context,1697const heim_octet_string *cleartext,1698const Certificate *cert,1699heim_oid *encryption_oid,1700heim_octet_string *ciphertext)1701{1702const SubjectPublicKeyInfo *spi;1703unsigned char *to;1704int tosize;1705int ret;1706RSA *rsa;1707size_t size;1708const unsigned char *p;17091710ciphertext->data = NULL;1711ciphertext->length = 0;17121713spi = &cert->tbsCertificate.subjectPublicKeyInfo;17141715p = spi->subjectPublicKey.data;1716size = spi->subjectPublicKey.length / 8;17171718rsa = d2i_RSAPublicKey(NULL, &p, size);1719if (rsa == NULL) {1720hx509_set_error_string(context, 0, ENOMEM, "out of memory");1721return ENOMEM;1722}17231724tosize = RSA_size(rsa);1725to = malloc(tosize);1726if (to == NULL) {1727RSA_free(rsa);1728hx509_set_error_string(context, 0, ENOMEM, "out of memory");1729return ENOMEM;1730}17311732ret = RSA_public_encrypt(cleartext->length,1733(unsigned char *)cleartext->data,1734to, rsa, RSA_PKCS1_PADDING);1735RSA_free(rsa);1736if (ret <= 0) {1737free(to);1738hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PUBLIC_ENCRYPT,1739"RSA public encrypt failed with %d", ret);1740return HX509_CRYPTO_RSA_PUBLIC_ENCRYPT;1741}1742if (ret > tosize)1743_hx509_abort("internal rsa decryption failure: ret > tosize");17441745ciphertext->length = ret;1746ciphertext->data = to;17471748ret = der_copy_oid(ASN1_OID_ID_PKCS1_RSAENCRYPTION, encryption_oid);1749if (ret) {1750der_free_octet_string(ciphertext);1751hx509_set_error_string(context, 0, ENOMEM, "out of memory");1752return ENOMEM;1753}17541755return 0;1756}17571758int1759hx509_private_key_private_decrypt(hx509_context context,1760const heim_octet_string *ciphertext,1761const heim_oid *encryption_oid,1762hx509_private_key p,1763heim_octet_string *cleartext)1764{1765int ret;17661767cleartext->data = NULL;1768cleartext->length = 0;17691770if (p->private_key.rsa == NULL) {1771hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,1772"Private RSA key missing");1773return HX509_PRIVATE_KEY_MISSING;1774}17751776cleartext->length = RSA_size(p->private_key.rsa);1777cleartext->data = malloc(cleartext->length);1778if (cleartext->data == NULL) {1779hx509_set_error_string(context, 0, ENOMEM, "out of memory");1780return ENOMEM;1781}1782ret = RSA_private_decrypt(ciphertext->length, ciphertext->data,1783cleartext->data,1784p->private_key.rsa,1785RSA_PKCS1_PADDING);1786if (ret <= 0) {1787der_free_octet_string(cleartext);1788hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PRIVATE_DECRYPT,1789"Failed to decrypt using private key: %d", ret);1790return HX509_CRYPTO_RSA_PRIVATE_DECRYPT;1791}1792if (cleartext->length < (size_t)ret)1793_hx509_abort("internal rsa decryption failure: ret > tosize");17941795cleartext->length = ret;17961797return 0;1798}179918001801int1802hx509_parse_private_key(hx509_context context,1803const AlgorithmIdentifier *keyai,1804const void *data,1805size_t len,1806hx509_key_format_t format,1807hx509_private_key *private_key)1808{1809struct hx509_private_key_ops *ops;1810int ret;18111812*private_key = NULL;18131814ops = hx509_find_private_alg(&keyai->algorithm);1815if (ops == NULL) {1816hx509_clear_error_string(context);1817return HX509_SIG_ALG_NO_SUPPORTED;1818}18191820ret = hx509_private_key_init(private_key, ops, NULL);1821if (ret) {1822hx509_set_error_string(context, 0, ret, "out of memory");1823return ret;1824}18251826ret = (*ops->import)(context, keyai, data, len, format, *private_key);1827if (ret)1828hx509_private_key_free(private_key);18291830return ret;1831}18321833/*1834*1835*/18361837int1838hx509_private_key2SPKI(hx509_context context,1839hx509_private_key private_key,1840SubjectPublicKeyInfo *spki)1841{1842const struct hx509_private_key_ops *ops = private_key->ops;1843if (ops == NULL || ops->get_spki == NULL) {1844hx509_set_error_string(context, 0, HX509_UNIMPLEMENTED_OPERATION,1845"Private key have no key2SPKI function");1846return HX509_UNIMPLEMENTED_OPERATION;1847}1848return (*ops->get_spki)(context, private_key, spki);1849}18501851int1852_hx509_generate_private_key_init(hx509_context context,1853const heim_oid *oid,1854struct hx509_generate_private_context **ctx)1855{1856*ctx = NULL;18571858if (der_heim_oid_cmp(oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0) {1859hx509_set_error_string(context, 0, EINVAL,1860"private key not an RSA key");1861return EINVAL;1862}18631864*ctx = calloc(1, sizeof(**ctx));1865if (*ctx == NULL) {1866hx509_set_error_string(context, 0, ENOMEM, "out of memory");1867return ENOMEM;1868}1869(*ctx)->key_oid = oid;18701871return 0;1872}18731874int1875_hx509_generate_private_key_is_ca(hx509_context context,1876struct hx509_generate_private_context *ctx)1877{1878ctx->isCA = 1;1879return 0;1880}18811882int1883_hx509_generate_private_key_bits(hx509_context context,1884struct hx509_generate_private_context *ctx,1885unsigned long bits)1886{1887ctx->num_bits = bits;1888return 0;1889}189018911892void1893_hx509_generate_private_key_free(struct hx509_generate_private_context **ctx)1894{1895free(*ctx);1896*ctx = NULL;1897}18981899int1900_hx509_generate_private_key(hx509_context context,1901struct hx509_generate_private_context *ctx,1902hx509_private_key *private_key)1903{1904struct hx509_private_key_ops *ops;1905int ret;19061907*private_key = NULL;19081909ops = hx509_find_private_alg(ctx->key_oid);1910if (ops == NULL) {1911hx509_clear_error_string(context);1912return HX509_SIG_ALG_NO_SUPPORTED;1913}19141915ret = hx509_private_key_init(private_key, ops, NULL);1916if (ret) {1917hx509_set_error_string(context, 0, ret, "out of memory");1918return ret;1919}19201921ret = (*ops->generate_private_key)(context, ctx, *private_key);1922if (ret)1923hx509_private_key_free(private_key);19241925return ret;1926}19271928/*1929*1930*/19311932const AlgorithmIdentifier *1933hx509_signature_sha512(void)1934{ return &_hx509_signature_sha512_data; }19351936const AlgorithmIdentifier *1937hx509_signature_sha384(void)1938{ return &_hx509_signature_sha384_data; }19391940const AlgorithmIdentifier *1941hx509_signature_sha256(void)1942{ return &_hx509_signature_sha256_data; }19431944const AlgorithmIdentifier *1945hx509_signature_sha1(void)1946{ return &_hx509_signature_sha1_data; }19471948const AlgorithmIdentifier *1949hx509_signature_md5(void)1950{ return &_hx509_signature_md5_data; }19511952const AlgorithmIdentifier *1953hx509_signature_ecPublicKey(void)1954{ return &_hx509_signature_ecPublicKey; }19551956const AlgorithmIdentifier *1957hx509_signature_ecdsa_with_sha256(void)1958{ return &_hx509_signature_ecdsa_with_sha256_data; }19591960const AlgorithmIdentifier *1961hx509_signature_ecdsa_with_sha1(void)1962{ return &_hx509_signature_ecdsa_with_sha1_data; }19631964const AlgorithmIdentifier *1965hx509_signature_rsa_with_sha512(void)1966{ return &_hx509_signature_rsa_with_sha512_data; }19671968const AlgorithmIdentifier *1969hx509_signature_rsa_with_sha384(void)1970{ return &_hx509_signature_rsa_with_sha384_data; }19711972const AlgorithmIdentifier *1973hx509_signature_rsa_with_sha256(void)1974{ return &_hx509_signature_rsa_with_sha256_data; }19751976const AlgorithmIdentifier *1977hx509_signature_rsa_with_sha1(void)1978{ return &_hx509_signature_rsa_with_sha1_data; }19791980const AlgorithmIdentifier *1981hx509_signature_rsa_with_md5(void)1982{ return &_hx509_signature_rsa_with_md5_data; }19831984const AlgorithmIdentifier *1985hx509_signature_rsa(void)1986{ return &_hx509_signature_rsa_data; }19871988const AlgorithmIdentifier *1989hx509_signature_rsa_pkcs1_x509(void)1990{ return &_hx509_signature_rsa_pkcs1_x509_data; }19911992const AlgorithmIdentifier *1993hx509_crypto_des_rsdi_ede3_cbc(void)1994{ return &_hx509_des_rsdi_ede3_cbc_oid; }19951996const AlgorithmIdentifier *1997hx509_crypto_aes128_cbc(void)1998{ return &_hx509_crypto_aes128_cbc_data; }19992000const AlgorithmIdentifier *2001hx509_crypto_aes256_cbc(void)2002{ return &_hx509_crypto_aes256_cbc_data; }20032004/*2005*2006*/20072008const AlgorithmIdentifier * _hx509_crypto_default_sig_alg =2009&_hx509_signature_rsa_with_sha256_data;2010const AlgorithmIdentifier * _hx509_crypto_default_digest_alg =2011&_hx509_signature_sha256_data;2012const AlgorithmIdentifier * _hx509_crypto_default_secret_alg =2013&_hx509_crypto_aes128_cbc_data;20142015/*2016*2017*/20182019int2020hx509_private_key_init(hx509_private_key *key,2021hx509_private_key_ops *ops,2022void *keydata)2023{2024*key = calloc(1, sizeof(**key));2025if (*key == NULL)2026return ENOMEM;2027(*key)->ref = 1;2028(*key)->ops = ops;2029(*key)->private_key.keydata = keydata;2030return 0;2031}20322033hx509_private_key2034_hx509_private_key_ref(hx509_private_key key)2035{2036if (key->ref == 0)2037_hx509_abort("key refcount <= 0 on ref");2038key->ref++;2039if (key->ref == UINT_MAX)2040_hx509_abort("key refcount == UINT_MAX on ref");2041return key;2042}20432044const char *2045_hx509_private_pem_name(hx509_private_key key)2046{2047return key->ops->pemtype;2048}20492050int2051hx509_private_key_free(hx509_private_key *key)2052{2053if (key == NULL || *key == NULL)2054return 0;20552056if ((*key)->ref == 0)2057_hx509_abort("key refcount == 0 on free");2058if (--(*key)->ref > 0)2059return 0;20602061if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {2062if ((*key)->private_key.rsa)2063RSA_free((*key)->private_key.rsa);2064#ifdef HAVE_OPENSSL2065} else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0) {2066if ((*key)->private_key.ecdsa)2067EC_KEY_free((*key)->private_key.ecdsa);2068#endif2069}2070(*key)->private_key.rsa = NULL;2071free(*key);2072*key = NULL;2073return 0;2074}20752076void2077hx509_private_key_assign_rsa(hx509_private_key key, void *ptr)2078{2079if (key->private_key.rsa)2080RSA_free(key->private_key.rsa);2081key->private_key.rsa = ptr;2082key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;2083key->md = &pkcs1_rsa_sha1_alg;2084}20852086int2087_hx509_private_key_oid(hx509_context context,2088const hx509_private_key key,2089heim_oid *data)2090{2091int ret;2092ret = der_copy_oid(key->ops->key_oid, data);2093if (ret)2094hx509_set_error_string(context, 0, ret, "malloc out of memory");2095return ret;2096}20972098int2099_hx509_private_key_exportable(hx509_private_key key)2100{2101if (key->ops->export == NULL)2102return 0;2103return 1;2104}21052106BIGNUM *2107_hx509_private_key_get_internal(hx509_context context,2108hx509_private_key key,2109const char *type)2110{2111if (key->ops->get_internal == NULL)2112return NULL;2113return (*key->ops->get_internal)(context, key, type);2114}21152116int2117_hx509_private_key_export(hx509_context context,2118const hx509_private_key key,2119hx509_key_format_t format,2120heim_octet_string *data)2121{2122if (key->ops->export == NULL) {2123hx509_clear_error_string(context);2124return HX509_UNIMPLEMENTED_OPERATION;2125}2126return (*key->ops->export)(context, key, format, data);2127}21282129/*2130*2131*/21322133struct hx509cipher {2134const char *name;2135int flags;2136#define CIPHER_WEAK 12137const heim_oid *oid;2138const AlgorithmIdentifier *(*ai_func)(void);2139const EVP_CIPHER *(*evp_func)(void);2140int (*get_params)(hx509_context, const hx509_crypto,2141const heim_octet_string *, heim_octet_string *);2142int (*set_params)(hx509_context, const heim_octet_string *,2143hx509_crypto, heim_octet_string *);2144};21452146struct hx509_crypto_data {2147char *name;2148int flags;2149#define ALLOW_WEAK 121502151#define PADDING_NONE 22152#define PADDING_PKCS7 42153#define PADDING_FLAGS (2|4)2154const struct hx509cipher *cipher;2155const EVP_CIPHER *c;2156heim_octet_string key;2157heim_oid oid;2158void *param;2159};21602161/*2162*2163*/21642165static unsigned private_rc2_40_oid_data[] = { 127, 1 };21662167static heim_oid asn1_oid_private_rc2_40 =2168{ 2, private_rc2_40_oid_data };21692170/*2171*2172*/21732174static int2175CMSCBCParam_get(hx509_context context, const hx509_crypto crypto,2176const heim_octet_string *ivec, heim_octet_string *param)2177{2178size_t size;2179int ret;21802181assert(crypto->param == NULL);2182if (ivec == NULL)2183return 0;21842185ASN1_MALLOC_ENCODE(CMSCBCParameter, param->data, param->length,2186ivec, &size, ret);2187if (ret == 0 && size != param->length)2188_hx509_abort("Internal asn1 encoder failure");2189if (ret)2190hx509_clear_error_string(context);2191return ret;2192}21932194static int2195CMSCBCParam_set(hx509_context context, const heim_octet_string *param,2196hx509_crypto crypto, heim_octet_string *ivec)2197{2198int ret;2199if (ivec == NULL)2200return 0;22012202ret = decode_CMSCBCParameter(param->data, param->length, ivec, NULL);2203if (ret)2204hx509_clear_error_string(context);22052206return ret;2207}22082209struct _RC2_params {2210int maximum_effective_key;2211};22122213static int2214CMSRC2CBCParam_get(hx509_context context, const hx509_crypto crypto,2215const heim_octet_string *ivec, heim_octet_string *param)2216{2217CMSRC2CBCParameter rc2params;2218const struct _RC2_params *p = crypto->param;2219int maximum_effective_key = 128;2220size_t size;2221int ret;22222223memset(&rc2params, 0, sizeof(rc2params));22242225if (p)2226maximum_effective_key = p->maximum_effective_key;22272228switch(maximum_effective_key) {2229case 40:2230rc2params.rc2ParameterVersion = 160;2231break;2232case 64:2233rc2params.rc2ParameterVersion = 120;2234break;2235case 128:2236rc2params.rc2ParameterVersion = 58;2237break;2238}2239rc2params.iv = *ivec;22402241ASN1_MALLOC_ENCODE(CMSRC2CBCParameter, param->data, param->length,2242&rc2params, &size, ret);2243if (ret == 0 && size != param->length)2244_hx509_abort("Internal asn1 encoder failure");22452246return ret;2247}22482249static int2250CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,2251hx509_crypto crypto, heim_octet_string *ivec)2252{2253CMSRC2CBCParameter rc2param;2254struct _RC2_params *p;2255size_t size;2256int ret;22572258ret = decode_CMSRC2CBCParameter(param->data, param->length,2259&rc2param, &size);2260if (ret) {2261hx509_clear_error_string(context);2262return ret;2263}22642265p = calloc(1, sizeof(*p));2266if (p == NULL) {2267free_CMSRC2CBCParameter(&rc2param);2268hx509_clear_error_string(context);2269return ENOMEM;2270}2271switch(rc2param.rc2ParameterVersion) {2272case 160:2273crypto->c = EVP_rc2_40_cbc();2274p->maximum_effective_key = 40;2275break;2276case 120:2277crypto->c = EVP_rc2_64_cbc();2278p->maximum_effective_key = 64;2279break;2280case 58:2281crypto->c = EVP_rc2_cbc();2282p->maximum_effective_key = 128;2283break;2284default:2285free(p);2286free_CMSRC2CBCParameter(&rc2param);2287return HX509_CRYPTO_SIG_INVALID_FORMAT;2288}2289if (ivec)2290ret = der_copy_octet_string(&rc2param.iv, ivec);2291free_CMSRC2CBCParameter(&rc2param);2292if (ret) {2293free(p);2294hx509_clear_error_string(context);2295} else2296crypto->param = p;22972298return ret;2299}23002301/*2302*2303*/23042305static const struct hx509cipher ciphers[] = {2306{2307"rc2-cbc",2308CIPHER_WEAK,2309ASN1_OID_ID_PKCS3_RC2_CBC,2310NULL,2311EVP_rc2_cbc,2312CMSRC2CBCParam_get,2313CMSRC2CBCParam_set2314},2315{2316"rc2-cbc",2317CIPHER_WEAK,2318ASN1_OID_ID_RSADSI_RC2_CBC,2319NULL,2320EVP_rc2_cbc,2321CMSRC2CBCParam_get,2322CMSRC2CBCParam_set2323},2324{2325"rc2-40-cbc",2326CIPHER_WEAK,2327&asn1_oid_private_rc2_40,2328NULL,2329EVP_rc2_40_cbc,2330CMSRC2CBCParam_get,2331CMSRC2CBCParam_set2332},2333{2334"des-ede3-cbc",23350,2336ASN1_OID_ID_PKCS3_DES_EDE3_CBC,2337NULL,2338EVP_des_ede3_cbc,2339CMSCBCParam_get,2340CMSCBCParam_set2341},2342{2343"des-ede3-cbc",23440,2345ASN1_OID_ID_RSADSI_DES_EDE3_CBC,2346hx509_crypto_des_rsdi_ede3_cbc,2347EVP_des_ede3_cbc,2348CMSCBCParam_get,2349CMSCBCParam_set2350},2351{2352"aes-128-cbc",23530,2354ASN1_OID_ID_AES_128_CBC,2355hx509_crypto_aes128_cbc,2356EVP_aes_128_cbc,2357CMSCBCParam_get,2358CMSCBCParam_set2359},2360{2361"aes-192-cbc",23620,2363ASN1_OID_ID_AES_192_CBC,2364NULL,2365EVP_aes_192_cbc,2366CMSCBCParam_get,2367CMSCBCParam_set2368},2369{2370"aes-256-cbc",23710,2372ASN1_OID_ID_AES_256_CBC,2373hx509_crypto_aes256_cbc,2374EVP_aes_256_cbc,2375CMSCBCParam_get,2376CMSCBCParam_set2377}2378};23792380static const struct hx509cipher *2381find_cipher_by_oid(const heim_oid *oid)2382{2383size_t i;23842385for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)2386if (der_heim_oid_cmp(oid, ciphers[i].oid) == 0)2387return &ciphers[i];23882389return NULL;2390}23912392static const struct hx509cipher *2393find_cipher_by_name(const char *name)2394{2395size_t i;23962397for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)2398if (strcasecmp(name, ciphers[i].name) == 0)2399return &ciphers[i];24002401return NULL;2402}240324042405const heim_oid *2406hx509_crypto_enctype_by_name(const char *name)2407{2408const struct hx509cipher *cipher;24092410cipher = find_cipher_by_name(name);2411if (cipher == NULL)2412return NULL;2413return cipher->oid;2414}24152416int2417hx509_crypto_init(hx509_context context,2418const char *provider,2419const heim_oid *enctype,2420hx509_crypto *crypto)2421{2422const struct hx509cipher *cipher;24232424*crypto = NULL;24252426cipher = find_cipher_by_oid(enctype);2427if (cipher == NULL) {2428hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,2429"Algorithm not supported");2430return HX509_ALG_NOT_SUPP;2431}24322433*crypto = calloc(1, sizeof(**crypto));2434if (*crypto == NULL) {2435hx509_clear_error_string(context);2436return ENOMEM;2437}24382439(*crypto)->flags = PADDING_PKCS7;2440(*crypto)->cipher = cipher;2441(*crypto)->c = (*cipher->evp_func)();24422443if (der_copy_oid(enctype, &(*crypto)->oid)) {2444hx509_crypto_destroy(*crypto);2445*crypto = NULL;2446hx509_clear_error_string(context);2447return ENOMEM;2448}24492450return 0;2451}24522453const char *2454hx509_crypto_provider(hx509_crypto crypto)2455{2456return "unknown";2457}24582459void2460hx509_crypto_destroy(hx509_crypto crypto)2461{2462if (crypto->name)2463free(crypto->name);2464if (crypto->key.data)2465free(crypto->key.data);2466if (crypto->param)2467free(crypto->param);2468der_free_oid(&crypto->oid);2469memset(crypto, 0, sizeof(*crypto));2470free(crypto);2471}24722473int2474hx509_crypto_set_key_name(hx509_crypto crypto, const char *name)2475{2476return 0;2477}24782479void2480hx509_crypto_allow_weak(hx509_crypto crypto)2481{2482crypto->flags |= ALLOW_WEAK;2483}24842485void2486hx509_crypto_set_padding(hx509_crypto crypto, int padding_type)2487{2488switch (padding_type) {2489case HX509_CRYPTO_PADDING_PKCS7:2490crypto->flags &= ~PADDING_FLAGS;2491crypto->flags |= PADDING_PKCS7;2492break;2493case HX509_CRYPTO_PADDING_NONE:2494crypto->flags &= ~PADDING_FLAGS;2495crypto->flags |= PADDING_NONE;2496break;2497default:2498_hx509_abort("Invalid padding");2499}2500}25012502int2503hx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length)2504{2505if (EVP_CIPHER_key_length(crypto->c) > (int)length)2506return HX509_CRYPTO_INTERNAL_ERROR;25072508if (crypto->key.data) {2509free(crypto->key.data);2510crypto->key.data = NULL;2511crypto->key.length = 0;2512}2513crypto->key.data = malloc(length);2514if (crypto->key.data == NULL)2515return ENOMEM;2516memcpy(crypto->key.data, data, length);2517crypto->key.length = length;25182519return 0;2520}25212522int2523hx509_crypto_set_random_key(hx509_crypto crypto, heim_octet_string *key)2524{2525if (crypto->key.data) {2526free(crypto->key.data);2527crypto->key.length = 0;2528}25292530crypto->key.length = EVP_CIPHER_key_length(crypto->c);2531crypto->key.data = malloc(crypto->key.length);2532if (crypto->key.data == NULL) {2533crypto->key.length = 0;2534return ENOMEM;2535}2536if (RAND_bytes(crypto->key.data, crypto->key.length) <= 0) {2537free(crypto->key.data);2538crypto->key.data = NULL;2539crypto->key.length = 0;2540return HX509_CRYPTO_INTERNAL_ERROR;2541}2542if (key)2543return der_copy_octet_string(&crypto->key, key);2544else2545return 0;2546}25472548int2549hx509_crypto_set_params(hx509_context context,2550hx509_crypto crypto,2551const heim_octet_string *param,2552heim_octet_string *ivec)2553{2554return (*crypto->cipher->set_params)(context, param, crypto, ivec);2555}25562557int2558hx509_crypto_get_params(hx509_context context,2559hx509_crypto crypto,2560const heim_octet_string *ivec,2561heim_octet_string *param)2562{2563return (*crypto->cipher->get_params)(context, crypto, ivec, param);2564}25652566int2567hx509_crypto_random_iv(hx509_crypto crypto, heim_octet_string *ivec)2568{2569ivec->length = EVP_CIPHER_iv_length(crypto->c);2570ivec->data = malloc(ivec->length);2571if (ivec->data == NULL) {2572ivec->length = 0;2573return ENOMEM;2574}25752576if (RAND_bytes(ivec->data, ivec->length) <= 0) {2577free(ivec->data);2578ivec->data = NULL;2579ivec->length = 0;2580return HX509_CRYPTO_INTERNAL_ERROR;2581}2582return 0;2583}25842585int2586hx509_crypto_encrypt(hx509_crypto crypto,2587const void *data,2588const size_t length,2589const heim_octet_string *ivec,2590heim_octet_string **ciphertext)2591{2592EVP_CIPHER_CTX *evp;2593size_t padsize, bsize;2594int ret;25952596*ciphertext = NULL;25972598if ((crypto->cipher->flags & CIPHER_WEAK) &&2599(crypto->flags & ALLOW_WEAK) == 0)2600return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;26012602assert(EVP_CIPHER_iv_length(crypto->c) == (int)ivec->length);26032604evp = EVP_CIPHER_CTX_new();2605if (evp == NULL)2606return ENOMEM;26072608ret = EVP_CipherInit_ex(evp, crypto->c, NULL,2609crypto->key.data, ivec->data, 1);2610if (ret != 1) {2611ret = HX509_CRYPTO_INTERNAL_ERROR;2612goto out;2613}26142615*ciphertext = calloc(1, sizeof(**ciphertext));2616if (*ciphertext == NULL) {2617ret = ENOMEM;2618goto out;2619}26202621assert(crypto->flags & PADDING_FLAGS);26222623bsize = EVP_CIPHER_block_size(crypto->c);2624padsize = 0;26252626if (crypto->flags & PADDING_NONE) {2627if (bsize != 1 && (length % bsize) != 0)2628return HX509_CMS_PADDING_ERROR;2629} else if (crypto->flags & PADDING_PKCS7) {2630if (bsize != 1)2631padsize = bsize - (length % bsize);2632}26332634(*ciphertext)->length = length + padsize;2635(*ciphertext)->data = malloc(length + padsize);2636if ((*ciphertext)->data == NULL) {2637ret = ENOMEM;2638goto out;2639}26402641memcpy((*ciphertext)->data, data, length);2642if (padsize) {2643size_t i;2644unsigned char *p = (*ciphertext)->data;2645p += length;2646for (i = 0; i < padsize; i++)2647*p++ = padsize;2648}26492650ret = EVP_Cipher(evp, (*ciphertext)->data,2651(*ciphertext)->data,2652length + padsize);2653if (ret != 1) {2654ret = HX509_CRYPTO_INTERNAL_ERROR;2655goto out;2656}2657ret = 0;26582659out:2660if (ret) {2661if (*ciphertext) {2662if ((*ciphertext)->data) {2663free((*ciphertext)->data);2664}2665free(*ciphertext);2666*ciphertext = NULL;2667}2668}2669EVP_CIPHER_CTX_free(evp);26702671return ret;2672}26732674int2675hx509_crypto_decrypt(hx509_crypto crypto,2676const void *data,2677const size_t length,2678heim_octet_string *ivec,2679heim_octet_string *clear)2680{2681EVP_CIPHER_CTX *evp;2682void *idata = NULL;2683int ret;26842685clear->data = NULL;2686clear->length = 0;26872688if ((crypto->cipher->flags & CIPHER_WEAK) &&2689(crypto->flags & ALLOW_WEAK) == 0)2690return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;26912692if (ivec && EVP_CIPHER_iv_length(crypto->c) < (int)ivec->length)2693return HX509_CRYPTO_INTERNAL_ERROR;26942695if (crypto->key.data == NULL)2696return HX509_CRYPTO_INTERNAL_ERROR;26972698if (ivec)2699idata = ivec->data;27002701evp = EVP_CIPHER_CTX_new();2702if (evp == NULL)2703return ENOMEM;27042705ret = EVP_CipherInit_ex(evp, crypto->c, NULL,2706crypto->key.data, idata, 0);2707if (ret != 1) {2708EVP_CIPHER_CTX_free(evp);2709return HX509_CRYPTO_INTERNAL_ERROR;2710}27112712clear->length = length;2713clear->data = malloc(length);2714if (clear->data == NULL) {2715EVP_CIPHER_CTX_free(evp);2716clear->length = 0;2717return ENOMEM;2718}27192720if (EVP_Cipher(evp, clear->data, data, length) != 1) {2721EVP_CIPHER_CTX_free(evp);2722return HX509_CRYPTO_INTERNAL_ERROR;2723}2724EVP_CIPHER_CTX_free(evp);27252726if ((crypto->flags & PADDING_PKCS7) && EVP_CIPHER_block_size(crypto->c) > 1) {2727int padsize;2728unsigned char *p;2729int j, bsize = EVP_CIPHER_block_size(crypto->c);27302731if ((int)clear->length < bsize) {2732ret = HX509_CMS_PADDING_ERROR;2733goto out;2734}27352736p = clear->data;2737p += clear->length - 1;2738padsize = *p;2739if (padsize > bsize) {2740ret = HX509_CMS_PADDING_ERROR;2741goto out;2742}2743clear->length -= padsize;2744for (j = 0; j < padsize; j++) {2745if (*p-- != padsize) {2746ret = HX509_CMS_PADDING_ERROR;2747goto out;2748}2749}2750}27512752return 0;27532754out:2755if (clear->data)2756free(clear->data);2757clear->data = NULL;2758clear->length = 0;2759return ret;2760}27612762typedef int (*PBE_string2key_func)(hx509_context,2763const char *,2764const heim_octet_string *,2765hx509_crypto *, heim_octet_string *,2766heim_octet_string *,2767const heim_oid *, const EVP_MD *);27682769static int2770PBE_string2key(hx509_context context,2771const char *password,2772const heim_octet_string *parameters,2773hx509_crypto *crypto,2774heim_octet_string *key, heim_octet_string *iv,2775const heim_oid *enc_oid,2776const EVP_MD *md)2777{2778PKCS12_PBEParams p12params;2779int passwordlen;2780hx509_crypto c;2781int iter, saltlen, ret;2782unsigned char *salt;27832784passwordlen = password ? strlen(password) : 0;27852786if (parameters == NULL)2787return HX509_ALG_NOT_SUPP;27882789ret = decode_PKCS12_PBEParams(parameters->data,2790parameters->length,2791&p12params, NULL);2792if (ret)2793goto out;27942795if (p12params.iterations)2796iter = *p12params.iterations;2797else2798iter = 1;2799salt = p12params.salt.data;2800saltlen = p12params.salt.length;28012802if (!PKCS12_key_gen (password, passwordlen, salt, saltlen,2803PKCS12_KEY_ID, iter, key->length, key->data, md)) {2804ret = HX509_CRYPTO_INTERNAL_ERROR;2805goto out;2806}28072808if (!PKCS12_key_gen (password, passwordlen, salt, saltlen,2809PKCS12_IV_ID, iter, iv->length, iv->data, md)) {2810ret = HX509_CRYPTO_INTERNAL_ERROR;2811goto out;2812}28132814ret = hx509_crypto_init(context, NULL, enc_oid, &c);2815if (ret)2816goto out;28172818hx509_crypto_allow_weak(c);28192820ret = hx509_crypto_set_key_data(c, key->data, key->length);2821if (ret) {2822hx509_crypto_destroy(c);2823goto out;2824}28252826*crypto = c;2827out:2828free_PKCS12_PBEParams(&p12params);2829return ret;2830}28312832static const heim_oid *2833find_string2key(const heim_oid *oid,2834const EVP_CIPHER **c,2835const EVP_MD **md,2836PBE_string2key_func *s2k)2837{2838if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC2_CBC) == 0) {2839*c = EVP_rc2_40_cbc();2840*md = EVP_sha1();2841*s2k = PBE_string2key;2842return &asn1_oid_private_rc2_40;2843} else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC2_CBC) == 0) {2844*c = EVP_rc2_cbc();2845*md = EVP_sha1();2846*s2k = PBE_string2key;2847return ASN1_OID_ID_PKCS3_RC2_CBC;2848#if 02849} else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC4) == 0) {2850*c = EVP_rc4_40();2851*md = EVP_sha1();2852*s2k = PBE_string2key;2853return NULL;2854} else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC4) == 0) {2855*c = EVP_rc4();2856*md = EVP_sha1();2857*s2k = PBE_string2key;2858return ASN1_OID_ID_PKCS3_RC4;2859#endif2860} else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND3_KEYTRIPLEDES_CBC) == 0) {2861*c = EVP_des_ede3_cbc();2862*md = EVP_sha1();2863*s2k = PBE_string2key;2864return ASN1_OID_ID_PKCS3_DES_EDE3_CBC;2865}28662867return NULL;2868}28692870/*2871*2872*/28732874int2875_hx509_pbe_encrypt(hx509_context context,2876hx509_lock lock,2877const AlgorithmIdentifier *ai,2878const heim_octet_string *content,2879heim_octet_string *econtent)2880{2881hx509_clear_error_string(context);2882return EINVAL;2883}28842885/*2886*2887*/28882889int2890_hx509_pbe_decrypt(hx509_context context,2891hx509_lock lock,2892const AlgorithmIdentifier *ai,2893const heim_octet_string *econtent,2894heim_octet_string *content)2895{2896const struct _hx509_password *pw;2897heim_octet_string key, iv;2898const heim_oid *enc_oid;2899const EVP_CIPHER *c;2900const EVP_MD *md;2901PBE_string2key_func s2k;2902int ret = 0;2903size_t i;29042905memset(&key, 0, sizeof(key));2906memset(&iv, 0, sizeof(iv));29072908memset(content, 0, sizeof(*content));29092910enc_oid = find_string2key(&ai->algorithm, &c, &md, &s2k);2911if (enc_oid == NULL) {2912hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,2913"String to key algorithm not supported");2914ret = HX509_ALG_NOT_SUPP;2915goto out;2916}29172918key.length = EVP_CIPHER_key_length(c);2919key.data = malloc(key.length);2920if (key.data == NULL) {2921ret = ENOMEM;2922hx509_clear_error_string(context);2923goto out;2924}29252926iv.length = EVP_CIPHER_iv_length(c);2927iv.data = malloc(iv.length);2928if (iv.data == NULL) {2929ret = ENOMEM;2930hx509_clear_error_string(context);2931goto out;2932}29332934pw = _hx509_lock_get_passwords(lock);29352936ret = HX509_CRYPTO_INTERNAL_ERROR;2937for (i = 0; i < pw->len + 1; i++) {2938hx509_crypto crypto;2939const char *password;29402941if (i < pw->len)2942password = pw->val[i];2943else if (i < pw->len + 1)2944password = "";2945else2946password = NULL;29472948ret = (*s2k)(context, password, ai->parameters, &crypto,2949&key, &iv, enc_oid, md);2950if (ret)2951goto out;29522953ret = hx509_crypto_decrypt(crypto,2954econtent->data,2955econtent->length,2956&iv,2957content);2958hx509_crypto_destroy(crypto);2959if (ret == 0)2960goto out;29612962}2963out:2964if (key.data)2965der_free_octet_string(&key);2966if (iv.data)2967der_free_octet_string(&iv);2968return ret;2969}29702971/*2972*2973*/297429752976static int2977match_keys_rsa(hx509_cert c, hx509_private_key private_key)2978{2979const Certificate *cert;2980const SubjectPublicKeyInfo *spi;2981RSAPublicKey pk;2982RSA *rsa;2983const BIGNUM *d, *p, *q, *dmp1, *dmq1, *iqmp;2984BIGNUM *new_d, *new_p, *new_q, *new_dmp1, *new_dmq1, *new_iqmp, *n, *e;2985size_t size;2986int ret;29872988if (private_key->private_key.rsa == NULL)2989return 0;29902991rsa = private_key->private_key.rsa;2992RSA_get0_key(rsa, NULL, NULL, &d);2993RSA_get0_factors(rsa, &p, &q);2994RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);2995if (d == NULL || p == NULL || q == NULL)2996return 0;29972998cert = _hx509_get_cert(c);2999spi = &cert->tbsCertificate.subjectPublicKeyInfo;30003001rsa = RSA_new();3002if (rsa == NULL)3003return 0;30043005ret = decode_RSAPublicKey(spi->subjectPublicKey.data,3006spi->subjectPublicKey.length / 8,3007&pk, &size);3008if (ret) {3009RSA_free(rsa);3010return 0;3011}3012n = heim_int2BN(&pk.modulus);3013e = heim_int2BN(&pk.publicExponent);30143015free_RSAPublicKey(&pk);30163017new_d = BN_dup(d);3018new_p = BN_dup(p);3019new_q = BN_dup(q);3020new_dmp1 = BN_dup(dmp1);3021new_dmq1 = BN_dup(dmq1);3022new_iqmp = BN_dup(iqmp);30233024if (n == NULL || e == NULL ||3025new_d == NULL || new_p == NULL|| new_q == NULL ||3026new_dmp1 == NULL || new_dmq1 == NULL || new_iqmp == NULL) {3027BN_free(n);3028BN_free(e);3029BN_free(new_d);3030BN_free(new_p);3031BN_free(new_q);3032BN_free(new_dmp1);3033BN_free(new_dmq1);3034BN_free(new_iqmp);3035RSA_free(rsa);3036return 0;3037}30383039ret = RSA_set0_key(rsa, new_d, n, e);30403041if (ret != 1) {3042BN_free(n);3043BN_free(e);3044BN_free(new_d);3045BN_free(new_p);3046BN_free(new_q);3047BN_free(new_dmp1);3048BN_free(new_dmq1);3049BN_free(new_iqmp);3050RSA_free(rsa);3051return 0;3052}30533054ret = RSA_set0_factors(rsa, new_p, new_q);30553056if (ret != 1) {3057BN_free(new_p);3058BN_free(new_q);3059BN_free(new_dmp1);3060BN_free(new_dmq1);3061BN_free(new_iqmp);3062RSA_free(rsa);3063return 0;3064}30653066ret = RSA_set0_crt_params(rsa, new_dmp1, new_dmq1, new_iqmp);30673068if (ret != 1) {3069BN_free(new_dmp1);3070BN_free(new_dmq1);3071BN_free(new_iqmp);3072RSA_free(rsa);3073return 0;3074}30753076ret = RSA_check_key(rsa);3077RSA_free(rsa);30783079return ret == 1;3080}30813082static int3083match_keys_ec(hx509_cert c, hx509_private_key private_key)3084{3085return 1; /* XXX use EC_KEY_check_key */3086}308730883089int3090_hx509_match_keys(hx509_cert c, hx509_private_key key)3091{3092if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0)3093return match_keys_rsa(c, key);3094if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0)3095return match_keys_ec(c, key);3096return 0;30973098}309931003101static const heim_oid *3102find_keytype(const hx509_private_key key)3103{3104const struct signature_alg *md;31053106if (key == NULL)3107return NULL;31083109md = find_sig_alg(key->signature_alg);3110if (md == NULL)3111return NULL;3112return md->key_oid;3113}31143115int3116hx509_crypto_select(const hx509_context context,3117int type,3118const hx509_private_key source,3119hx509_peer_info peer,3120AlgorithmIdentifier *selected)3121{3122const AlgorithmIdentifier *def = NULL;3123size_t i, j;3124int ret, bits;31253126memset(selected, 0, sizeof(*selected));31273128if (type == HX509_SELECT_DIGEST) {3129bits = SIG_DIGEST;3130if (source)3131def = alg_for_privatekey(source, type);3132if (def == NULL)3133def = _hx509_crypto_default_digest_alg;3134} else if (type == HX509_SELECT_PUBLIC_SIG) {3135bits = SIG_PUBLIC_SIG;3136/* XXX depend on `sourceĀ“ and `peerĀ“ */3137if (source)3138def = alg_for_privatekey(source, type);3139if (def == NULL)3140def = _hx509_crypto_default_sig_alg;3141} else if (type == HX509_SELECT_SECRET_ENC) {3142bits = SIG_SECRET;3143def = _hx509_crypto_default_secret_alg;3144} else {3145hx509_set_error_string(context, 0, EINVAL,3146"Unknown type %d of selection", type);3147return EINVAL;3148}31493150if (peer) {3151const heim_oid *keytype = NULL;31523153keytype = find_keytype(source);31543155for (i = 0; i < peer->len; i++) {3156for (j = 0; sig_algs[j]; j++) {3157if ((sig_algs[j]->flags & bits) != bits)3158continue;3159if (der_heim_oid_cmp(sig_algs[j]->sig_oid,3160&peer->val[i].algorithm) != 0)3161continue;3162if (keytype && sig_algs[j]->key_oid &&3163der_heim_oid_cmp(keytype, sig_algs[j]->key_oid))3164continue;31653166/* found one, use that */3167ret = copy_AlgorithmIdentifier(&peer->val[i], selected);3168if (ret)3169hx509_clear_error_string(context);3170return ret;3171}3172if (bits & SIG_SECRET) {3173const struct hx509cipher *cipher;31743175cipher = find_cipher_by_oid(&peer->val[i].algorithm);3176if (cipher == NULL)3177continue;3178if (cipher->ai_func == NULL)3179continue;3180ret = copy_AlgorithmIdentifier(cipher->ai_func(), selected);3181if (ret)3182hx509_clear_error_string(context);3183return ret;3184}3185}3186}31873188/* use default */3189ret = copy_AlgorithmIdentifier(def, selected);3190if (ret)3191hx509_clear_error_string(context);3192return ret;3193}31943195int3196hx509_crypto_available(hx509_context context,3197int type,3198hx509_cert source,3199AlgorithmIdentifier **val,3200unsigned int *plen)3201{3202const heim_oid *keytype = NULL;3203unsigned int len, i;3204void *ptr;3205int bits, ret;32063207*val = NULL;32083209if (type == HX509_SELECT_ALL) {3210bits = SIG_DIGEST | SIG_PUBLIC_SIG | SIG_SECRET;3211} else if (type == HX509_SELECT_DIGEST) {3212bits = SIG_DIGEST;3213} else if (type == HX509_SELECT_PUBLIC_SIG) {3214bits = SIG_PUBLIC_SIG;3215} else {3216hx509_set_error_string(context, 0, EINVAL,3217"Unknown type %d of available", type);3218return EINVAL;3219}32203221if (source)3222keytype = find_keytype(_hx509_cert_private_key(source));32233224len = 0;3225for (i = 0; sig_algs[i]; i++) {3226if ((sig_algs[i]->flags & bits) == 0)3227continue;3228if (sig_algs[i]->sig_alg == NULL)3229continue;3230if (keytype && sig_algs[i]->key_oid &&3231der_heim_oid_cmp(sig_algs[i]->key_oid, keytype))3232continue;32333234/* found one, add that to the list */3235ptr = realloc(*val, sizeof(**val) * (len + 1));3236if (ptr == NULL)3237goto out;3238*val = ptr;32393240ret = copy_AlgorithmIdentifier(sig_algs[i]->sig_alg, &(*val)[len]);3241if (ret)3242goto out;3243len++;3244}32453246/* Add AES */3247if (bits & SIG_SECRET) {32483249for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) {32503251if (ciphers[i].flags & CIPHER_WEAK)3252continue;3253if (ciphers[i].ai_func == NULL)3254continue;32553256ptr = realloc(*val, sizeof(**val) * (len + 1));3257if (ptr == NULL)3258goto out;3259*val = ptr;32603261ret = copy_AlgorithmIdentifier((ciphers[i].ai_func)(), &(*val)[len]);3262if (ret)3263goto out;3264len++;3265}3266}32673268*plen = len;3269return 0;32703271out:3272for (i = 0; i < len; i++)3273free_AlgorithmIdentifier(&(*val)[i]);3274free(*val);3275*val = NULL;3276hx509_set_error_string(context, 0, ENOMEM, "out of memory");3277return ENOMEM;3278}32793280void3281hx509_crypto_free_algs(AlgorithmIdentifier *val,3282unsigned int len)3283{3284unsigned int i;3285for (i = 0; i < len; i++)3286free_AlgorithmIdentifier(&val[i]);3287free(val);3288}328932903291