Coverage Report

Created: 2025-06-13 06:58

/src/openssl30/crypto/ec/ecx_meth.c
Line
Count
Source (jump to first uncovered line)
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
25.6k
{
58
25.6k
    const unsigned char *p;
59
25.6k
    int pklen;
60
25.6k
    X509_ALGOR *palg;
61
25.6k
    ECX_KEY *ecx;
62
25.6k
    int ret = 0;
63
64
25.6k
    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
65
0
        return 0;
66
25.6k
    ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id,
67
25.6k
                          KEY_OP_PUBLIC, NULL, NULL);
68
25.6k
    if (ecx != NULL) {
69
3.70k
        ret = 1;
70
3.70k
        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
71
3.70k
    }
72
25.6k
    return ret;
73
25.6k
}
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
66
{
89
66
    int ret = 0;
90
66
    ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq);
91
92
66
    if (ecx != NULL) {
93
18
        ret = 1;
94
18
        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
95
18
    }
96
97
66
    return ret;
98
66
}
99
100
static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
101
14
{
102
14
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
103
14
    ASN1_OCTET_STRING oct;
104
14
    unsigned char *penc = NULL;
105
14
    int penclen;
106
107
14
    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
14
    oct.data = ecxkey->privkey;
113
14
    oct.length = KEYLEN(pkey);
114
14
    oct.flags = 0;
115
116
14
    penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
117
14
    if (penclen < 0) {
118
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
119
0
        return 0;
120
0
    }
121
122
14
    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
123
14
                         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
14
    return 1;
130
14
}
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
25.7k
{
159
25.7k
    ossl_ecx_key_free(pkey->pkey.ecx);
160
25.7k
}
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
14
{
171
14
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
172
14
    const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
173
174
14
    if (op == KEY_OP_PRIVATE) {
175
14
        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
14
        if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
181
0
            return 0;
182
14
        if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
183
0
            return 0;
184
14
        if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
185
14
                           indent + 4) == 0)
186
0
            return 0;
187
14
    } else {
188
0
        if (ecxkey == NULL) {
189
0
            if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
190
0
                return 0;
191
0
            return 1;
192
0
        }
193
0
        if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
194
0
            return 0;
195
0
    }
196
14
    if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
197
0
        return 0;
198
199
14
    if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
200
14
                       indent + 4) == 0)
201
0
        return 0;
202
14
    return 1;
203
14
}
204
205
static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
206
                          ASN1_PCTX *ctx)
207
14
{
208
14
    return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
209
14
}
210
211
static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
212
                         ASN1_PCTX *ctx)
213
0
{
214
0
    return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
215
0
}
216
217
static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
218
0
{
219
0
    switch (op) {
220
221
0
    case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: {
222
0
        ECX_KEY *ecx = ossl_ecx_key_op(NULL, arg2, arg1, pkey->ameth->pkey_id,
223
0
                                       KEY_OP_PUBLIC, NULL, NULL);
224
225
0
        if (ecx != NULL) {
226
0
            EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
227
0
            return 1;
228
0
        }
229
0
        return 0;
230
0
    }
231
0
    case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
232
0
        if (pkey->pkey.ecx != NULL) {
233
0
            unsigned char **ppt = arg2;
234
235
0
            *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
236
0
            if (*ppt != NULL)
237
0
                return KEYLEN(pkey);
238
0
        }
239
0
        return 0;
240
241
0
    default:
242
0
        return -2;
243
244
0
    }
245
0
}
246
247
static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
248
0
{
249
0
    switch (op) {
250
0
    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
251
        /* We currently only support Pure EdDSA which takes no digest */
252
0
        *(int *)arg2 = NID_undef;
253
0
        return 2;
254
255
0
    default:
256
0
        return -2;
257
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
90
{
580
90
    X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
581
90
                      X509_SIG_INFO_TLS);
582
90
    return 1;
583
90
}
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
27
{
601
27
    X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
602
27
                      X509_SIG_INFO_TLS);
603
27
    return 1;
604
27
}
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) == 0)
827
0
        return 0;
828
0
    *siglen = ED25519_SIGSIZE;
829
0
    return 1;
830
0
}
831
832
static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
833
                                  size_t *siglen, const unsigned char *tbs,
834
                                  size_t tbslen)
835
0
{
836
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
837
838
0
    if (edkey == NULL) {
839
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
840
0
        return 0;
841
0
    }
842
843
0
    if (sig == NULL) {
844
0
        *siglen = ED448_SIGSIZE;
845
0
        return 1;
846
0
    }
847
0
    if (*siglen < ED448_SIGSIZE) {
848
0
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
849
0
        return 0;
850
0
    }
851
852
0
    if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
853
0
                        edkey->privkey, NULL, 0, edkey->propq) == 0)
854
0
        return 0;
855
0
    *siglen = ED448_SIGSIZE;
856
0
    return 1;
857
0
}
858
859
static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
860
                                      size_t siglen, const unsigned char *tbs,
861
                                      size_t tbslen)
862
0
{
863
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
864
865
0
    if (edkey == NULL) {
866
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
867
0
        return 0;
868
0
    }
869
870
0
    if (siglen != ED25519_SIGSIZE)
871
0
        return 0;
872
873
0
    return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
874
0
                               edkey->libctx, edkey->propq);
875
0
}
876
877
static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
878
                                    size_t siglen, const unsigned char *tbs,
879
                                    size_t tbslen)
880
0
{
881
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
882
883
0
    if (edkey == NULL) {
884
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
885
0
        return 0;
886
0
    }
887
888
0
    if (siglen != ED448_SIGSIZE)
889
0
        return 0;
890
891
0
    return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
892
0
                             NULL, 0, edkey->propq);
893
0
}
894
895
static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
896
0
{
897
0
    switch (type) {
898
0
    case EVP_PKEY_CTRL_MD:
899
        /* Only NULL allowed as digest */
900
0
        if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
901
0
            return 1;
902
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
903
0
        return 0;
904
905
0
    case EVP_PKEY_CTRL_DIGESTINIT:
906
0
        return 1;
907
0
    }
908
0
    return -2;
909
0
}
910
911
static const EVP_PKEY_METHOD ed25519_pkey_meth = {
912
    EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
913
    0, 0, 0, 0, 0, 0,
914
    pkey_ecx_keygen,
915
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
916
    pkey_ecd_ctrl,
917
    0,
918
    pkey_ecd_digestsign25519,
919
    pkey_ecd_digestverify25519
920
};
921
922
static const EVP_PKEY_METHOD ed448_pkey_meth = {
923
    EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
924
    0, 0, 0, 0, 0, 0,
925
    pkey_ecx_keygen,
926
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
927
    pkey_ecd_ctrl,
928
    0,
929
    pkey_ecd_digestsign448,
930
    pkey_ecd_digestverify448
931
};
932
933
#ifdef S390X_EC_ASM
934
# include "s390x_arch.h"
935
936
static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
937
{
938
    static const unsigned char generator[] = {
939
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
940
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
941
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
942
    };
943
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
944
                                    ctx->propquery);
945
    unsigned char *privkey = NULL, *pubkey;
946
947
    if (key == NULL) {
948
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
949
        goto err;
950
    }
951
952
    pubkey = key->pubkey;
953
954
    privkey = ossl_ecx_key_allocate_privkey(key);
955
    if (privkey == NULL) {
956
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
957
        goto err;
958
    }
959
960
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
961
        goto err;
962
963
    privkey[0] &= 248;
964
    privkey[31] &= 127;
965
    privkey[31] |= 64;
966
967
    if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
968
        goto err;
969
970
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
971
    return 1;
972
 err:
973
    ossl_ecx_key_free(key);
974
    return 0;
975
}
976
977
static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
978
{
979
    static const unsigned char generator[] = {
980
        0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
981
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
982
        0x00, 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
985
    };
986
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
987
                                    ctx->propquery);
988
    unsigned char *privkey = NULL, *pubkey;
989
990
    if (key == NULL) {
991
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
992
        goto err;
993
    }
994
995
    pubkey = key->pubkey;
996
997
    privkey = ossl_ecx_key_allocate_privkey(key);
998
    if (privkey == NULL) {
999
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1000
        goto err;
1001
    }
1002
1003
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1004
        goto err;
1005
1006
    privkey[0] &= 252;
1007
    privkey[55] |= 128;
1008
1009
    if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1010
        goto err;
1011
1012
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1013
    return 1;
1014
 err:
1015
    ossl_ecx_key_free(key);
1016
    return 0;
1017
}
1018
1019
static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1020
{
1021
    static const unsigned char generator_x[] = {
1022
        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1023
        0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1024
        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1025
    };
1026
    static const unsigned char generator_y[] = {
1027
        0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1028
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1029
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1030
    };
1031
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1032
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1033
                                    ctx->propquery);
1034
    unsigned char *privkey = NULL, *pubkey;
1035
    unsigned int sz;
1036
    EVP_MD *md = NULL;
1037
    int rv;
1038
1039
    if (key == NULL) {
1040
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1041
        goto err;
1042
    }
1043
1044
    pubkey = key->pubkey;
1045
1046
    privkey = ossl_ecx_key_allocate_privkey(key);
1047
    if (privkey == NULL) {
1048
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1049
        goto err;
1050
    }
1051
1052
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1053
        goto err;
1054
1055
    md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1056
    if (md == NULL)
1057
        goto err;
1058
1059
    rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1060
    EVP_MD_free(md);
1061
    if (!rv)
1062
        goto err;
1063
1064
    buff[0] &= 248;
1065
    buff[31] &= 63;
1066
    buff[31] |= 64;
1067
1068
    if (s390x_ed25519_mul(x_dst, pubkey,
1069
                          generator_x, generator_y, buff) != 1)
1070
        goto err;
1071
1072
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1073
1074
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1075
    return 1;
1076
 err:
1077
    ossl_ecx_key_free(key);
1078
    return 0;
1079
}
1080
1081
static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1082
{
1083
    static const unsigned char generator_x[] = {
1084
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1085
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1086
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1087
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1088
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1089
    };
1090
    static const unsigned char generator_y[] = {
1091
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1092
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1093
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1094
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1095
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1096
    };
1097
    unsigned char x_dst[57], buff[114];
1098
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1099
                                    ctx->propquery);
1100
    unsigned char *privkey = NULL, *pubkey;
1101
    EVP_MD_CTX *hashctx = NULL;
1102
    EVP_MD *md = NULL;
1103
    int rv;
1104
1105
    if (key == NULL) {
1106
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1107
        goto err;
1108
    }
1109
1110
    pubkey = key->pubkey;
1111
1112
    privkey = ossl_ecx_key_allocate_privkey(key);
1113
    if (privkey == NULL) {
1114
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1115
        goto err;
1116
    }
1117
1118
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1119
        goto err;
1120
1121
    hashctx = EVP_MD_CTX_new();
1122
    if (hashctx == NULL)
1123
        goto err;
1124
1125
    md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1126
    if (md == NULL)
1127
        goto err;
1128
1129
    rv = EVP_DigestInit_ex(hashctx, md, NULL);
1130
    EVP_MD_free(md);
1131
    if (rv != 1)
1132
        goto err;
1133
1134
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1135
        goto err;
1136
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1137
        goto err;
1138
1139
    buff[0] &= -4;
1140
    buff[55] |= 0x80;
1141
    buff[56] = 0;
1142
1143
    if (s390x_ed448_mul(x_dst, pubkey,
1144
                        generator_x, generator_y, buff) != 1)
1145
        goto err;
1146
1147
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1148
1149
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1150
    EVP_MD_CTX_free(hashctx);
1151
    return 1;
1152
 err:
1153
    ossl_ecx_key_free(key);
1154
    EVP_MD_CTX_free(hashctx);
1155
    return 0;
1156
}
1157
1158
static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1159
                                      size_t *keylen)
1160
{
1161
    const unsigned char *privkey, *pubkey;
1162
1163
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1164
        || (key != NULL
1165
            && s390x_x25519_mul(key, privkey, pubkey) == 0))
1166
        return 0;
1167
    *keylen = X25519_KEYLEN;
1168
    return 1;
1169
}
1170
1171
static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1172
                                      size_t *keylen)
1173
{
1174
    const unsigned char *privkey, *pubkey;
1175
1176
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1177
        || (key != NULL
1178
            && s390x_x448_mul(key, pubkey, privkey) == 0))
1179
        return 0;
1180
    *keylen = X448_KEYLEN;
1181
    return 1;
1182
}
1183
1184
static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1185
                                          unsigned char *sig, size_t *siglen,
1186
                                          const unsigned char *tbs,
1187
                                          size_t tbslen)
1188
{
1189
    union {
1190
        struct {
1191
            unsigned char sig[64];
1192
            unsigned char priv[32];
1193
        } ed25519;
1194
        unsigned long long buff[512];
1195
    } param;
1196
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1197
    int rc;
1198
1199
    if (edkey == NULL) {
1200
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1201
        return 0;
1202
    }
1203
1204
    if (sig == NULL) {
1205
        *siglen = ED25519_SIGSIZE;
1206
        return 1;
1207
    }
1208
1209
    if (*siglen < ED25519_SIGSIZE) {
1210
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1211
        return 0;
1212
    }
1213
1214
    memset(&param, 0, sizeof(param));
1215
    memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1216
1217
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1218
    OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1219
    if (rc != 0)
1220
        return 0;
1221
1222
    s390x_flip_endian32(sig, param.ed25519.sig);
1223
    s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1224
1225
    *siglen = ED25519_SIGSIZE;
1226
    return 1;
1227
}
1228
1229
static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1230
                                        unsigned char *sig, size_t *siglen,
1231
                                        const unsigned char *tbs,
1232
                                        size_t tbslen)
1233
{
1234
    union {
1235
        struct {
1236
            unsigned char sig[128];
1237
            unsigned char priv[64];
1238
        } ed448;
1239
        unsigned long long buff[512];
1240
    } param;
1241
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1242
    int rc;
1243
1244
    if (edkey == NULL) {
1245
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1246
        return 0;
1247
    }
1248
1249
    if (sig == NULL) {
1250
        *siglen = ED448_SIGSIZE;
1251
        return 1;
1252
    }
1253
1254
    if (*siglen < ED448_SIGSIZE) {
1255
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1256
        return 0;
1257
    }
1258
1259
    memset(&param, 0, sizeof(param));
1260
    memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1261
1262
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1263
    OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1264
    if (rc != 0)
1265
        return 0;
1266
1267
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1268
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1269
    memcpy(sig, param.ed448.sig, 57);
1270
    memcpy(sig + 57, param.ed448.sig + 64, 57);
1271
1272
    *siglen = ED448_SIGSIZE;
1273
    return 1;
1274
}
1275
1276
static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1277
                                            const unsigned char *sig,
1278
                                            size_t siglen,
1279
                                            const unsigned char *tbs,
1280
                                            size_t tbslen)
1281
{
1282
    union {
1283
        struct {
1284
            unsigned char sig[64];
1285
            unsigned char pub[32];
1286
        } ed25519;
1287
        unsigned long long buff[512];
1288
    } param;
1289
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1290
1291
    if (edkey == NULL) {
1292
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1293
        return 0;
1294
    }
1295
1296
    if (siglen != ED25519_SIGSIZE)
1297
        return 0;
1298
1299
    memset(&param, 0, sizeof(param));
1300
    s390x_flip_endian32(param.ed25519.sig, sig);
1301
    s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1302
    s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1303
1304
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1305
                      &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1306
}
1307
1308
static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1309
                                          const unsigned char *sig,
1310
                                          size_t siglen,
1311
                                          const unsigned char *tbs,
1312
                                          size_t tbslen)
1313
{
1314
    union {
1315
        struct {
1316
            unsigned char sig[128];
1317
            unsigned char pub[64];
1318
        } ed448;
1319
        unsigned long long buff[512];
1320
    } param;
1321
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1322
1323
    if (edkey == NULL) {
1324
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1325
        return 0;
1326
    }
1327
1328
    if (siglen != ED448_SIGSIZE)
1329
        return 0;
1330
1331
    memset(&param, 0, sizeof(param));
1332
    memcpy(param.ed448.sig, sig, 57);
1333
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1334
    memcpy(param.ed448.sig + 64, sig + 57, 57);
1335
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1336
    memcpy(param.ed448.pub, edkey->pubkey, 57);
1337
    s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1338
1339
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1340
                      &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1341
}
1342
1343
static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1344
    EVP_PKEY_X25519,
1345
    0, 0, 0, 0, 0, 0, 0,
1346
    s390x_pkey_ecx_keygen25519,
1347
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1348
    s390x_pkey_ecx_derive25519,
1349
    pkey_ecx_ctrl,
1350
    0
1351
};
1352
1353
static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1354
    EVP_PKEY_X448,
1355
    0, 0, 0, 0, 0, 0, 0,
1356
    s390x_pkey_ecx_keygen448,
1357
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1358
    s390x_pkey_ecx_derive448,
1359
    pkey_ecx_ctrl,
1360
    0
1361
};
1362
static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1363
    EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1364
    0, 0, 0, 0, 0, 0,
1365
    s390x_pkey_ecd_keygen25519,
1366
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1367
    pkey_ecd_ctrl,
1368
    0,
1369
    s390x_pkey_ecd_digestsign25519,
1370
    s390x_pkey_ecd_digestverify25519
1371
};
1372
1373
static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1374
    EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1375
    0, 0, 0, 0, 0, 0,
1376
    s390x_pkey_ecd_keygen448,
1377
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1378
    pkey_ecd_ctrl,
1379
    0,
1380
    s390x_pkey_ecd_digestsign448,
1381
    s390x_pkey_ecd_digestverify448
1382
};
1383
#endif
1384
1385
const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1386
0
{
1387
#ifdef S390X_EC_ASM
1388
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1389
        return &ecx25519_s390x_pkey_meth;
1390
#endif
1391
0
    return &ecx25519_pkey_meth;
1392
0
}
1393
1394
const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1395
0
{
1396
#ifdef S390X_EC_ASM
1397
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1398
        return &ecx448_s390x_pkey_meth;
1399
#endif
1400
0
    return &ecx448_pkey_meth;
1401
0
}
1402
1403
const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1404
0
{
1405
#ifdef S390X_EC_ASM
1406
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1407
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1408
        && OPENSSL_s390xcap_P.kdsa[0]
1409
            & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1410
        return &ed25519_s390x_pkey_meth;
1411
#endif
1412
0
    return &ed25519_pkey_meth;
1413
0
}
1414
1415
const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1416
0
{
1417
#ifdef S390X_EC_ASM
1418
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1419
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1420
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1421
        return &ed448_s390x_pkey_meth;
1422
#endif
1423
0
    return &ed448_pkey_meth;
1424
0
}