Coverage Report

Created: 2025-03-09 06:52

/src/libressl/crypto/ec/ecx_methods.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: ecx_methods.c,v 1.14 2024/08/28 07:15:04 tb Exp $ */
2
/*
3
 * Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <string.h>
19
20
#include <openssl/cms.h>
21
#include <openssl/curve25519.h>
22
#include <openssl/ec.h>
23
#include <openssl/err.h>
24
#include <openssl/evp.h>
25
#include <openssl/x509.h>
26
27
#include "asn1_local.h"
28
#include "bytestring.h"
29
#include "curve25519_internal.h"
30
#include "evp_local.h"
31
#include "x509_local.h"
32
33
/*
34
 * EVP PKEY and PKEY ASN.1 methods Ed25519 and X25519.
35
 *
36
 * RFC 7748 - Elliptic Curves for Security.
37
 * RFC 8032 - Edwards-Curve Digital Signature Algorithm (EdDSA).
38
 */
39
40
0
#define ED25519_BITS    253
41
0
#define ED25519_SECURITY_BITS 128
42
0
#define ED25519_SIG_SIZE  64
43
44
0
#define X25519_BITS   253
45
0
#define X25519_SECURITY_BITS  128
46
47
static int
48
ecx_key_len(int nid)
49
14
{
50
14
  switch (nid) {
51
5
  case NID_ED25519:
52
5
    return ED25519_KEYLEN;
53
9
  case NID_X25519:
54
9
    return X25519_KEYLEN;
55
14
  }
56
57
0
  return 0;
58
14
}
59
60
static struct ecx_key_st *
61
ecx_key_new(int nid)
62
4
{
63
4
  struct ecx_key_st *ecx_key;
64
4
  int key_len;
65
66
4
  if ((key_len = ecx_key_len(nid)) == 0)
67
0
    return NULL;
68
69
4
  if ((ecx_key = calloc(1, sizeof(*ecx_key))) == NULL)
70
0
    return NULL;
71
72
4
  ecx_key->nid = nid;
73
4
  ecx_key->key_len = key_len;
74
75
4
  return ecx_key;
76
4
}
77
78
static void
79
ecx_key_clear(struct ecx_key_st *ecx_key)
80
8
{
81
8
  freezero(ecx_key->priv_key, ecx_key->priv_key_len);
82
8
  ecx_key->priv_key = NULL;
83
8
  ecx_key->priv_key_len = 0;
84
85
8
  freezero(ecx_key->pub_key, ecx_key->pub_key_len);
86
8
  ecx_key->pub_key = NULL;
87
8
  ecx_key->pub_key_len = 0;
88
8
}
89
90
static void
91
ecx_key_free(struct ecx_key_st *ecx_key)
92
56
{
93
56
  if (ecx_key == NULL)
94
52
    return;
95
96
4
  ecx_key_clear(ecx_key);
97
98
4
  freezero(ecx_key, sizeof(*ecx_key));
99
4
}
100
101
static int
102
ecx_key_generate(struct ecx_key_st *ecx_key)
103
0
{
104
0
  uint8_t *pub_key = NULL, *priv_key = NULL;
105
0
  int ret = 0;
106
107
0
  ecx_key_clear(ecx_key);
108
109
0
  if ((pub_key = calloc(1, ecx_key->key_len)) == NULL)
110
0
    goto err;
111
0
  if ((priv_key = calloc(1, ecx_key->key_len)) == NULL)
112
0
    goto err;
113
114
0
  switch (ecx_key->nid) {
115
0
  case NID_ED25519:
116
0
    ED25519_keypair(pub_key, priv_key);
117
0
    break;
118
0
  case NID_X25519:
119
0
    X25519_keypair(pub_key, priv_key);
120
0
    break;
121
0
  default:
122
0
    goto err;
123
0
  }
124
125
0
  ecx_key->priv_key = priv_key;
126
0
  ecx_key->priv_key_len = ecx_key->key_len;
127
0
  priv_key = NULL;
128
129
0
  ecx_key->pub_key = pub_key;
130
0
  ecx_key->pub_key_len = ecx_key->key_len;
131
0
  pub_key = NULL;
132
133
0
  ret = 1;
134
135
0
 err:
136
0
  freezero(pub_key, ecx_key->key_len);
137
0
  freezero(priv_key, ecx_key->key_len);
138
139
0
  return ret;
140
0
}
141
142
static int
143
ecx_key_set_priv(struct ecx_key_st *ecx_key, const uint8_t *priv_key,
144
    size_t priv_key_len)
145
2
{
146
2
  uint8_t *pub_key = NULL;
147
2
  CBS cbs;
148
149
2
  ecx_key_clear(ecx_key);
150
151
2
  if (priv_key_len != ecx_key->key_len)
152
0
    goto err;
153
154
2
  if ((pub_key = calloc(1, ecx_key->key_len)) == NULL)
155
0
    goto err;
156
157
2
  switch (ecx_key->nid) {
158
1
  case NID_ED25519:
159
1
    ED25519_public_from_private(pub_key, priv_key);
160
1
    break;
161
1
  case NID_X25519:
162
1
    X25519_public_from_private(pub_key, priv_key);
163
1
    break;
164
0
  default:
165
0
    goto err;
166
2
  }
167
168
2
  CBS_init(&cbs, priv_key, priv_key_len);
169
2
  if (!CBS_stow(&cbs, &ecx_key->priv_key, &ecx_key->priv_key_len))
170
0
    goto err;
171
172
2
  ecx_key->pub_key = pub_key;
173
2
  ecx_key->pub_key_len = ecx_key->key_len;
174
2
  pub_key = NULL;
175
176
2
 err:
177
2
  freezero(pub_key, ecx_key->key_len);
178
179
2
  return 1;
180
2
}
181
182
static int
183
ecx_key_set_pub(struct ecx_key_st *ecx_key, const uint8_t *pub_key,
184
    size_t pub_key_len)
185
2
{
186
2
  CBS cbs;
187
188
2
  ecx_key_clear(ecx_key);
189
190
2
  if (pub_key_len != ecx_key->key_len)
191
0
    return 0;
192
193
2
  CBS_init(&cbs, pub_key, pub_key_len);
194
2
  if (!CBS_stow(&cbs, &ecx_key->pub_key, &ecx_key->pub_key_len))
195
0
    return 0;
196
197
2
  return 1;
198
2
}
199
200
static int
201
ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *xpubkey)
202
16
{
203
16
  struct ecx_key_st *ecx_key = NULL;
204
16
  X509_ALGOR *algor;
205
16
  int algor_type;
206
16
  const uint8_t *param;
207
16
  int param_len;
208
16
  int ret = 0;
209
210
16
  if (!X509_PUBKEY_get0_param(NULL, &param, &param_len, &algor, xpubkey))
211
0
    goto err;
212
213
  /* Ensure that parameters have not been specified in the encoding. */
214
16
  if (algor != NULL) {
215
16
    X509_ALGOR_get0(NULL, &algor_type, NULL, algor);
216
16
    if (algor_type != V_ASN1_UNDEF) {
217
9
      ECerror(EC_R_INVALID_ENCODING);
218
9
      goto err;
219
9
    }
220
16
  }
221
222
7
  if (param == NULL || param_len != ecx_key_len(pkey->ameth->pkey_id)) {
223
5
    ECerror(EC_R_INVALID_ENCODING);
224
5
    goto err;
225
5
  }
226
227
2
  if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
228
0
    goto err;
229
2
  if (!ecx_key_set_pub(ecx_key, param, param_len))
230
0
    goto err;
231
2
  if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
232
0
    goto err;
233
2
  ecx_key = NULL;
234
235
2
  ret = 1;
236
237
16
 err:
238
16
  ecx_key_free(ecx_key);
239
240
16
  return ret;
241
2
}
242
243
static int
244
ecx_pub_encode(X509_PUBKEY *xpubkey, const EVP_PKEY *pkey)
245
0
{
246
0
  const struct ecx_key_st *ecx_key = pkey->pkey.ecx;
247
0
  uint8_t *pub_key = NULL;
248
0
  size_t pub_key_len = 0;
249
0
  ASN1_OBJECT *aobj;
250
0
  CBS cbs;
251
0
  int ret = 0;
252
253
0
  if (ecx_key == NULL) {
254
0
    ECerror(EC_R_INVALID_KEY);
255
0
    goto err;
256
0
  }
257
258
0
  if (ecx_key->pub_key_len != ecx_key->key_len)
259
0
    goto err;
260
261
0
  if ((aobj = OBJ_nid2obj(pkey->ameth->pkey_id)) == NULL)
262
0
    goto err;
263
264
0
  CBS_init(&cbs, ecx_key->pub_key, ecx_key->pub_key_len);
265
0
  if (!CBS_stow(&cbs, &pub_key, &pub_key_len))
266
0
    goto err;
267
268
0
  if (!X509_PUBKEY_set0_param(xpubkey, aobj, V_ASN1_UNDEF, NULL,
269
0
      pub_key, pub_key_len))
270
0
    goto err;
271
272
0
  pub_key = NULL;
273
0
  pub_key_len = 0;
274
275
0
  ret = 1;
276
277
0
 err:
278
0
  free(pub_key);
279
280
0
  return ret;
281
0
}
282
283
static int
284
ecx_pub_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2)
285
0
{
286
0
  if (pkey1->pkey.ecx == NULL || pkey1->pkey.ecx->pub_key == NULL)
287
0
    return -2;
288
0
  if (pkey2->pkey.ecx == NULL || pkey2->pkey.ecx->pub_key == NULL)
289
0
    return -2;
290
0
  if (pkey1->pkey.ecx->pub_key_len != pkey2->pkey.ecx->pub_key_len)
291
0
    return -2;
292
293
0
  return timingsafe_memcmp(pkey1->pkey.ecx->pub_key, pkey2->pkey.ecx->pub_key,
294
0
      pkey1->pkey.ecx->pub_key_len) == 0;
295
0
}
296
297
/* Reimplementation of ASN1_buf_print() that adds a secondary indent of 4. */
298
static int
299
ecx_buf_print(BIO *bio, const uint8_t *buf, size_t buf_len, int indent)
300
6
{
301
6
  uint8_t u8;
302
6
  size_t octets = 0;
303
6
  const char *sep = ":", *nl = "";
304
6
  CBS cbs;
305
306
6
  if (indent > 60)
307
0
    indent = 60;
308
6
  indent += 4;
309
6
  if (indent < 0)
310
0
    indent = 0;
311
312
6
  CBS_init(&cbs, buf, buf_len);
313
198
  while (CBS_len(&cbs) > 0) {
314
192
    if (!CBS_get_u8(&cbs, &u8))
315
0
      return 0;
316
192
    if (octets++ % 15 == 0) {
317
18
      if (BIO_printf(bio, "%s%*s", nl, indent, "") < 0)
318
0
        return 0;
319
18
      nl = "\n";
320
18
    }
321
192
    if (CBS_len(&cbs) == 0)
322
6
      sep = "";
323
192
    if (BIO_printf(bio, "%02x%s", u8, sep) <= 0)
324
0
      return 0;
325
192
  }
326
327
6
  if (BIO_printf(bio, "\n") <= 0)
328
0
    return 0;
329
330
6
  return 1;
331
6
}
332
333
static int
334
ecx_pub_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
335
2
{
336
2
  struct ecx_key_st *ecx_key = pkey->pkey.ecx;
337
2
  const char *name;
338
339
2
  if ((name = OBJ_nid2ln(pkey->ameth->pkey_id)) == NULL)
340
0
    return 0;
341
342
2
  if (ecx_key == NULL || ecx_key->pub_key == NULL)
343
0
    return BIO_printf(bio, "%*s<INVALID PUBLIC KEY>\n",
344
0
        indent, "") > 0;
345
346
2
  if (BIO_printf(bio, "%*s%s Public-Key:\n", indent, "", name) <= 0)
347
0
    return 0;
348
2
  if (BIO_printf(bio, "%*spub:\n", indent, "") <= 0)
349
0
    return 0;
350
2
  if (!ecx_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len, indent))
351
0
    return 0;
352
353
2
  return 1;
354
2
}
355
356
static int
357
ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8pki)
358
10
{
359
10
  struct ecx_key_st *ecx_key = NULL;
360
10
  ASN1_OCTET_STRING *aos = NULL;
361
10
  const X509_ALGOR *algor;
362
10
  int algor_type;
363
10
  const uint8_t *param;
364
10
  int param_len;
365
10
  int ret = 0;
366
367
10
  if (!PKCS8_pkey_get0(NULL, &param, &param_len, &algor, p8pki))
368
0
    goto err;
369
10
  if ((aos = d2i_ASN1_OCTET_STRING(NULL, &param, param_len)) == NULL)
370
2
    goto err;
371
372
  /* Ensure that parameters have not been specified in the encoding. */
373
8
  if (algor != NULL) {
374
8
    X509_ALGOR_get0(NULL, &algor_type, NULL, algor);
375
8
    if (algor_type != V_ASN1_UNDEF) {
376
1
      ECerror(EC_R_INVALID_ENCODING);
377
1
      goto err;
378
1
    }
379
8
  }
380
381
7
  if (ASN1_STRING_get0_data(aos) == NULL ||
382
7
      ASN1_STRING_length(aos) != ecx_key_len(pkey->ameth->pkey_id)) {
383
5
    ECerror(EC_R_INVALID_ENCODING);
384
5
    goto err;
385
5
  }
386
387
2
  if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
388
0
    goto err;
389
2
  if (!ecx_key_set_priv(ecx_key, ASN1_STRING_get0_data(aos),
390
2
      ASN1_STRING_length(aos)))
391
0
    goto err;
392
2
  if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
393
0
    goto err;
394
2
  ecx_key = NULL;
395
396
2
  ret = 1;
397
398
10
 err:
399
10
  ASN1_OCTET_STRING_free(aos);
400
10
  ecx_key_free(ecx_key);
401
402
10
  return ret;
403
2
}
404
405
static int
406
ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8pki, const EVP_PKEY *pkey)
407
2
{
408
2
  struct ecx_key_st *ecx_key = pkey->pkey.ecx;
409
2
  ASN1_OCTET_STRING *aos = NULL;
410
2
  ASN1_OBJECT *aobj;
411
2
  uint8_t *der = NULL;
412
2
  int der_len = 0;
413
2
  int ret = 0;
414
415
2
  if (ecx_key == NULL || ecx_key->priv_key == NULL) {
416
0
    ECerror(EC_R_INVALID_PRIVATE_KEY);
417
0
    goto err;
418
0
  }
419
420
2
  if ((aobj = OBJ_nid2obj(pkey->ameth->pkey_id)) == NULL)
421
0
    goto err;
422
423
2
  if ((aos = ASN1_OCTET_STRING_new()) == NULL)
424
0
    goto err;
425
2
  if (!ASN1_OCTET_STRING_set(aos, ecx_key->priv_key,
426
2
      ecx_key->priv_key_len))
427
0
    goto err;
428
2
  if ((der_len = i2d_ASN1_OCTET_STRING(aos, &der)) < 0)
429
0
    goto err;
430
2
  if (!PKCS8_pkey_set0(p8pki, aobj, 0, V_ASN1_UNDEF, NULL, der, der_len))
431
0
    goto err;
432
433
2
  der = NULL;
434
2
  der_len = 0;
435
436
2
  ret = 1;
437
438
2
 err:
439
2
  freezero(der, der_len);
440
2
  ASN1_OCTET_STRING_free(aos);
441
442
2
  return ret;
443
2
}
444
445
static int
446
ecx_priv_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
447
2
{
448
2
  struct ecx_key_st *ecx_key = pkey->pkey.ecx;
449
2
  const char *name;
450
451
2
  if ((name = OBJ_nid2ln(pkey->ameth->pkey_id)) == NULL)
452
0
    return 0;
453
454
2
  if (ecx_key == NULL || ecx_key->priv_key == NULL)
455
0
    return BIO_printf(bio, "%*s<INVALID PRIVATE KEY>\n",
456
0
        indent, "") > 0;
457
458
2
  if (BIO_printf(bio, "%*s%s Private-Key:\n", indent, "", name) <= 0)
459
0
    return 0;
460
2
  if (BIO_printf(bio, "%*spriv:\n", indent, "") <= 0)
461
0
    return 0;
462
2
  if (!ecx_buf_print(bio, ecx_key->priv_key, ecx_key->priv_key_len, indent))
463
0
    return 0;
464
2
  if (BIO_printf(bio, "%*spub:\n", indent, "") <= 0)
465
0
    return 0;
466
2
  if (!ecx_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len, indent))
467
0
    return 0;
468
469
2
  return 1;
470
2
}
471
472
static int
473
ecx_size(const EVP_PKEY *pkey)
474
0
{
475
0
  return ecx_key_len(pkey->ameth->pkey_id);
476
0
}
477
478
static int
479
ecx_sig_size(const EVP_PKEY *pkey)
480
0
{
481
0
  switch (pkey->ameth->pkey_id) {
482
0
  case EVP_PKEY_ED25519:
483
0
    return ED25519_SIG_SIZE;
484
0
  }
485
0
  return 0;
486
0
}
487
488
static int
489
ecx_bits(const EVP_PKEY *pkey)
490
0
{
491
0
  switch (pkey->ameth->pkey_id) {
492
0
  case EVP_PKEY_ED25519:
493
0
    return ED25519_BITS;
494
0
  case EVP_PKEY_X25519:
495
0
    return X25519_BITS;
496
0
  }
497
0
  return 0;
498
0
}
499
500
static int
501
ecx_security_bits(const EVP_PKEY *pkey)
502
0
{
503
0
  switch (pkey->ameth->pkey_id) {
504
0
  case EVP_PKEY_ED25519:
505
0
    return ED25519_SECURITY_BITS;
506
0
  case EVP_PKEY_X25519:
507
0
    return X25519_SECURITY_BITS;
508
0
  }
509
0
  return 0;
510
0
}
511
512
static int
513
ecx_signature_info(const X509_ALGOR *algor, int *md_nid, int *pkey_nid,
514
    int *security_bits, uint32_t *flags)
515
0
{
516
0
  const ASN1_OBJECT *aobj;
517
518
0
  X509_ALGOR_get0(&aobj, NULL, NULL, algor);
519
0
  if (OBJ_obj2nid(aobj) != EVP_PKEY_ED25519)
520
0
    return 0;
521
522
0
  *md_nid = NID_undef;
523
0
  *pkey_nid = NID_ED25519;
524
0
  *security_bits = ED25519_SECURITY_BITS;
525
0
  *flags = X509_SIG_INFO_TLS | X509_SIG_INFO_VALID;
526
527
0
  return 1;
528
0
}
529
530
static int
531
ecx_param_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2)
532
0
{
533
  /* No parameters, so always equivalent. */
534
0
  return 1;
535
0
}
536
537
static void
538
ecx_free(EVP_PKEY *pkey)
539
30
{
540
30
  struct ecx_key_st *ecx_key = pkey->pkey.ecx;
541
542
30
  ecx_key_free(ecx_key);
543
30
}
544
545
static int
546
ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
547
0
{
548
  /* Not supported. */
549
0
  return -2;
550
0
}
551
552
#ifndef OPENSSL_NO_CMS
553
static int
554
ecx_cms_sign_or_verify(EVP_PKEY *pkey, long verify, CMS_SignerInfo *si)
555
0
{
556
0
  X509_ALGOR *digestAlgorithm, *signatureAlgorithm;
557
558
0
  if (verify != 0 && verify != 1)
559
0
    return -1;
560
561
  /* Check that we have an Ed25519 public key. */
562
0
  if (EVP_PKEY_id(pkey) != NID_ED25519)
563
0
    return -1;
564
565
0
  CMS_SignerInfo_get0_algs(si, NULL, NULL, &digestAlgorithm,
566
0
      &signatureAlgorithm);
567
568
  /* RFC 8419, section 2.3: digestAlgorithm MUST be SHA-512. */
569
0
  if (digestAlgorithm == NULL)
570
0
    return -1;
571
0
  if (OBJ_obj2nid(digestAlgorithm->algorithm) != NID_sha512)
572
0
    return -1;
573
574
  /*
575
   * RFC 8419, section 2.4: signatureAlgorithm MUST be Ed25519, and the
576
   * parameters MUST be absent. For verification check that this is the
577
   * case, for signing set the signatureAlgorithm accordingly.
578
   */
579
0
  if (verify) {
580
0
    const ASN1_OBJECT *obj;
581
0
    int param_type;
582
583
0
    if (signatureAlgorithm == NULL)
584
0
      return -1;
585
586
0
    X509_ALGOR_get0(&obj, &param_type, NULL, signatureAlgorithm);
587
0
    if (OBJ_obj2nid(obj) != NID_ED25519)
588
0
      return -1;
589
0
    if (param_type != V_ASN1_UNDEF)
590
0
      return -1;
591
592
0
    return 1;
593
0
  }
594
595
0
  if (!X509_ALGOR_set0_by_nid(signatureAlgorithm, NID_ED25519,
596
0
      V_ASN1_UNDEF, NULL))
597
0
    return -1;
598
599
0
  return 1;
600
0
}
601
#endif
602
603
static int
604
ecx_sign_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
605
0
{
606
0
  switch (op) {
607
0
#ifndef OPENSSL_NO_CMS
608
0
  case ASN1_PKEY_CTRL_CMS_SIGN:
609
0
    return ecx_cms_sign_or_verify(pkey, arg1, arg2);
610
0
#endif
611
0
  case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
612
    /* PureEdDSA does its own hashing. */
613
0
    *(int *)arg2 = NID_undef;
614
0
    return 2;
615
0
  }
616
0
  return -2;
617
0
}
618
619
static int
620
ecx_set_priv_key(EVP_PKEY *pkey, const uint8_t *priv, size_t len)
621
0
{
622
0
  struct ecx_key_st *ecx_key = NULL;
623
0
  int ret = 0;
624
625
0
  if (priv == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) {
626
0
    ECerror(EC_R_INVALID_ENCODING);
627
0
    goto err;
628
0
  }
629
630
0
  if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
631
0
    goto err;
632
0
  if (!ecx_key_set_priv(ecx_key, priv, len))
633
0
    goto err;
634
0
  if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
635
0
    goto err;
636
0
  ecx_key = NULL;
637
638
0
  ret = 1;
639
640
0
 err:
641
0
  ecx_key_free(ecx_key);
642
643
0
  return ret;
644
0
}
645
646
static int
647
ecx_set_pub_key(EVP_PKEY *pkey, const uint8_t *pub, size_t len)
648
0
{
649
0
  struct ecx_key_st *ecx_key = NULL;
650
0
  int ret = 0;
651
652
0
  if (pub == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) {
653
0
    ECerror(EC_R_INVALID_ENCODING);
654
0
    goto err;
655
0
  }
656
657
0
  if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
658
0
    goto err;
659
0
  if (!ecx_key_set_pub(ecx_key, pub, len))
660
0
    goto err;
661
0
  if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
662
0
    goto err;
663
0
  ecx_key = NULL;
664
665
0
  ret = 1;
666
667
0
 err:
668
0
  ecx_key_free(ecx_key);
669
670
0
  return ret;
671
0
}
672
673
static int
674
ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *out_priv, size_t *out_len)
675
0
{
676
0
  struct ecx_key_st *ecx_key = pkey->pkey.ecx;
677
0
  CBS cbs;
678
679
0
  if (out_priv == NULL) {
680
0
    *out_len = ecx_key_len(pkey->ameth->pkey_id);
681
0
    return 1;
682
0
  }
683
684
0
  if (ecx_key == NULL || ecx_key->priv_key == NULL)
685
0
    return 0;
686
687
0
  CBS_init(&cbs, ecx_key->priv_key, ecx_key->priv_key_len);
688
0
  if (!CBS_write_bytes(&cbs, out_priv, *out_len, out_len))
689
0
    return 0;
690
691
0
  return 1;
692
0
}
693
694
static int
695
ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *out_pub, size_t *out_len)
696
0
{
697
0
  struct ecx_key_st *ecx_key = pkey->pkey.ecx;
698
0
  CBS cbs;
699
700
0
  if (out_pub == NULL) {
701
0
    *out_len = ecx_key_len(pkey->ameth->pkey_id);
702
0
    return 1;
703
0
  }
704
705
0
  if (ecx_key == NULL || ecx_key->pub_key == NULL)
706
0
    return 0;
707
708
0
  CBS_init(&cbs, ecx_key->pub_key, ecx_key->pub_key_len);
709
0
  if (!CBS_write_bytes(&cbs, out_pub, *out_len, out_len))
710
0
    return 0;
711
712
0
  return 1;
713
0
}
714
715
static int
716
pkey_ecx_keygen(EVP_PKEY_CTX *pkey_ctx, EVP_PKEY *pkey)
717
0
{
718
0
  struct ecx_key_st *ecx_key = NULL;
719
0
  int ret = 0;
720
721
0
  if ((ecx_key = ecx_key_new(pkey_ctx->pmeth->pkey_id)) == NULL)
722
0
    goto err;
723
0
  if (!ecx_key_generate(ecx_key))
724
0
    goto err;
725
0
  if (!EVP_PKEY_assign(pkey, pkey_ctx->pmeth->pkey_id, ecx_key))
726
0
    goto err;
727
0
  ecx_key = NULL;
728
729
0
  ret = 1;
730
731
0
 err:
732
0
  ecx_key_free(ecx_key);
733
734
0
  return ret;
735
0
}
736
737
static int
738
pkey_ecx_derive(EVP_PKEY_CTX *pkey_ctx, unsigned char *out_key,
739
    size_t *out_key_len)
740
0
{
741
0
  struct ecx_key_st *ecx_key, *ecx_peer_key;
742
743
0
  if (pkey_ctx->pkey == NULL || pkey_ctx->peerkey == NULL) {
744
0
    ECerror(EC_R_KEYS_NOT_SET);
745
0
    return 0;
746
0
  }
747
748
0
  if ((ecx_key = pkey_ctx->pkey->pkey.ecx) == NULL) {
749
0
    ECerror(EC_R_INVALID_PRIVATE_KEY);
750
0
    return 0;
751
0
  }
752
0
  if (ecx_key->priv_key == NULL) {
753
0
    ECerror(EC_R_INVALID_PRIVATE_KEY);
754
0
    return 0;
755
0
  }
756
757
0
  if ((ecx_peer_key = pkey_ctx->peerkey->pkey.ecx) == NULL) {
758
0
    ECerror(EC_R_INVALID_PEER_KEY);
759
0
    return 0;
760
0
  }
761
762
0
  if (out_key != NULL) {
763
0
    if (!X25519(out_key, ecx_key->priv_key, ecx_peer_key->pub_key))
764
0
      return 0;
765
0
  }
766
767
0
  *out_key_len = X25519_KEYLEN;
768
769
0
  return 1;
770
0
}
771
772
static int
773
pkey_ecx_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2)
774
0
{
775
0
  if (op == EVP_PKEY_CTRL_PEER_KEY)
776
0
    return 1;
777
778
0
  return -2;
779
0
}
780
781
static int
782
ecx_item_verify(EVP_MD_CTX *md_ctx, const ASN1_ITEM *it, void *asn,
783
   X509_ALGOR *algor, ASN1_BIT_STRING *abs, EVP_PKEY *pkey)
784
0
{
785
0
  const ASN1_OBJECT *aobj;
786
0
  int nid, param_type;
787
788
0
  X509_ALGOR_get0(&aobj, &param_type, NULL, algor);
789
790
0
  nid = OBJ_obj2nid(aobj);
791
792
0
  if (nid != NID_ED25519 || param_type != V_ASN1_UNDEF) {
793
0
    ECerror(EC_R_INVALID_ENCODING);
794
0
    return -1;
795
0
  }
796
797
0
  if (!EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, pkey))
798
0
    return -1;
799
800
0
  return 2;
801
0
}
802
803
static int
804
ecx_item_sign(EVP_MD_CTX *md_ctx, const ASN1_ITEM *it, void *asn,
805
    X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *abs)
806
0
{
807
0
  if (!X509_ALGOR_set0_by_nid(algor1, NID_ED25519, V_ASN1_UNDEF, NULL))
808
0
    return 0;
809
810
0
  if (algor2 != NULL) {
811
0
    if (!X509_ALGOR_set0_by_nid(algor2, NID_ED25519, V_ASN1_UNDEF,
812
0
        NULL))
813
0
      return 0;
814
0
  }
815
816
  /* Tell ASN1_item_sign_ctx() that identifiers are set and it needs to sign. */
817
0
  return 3;
818
0
}
819
820
static int
821
pkey_ecx_digestsign(EVP_MD_CTX *md_ctx, unsigned char *out_sig,
822
    size_t *out_sig_len, const unsigned char *message, size_t message_len)
823
0
{
824
0
  struct ecx_key_st *ecx_key;
825
0
  EVP_PKEY_CTX *pkey_ctx;
826
827
0
  pkey_ctx = EVP_MD_CTX_pkey_ctx(md_ctx);
828
0
  ecx_key = pkey_ctx->pkey->pkey.ecx;
829
830
0
  if (out_sig == NULL) {
831
0
    *out_sig_len = ecx_sig_size(pkey_ctx->pkey);
832
0
    return 1;
833
0
  }
834
0
  if (*out_sig_len < ecx_sig_size(pkey_ctx->pkey)) {
835
0
    ECerror(EC_R_BUFFER_TOO_SMALL);
836
0
    return 0;
837
0
  }
838
839
0
  if (ecx_key == NULL)
840
0
    return 0;
841
0
  if (ecx_key->priv_key == NULL || ecx_key->pub_key == NULL)
842
0
    return 0;
843
844
0
  if (!ED25519_sign(out_sig, message, message_len, ecx_key->pub_key,
845
0
      ecx_key->priv_key))
846
0
    return 0;
847
848
0
  *out_sig_len = ecx_sig_size(pkey_ctx->pkey);
849
850
0
  return 1;
851
0
}
852
853
static int
854
pkey_ecx_digestverify(EVP_MD_CTX *md_ctx, const unsigned char *sig,
855
   size_t sig_len, const unsigned char *message, size_t message_len)
856
0
{
857
0
  struct ecx_key_st *ecx_key;
858
0
  EVP_PKEY_CTX *pkey_ctx;
859
860
0
  pkey_ctx = EVP_MD_CTX_pkey_ctx(md_ctx);
861
0
  ecx_key = pkey_ctx->pkey->pkey.ecx;
862
863
0
  if (ecx_key == NULL || ecx_key->pub_key == NULL)
864
0
    return -1;
865
0
  if (sig_len != ecx_sig_size(pkey_ctx->pkey))
866
0
    return -1;
867
868
0
  return ED25519_verify(message, message_len, sig, ecx_key->pub_key);
869
0
}
870
871
static int
872
pkey_ecx_ed_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2)
873
0
{
874
0
  switch (op) {
875
0
  case EVP_PKEY_CTRL_MD:
876
    /* PureEdDSA does its own hashing. */
877
0
    if (arg2 != NULL && (const EVP_MD *)arg2 != EVP_md_null()) {
878
0
      ECerror(EC_R_INVALID_DIGEST_TYPE);
879
0
      return 0;
880
0
    }
881
0
    return 1;
882
883
0
#ifndef OPENSSL_NO_CMS
884
0
  case EVP_PKEY_CTRL_CMS_SIGN:
885
0
#endif
886
0
  case EVP_PKEY_CTRL_DIGESTINIT:
887
0
    return 1;
888
0
  }
889
0
  return -2;
890
0
}
891
892
const EVP_PKEY_ASN1_METHOD x25519_asn1_meth = {
893
  .base_method = &x25519_asn1_meth,
894
  .pkey_id = EVP_PKEY_X25519,
895
  .pkey_flags = 0,
896
  .pem_str = "X25519",
897
  .info = "OpenSSL X25519 algorithm",
898
899
  .pub_decode = ecx_pub_decode,
900
  .pub_encode = ecx_pub_encode,
901
  .pub_cmp = ecx_pub_cmp,
902
  .pub_print = ecx_pub_print,
903
904
  .priv_decode = ecx_priv_decode,
905
  .priv_encode = ecx_priv_encode,
906
  .priv_print = ecx_priv_print,
907
908
  .pkey_size = ecx_size,
909
  .pkey_bits = ecx_bits,
910
  .pkey_security_bits = ecx_security_bits,
911
912
  .param_cmp = ecx_param_cmp,
913
914
  .pkey_free = ecx_free,
915
  .pkey_ctrl = ecx_ctrl,
916
917
  .set_priv_key = ecx_set_priv_key,
918
  .set_pub_key = ecx_set_pub_key,
919
  .get_priv_key = ecx_get_priv_key,
920
  .get_pub_key = ecx_get_pub_key,
921
};
922
923
const EVP_PKEY_METHOD x25519_pkey_meth = {
924
  .pkey_id = EVP_PKEY_X25519,
925
  .keygen = pkey_ecx_keygen,
926
  .derive = pkey_ecx_derive,
927
  .ctrl = pkey_ecx_ctrl,
928
};
929
930
const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
931
  .base_method = &ed25519_asn1_meth,
932
  .pkey_id = EVP_PKEY_ED25519,
933
  .pkey_flags = 0,
934
  .pem_str = "ED25519",
935
  .info = "OpenSSL ED25519 algorithm",
936
937
  .pub_decode = ecx_pub_decode,
938
  .pub_encode = ecx_pub_encode,
939
  .pub_cmp = ecx_pub_cmp,
940
  .pub_print = ecx_pub_print,
941
942
  .priv_decode = ecx_priv_decode,
943
  .priv_encode = ecx_priv_encode,
944
  .priv_print = ecx_priv_print,
945
946
  .pkey_size = ecx_sig_size,
947
  .pkey_bits = ecx_bits,
948
  .pkey_security_bits = ecx_security_bits,
949
950
  .signature_info = ecx_signature_info,
951
952
  .param_cmp = ecx_param_cmp,
953
954
  .pkey_free = ecx_free,
955
  .pkey_ctrl = ecx_sign_ctrl,
956
957
  .item_verify = ecx_item_verify,
958
  .item_sign = ecx_item_sign,
959
960
  .set_priv_key = ecx_set_priv_key,
961
  .set_pub_key = ecx_set_pub_key,
962
  .get_priv_key = ecx_get_priv_key,
963
  .get_pub_key = ecx_get_pub_key,
964
};
965
966
const EVP_PKEY_METHOD ed25519_pkey_meth = {
967
  .pkey_id = EVP_PKEY_ED25519,
968
  .flags = EVP_PKEY_FLAG_SIGCTX_CUSTOM,
969
  .keygen = pkey_ecx_keygen,
970
  .ctrl = pkey_ecx_ed_ctrl,
971
  .digestsign = pkey_ecx_digestsign,
972
  .digestverify = pkey_ecx_digestverify,
973
};