Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl30/crypto/ec/ecx_meth.c
Line
Count
Source
1
/*
2
 * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (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
/*
11
 * ECDSA low level APIs are deprecated for public use, but still ok for
12
 * internal use.
13
 */
14
#include "internal/deprecated.h"
15
16
#include <stdio.h>
17
#include <openssl/x509.h>
18
#include <openssl/ec.h>
19
#include <openssl/core_names.h>
20
#include <openssl/param_build.h>
21
#include <openssl/rand.h>
22
#include "internal/cryptlib.h"
23
#include "internal/provider.h"
24
#include "crypto/asn1.h"
25
#include "crypto/evp.h"
26
#include "crypto/ecx.h"
27
#include "ec_local.h"
28
#include "curve448/curve448_local.h"
29
#include "ecx_backend.h"
30
31
static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
32
0
{
33
0
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
34
0
    unsigned char *penc;
35
36
0
    if (ecxkey == NULL) {
37
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
38
0
        return 0;
39
0
    }
40
41
0
    penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
42
0
    if (penc == NULL) {
43
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
44
0
        return 0;
45
0
    }
46
47
0
    if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
48
0
            V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
49
0
        OPENSSL_free(penc);
50
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
51
0
        return 0;
52
0
    }
53
0
    return 1;
54
0
}
55
56
static int ecx_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
57
16.0k
{
58
16.0k
    const unsigned char *p;
59
16.0k
    int pklen;
60
16.0k
    X509_ALGOR *palg;
61
16.0k
    ECX_KEY *ecx;
62
16.0k
    int ret = 0;
63
64
16.0k
    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
65
0
        return 0;
66
16.0k
    ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id,
67
16.0k
        KEY_OP_PUBLIC, NULL, NULL);
68
16.0k
    if (ecx != NULL) {
69
3.20k
        ret = 1;
70
3.20k
        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
71
3.20k
    }
72
16.0k
    return ret;
73
16.0k
}
74
75
static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
76
0
{
77
0
    const ECX_KEY *akey = a->pkey.ecx;
78
0
    const ECX_KEY *bkey = b->pkey.ecx;
79
80
0
    if (akey == NULL || bkey == NULL)
81
0
        return -2;
82
83
0
    return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
84
0
}
85
86
static int ecx_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
87
    OSSL_LIB_CTX *libctx, const char *propq)
88
84
{
89
84
    int ret = 0;
90
84
    ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq);
91
92
84
    if (ecx != NULL) {
93
22
        ret = 1;
94
22
        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
95
22
    }
96
97
84
    return ret;
98
84
}
99
100
static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
101
17
{
102
17
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
103
17
    ASN1_OCTET_STRING oct;
104
17
    unsigned char *penc = NULL;
105
17
    int penclen;
106
107
17
    if (ecxkey == NULL || ecxkey->privkey == NULL) {
108
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
109
0
        return 0;
110
0
    }
111
112
17
    oct.data = ecxkey->privkey;
113
17
    oct.length = KEYLEN(pkey);
114
17
    oct.flags = 0;
115
116
17
    penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
117
17
    if (penclen < 0) {
118
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
119
0
        return 0;
120
0
    }
121
122
17
    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
123
17
            V_ASN1_UNDEF, NULL, penc, penclen)) {
124
0
        OPENSSL_clear_free(penc, penclen);
125
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
126
0
        return 0;
127
0
    }
128
129
17
    return 1;
130
17
}
131
132
static int ecx_size(const EVP_PKEY *pkey)
133
0
{
134
0
    return KEYLEN(pkey);
135
0
}
136
137
static int ecx_bits(const EVP_PKEY *pkey)
138
0
{
139
0
    if (IS25519(pkey->ameth->pkey_id)) {
140
0
        return X25519_BITS;
141
0
    } else if (ISX448(pkey->ameth->pkey_id)) {
142
0
        return X448_BITS;
143
0
    } else {
144
0
        return ED448_BITS;
145
0
    }
146
0
}
147
148
static int ecx_security_bits(const EVP_PKEY *pkey)
149
0
{
150
0
    if (IS25519(pkey->ameth->pkey_id)) {
151
0
        return X25519_SECURITY_BITS;
152
0
    } else {
153
0
        return X448_SECURITY_BITS;
154
0
    }
155
0
}
156
157
static void ecx_free(EVP_PKEY *pkey)
158
16.1k
{
159
16.1k
    ossl_ecx_key_free(pkey->pkey.ecx);
160
16.1k
}
161
162
/* "parameters" are always equal */
163
static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
164
0
{
165
0
    return 1;
166
0
}
167
168
static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
169
    ASN1_PCTX *ctx, ecx_key_op_t op)
170
17
{
171
17
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
172
17
    const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
173
174
17
    if (op == KEY_OP_PRIVATE) {
175
17
        if (ecxkey == NULL || ecxkey->privkey == NULL) {
176
0
            if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
177
0
                return 0;
178
0
            return 1;
179
0
        }
180
17
        if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
181
0
            return 0;
182
17
        if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
183
0
            return 0;
184
17
        if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
185
17
                indent + 4)
186
17
            == 0)
187
0
            return 0;
188
17
    } else {
189
0
        if (ecxkey == NULL) {
190
0
            if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
191
0
                return 0;
192
0
            return 1;
193
0
        }
194
0
        if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
195
0
            return 0;
196
0
    }
197
17
    if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
198
0
        return 0;
199
200
17
    if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
201
17
            indent + 4)
202
17
        == 0)
203
0
        return 0;
204
17
    return 1;
205
17
}
206
207
static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
208
    ASN1_PCTX *ctx)
209
17
{
210
17
    return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
211
17
}
212
213
static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
214
    ASN1_PCTX *ctx)
215
0
{
216
0
    return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
217
0
}
218
219
static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
220
0
{
221
0
    switch (op) {
222
223
0
    case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: {
224
0
        ECX_KEY *ecx = ossl_ecx_key_op(NULL, arg2, arg1, pkey->ameth->pkey_id,
225
0
            KEY_OP_PUBLIC, NULL, NULL);
226
227
0
        if (ecx != NULL) {
228
0
            EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
229
0
            return 1;
230
0
        }
231
0
        return 0;
232
0
    }
233
0
    case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
234
0
        if (pkey->pkey.ecx != NULL) {
235
0
            unsigned char **ppt = arg2;
236
237
0
            *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
238
0
            if (*ppt != NULL)
239
0
                return KEYLEN(pkey);
240
0
        }
241
0
        return 0;
242
243
0
    default:
244
0
        return -2;
245
0
    }
246
0
}
247
248
static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
249
0
{
250
0
    switch (op) {
251
0
    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
252
        /* We currently only support Pure EdDSA which takes no digest */
253
0
        *(int *)arg2 = NID_undef;
254
0
        return 2;
255
256
0
    default:
257
0
        return -2;
258
0
    }
259
0
}
260
261
static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
262
    size_t len)
263
0
{
264
0
    OSSL_LIB_CTX *libctx = NULL;
265
0
    ECX_KEY *ecx = NULL;
266
267
0
    if (pkey->keymgmt != NULL)
268
0
        libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
269
270
0
    ecx = ossl_ecx_key_op(NULL, priv, len, pkey->ameth->pkey_id,
271
0
        KEY_OP_PRIVATE, libctx, NULL);
272
273
0
    if (ecx != NULL) {
274
0
        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
275
0
        return 1;
276
0
    }
277
0
    return 0;
278
0
}
279
280
static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
281
0
{
282
0
    OSSL_LIB_CTX *libctx = NULL;
283
0
    ECX_KEY *ecx = NULL;
284
285
0
    if (pkey->keymgmt != NULL)
286
0
        libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
287
288
0
    ecx = ossl_ecx_key_op(NULL, pub, len, pkey->ameth->pkey_id,
289
0
        KEY_OP_PUBLIC, libctx, NULL);
290
291
0
    if (ecx != NULL) {
292
0
        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
293
0
        return 1;
294
0
    }
295
0
    return 0;
296
0
}
297
298
static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
299
    size_t *len)
300
0
{
301
0
    const ECX_KEY *key = pkey->pkey.ecx;
302
303
0
    if (priv == NULL) {
304
0
        *len = KEYLENID(pkey->ameth->pkey_id);
305
0
        return 1;
306
0
    }
307
308
0
    if (key == NULL
309
0
        || key->privkey == NULL
310
0
        || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
311
0
        return 0;
312
313
0
    *len = KEYLENID(pkey->ameth->pkey_id);
314
0
    memcpy(priv, key->privkey, *len);
315
316
0
    return 1;
317
0
}
318
319
static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
320
    size_t *len)
321
0
{
322
0
    const ECX_KEY *key = pkey->pkey.ecx;
323
324
0
    if (pub == NULL) {
325
0
        *len = KEYLENID(pkey->ameth->pkey_id);
326
0
        return 1;
327
0
    }
328
329
0
    if (key == NULL
330
0
        || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
331
0
        return 0;
332
333
0
    *len = KEYLENID(pkey->ameth->pkey_id);
334
0
    memcpy(pub, key->pubkey, *len);
335
336
0
    return 1;
337
0
}
338
339
static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey)
340
0
{
341
    /*
342
     * We provide no mechanism to "update" an ECX key once it has been set,
343
     * therefore we do not have to maintain a dirty count.
344
     */
345
0
    return 1;
346
0
}
347
348
static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
349
    OSSL_FUNC_keymgmt_import_fn *importer,
350
    OSSL_LIB_CTX *libctx, const char *propq)
351
0
{
352
0
    const ECX_KEY *key = from->pkey.ecx;
353
0
    OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
354
0
    OSSL_PARAM *params = NULL;
355
0
    int selection = 0;
356
0
    int rv = 0;
357
358
0
    if (tmpl == NULL)
359
0
        return 0;
360
361
    /* A key must at least have a public part */
362
0
    if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
363
0
            key->pubkey, key->keylen))
364
0
        goto err;
365
0
    selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
366
367
0
    if (key->privkey != NULL) {
368
0
        if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
369
0
                OSSL_PKEY_PARAM_PRIV_KEY,
370
0
                key->privkey, key->keylen))
371
0
            goto err;
372
0
        selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
373
0
    }
374
375
0
    params = OSSL_PARAM_BLD_to_param(tmpl);
376
377
    /* We export, the provider imports */
378
0
    rv = importer(to_keydata, selection, params);
379
380
0
err:
381
0
    OSSL_PARAM_BLD_free(tmpl);
382
0
    OSSL_PARAM_free(params);
383
0
    return rv;
384
0
}
385
386
static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
387
    int keytype)
388
0
{
389
0
    EVP_PKEY_CTX *pctx = vpctx;
390
0
    EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
391
0
    ECX_KEY *ecx = ossl_ecx_key_new(pctx->libctx, KEYNID2TYPE(keytype), 0,
392
0
        pctx->propquery);
393
394
0
    if (ecx == NULL) {
395
0
        ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
396
0
        return 0;
397
0
    }
398
399
0
    if (!ossl_ecx_key_fromdata(ecx, params, 1)
400
0
        || !EVP_PKEY_assign(pkey, keytype, ecx)) {
401
0
        ossl_ecx_key_free(ecx);
402
0
        return 0;
403
0
    }
404
0
    return 1;
405
0
}
406
407
static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
408
0
{
409
0
    ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL;
410
0
    int ret;
411
412
0
    if (ecx != NULL) {
413
0
        dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL);
414
0
        if (dupkey == NULL)
415
0
            return 0;
416
0
    }
417
418
0
    ret = EVP_PKEY_assign(to, from->type, dupkey);
419
0
    if (!ret)
420
0
        ossl_ecx_key_free(dupkey);
421
0
    return ret;
422
0
}
423
424
static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
425
0
{
426
0
    return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
427
0
}
428
429
const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = {
430
    EVP_PKEY_X25519,
431
    EVP_PKEY_X25519,
432
    0,
433
    "X25519",
434
    "OpenSSL X25519 algorithm",
435
436
    ecx_pub_decode,
437
    ecx_pub_encode,
438
    ecx_pub_cmp,
439
    ecx_pub_print,
440
441
    NULL,
442
    ecx_priv_encode,
443
    ecx_priv_print,
444
445
    ecx_size,
446
    ecx_bits,
447
    ecx_security_bits,
448
449
    0, 0, 0, 0,
450
    ecx_cmp_parameters,
451
    0, 0,
452
453
    ecx_free,
454
    ecx_ctrl,
455
    NULL,
456
    NULL,
457
458
    NULL,
459
    NULL,
460
    NULL,
461
462
    NULL,
463
    NULL,
464
    NULL,
465
466
    ecx_set_priv_key,
467
    ecx_set_pub_key,
468
    ecx_get_priv_key,
469
    ecx_get_pub_key,
470
    ecx_pkey_dirty_cnt,
471
    ecx_pkey_export_to,
472
    x25519_import_from,
473
    ecx_pkey_copy,
474
475
    ecx_priv_decode_ex
476
};
477
478
static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
479
0
{
480
0
    return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
481
0
}
482
483
const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = {
484
    EVP_PKEY_X448,
485
    EVP_PKEY_X448,
486
    0,
487
    "X448",
488
    "OpenSSL X448 algorithm",
489
490
    ecx_pub_decode,
491
    ecx_pub_encode,
492
    ecx_pub_cmp,
493
    ecx_pub_print,
494
495
    NULL,
496
    ecx_priv_encode,
497
    ecx_priv_print,
498
499
    ecx_size,
500
    ecx_bits,
501
    ecx_security_bits,
502
503
    0, 0, 0, 0,
504
    ecx_cmp_parameters,
505
    0, 0,
506
507
    ecx_free,
508
    ecx_ctrl,
509
    NULL,
510
    NULL,
511
512
    NULL,
513
    NULL,
514
    NULL,
515
516
    NULL,
517
    NULL,
518
    NULL,
519
520
    ecx_set_priv_key,
521
    ecx_set_pub_key,
522
    ecx_get_priv_key,
523
    ecx_get_pub_key,
524
    ecx_pkey_dirty_cnt,
525
    ecx_pkey_export_to,
526
    x448_import_from,
527
    ecx_pkey_copy,
528
529
    ecx_priv_decode_ex
530
};
531
532
static int ecd_size25519(const EVP_PKEY *pkey)
533
0
{
534
0
    return ED25519_SIGSIZE;
535
0
}
536
537
static int ecd_size448(const EVP_PKEY *pkey)
538
0
{
539
0
    return ED448_SIGSIZE;
540
0
}
541
542
static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
543
    const void *asn, const X509_ALGOR *sigalg,
544
    const ASN1_BIT_STRING *str, EVP_PKEY *pkey)
545
0
{
546
0
    const ASN1_OBJECT *obj;
547
0
    int ptype;
548
0
    int nid;
549
550
    /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
551
0
    X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
552
0
    nid = OBJ_obj2nid(obj);
553
0
    if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
554
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
555
0
        return 0;
556
0
    }
557
558
0
    if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
559
0
        return 0;
560
561
0
    return 2;
562
0
}
563
564
static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
565
    const void *asn,
566
    X509_ALGOR *alg1, X509_ALGOR *alg2,
567
    ASN1_BIT_STRING *str)
568
0
{
569
    /* Set algorithms identifiers */
570
0
    X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
571
0
    if (alg2)
572
0
        X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
573
    /* Algorithm identifiers set: carry on as normal */
574
0
    return 3;
575
0
}
576
577
static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
578
    const ASN1_STRING *sig)
579
107
{
580
107
    X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
581
107
        X509_SIG_INFO_TLS);
582
107
    return 1;
583
107
}
584
585
static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
586
    const void *asn,
587
    X509_ALGOR *alg1, X509_ALGOR *alg2,
588
    ASN1_BIT_STRING *str)
589
0
{
590
    /* Set algorithm identifier */
591
0
    X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
592
0
    if (alg2 != NULL)
593
0
        X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
594
    /* Algorithm identifier set: carry on as normal */
595
0
    return 3;
596
0
}
597
598
static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
599
    const ASN1_STRING *sig)
600
31
{
601
31
    X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
602
31
        X509_SIG_INFO_TLS);
603
31
    return 1;
604
31
}
605
606
static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
607
0
{
608
0
    return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
609
0
}
610
611
const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
612
    EVP_PKEY_ED25519,
613
    EVP_PKEY_ED25519,
614
    0,
615
    "ED25519",
616
    "OpenSSL ED25519 algorithm",
617
618
    ecx_pub_decode,
619
    ecx_pub_encode,
620
    ecx_pub_cmp,
621
    ecx_pub_print,
622
623
    NULL,
624
    ecx_priv_encode,
625
    ecx_priv_print,
626
627
    ecd_size25519,
628
    ecx_bits,
629
    ecx_security_bits,
630
631
    0, 0, 0, 0,
632
    ecx_cmp_parameters,
633
    0, 0,
634
635
    ecx_free,
636
    ecd_ctrl,
637
    NULL,
638
    NULL,
639
    ecd_item_verify,
640
    ecd_item_sign25519,
641
    ecd_sig_info_set25519,
642
643
    NULL,
644
    NULL,
645
    NULL,
646
647
    ecx_set_priv_key,
648
    ecx_set_pub_key,
649
    ecx_get_priv_key,
650
    ecx_get_pub_key,
651
    ecx_pkey_dirty_cnt,
652
    ecx_pkey_export_to,
653
    ed25519_import_from,
654
    ecx_pkey_copy,
655
656
    ecx_priv_decode_ex
657
};
658
659
static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
660
0
{
661
0
    return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
662
0
}
663
664
const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
665
    EVP_PKEY_ED448,
666
    EVP_PKEY_ED448,
667
    0,
668
    "ED448",
669
    "OpenSSL ED448 algorithm",
670
671
    ecx_pub_decode,
672
    ecx_pub_encode,
673
    ecx_pub_cmp,
674
    ecx_pub_print,
675
676
    NULL,
677
    ecx_priv_encode,
678
    ecx_priv_print,
679
680
    ecd_size448,
681
    ecx_bits,
682
    ecx_security_bits,
683
684
    0, 0, 0, 0,
685
    ecx_cmp_parameters,
686
    0, 0,
687
688
    ecx_free,
689
    ecd_ctrl,
690
    NULL,
691
    NULL,
692
    ecd_item_verify,
693
    ecd_item_sign448,
694
    ecd_sig_info_set448,
695
696
    NULL,
697
    NULL,
698
    NULL,
699
700
    ecx_set_priv_key,
701
    ecx_set_pub_key,
702
    ecx_get_priv_key,
703
    ecx_get_pub_key,
704
    ecx_pkey_dirty_cnt,
705
    ecx_pkey_export_to,
706
    ed448_import_from,
707
    ecx_pkey_copy,
708
709
    ecx_priv_decode_ex
710
};
711
712
static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
713
0
{
714
0
    ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
715
0
        KEY_OP_KEYGEN, NULL, NULL);
716
717
0
    if (ecx != NULL) {
718
0
        EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
719
0
        return 1;
720
0
    }
721
0
    return 0;
722
0
}
723
724
static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
725
    size_t *keylen,
726
    const unsigned char **privkey,
727
    const unsigned char **pubkey)
728
0
{
729
0
    const ECX_KEY *ecxkey, *peerkey;
730
731
0
    if (ctx->pkey == NULL || ctx->peerkey == NULL) {
732
0
        ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
733
0
        return 0;
734
0
    }
735
0
    ecxkey = evp_pkey_get_legacy(ctx->pkey);
736
0
    peerkey = evp_pkey_get_legacy(ctx->peerkey);
737
0
    if (ecxkey == NULL || ecxkey->privkey == NULL) {
738
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
739
0
        return 0;
740
0
    }
741
0
    if (peerkey == NULL) {
742
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
743
0
        return 0;
744
0
    }
745
0
    *privkey = ecxkey->privkey;
746
0
    *pubkey = peerkey->pubkey;
747
748
0
    return 1;
749
0
}
750
751
static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
752
    size_t *keylen)
753
0
{
754
0
    const unsigned char *privkey, *pubkey;
755
756
0
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
757
0
        || (key != NULL
758
0
            && ossl_x25519(key, privkey, pubkey) == 0))
759
0
        return 0;
760
0
    *keylen = X25519_KEYLEN;
761
0
    return 1;
762
0
}
763
764
static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
765
    size_t *keylen)
766
0
{
767
0
    const unsigned char *privkey, *pubkey;
768
769
0
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
770
0
        || (key != NULL
771
0
            && ossl_x448(key, privkey, pubkey) == 0))
772
0
        return 0;
773
0
    *keylen = X448_KEYLEN;
774
0
    return 1;
775
0
}
776
777
static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
778
0
{
779
    /* Only need to handle peer key for derivation */
780
0
    if (type == EVP_PKEY_CTRL_PEER_KEY)
781
0
        return 1;
782
0
    return -2;
783
0
}
784
785
static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
786
    EVP_PKEY_X25519,
787
    0, 0, 0, 0, 0, 0, 0,
788
    pkey_ecx_keygen,
789
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
790
    pkey_ecx_derive25519,
791
    pkey_ecx_ctrl,
792
    0
793
};
794
795
static const EVP_PKEY_METHOD ecx448_pkey_meth = {
796
    EVP_PKEY_X448,
797
    0, 0, 0, 0, 0, 0, 0,
798
    pkey_ecx_keygen,
799
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
800
    pkey_ecx_derive448,
801
    pkey_ecx_ctrl,
802
    0
803
};
804
805
static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
806
    size_t *siglen, const unsigned char *tbs,
807
    size_t tbslen)
808
0
{
809
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
810
811
0
    if (edkey == NULL) {
812
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
813
0
        return 0;
814
0
    }
815
816
0
    if (sig == NULL) {
817
0
        *siglen = ED25519_SIGSIZE;
818
0
        return 1;
819
0
    }
820
0
    if (*siglen < ED25519_SIGSIZE) {
821
0
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
822
0
        return 0;
823
0
    }
824
825
0
    if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
826
0
            NULL)
827
0
        == 0)
828
0
        return 0;
829
0
    *siglen = ED25519_SIGSIZE;
830
0
    return 1;
831
0
}
832
833
static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
834
    size_t *siglen, const unsigned char *tbs,
835
    size_t tbslen)
836
0
{
837
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
838
839
0
    if (edkey == NULL) {
840
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
841
0
        return 0;
842
0
    }
843
844
0
    if (sig == NULL) {
845
0
        *siglen = ED448_SIGSIZE;
846
0
        return 1;
847
0
    }
848
0
    if (*siglen < ED448_SIGSIZE) {
849
0
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
850
0
        return 0;
851
0
    }
852
853
0
    if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
854
0
            edkey->privkey, NULL, 0, edkey->propq)
855
0
        == 0)
856
0
        return 0;
857
0
    *siglen = ED448_SIGSIZE;
858
0
    return 1;
859
0
}
860
861
static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
862
    size_t siglen, const unsigned char *tbs,
863
    size_t tbslen)
864
0
{
865
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
866
867
0
    if (edkey == NULL) {
868
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
869
0
        return 0;
870
0
    }
871
872
0
    if (siglen != ED25519_SIGSIZE)
873
0
        return 0;
874
875
0
    return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
876
0
        edkey->libctx, edkey->propq);
877
0
}
878
879
static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
880
    size_t siglen, const unsigned char *tbs,
881
    size_t tbslen)
882
0
{
883
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
884
885
0
    if (edkey == NULL) {
886
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
887
0
        return 0;
888
0
    }
889
890
0
    if (siglen != ED448_SIGSIZE)
891
0
        return 0;
892
893
0
    return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
894
0
        NULL, 0, edkey->propq);
895
0
}
896
897
static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
898
0
{
899
0
    switch (type) {
900
0
    case EVP_PKEY_CTRL_MD:
901
        /* Only NULL allowed as digest */
902
0
        if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
903
0
            return 1;
904
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
905
0
        return 0;
906
907
0
    case EVP_PKEY_CTRL_DIGESTINIT:
908
0
        return 1;
909
0
    }
910
0
    return -2;
911
0
}
912
913
static const EVP_PKEY_METHOD ed25519_pkey_meth = {
914
    EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
915
    0, 0, 0, 0, 0, 0,
916
    pkey_ecx_keygen,
917
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
918
    pkey_ecd_ctrl,
919
    0,
920
    pkey_ecd_digestsign25519,
921
    pkey_ecd_digestverify25519
922
};
923
924
static const EVP_PKEY_METHOD ed448_pkey_meth = {
925
    EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
926
    0, 0, 0, 0, 0, 0,
927
    pkey_ecx_keygen,
928
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
929
    pkey_ecd_ctrl,
930
    0,
931
    pkey_ecd_digestsign448,
932
    pkey_ecd_digestverify448
933
};
934
935
#ifdef S390X_EC_ASM
936
#include "s390x_arch.h"
937
938
static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
939
{
940
    static const unsigned char generator[] = {
941
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
942
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
943
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
944
    };
945
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
946
        ctx->propquery);
947
    unsigned char *privkey = NULL, *pubkey;
948
949
    if (key == NULL) {
950
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
951
        goto err;
952
    }
953
954
    pubkey = key->pubkey;
955
956
    privkey = ossl_ecx_key_allocate_privkey(key);
957
    if (privkey == NULL) {
958
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
959
        goto err;
960
    }
961
962
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
963
        goto err;
964
965
    privkey[0] &= 248;
966
    privkey[31] &= 127;
967
    privkey[31] |= 64;
968
969
    if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
970
        goto err;
971
972
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
973
    return 1;
974
err:
975
    ossl_ecx_key_free(key);
976
    return 0;
977
}
978
979
static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
980
{
981
    static const unsigned char generator[] = {
982
        0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
983
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
984
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
985
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
986
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
987
    };
988
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
989
        ctx->propquery);
990
    unsigned char *privkey = NULL, *pubkey;
991
992
    if (key == NULL) {
993
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
994
        goto err;
995
    }
996
997
    pubkey = key->pubkey;
998
999
    privkey = ossl_ecx_key_allocate_privkey(key);
1000
    if (privkey == NULL) {
1001
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1002
        goto err;
1003
    }
1004
1005
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1006
        goto err;
1007
1008
    privkey[0] &= 252;
1009
    privkey[55] |= 128;
1010
1011
    if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1012
        goto err;
1013
1014
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1015
    return 1;
1016
err:
1017
    ossl_ecx_key_free(key);
1018
    return 0;
1019
}
1020
1021
static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1022
{
1023
    static const unsigned char generator_x[] = {
1024
        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1025
        0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1026
        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1027
    };
1028
    static const unsigned char generator_y[] = {
1029
        0x58,
1030
        0x66,
1031
        0x66,
1032
        0x66,
1033
        0x66,
1034
        0x66,
1035
        0x66,
1036
        0x66,
1037
        0x66,
1038
        0x66,
1039
        0x66,
1040
        0x66,
1041
        0x66,
1042
        0x66,
1043
        0x66,
1044
        0x66,
1045
        0x66,
1046
        0x66,
1047
        0x66,
1048
        0x66,
1049
        0x66,
1050
        0x66,
1051
        0x66,
1052
        0x66,
1053
        0x66,
1054
        0x66,
1055
        0x66,
1056
        0x66,
1057
        0x66,
1058
        0x66,
1059
        0x66,
1060
        0x66,
1061
    };
1062
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1063
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1064
        ctx->propquery);
1065
    unsigned char *privkey = NULL, *pubkey;
1066
    unsigned int sz;
1067
    EVP_MD *md = NULL;
1068
    int rv;
1069
1070
    if (key == NULL) {
1071
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1072
        goto err;
1073
    }
1074
1075
    pubkey = key->pubkey;
1076
1077
    privkey = ossl_ecx_key_allocate_privkey(key);
1078
    if (privkey == NULL) {
1079
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1080
        goto err;
1081
    }
1082
1083
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1084
        goto err;
1085
1086
    md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1087
    if (md == NULL)
1088
        goto err;
1089
1090
    rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1091
    EVP_MD_free(md);
1092
    if (!rv)
1093
        goto err;
1094
1095
    buff[0] &= 248;
1096
    buff[31] &= 63;
1097
    buff[31] |= 64;
1098
1099
    if (s390x_ed25519_mul(x_dst, pubkey,
1100
            generator_x, generator_y, buff)
1101
        != 1)
1102
        goto err;
1103
1104
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1105
1106
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1107
    return 1;
1108
err:
1109
    ossl_ecx_key_free(key);
1110
    return 0;
1111
}
1112
1113
static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1114
{
1115
    static const unsigned char generator_x[] = {
1116
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1117
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1118
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1119
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1120
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1121
    };
1122
    static const unsigned char generator_y[] = {
1123
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1124
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1125
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1126
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1127
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1128
    };
1129
    unsigned char x_dst[57], buff[114];
1130
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1131
        ctx->propquery);
1132
    unsigned char *privkey = NULL, *pubkey;
1133
    EVP_MD_CTX *hashctx = NULL;
1134
    EVP_MD *md = NULL;
1135
    int rv;
1136
1137
    if (key == NULL) {
1138
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1139
        goto err;
1140
    }
1141
1142
    pubkey = key->pubkey;
1143
1144
    privkey = ossl_ecx_key_allocate_privkey(key);
1145
    if (privkey == NULL) {
1146
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1147
        goto err;
1148
    }
1149
1150
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1151
        goto err;
1152
1153
    hashctx = EVP_MD_CTX_new();
1154
    if (hashctx == NULL)
1155
        goto err;
1156
1157
    md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1158
    if (md == NULL)
1159
        goto err;
1160
1161
    rv = EVP_DigestInit_ex(hashctx, md, NULL);
1162
    EVP_MD_free(md);
1163
    if (rv != 1)
1164
        goto err;
1165
1166
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1167
        goto err;
1168
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1169
        goto err;
1170
1171
    buff[0] &= -4;
1172
    buff[55] |= 0x80;
1173
    buff[56] = 0;
1174
1175
    if (s390x_ed448_mul(x_dst, pubkey,
1176
            generator_x, generator_y, buff)
1177
        != 1)
1178
        goto err;
1179
1180
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1181
1182
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1183
    EVP_MD_CTX_free(hashctx);
1184
    return 1;
1185
err:
1186
    ossl_ecx_key_free(key);
1187
    EVP_MD_CTX_free(hashctx);
1188
    return 0;
1189
}
1190
1191
static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1192
    size_t *keylen)
1193
{
1194
    const unsigned char *privkey, *pubkey;
1195
1196
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1197
        || (key != NULL
1198
            && s390x_x25519_mul(key, privkey, pubkey) == 0))
1199
        return 0;
1200
    *keylen = X25519_KEYLEN;
1201
    return 1;
1202
}
1203
1204
static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1205
    size_t *keylen)
1206
{
1207
    const unsigned char *privkey, *pubkey;
1208
1209
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1210
        || (key != NULL
1211
            && s390x_x448_mul(key, pubkey, privkey) == 0))
1212
        return 0;
1213
    *keylen = X448_KEYLEN;
1214
    return 1;
1215
}
1216
1217
static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1218
    unsigned char *sig, size_t *siglen,
1219
    const unsigned char *tbs,
1220
    size_t tbslen)
1221
{
1222
    union {
1223
        struct {
1224
            unsigned char sig[64];
1225
            unsigned char priv[32];
1226
        } ed25519;
1227
        unsigned long long buff[512];
1228
    } param;
1229
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1230
    int rc;
1231
1232
    if (edkey == NULL) {
1233
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1234
        return 0;
1235
    }
1236
1237
    if (sig == NULL) {
1238
        *siglen = ED25519_SIGSIZE;
1239
        return 1;
1240
    }
1241
1242
    if (*siglen < ED25519_SIGSIZE) {
1243
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1244
        return 0;
1245
    }
1246
1247
    memset(&param, 0, sizeof(param));
1248
    memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1249
1250
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1251
    OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1252
    if (rc != 0)
1253
        return 0;
1254
1255
    s390x_flip_endian32(sig, param.ed25519.sig);
1256
    s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1257
1258
    *siglen = ED25519_SIGSIZE;
1259
    return 1;
1260
}
1261
1262
static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1263
    unsigned char *sig, size_t *siglen,
1264
    const unsigned char *tbs,
1265
    size_t tbslen)
1266
{
1267
    union {
1268
        struct {
1269
            unsigned char sig[128];
1270
            unsigned char priv[64];
1271
        } ed448;
1272
        unsigned long long buff[512];
1273
    } param;
1274
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1275
    int rc;
1276
1277
    if (edkey == NULL) {
1278
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1279
        return 0;
1280
    }
1281
1282
    if (sig == NULL) {
1283
        *siglen = ED448_SIGSIZE;
1284
        return 1;
1285
    }
1286
1287
    if (*siglen < ED448_SIGSIZE) {
1288
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1289
        return 0;
1290
    }
1291
1292
    memset(&param, 0, sizeof(param));
1293
    memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1294
1295
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1296
    OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1297
    if (rc != 0)
1298
        return 0;
1299
1300
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1301
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1302
    memcpy(sig, param.ed448.sig, 57);
1303
    memcpy(sig + 57, param.ed448.sig + 64, 57);
1304
1305
    *siglen = ED448_SIGSIZE;
1306
    return 1;
1307
}
1308
1309
static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1310
    const unsigned char *sig,
1311
    size_t siglen,
1312
    const unsigned char *tbs,
1313
    size_t tbslen)
1314
{
1315
    union {
1316
        struct {
1317
            unsigned char sig[64];
1318
            unsigned char pub[32];
1319
        } ed25519;
1320
        unsigned long long buff[512];
1321
    } param;
1322
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1323
1324
    if (edkey == NULL) {
1325
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1326
        return 0;
1327
    }
1328
1329
    if (siglen != ED25519_SIGSIZE)
1330
        return 0;
1331
1332
    memset(&param, 0, sizeof(param));
1333
    s390x_flip_endian32(param.ed25519.sig, sig);
1334
    s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1335
    s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1336
1337
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1338
               &param.ed25519, tbs, tbslen)
1339
            == 0
1340
        ? 1
1341
        : 0;
1342
}
1343
1344
static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1345
    const unsigned char *sig,
1346
    size_t siglen,
1347
    const unsigned char *tbs,
1348
    size_t tbslen)
1349
{
1350
    union {
1351
        struct {
1352
            unsigned char sig[128];
1353
            unsigned char pub[64];
1354
        } ed448;
1355
        unsigned long long buff[512];
1356
    } param;
1357
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1358
1359
    if (edkey == NULL) {
1360
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1361
        return 0;
1362
    }
1363
1364
    if (siglen != ED448_SIGSIZE)
1365
        return 0;
1366
1367
    memset(&param, 0, sizeof(param));
1368
    memcpy(param.ed448.sig, sig, 57);
1369
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1370
    memcpy(param.ed448.sig + 64, sig + 57, 57);
1371
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1372
    memcpy(param.ed448.pub, edkey->pubkey, 57);
1373
    s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1374
1375
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1376
               &param.ed448, tbs, tbslen)
1377
            == 0
1378
        ? 1
1379
        : 0;
1380
}
1381
1382
static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1383
    EVP_PKEY_X25519,
1384
    0, 0, 0, 0, 0, 0, 0,
1385
    s390x_pkey_ecx_keygen25519,
1386
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1387
    s390x_pkey_ecx_derive25519,
1388
    pkey_ecx_ctrl,
1389
    0
1390
};
1391
1392
static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1393
    EVP_PKEY_X448,
1394
    0, 0, 0, 0, 0, 0, 0,
1395
    s390x_pkey_ecx_keygen448,
1396
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1397
    s390x_pkey_ecx_derive448,
1398
    pkey_ecx_ctrl,
1399
    0
1400
};
1401
static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1402
    EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1403
    0, 0, 0, 0, 0, 0,
1404
    s390x_pkey_ecd_keygen25519,
1405
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1406
    pkey_ecd_ctrl,
1407
    0,
1408
    s390x_pkey_ecd_digestsign25519,
1409
    s390x_pkey_ecd_digestverify25519
1410
};
1411
1412
static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1413
    EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1414
    0, 0, 0, 0, 0, 0,
1415
    s390x_pkey_ecd_keygen448,
1416
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1417
    pkey_ecd_ctrl,
1418
    0,
1419
    s390x_pkey_ecd_digestsign448,
1420
    s390x_pkey_ecd_digestverify448
1421
};
1422
#endif
1423
1424
const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1425
0
{
1426
#ifdef S390X_EC_ASM
1427
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1428
        return &ecx25519_s390x_pkey_meth;
1429
#endif
1430
0
    return &ecx25519_pkey_meth;
1431
0
}
1432
1433
const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1434
0
{
1435
#ifdef S390X_EC_ASM
1436
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1437
        return &ecx448_s390x_pkey_meth;
1438
#endif
1439
0
    return &ecx448_pkey_meth;
1440
0
}
1441
1442
const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1443
0
{
1444
#ifdef S390X_EC_ASM
1445
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1446
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1447
        && OPENSSL_s390xcap_P.kdsa[0]
1448
            & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1449
        return &ed25519_s390x_pkey_meth;
1450
#endif
1451
0
    return &ed25519_pkey_meth;
1452
0
}
1453
1454
const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1455
0
{
1456
#ifdef S390X_EC_ASM
1457
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1458
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1459
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1460
        return &ed448_s390x_pkey_meth;
1461
#endif
1462
0
    return &ed448_pkey_meth;
1463
0
}