LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/hx509 - crypto.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 116 1175 9.9 %
Date: 2024-06-13 04:01:37 Functions: 14 84 16.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2004 - 2016 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include "hx_locl.h"
      35             : 
      36             : /*-
      37             :  * RFC5758 specifies no parameters for ecdsa-with-SHA<N> signatures
      38             :  * RFC5754 specifies NULL parameters for sha<N>WithRSAEncryption signatures
      39             :  *
      40             :  * XXX: Make sure that the parameters are either NULL in both the tbs and the
      41             :  * signature, or absent from both the tbs and the signature.
      42             :  */
      43             : 
      44             : static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };
      45             : 
      46             : static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
      47             : const AlgorithmIdentifier _hx509_signature_sha512_data = {
      48             :     { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid)
      49             : };
      50             : 
      51             : static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
      52             : const AlgorithmIdentifier _hx509_signature_sha384_data = {
      53             :     { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid)
      54             : };
      55             : 
      56             : static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
      57             : const AlgorithmIdentifier _hx509_signature_sha256_data = {
      58             :     { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
      59             : };
      60             : 
      61             : static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
      62             : const AlgorithmIdentifier _hx509_signature_sha1_data = {
      63             :     { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid)
      64             : };
      65             : 
      66             : static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 };
      67             : const AlgorithmIdentifier _hx509_signature_md5_data = {
      68             :     { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
      69             : };
      70             : 
      71             : static const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 };
      72             : const AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = {
      73             :     { 7, rk_UNCONST(rsa_with_sha512_oid) }, rk_UNCONST(&null_entry_oid)
      74             : };
      75             : 
      76             : static const unsigned rsa_with_sha384_oid[] ={ 1, 2, 840, 113549, 1, 1, 12 };
      77             : const AlgorithmIdentifier _hx509_signature_rsa_with_sha384_data = {
      78             :     { 7, rk_UNCONST(rsa_with_sha384_oid) }, rk_UNCONST(&null_entry_oid)
      79             : };
      80             : 
      81             : static const unsigned rsa_with_sha256_oid[] ={ 1, 2, 840, 113549, 1, 1, 11 };
      82             : const AlgorithmIdentifier _hx509_signature_rsa_with_sha256_data = {
      83             :     { 7, rk_UNCONST(rsa_with_sha256_oid) }, rk_UNCONST(&null_entry_oid)
      84             : };
      85             : 
      86             : static const unsigned rsa_with_sha1_oid[] ={ 1, 2, 840, 113549, 1, 1, 5 };
      87             : const AlgorithmIdentifier _hx509_signature_rsa_with_sha1_data = {
      88             :     { 7, rk_UNCONST(rsa_with_sha1_oid) }, rk_UNCONST(&null_entry_oid)
      89             : };
      90             : 
      91             : static const unsigned rsa_with_md5_oid[] ={ 1, 2, 840, 113549, 1, 1, 4 };
      92             : const AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = {
      93             :     { 7, rk_UNCONST(rsa_with_md5_oid) }, rk_UNCONST(&null_entry_oid)
      94             : };
      95             : 
      96             : static const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 };
      97             : const AlgorithmIdentifier _hx509_signature_rsa_data = {
      98             :     { 7, rk_UNCONST(rsa_oid) }, NULL
      99             : };
     100             : 
     101             : static const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 };
     102             : const AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = {
     103             :     { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL
     104             : };
     105             : 
     106             : static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 };
     107             : const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = {
     108             :     { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL
     109             : };
     110             : 
     111             : static const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 };
     112             : const AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = {
     113             :     { 9, rk_UNCONST(aes128_cbc_oid) }, NULL
     114             : };
     115             : 
     116             : static const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 };
     117             : const AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = {
     118             :     { 9, rk_UNCONST(aes256_cbc_oid) }, NULL
     119             : };
     120             : 
     121             : /*
     122             :  *
     123             :  */
     124             : 
     125             : static BIGNUM *
     126          76 : heim_int2BN(const heim_integer *i)
     127             : {
     128             :     BIGNUM *bn;
     129             : 
     130          76 :     bn = BN_bin2bn(i->data, i->length, NULL);
     131          76 :     BN_set_negative(bn, i->negative);
     132          76 :     return bn;
     133             : }
     134             : 
     135             : /*
     136             :  *
     137             :  */
     138             : 
     139             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     140           0 : _hx509_set_digest_alg(DigestAlgorithmIdentifier *id,
     141             :                       const heim_oid *oid,
     142             :                       const void *param, size_t length)
     143             : {
     144             :     int ret;
     145           0 :     if (param) {
     146           0 :         id->parameters = malloc(sizeof(*id->parameters));
     147           0 :         if (id->parameters == NULL)
     148           0 :             return ENOMEM;
     149           0 :         id->parameters->data = malloc(length);
     150           0 :         if (id->parameters->data == NULL) {
     151           0 :             free(id->parameters);
     152           0 :             id->parameters = NULL;
     153           0 :             return ENOMEM;
     154             :         }
     155           0 :         memcpy(id->parameters->data, param, length);
     156           0 :         id->parameters->length = length;
     157             :     } else
     158           0 :         id->parameters = NULL;
     159           0 :     ret = der_copy_oid(oid, &id->algorithm);
     160           0 :     if (ret) {
     161           0 :         if (id->parameters) {
     162           0 :             free(id->parameters->data);
     163           0 :             free(id->parameters);
     164           0 :             id->parameters = NULL;
     165             :         }
     166           0 :         return ret;
     167             :     }
     168           0 :     return 0;
     169             : }
     170             : 
     171             : /*
     172             :  *
     173             :  */
     174             : 
     175             : static int
     176           0 : rsa_verify_signature(hx509_context context,
     177             :                      const struct signature_alg *sig_alg,
     178             :                      const Certificate *signer,
     179             :                      const AlgorithmIdentifier *alg,
     180             :                      const heim_octet_string *data,
     181             :                      const heim_octet_string *sig)
     182             : {
     183             :     const SubjectPublicKeyInfo *spi;
     184             :     DigestInfo di;
     185             :     unsigned char *to;
     186             :     int tosize, retsize;
     187             :     int ret;
     188             :     RSA *rsa;
     189             :     size_t size;
     190             :     const unsigned char *p;
     191             : 
     192           0 :     memset(&di, 0, sizeof(di));
     193             : 
     194           0 :     spi = &signer->tbsCertificate.subjectPublicKeyInfo;
     195             : 
     196           0 :     p = spi->subjectPublicKey.data;
     197           0 :     size = spi->subjectPublicKey.length / 8;
     198             : 
     199           0 :     rsa = d2i_RSAPublicKey(NULL, &p, size);
     200           0 :     if (rsa == NULL) {
     201           0 :         ret = ENOMEM;
     202           0 :         hx509_set_error_string(context, 0, ret, "out of memory");
     203           0 :         goto out;
     204             :     }
     205             : 
     206           0 :     tosize = RSA_size(rsa);
     207           0 :     to = malloc(tosize);
     208           0 :     if (to == NULL) {
     209           0 :         ret = ENOMEM;
     210           0 :         hx509_set_error_string(context, 0, ret, "out of memory");
     211           0 :         goto out;
     212             :     }
     213             : 
     214           0 :     retsize = RSA_public_decrypt(sig->length, (unsigned char *)sig->data,
     215             :                                  to, rsa, RSA_PKCS1_PADDING);
     216           0 :     if (retsize <= 0) {
     217           0 :         ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
     218           0 :         hx509_set_error_string(context, 0, ret,
     219             :                                "RSA public decrypt failed: %d", retsize);
     220           0 :         free(to);
     221           0 :         goto out;
     222             :     }
     223           0 :     if (retsize > tosize)
     224           0 :         _hx509_abort("internal rsa decryption failure: ret > tosize");
     225             : 
     226           0 :     if (sig_alg->flags & RA_RSA_USES_DIGEST_INFO) {
     227             : 
     228           0 :         ret = decode_DigestInfo(to, retsize, &di, &size);
     229           0 :         free(to);
     230           0 :         if (ret) {
     231           0 :             goto out;
     232             :         }
     233             : 
     234             :         /* Check for extra data inside the sigature */
     235           0 :         if (size != (size_t)retsize) {
     236           0 :             ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
     237           0 :             hx509_set_error_string(context, 0, ret, "size from decryption mismatch");
     238           0 :             goto out;
     239             :         }
     240             : 
     241           0 :         if (sig_alg->digest_alg &&
     242           0 :             der_heim_oid_cmp(&di.digestAlgorithm.algorithm,
     243           0 :                              &sig_alg->digest_alg->algorithm) != 0)
     244             :         {
     245           0 :             ret = HX509_CRYPTO_OID_MISMATCH;
     246           0 :             hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch");
     247           0 :             goto out;
     248             :         }
     249             : 
     250             :         /* verify that the parameters are NULL or the NULL-type */
     251           0 :         if (di.digestAlgorithm.parameters != NULL &&
     252           0 :             (di.digestAlgorithm.parameters->length != 2 ||
     253           0 :              memcmp(di.digestAlgorithm.parameters->data, "\x05\x00", 2) != 0))
     254             :         {
     255           0 :             ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
     256           0 :             hx509_set_error_string(context, 0, ret, "Extra parameters inside RSA signature");
     257           0 :             goto out;
     258             :         }
     259             : 
     260           0 :         ret = _hx509_verify_signature(context,
     261             :                                       NULL,
     262             :                                       &di.digestAlgorithm,
     263             :                                       data,
     264             :                                       &di.digest);
     265           0 :         if (ret)
     266           0 :             goto out;
     267             : 
     268             :     } else {
     269           0 :         if ((size_t)retsize != data->length ||
     270           0 :             ct_memcmp(to, data->data, retsize) != 0)
     271             :         {
     272           0 :             ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
     273           0 :             hx509_set_error_string(context, 0, ret, "RSA Signature incorrect");
     274           0 :             goto out;
     275             :         }
     276           0 :         free(to);
     277           0 :         ret = 0;
     278             :     }
     279             : 
     280           0 :  out:
     281           0 :     free_DigestInfo(&di);
     282           0 :     if (rsa)
     283           0 :         RSA_free(rsa);
     284           0 :     return ret;
     285             : }
     286             : 
     287             : static int
     288           0 : rsa_create_signature(hx509_context context,
     289             :                      const struct signature_alg *sig_alg,
     290             :                      const hx509_private_key signer,
     291             :                      const AlgorithmIdentifier *alg,
     292             :                      const heim_octet_string *data,
     293             :                      AlgorithmIdentifier *signatureAlgorithm,
     294             :                      heim_octet_string *sig)
     295             : {
     296             :     const AlgorithmIdentifier *digest_alg;
     297             :     heim_octet_string indata;
     298             :     const heim_oid *sig_oid;
     299             :     size_t size;
     300             :     int ret;
     301             : 
     302           0 :     if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0)
     303           0 :         return HX509_ALG_NOT_SUPP;
     304             : 
     305           0 :     if (alg)
     306           0 :         sig_oid = &alg->algorithm;
     307             :     else
     308           0 :         sig_oid = signer->signature_alg;
     309             : 
     310           0 :     if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION) == 0) {
     311           0 :         digest_alg = hx509_signature_sha512();
     312           0 :     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION) == 0) {
     313           0 :         digest_alg = hx509_signature_sha384();
     314           0 :     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION) == 0) {
     315           0 :         digest_alg = hx509_signature_sha256();
     316           0 :     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION) == 0) {
     317           0 :         digest_alg = hx509_signature_sha1();
     318           0 :     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) {
     319           0 :         digest_alg = hx509_signature_md5();
     320           0 :     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) {
     321           0 :         digest_alg = hx509_signature_md5();
     322           0 :     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_DSA_WITH_SHA1) == 0) {
     323           0 :         digest_alg = hx509_signature_sha1();
     324           0 :     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {
     325           0 :         digest_alg = hx509_signature_sha1();
     326           0 :     } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_HEIM_RSA_PKCS1_X509) == 0) {
     327           0 :         digest_alg = NULL;
     328             :     } else
     329           0 :         return HX509_ALG_NOT_SUPP;
     330             : 
     331           0 :     if (signatureAlgorithm) {
     332           0 :         ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid,
     333             :                                     "\x05\x00", 2);
     334           0 :         if (ret) {
     335           0 :             hx509_clear_error_string(context);
     336           0 :             return ret;
     337             :         }
     338             :     }
     339             : 
     340           0 :     if (digest_alg) {
     341             :         DigestInfo di;
     342           0 :         memset(&di, 0, sizeof(di));
     343             : 
     344           0 :         ret = _hx509_create_signature(context,
     345             :                                       NULL,
     346             :                                       digest_alg,
     347             :                                       data,
     348             :                                       &di.digestAlgorithm,
     349             :                                       &di.digest);
     350           0 :         if (ret)
     351           0 :             return ret;
     352           0 :         ASN1_MALLOC_ENCODE(DigestInfo,
     353             :                            indata.data,
     354             :                            indata.length,
     355             :                            &di,
     356             :                            &size,
     357             :                            ret);
     358           0 :         free_DigestInfo(&di);
     359           0 :         if (ret) {
     360           0 :             hx509_set_error_string(context, 0, ret, "out of memory");
     361           0 :             return ret;
     362             :         }
     363           0 :         if (indata.length != size)
     364           0 :             _hx509_abort("internal ASN.1 encoder error");
     365             :     } else {
     366           0 :         indata = *data;
     367             :     }
     368             : 
     369           0 :     sig->length = RSA_size(signer->private_key.rsa);
     370           0 :     sig->data = malloc(sig->length);
     371           0 :     if (sig->data == NULL) {
     372           0 :         der_free_octet_string(&indata);
     373           0 :         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
     374           0 :         return ENOMEM;
     375             :     }
     376             : 
     377           0 :     ret = RSA_private_encrypt(indata.length, indata.data,
     378           0 :                               sig->data,
     379             :                               signer->private_key.rsa,
     380             :                               RSA_PKCS1_PADDING);
     381           0 :     if (indata.data != data->data)
     382           0 :         der_free_octet_string(&indata);
     383           0 :     if (ret <= 0) {
     384           0 :         ret = HX509_CMS_FAILED_CREATE_SIGATURE;
     385           0 :         hx509_set_error_string(context, 0, ret,
     386             :                                "RSA private encrypt failed: %d", ret);
     387           0 :         return ret;
     388             :     }
     389           0 :     if (sig->length > (size_t)ret) {
     390           0 :         size = sig->length - ret;
     391           0 :         memmove((uint8_t *)sig->data + size, sig->data, ret);
     392           0 :         memset(sig->data, 0, size);
     393           0 :     } else if (sig->length < (size_t)ret)
     394           0 :         _hx509_abort("RSA signature prelen longer the output len");
     395             : 
     396           0 :     return 0;
     397             : }
     398             : 
     399             : static int
     400          38 : rsa_private_key_import(hx509_context context,
     401             :                        const AlgorithmIdentifier *keyai,
     402             :                        const void *data,
     403             :                        size_t len,
     404             :                        hx509_key_format_t format,
     405             :                        hx509_private_key private_key)
     406             : {
     407          38 :     switch (format) {
     408          38 :     case HX509_KEY_FORMAT_DER: {
     409          38 :         const unsigned char *p = data;
     410             : 
     411          38 :         private_key->private_key.rsa =
     412          38 :             d2i_RSAPrivateKey(NULL, &p, len);
     413          38 :         if (private_key->private_key.rsa == NULL) {
     414           0 :             hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
     415             :                                    "Failed to parse RSA key");
     416           0 :             return HX509_PARSING_KEY_FAILED;
     417             :         }
     418          38 :         private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
     419          38 :         break;
     420             : 
     421             :     }
     422           0 :     default:
     423           0 :         return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
     424             :     }
     425             : 
     426          38 :     return 0;
     427             : }
     428             : 
     429             : static int
     430           0 : rsa_private_key2SPKI(hx509_context context,
     431             :                      hx509_private_key private_key,
     432             :                      SubjectPublicKeyInfo *spki)
     433             : {
     434             :     int len, ret;
     435             : 
     436           0 :     memset(spki, 0, sizeof(*spki));
     437             : 
     438           0 :     len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL);
     439           0 :     if (len < 0)
     440           0 :         return -1;
     441             : 
     442           0 :     spki->subjectPublicKey.data = malloc(len);
     443           0 :     if (spki->subjectPublicKey.data == NULL) {
     444           0 :         hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");
     445           0 :         return ENOMEM;
     446             :     }
     447           0 :     spki->subjectPublicKey.length = len * 8;
     448             : 
     449           0 :     ret = _hx509_set_digest_alg(&spki->algorithm,
     450             :                                 ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     451             :                                 "\x05\x00", 2);
     452           0 :     if (ret) {
     453           0 :         hx509_set_error_string(context, 0, ret, "malloc - out of memory");
     454           0 :         free(spki->subjectPublicKey.data);
     455           0 :         spki->subjectPublicKey.data = NULL;
     456           0 :         spki->subjectPublicKey.length = 0;
     457           0 :         return ret;
     458             :     }
     459             : 
     460             :     {
     461           0 :         unsigned char *pp = spki->subjectPublicKey.data;
     462           0 :         i2d_RSAPublicKey(private_key->private_key.rsa, &pp);
     463             :     }
     464             : 
     465           0 :     return 0;
     466             : }
     467             : 
     468             : static int
     469           0 : rsa_generate_private_key(hx509_context context,
     470             :                          struct hx509_generate_private_context *ctx,
     471             :                          hx509_private_key private_key)
     472             : {
     473             :     BIGNUM *e;
     474             :     int ret;
     475             :     unsigned long bits;
     476             : 
     477             :     static const int default_rsa_e = 65537;
     478             :     static const int default_rsa_bits = 2048;
     479             : 
     480           0 :     private_key->private_key.rsa = RSA_new();
     481           0 :     if (private_key->private_key.rsa == NULL) {
     482           0 :         hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
     483             :                                "Failed to generate RSA key");
     484           0 :         return HX509_PARSING_KEY_FAILED;
     485             :     }
     486             : 
     487           0 :     e = BN_new();
     488           0 :     BN_set_word(e, default_rsa_e);
     489             : 
     490           0 :     bits = default_rsa_bits;
     491             : 
     492           0 :     if (ctx->num_bits)
     493           0 :         bits = ctx->num_bits;
     494             : 
     495           0 :     ret = RSA_generate_key_ex(private_key->private_key.rsa, bits, e, NULL);
     496           0 :     BN_free(e);
     497           0 :     if (ret != 1) {
     498           0 :         hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
     499             :                                "Failed to generate RSA key");
     500           0 :         return HX509_PARSING_KEY_FAILED;
     501             :     }
     502           0 :     private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
     503             : 
     504           0 :     return 0;
     505             : }
     506             : 
     507             : static int
     508           0 : rsa_private_key_export(hx509_context context,
     509             :                        const hx509_private_key key,
     510             :                        hx509_key_format_t format,
     511             :                        heim_octet_string *data)
     512             : {
     513             :     int ret;
     514             : 
     515           0 :     data->data = NULL;
     516           0 :     data->length = 0;
     517             : 
     518           0 :     switch (format) {
     519           0 :     case HX509_KEY_FORMAT_DER:
     520             : 
     521           0 :         ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL);
     522           0 :         if (ret <= 0) {
     523           0 :             ret = EINVAL;
     524           0 :             hx509_set_error_string(context, 0, ret,
     525             :                                "Private key is not exportable");
     526           0 :             return ret;
     527             :         }
     528             : 
     529           0 :         data->data = malloc(ret);
     530           0 :         if (data->data == NULL) {
     531           0 :             ret = ENOMEM;
     532           0 :             hx509_set_error_string(context, 0, ret, "malloc out of memory");
     533           0 :             return ret;
     534             :         }
     535           0 :         data->length = ret;
     536             : 
     537           0 :         {
     538           0 :             unsigned char *p = data->data;
     539           0 :             i2d_RSAPrivateKey(key->private_key.rsa, &p);
     540             :         }
     541           0 :         break;
     542           0 :     default:
     543           0 :         return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
     544             :     }
     545             : 
     546           0 :     return 0;
     547             : }
     548             : 
     549             : static BIGNUM *
     550           0 : rsa_get_internal(hx509_context context,
     551             :                  hx509_private_key key,
     552             :                  const char *type)
     553             : {
     554           0 :     if (strcasecmp(type, "rsa-modulus") == 0) {
     555           0 :         return BN_dup(key->private_key.rsa->n);
     556           0 :     } else if (strcasecmp(type, "rsa-exponent") == 0) {
     557           0 :         return BN_dup(key->private_key.rsa->e);
     558             :     } else
     559           0 :         return NULL;
     560             : }
     561             : 
     562             : 
     563             : 
     564             : static hx509_private_key_ops rsa_private_key_ops = {
     565             :     "RSA PRIVATE KEY",
     566             :     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     567             :     NULL,
     568             :     rsa_private_key2SPKI,
     569             :     rsa_private_key_export,
     570             :     rsa_private_key_import,
     571             :     rsa_generate_private_key,
     572             :     rsa_get_internal
     573             : };
     574             : 
     575             : /*
     576             :  *
     577             :  */
     578             : 
     579             : static int
     580           0 : dsa_verify_signature(hx509_context context,
     581             :                      const struct signature_alg *sig_alg,
     582             :                      const Certificate *signer,
     583             :                      const AlgorithmIdentifier *alg,
     584             :                      const heim_octet_string *data,
     585             :                      const heim_octet_string *sig)
     586             : {
     587             :     const SubjectPublicKeyInfo *spi;
     588             :     DSAPublicKey pk;
     589             :     DSAParams param;
     590             :     size_t size;
     591             :     DSA *dsa;
     592             :     int ret;
     593             : 
     594           0 :     spi = &signer->tbsCertificate.subjectPublicKeyInfo;
     595             : 
     596           0 :     dsa = DSA_new();
     597           0 :     if (dsa == NULL) {
     598           0 :         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
     599           0 :         return ENOMEM;
     600             :     }
     601             : 
     602           0 :     ret = decode_DSAPublicKey(spi->subjectPublicKey.data,
     603           0 :                               spi->subjectPublicKey.length / 8,
     604             :                               &pk, &size);
     605           0 :     if (ret)
     606           0 :         goto out;
     607             : 
     608           0 :     dsa->pub_key = heim_int2BN(&pk);
     609             : 
     610           0 :     free_DSAPublicKey(&pk);
     611             : 
     612           0 :     if (dsa->pub_key == NULL) {
     613           0 :         ret = ENOMEM;
     614           0 :         hx509_set_error_string(context, 0, ret, "out of memory");
     615           0 :         goto out;
     616             :     }
     617             : 
     618           0 :     if (spi->algorithm.parameters == NULL) {
     619           0 :         ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
     620           0 :         hx509_set_error_string(context, 0, ret, "DSA parameters missing");
     621           0 :         goto out;
     622             :     }
     623             : 
     624           0 :     ret = decode_DSAParams(spi->algorithm.parameters->data,
     625           0 :                            spi->algorithm.parameters->length,
     626             :                            &param,
     627             :                            &size);
     628           0 :     if (ret) {
     629           0 :         hx509_set_error_string(context, 0, ret, "DSA parameters failed to decode");
     630           0 :         goto out;
     631             :     }
     632             : 
     633           0 :     dsa->p = heim_int2BN(&param.p);
     634           0 :     dsa->q = heim_int2BN(&param.q);
     635           0 :     dsa->g = heim_int2BN(&param.g);
     636             : 
     637           0 :     free_DSAParams(&param);
     638             : 
     639           0 :     if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
     640           0 :         ret = ENOMEM;
     641           0 :         hx509_set_error_string(context, 0, ret, "out of memory");
     642           0 :         goto out;
     643             :     }
     644             : 
     645           0 :     ret = DSA_verify(-1, data->data, data->length,
     646           0 :                      (unsigned char*)sig->data, sig->length,
     647             :                      dsa);
     648           0 :     if (ret == 1)
     649           0 :         ret = 0;
     650           0 :     else if (ret == 0 || ret == -1) {
     651           0 :         ret = HX509_CRYPTO_BAD_SIGNATURE;
     652           0 :         hx509_set_error_string(context, 0, ret, "BAD DSA sigature");
     653             :     } else {
     654           0 :         ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
     655           0 :         hx509_set_error_string(context, 0, ret, "Invalid format of DSA sigature");
     656             :     }
     657             : 
     658           0 :  out:
     659           0 :     DSA_free(dsa);
     660             : 
     661           0 :     return ret;
     662             : }
     663             : 
     664             : #if 0
     665             : static int
     666             : dsa_parse_private_key(hx509_context context,
     667             :                       const void *data,
     668             :                       size_t len,
     669             :                       hx509_private_key private_key)
     670             : {
     671             :     const unsigned char *p = data;
     672             : 
     673             :     private_key->private_key.dsa =
     674             :         d2i_DSAPrivateKey(NULL, &p, len);
     675             :     if (private_key->private_key.dsa == NULL)
     676             :         return EINVAL;
     677             :     private_key->signature_alg = ASN1_OID_ID_DSA_WITH_SHA1;
     678             : 
     679             :     return 0;
     680             : /* else */
     681             :     hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
     682             :                            "No support to parse DSA keys");
     683             :     return HX509_PARSING_KEY_FAILED;
     684             : }
     685             : #endif
     686             : 
     687             : static int
     688           0 : evp_md_create_signature(hx509_context context,
     689             :                         const struct signature_alg *sig_alg,
     690             :                         const hx509_private_key signer,
     691             :                         const AlgorithmIdentifier *alg,
     692             :                         const heim_octet_string *data,
     693             :                         AlgorithmIdentifier *signatureAlgorithm,
     694             :                         heim_octet_string *sig)
     695             : {
     696           0 :     size_t sigsize = EVP_MD_size(sig_alg->evp_md());
     697             :     EVP_MD_CTX *ctx;
     698             : 
     699           0 :     memset(sig, 0, sizeof(*sig));
     700             : 
     701           0 :     if (signatureAlgorithm) {
     702             :         int ret;
     703           0 :         ret = _hx509_set_digest_alg(signatureAlgorithm,
     704             :                                     sig_alg->sig_oid, "\x05\x00", 2);
     705           0 :         if (ret)
     706           0 :             return ret;
     707             :     }
     708             : 
     709             : 
     710           0 :     sig->data = malloc(sigsize);
     711           0 :     if (sig->data == NULL) {
     712           0 :         sig->length = 0;
     713           0 :         return ENOMEM;
     714             :     }
     715           0 :     sig->length = sigsize;
     716             : 
     717           0 :     ctx = EVP_MD_CTX_create();
     718           0 :     EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL);
     719           0 :     EVP_DigestUpdate(ctx, data->data, data->length);
     720           0 :     EVP_DigestFinal_ex(ctx, sig->data, NULL);
     721           0 :     EVP_MD_CTX_destroy(ctx);
     722             : 
     723             : 
     724           0 :     return 0;
     725             : }
     726             : 
     727             : static int
     728           0 : evp_md_verify_signature(hx509_context context,
     729             :                         const struct signature_alg *sig_alg,
     730             :                         const Certificate *signer,
     731             :                         const AlgorithmIdentifier *alg,
     732             :                         const heim_octet_string *data,
     733             :                         const heim_octet_string *sig)
     734             : {
     735             :     unsigned char digest[EVP_MAX_MD_SIZE];
     736             :     EVP_MD_CTX *ctx;
     737           0 :     size_t sigsize = EVP_MD_size(sig_alg->evp_md());
     738             : 
     739           0 :     if (sig->length != sigsize || sigsize > sizeof(digest)) {
     740           0 :         hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT,
     741             :                                "SHA256 sigature have wrong length");
     742           0 :         return HX509_CRYPTO_SIG_INVALID_FORMAT;
     743             :     }
     744             : 
     745           0 :     ctx = EVP_MD_CTX_create();
     746           0 :     EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL);
     747           0 :     EVP_DigestUpdate(ctx, data->data, data->length);
     748           0 :     EVP_DigestFinal_ex(ctx, digest, NULL);
     749           0 :     EVP_MD_CTX_destroy(ctx);
     750             : 
     751           0 :     if (ct_memcmp(digest, sig->data, sigsize) != 0) {
     752           0 :         hx509_set_error_string(context, 0, HX509_CRYPTO_BAD_SIGNATURE,
     753             :                                "Bad %s sigature", sig_alg->name);
     754           0 :         return HX509_CRYPTO_BAD_SIGNATURE;
     755             :     }
     756             : 
     757           0 :     return 0;
     758             : }
     759             : 
     760             : #ifdef HAVE_HCRYPTO_W_OPENSSL
     761             : extern const struct signature_alg ecdsa_with_sha512_alg;
     762             : extern const struct signature_alg ecdsa_with_sha384_alg;
     763             : extern const struct signature_alg ecdsa_with_sha256_alg;
     764             : extern const struct signature_alg ecdsa_with_sha1_alg;
     765             : #endif
     766             : 
     767             : static const struct signature_alg heim_rsa_pkcs1_x509 = {
     768             :     "rsa-pkcs1-x509",
     769             :     ASN1_OID_ID_HEIM_RSA_PKCS1_X509,
     770             :     &_hx509_signature_rsa_pkcs1_x509_data,
     771             :     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     772             :     NULL,
     773             :     PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
     774             :     0,
     775             :     NULL,
     776             :     rsa_verify_signature,
     777             :     rsa_create_signature,
     778             :     0
     779             : };
     780             : 
     781             : static const struct signature_alg pkcs1_rsa_sha1_alg = {
     782             :     "rsa",
     783             :     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     784             :     &_hx509_signature_rsa_with_sha1_data,
     785             :     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     786             :     NULL,
     787             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     788             :     0,
     789             :     NULL,
     790             :     rsa_verify_signature,
     791             :     rsa_create_signature,
     792             :     0
     793             : };
     794             : 
     795             : static const struct signature_alg rsa_with_sha512_alg = {
     796             :     "rsa-with-sha512",
     797             :     ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION,
     798             :     &_hx509_signature_rsa_with_sha512_data,
     799             :     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     800             :     &_hx509_signature_sha512_data,
     801             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     802             :     0,
     803             :     NULL,
     804             :     rsa_verify_signature,
     805             :     rsa_create_signature,
     806             :     0
     807             : };
     808             : 
     809             : static const struct signature_alg rsa_with_sha384_alg = {
     810             :     "rsa-with-sha384",
     811             :     ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION,
     812             :     &_hx509_signature_rsa_with_sha384_data,
     813             :     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     814             :     &_hx509_signature_sha384_data,
     815             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     816             :     0,
     817             :     NULL,
     818             :     rsa_verify_signature,
     819             :     rsa_create_signature,
     820             :     0
     821             : };
     822             : 
     823             : static const struct signature_alg rsa_with_sha256_alg = {
     824             :     "rsa-with-sha256",
     825             :     ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION,
     826             :     &_hx509_signature_rsa_with_sha256_data,
     827             :     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     828             :     &_hx509_signature_sha256_data,
     829             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     830             :     0,
     831             :     NULL,
     832             :     rsa_verify_signature,
     833             :     rsa_create_signature,
     834             :     0
     835             : };
     836             : 
     837             : static const struct signature_alg rsa_with_sha1_alg = {
     838             :     "rsa-with-sha1",
     839             :     ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION,
     840             :     &_hx509_signature_rsa_with_sha1_data,
     841             :     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     842             :     &_hx509_signature_sha1_data,
     843             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     844             :     0,
     845             :     NULL,
     846             :     rsa_verify_signature,
     847             :     rsa_create_signature,
     848             :     0
     849             : };
     850             : 
     851             : static const struct signature_alg rsa_with_sha1_alg_secsig = {
     852             :     "rsa-with-sha1",
     853             :     ASN1_OID_ID_SECSIG_SHA_1WITHRSAENCRYPTION,
     854             :     &_hx509_signature_rsa_with_sha1_data,
     855             :     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     856             :     &_hx509_signature_sha1_data,
     857             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     858             :     0,
     859             :     NULL,
     860             :     rsa_verify_signature,
     861             :     rsa_create_signature,
     862             :     0
     863             : };
     864             : 
     865             : static const struct signature_alg rsa_with_md5_alg = {
     866             :     "rsa-with-md5",
     867             :     ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION,
     868             :     &_hx509_signature_rsa_with_md5_data,
     869             :     ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     870             :     &_hx509_signature_md5_data,
     871             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|WEAK_SIG_ALG,
     872             :     1230739889,
     873             :     NULL,
     874             :     rsa_verify_signature,
     875             :     rsa_create_signature,
     876             :     0
     877             : };
     878             : 
     879             : static const struct signature_alg dsa_sha1_alg = {
     880             :     "dsa-with-sha1",
     881             :     ASN1_OID_ID_DSA_WITH_SHA1,
     882             :     NULL,
     883             :     ASN1_OID_ID_DSA,
     884             :     &_hx509_signature_sha1_data,
     885             :     PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
     886             :     0,
     887             :     NULL,
     888             :     dsa_verify_signature,
     889             :     /* create_signature */ NULL,
     890             :     0
     891             : };
     892             : 
     893             : static const struct signature_alg sha512_alg = {
     894             :     "sha-512",
     895             :     ASN1_OID_ID_SHA512,
     896             :     &_hx509_signature_sha512_data,
     897             :     NULL,
     898             :     NULL,
     899             :     SIG_DIGEST,
     900             :     0,
     901             :     EVP_sha512,
     902             :     evp_md_verify_signature,
     903             :     evp_md_create_signature,
     904             :     0
     905             : };
     906             : 
     907             : static const struct signature_alg sha384_alg = {
     908             :     "sha-384",
     909             :     ASN1_OID_ID_SHA384,
     910             :     &_hx509_signature_sha384_data,
     911             :     NULL,
     912             :     NULL,
     913             :     SIG_DIGEST,
     914             :     0,
     915             :     EVP_sha384,
     916             :     evp_md_verify_signature,
     917             :     evp_md_create_signature,
     918             :     0
     919             : };
     920             : 
     921             : static const struct signature_alg sha256_alg = {
     922             :     "sha-256",
     923             :     ASN1_OID_ID_SHA256,
     924             :     &_hx509_signature_sha256_data,
     925             :     NULL,
     926             :     NULL,
     927             :     SIG_DIGEST,
     928             :     0,
     929             :     EVP_sha256,
     930             :     evp_md_verify_signature,
     931             :     evp_md_create_signature,
     932             :     0
     933             : };
     934             : 
     935             : static const struct signature_alg sha1_alg = {
     936             :     "sha1",
     937             :     ASN1_OID_ID_SECSIG_SHA_1,
     938             :     &_hx509_signature_sha1_data,
     939             :     NULL,
     940             :     NULL,
     941             :     SIG_DIGEST,
     942             :     0,
     943             :     EVP_sha1,
     944             :     evp_md_verify_signature,
     945             :     evp_md_create_signature,
     946             :     0
     947             : };
     948             : 
     949             : static const struct signature_alg md5_alg = {
     950             :     "rsa-md5",
     951             :     ASN1_OID_ID_RSA_DIGEST_MD5,
     952             :     &_hx509_signature_md5_data,
     953             :     NULL,
     954             :     NULL,
     955             :     SIG_DIGEST|WEAK_SIG_ALG,
     956             :     0,
     957             :     EVP_md5,
     958             :     evp_md_verify_signature,
     959             :     NULL,
     960             :     0
     961             : };
     962             : 
     963             : /*
     964             :  * Order matter in this structure, "best" first for each "key
     965             :  * compatible" type (type is ECDSA, RSA, DSA, none, etc)
     966             :  */
     967             : 
     968             : static const struct signature_alg *sig_algs[] = {
     969             : #ifdef HAVE_HCRYPTO_W_OPENSSL
     970             :     &ecdsa_with_sha512_alg,
     971             :     &ecdsa_with_sha384_alg,
     972             :     &ecdsa_with_sha256_alg,
     973             :     &ecdsa_with_sha1_alg,
     974             : #endif
     975             :     &rsa_with_sha512_alg,
     976             :     &rsa_with_sha384_alg,
     977             :     &rsa_with_sha256_alg,
     978             :     &rsa_with_sha1_alg,
     979             :     &rsa_with_sha1_alg_secsig,
     980             :     &pkcs1_rsa_sha1_alg,
     981             :     &rsa_with_md5_alg,
     982             :     &heim_rsa_pkcs1_x509,
     983             :     &dsa_sha1_alg,
     984             :     &sha512_alg,
     985             :     &sha384_alg,
     986             :     &sha256_alg,
     987             :     &sha1_alg,
     988             :     &md5_alg,
     989             :     NULL
     990             : };
     991             : 
     992             : const struct signature_alg *
     993           0 : _hx509_find_sig_alg(const heim_oid *oid)
     994             : {
     995             :     unsigned int i;
     996           0 :     for (i = 0; sig_algs[i]; i++)
     997           0 :         if (der_heim_oid_cmp(sig_algs[i]->sig_oid, oid) == 0)
     998           0 :             return sig_algs[i];
     999           0 :     return NULL;
    1000             : }
    1001             : 
    1002             : static const AlgorithmIdentifier *
    1003           0 : alg_for_privatekey(const hx509_private_key pk, int type)
    1004             : {
    1005             :     const heim_oid *keytype;
    1006             :     unsigned int i;
    1007             : 
    1008           0 :     if (pk->ops == NULL)
    1009           0 :         return NULL;
    1010             : 
    1011           0 :     keytype = pk->ops->key_oid;
    1012             : 
    1013           0 :     for (i = 0; sig_algs[i]; i++) {
    1014           0 :         if (sig_algs[i]->key_oid == NULL)
    1015           0 :             continue;
    1016           0 :         if (der_heim_oid_cmp(sig_algs[i]->key_oid, keytype) != 0)
    1017           0 :             continue;
    1018           0 :         if (pk->ops->available &&
    1019           0 :             pk->ops->available(pk, sig_algs[i]->sig_alg) == 0)
    1020           0 :             continue;
    1021           0 :         if (type == HX509_SELECT_PUBLIC_SIG)
    1022           0 :             return sig_algs[i]->sig_alg;
    1023           0 :         if (type == HX509_SELECT_DIGEST)
    1024           0 :             return sig_algs[i]->digest_alg;
    1025             : 
    1026           0 :         return NULL;
    1027             :     }
    1028           0 :     return NULL;
    1029             : }
    1030             : 
    1031             : /*
    1032             :  *
    1033             :  */
    1034             : #ifdef HAVE_HCRYPTO_W_OPENSSL
    1035             : extern hx509_private_key_ops ecdsa_private_key_ops;
    1036             : #endif
    1037             : 
    1038             : static struct hx509_private_key_ops *private_algs[] = {
    1039             :     &rsa_private_key_ops,
    1040             : #ifdef HAVE_HCRYPTO_W_OPENSSL
    1041             :     &ecdsa_private_key_ops,
    1042             : #endif
    1043             :     NULL
    1044             : };
    1045             : 
    1046             : HX509_LIB_FUNCTION hx509_private_key_ops * HX509_LIB_CALL
    1047          38 : hx509_find_private_alg(const heim_oid *oid)
    1048             : {
    1049             :     int i;
    1050          38 :     for (i = 0; private_algs[i]; i++) {
    1051          38 :         if (private_algs[i]->key_oid == NULL)
    1052           0 :             continue;
    1053          38 :         if (der_heim_oid_cmp(private_algs[i]->key_oid, oid) == 0)
    1054          38 :             return private_algs[i];
    1055             :     }
    1056           0 :     return NULL;
    1057             : }
    1058             : 
    1059             : /*
    1060             :  * Check if the algorithm `alg' have a best before date, and if it
    1061             :  * des, make sure the its before the time `t'.
    1062             :  */
    1063             : 
    1064             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1065           0 : _hx509_signature_is_weak(hx509_context context, const AlgorithmIdentifier *alg)
    1066             : {
    1067             :     const struct signature_alg *md;
    1068             : 
    1069           0 :     md = _hx509_find_sig_alg(&alg->algorithm);
    1070           0 :     if (md == NULL) {
    1071           0 :         hx509_clear_error_string(context);
    1072           0 :         return HX509_SIG_ALG_NO_SUPPORTED;
    1073             :     }
    1074           0 :     if (md->flags & WEAK_SIG_ALG) {
    1075           0 :         hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE,
    1076             :                                "Algorithm %s is weak", md->name);
    1077           0 :         return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
    1078             :     }
    1079           0 :     return 0;
    1080             : }
    1081             : 
    1082             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1083           0 : _hx509_self_signed_valid(hx509_context context,
    1084             :                          const AlgorithmIdentifier *alg)
    1085             : {
    1086             :     const struct signature_alg *md;
    1087             : 
    1088           0 :     md = _hx509_find_sig_alg(&alg->algorithm);
    1089           0 :     if (md == NULL) {
    1090           0 :         hx509_clear_error_string(context);
    1091           0 :         return HX509_SIG_ALG_NO_SUPPORTED;
    1092             :     }
    1093           0 :     if ((md->flags & SELF_SIGNED_OK) == 0) {
    1094           0 :         hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE,
    1095             :                                "Algorithm %s not trusted for self signatures",
    1096             :                                md->name);
    1097           0 :         return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
    1098             :     }
    1099           0 :     return 0;
    1100             : }
    1101             : 
    1102             : 
    1103             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1104           0 : _hx509_verify_signature(hx509_context context,
    1105             :                         const hx509_cert cert,
    1106             :                         const AlgorithmIdentifier *alg,
    1107             :                         const heim_octet_string *data,
    1108             :                         const heim_octet_string *sig)
    1109             : {
    1110             :     const struct signature_alg *md;
    1111           0 :     const Certificate *signer = NULL;
    1112             : 
    1113           0 :     if (cert)
    1114           0 :         signer = _hx509_get_cert(cert);
    1115             : 
    1116           0 :     md = _hx509_find_sig_alg(&alg->algorithm);
    1117           0 :     if (md == NULL) {
    1118           0 :         hx509_clear_error_string(context);
    1119           0 :         return HX509_SIG_ALG_NO_SUPPORTED;
    1120             :     }
    1121           0 :     if (signer && (md->flags & PROVIDE_CONF) == 0) {
    1122           0 :         hx509_clear_error_string(context);
    1123           0 :         return HX509_CRYPTO_SIG_NO_CONF;
    1124             :     }
    1125           0 :     if (signer == NULL && (md->flags & REQUIRE_SIGNER)) {
    1126           0 :             hx509_clear_error_string(context);
    1127           0 :         return HX509_CRYPTO_SIGNATURE_WITHOUT_SIGNER;
    1128             :     }
    1129           0 :     if (md->key_oid && signer) {
    1130             :         const SubjectPublicKeyInfo *spi;
    1131           0 :         spi = &signer->tbsCertificate.subjectPublicKeyInfo;
    1132             : 
    1133           0 :         if (der_heim_oid_cmp(&spi->algorithm.algorithm, md->key_oid) != 0) {
    1134           0 :             hx509_clear_error_string(context);
    1135           0 :             return HX509_SIG_ALG_DONT_MATCH_KEY_ALG;
    1136             :         }
    1137             :     }
    1138           0 :     return (*md->verify_signature)(context, md, signer, alg, data, sig);
    1139             : }
    1140             : 
    1141             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1142           0 : _hx509_create_signature(hx509_context context,
    1143             :                         const hx509_private_key signer,
    1144             :                         const AlgorithmIdentifier *alg,
    1145             :                         const heim_octet_string *data,
    1146             :                         AlgorithmIdentifier *signatureAlgorithm,
    1147             :                         heim_octet_string *sig)
    1148             : {
    1149             :     const struct signature_alg *md;
    1150             : 
    1151           0 :     md = _hx509_find_sig_alg(&alg->algorithm);
    1152           0 :     if (md == NULL) {
    1153           0 :         hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,
    1154             :             "algorithm no supported");
    1155           0 :         return HX509_SIG_ALG_NO_SUPPORTED;
    1156             :     }
    1157             : 
    1158           0 :     if (signer && (md->flags & PROVIDE_CONF) == 0) {
    1159           0 :         hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,
    1160             :             "algorithm provides no conf");
    1161           0 :         return HX509_CRYPTO_SIG_NO_CONF;
    1162             :     }
    1163             : 
    1164           0 :     return (*md->create_signature)(context, md, signer, alg, data,
    1165             :                                    signatureAlgorithm, sig);
    1166             : }
    1167             : 
    1168             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1169           0 : _hx509_create_signature_bitstring(hx509_context context,
    1170             :                                   const hx509_private_key signer,
    1171             :                                   const AlgorithmIdentifier *alg,
    1172             :                                   const heim_octet_string *data,
    1173             :                                   AlgorithmIdentifier *signatureAlgorithm,
    1174             :                                   heim_bit_string *sig)
    1175             : {
    1176             :     heim_octet_string os;
    1177             :     int ret;
    1178             : 
    1179           0 :     ret = _hx509_create_signature(context, signer, alg,
    1180             :                                   data, signatureAlgorithm, &os);
    1181           0 :     if (ret)
    1182           0 :         return ret;
    1183           0 :     sig->data = os.data;
    1184           0 :     sig->length = os.length * 8;
    1185           0 :     return 0;
    1186             : }
    1187             : 
    1188             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1189           0 : _hx509_public_encrypt(hx509_context context,
    1190             :                       const heim_octet_string *cleartext,
    1191             :                       const Certificate *cert,
    1192             :                       heim_oid *encryption_oid,
    1193             :                       heim_octet_string *ciphertext)
    1194             : {
    1195             :     const SubjectPublicKeyInfo *spi;
    1196             :     unsigned char *to;
    1197             :     int tosize;
    1198             :     int ret;
    1199             :     RSA *rsa;
    1200             :     size_t size;
    1201             :     const unsigned char *p;
    1202             : 
    1203           0 :     ciphertext->data = NULL;
    1204           0 :     ciphertext->length = 0;
    1205             : 
    1206           0 :     spi = &cert->tbsCertificate.subjectPublicKeyInfo;
    1207             : 
    1208           0 :     p = spi->subjectPublicKey.data;
    1209           0 :     size = spi->subjectPublicKey.length / 8;
    1210             : 
    1211           0 :     rsa = d2i_RSAPublicKey(NULL, &p, size);
    1212           0 :     if (rsa == NULL) {
    1213           0 :         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
    1214           0 :         return ENOMEM;
    1215             :     }
    1216             : 
    1217           0 :     tosize = RSA_size(rsa);
    1218           0 :     to = malloc(tosize);
    1219           0 :     if (to == NULL) {
    1220           0 :         RSA_free(rsa);
    1221           0 :         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
    1222           0 :         return ENOMEM;
    1223             :     }
    1224             : 
    1225           0 :     ret = RSA_public_encrypt(cleartext->length,
    1226           0 :                              (unsigned char *)cleartext->data,
    1227             :                              to, rsa, RSA_PKCS1_PADDING);
    1228           0 :     RSA_free(rsa);
    1229           0 :     if (ret <= 0) {
    1230           0 :         free(to);
    1231           0 :         hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PUBLIC_ENCRYPT,
    1232             :                                "RSA public encrypt failed with %d", ret);
    1233           0 :         return HX509_CRYPTO_RSA_PUBLIC_ENCRYPT;
    1234             :     }
    1235           0 :     if (ret > tosize)
    1236           0 :         _hx509_abort("internal rsa decryption failure: ret > tosize");
    1237             : 
    1238           0 :     ciphertext->length = ret;
    1239           0 :     ciphertext->data = to;
    1240             : 
    1241           0 :     ret = der_copy_oid(ASN1_OID_ID_PKCS1_RSAENCRYPTION, encryption_oid);
    1242           0 :     if (ret) {
    1243           0 :         der_free_octet_string(ciphertext);
    1244           0 :         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
    1245           0 :         return ENOMEM;
    1246             :     }
    1247             : 
    1248           0 :     return 0;
    1249             : }
    1250             : 
    1251             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1252           0 : hx509_private_key_private_decrypt(hx509_context context,
    1253             :                                    const heim_octet_string *ciphertext,
    1254             :                                    const heim_oid *encryption_oid,
    1255             :                                    hx509_private_key p,
    1256             :                                    heim_octet_string *cleartext)
    1257             : {
    1258             :     int ret;
    1259             : 
    1260           0 :     cleartext->data = NULL;
    1261           0 :     cleartext->length = 0;
    1262             : 
    1263           0 :     if (p->private_key.rsa == NULL) {
    1264           0 :         hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
    1265             :                                "Private RSA key missing");
    1266           0 :         return HX509_PRIVATE_KEY_MISSING;
    1267             :     }
    1268             : 
    1269           0 :     cleartext->length = RSA_size(p->private_key.rsa);
    1270           0 :     cleartext->data = malloc(cleartext->length);
    1271           0 :     if (cleartext->data == NULL) {
    1272           0 :         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
    1273           0 :         return ENOMEM;
    1274             :     }
    1275           0 :     ret = RSA_private_decrypt(ciphertext->length, ciphertext->data,
    1276           0 :                               cleartext->data,
    1277             :                               p->private_key.rsa,
    1278             :                               RSA_PKCS1_PADDING);
    1279           0 :     if (ret <= 0) {
    1280           0 :         der_free_octet_string(cleartext);
    1281           0 :         hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PRIVATE_DECRYPT,
    1282             :                                "Failed to decrypt using private key: %d", ret);
    1283           0 :         return HX509_CRYPTO_RSA_PRIVATE_DECRYPT;
    1284             :     }
    1285           0 :     if (cleartext->length < (size_t)ret)
    1286           0 :         _hx509_abort("internal rsa decryption failure: ret > tosize");
    1287             : 
    1288           0 :     cleartext->length = ret;
    1289             : 
    1290           0 :     return 0;
    1291             : }
    1292             : 
    1293             : 
    1294             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1295          38 : hx509_parse_private_key(hx509_context context,
    1296             :                          const AlgorithmIdentifier *keyai,
    1297             :                          const void *data,
    1298             :                          size_t len,
    1299             :                          hx509_key_format_t format,
    1300             :                          hx509_private_key *private_key)
    1301             : {
    1302             :     struct hx509_private_key_ops *ops;
    1303             :     int ret;
    1304             : 
    1305          38 :     *private_key = NULL;
    1306             : 
    1307          38 :     if (format == HX509_KEY_FORMAT_PKCS8) {
    1308             :         PKCS8PrivateKeyInfo ki;
    1309             :         hx509_private_key key;
    1310             : 
    1311           0 :         ret = decode_PKCS8PrivateKeyInfo(data, len, &ki, NULL);
    1312           0 :         if (ret) {
    1313           0 :             hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
    1314             :                                    "Failed to parse PKCS#8-encoded private "
    1315             :                                    "key");
    1316           0 :             return HX509_PARSING_KEY_FAILED;
    1317             :         }
    1318             : 
    1319             :         /* Re-enter to parse DER-encoded key from PKCS#8 envelope */
    1320           0 :         ret = hx509_parse_private_key(context, &ki.privateKeyAlgorithm,
    1321           0 :                                       ki.privateKey.data, ki.privateKey.length,
    1322             :                                       HX509_KEY_FORMAT_DER, &key);
    1323           0 :         free_PKCS8PrivateKeyInfo(&ki);
    1324           0 :         if (ret) {
    1325           0 :             hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
    1326             :                                    "Failed to parse RSA key from PKCS#8 "
    1327             :                                    "envelope");
    1328           0 :             return HX509_PARSING_KEY_FAILED;
    1329             :         }
    1330             : 
    1331           0 :         *private_key = key;
    1332           0 :         return ret;
    1333             :     }
    1334             : 
    1335          38 :     ops = hx509_find_private_alg(&keyai->algorithm);
    1336          38 :     if (ops == NULL) {
    1337           0 :         hx509_clear_error_string(context);
    1338           0 :         return HX509_SIG_ALG_NO_SUPPORTED;
    1339             :     }
    1340             : 
    1341          38 :     ret = hx509_private_key_init(private_key, ops, NULL);
    1342          38 :     if (ret) {
    1343           0 :         hx509_set_error_string(context, 0, ret, "out of memory");
    1344           0 :         return ret;
    1345             :     }
    1346             : 
    1347          38 :     ret = (*ops->import)(context, keyai, data, len, format, *private_key);
    1348          38 :     if (ret)
    1349           0 :         hx509_private_key_free(private_key);
    1350             : 
    1351          38 :     return ret;
    1352             : }
    1353             : 
    1354             : /*
    1355             :  *
    1356             :  */
    1357             : 
    1358             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1359           0 : hx509_private_key2SPKI(hx509_context context,
    1360             :                         hx509_private_key private_key,
    1361             :                         SubjectPublicKeyInfo *spki)
    1362             : {
    1363           0 :     const struct hx509_private_key_ops *ops = private_key->ops;
    1364           0 :     if (ops == NULL || ops->get_spki == NULL) {
    1365           0 :         hx509_set_error_string(context, 0, HX509_UNIMPLEMENTED_OPERATION,
    1366             :                                "Private key have no key2SPKI function");
    1367           0 :         return HX509_UNIMPLEMENTED_OPERATION;
    1368             :     }
    1369           0 :     return (*ops->get_spki)(context, private_key, spki);
    1370             : }
    1371             : 
    1372             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1373           0 : _hx509_generate_private_key_init(hx509_context context,
    1374             :                                  const heim_oid *oid,
    1375             :                                  struct hx509_generate_private_context **ctx)
    1376             : {
    1377           0 :     *ctx = NULL;
    1378             : 
    1379           0 :     if (der_heim_oid_cmp(oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0) {
    1380           0 :         hx509_set_error_string(context, 0, EINVAL,
    1381             :                                "private key not an RSA key");
    1382           0 :         return EINVAL;
    1383             :     }
    1384             : 
    1385           0 :     *ctx = calloc(1, sizeof(**ctx));
    1386           0 :     if (*ctx == NULL) {
    1387           0 :         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
    1388           0 :         return ENOMEM;
    1389             :     }
    1390           0 :     (*ctx)->key_oid = oid;
    1391             : 
    1392           0 :     return 0;
    1393             : }
    1394             : 
    1395             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1396           0 : _hx509_generate_private_key_is_ca(hx509_context context,
    1397             :                                   struct hx509_generate_private_context *ctx)
    1398             : {
    1399           0 :     ctx->isCA = 1;
    1400           0 :     return 0;
    1401             : }
    1402             : 
    1403             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1404           0 : _hx509_generate_private_key_bits(hx509_context context,
    1405             :                                  struct hx509_generate_private_context *ctx,
    1406             :                                  unsigned long bits)
    1407             : {
    1408           0 :     ctx->num_bits = bits;
    1409           0 :     return 0;
    1410             : }
    1411             : 
    1412             : 
    1413             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    1414           0 : _hx509_generate_private_key_free(struct hx509_generate_private_context **ctx)
    1415             : {
    1416           0 :     free(*ctx);
    1417           0 :     *ctx = NULL;
    1418           0 : }
    1419             : 
    1420             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1421           0 : _hx509_generate_private_key(hx509_context context,
    1422             :                             struct hx509_generate_private_context *ctx,
    1423             :                             hx509_private_key *private_key)
    1424             : {
    1425             :     struct hx509_private_key_ops *ops;
    1426             :     int ret;
    1427             : 
    1428           0 :     *private_key = NULL;
    1429             : 
    1430           0 :     ops = hx509_find_private_alg(ctx->key_oid);
    1431           0 :     if (ops == NULL) {
    1432           0 :         hx509_clear_error_string(context);
    1433           0 :         return HX509_SIG_ALG_NO_SUPPORTED;
    1434             :     }
    1435             : 
    1436           0 :     ret = hx509_private_key_init(private_key, ops, NULL);
    1437           0 :     if (ret) {
    1438           0 :         hx509_set_error_string(context, 0, ret, "out of memory");
    1439           0 :         return ret;
    1440             :     }
    1441             : 
    1442           0 :     ret = (*ops->generate_private_key)(context, ctx, *private_key);
    1443           0 :     if (ret)
    1444           0 :         hx509_private_key_free(private_key);
    1445             : 
    1446           0 :     return ret;
    1447             : }
    1448             : 
    1449             : /*
    1450             :  *
    1451             :  */
    1452             : 
    1453             : const AlgorithmIdentifier *
    1454           0 : hx509_signature_sha512(void)
    1455           0 : { return &_hx509_signature_sha512_data; }
    1456             : 
    1457             : const AlgorithmIdentifier *
    1458           0 : hx509_signature_sha384(void)
    1459           0 : { return &_hx509_signature_sha384_data; }
    1460             : 
    1461             : const AlgorithmIdentifier *
    1462           0 : hx509_signature_sha256(void)
    1463           0 : { return &_hx509_signature_sha256_data; }
    1464             : 
    1465             : const AlgorithmIdentifier *
    1466           0 : hx509_signature_sha1(void)
    1467           0 : { return &_hx509_signature_sha1_data; }
    1468             : 
    1469             : const AlgorithmIdentifier *
    1470           0 : hx509_signature_md5(void)
    1471           0 : { return &_hx509_signature_md5_data; }
    1472             : 
    1473             : const AlgorithmIdentifier *
    1474           0 : hx509_signature_rsa_with_sha512(void)
    1475           0 : { return &_hx509_signature_rsa_with_sha512_data; }
    1476             : 
    1477             : const AlgorithmIdentifier *
    1478           0 : hx509_signature_rsa_with_sha384(void)
    1479           0 : { return &_hx509_signature_rsa_with_sha384_data; }
    1480             : 
    1481             : const AlgorithmIdentifier *
    1482           0 : hx509_signature_rsa_with_sha256(void)
    1483           0 : { return &_hx509_signature_rsa_with_sha256_data; }
    1484             : 
    1485             : const AlgorithmIdentifier *
    1486           0 : hx509_signature_rsa_with_sha1(void)
    1487           0 : { return &_hx509_signature_rsa_with_sha1_data; }
    1488             : 
    1489             : const AlgorithmIdentifier *
    1490           0 : hx509_signature_rsa_with_md5(void)
    1491           0 : { return &_hx509_signature_rsa_with_md5_data; }
    1492             : 
    1493             : const AlgorithmIdentifier *
    1494          38 : hx509_signature_rsa(void)
    1495          38 : { return &_hx509_signature_rsa_data; }
    1496             : 
    1497             : const AlgorithmIdentifier *
    1498           0 : hx509_signature_rsa_pkcs1_x509(void)
    1499           0 : { return &_hx509_signature_rsa_pkcs1_x509_data; }
    1500             : 
    1501             : const AlgorithmIdentifier *
    1502          77 : hx509_crypto_des_rsdi_ede3_cbc(void)
    1503          77 : { return &_hx509_des_rsdi_ede3_cbc_oid; }
    1504             : 
    1505             : const AlgorithmIdentifier *
    1506          77 : hx509_crypto_aes128_cbc(void)
    1507          77 : { return &_hx509_crypto_aes128_cbc_data; }
    1508             : 
    1509             : const AlgorithmIdentifier *
    1510          77 : hx509_crypto_aes256_cbc(void)
    1511          77 : { return &_hx509_crypto_aes256_cbc_data; }
    1512             : 
    1513             : /*
    1514             :  *
    1515             :  */
    1516             : 
    1517             : const AlgorithmIdentifier * _hx509_crypto_default_sig_alg =
    1518             :     &_hx509_signature_rsa_with_sha256_data;
    1519             : const AlgorithmIdentifier * _hx509_crypto_default_digest_alg =
    1520             :     &_hx509_signature_sha256_data;
    1521             : const AlgorithmIdentifier * _hx509_crypto_default_secret_alg =
    1522             :     &_hx509_crypto_aes128_cbc_data;
    1523             : 
    1524             : /*
    1525             :  *
    1526             :  */
    1527             : 
    1528             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1529          38 : hx509_private_key_init(hx509_private_key *key,
    1530             :                         hx509_private_key_ops *ops,
    1531             :                         void *keydata)
    1532             : {
    1533          38 :     *key = calloc(1, sizeof(**key));
    1534          38 :     if (*key == NULL)
    1535           0 :         return ENOMEM;
    1536          38 :     (*key)->ref = 1;
    1537          38 :     (*key)->ops = ops;
    1538          38 :     (*key)->private_key.keydata = keydata;
    1539          38 :     return 0;
    1540             : }
    1541             : 
    1542             : HX509_LIB_FUNCTION hx509_private_key HX509_LIB_CALL
    1543          76 : _hx509_private_key_ref(hx509_private_key key)
    1544             : {
    1545          76 :     if (key->ref == 0)
    1546           0 :         _hx509_abort("key refcount <= 0 on ref");
    1547          76 :     key->ref++;
    1548          76 :     if (key->ref == UINT_MAX)
    1549           0 :         _hx509_abort("key refcount == UINT_MAX on ref");
    1550          76 :     return key;
    1551             : }
    1552             : 
    1553             : HX509_LIB_FUNCTION const char * HX509_LIB_CALL
    1554           0 : _hx509_private_pem_name(hx509_private_key key)
    1555             : {
    1556           0 :     return key->ops->pemtype;
    1557             : }
    1558             : 
    1559             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1560          38 : hx509_private_key_free(hx509_private_key *key)
    1561             : {
    1562          38 :     if (key == NULL || *key == NULL)
    1563           0 :         return 0;
    1564             : 
    1565          38 :     if ((*key)->ref == 0)
    1566           0 :         _hx509_abort("key refcount == 0 on free");
    1567          38 :     if (--(*key)->ref > 0)
    1568          38 :         return 0;
    1569             : 
    1570           0 :     if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {
    1571           0 :         if ((*key)->private_key.rsa)
    1572           0 :             RSA_free((*key)->private_key.rsa);
    1573           0 :     } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid,
    1574           0 :                                                ASN1_OID_ID_ECPUBLICKEY) == 0 &&
    1575           0 :                (*key)->private_key.ecdsa != NULL) {
    1576           0 :       _hx509_private_eckey_free((*key)->private_key.ecdsa);
    1577             :     }
    1578           0 :     (*key)->private_key.rsa = NULL;
    1579           0 :     free(*key);
    1580           0 :     *key = NULL;
    1581           0 :     return 0;
    1582             : }
    1583             : 
    1584             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    1585           0 : hx509_private_key_assign_rsa(hx509_private_key key, void *ptr)
    1586             : {
    1587           0 :     if (key->private_key.rsa)
    1588           0 :         RSA_free(key->private_key.rsa);
    1589           0 :     key->private_key.rsa = ptr;
    1590           0 :     key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
    1591           0 :     key->md = &pkcs1_rsa_sha1_alg;
    1592           0 : }
    1593             : 
    1594             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1595           0 : _hx509_private_key_oid(hx509_context context,
    1596             :                        const hx509_private_key key,
    1597             :                        heim_oid *data)
    1598             : {
    1599             :     int ret;
    1600           0 :     ret = der_copy_oid(key->ops->key_oid, data);
    1601           0 :     if (ret)
    1602           0 :         hx509_set_error_string(context, 0, ret, "malloc out of memory");
    1603           0 :     return ret;
    1604             : }
    1605             : 
    1606             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1607           0 : _hx509_private_key_exportable(hx509_private_key key)
    1608             : {
    1609           0 :     if (key->ops->export == NULL)
    1610           0 :         return 0;
    1611           0 :     return 1;
    1612             : }
    1613             : 
    1614             : HX509_LIB_FUNCTION BIGNUM * HX509_LIB_CALL
    1615           0 : _hx509_private_key_get_internal(hx509_context context,
    1616             :                                 hx509_private_key key,
    1617             :                                 const char *type)
    1618             : {
    1619           0 :     if (key->ops->get_internal == NULL)
    1620           0 :         return NULL;
    1621           0 :     return (*key->ops->get_internal)(context, key, type);
    1622             : }
    1623             : 
    1624             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1625           0 : _hx509_private_key_export(hx509_context context,
    1626             :                           const hx509_private_key key,
    1627             :                           hx509_key_format_t format,
    1628             :                           heim_octet_string *data)
    1629             : {
    1630           0 :     data->length = 0;
    1631           0 :     data->data = NULL;
    1632           0 :     if (key->ops->export == NULL) {
    1633           0 :         hx509_clear_error_string(context);
    1634           0 :         return HX509_UNIMPLEMENTED_OPERATION;
    1635             :     }
    1636           0 :     if (format == HX509_KEY_FORMAT_PKCS8) {
    1637             :         PKCS8PrivateKeyInfo ki;
    1638             :         size_t size;
    1639             :         int ret;
    1640             : 
    1641           0 :         memset(&ki, 0, sizeof(ki));
    1642           0 :         ki.attributes = NULL; /* No localKeyId needed */
    1643           0 :         ki.privateKey.data = NULL;
    1644           0 :         ki.privateKeyAlgorithm.algorithm.components = NULL;
    1645           0 :         ret = der_parse_hex_heim_integer("00", &ki.version);
    1646           0 :         if (ret == 0)
    1647           0 :             ret = _hx509_private_key_oid(context, key,
    1648             :                                          &ki.privateKeyAlgorithm.algorithm);
    1649           0 :         if (ret == 0)
    1650             :             /* Re-enter */
    1651           0 :             ret = _hx509_private_key_export(context, key, HX509_KEY_FORMAT_DER,
    1652             :                                             &ki.privateKey);
    1653             : 
    1654             :         /*
    1655             :          * XXX To set ki.privateKeyAlgorithm.parameters we'll need to either
    1656             :          * move this code into the *key->ops->export() functions, or expand
    1657             :          * their signature to allow them to set it for us, or add a method to
    1658             :          * hx509_private_key_ops that allows us to get the parameters from the
    1659             :          * backend.
    1660             :          */
    1661           0 :         ki.privateKeyAlgorithm.parameters = NULL;
    1662             : 
    1663           0 :         if (ret == 0)
    1664           0 :             ASN1_MALLOC_ENCODE(PKCS8PrivateKeyInfo, data->data, data->length,
    1665             :                                &ki, &size, ret);
    1666           0 :         free_PKCS8PrivateKeyInfo(&ki);
    1667           0 :         if (ret == 0 && size != data->length)
    1668           0 :             ret = EINVAL;
    1669           0 :         if (ret)
    1670           0 :             hx509_set_error_string(context, 0, ret,
    1671             :                                    "Private key PKCS#8 encoding failed");
    1672           0 :         return ret;
    1673             :     }
    1674           0 :     return (*key->ops->export)(context, key, format, data);
    1675             : }
    1676             : 
    1677             : /*
    1678             :  *
    1679             :  */
    1680             : 
    1681             : struct hx509cipher {
    1682             :     const char *name;
    1683             :     int flags;
    1684             : #define CIPHER_WEAK 1
    1685             :     const heim_oid *oid;
    1686             :     const AlgorithmIdentifier *(*ai_func)(void);
    1687             :     const EVP_CIPHER *(*evp_func)(void);
    1688             :     int (*get_params)(hx509_context, const hx509_crypto,
    1689             :                       const heim_octet_string *, heim_octet_string *);
    1690             :     int (*set_params)(hx509_context, const heim_octet_string *,
    1691             :                       hx509_crypto, heim_octet_string *);
    1692             : };
    1693             : 
    1694             : struct hx509_crypto_data {
    1695             :     char *name;
    1696             :     int flags;
    1697             : #define ALLOW_WEAK      1
    1698             : 
    1699             : #define PADDING_NONE    2
    1700             : #define PADDING_PKCS7   4
    1701             : #define PADDING_FLAGS   (2|4)
    1702             :     const struct hx509cipher *cipher;
    1703             :     const EVP_CIPHER *c;
    1704             :     heim_octet_string key;
    1705             :     heim_oid oid;
    1706             :     void *param;
    1707             : };
    1708             : 
    1709             : /*
    1710             :  *
    1711             :  */
    1712             : 
    1713             : static unsigned private_rc2_40_oid_data[] = { 127, 1 };
    1714             : 
    1715             : static heim_oid asn1_oid_private_rc2_40 =
    1716             :     { 2, private_rc2_40_oid_data };
    1717             : 
    1718             : /*
    1719             :  *
    1720             :  */
    1721             : 
    1722             : static int
    1723           0 : CMSCBCParam_get(hx509_context context, const hx509_crypto crypto,
    1724             :                  const heim_octet_string *ivec, heim_octet_string *param)
    1725             : {
    1726             :     size_t size;
    1727             :     int ret;
    1728             : 
    1729           0 :     assert(crypto->param == NULL);
    1730           0 :     if (ivec == NULL)
    1731           0 :         return 0;
    1732             : 
    1733           0 :     ASN1_MALLOC_ENCODE(CMSCBCParameter, param->data, param->length,
    1734             :                        ivec, &size, ret);
    1735           0 :     if (ret == 0 && size != param->length)
    1736           0 :         _hx509_abort("Internal asn1 encoder failure");
    1737           0 :     if (ret)
    1738           0 :         hx509_clear_error_string(context);
    1739           0 :     return ret;
    1740             : }
    1741             : 
    1742             : static int
    1743           0 : CMSCBCParam_set(hx509_context context, const heim_octet_string *param,
    1744             :                 hx509_crypto crypto, heim_octet_string *ivec)
    1745             : {
    1746             :     int ret;
    1747           0 :     if (ivec == NULL)
    1748           0 :         return 0;
    1749             : 
    1750           0 :     ret = decode_CMSCBCParameter(param->data, param->length, ivec, NULL);
    1751           0 :     if (ret)
    1752           0 :         hx509_clear_error_string(context);
    1753             : 
    1754           0 :     return ret;
    1755             : }
    1756             : 
    1757             : struct _RC2_params {
    1758             :     int maximum_effective_key;
    1759             : };
    1760             : 
    1761             : static int
    1762           0 : CMSRC2CBCParam_get(hx509_context context, const hx509_crypto crypto,
    1763             :                    const heim_octet_string *ivec, heim_octet_string *param)
    1764             : {
    1765             :     CMSRC2CBCParameter rc2params;
    1766           0 :     const struct _RC2_params *p = crypto->param;
    1767           0 :     int maximum_effective_key = 128;
    1768             :     size_t size;
    1769             :     int ret;
    1770             : 
    1771           0 :     memset(&rc2params, 0, sizeof(rc2params));
    1772             : 
    1773           0 :     if (p)
    1774           0 :         maximum_effective_key = p->maximum_effective_key;
    1775             : 
    1776           0 :     switch(maximum_effective_key) {
    1777           0 :     case 40:
    1778           0 :         rc2params.rc2ParameterVersion = 160;
    1779           0 :         break;
    1780           0 :     case 64:
    1781           0 :         rc2params.rc2ParameterVersion = 120;
    1782           0 :         break;
    1783           0 :     case 128:
    1784           0 :         rc2params.rc2ParameterVersion = 58;
    1785           0 :         break;
    1786             :     }
    1787           0 :     rc2params.iv = *ivec;
    1788             : 
    1789           0 :     ASN1_MALLOC_ENCODE(CMSRC2CBCParameter, param->data, param->length,
    1790             :                        &rc2params, &size, ret);
    1791           0 :     if (ret == 0 && size != param->length)
    1792           0 :         _hx509_abort("Internal asn1 encoder failure");
    1793             : 
    1794           0 :     return ret;
    1795             : }
    1796             : 
    1797             : static int
    1798           0 : CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,
    1799             :                    hx509_crypto crypto, heim_octet_string *ivec)
    1800             : {
    1801             :     CMSRC2CBCParameter rc2param;
    1802             :     struct _RC2_params *p;
    1803             :     size_t size;
    1804             :     int ret;
    1805             : 
    1806           0 :     ret = decode_CMSRC2CBCParameter(param->data, param->length,
    1807             :                                     &rc2param, &size);
    1808           0 :     if (ret) {
    1809           0 :         hx509_clear_error_string(context);
    1810           0 :         return ret;
    1811             :     }
    1812             : 
    1813           0 :     p = calloc(1, sizeof(*p));
    1814           0 :     if (p == NULL) {
    1815           0 :         free_CMSRC2CBCParameter(&rc2param);
    1816           0 :         hx509_clear_error_string(context);
    1817           0 :         return ENOMEM;
    1818             :     }
    1819           0 :     switch(rc2param.rc2ParameterVersion) {
    1820           0 :     case 160:
    1821           0 :         crypto->c = EVP_rc2_40_cbc();
    1822           0 :         p->maximum_effective_key = 40;
    1823           0 :         break;
    1824           0 :     case 120:
    1825           0 :         crypto->c = EVP_rc2_64_cbc();
    1826           0 :         p->maximum_effective_key = 64;
    1827           0 :         break;
    1828           0 :     case 58:
    1829           0 :         crypto->c = EVP_rc2_cbc();
    1830           0 :         p->maximum_effective_key = 128;
    1831           0 :         break;
    1832           0 :     default:
    1833           0 :         free(p);
    1834           0 :         free_CMSRC2CBCParameter(&rc2param);
    1835           0 :         return HX509_CRYPTO_SIG_INVALID_FORMAT;
    1836             :     }
    1837           0 :     if (ivec)
    1838           0 :         ret = der_copy_octet_string(&rc2param.iv, ivec);
    1839           0 :     free_CMSRC2CBCParameter(&rc2param);
    1840           0 :     if (ret) {
    1841           0 :         free(p);
    1842           0 :         hx509_clear_error_string(context);
    1843             :     } else
    1844           0 :         crypto->param = p;
    1845             : 
    1846           0 :     return ret;
    1847             : }
    1848             : 
    1849             : /*
    1850             :  *
    1851             :  */
    1852             : 
    1853             : static const struct hx509cipher ciphers[] = {
    1854             :     {
    1855             :         "rc2-cbc",
    1856             :         CIPHER_WEAK,
    1857             :         ASN1_OID_ID_PKCS3_RC2_CBC,
    1858             :         NULL,
    1859             :         EVP_rc2_cbc,
    1860             :         CMSRC2CBCParam_get,
    1861             :         CMSRC2CBCParam_set
    1862             :     },
    1863             :     {
    1864             :         "rc2-cbc",
    1865             :         CIPHER_WEAK,
    1866             :         ASN1_OID_ID_RSADSI_RC2_CBC,
    1867             :         NULL,
    1868             :         EVP_rc2_cbc,
    1869             :         CMSRC2CBCParam_get,
    1870             :         CMSRC2CBCParam_set
    1871             :     },
    1872             :     {
    1873             :         "rc2-40-cbc",
    1874             :         CIPHER_WEAK,
    1875             :         &asn1_oid_private_rc2_40,
    1876             :         NULL,
    1877             :         EVP_rc2_40_cbc,
    1878             :         CMSRC2CBCParam_get,
    1879             :         CMSRC2CBCParam_set
    1880             :     },
    1881             :     {
    1882             :         "des-ede3-cbc",
    1883             :         0,
    1884             :         ASN1_OID_ID_PKCS3_DES_EDE3_CBC,
    1885             :         NULL,
    1886             :         EVP_des_ede3_cbc,
    1887             :         CMSCBCParam_get,
    1888             :         CMSCBCParam_set
    1889             :     },
    1890             :     {
    1891             :         "des-ede3-cbc",
    1892             :         0,
    1893             :         ASN1_OID_ID_RSADSI_DES_EDE3_CBC,
    1894             :         hx509_crypto_des_rsdi_ede3_cbc,
    1895             :         EVP_des_ede3_cbc,
    1896             :         CMSCBCParam_get,
    1897             :         CMSCBCParam_set
    1898             :     },
    1899             :     {
    1900             :         "aes-128-cbc",
    1901             :         0,
    1902             :         ASN1_OID_ID_AES_128_CBC,
    1903             :         hx509_crypto_aes128_cbc,
    1904             :         EVP_aes_128_cbc,
    1905             :         CMSCBCParam_get,
    1906             :         CMSCBCParam_set
    1907             :     },
    1908             :     {
    1909             :         "aes-192-cbc",
    1910             :         0,
    1911             :         ASN1_OID_ID_AES_192_CBC,
    1912             :         NULL,
    1913             :         EVP_aes_192_cbc,
    1914             :         CMSCBCParam_get,
    1915             :         CMSCBCParam_set
    1916             :     },
    1917             :     {
    1918             :         "aes-256-cbc",
    1919             :         0,
    1920             :         ASN1_OID_ID_AES_256_CBC,
    1921             :         hx509_crypto_aes256_cbc,
    1922             :         EVP_aes_256_cbc,
    1923             :         CMSCBCParam_get,
    1924             :         CMSCBCParam_set
    1925             :     }
    1926             : };
    1927             : 
    1928             : static const struct hx509cipher *
    1929           0 : find_cipher_by_oid(const heim_oid *oid)
    1930             : {
    1931             :     size_t i;
    1932             : 
    1933           0 :     for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)
    1934           0 :         if (der_heim_oid_cmp(oid, ciphers[i].oid) == 0)
    1935           0 :             return &ciphers[i];
    1936             : 
    1937           0 :     return NULL;
    1938             : }
    1939             : 
    1940             : static const struct hx509cipher *
    1941           0 : find_cipher_by_name(const char *name)
    1942             : {
    1943             :     size_t i;
    1944             : 
    1945           0 :     for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)
    1946           0 :         if (strcasecmp(name, ciphers[i].name) == 0)
    1947           0 :             return &ciphers[i];
    1948             : 
    1949           0 :     return NULL;
    1950             : }
    1951             : 
    1952             : 
    1953             : HX509_LIB_FUNCTION const heim_oid * HX509_LIB_CALL
    1954           0 : hx509_crypto_enctype_by_name(const char *name)
    1955             : {
    1956             :     const struct hx509cipher *cipher;
    1957             : 
    1958           0 :     cipher = find_cipher_by_name(name);
    1959           0 :     if (cipher == NULL)
    1960           0 :         return NULL;
    1961           0 :     return cipher->oid;
    1962             : }
    1963             : 
    1964             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1965           0 : hx509_crypto_init(hx509_context context,
    1966             :                   const char *provider,
    1967             :                   const heim_oid *enctype,
    1968             :                   hx509_crypto *crypto)
    1969             : {
    1970             :     const struct hx509cipher *cipher;
    1971             : 
    1972           0 :     *crypto = NULL;
    1973             : 
    1974           0 :     cipher = find_cipher_by_oid(enctype);
    1975           0 :     if (cipher == NULL) {
    1976           0 :         hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
    1977             :                                "Algorithm not supported");
    1978           0 :         return HX509_ALG_NOT_SUPP;
    1979             :     }
    1980             : 
    1981           0 :     *crypto = calloc(1, sizeof(**crypto));
    1982           0 :     if (*crypto == NULL) {
    1983           0 :         hx509_clear_error_string(context);
    1984           0 :         return ENOMEM;
    1985             :     }
    1986             : 
    1987           0 :     (*crypto)->flags = PADDING_PKCS7;
    1988           0 :     (*crypto)->cipher = cipher;
    1989           0 :     (*crypto)->c = (*cipher->evp_func)();
    1990             : 
    1991           0 :     if (der_copy_oid(enctype, &(*crypto)->oid)) {
    1992           0 :         hx509_crypto_destroy(*crypto);
    1993           0 :         *crypto = NULL;
    1994           0 :         hx509_clear_error_string(context);
    1995           0 :         return ENOMEM;
    1996             :     }
    1997             : 
    1998           0 :     return 0;
    1999             : }
    2000             : 
    2001             : HX509_LIB_FUNCTION const char * HX509_LIB_CALL
    2002           0 : hx509_crypto_provider(hx509_crypto crypto)
    2003             : {
    2004           0 :     return "unknown";
    2005             : }
    2006             : 
    2007             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    2008           0 : hx509_crypto_destroy(hx509_crypto crypto)
    2009             : {
    2010           0 :     if (crypto->name)
    2011           0 :         free(crypto->name);
    2012           0 :     if (crypto->key.data)
    2013           0 :         free(crypto->key.data);
    2014           0 :     if (crypto->param)
    2015           0 :         free(crypto->param);
    2016           0 :     der_free_oid(&crypto->oid);
    2017           0 :     memset(crypto, 0, sizeof(*crypto));
    2018           0 :     free(crypto);
    2019           0 : }
    2020             : 
    2021             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2022           0 : hx509_crypto_set_key_name(hx509_crypto crypto, const char *name)
    2023             : {
    2024           0 :     return 0;
    2025             : }
    2026             : 
    2027             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    2028           0 : hx509_crypto_allow_weak(hx509_crypto crypto)
    2029             : {
    2030           0 :     crypto->flags |= ALLOW_WEAK;
    2031           0 : }
    2032             : 
    2033             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    2034           0 : hx509_crypto_set_padding(hx509_crypto crypto, int padding_type)
    2035             : {
    2036           0 :     switch (padding_type) {
    2037           0 :     case HX509_CRYPTO_PADDING_PKCS7:
    2038           0 :         crypto->flags &= ~PADDING_FLAGS;
    2039           0 :         crypto->flags |= PADDING_PKCS7;
    2040           0 :         break;
    2041           0 :     case HX509_CRYPTO_PADDING_NONE:
    2042           0 :         crypto->flags &= ~PADDING_FLAGS;
    2043           0 :         crypto->flags |= PADDING_NONE;
    2044           0 :         break;
    2045           0 :     default:
    2046           0 :         _hx509_abort("Invalid padding");
    2047             :     }
    2048           0 : }
    2049             : 
    2050             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2051           0 : hx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length)
    2052             : {
    2053           0 :     if (EVP_CIPHER_key_length(crypto->c) > (int)length)
    2054           0 :         return HX509_CRYPTO_INTERNAL_ERROR;
    2055             : 
    2056           0 :     if (crypto->key.data) {
    2057           0 :         free(crypto->key.data);
    2058           0 :         crypto->key.data = NULL;
    2059           0 :         crypto->key.length = 0;
    2060             :     }
    2061           0 :     crypto->key.data = malloc(length);
    2062           0 :     if (crypto->key.data == NULL)
    2063           0 :         return ENOMEM;
    2064           0 :     memcpy(crypto->key.data, data, length);
    2065           0 :     crypto->key.length = length;
    2066             : 
    2067           0 :     return 0;
    2068             : }
    2069             : 
    2070             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2071           0 : hx509_crypto_set_random_key(hx509_crypto crypto, heim_octet_string *key)
    2072             : {
    2073           0 :     if (crypto->key.data) {
    2074           0 :         free(crypto->key.data);
    2075           0 :         crypto->key.length = 0;
    2076             :     }
    2077             : 
    2078           0 :     crypto->key.length = EVP_CIPHER_key_length(crypto->c);
    2079           0 :     crypto->key.data = malloc(crypto->key.length);
    2080           0 :     if (crypto->key.data == NULL) {
    2081           0 :         crypto->key.length = 0;
    2082           0 :         return ENOMEM;
    2083             :     }
    2084           0 :     if (RAND_bytes(crypto->key.data, crypto->key.length) <= 0) {
    2085           0 :         free(crypto->key.data);
    2086           0 :         crypto->key.data = NULL;
    2087           0 :         crypto->key.length = 0;
    2088           0 :         return HX509_CRYPTO_INTERNAL_ERROR;
    2089             :     }
    2090           0 :     if (key)
    2091           0 :         return der_copy_octet_string(&crypto->key, key);
    2092             :     else
    2093           0 :         return 0;
    2094             : }
    2095             : 
    2096             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2097           0 : hx509_crypto_set_params(hx509_context context,
    2098             :                         hx509_crypto crypto,
    2099             :                         const heim_octet_string *param,
    2100             :                         heim_octet_string *ivec)
    2101             : {
    2102           0 :     return (*crypto->cipher->set_params)(context, param, crypto, ivec);
    2103             : }
    2104             : 
    2105             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2106           0 : hx509_crypto_get_params(hx509_context context,
    2107             :                         hx509_crypto crypto,
    2108             :                         const heim_octet_string *ivec,
    2109             :                         heim_octet_string *param)
    2110             : {
    2111           0 :     return (*crypto->cipher->get_params)(context, crypto, ivec, param);
    2112             : }
    2113             : 
    2114             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2115           0 : hx509_crypto_random_iv(hx509_crypto crypto, heim_octet_string *ivec)
    2116             : {
    2117           0 :     ivec->length = EVP_CIPHER_iv_length(crypto->c);
    2118           0 :     ivec->data = malloc(ivec->length);
    2119           0 :     if (ivec->data == NULL) {
    2120           0 :         ivec->length = 0;
    2121           0 :         return ENOMEM;
    2122             :     }
    2123             : 
    2124           0 :     if (RAND_bytes(ivec->data, ivec->length) <= 0) {
    2125           0 :         free(ivec->data);
    2126           0 :         ivec->data = NULL;
    2127           0 :         ivec->length = 0;
    2128           0 :         return HX509_CRYPTO_INTERNAL_ERROR;
    2129             :     }
    2130           0 :     return 0;
    2131             : }
    2132             : 
    2133             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2134           0 : hx509_crypto_encrypt(hx509_crypto crypto,
    2135             :                      const void *data,
    2136             :                      const size_t length,
    2137             :                      const heim_octet_string *ivec,
    2138             :                      heim_octet_string **ciphertext)
    2139             : {
    2140             :     EVP_CIPHER_CTX evp;
    2141             :     size_t padsize, bsize;
    2142             :     int ret;
    2143             : 
    2144           0 :     *ciphertext = NULL;
    2145             : 
    2146           0 :     if ((crypto->cipher->flags & CIPHER_WEAK) &&
    2147           0 :         (crypto->flags & ALLOW_WEAK) == 0)
    2148           0 :         return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
    2149             : 
    2150           0 :     assert(EVP_CIPHER_iv_length(crypto->c) == (int)ivec->length);
    2151             : 
    2152           0 :     EVP_CIPHER_CTX_init(&evp);
    2153             : 
    2154           0 :     ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
    2155           0 :                             crypto->key.data, ivec->data, 1);
    2156           0 :     if (ret != 1) {
    2157           0 :         EVP_CIPHER_CTX_cleanup(&evp);
    2158           0 :         ret = HX509_CRYPTO_INTERNAL_ERROR;
    2159           0 :         goto out;
    2160             :     }
    2161             : 
    2162           0 :     *ciphertext = calloc(1, sizeof(**ciphertext));
    2163           0 :     if (*ciphertext == NULL) {
    2164           0 :         ret = ENOMEM;
    2165           0 :         goto out;
    2166             :     }
    2167             : 
    2168           0 :     assert(crypto->flags & PADDING_FLAGS);
    2169             : 
    2170           0 :     bsize = EVP_CIPHER_block_size(crypto->c);
    2171           0 :     padsize = 0;
    2172             : 
    2173           0 :     if (crypto->flags & PADDING_NONE) {
    2174           0 :         if (bsize != 1 && (length % bsize) != 0)
    2175           0 :             return HX509_CMS_PADDING_ERROR;
    2176           0 :     } else if (crypto->flags & PADDING_PKCS7) {
    2177           0 :         if (bsize != 1)
    2178           0 :             padsize = bsize - (length % bsize);
    2179             :     }
    2180             : 
    2181           0 :     (*ciphertext)->length = length + padsize;
    2182           0 :     (*ciphertext)->data = malloc(length + padsize);
    2183           0 :     if ((*ciphertext)->data == NULL) {
    2184           0 :         ret = ENOMEM;
    2185           0 :         goto out;
    2186             :     }
    2187             : 
    2188           0 :     memcpy((*ciphertext)->data, data, length);
    2189           0 :     if (padsize) {
    2190             :         size_t i;
    2191           0 :         unsigned char *p = (*ciphertext)->data;
    2192           0 :         p += length;
    2193           0 :         for (i = 0; i < padsize; i++)
    2194           0 :             *p++ = padsize;
    2195             :     }
    2196             : 
    2197           0 :     ret = EVP_Cipher(&evp, (*ciphertext)->data,
    2198           0 :                      (*ciphertext)->data,
    2199             :                      length + padsize);
    2200           0 :     if (ret != 1) {
    2201           0 :         ret = HX509_CRYPTO_INTERNAL_ERROR;
    2202           0 :         goto out;
    2203             :     }
    2204           0 :     ret = 0;
    2205             : 
    2206           0 :  out:
    2207           0 :     if (ret) {
    2208           0 :         if (*ciphertext) {
    2209           0 :             if ((*ciphertext)->data) {
    2210           0 :                 free((*ciphertext)->data);
    2211             :             }
    2212           0 :             free(*ciphertext);
    2213           0 :             *ciphertext = NULL;
    2214             :         }
    2215             :     }
    2216           0 :     EVP_CIPHER_CTX_cleanup(&evp);
    2217             : 
    2218           0 :     return ret;
    2219             : }
    2220             : 
    2221             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2222           0 : hx509_crypto_decrypt(hx509_crypto crypto,
    2223             :                      const void *data,
    2224             :                      const size_t length,
    2225             :                      heim_octet_string *ivec,
    2226             :                      heim_octet_string *clear)
    2227             : {
    2228             :     EVP_CIPHER_CTX evp;
    2229           0 :     void *idata = NULL;
    2230             :     int ret;
    2231             : 
    2232           0 :     clear->data = NULL;
    2233           0 :     clear->length = 0;
    2234             : 
    2235           0 :     if ((crypto->cipher->flags & CIPHER_WEAK) &&
    2236           0 :         (crypto->flags & ALLOW_WEAK) == 0)
    2237           0 :         return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
    2238             : 
    2239           0 :     if (ivec && EVP_CIPHER_iv_length(crypto->c) < (int)ivec->length)
    2240           0 :         return HX509_CRYPTO_INTERNAL_ERROR;
    2241             : 
    2242           0 :     if (crypto->key.data == NULL)
    2243           0 :         return HX509_CRYPTO_INTERNAL_ERROR;
    2244             : 
    2245           0 :     if (ivec)
    2246           0 :         idata = ivec->data;
    2247             : 
    2248           0 :     EVP_CIPHER_CTX_init(&evp);
    2249             : 
    2250           0 :     ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
    2251           0 :                             crypto->key.data, idata, 0);
    2252           0 :     if (ret != 1) {
    2253           0 :         EVP_CIPHER_CTX_cleanup(&evp);
    2254           0 :         return HX509_CRYPTO_INTERNAL_ERROR;
    2255             :     }
    2256             : 
    2257           0 :     clear->length = length;
    2258           0 :     clear->data = malloc(length);
    2259           0 :     if (clear->data == NULL) {
    2260           0 :         EVP_CIPHER_CTX_cleanup(&evp);
    2261           0 :         clear->length = 0;
    2262           0 :         return ENOMEM;
    2263             :     }
    2264             : 
    2265           0 :     if (EVP_Cipher(&evp, clear->data, data, length) != 1) {
    2266           0 :         return HX509_CRYPTO_INTERNAL_ERROR;
    2267             :     }
    2268           0 :     EVP_CIPHER_CTX_cleanup(&evp);
    2269             : 
    2270           0 :     if ((crypto->flags & PADDING_PKCS7) && EVP_CIPHER_block_size(crypto->c) > 1) {
    2271             :         int padsize;
    2272             :         unsigned char *p;
    2273           0 :         int j, bsize = EVP_CIPHER_block_size(crypto->c);
    2274             : 
    2275           0 :         if ((int)clear->length < bsize) {
    2276           0 :             ret = HX509_CMS_PADDING_ERROR;
    2277           0 :             goto out;
    2278             :         }
    2279             : 
    2280           0 :         p = clear->data;
    2281           0 :         p += clear->length - 1;
    2282           0 :         padsize = *p;
    2283           0 :         if (padsize > bsize) {
    2284           0 :             ret = HX509_CMS_PADDING_ERROR;
    2285           0 :             goto out;
    2286             :         }
    2287           0 :         clear->length -= padsize;
    2288           0 :         for (j = 0; j < padsize; j++) {
    2289           0 :             if (*p-- != padsize) {
    2290           0 :                 ret = HX509_CMS_PADDING_ERROR;
    2291           0 :                 goto out;
    2292             :             }
    2293             :         }
    2294             :     }
    2295             : 
    2296           0 :     return 0;
    2297             : 
    2298           0 :  out:
    2299           0 :     if (clear->data)
    2300           0 :         free(clear->data);
    2301           0 :     clear->data = NULL;
    2302           0 :     clear->length = 0;
    2303           0 :     return ret;
    2304             : }
    2305             : 
    2306             : typedef int (*PBE_string2key_func)(hx509_context,
    2307             :                                    const char *,
    2308             :                                    const heim_octet_string *,
    2309             :                                    hx509_crypto *, heim_octet_string *,
    2310             :                                    heim_octet_string *,
    2311             :                                    const heim_oid *, const EVP_MD *);
    2312             : 
    2313             : static int
    2314           0 : PBE_string2key(hx509_context context,
    2315             :                const char *password,
    2316             :                const heim_octet_string *parameters,
    2317             :                hx509_crypto *crypto,
    2318             :                heim_octet_string *key, heim_octet_string *iv,
    2319             :                const heim_oid *enc_oid,
    2320             :                const EVP_MD *md)
    2321             : {
    2322             :     PKCS12_PBEParams p12params;
    2323             :     int passwordlen;
    2324             :     hx509_crypto c;
    2325             :     int iter, saltlen, ret;
    2326             :     unsigned char *salt;
    2327             : 
    2328           0 :     passwordlen = password ? strlen(password) : 0;
    2329             : 
    2330           0 :     if (parameters == NULL)
    2331           0 :         return HX509_ALG_NOT_SUPP;
    2332             : 
    2333           0 :     ret = decode_PKCS12_PBEParams(parameters->data,
    2334             :                                   parameters->length,
    2335             :                                   &p12params, NULL);
    2336           0 :     if (ret)
    2337           0 :         goto out;
    2338             : 
    2339           0 :     if (p12params.iterations)
    2340           0 :         iter = *p12params.iterations;
    2341             :     else
    2342           0 :         iter = 1;
    2343           0 :     salt = p12params.salt.data;
    2344           0 :     saltlen = p12params.salt.length;
    2345             : 
    2346           0 :     if (!PKCS12_key_gen (password, passwordlen, salt, saltlen,
    2347             :                          PKCS12_KEY_ID, iter, key->length, key->data, md)) {
    2348           0 :         ret = HX509_CRYPTO_INTERNAL_ERROR;
    2349           0 :         goto out;
    2350             :     }
    2351             : 
    2352           0 :     if (!PKCS12_key_gen (password, passwordlen, salt, saltlen,
    2353             :                          PKCS12_IV_ID, iter, iv->length, iv->data, md)) {
    2354           0 :         ret = HX509_CRYPTO_INTERNAL_ERROR;
    2355           0 :         goto out;
    2356             :     }
    2357             : 
    2358           0 :     ret = hx509_crypto_init(context, NULL, enc_oid, &c);
    2359           0 :     if (ret)
    2360           0 :         goto out;
    2361             : 
    2362           0 :     hx509_crypto_allow_weak(c);
    2363             : 
    2364           0 :     ret = hx509_crypto_set_key_data(c, key->data, key->length);
    2365           0 :     if (ret) {
    2366           0 :         hx509_crypto_destroy(c);
    2367           0 :         goto out;
    2368             :     }
    2369             : 
    2370           0 :     *crypto = c;
    2371           0 : out:
    2372           0 :     free_PKCS12_PBEParams(&p12params);
    2373           0 :     return ret;
    2374             : }
    2375             : 
    2376             : static const heim_oid *
    2377           0 : find_string2key(const heim_oid *oid,
    2378             :                 const EVP_CIPHER **c,
    2379             :                 const EVP_MD **md,
    2380             :                 PBE_string2key_func *s2k)
    2381             : {
    2382           0 :     if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC2_CBC) == 0) {
    2383           0 :         *c = EVP_rc2_40_cbc();
    2384           0 :         if (*c == NULL)
    2385           0 :             return NULL;
    2386           0 :         *md = EVP_sha1();
    2387           0 :         if (*md == NULL)
    2388           0 :             return NULL;
    2389           0 :         *s2k = PBE_string2key;
    2390           0 :         return &asn1_oid_private_rc2_40;
    2391           0 :     } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC2_CBC) == 0) {
    2392           0 :         *c = EVP_rc2_cbc();
    2393           0 :         if (*c == NULL)
    2394           0 :             return NULL;
    2395           0 :         *md = EVP_sha1();
    2396           0 :         if (*md == NULL)
    2397           0 :             return NULL;
    2398           0 :         *s2k = PBE_string2key;
    2399           0 :         return ASN1_OID_ID_PKCS3_RC2_CBC;
    2400             : #if 0
    2401             :     } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC4) == 0) {
    2402             :         *c = EVP_rc4_40();
    2403             :         if (*c == NULL)
    2404             :             return NULL;
    2405             :         *md = EVP_sha1();
    2406             :         if (*md == NULL)
    2407             :             return NULL;
    2408             :         *s2k = PBE_string2key;
    2409             :         return NULL;
    2410             :     } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC4) == 0) {
    2411             :         *c = EVP_rc4();
    2412             :         if (*c == NULL)
    2413             :             return NULL;
    2414             :         *md = EVP_sha1();
    2415             :         if (*md == NULL)
    2416             :             return NULL;
    2417             :         *s2k = PBE_string2key;
    2418             :         return ASN1_OID_ID_PKCS3_RC4;
    2419             : #endif
    2420           0 :     } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND3_KEYTRIPLEDES_CBC) == 0) {
    2421           0 :         *c = EVP_des_ede3_cbc();
    2422           0 :         if (*c == NULL)
    2423           0 :             return NULL;
    2424           0 :         *md = EVP_sha1();
    2425           0 :         if (*md == NULL)
    2426           0 :             return NULL;
    2427           0 :         *s2k = PBE_string2key;
    2428           0 :         return ASN1_OID_ID_PKCS3_DES_EDE3_CBC;
    2429             :     }
    2430             : 
    2431           0 :     return NULL;
    2432             : }
    2433             : 
    2434             : /*
    2435             :  *
    2436             :  */
    2437             : 
    2438             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2439           0 : _hx509_pbe_encrypt(hx509_context context,
    2440             :                    hx509_lock lock,
    2441             :                    const AlgorithmIdentifier *ai,
    2442             :                    const heim_octet_string *content,
    2443             :                    heim_octet_string *econtent)
    2444             : {
    2445           0 :     hx509_clear_error_string(context);
    2446           0 :     return EINVAL;
    2447             : }
    2448             : 
    2449             : /*
    2450             :  *
    2451             :  */
    2452             : 
    2453             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2454           0 : _hx509_pbe_decrypt(hx509_context context,
    2455             :                    hx509_lock lock,
    2456             :                    const AlgorithmIdentifier *ai,
    2457             :                    const heim_octet_string *econtent,
    2458             :                    heim_octet_string *content)
    2459             : {
    2460             :     const struct _hx509_password *pw;
    2461             :     heim_octet_string key, iv;
    2462             :     const heim_oid *enc_oid;
    2463             :     const EVP_CIPHER *c;
    2464             :     const EVP_MD *md;
    2465             :     PBE_string2key_func s2k;
    2466           0 :     int ret = 0;
    2467             :     size_t i;
    2468             : 
    2469           0 :     memset(&key, 0, sizeof(key));
    2470           0 :     memset(&iv, 0, sizeof(iv));
    2471             : 
    2472           0 :     memset(content, 0, sizeof(*content));
    2473             : 
    2474           0 :     enc_oid = find_string2key(&ai->algorithm, &c, &md, &s2k);
    2475           0 :     if (enc_oid == NULL) {
    2476           0 :         hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
    2477             :                                "String to key algorithm not supported");
    2478           0 :         ret = HX509_ALG_NOT_SUPP;
    2479           0 :         goto out;
    2480             :     }
    2481             : 
    2482           0 :     key.length = EVP_CIPHER_key_length(c);
    2483           0 :     key.data = malloc(key.length);
    2484           0 :     if (key.data == NULL) {
    2485           0 :         ret = ENOMEM;
    2486           0 :         hx509_clear_error_string(context);
    2487           0 :         goto out;
    2488             :     }
    2489             : 
    2490           0 :     iv.length = EVP_CIPHER_iv_length(c);
    2491           0 :     iv.data = malloc(iv.length);
    2492           0 :     if (iv.data == NULL) {
    2493           0 :         ret = ENOMEM;
    2494           0 :         hx509_clear_error_string(context);
    2495           0 :         goto out;
    2496             :     }
    2497             : 
    2498           0 :     pw = _hx509_lock_get_passwords(lock);
    2499             : 
    2500           0 :     ret = HX509_CRYPTO_INTERNAL_ERROR;
    2501           0 :     for (i = 0; i < pw->len + 1; i++) {
    2502             :         hx509_crypto crypto;
    2503             :         const char *password;
    2504             : 
    2505           0 :         if (i < pw->len)
    2506           0 :             password = pw->val[i];
    2507           0 :         else if (i < pw->len + 1)
    2508           0 :             password = "";
    2509             :         else
    2510           0 :             password = NULL;
    2511             : 
    2512           0 :         ret = (*s2k)(context, password, ai->parameters, &crypto,
    2513             :                      &key, &iv, enc_oid, md);
    2514           0 :         if (ret)
    2515           0 :             goto out;
    2516             : 
    2517           0 :         ret = hx509_crypto_decrypt(crypto,
    2518           0 :                                    econtent->data,
    2519             :                                    econtent->length,
    2520             :                                    &iv,
    2521             :                                    content);
    2522           0 :         hx509_crypto_destroy(crypto);
    2523           0 :         if (ret == 0)
    2524           0 :             goto out;
    2525             : 
    2526             :     }
    2527           0 : out:
    2528           0 :     if (key.data)
    2529           0 :         der_free_octet_string(&key);
    2530           0 :     if (iv.data)
    2531           0 :         der_free_octet_string(&iv);
    2532           0 :     return ret;
    2533             : }
    2534             : 
    2535             : /*
    2536             :  *
    2537             :  */
    2538             : 
    2539             : 
    2540             : static int
    2541          38 : match_keys_rsa(hx509_cert c, hx509_private_key private_key)
    2542             : {
    2543             :     const Certificate *cert;
    2544             :     const SubjectPublicKeyInfo *spi;
    2545             :     RSAPublicKey pk;
    2546             :     RSA *rsa;
    2547             :     size_t size;
    2548             :     int ret;
    2549             : 
    2550          38 :     if (private_key->private_key.rsa == NULL)
    2551           0 :         return 0;
    2552             : 
    2553          38 :     rsa = private_key->private_key.rsa;
    2554          38 :     if (rsa->d == NULL || rsa->p == NULL || rsa->q == NULL)
    2555           0 :         return 0;
    2556             : 
    2557          38 :     cert = _hx509_get_cert(c);
    2558          38 :     spi = &cert->tbsCertificate.subjectPublicKeyInfo;
    2559             : 
    2560          38 :     rsa = RSA_new();
    2561          38 :     if (rsa == NULL)
    2562           0 :         return 0;
    2563             : 
    2564          38 :     ret = decode_RSAPublicKey(spi->subjectPublicKey.data,
    2565          38 :                               spi->subjectPublicKey.length / 8,
    2566             :                               &pk, &size);
    2567          38 :     if (ret) {
    2568           0 :         RSA_free(rsa);
    2569           0 :         return 0;
    2570             :     }
    2571          38 :     rsa->n = heim_int2BN(&pk.modulus);
    2572          38 :     rsa->e = heim_int2BN(&pk.publicExponent);
    2573             : 
    2574          38 :     free_RSAPublicKey(&pk);
    2575             : 
    2576          38 :     rsa->d = BN_dup(private_key->private_key.rsa->d);
    2577          38 :     rsa->p = BN_dup(private_key->private_key.rsa->p);
    2578          38 :     rsa->q = BN_dup(private_key->private_key.rsa->q);
    2579          38 :     rsa->dmp1 = BN_dup(private_key->private_key.rsa->dmp1);
    2580          38 :     rsa->dmq1 = BN_dup(private_key->private_key.rsa->dmq1);
    2581          38 :     rsa->iqmp = BN_dup(private_key->private_key.rsa->iqmp);
    2582             : 
    2583          76 :     if (rsa->n == NULL || rsa->e == NULL ||
    2584         114 :         rsa->d == NULL || rsa->p == NULL|| rsa->q == NULL ||
    2585          76 :         rsa->dmp1 == NULL || rsa->dmq1 == NULL) {
    2586           0 :         RSA_free(rsa);
    2587           0 :         return 0;
    2588             :     }
    2589             : 
    2590          38 :     ret = RSA_check_key(rsa);
    2591          38 :     RSA_free(rsa);
    2592             : 
    2593          38 :     return ret == 1;
    2594             : }
    2595             : 
    2596             : static int
    2597           0 : match_keys_ec(hx509_cert c, hx509_private_key private_key)
    2598             : {
    2599           0 :     return 1; /* XXX use EC_KEY_check_key */
    2600             : }
    2601             : 
    2602             : 
    2603             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2604          38 : _hx509_match_keys(hx509_cert c, hx509_private_key key)
    2605             : {
    2606          38 :     if (!key->ops)
    2607           0 :         return 0;
    2608          38 :     if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0)
    2609          38 :         return match_keys_rsa(c, key);
    2610           0 :     if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0)
    2611           0 :         return match_keys_ec(c, key);
    2612           0 :     return 0;
    2613             : 
    2614             : }
    2615             : 
    2616             : 
    2617             : static const heim_oid *
    2618           0 : find_keytype(const hx509_private_key key)
    2619             : {
    2620             :     const struct signature_alg *md;
    2621             : 
    2622           0 :     if (key == NULL)
    2623           0 :         return NULL;
    2624             : 
    2625           0 :     md = _hx509_find_sig_alg(key->signature_alg);
    2626           0 :     if (md == NULL)
    2627           0 :         return NULL;
    2628           0 :     return md->key_oid;
    2629             : }
    2630             : 
    2631             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2632           0 : hx509_crypto_select(const hx509_context context,
    2633             :                     int type,
    2634             :                     const hx509_private_key source,
    2635             :                     hx509_peer_info peer,
    2636             :                     AlgorithmIdentifier *selected)
    2637             : {
    2638           0 :     const AlgorithmIdentifier *def = NULL;
    2639             :     size_t i, j;
    2640             :     int ret, bits;
    2641             : 
    2642           0 :     memset(selected, 0, sizeof(*selected));
    2643             : 
    2644           0 :     if (type == HX509_SELECT_DIGEST) {
    2645           0 :         bits = SIG_DIGEST;
    2646           0 :         if (source)
    2647           0 :             def = alg_for_privatekey(source, type);
    2648           0 :         if (def == NULL)
    2649           0 :             def = _hx509_crypto_default_digest_alg;
    2650           0 :     } else if (type == HX509_SELECT_PUBLIC_SIG) {
    2651           0 :         bits = SIG_PUBLIC_SIG;
    2652             :         /* XXX depend on `source´ and `peer´ */
    2653           0 :         if (source)
    2654           0 :             def = alg_for_privatekey(source, type);
    2655           0 :         if (def == NULL)
    2656           0 :             def = _hx509_crypto_default_sig_alg;
    2657           0 :     } else if (type == HX509_SELECT_SECRET_ENC) {
    2658           0 :         bits = SIG_SECRET;
    2659           0 :         def = _hx509_crypto_default_secret_alg;
    2660             :     } else {
    2661           0 :         hx509_set_error_string(context, 0, EINVAL,
    2662             :                                "Unknown type %d of selection", type);
    2663           0 :         return EINVAL;
    2664             :     }
    2665             : 
    2666           0 :     if (peer) {
    2667           0 :         const heim_oid *keytype = NULL;
    2668             : 
    2669           0 :         keytype = find_keytype(source);
    2670             : 
    2671           0 :         for (i = 0; i < peer->len; i++) {
    2672           0 :             for (j = 0; sig_algs[j]; j++) {
    2673           0 :                 if ((sig_algs[j]->flags & bits) != bits)
    2674           0 :                     continue;
    2675           0 :                 if (der_heim_oid_cmp(sig_algs[j]->sig_oid,
    2676           0 :                                      &peer->val[i].algorithm) != 0)
    2677           0 :                     continue;
    2678           0 :                 if (keytype && sig_algs[j]->key_oid &&
    2679           0 :                     der_heim_oid_cmp(keytype, sig_algs[j]->key_oid))
    2680           0 :                     continue;
    2681             : 
    2682             :                 /* found one, use that */
    2683           0 :                 ret = copy_AlgorithmIdentifier(&peer->val[i], selected);
    2684           0 :                 if (ret)
    2685           0 :                     hx509_clear_error_string(context);
    2686           0 :                 return ret;
    2687             :             }
    2688           0 :             if (bits & SIG_SECRET) {
    2689             :                 const struct hx509cipher *cipher;
    2690             : 
    2691           0 :                 cipher = find_cipher_by_oid(&peer->val[i].algorithm);
    2692           0 :                 if (cipher == NULL)
    2693           0 :                     continue;
    2694           0 :                 if (cipher->ai_func == NULL)
    2695           0 :                     continue;
    2696           0 :                 ret = copy_AlgorithmIdentifier(cipher->ai_func(), selected);
    2697           0 :                 if (ret)
    2698           0 :                     hx509_clear_error_string(context);
    2699           0 :                 return ret;
    2700             :             }
    2701             :         }
    2702             :     }
    2703             : 
    2704             :     /* use default */
    2705           0 :     ret = copy_AlgorithmIdentifier(def, selected);
    2706           0 :     if (ret)
    2707           0 :         hx509_clear_error_string(context);
    2708           0 :     return ret;
    2709             : }
    2710             : 
    2711             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2712          77 : hx509_crypto_available(hx509_context context,
    2713             :                        int type,
    2714             :                        hx509_cert source,
    2715             :                        AlgorithmIdentifier **val,
    2716             :                        unsigned int *plen)
    2717             : {
    2718          77 :     const heim_oid *keytype = NULL;
    2719             :     unsigned int len, i;
    2720             :     void *ptr;
    2721             :     int bits, ret;
    2722             : 
    2723          77 :     *val = NULL;
    2724             : 
    2725          77 :     if (type == HX509_SELECT_ALL) {
    2726          77 :         bits = SIG_DIGEST | SIG_PUBLIC_SIG | SIG_SECRET;
    2727           0 :     } else if (type == HX509_SELECT_DIGEST) {
    2728           0 :         bits = SIG_DIGEST;
    2729           0 :     } else if (type == HX509_SELECT_PUBLIC_SIG) {
    2730           0 :         bits = SIG_PUBLIC_SIG;
    2731             :     } else {
    2732           0 :         hx509_set_error_string(context, 0, EINVAL,
    2733             :                                "Unknown type %d of available", type);
    2734           0 :         return EINVAL;
    2735             :     }
    2736             : 
    2737          77 :     if (source)
    2738           0 :         keytype = find_keytype(_hx509_cert_private_key(source));
    2739             : 
    2740          77 :     len = 0;
    2741        1155 :     for (i = 0; sig_algs[i]; i++) {
    2742        1078 :         if ((sig_algs[i]->flags & bits) == 0)
    2743           0 :             continue;
    2744        1078 :         if (sig_algs[i]->sig_alg == NULL)
    2745          77 :             continue;
    2746        1001 :         if (keytype && sig_algs[i]->key_oid &&
    2747           0 :             der_heim_oid_cmp(sig_algs[i]->key_oid, keytype))
    2748           0 :             continue;
    2749             : 
    2750             :         /* found one, add that to the list */
    2751        1001 :         ptr = realloc(*val, sizeof(**val) * (len + 1));
    2752        1001 :         if (ptr == NULL)
    2753           0 :             goto out;
    2754        1001 :         *val = ptr;
    2755             : 
    2756        1001 :         ret = copy_AlgorithmIdentifier(sig_algs[i]->sig_alg, &(*val)[len]);
    2757        1001 :         if (ret)
    2758           0 :             goto out;
    2759        1001 :         len++;
    2760             :     }
    2761             : 
    2762             :     /* Add AES */
    2763          77 :     if (bits & SIG_SECRET) {
    2764             : 
    2765         693 :         for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) {
    2766             : 
    2767         616 :             if (ciphers[i].flags & CIPHER_WEAK)
    2768         231 :                 continue;
    2769         385 :             if (ciphers[i].ai_func == NULL)
    2770         154 :                 continue;
    2771             : 
    2772         231 :             ptr = realloc(*val, sizeof(**val) * (len + 1));
    2773         231 :             if (ptr == NULL)
    2774           0 :                 goto out;
    2775         231 :             *val = ptr;
    2776             : 
    2777         231 :             ret = copy_AlgorithmIdentifier((ciphers[i].ai_func)(), &(*val)[len]);
    2778         231 :             if (ret)
    2779           0 :                 goto out;
    2780         231 :             len++;
    2781             :         }
    2782             :     }
    2783             : 
    2784          77 :     *plen = len;
    2785          77 :     return 0;
    2786             : 
    2787           0 : out:
    2788           0 :     for (i = 0; i < len; i++)
    2789           0 :         free_AlgorithmIdentifier(&(*val)[i]);
    2790           0 :     free(*val);
    2791           0 :     *val = NULL;
    2792           0 :     hx509_set_error_string(context, 0, ENOMEM, "out of memory");
    2793           0 :     return ENOMEM;
    2794             : }
    2795             : 
    2796             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    2797           0 : hx509_crypto_free_algs(AlgorithmIdentifier *val,
    2798             :                        unsigned int len)
    2799             : {
    2800             :     unsigned int i;
    2801           0 :     for (i = 0; i < len; i++)
    2802           0 :         free_AlgorithmIdentifier(&val[i]);
    2803           0 :     free(val);
    2804           0 : }

Generated by: LCOV version 1.13