Coverage Report

Created: 2025-08-24 06:20

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