LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/hx509 - crypto-ec.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 0 6 0.0 %
Date: 2024-04-21 15:09:00 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 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 <config.h>
      35             : 
      36             : #ifdef HAVE_HCRYPTO_W_OPENSSL
      37             : #include <openssl/evp.h>
      38             : #include <openssl/ec.h>
      39             : #include <openssl/ecdsa.h>
      40             : #include <openssl/rsa.h>
      41             : #include <openssl/bn.h>
      42             : #include <openssl/objects.h>
      43             : #ifdef HAVE_OPENSSL_30
      44             : #include <openssl/asn1.h>
      45             : #include <openssl/core_names.h>
      46             : #endif
      47             : #define HEIM_NO_CRYPTO_HDRS
      48             : #endif /* HAVE_HCRYPTO_W_OPENSSL */
      49             : 
      50             : #include "hx_locl.h"
      51             : 
      52             : extern const AlgorithmIdentifier _hx509_signature_sha512_data;
      53             : extern const AlgorithmIdentifier _hx509_signature_sha384_data;
      54             : extern const AlgorithmIdentifier _hx509_signature_sha256_data;
      55             : extern const AlgorithmIdentifier _hx509_signature_sha1_data;
      56             : 
      57             : HX509_LIB_FUNCTION void HX509_LIB_CALL
      58           0 : _hx509_private_eckey_free(void *eckey)
      59             : {
      60             : #ifdef HAVE_HCRYPTO_W_OPENSSL
      61             : #ifdef HAVE_OPENSSL_30
      62             :     EVP_PKEY_free(eckey);
      63             : #else
      64             :     EC_KEY_free(eckey);
      65             : #endif
      66             : #endif
      67           0 : }
      68             : 
      69             : #ifdef HAVE_HCRYPTO_W_OPENSSL
      70             : static struct oid2nid_st {
      71             :     const heim_oid *oid;
      72             :     int nid;
      73             : } oid2nid[] = {
      74             :     { ASN1_OID_ID_EC_GROUP_SECP256R1, NID_X9_62_prime256v1 },
      75             : #ifdef NID_secp521r1
      76             :     { ASN1_OID_ID_EC_GROUP_SECP521R1, NID_secp521r1 },
      77             : #endif
      78             : #ifdef NID_secp384r1
      79             :     { ASN1_OID_ID_EC_GROUP_SECP384R1, NID_secp384r1 },
      80             : #endif
      81             : #ifdef NID_secp160r1
      82             :     { ASN1_OID_ID_EC_GROUP_SECP160R1, NID_secp160r1 },
      83             : #endif
      84             : #ifdef NID_secp160r2
      85             :     { ASN1_OID_ID_EC_GROUP_SECP160R2, NID_secp160r2 },
      86             : #endif
      87             :     /* XXX Add more!  Add X25519! */
      88             : };
      89             : 
      90             : int
      91             : _hx509_ossl_oid2nid(heim_oid *oid)
      92             : {
      93             :     size_t i;
      94             : 
      95             :     for (i = 0; i < sizeof(oid2nid)/sizeof(oid2nid[0]); i++)
      96             :         if (der_heim_oid_cmp(oid, oid2nid[i].oid) == 0)
      97             :             return oid2nid[i].nid;
      98             :     return NID_undef;
      99             : }
     100             : 
     101             : static int
     102             : ECParameters2nid(hx509_context context,
     103             :                  heim_octet_string *parameters,
     104             :                  int *nid)
     105             : {
     106             :     ECParameters ecparam;
     107             :     size_t size;
     108             :     int ret;
     109             : 
     110             :     if (parameters == NULL) {
     111             :         ret = HX509_PARSING_KEY_FAILED;
     112             :         hx509_set_error_string(context, 0, ret,
     113             :                                "EC parameters missing");
     114             :         return ret;
     115             :     }
     116             : 
     117             :     ret = decode_ECParameters(parameters->data, parameters->length,
     118             :                               &ecparam, &size);
     119             :     if (ret) {
     120             :         hx509_set_error_string(context, 0, ret,
     121             :                                "Failed to decode EC parameters");
     122             :         return ret;
     123             :     }
     124             : 
     125             :     if (ecparam.element != choice_ECParameters_namedCurve) {
     126             :         free_ECParameters(&ecparam);
     127             :         hx509_set_error_string(context, 0, ret,
     128             :                                "EC parameters is not a named curve");
     129             :         return HX509_CRYPTO_SIG_INVALID_FORMAT;
     130             :     }
     131             : 
     132             :     *nid = _hx509_ossl_oid2nid(&ecparam.u.namedCurve);
     133             :     free_ECParameters(&ecparam);
     134             :     if (*nid == NID_undef) {
     135             :         hx509_set_error_string(context, 0, ret,
     136             :                                "Failed to find matcing NID for EC curve");
     137             :         return HX509_CRYPTO_SIG_INVALID_FORMAT;
     138             :     }
     139             :     return 0;
     140             : }
     141             : 
     142             : #ifdef HAVE_OPENSSL_30
     143             : static const EVP_MD *
     144             : signature_alg2digest_evp_md(hx509_context context,
     145             :                             const AlgorithmIdentifier *digest_alg)
     146             : {
     147             :     if ((&digest_alg->algorithm == &asn1_oid_id_sha512 ||
     148             :          der_heim_oid_cmp(&digest_alg->algorithm, &asn1_oid_id_sha512) == 0))
     149             :         return EVP_sha512();
     150             :     if ((&digest_alg->algorithm == &asn1_oid_id_sha384 ||
     151             :          der_heim_oid_cmp(&digest_alg->algorithm, &asn1_oid_id_sha384) == 0))
     152             :         return EVP_sha384();
     153             :     if ((&digest_alg->algorithm == &asn1_oid_id_sha256 ||
     154             :          der_heim_oid_cmp(&digest_alg->algorithm, &asn1_oid_id_sha256) == 0))
     155             :         return EVP_sha256();
     156             :     if ((&digest_alg->algorithm == &asn1_oid_id_secsig_sha_1 ||
     157             :          der_heim_oid_cmp(&digest_alg->algorithm, &asn1_oid_id_secsig_sha_1) == 0))
     158             :         return EVP_sha1();
     159             :     if ((&digest_alg->algorithm == &asn1_oid_id_rsa_digest_md5 ||
     160             :          der_heim_oid_cmp(&digest_alg->algorithm,
     161             :                           &asn1_oid_id_rsa_digest_md5) == 0))
     162             :         return EVP_md5();
     163             : 
     164             :     /*
     165             :      * XXX Decode the `digest_alg->algorithm' OID and include it in the error
     166             :      * message.
     167             :      */
     168             :     hx509_set_error_string(context, 0, EINVAL,
     169             :                            "Digest algorithm not found");
     170             :     return NULL;
     171             : }
     172             : #endif
     173             : 
     174             : 
     175             : 
     176             : /*
     177             :  *
     178             :  */
     179             : 
     180             : static int
     181             : ecdsa_verify_signature(hx509_context context,
     182             :                        const struct signature_alg *sig_alg,
     183             :                        const Certificate *signer,
     184             :                        const AlgorithmIdentifier *alg,
     185             :                        const heim_octet_string *data,
     186             :                        const heim_octet_string *sig)
     187             : {
     188             : #ifdef HAVE_OPENSSL_30
     189             :     const AlgorithmIdentifier *digest_alg = sig_alg->digest_alg;
     190             :     const EVP_MD *md = signature_alg2digest_evp_md(context, digest_alg);
     191             :     const SubjectPublicKeyInfo *spi;
     192             :     const char *curve_sn = NULL; /* sn == short name in OpenSSL parlance */
     193             :     OSSL_PARAM params[2];
     194             :     EVP_PKEY_CTX *pctx = NULL;
     195             :     EVP_MD_CTX *mdctx = NULL;
     196             :     EVP_PKEY *template = NULL;
     197             :     EVP_PKEY *public = NULL;
     198             :     const unsigned char *p;
     199             :     size_t len;
     200             :     char *curve_sn_dup = NULL;
     201             :     int groupnid;
     202             :     int ret = 0;
     203             : 
     204             :     spi = &signer->tbsCertificate.subjectPublicKeyInfo;
     205             :     if (der_heim_oid_cmp(&spi->algorithm.algorithm,
     206             :                          ASN1_OID_ID_ECPUBLICKEY) != 0)
     207             :         hx509_set_error_string(context, 0,
     208             :                                ret =  HX509_CRYPTO_SIG_INVALID_FORMAT,
     209             :                                /* XXX Include the OID in the message */
     210             :                                "Unsupported subjectPublicKey algorithm");
     211             :     if (ret == 0)
     212             :         ret = ECParameters2nid(context, spi->algorithm.parameters, &groupnid);
     213             :     if (ret == 0 && (curve_sn = OBJ_nid2sn(groupnid)) == NULL)
     214             :         hx509_set_error_string(context, 0,
     215             :                                ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
     216             :                                "Could not resolve curve NID %d to its short name",
     217             :                                groupnid);
     218             :     if (ret == 0 && (curve_sn_dup = strdup(curve_sn)) == NULL)
     219             :         ret = hx509_enomem(context);
     220             :     if (ret == 0 && (mdctx = EVP_MD_CTX_new()) == NULL)
     221             :         ret = hx509_enomem(context);
     222             : 
     223             :     /*
     224             :      * In order for d2i_PublicKey() to work we need to create a template key
     225             :      * that has the curve parameters for the subjectPublicKey.
     226             :      *
     227             :      * Or maybe we could learn to use the OSSL_DECODER(3) API.  But this works,
     228             :      * at least until OpenSSL deprecates d2i_PublicKey() and forces us to use
     229             :      * OSSL_DECODER(3).
     230             :      */
     231             :     if (ret == 0) {
     232             :         /*
     233             :          * Apparently there's no error checking to be done here?  Why does
     234             :          * OSSL_PARAM_construct_utf8_string() want a non-const for the value?
     235             :          * Is that a bug in OpenSSL?
     236             :          */
     237             :         params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
     238             :                                                      curve_sn_dup, 0);
     239             :         params[1] = OSSL_PARAM_construct_end();
     240             : 
     241             :         if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL)
     242             :             ret = hx509_enomem(context);
     243             :     }
     244             :     if (ret == 0 && EVP_PKEY_fromdata_init(pctx) != 1)
     245             :         ret = hx509_enomem(context);
     246             :     if (ret == 0 &&
     247             :         EVP_PKEY_fromdata(pctx, &template,
     248             :                           OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, params) != 1)
     249             :         hx509_set_error_string(context, 0,
     250             :                                ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
     251             :                                "Could not set up to parse key for curve %s",
     252             :                                curve_sn);
     253             : 
     254             :     /* Finally we can decode the subjectPublicKey */
     255             :     p = spi->subjectPublicKey.data;
     256             :     len = spi->subjectPublicKey.length / 8;
     257             :     if (ret == 0 &&
     258             :         (public = d2i_PublicKey(EVP_PKEY_EC, &template, &p, len)) == NULL)
     259             :         ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
     260             : 
     261             :     /* EVP_DigestVerifyInit() will allocate a new pctx */
     262             :     EVP_PKEY_CTX_free(pctx);
     263             :     pctx = NULL;
     264             : 
     265             :     if (ret == 0 &&
     266             :         EVP_DigestVerifyInit(mdctx, &pctx, md, NULL, public) != 1)
     267             :         hx509_set_error_string(context, 0,
     268             :                                ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
     269             :                                "Could not initialize "
     270             :                                "OpenSSL signature verification");
     271             :     if (ret == 0 &&
     272             :         EVP_DigestVerifyUpdate(mdctx, data->data, data->length) != 1)
     273             :         hx509_set_error_string(context, 0,
     274             :                                ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
     275             :                                "Could not initialize "
     276             :                                "OpenSSL signature verification");
     277             :     if (ret == 0 &&
     278             :         EVP_DigestVerifyFinal(mdctx, sig->data, sig->length) != 1)
     279             :         hx509_set_error_string(context, 0,
     280             :                                ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
     281             :                                "Signature verification failed");
     282             : 
     283             :     EVP_MD_CTX_free(mdctx);
     284             :     EVP_PKEY_free(template);
     285             :     free(curve_sn_dup);
     286             :     return ret;
     287             : #else
     288             :     const AlgorithmIdentifier *digest_alg;
     289             :     const SubjectPublicKeyInfo *spi;
     290             :     heim_octet_string digest;
     291             :     int ret;
     292             :     EC_KEY *key = NULL;
     293             :     int groupnid;
     294             :     EC_GROUP *group;
     295             :     const unsigned char *p;
     296             :     long len;
     297             : 
     298             :     digest_alg = sig_alg->digest_alg;
     299             : 
     300             :     ret = _hx509_create_signature(context,
     301             :                                  NULL,
     302             :                                  digest_alg,
     303             :                                  data,
     304             :                                  NULL,
     305             :                                  &digest);
     306             :     if (ret)
     307             :        return ret;
     308             : 
     309             :     /* set up EC KEY */
     310             :     spi = &signer->tbsCertificate.subjectPublicKeyInfo;
     311             : 
     312             :     if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)
     313             :        return HX509_CRYPTO_SIG_INVALID_FORMAT;
     314             : 
     315             :     /*
     316             :      * Find the group id
     317             :      */
     318             : 
     319             :     ret = ECParameters2nid(context, spi->algorithm.parameters, &groupnid);
     320             :     if (ret) {
     321             :        der_free_octet_string(&digest);
     322             :        return ret;
     323             :     }
     324             : 
     325             :     /*
     326             :      * Create group, key, parse key
     327             :      */
     328             : 
     329             :     key = EC_KEY_new();
     330             :     group = EC_GROUP_new_by_curve_name(groupnid);
     331             :     EC_KEY_set_group(key, group);
     332             :     EC_GROUP_free(group);
     333             : 
     334             :     p = spi->subjectPublicKey.data;
     335             :     len = spi->subjectPublicKey.length / 8;
     336             : 
     337             :     if (o2i_ECPublicKey(&key, &p, len) == NULL) {
     338             :        EC_KEY_free(key);
     339             :        return HX509_CRYPTO_SIG_INVALID_FORMAT;
     340             :     }
     341             : 
     342             :     ret = ECDSA_verify(-1, digest.data, digest.length,
     343             :                       sig->data, sig->length, key);
     344             :     der_free_octet_string(&digest);
     345             :     EC_KEY_free(key);
     346             :     if (ret != 1) {
     347             :        ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
     348             :        return ret;
     349             :     }
     350             : 
     351             :     return 0;
     352             : #endif
     353             : }
     354             : 
     355             : static int
     356             : ecdsa_create_signature(hx509_context context,
     357             :                        const struct signature_alg *sig_alg,
     358             :                        const hx509_private_key signer,
     359             :                        const AlgorithmIdentifier *alg,
     360             :                        const heim_octet_string *data,
     361             :                        AlgorithmIdentifier *signatureAlgorithm,
     362             :                        heim_octet_string *sig)
     363             : {
     364             : #ifdef HAVE_OPENSSL_30
     365             :     const AlgorithmIdentifier *digest_alg = sig_alg->digest_alg;
     366             :     const EVP_MD *md = signature_alg2digest_evp_md(context, digest_alg);
     367             :     EVP_MD_CTX *mdctx = NULL;
     368             :     EVP_PKEY_CTX *pctx = NULL;
     369             :     const heim_oid *sig_oid;
     370             :     int ret = 0;
     371             : 
     372             :     sig->data = NULL;
     373             :     sig->length = 0;
     374             :     if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
     375             :         _hx509_abort("internal error passing private key to wrong ops");
     376             : 
     377             :     sig_oid = sig_alg->sig_oid;
     378             :     digest_alg = sig_alg->digest_alg;
     379             : 
     380             :     if (signatureAlgorithm)
     381             :         ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid,
     382             :                                     "\x05\x00", 2);
     383             :     mdctx = EVP_MD_CTX_new();
     384             :     if (mdctx == NULL)
     385             :         ret = hx509_enomem(context);
     386             :     if (ret == 0 && EVP_DigestSignInit(mdctx, &pctx, md, NULL,
     387             :                                        signer->private_key.ecdsa) != 1)
     388             :         ret = HX509_CMS_FAILED_CREATE_SIGATURE;
     389             :     if (ret == 0 && EVP_DigestSignUpdate(mdctx, data->data, data->length) != 1)
     390             :         ret = HX509_CMS_FAILED_CREATE_SIGATURE;
     391             :     if (ret == 0 && EVP_DigestSignFinal(mdctx, NULL, &sig->length) != 1)
     392             :         ret = HX509_CMS_FAILED_CREATE_SIGATURE;
     393             :     if (ret == 0 && (sig->data = malloc(sig->length)) == NULL)
     394             :         ret = hx509_enomem(context);
     395             :     if (ret == 0 && EVP_DigestSignFinal(mdctx, sig->data, &sig->length) != 1)
     396             :         ret = HX509_CMS_FAILED_CREATE_SIGATURE;
     397             : 
     398             :     if (ret == HX509_CMS_FAILED_CREATE_SIGATURE) {
     399             :         /* XXX Extract error detail from OpenSSL */
     400             :         hx509_set_error_string(context, 0, ret,
     401             :                                "ECDSA sign failed");
     402             :     }
     403             : 
     404             :     if (ret) {
     405             :         if (signatureAlgorithm)
     406             :             free_AlgorithmIdentifier(signatureAlgorithm);
     407             :         free(sig->data);
     408             :         sig->data = NULL;
     409             :         sig->length = 0;
     410             :     }
     411             :     EVP_MD_CTX_free(mdctx);
     412             :     return ret;
     413             : #else
     414             :     const AlgorithmIdentifier *digest_alg;
     415             :     heim_octet_string indata;
     416             :     const heim_oid *sig_oid;
     417             :     unsigned int siglen;
     418             :     int ret;
     419             : 
     420             :     if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
     421             :         _hx509_abort("internal error passing private key to wrong ops");
     422             : 
     423             :     sig_oid = sig_alg->sig_oid;
     424             :     digest_alg = sig_alg->digest_alg;
     425             : 
     426             :     if (signatureAlgorithm) {
     427             :         ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid,
     428             :                                     "\x05\x00", 2);
     429             :         if (ret) {
     430             :             hx509_clear_error_string(context);
     431             :             return ret;
     432             :         }
     433             :     }
     434             : 
     435             :     ret = _hx509_create_signature(context,
     436             :                                   NULL,
     437             :                                   digest_alg,
     438             :                                   data,
     439             :                                   NULL,
     440             :                                   &indata);
     441             :     if (ret)
     442             :         goto error;
     443             : 
     444             :     sig->length = ECDSA_size(signer->private_key.ecdsa);
     445             :     sig->data = malloc(sig->length);
     446             :     if (sig->data == NULL) {
     447             :         der_free_octet_string(&indata);
     448             :         ret = ENOMEM;
     449             :         hx509_set_error_string(context, 0, ret, "out of memory");
     450             :         goto error;
     451             :     }
     452             : 
     453             :     siglen = sig->length;
     454             : 
     455             :     ret = ECDSA_sign(-1, indata.data, indata.length,
     456             :                      sig->data, &siglen, signer->private_key.ecdsa);
     457             :     der_free_octet_string(&indata);
     458             :     if (ret != 1) {
     459             :         ret = HX509_CMS_FAILED_CREATE_SIGATURE;
     460             :         hx509_set_error_string(context, 0, ret,
     461             :                                "ECDSA sign failed: %d", ret);
     462             :         goto error;
     463             :     }
     464             :     if (siglen > sig->length)
     465             :         _hx509_abort("ECDSA signature prelen longer than output len");
     466             : 
     467             :     sig->length = siglen;
     468             : 
     469             :     return 0;
     470             : error:
     471             :     if (signatureAlgorithm)
     472             :         free_AlgorithmIdentifier(signatureAlgorithm);
     473             :     return ret;
     474             : #endif
     475             : }
     476             : 
     477             : static int
     478             : ecdsa_available(const hx509_private_key signer,
     479             :                 const AlgorithmIdentifier *sig_alg)
     480             : {
     481             : #ifdef HAVE_OPENSSL_30
     482             :     const struct signature_alg *sig;
     483             :     size_t group_name_len = 0;
     484             :     char group_name_buf[96];
     485             :     EC_GROUP *group = NULL;
     486             :     BN_CTX *bnctx = NULL;
     487             :     BIGNUM *order = NULL;
     488             :     int ret = 0;
     489             : 
     490             :     if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
     491             :         _hx509_abort("internal error passing private key to wrong ops");
     492             : 
     493             :     sig = _hx509_find_sig_alg(&sig_alg->algorithm);
     494             :     if (sig == NULL || sig->digest_size == 0)
     495             :         return 0;
     496             : 
     497             :     if (EVP_PKEY_get_group_name(signer->private_key.ecdsa, group_name_buf,
     498             :                                 sizeof(group_name_buf),
     499             :                                 &group_name_len) != 1 ||
     500             :         group_name_len >= sizeof(group_name_buf)) {
     501             :         return 0;
     502             :     }
     503             :     group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(group_name_buf));
     504             :     bnctx = BN_CTX_new();
     505             :     order = BN_new();
     506             :     if (group && bnctx && order &&
     507             :         EC_GROUP_get_order(group, order, bnctx) == 1)
     508             :         ret = 1;
     509             : 
     510             : #if 0
     511             :     /*
     512             :      * If anything, require a digest at least as wide as the EC key size
     513             :      *
     514             :      *  if (BN_num_bytes(order) > sig->digest_size)
     515             :      *      ret = 0;
     516             :      */
     517             : #endif
     518             : 
     519             :     BN_CTX_free(bnctx);
     520             :     BN_clear_free(order);
     521             :     EC_GROUP_free(group);
     522             :     return ret;
     523             : #else
     524             :     const struct signature_alg *sig;
     525             :     const EC_GROUP *group;
     526             :     BN_CTX *bnctx = NULL;
     527             :     BIGNUM *order = NULL;
     528             :     int ret = 0;
     529             : 
     530             :     if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
     531             :        _hx509_abort("internal error passing private key to wrong ops");
     532             : 
     533             :     sig = _hx509_find_sig_alg(&sig_alg->algorithm);
     534             : 
     535             :     if (sig == NULL || sig->digest_size == 0)
     536             :        return 0;
     537             : 
     538             :     group = EC_KEY_get0_group(signer->private_key.ecdsa);
     539             :     if (group == NULL)
     540             :        return 0;
     541             : 
     542             :     bnctx = BN_CTX_new();
     543             :     order = BN_new();
     544             :     if (order == NULL)
     545             :        goto err;
     546             : 
     547             :     if (EC_GROUP_get_order(group, order, bnctx) != 1)
     548             :        goto err;
     549             : 
     550             : #if 0
     551             :     /* If anything, require a digest at least as wide as the EC key size */
     552             :     if (BN_num_bytes(order) > sig->digest_size)
     553             : #endif
     554             :        ret = 1;
     555             :  err:
     556             :     if (bnctx)
     557             :        BN_CTX_free(bnctx);
     558             :     if (order)
     559             :        BN_clear_free(order);
     560             : 
     561             :      return ret;
     562             : #endif
     563             : }
     564             : 
     565             : static int
     566             : ecdsa_private_key2SPKI(hx509_context context,
     567             :                        hx509_private_key private_key,
     568             :                        SubjectPublicKeyInfo *spki)
     569             : {
     570             :     memset(spki, 0, sizeof(*spki));
     571             :     return ENOMEM;
     572             : }
     573             : 
     574             : static int
     575             : ecdsa_private_key_export(hx509_context context,
     576             :                          const hx509_private_key key,
     577             :                          hx509_key_format_t format,
     578             :                          heim_octet_string *data)
     579             : {
     580             :     return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
     581             : }
     582             : 
     583             : static int
     584             : ecdsa_private_key_import(hx509_context context,
     585             :                          const AlgorithmIdentifier *keyai,
     586             :                          const void *data,
     587             :                          size_t len,
     588             :                          hx509_key_format_t format,
     589             :                          hx509_private_key private_key)
     590             : {
     591             : #ifdef HAVE_OPENSSL_30
     592             :     const unsigned char *p = data;
     593             :     EVP_PKEY *key = NULL;
     594             :     int ret = 0;
     595             : 
     596             :     switch (format) {
     597             :     case HX509_KEY_FORMAT_PKCS8:
     598             :         key = d2i_PrivateKey(EVP_PKEY_EC, NULL, &p, len);
     599             :         if (key == NULL) {
     600             :             hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
     601             :                                    "Failed to parse EC private key");
     602             :             return HX509_PARSING_KEY_FAILED;
     603             :         }
     604             :         break;
     605             : 
     606             :     default:
     607             :         return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
     608             :     }
     609             : 
     610             :     /*
     611             :      * We used to have to call EC_KEY_new(), then EC_KEY_set_group() the group
     612             :      * (curve) on the resulting EC_KEY _before_ we could d2i_ECPrivateKey() the
     613             :      * key, but that's all deprecated in OpenSSL 3.0.
     614             :      *
     615             :      * In fact, it's not clear how ever to assign a group to a private key,
     616             :      * but that's what the documentation for d2i_PrivateKey() says: that
     617             :      * its `EVP_PKEY **' argument must be non-NULL pointing to a key that
     618             :      * has had the group set.
     619             :      *
     620             :      * However, from code inspection it's clear that when the ECParameters
     621             :      * are present in the private key payload passed to d2i_PrivateKey(),
     622             :      * the group will be taken from that.
     623             :      *
     624             :      * What we'll do is that if we have `keyai->parameters' we'll check if the
     625             :      * key we got is for the same group.
     626             :      */
     627             :     if (keyai->parameters) {
     628             :         size_t gname_len = 0;
     629             :         char buf[96];
     630             :         int got_group_nid = NID_undef;
     631             :         int want_groupnid = NID_undef;
     632             : 
     633             :         ret = ECParameters2nid(context, keyai->parameters, &want_groupnid);
     634             :         if (ret == 0 &&
     635             :             (EVP_PKEY_get_group_name(key, buf, sizeof(buf), &gname_len) != 1 ||
     636             :              gname_len >= sizeof(buf)))
     637             :             ret = HX509_ALG_NOT_SUPP;
     638             :         if (ret == 0)
     639             :             got_group_nid = OBJ_txt2nid(buf);
     640             :         if (ret == 0 &&
     641             :             (got_group_nid == NID_undef || want_groupnid != got_group_nid))
     642             :             ret = HX509_ALG_NOT_SUPP;
     643             :     }
     644             : 
     645             :     if (ret == 0) {
     646             :         private_key->private_key.ecdsa = key;
     647             :         private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
     648             :         key = NULL;
     649             :     }
     650             : 
     651             :     EVP_PKEY_free(key);
     652             :     return ret;
     653             : #else
     654             :     const unsigned char *p = data;
     655             :     EC_KEY **pkey = NULL;
     656             :     EC_KEY *key;
     657             : 
     658             :     if (keyai->parameters) {
     659             :        EC_GROUP *group;
     660             :        int groupnid;
     661             :        int ret;
     662             : 
     663             :        ret = ECParameters2nid(context, keyai->parameters, &groupnid);
     664             :        if (ret)
     665             :            return ret;
     666             : 
     667             :        key = EC_KEY_new();
     668             :        if (key == NULL)
     669             :            return ENOMEM;
     670             : 
     671             :        group = EC_GROUP_new_by_curve_name(groupnid);
     672             :        if (group == NULL) {
     673             :            EC_KEY_free(key);
     674             :            return ENOMEM;
     675             :        }
     676             :        EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
     677             :        if (EC_KEY_set_group(key, group) != 1) {
     678             :            EC_KEY_free(key);
     679             :            EC_GROUP_free(group);
     680             :            return ENOMEM;
     681             :        }
     682             :        EC_GROUP_free(group);
     683             :        pkey = &key;
     684             :     }
     685             : 
     686             :     switch (format) {
     687             :     case HX509_KEY_FORMAT_DER:
     688             : 
     689             :        private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
     690             :        if (private_key->private_key.ecdsa == NULL) {
     691             :            hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
     692             :                                   "Failed to parse EC private key");
     693             :            return HX509_PARSING_KEY_FAILED;
     694             :        }
     695             :        private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
     696             :        break;
     697             : 
     698             :     default:
     699             :        return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
     700             :     }
     701             : 
     702             :     return 0;
     703             : #endif
     704             : }
     705             : 
     706             : static int
     707             : ecdsa_generate_private_key(hx509_context context,
     708             :                            struct hx509_generate_private_context *ctx,
     709             :                            hx509_private_key private_key)
     710             : {
     711             :     return ENOMEM;
     712             : }
     713             : 
     714             : static BIGNUM *
     715             : ecdsa_get_internal(hx509_context context,
     716             :                    hx509_private_key key,
     717             :                    const char *type)
     718             : {
     719             :     return NULL;
     720             : }
     721             : 
     722             : static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };
     723             : const AlgorithmIdentifier _hx509_signature_ecPublicKey = {
     724             :     { 6, rk_UNCONST(ecPublicKey) }, NULL
     725             : };
     726             : 
     727             : static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 };
     728             : const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = {
     729             :     { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL
     730             : };
     731             : 
     732             : static const unsigned ecdsa_with_sha384_oid[] ={ 1, 2, 840, 10045, 4, 3, 3 };
     733             : const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha384_data = {
     734             :     { 7, rk_UNCONST(ecdsa_with_sha384_oid) }, NULL
     735             : };
     736             : 
     737             : static const unsigned ecdsa_with_sha512_oid[] ={ 1, 2, 840, 10045, 4, 3, 4 };
     738             : const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha512_data = {
     739             :     { 7, rk_UNCONST(ecdsa_with_sha512_oid) }, NULL
     740             : };
     741             : 
     742             : static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 };
     743             : const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = {
     744             :     { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL
     745             : };
     746             : 
     747             : hx509_private_key_ops ecdsa_private_key_ops = {
     748             :     "EC PRIVATE KEY",
     749             :     ASN1_OID_ID_ECPUBLICKEY,
     750             :     ecdsa_available,
     751             :     ecdsa_private_key2SPKI,
     752             :     ecdsa_private_key_export,
     753             :     ecdsa_private_key_import,
     754             :     ecdsa_generate_private_key,
     755             :     ecdsa_get_internal
     756             : };
     757             : 
     758             : const struct signature_alg ecdsa_with_sha512_alg = {
     759             :     "ecdsa-with-sha512",
     760             :     ASN1_OID_ID_ECDSA_WITH_SHA512,
     761             :     &_hx509_signature_ecdsa_with_sha512_data,
     762             :     ASN1_OID_ID_ECPUBLICKEY,
     763             :     &_hx509_signature_sha512_data,
     764             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
     765             :         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     766             :     0,
     767             :     NULL,
     768             :     ecdsa_verify_signature,
     769             :     ecdsa_create_signature,
     770             :     64
     771             : };
     772             : 
     773             : const struct signature_alg ecdsa_with_sha384_alg = {
     774             :     "ecdsa-with-sha384",
     775             :     ASN1_OID_ID_ECDSA_WITH_SHA384,
     776             :     &_hx509_signature_ecdsa_with_sha384_data,
     777             :     ASN1_OID_ID_ECPUBLICKEY,
     778             :     &_hx509_signature_sha384_data,
     779             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
     780             :         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     781             :     0,
     782             :     NULL,
     783             :     ecdsa_verify_signature,
     784             :     ecdsa_create_signature,
     785             :     48
     786             : };
     787             : 
     788             : const struct signature_alg ecdsa_with_sha256_alg = {
     789             :     "ecdsa-with-sha256",
     790             :     ASN1_OID_ID_ECDSA_WITH_SHA256,
     791             :     &_hx509_signature_ecdsa_with_sha256_data,
     792             :     ASN1_OID_ID_ECPUBLICKEY,
     793             :     &_hx509_signature_sha256_data,
     794             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
     795             :         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     796             :     0,
     797             :     NULL,
     798             :     ecdsa_verify_signature,
     799             :     ecdsa_create_signature,
     800             :     32
     801             : };
     802             : 
     803             : const struct signature_alg ecdsa_with_sha1_alg = {
     804             :     "ecdsa-with-sha1",
     805             :     ASN1_OID_ID_ECDSA_WITH_SHA1,
     806             :     &_hx509_signature_ecdsa_with_sha1_data,
     807             :     ASN1_OID_ID_ECPUBLICKEY,
     808             :     &_hx509_signature_sha1_data,
     809             :     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
     810             :         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     811             :     0,
     812             :     NULL,
     813             :     ecdsa_verify_signature,
     814             :     ecdsa_create_signature,
     815             :     20
     816             : };
     817             : 
     818             : #endif /* HAVE_HCRYPTO_W_OPENSSL */
     819             : 
     820             : HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL
     821           0 : hx509_signature_ecPublicKey(void)
     822             : {
     823             : #ifdef HAVE_HCRYPTO_W_OPENSSL
     824             :     return &_hx509_signature_ecPublicKey;
     825             : #else
     826           0 :     return NULL;
     827             : #endif /* HAVE_HCRYPTO_W_OPENSSL */
     828             : }
     829             : 
     830             : HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL
     831           0 : hx509_signature_ecdsa_with_sha256(void)
     832             : {
     833             : #ifdef HAVE_HCRYPTO_W_OPENSSL
     834             :     return &_hx509_signature_ecdsa_with_sha256_data;
     835             : #else
     836           0 :     return NULL;
     837             : #endif /* HAVE_HCRYPTO_W_OPENSSL */
     838             : }

Generated by: LCOV version 1.14