third_party/heimdal: import lorikeet-heimdal-202311290849 (commit 84fb4579594a5fd8f84...
[scabrero/samba-autobuild/.git] / third_party / heimdal / lib / hx509 / crypto-ec.c
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 _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 }
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 hx509_signature_ecPublicKey(void)
822 {
823 #ifdef HAVE_HCRYPTO_W_OPENSSL
824     return &_hx509_signature_ecPublicKey;
825 #else
826     return NULL;
827 #endif /* HAVE_HCRYPTO_W_OPENSSL */
828 }
829
830 HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL
831 hx509_signature_ecdsa_with_sha256(void)
832 {
833 #ifdef HAVE_HCRYPTO_W_OPENSSL
834     return &_hx509_signature_ecdsa_with_sha256_data;
835 #else
836     return NULL;
837 #endif /* HAVE_HCRYPTO_W_OPENSSL */
838 }