Coverage Report

Created: 2018-08-29 13:53

/src/openssl/crypto/ec/ecx_meth.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the OpenSSL license (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include "internal/cryptlib.h"
12
#include <openssl/x509.h>
13
#include <openssl/ec.h>
14
#include <openssl/rand.h>
15
#include "internal/asn1_int.h"
16
#include "internal/evp_int.h"
17
#include "ec_lcl.h"
18
19
0
#define X25519_BITS          253
20
0
#define X25519_SECURITY_BITS 128
21
22
0
#define ED25519_SIGSIZE      64
23
24
0
#define X448_BITS            448
25
0
#define ED448_BITS           456
26
0
#define X448_SECURITY_BITS   224
27
28
0
#define ED448_SIGSIZE        114
29
30
0
#define ISX448(id)      ((id) == EVP_PKEY_X448)
31
0
#define IS25519(id)     ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519)
32
0
#define KEYLENID(id)    (IS25519(id) ? X25519_KEYLEN \
33
0
                                     : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \
34
0
                                                              : ED448_KEYLEN))
35
0
#define KEYLEN(p)       KEYLENID((p)->ameth->pkey_id)
36
37
38
typedef enum {
39
    KEY_OP_PUBLIC,
40
    KEY_OP_PRIVATE,
41
    KEY_OP_KEYGEN
42
} ecx_key_op_t;
43
44
/* Setup EVP_PKEY using public, private or generation */
45
static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
46
                      const unsigned char *p, int plen, ecx_key_op_t op)
47
0
{
48
0
    ECX_KEY *key = NULL;
49
0
    unsigned char *privkey, *pubkey;
50
0
51
0
    if (op != KEY_OP_KEYGEN) {
52
0
        if (palg != NULL) {
53
0
            int ptype;
54
0
55
0
            /* Algorithm parameters must be absent */
56
0
            X509_ALGOR_get0(NULL, &ptype, NULL, palg);
57
0
            if (ptype != V_ASN1_UNDEF) {
58
0
                ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
59
0
                return 0;
60
0
            }
61
0
        }
62
0
63
0
        if (p == NULL || plen != KEYLENID(id)) {
64
0
            ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
65
0
            return 0;
66
0
        }
67
0
    }
68
0
69
0
    key = OPENSSL_zalloc(sizeof(*key));
70
0
    if (key == NULL) {
71
0
        ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
72
0
        return 0;
73
0
    }
74
0
    pubkey = key->pubkey;
75
0
76
0
    if (op == KEY_OP_PUBLIC) {
77
0
        memcpy(pubkey, p, plen);
78
0
    } else {
79
0
        privkey = key->privkey = OPENSSL_secure_malloc(KEYLENID(id));
80
0
        if (privkey == NULL) {
81
0
            ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
82
0
            goto err;
83
0
        }
84
0
        if (op == KEY_OP_KEYGEN) {
85
0
            if (RAND_priv_bytes(privkey, KEYLENID(id)) <= 0) {
86
0
                OPENSSL_secure_free(privkey);
87
0
                key->privkey = NULL;
88
0
                goto err;
89
0
            }
90
0
            if (id == EVP_PKEY_X25519) {
91
0
                privkey[0] &= 248;
92
0
                privkey[X25519_KEYLEN - 1] &= 127;
93
0
                privkey[X25519_KEYLEN - 1] |= 64;
94
0
            } else if (id == EVP_PKEY_X448) {
95
0
                privkey[0] &= 252;
96
0
                privkey[X448_KEYLEN - 1] |= 128;
97
0
            }
98
0
        } else {
99
0
            memcpy(privkey, p, KEYLENID(id));
100
0
        }
101
0
        switch (id) {
102
0
        case EVP_PKEY_X25519:
103
0
            X25519_public_from_private(pubkey, privkey);
104
0
            break;
105
0
        case EVP_PKEY_ED25519:
106
0
            ED25519_public_from_private(pubkey, privkey);
107
0
            break;
108
0
        case EVP_PKEY_X448:
109
0
            X448_public_from_private(pubkey, privkey);
110
0
            break;
111
0
        case EVP_PKEY_ED448:
112
0
            ED448_public_from_private(pubkey, privkey);
113
0
            break;
114
0
        }
115
0
    }
116
0
117
0
    EVP_PKEY_assign(pkey, id, key);
118
0
    return 1;
119
0
 err:
120
0
    OPENSSL_free(key);
121
0
    return 0;
122
0
}
123
124
static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
125
0
{
126
0
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
127
0
    unsigned char *penc;
128
0
129
0
    if (ecxkey == NULL) {
130
0
        ECerr(EC_F_ECX_PUB_ENCODE, EC_R_INVALID_KEY);
131
0
        return 0;
132
0
    }
133
0
134
0
    penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
135
0
    if (penc == NULL) {
136
0
        ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
137
0
        return 0;
138
0
    }
139
0
140
0
    if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
141
0
                                V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
142
0
        OPENSSL_free(penc);
143
0
        ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
144
0
        return 0;
145
0
    }
146
0
    return 1;
147
0
}
148
149
static int ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
150
0
{
151
0
    const unsigned char *p;
152
0
    int pklen;
153
0
    X509_ALGOR *palg;
154
0
155
0
    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
156
0
        return 0;
157
0
    return ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, pklen,
158
0
                      KEY_OP_PUBLIC);
159
0
}
160
161
static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
162
0
{
163
0
    const ECX_KEY *akey = a->pkey.ecx;
164
0
    const ECX_KEY *bkey = b->pkey.ecx;
165
0
166
0
    if (akey == NULL || bkey == NULL)
167
0
        return -2;
168
0
169
0
    return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
170
0
}
171
172
static int ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
173
0
{
174
0
    const unsigned char *p;
175
0
    int plen;
176
0
    ASN1_OCTET_STRING *oct = NULL;
177
0
    const X509_ALGOR *palg;
178
0
    int rv;
179
0
180
0
    if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8))
181
0
        return 0;
182
0
183
0
    oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen);
184
0
    if (oct == NULL) {
185
0
        p = NULL;
186
0
        plen = 0;
187
0
    } else {
188
0
        p = ASN1_STRING_get0_data(oct);
189
0
        plen = ASN1_STRING_length(oct);
190
0
    }
191
0
192
0
    rv = ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, plen, KEY_OP_PRIVATE);
193
0
    ASN1_OCTET_STRING_free(oct);
194
0
    return rv;
195
0
}
196
197
static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
198
0
{
199
0
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
200
0
    ASN1_OCTET_STRING oct;
201
0
    unsigned char *penc = NULL;
202
0
    int penclen;
203
0
204
0
    if (ecxkey == NULL || ecxkey->privkey == NULL) {
205
0
        ECerr(EC_F_ECX_PRIV_ENCODE, EC_R_INVALID_PRIVATE_KEY);
206
0
        return 0;
207
0
    }
208
0
209
0
    oct.data = ecxkey->privkey;
210
0
    oct.length = KEYLEN(pkey);
211
0
    oct.flags = 0;
212
0
213
0
    penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
214
0
    if (penclen < 0) {
215
0
        ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
216
0
        return 0;
217
0
    }
218
0
219
0
    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
220
0
                         V_ASN1_UNDEF, NULL, penc, penclen)) {
221
0
        OPENSSL_clear_free(penc, penclen);
222
0
        ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
223
0
        return 0;
224
0
    }
225
0
226
0
    return 1;
227
0
}
228
229
static int ecx_size(const EVP_PKEY *pkey)
230
0
{
231
0
    return KEYLEN(pkey);
232
0
}
233
234
static int ecx_bits(const EVP_PKEY *pkey)
235
0
{
236
0
    if (IS25519(pkey->ameth->pkey_id)) {
237
0
        return X25519_BITS;
238
0
    } else if(ISX448(pkey->ameth->pkey_id)) {
239
0
        return X448_BITS;
240
0
    } else {
241
0
        return ED448_BITS;
242
0
    }
243
0
}
244
245
static int ecx_security_bits(const EVP_PKEY *pkey)
246
0
{
247
0
    if (IS25519(pkey->ameth->pkey_id)) {
248
0
        return X25519_SECURITY_BITS;
249
0
    } else {
250
0
        return X448_SECURITY_BITS;
251
0
    }
252
0
}
253
254
static void ecx_free(EVP_PKEY *pkey)
255
0
{
256
0
    if (pkey->pkey.ecx != NULL)
257
0
        OPENSSL_secure_clear_free(pkey->pkey.ecx->privkey, KEYLEN(pkey));
258
0
    OPENSSL_free(pkey->pkey.ecx);
259
0
}
260
261
/* "parameters" are always equal */
262
static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
263
0
{
264
0
    return 1;
265
0
}
266
267
static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
268
                         ASN1_PCTX *ctx, ecx_key_op_t op)
269
0
{
270
0
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
271
0
    const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
272
0
273
0
    if (op == KEY_OP_PRIVATE) {
274
0
        if (ecxkey == NULL || ecxkey->privkey == NULL) {
275
0
            if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
276
0
                return 0;
277
0
            return 1;
278
0
        }
279
0
        if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
280
0
            return 0;
281
0
        if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
282
0
            return 0;
283
0
        if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
284
0
                           indent + 4) == 0)
285
0
            return 0;
286
0
    } else {
287
0
        if (ecxkey == NULL) {
288
0
            if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
289
0
                return 0;
290
0
            return 1;
291
0
        }
292
0
        if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
293
0
            return 0;
294
0
    }
295
0
    if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
296
0
        return 0;
297
0
298
0
    if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
299
0
                       indent + 4) == 0)
300
0
        return 0;
301
0
    return 1;
302
0
}
303
304
static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
305
                          ASN1_PCTX *ctx)
306
0
{
307
0
    return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
308
0
}
309
310
static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
311
                         ASN1_PCTX *ctx)
312
0
{
313
0
    return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
314
0
}
315
316
static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
317
0
{
318
0
    switch (op) {
319
0
320
0
    case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
321
0
        return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, arg2, arg1,
322
0
                          KEY_OP_PUBLIC);
323
0
324
0
    case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
325
0
        if (pkey->pkey.ecx != NULL) {
326
0
            unsigned char **ppt = arg2;
327
0
328
0
            *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
329
0
            if (*ppt != NULL)
330
0
                return KEYLEN(pkey);
331
0
        }
332
0
        return 0;
333
0
334
0
    default:
335
0
        return -2;
336
0
337
0
    }
338
0
}
339
340
static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
341
0
{
342
0
    switch (op) {
343
0
    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
344
0
        /* We currently only support Pure EdDSA which takes no digest */
345
0
        *(int *)arg2 = NID_undef;
346
0
        return 2;
347
0
348
0
    default:
349
0
        return -2;
350
0
351
0
    }
352
0
}
353
354
static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
355
                            size_t len)
356
0
{
357
0
    return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, priv, len,
358
0
                       KEY_OP_PRIVATE);
359
0
}
360
361
static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
362
0
{
363
0
    return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, pub, len,
364
0
                      KEY_OP_PUBLIC);
365
0
}
366
367
static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
368
                            size_t *len)
369
0
{
370
0
    const ECX_KEY *key = pkey->pkey.ecx;
371
0
372
0
    if (priv == NULL) {
373
0
        *len = KEYLENID(pkey->ameth->pkey_id);
374
0
        return 1;
375
0
    }
376
0
377
0
    if (key == NULL
378
0
            || key->privkey == NULL
379
0
            || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
380
0
        return 0;
381
0
382
0
    *len = KEYLENID(pkey->ameth->pkey_id);
383
0
    memcpy(priv, key->privkey, *len);
384
0
385
0
    return 1;
386
0
}
387
388
static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
389
                           size_t *len)
390
0
{
391
0
    const ECX_KEY *key = pkey->pkey.ecx;
392
0
393
0
    if (pub == NULL) {
394
0
        *len = KEYLENID(pkey->ameth->pkey_id);
395
0
        return 1;
396
0
    }
397
0
398
0
    if (key == NULL
399
0
            || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
400
0
        return 0;
401
0
402
0
    *len = KEYLENID(pkey->ameth->pkey_id);
403
0
    memcpy(pub, key->pubkey, *len);
404
0
405
0
    return 1;
406
0
}
407
408
const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
409
    EVP_PKEY_X25519,
410
    EVP_PKEY_X25519,
411
    0,
412
    "X25519",
413
    "OpenSSL X25519 algorithm",
414
415
    ecx_pub_decode,
416
    ecx_pub_encode,
417
    ecx_pub_cmp,
418
    ecx_pub_print,
419
420
    ecx_priv_decode,
421
    ecx_priv_encode,
422
    ecx_priv_print,
423
424
    ecx_size,
425
    ecx_bits,
426
    ecx_security_bits,
427
428
    0, 0, 0, 0,
429
    ecx_cmp_parameters,
430
    0, 0,
431
432
    ecx_free,
433
    ecx_ctrl,
434
    NULL,
435
    NULL,
436
437
    NULL,
438
    NULL,
439
    NULL,
440
441
    NULL,
442
    NULL,
443
    NULL,
444
445
    ecx_set_priv_key,
446
    ecx_set_pub_key,
447
    ecx_get_priv_key,
448
    ecx_get_pub_key,
449
};
450
451
const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
452
    EVP_PKEY_X448,
453
    EVP_PKEY_X448,
454
    0,
455
    "X448",
456
    "OpenSSL X448 algorithm",
457
458
    ecx_pub_decode,
459
    ecx_pub_encode,
460
    ecx_pub_cmp,
461
    ecx_pub_print,
462
463
    ecx_priv_decode,
464
    ecx_priv_encode,
465
    ecx_priv_print,
466
467
    ecx_size,
468
    ecx_bits,
469
    ecx_security_bits,
470
471
    0, 0, 0, 0,
472
    ecx_cmp_parameters,
473
    0, 0,
474
475
    ecx_free,
476
    ecx_ctrl,
477
    NULL,
478
    NULL,
479
480
    NULL,
481
    NULL,
482
    NULL,
483
484
    NULL,
485
    NULL,
486
    NULL,
487
488
    ecx_set_priv_key,
489
    ecx_set_pub_key,
490
    ecx_get_priv_key,
491
    ecx_get_pub_key,
492
};
493
494
static int ecd_size25519(const EVP_PKEY *pkey)
495
0
{
496
0
    return ED25519_SIGSIZE;
497
0
}
498
499
static int ecd_size448(const EVP_PKEY *pkey)
500
0
{
501
0
    return ED448_SIGSIZE;
502
0
}
503
504
static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
505
                           X509_ALGOR *sigalg, ASN1_BIT_STRING *str,
506
                           EVP_PKEY *pkey)
507
0
{
508
0
    const ASN1_OBJECT *obj;
509
0
    int ptype;
510
0
    int nid;
511
0
512
0
    /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
513
0
    X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
514
0
    nid = OBJ_obj2nid(obj);
515
0
    if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
516
0
        ECerr(EC_F_ECD_ITEM_VERIFY, EC_R_INVALID_ENCODING);
517
0
        return 0;
518
0
    }
519
0
520
0
    if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
521
0
        return 0;
522
0
523
0
    return 2;
524
0
}
525
526
static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
527
                              X509_ALGOR *alg1, X509_ALGOR *alg2,
528
                              ASN1_BIT_STRING *str)
529
0
{
530
0
    /* Set algorithms identifiers */
531
0
    X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
532
0
    if (alg2)
533
0
        X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
534
0
    /* Algorithm idetifiers set: carry on as normal */
535
0
    return 3;
536
0
}
537
538
static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
539
                                 const ASN1_STRING *sig)
540
0
{
541
0
    X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
542
0
                      X509_SIG_INFO_TLS);
543
0
    return 1;
544
0
}
545
546
static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
547
                            X509_ALGOR *alg1, X509_ALGOR *alg2,
548
                            ASN1_BIT_STRING *str)
549
0
{
550
0
    /* Set algorithm identifier */
551
0
    X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
552
0
    if (alg2 != NULL)
553
0
        X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
554
0
    /* Algorithm identifier set: carry on as normal */
555
0
    return 3;
556
0
}
557
558
static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
559
                               const ASN1_STRING *sig)
560
0
{
561
0
    X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
562
0
                      X509_SIG_INFO_TLS);
563
0
    return 1;
564
0
}
565
566
567
const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
568
    EVP_PKEY_ED25519,
569
    EVP_PKEY_ED25519,
570
    0,
571
    "ED25519",
572
    "OpenSSL ED25519 algorithm",
573
574
    ecx_pub_decode,
575
    ecx_pub_encode,
576
    ecx_pub_cmp,
577
    ecx_pub_print,
578
579
    ecx_priv_decode,
580
    ecx_priv_encode,
581
    ecx_priv_print,
582
583
    ecd_size25519,
584
    ecx_bits,
585
    ecx_security_bits,
586
587
    0, 0, 0, 0,
588
    ecx_cmp_parameters,
589
    0, 0,
590
591
    ecx_free,
592
    ecd_ctrl,
593
    NULL,
594
    NULL,
595
    ecd_item_verify,
596
    ecd_item_sign25519,
597
    ecd_sig_info_set25519,
598
599
    NULL,
600
    NULL,
601
    NULL,
602
603
    ecx_set_priv_key,
604
    ecx_set_pub_key,
605
    ecx_get_priv_key,
606
    ecx_get_pub_key,
607
};
608
609
const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
610
    EVP_PKEY_ED448,
611
    EVP_PKEY_ED448,
612
    0,
613
    "ED448",
614
    "OpenSSL ED448 algorithm",
615
616
    ecx_pub_decode,
617
    ecx_pub_encode,
618
    ecx_pub_cmp,
619
    ecx_pub_print,
620
621
    ecx_priv_decode,
622
    ecx_priv_encode,
623
    ecx_priv_print,
624
625
    ecd_size448,
626
    ecx_bits,
627
    ecx_security_bits,
628
629
    0, 0, 0, 0,
630
    ecx_cmp_parameters,
631
    0, 0,
632
633
    ecx_free,
634
    ecd_ctrl,
635
    NULL,
636
    NULL,
637
    ecd_item_verify,
638
    ecd_item_sign448,
639
    ecd_sig_info_set448,
640
641
    NULL,
642
    NULL,
643
    NULL,
644
645
    ecx_set_priv_key,
646
    ecx_set_pub_key,
647
    ecx_get_priv_key,
648
    ecx_get_pub_key,
649
};
650
651
static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
652
0
{
653
0
    return ecx_key_op(pkey, ctx->pmeth->pkey_id, NULL, NULL, 0, KEY_OP_KEYGEN);
654
0
}
655
656
static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
657
                                          size_t *keylen,
658
                                          const unsigned char **privkey,
659
                                          const unsigned char **pubkey)
660
0
{
661
0
    const ECX_KEY *ecxkey, *peerkey;
662
0
663
0
    if (ctx->pkey == NULL || ctx->peerkey == NULL) {
664
0
        ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_KEYS_NOT_SET);
665
0
        return 0;
666
0
    }
667
0
    ecxkey = ctx->pkey->pkey.ecx;
668
0
    peerkey = ctx->peerkey->pkey.ecx;
669
0
    if (ecxkey == NULL || ecxkey->privkey == NULL) {
670
0
        ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PRIVATE_KEY);
671
0
        return 0;
672
0
    }
673
0
    if (peerkey == NULL) {
674
0
        ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PEER_KEY);
675
0
        return 0;
676
0
    }
677
0
    *privkey = ecxkey->privkey;
678
0
    *pubkey = peerkey->pubkey;
679
0
680
0
    return 1;
681
0
}
682
683
static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
684
                                size_t *keylen)
685
0
{
686
0
    const unsigned char *privkey, *pubkey;
687
0
688
0
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
689
0
            || (key != NULL
690
0
                && X25519(key, privkey, pubkey) == 0))
691
0
        return 0;
692
0
    *keylen = X25519_KEYLEN;
693
0
    return 1;
694
0
}
695
696
static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
697
                              size_t *keylen)
698
0
{
699
0
    const unsigned char *privkey, *pubkey;
700
0
701
0
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
702
0
            || (key != NULL
703
0
                && X448(key, privkey, pubkey) == 0))
704
0
        return 0;
705
0
    *keylen = X448_KEYLEN;
706
0
    return 1;
707
0
}
708
709
static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
710
0
{
711
0
    /* Only need to handle peer key for derivation */
712
0
    if (type == EVP_PKEY_CTRL_PEER_KEY)
713
0
        return 1;
714
0
    return -2;
715
0
}
716
717
const EVP_PKEY_METHOD ecx25519_pkey_meth = {
718
    EVP_PKEY_X25519,
719
    0, 0, 0, 0, 0, 0, 0,
720
    pkey_ecx_keygen,
721
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
722
    pkey_ecx_derive25519,
723
    pkey_ecx_ctrl,
724
    0
725
};
726
727
const EVP_PKEY_METHOD ecx448_pkey_meth = {
728
    EVP_PKEY_X448,
729
    0, 0, 0, 0, 0, 0, 0,
730
    pkey_ecx_keygen,
731
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
732
    pkey_ecx_derive448,
733
    pkey_ecx_ctrl,
734
    0
735
};
736
737
static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
738
                                    size_t *siglen, const unsigned char *tbs,
739
                                    size_t tbslen)
740
0
{
741
0
    const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
742
0
743
0
    if (sig == NULL) {
744
0
        *siglen = ED25519_SIGSIZE;
745
0
        return 1;
746
0
    }
747
0
    if (*siglen < ED25519_SIGSIZE) {
748
0
        ECerr(EC_F_PKEY_ECD_DIGESTSIGN25519, EC_R_BUFFER_TOO_SMALL);
749
0
        return 0;
750
0
    }
751
0
752
0
    if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey) == 0)
753
0
        return 0;
754
0
    *siglen = ED25519_SIGSIZE;
755
0
    return 1;
756
0
}
757
758
static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
759
                                  size_t *siglen, const unsigned char *tbs,
760
                                  size_t tbslen)
761
0
{
762
0
    const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
763
0
764
0
    if (sig == NULL) {
765
0
        *siglen = ED448_SIGSIZE;
766
0
        return 1;
767
0
    }
768
0
    if (*siglen < ED448_SIGSIZE) {
769
0
        ECerr(EC_F_PKEY_ECD_DIGESTSIGN448, EC_R_BUFFER_TOO_SMALL);
770
0
        return 0;
771
0
    }
772
0
773
0
    if (ED448_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
774
0
                   0) == 0)
775
0
        return 0;
776
0
    *siglen = ED448_SIGSIZE;
777
0
    return 1;
778
0
}
779
780
static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
781
                                      size_t siglen, const unsigned char *tbs,
782
                                      size_t tbslen)
783
0
{
784
0
    const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
785
0
786
0
    if (siglen != ED25519_SIGSIZE)
787
0
        return 0;
788
0
789
0
    return ED25519_verify(tbs, tbslen, sig, edkey->pubkey);
790
0
}
791
792
static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
793
                                    size_t siglen, const unsigned char *tbs,
794
                                    size_t tbslen)
795
0
{
796
0
    const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
797
0
798
0
    if (siglen != ED448_SIGSIZE)
799
0
        return 0;
800
0
801
0
    return ED448_verify(tbs, tbslen, sig, edkey->pubkey, NULL, 0);
802
0
}
803
804
static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
805
0
{
806
0
    switch (type) {
807
0
    case EVP_PKEY_CTRL_MD:
808
0
        /* Only NULL allowed as digest */
809
0
        if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
810
0
            return 1;
811
0
        ECerr(EC_F_PKEY_ECD_CTRL, EC_R_INVALID_DIGEST_TYPE);
812
0
        return 0;
813
0
814
0
    case EVP_PKEY_CTRL_DIGESTINIT:
815
0
        return 1;
816
0
    }
817
0
    return -2;
818
0
}
819
820
const EVP_PKEY_METHOD ed25519_pkey_meth = {
821
    EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
822
    0, 0, 0, 0, 0, 0,
823
    pkey_ecx_keygen,
824
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
825
    pkey_ecd_ctrl,
826
    0,
827
    pkey_ecd_digestsign25519,
828
    pkey_ecd_digestverify25519
829
};
830
831
const EVP_PKEY_METHOD ed448_pkey_meth = {
832
    EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
833
    0, 0, 0, 0, 0, 0,
834
    pkey_ecx_keygen,
835
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
836
    pkey_ecd_ctrl,
837
    0,
838
    pkey_ecd_digestsign448,
839
    pkey_ecd_digestverify448
840
};