Coverage Report

Created: 2025-06-13 06:57

/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
42
{
56
42
    const unsigned char *p;
57
42
    int pklen;
58
42
    X509_ALGOR *palg;
59
42
    ECX_KEY *ecx;
60
42
    int ret = 0;
61
62
42
    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
63
0
        return 0;
64
42
    ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id,
65
42
                          KEY_OP_PUBLIC, NULL, NULL);
66
42
    if (ecx != NULL) {
67
4
        ret = 1;
68
4
        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
69
4
    }
70
42
    return ret;
71
42
}
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
42
{
157
42
    ossl_ecx_key_free(pkey->pkey.ecx);
158
42
}
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, 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, 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
392
0
    if (ecx == NULL) {
393
0
        ERR_raise(ERR_LIB_DH, ERR_R_EC_LIB);
394
0
        return 0;
395
0
    }
396
397
0
    if (!ossl_ecx_key_fromdata(ecx, params, 1)
398
0
        || !EVP_PKEY_assign(pkey, keytype, ecx)) {
399
0
        ossl_ecx_key_free(ecx);
400
0
        return 0;
401
0
    }
402
0
    return 1;
403
0
}
404
405
static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
406
0
{
407
0
    ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL;
408
0
    int ret;
409
410
0
    if (ecx != NULL) {
411
0
        dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL);
412
0
        if (dupkey == NULL)
413
0
            return 0;
414
0
    }
415
416
0
    ret = EVP_PKEY_assign(to, from->type, dupkey);
417
0
    if (!ret)
418
0
        ossl_ecx_key_free(dupkey);
419
0
    return ret;
420
0
}
421
422
static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
423
0
{
424
0
    return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
425
0
}
426
427
const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = {
428
    EVP_PKEY_X25519,
429
    EVP_PKEY_X25519,
430
    0,
431
    "X25519",
432
    "OpenSSL X25519 algorithm",
433
434
    ecx_pub_decode,
435
    ecx_pub_encode,
436
    ecx_pub_cmp,
437
    ecx_pub_print,
438
439
    NULL,
440
    ecx_priv_encode,
441
    ecx_priv_print,
442
443
    ecx_size,
444
    ecx_bits,
445
    ecx_security_bits,
446
447
    0, 0, 0, 0,
448
    ecx_cmp_parameters,
449
    0, 0,
450
451
    ecx_free,
452
    ecx_ctrl,
453
    NULL,
454
    NULL,
455
456
    NULL,
457
    NULL,
458
    NULL,
459
460
    NULL,
461
    NULL,
462
    NULL,
463
464
    ecx_set_priv_key,
465
    ecx_set_pub_key,
466
    ecx_get_priv_key,
467
    ecx_get_pub_key,
468
    ecx_pkey_dirty_cnt,
469
    ecx_pkey_export_to,
470
    x25519_import_from,
471
    ecx_pkey_copy,
472
473
    ecx_priv_decode_ex
474
};
475
476
static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
477
0
{
478
0
    return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
479
0
}
480
481
const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = {
482
    EVP_PKEY_X448,
483
    EVP_PKEY_X448,
484
    0,
485
    "X448",
486
    "OpenSSL X448 algorithm",
487
488
    ecx_pub_decode,
489
    ecx_pub_encode,
490
    ecx_pub_cmp,
491
    ecx_pub_print,
492
493
    NULL,
494
    ecx_priv_encode,
495
    ecx_priv_print,
496
497
    ecx_size,
498
    ecx_bits,
499
    ecx_security_bits,
500
501
    0, 0, 0, 0,
502
    ecx_cmp_parameters,
503
    0, 0,
504
505
    ecx_free,
506
    ecx_ctrl,
507
    NULL,
508
    NULL,
509
510
    NULL,
511
    NULL,
512
    NULL,
513
514
    NULL,
515
    NULL,
516
    NULL,
517
518
    ecx_set_priv_key,
519
    ecx_set_pub_key,
520
    ecx_get_priv_key,
521
    ecx_get_pub_key,
522
    ecx_pkey_dirty_cnt,
523
    ecx_pkey_export_to,
524
    x448_import_from,
525
    ecx_pkey_copy,
526
527
    ecx_priv_decode_ex
528
};
529
530
static int ecd_size25519(const EVP_PKEY *pkey)
531
0
{
532
0
    return ED25519_SIGSIZE;
533
0
}
534
535
static int ecd_size448(const EVP_PKEY *pkey)
536
0
{
537
0
    return ED448_SIGSIZE;
538
0
}
539
540
static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
541
                           const void *asn, const X509_ALGOR *sigalg,
542
                           const ASN1_BIT_STRING *str, EVP_PKEY *pkey)
543
0
{
544
0
    const ASN1_OBJECT *obj;
545
0
    int ptype;
546
0
    int nid;
547
548
    /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
549
0
    X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
550
0
    nid = OBJ_obj2nid(obj);
551
0
    if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
552
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
553
0
        return 0;
554
0
    }
555
556
0
    if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
557
0
        return 0;
558
559
0
    return 2;
560
0
}
561
562
static int ecd_item_sign(X509_ALGOR *alg1, X509_ALGOR *alg2, int nid)
563
0
{
564
    /* Note that X509_ALGOR_set0(..., ..., V_ASN1_UNDEF, ...) cannot fail */
565
    /* Set algorithms identifiers */
566
0
    (void)X509_ALGOR_set0(alg1, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
567
0
    if (alg2 != NULL)
568
0
        (void)X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
569
    /* Algorithm identifiers set: carry on as normal */
570
0
    return 3;
571
0
}
572
573
static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
574
                              const void *asn,
575
                              X509_ALGOR *alg1, X509_ALGOR *alg2,
576
                              ASN1_BIT_STRING *str)
577
0
{
578
0
    return ecd_item_sign(alg1, alg2, NID_ED25519);
579
0
}
580
581
static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
582
                                 const ASN1_STRING *sig)
583
0
{
584
0
    X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
585
0
                      X509_SIG_INFO_TLS);
586
0
    return 1;
587
0
}
588
589
static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
590
                            const void *asn,
591
                            X509_ALGOR *alg1, X509_ALGOR *alg2,
592
                            ASN1_BIT_STRING *str)
593
0
{
594
0
    return ecd_item_sign(alg1, alg2, NID_ED448);
595
0
}
596
597
static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
598
                               const ASN1_STRING *sig)
599
0
{
600
0
    X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
601
0
                      X509_SIG_INFO_TLS);
602
0
    return 1;
603
0
}
604
605
static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
606
0
{
607
0
    return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
608
0
}
609
610
const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
611
    EVP_PKEY_ED25519,
612
    EVP_PKEY_ED25519,
613
    0,
614
    "ED25519",
615
    "OpenSSL ED25519 algorithm",
616
617
    ecx_pub_decode,
618
    ecx_pub_encode,
619
    ecx_pub_cmp,
620
    ecx_pub_print,
621
622
    NULL,
623
    ecx_priv_encode,
624
    ecx_priv_print,
625
626
    ecd_size25519,
627
    ecx_bits,
628
    ecx_security_bits,
629
630
    0, 0, 0, 0,
631
    ecx_cmp_parameters,
632
    0, 0,
633
634
    ecx_free,
635
    ecd_ctrl,
636
    NULL,
637
    NULL,
638
    ecd_item_verify,
639
    ecd_item_sign25519,
640
    ecd_sig_info_set25519,
641
642
    NULL,
643
    NULL,
644
    NULL,
645
646
    ecx_set_priv_key,
647
    ecx_set_pub_key,
648
    ecx_get_priv_key,
649
    ecx_get_pub_key,
650
    ecx_pkey_dirty_cnt,
651
    ecx_pkey_export_to,
652
    ed25519_import_from,
653
    ecx_pkey_copy,
654
655
    ecx_priv_decode_ex
656
};
657
658
static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
659
0
{
660
0
    return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
661
0
}
662
663
const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
664
    EVP_PKEY_ED448,
665
    EVP_PKEY_ED448,
666
    0,
667
    "ED448",
668
    "OpenSSL ED448 algorithm",
669
670
    ecx_pub_decode,
671
    ecx_pub_encode,
672
    ecx_pub_cmp,
673
    ecx_pub_print,
674
675
    NULL,
676
    ecx_priv_encode,
677
    ecx_priv_print,
678
679
    ecd_size448,
680
    ecx_bits,
681
    ecx_security_bits,
682
683
    0, 0, 0, 0,
684
    ecx_cmp_parameters,
685
    0, 0,
686
687
    ecx_free,
688
    ecd_ctrl,
689
    NULL,
690
    NULL,
691
    ecd_item_verify,
692
    ecd_item_sign448,
693
    ecd_sig_info_set448,
694
695
    NULL,
696
    NULL,
697
    NULL,
698
699
    ecx_set_priv_key,
700
    ecx_set_pub_key,
701
    ecx_get_priv_key,
702
    ecx_get_pub_key,
703
    ecx_pkey_dirty_cnt,
704
    ecx_pkey_export_to,
705
    ed448_import_from,
706
    ecx_pkey_copy,
707
708
    ecx_priv_decode_ex
709
};
710
711
static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
712
0
{
713
0
    ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
714
0
                                   KEY_OP_KEYGEN, NULL, NULL);
715
716
0
    if (ecx != NULL) {
717
0
        EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
718
0
        return 1;
719
0
    }
720
0
    return 0;
721
0
}
722
723
static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
724
                                          size_t *keylen,
725
                                          const unsigned char **privkey,
726
                                          const unsigned char **pubkey)
727
0
{
728
0
    const ECX_KEY *ecxkey, *peerkey;
729
730
0
    if (ctx->pkey == NULL || ctx->peerkey == NULL) {
731
0
        ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
732
0
        return 0;
733
0
    }
734
0
    ecxkey = evp_pkey_get_legacy(ctx->pkey);
735
0
    peerkey = evp_pkey_get_legacy(ctx->peerkey);
736
0
    if (ecxkey == NULL || ecxkey->privkey == NULL) {
737
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
738
0
        return 0;
739
0
    }
740
0
    if (peerkey == NULL) {
741
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
742
0
        return 0;
743
0
    }
744
0
    *privkey = ecxkey->privkey;
745
0
    *pubkey = peerkey->pubkey;
746
747
0
    return 1;
748
0
}
749
750
static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
751
                                size_t *keylen)
752
0
{
753
0
    const unsigned char *privkey, *pubkey;
754
755
0
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
756
0
            || (key != NULL
757
0
                && ossl_x25519(key, privkey, pubkey) == 0))
758
0
        return 0;
759
0
    *keylen = X25519_KEYLEN;
760
0
    return 1;
761
0
}
762
763
static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
764
                              size_t *keylen)
765
0
{
766
0
    const unsigned char *privkey, *pubkey;
767
768
0
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
769
0
            || (key != NULL
770
0
                && ossl_x448(key, privkey, pubkey) == 0))
771
0
        return 0;
772
0
    *keylen = X448_KEYLEN;
773
0
    return 1;
774
0
}
775
776
static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
777
0
{
778
    /* Only need to handle peer key for derivation */
779
0
    if (type == EVP_PKEY_CTRL_PEER_KEY)
780
0
        return 1;
781
0
    return -2;
782
0
}
783
784
static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
785
    EVP_PKEY_X25519,
786
    0, 0, 0, 0, 0, 0, 0,
787
    pkey_ecx_keygen,
788
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
789
    pkey_ecx_derive25519,
790
    pkey_ecx_ctrl,
791
    0
792
};
793
794
static const EVP_PKEY_METHOD ecx448_pkey_meth = {
795
    EVP_PKEY_X448,
796
    0, 0, 0, 0, 0, 0, 0,
797
    pkey_ecx_keygen,
798
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
799
    pkey_ecx_derive448,
800
    pkey_ecx_ctrl,
801
    0
802
};
803
804
static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
805
                                    size_t *siglen, const unsigned char *tbs,
806
                                    size_t tbslen)
807
0
{
808
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
809
810
0
    if (edkey == NULL) {
811
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
812
0
        return 0;
813
0
    }
814
815
0
    if (sig == NULL) {
816
0
        *siglen = ED25519_SIGSIZE;
817
0
        return 1;
818
0
    }
819
0
    if (*siglen < ED25519_SIGSIZE) {
820
0
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
821
0
        return 0;
822
0
    }
823
824
0
    if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey,
825
0
                          0, 0, 0,
826
0
                          NULL, 0,
827
0
                          NULL, NULL) == 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, 0, edkey->propq) == 0)
855
0
        return 0;
856
0
    *siglen = ED448_SIGSIZE;
857
0
    return 1;
858
0
}
859
860
static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
861
                                      size_t siglen, const unsigned char *tbs,
862
                                      size_t tbslen)
863
0
{
864
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
865
866
0
    if (edkey == NULL) {
867
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
868
0
        return 0;
869
0
    }
870
871
0
    if (siglen != ED25519_SIGSIZE)
872
0
        return 0;
873
874
0
    return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
875
0
                               0, 0, 0,
876
0
                               NULL, 0,
877
0
                               edkey->libctx, edkey->propq);
878
0
}
879
880
static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
881
                                    size_t siglen, const unsigned char *tbs,
882
                                    size_t tbslen)
883
0
{
884
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
885
886
0
    if (edkey == NULL) {
887
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
888
0
        return 0;
889
0
    }
890
891
0
    if (siglen != ED448_SIGSIZE)
892
0
        return 0;
893
894
0
    return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
895
0
                             NULL, 0, 0, edkey->propq);
896
0
}
897
898
static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
899
0
{
900
0
    switch (type) {
901
0
    case EVP_PKEY_CTRL_MD:
902
        /* Only NULL allowed as digest */
903
0
        if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
904
0
            return 1;
905
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
906
0
        return 0;
907
908
0
    case EVP_PKEY_CTRL_DIGESTINIT:
909
0
        return 1;
910
0
    }
911
0
    return -2;
912
0
}
913
914
static const EVP_PKEY_METHOD ed25519_pkey_meth = {
915
    EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
916
    0, 0, 0, 0, 0, 0,
917
    pkey_ecx_keygen,
918
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
919
    pkey_ecd_ctrl,
920
    0,
921
    pkey_ecd_digestsign25519,
922
    pkey_ecd_digestverify25519
923
};
924
925
static const EVP_PKEY_METHOD ed448_pkey_meth = {
926
    EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
927
    0, 0, 0, 0, 0, 0,
928
    pkey_ecx_keygen,
929
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
930
    pkey_ecd_ctrl,
931
    0,
932
    pkey_ecd_digestsign448,
933
    pkey_ecd_digestverify448
934
};
935
936
#ifdef S390X_EC_ASM
937
# include "s390x_arch.h"
938
939
static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
940
{
941
    static const unsigned char generator[] = {
942
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
943
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
944
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
945
    };
946
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
947
                                    ctx->propquery);
948
    unsigned char *privkey = NULL, *pubkey;
949
950
    if (key == NULL) {
951
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
952
        goto err;
953
    }
954
955
    pubkey = key->pubkey;
956
957
    privkey = ossl_ecx_key_allocate_privkey(key);
958
    if (privkey == NULL) {
959
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
960
        goto err;
961
    }
962
963
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
964
        goto err;
965
966
    privkey[0] &= 248;
967
    privkey[31] &= 127;
968
    privkey[31] |= 64;
969
970
    if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
971
        goto err;
972
973
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
974
    return 1;
975
 err:
976
    ossl_ecx_key_free(key);
977
    return 0;
978
}
979
980
static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
981
{
982
    static const unsigned char generator[] = {
983
        0x05, 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, 0x00, 0x00, 0x00, 0x00,
987
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
988
    };
989
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
990
                                    ctx->propquery);
991
    unsigned char *privkey = NULL, *pubkey;
992
993
    if (key == NULL) {
994
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
995
        goto err;
996
    }
997
998
    pubkey = key->pubkey;
999
1000
    privkey = ossl_ecx_key_allocate_privkey(key);
1001
    if (privkey == NULL) {
1002
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1003
        goto err;
1004
    }
1005
1006
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1007
        goto err;
1008
1009
    privkey[0] &= 252;
1010
    privkey[55] |= 128;
1011
1012
    if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1013
        goto err;
1014
1015
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1016
    return 1;
1017
 err:
1018
    ossl_ecx_key_free(key);
1019
    return 0;
1020
}
1021
1022
static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1023
{
1024
    static const unsigned char generator_x[] = {
1025
        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1026
        0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1027
        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1028
    };
1029
    static const unsigned char generator_y[] = {
1030
        0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1031
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1032
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1033
    };
1034
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1035
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1036
                                    ctx->propquery);
1037
    unsigned char *privkey = NULL, *pubkey;
1038
    unsigned int sz;
1039
    EVP_MD *md = NULL;
1040
    int rv;
1041
1042
    if (key == NULL) {
1043
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1044
        goto err;
1045
    }
1046
1047
    pubkey = key->pubkey;
1048
1049
    privkey = ossl_ecx_key_allocate_privkey(key);
1050
    if (privkey == NULL) {
1051
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1052
        goto err;
1053
    }
1054
1055
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1056
        goto err;
1057
1058
    md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1059
    if (md == NULL)
1060
        goto err;
1061
1062
    rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1063
    EVP_MD_free(md);
1064
    if (!rv)
1065
        goto err;
1066
1067
    buff[0] &= 248;
1068
    buff[31] &= 63;
1069
    buff[31] |= 64;
1070
1071
    if (s390x_ed25519_mul(x_dst, pubkey,
1072
                          generator_x, generator_y, buff) != 1)
1073
        goto err;
1074
1075
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1076
1077
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1078
    return 1;
1079
 err:
1080
    ossl_ecx_key_free(key);
1081
    return 0;
1082
}
1083
1084
static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1085
{
1086
    static const unsigned char generator_x[] = {
1087
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1088
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1089
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1090
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1091
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1092
    };
1093
    static const unsigned char generator_y[] = {
1094
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1095
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1096
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1097
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1098
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1099
    };
1100
    unsigned char x_dst[57], buff[114];
1101
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1102
                                    ctx->propquery);
1103
    unsigned char *privkey = NULL, *pubkey;
1104
    EVP_MD_CTX *hashctx = NULL;
1105
    EVP_MD *md = NULL;
1106
    int rv;
1107
1108
    if (key == NULL) {
1109
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1110
        goto err;
1111
    }
1112
1113
    pubkey = key->pubkey;
1114
1115
    privkey = ossl_ecx_key_allocate_privkey(key);
1116
    if (privkey == NULL) {
1117
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1118
        goto err;
1119
    }
1120
1121
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1122
        goto err;
1123
1124
    hashctx = EVP_MD_CTX_new();
1125
    if (hashctx == NULL)
1126
        goto err;
1127
1128
    md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1129
    if (md == NULL)
1130
        goto err;
1131
1132
    rv = EVP_DigestInit_ex(hashctx, md, NULL);
1133
    EVP_MD_free(md);
1134
    if (rv != 1)
1135
        goto err;
1136
1137
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1138
        goto err;
1139
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1140
        goto err;
1141
1142
    buff[0] &= -4;
1143
    buff[55] |= 0x80;
1144
    buff[56] = 0;
1145
1146
    if (s390x_ed448_mul(x_dst, pubkey,
1147
                        generator_x, generator_y, buff) != 1)
1148
        goto err;
1149
1150
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1151
1152
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1153
    EVP_MD_CTX_free(hashctx);
1154
    return 1;
1155
 err:
1156
    ossl_ecx_key_free(key);
1157
    EVP_MD_CTX_free(hashctx);
1158
    return 0;
1159
}
1160
1161
static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1162
                                      size_t *keylen)
1163
{
1164
    const unsigned char *privkey, *pubkey;
1165
1166
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1167
        || (key != NULL
1168
            && s390x_x25519_mul(key, privkey, pubkey) == 0))
1169
        return 0;
1170
    *keylen = X25519_KEYLEN;
1171
    return 1;
1172
}
1173
1174
static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1175
                                      size_t *keylen)
1176
{
1177
    const unsigned char *privkey, *pubkey;
1178
1179
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1180
        || (key != NULL
1181
            && s390x_x448_mul(key, pubkey, privkey) == 0))
1182
        return 0;
1183
    *keylen = X448_KEYLEN;
1184
    return 1;
1185
}
1186
1187
static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1188
                                          unsigned char *sig, size_t *siglen,
1189
                                          const unsigned char *tbs,
1190
                                          size_t tbslen)
1191
{
1192
    union {
1193
        struct {
1194
            unsigned char sig[64];
1195
            unsigned char priv[32];
1196
        } ed25519;
1197
        unsigned long long buff[512];
1198
    } param;
1199
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1200
    int rc;
1201
1202
    if (edkey == NULL) {
1203
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1204
        return 0;
1205
    }
1206
1207
    if (sig == NULL) {
1208
        *siglen = ED25519_SIGSIZE;
1209
        return 1;
1210
    }
1211
1212
    if (*siglen < ED25519_SIGSIZE) {
1213
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1214
        return 0;
1215
    }
1216
1217
    memset(&param, 0, sizeof(param));
1218
    memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1219
1220
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1221
    OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1222
    if (rc != 0)
1223
        return 0;
1224
1225
    s390x_flip_endian32(sig, param.ed25519.sig);
1226
    s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1227
1228
    *siglen = ED25519_SIGSIZE;
1229
    return 1;
1230
}
1231
1232
static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1233
                                        unsigned char *sig, size_t *siglen,
1234
                                        const unsigned char *tbs,
1235
                                        size_t tbslen)
1236
{
1237
    union {
1238
        struct {
1239
            unsigned char sig[128];
1240
            unsigned char priv[64];
1241
        } ed448;
1242
        unsigned long long buff[512];
1243
    } param;
1244
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1245
    int rc;
1246
1247
    if (edkey == NULL) {
1248
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1249
        return 0;
1250
    }
1251
1252
    if (sig == NULL) {
1253
        *siglen = ED448_SIGSIZE;
1254
        return 1;
1255
    }
1256
1257
    if (*siglen < ED448_SIGSIZE) {
1258
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1259
        return 0;
1260
    }
1261
1262
    memset(&param, 0, sizeof(param));
1263
    memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1264
1265
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1266
    OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1267
    if (rc != 0)
1268
        return 0;
1269
1270
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1271
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1272
    memcpy(sig, param.ed448.sig, 57);
1273
    memcpy(sig + 57, param.ed448.sig + 64, 57);
1274
1275
    *siglen = ED448_SIGSIZE;
1276
    return 1;
1277
}
1278
1279
static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1280
                                            const unsigned char *sig,
1281
                                            size_t siglen,
1282
                                            const unsigned char *tbs,
1283
                                            size_t tbslen)
1284
{
1285
    union {
1286
        struct {
1287
            unsigned char sig[64];
1288
            unsigned char pub[32];
1289
        } ed25519;
1290
        unsigned long long buff[512];
1291
    } param;
1292
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1293
1294
    if (edkey == NULL) {
1295
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1296
        return 0;
1297
    }
1298
1299
    if (siglen != ED25519_SIGSIZE)
1300
        return 0;
1301
1302
    memset(&param, 0, sizeof(param));
1303
    s390x_flip_endian32(param.ed25519.sig, sig);
1304
    s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1305
    s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1306
1307
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1308
                      &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1309
}
1310
1311
static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1312
                                          const unsigned char *sig,
1313
                                          size_t siglen,
1314
                                          const unsigned char *tbs,
1315
                                          size_t tbslen)
1316
{
1317
    union {
1318
        struct {
1319
            unsigned char sig[128];
1320
            unsigned char pub[64];
1321
        } ed448;
1322
        unsigned long long buff[512];
1323
    } param;
1324
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1325
1326
    if (edkey == NULL) {
1327
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1328
        return 0;
1329
    }
1330
1331
    if (siglen != ED448_SIGSIZE)
1332
        return 0;
1333
1334
    memset(&param, 0, sizeof(param));
1335
    memcpy(param.ed448.sig, sig, 57);
1336
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1337
    memcpy(param.ed448.sig + 64, sig + 57, 57);
1338
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1339
    memcpy(param.ed448.pub, edkey->pubkey, 57);
1340
    s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1341
1342
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1343
                      &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1344
}
1345
1346
static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1347
    EVP_PKEY_X25519,
1348
    0, 0, 0, 0, 0, 0, 0,
1349
    s390x_pkey_ecx_keygen25519,
1350
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1351
    s390x_pkey_ecx_derive25519,
1352
    pkey_ecx_ctrl,
1353
    0
1354
};
1355
1356
static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1357
    EVP_PKEY_X448,
1358
    0, 0, 0, 0, 0, 0, 0,
1359
    s390x_pkey_ecx_keygen448,
1360
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1361
    s390x_pkey_ecx_derive448,
1362
    pkey_ecx_ctrl,
1363
    0
1364
};
1365
static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1366
    EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1367
    0, 0, 0, 0, 0, 0,
1368
    s390x_pkey_ecd_keygen25519,
1369
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1370
    pkey_ecd_ctrl,
1371
    0,
1372
    s390x_pkey_ecd_digestsign25519,
1373
    s390x_pkey_ecd_digestverify25519
1374
};
1375
1376
static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1377
    EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1378
    0, 0, 0, 0, 0, 0,
1379
    s390x_pkey_ecd_keygen448,
1380
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1381
    pkey_ecd_ctrl,
1382
    0,
1383
    s390x_pkey_ecd_digestsign448,
1384
    s390x_pkey_ecd_digestverify448
1385
};
1386
#endif
1387
1388
const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1389
0
{
1390
#ifdef S390X_EC_ASM
1391
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1392
        return &ecx25519_s390x_pkey_meth;
1393
#endif
1394
0
    return &ecx25519_pkey_meth;
1395
0
}
1396
1397
const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1398
0
{
1399
#ifdef S390X_EC_ASM
1400
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1401
        return &ecx448_s390x_pkey_meth;
1402
#endif
1403
0
    return &ecx448_pkey_meth;
1404
0
}
1405
1406
const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1407
0
{
1408
#ifdef S390X_EC_ASM
1409
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1410
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1411
        && OPENSSL_s390xcap_P.kdsa[0]
1412
            & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1413
        return &ed25519_s390x_pkey_meth;
1414
#endif
1415
0
    return &ed25519_pkey_meth;
1416
0
}
1417
1418
const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1419
0
{
1420
#ifdef S390X_EC_ASM
1421
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1422
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1423
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1424
        return &ed448_s390x_pkey_meth;
1425
#endif
1426
0
    return &ed448_pkey_meth;
1427
0
}