Coverage Report

Created: 2026-05-24 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/third_party/heimdal/lib/hx509/crypto-ec.c
Line
Count
Source
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
0
{
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
hx509_signature_ecPublicKey(void)
822
0
{
823
#ifdef HAVE_HCRYPTO_W_OPENSSL
824
    return &_hx509_signature_ecPublicKey;
825
#else
826
0
    return NULL;
827
0
#endif /* HAVE_HCRYPTO_W_OPENSSL */
828
0
}
829
830
HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL
831
hx509_signature_ecdsa_with_sha256(void)
832
0
{
833
#ifdef HAVE_HCRYPTO_W_OPENSSL
834
    return &_hx509_signature_ecdsa_with_sha256_data;
835
#else
836
    return NULL;
837
0
#endif /* HAVE_HCRYPTO_W_OPENSSL */
838
0
}