Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl33/crypto/ec/ecx_meth.c
Line
Count
Source
1
/*
2
 * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
/*
11
 * ECDSA low level APIs are deprecated for public use, but still ok for
12
 * internal use.
13
 */
14
#include "internal/deprecated.h"
15
16
#include <stdio.h>
17
#include <openssl/x509.h>
18
#include <openssl/ec.h>
19
#include <openssl/core_names.h>
20
#include <openssl/param_build.h>
21
#include <openssl/rand.h>
22
#include "internal/cryptlib.h"
23
#include "internal/provider.h"
24
#include "crypto/asn1.h"
25
#include "crypto/evp.h"
26
#include "crypto/ecx.h"
27
#include "ec_local.h"
28
#include "curve448/curve448_local.h"
29
#include "ecx_backend.h"
30
31
static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
32
0
{
33
0
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
34
0
    unsigned char *penc;
35
36
0
    if (ecxkey == NULL) {
37
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
38
0
        return 0;
39
0
    }
40
41
0
    penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
42
0
    if (penc == NULL)
43
0
        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
16.0k
{
56
16.0k
    const unsigned char *p;
57
16.0k
    int pklen;
58
16.0k
    X509_ALGOR *palg;
59
16.0k
    ECX_KEY *ecx;
60
16.0k
    int ret = 0;
61
62
16.0k
    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
63
0
        return 0;
64
16.0k
    ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id,
65
16.0k
        KEY_OP_PUBLIC, NULL, NULL);
66
16.0k
    if (ecx != NULL) {
67
3.20k
        ret = 1;
68
3.20k
        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
69
3.20k
    }
70
16.0k
    return ret;
71
16.0k
}
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
84
{
87
84
    int ret = 0;
88
84
    ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq);
89
90
84
    if (ecx != NULL) {
91
22
        ret = 1;
92
22
        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
93
22
    }
94
95
84
    return ret;
96
84
}
97
98
static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
99
17
{
100
17
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
101
17
    ASN1_OCTET_STRING oct;
102
17
    unsigned char *penc = NULL;
103
17
    int penclen;
104
105
17
    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
17
    oct.data = ecxkey->privkey;
111
17
    oct.length = KEYLEN(pkey);
112
17
    oct.flags = 0;
113
114
17
    penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
115
17
    if (penclen < 0) {
116
0
        ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
117
0
        return 0;
118
0
    }
119
120
17
    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
121
17
            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
17
    return 1;
128
17
}
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
16.1k
{
157
16.1k
    ossl_ecx_key_free(pkey->pkey.ecx);
158
16.1k
}
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
17
{
169
17
    const ECX_KEY *ecxkey = pkey->pkey.ecx;
170
17
    const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
171
172
17
    if (op == KEY_OP_PRIVATE) {
173
17
        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
17
        if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
179
0
            return 0;
180
17
        if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
181
0
            return 0;
182
17
        if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
183
17
                indent + 4)
184
17
            == 0)
185
0
            return 0;
186
17
    } else {
187
0
        if (ecxkey == NULL) {
188
0
            if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
189
0
                return 0;
190
0
            return 1;
191
0
        }
192
0
        if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
193
0
            return 0;
194
0
    }
195
17
    if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
196
0
        return 0;
197
198
17
    if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
199
17
            indent + 4)
200
17
        == 0)
201
0
        return 0;
202
17
    return 1;
203
17
}
204
205
static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
206
    ASN1_PCTX *ctx)
207
17
{
208
17
    return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
209
17
}
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
0
    }
244
0
}
245
246
static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
247
0
{
248
0
    switch (op) {
249
0
    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
250
        /* We currently only support Pure EdDSA which takes no digest */
251
0
        *(int *)arg2 = NID_undef;
252
0
        return 2;
253
254
0
    default:
255
0
        return -2;
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
107
{
584
107
    X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
585
107
        X509_SIG_INFO_TLS);
586
107
    return 1;
587
107
}
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
31
{
600
31
    X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
601
31
        X509_SIG_INFO_TLS);
602
31
    return 1;
603
31
}
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)
828
0
        == 0)
829
0
        return 0;
830
0
    *siglen = ED25519_SIGSIZE;
831
0
    return 1;
832
0
}
833
834
static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
835
    size_t *siglen, const unsigned char *tbs,
836
    size_t tbslen)
837
0
{
838
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
839
840
0
    if (edkey == NULL) {
841
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
842
0
        return 0;
843
0
    }
844
845
0
    if (sig == NULL) {
846
0
        *siglen = ED448_SIGSIZE;
847
0
        return 1;
848
0
    }
849
0
    if (*siglen < ED448_SIGSIZE) {
850
0
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
851
0
        return 0;
852
0
    }
853
854
0
    if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
855
0
            edkey->privkey, NULL, 0, 0, edkey->propq)
856
0
        == 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,
1033
        0x66,
1034
        0x66,
1035
        0x66,
1036
        0x66,
1037
        0x66,
1038
        0x66,
1039
        0x66,
1040
        0x66,
1041
        0x66,
1042
        0x66,
1043
        0x66,
1044
        0x66,
1045
        0x66,
1046
        0x66,
1047
        0x66,
1048
        0x66,
1049
        0x66,
1050
        0x66,
1051
        0x66,
1052
        0x66,
1053
        0x66,
1054
        0x66,
1055
        0x66,
1056
        0x66,
1057
        0x66,
1058
        0x66,
1059
        0x66,
1060
        0x66,
1061
        0x66,
1062
        0x66,
1063
        0x66,
1064
    };
1065
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1066
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1067
        ctx->propquery);
1068
    unsigned char *privkey = NULL, *pubkey;
1069
    unsigned int sz;
1070
    EVP_MD *md = NULL;
1071
    int rv;
1072
1073
    if (key == NULL) {
1074
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1075
        goto err;
1076
    }
1077
1078
    pubkey = key->pubkey;
1079
1080
    privkey = ossl_ecx_key_allocate_privkey(key);
1081
    if (privkey == NULL) {
1082
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1083
        goto err;
1084
    }
1085
1086
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1087
        goto err;
1088
1089
    md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1090
    if (md == NULL)
1091
        goto err;
1092
1093
    rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1094
    EVP_MD_free(md);
1095
    if (!rv)
1096
        goto err;
1097
1098
    buff[0] &= 248;
1099
    buff[31] &= 63;
1100
    buff[31] |= 64;
1101
1102
    if (s390x_ed25519_mul(x_dst, pubkey,
1103
            generator_x, generator_y, buff)
1104
        != 1)
1105
        goto err;
1106
1107
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1108
1109
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1110
    return 1;
1111
err:
1112
    ossl_ecx_key_free(key);
1113
    return 0;
1114
}
1115
1116
static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1117
{
1118
    static const unsigned char generator_x[] = {
1119
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1120
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1121
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1122
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1123
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1124
    };
1125
    static const unsigned char generator_y[] = {
1126
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1127
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1128
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1129
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1130
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1131
    };
1132
    unsigned char x_dst[57], buff[114];
1133
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1134
        ctx->propquery);
1135
    unsigned char *privkey = NULL, *pubkey;
1136
    EVP_MD_CTX *hashctx = NULL;
1137
    EVP_MD *md = NULL;
1138
    int rv;
1139
1140
    if (key == NULL) {
1141
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1142
        goto err;
1143
    }
1144
1145
    pubkey = key->pubkey;
1146
1147
    privkey = ossl_ecx_key_allocate_privkey(key);
1148
    if (privkey == NULL) {
1149
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1150
        goto err;
1151
    }
1152
1153
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1154
        goto err;
1155
1156
    hashctx = EVP_MD_CTX_new();
1157
    if (hashctx == NULL)
1158
        goto err;
1159
1160
    md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1161
    if (md == NULL)
1162
        goto err;
1163
1164
    rv = EVP_DigestInit_ex(hashctx, md, NULL);
1165
    EVP_MD_free(md);
1166
    if (rv != 1)
1167
        goto err;
1168
1169
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1170
        goto err;
1171
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1172
        goto err;
1173
1174
    buff[0] &= -4;
1175
    buff[55] |= 0x80;
1176
    buff[56] = 0;
1177
1178
    if (s390x_ed448_mul(x_dst, pubkey,
1179
            generator_x, generator_y, buff)
1180
        != 1)
1181
        goto err;
1182
1183
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1184
1185
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1186
    EVP_MD_CTX_free(hashctx);
1187
    return 1;
1188
err:
1189
    ossl_ecx_key_free(key);
1190
    EVP_MD_CTX_free(hashctx);
1191
    return 0;
1192
}
1193
1194
static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1195
    size_t *keylen)
1196
{
1197
    const unsigned char *privkey, *pubkey;
1198
1199
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1200
        || (key != NULL
1201
            && s390x_x25519_mul(key, privkey, pubkey) == 0))
1202
        return 0;
1203
    *keylen = X25519_KEYLEN;
1204
    return 1;
1205
}
1206
1207
static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1208
    size_t *keylen)
1209
{
1210
    const unsigned char *privkey, *pubkey;
1211
1212
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1213
        || (key != NULL
1214
            && s390x_x448_mul(key, pubkey, privkey) == 0))
1215
        return 0;
1216
    *keylen = X448_KEYLEN;
1217
    return 1;
1218
}
1219
1220
static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1221
    unsigned char *sig, size_t *siglen,
1222
    const unsigned char *tbs,
1223
    size_t tbslen)
1224
{
1225
    union {
1226
        struct {
1227
            unsigned char sig[64];
1228
            unsigned char priv[32];
1229
        } ed25519;
1230
        unsigned long long buff[512];
1231
    } param;
1232
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1233
    int rc;
1234
1235
    if (edkey == NULL) {
1236
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1237
        return 0;
1238
    }
1239
1240
    if (sig == NULL) {
1241
        *siglen = ED25519_SIGSIZE;
1242
        return 1;
1243
    }
1244
1245
    if (*siglen < ED25519_SIGSIZE) {
1246
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1247
        return 0;
1248
    }
1249
1250
    memset(&param, 0, sizeof(param));
1251
    memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1252
1253
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1254
    OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1255
    if (rc != 0)
1256
        return 0;
1257
1258
    s390x_flip_endian32(sig, param.ed25519.sig);
1259
    s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1260
1261
    *siglen = ED25519_SIGSIZE;
1262
    return 1;
1263
}
1264
1265
static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1266
    unsigned char *sig, size_t *siglen,
1267
    const unsigned char *tbs,
1268
    size_t tbslen)
1269
{
1270
    union {
1271
        struct {
1272
            unsigned char sig[128];
1273
            unsigned char priv[64];
1274
        } ed448;
1275
        unsigned long long buff[512];
1276
    } param;
1277
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1278
    int rc;
1279
1280
    if (edkey == NULL) {
1281
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1282
        return 0;
1283
    }
1284
1285
    if (sig == NULL) {
1286
        *siglen = ED448_SIGSIZE;
1287
        return 1;
1288
    }
1289
1290
    if (*siglen < ED448_SIGSIZE) {
1291
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1292
        return 0;
1293
    }
1294
1295
    memset(&param, 0, sizeof(param));
1296
    memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1297
1298
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1299
    OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1300
    if (rc != 0)
1301
        return 0;
1302
1303
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1304
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1305
    memcpy(sig, param.ed448.sig, 57);
1306
    memcpy(sig + 57, param.ed448.sig + 64, 57);
1307
1308
    *siglen = ED448_SIGSIZE;
1309
    return 1;
1310
}
1311
1312
static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1313
    const unsigned char *sig,
1314
    size_t siglen,
1315
    const unsigned char *tbs,
1316
    size_t tbslen)
1317
{
1318
    union {
1319
        struct {
1320
            unsigned char sig[64];
1321
            unsigned char pub[32];
1322
        } ed25519;
1323
        unsigned long long buff[512];
1324
    } param;
1325
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1326
1327
    if (edkey == NULL) {
1328
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1329
        return 0;
1330
    }
1331
1332
    if (siglen != ED25519_SIGSIZE)
1333
        return 0;
1334
1335
    memset(&param, 0, sizeof(param));
1336
    s390x_flip_endian32(param.ed25519.sig, sig);
1337
    s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1338
    s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1339
1340
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1341
               &param.ed25519, tbs, tbslen)
1342
            == 0
1343
        ? 1
1344
        : 0;
1345
}
1346
1347
static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1348
    const unsigned char *sig,
1349
    size_t siglen,
1350
    const unsigned char *tbs,
1351
    size_t tbslen)
1352
{
1353
    union {
1354
        struct {
1355
            unsigned char sig[128];
1356
            unsigned char pub[64];
1357
        } ed448;
1358
        unsigned long long buff[512];
1359
    } param;
1360
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1361
1362
    if (edkey == NULL) {
1363
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1364
        return 0;
1365
    }
1366
1367
    if (siglen != ED448_SIGSIZE)
1368
        return 0;
1369
1370
    memset(&param, 0, sizeof(param));
1371
    memcpy(param.ed448.sig, sig, 57);
1372
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1373
    memcpy(param.ed448.sig + 64, sig + 57, 57);
1374
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1375
    memcpy(param.ed448.pub, edkey->pubkey, 57);
1376
    s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1377
1378
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1379
               &param.ed448, tbs, tbslen)
1380
            == 0
1381
        ? 1
1382
        : 0;
1383
}
1384
1385
static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1386
    EVP_PKEY_X25519,
1387
    0, 0, 0, 0, 0, 0, 0,
1388
    s390x_pkey_ecx_keygen25519,
1389
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1390
    s390x_pkey_ecx_derive25519,
1391
    pkey_ecx_ctrl,
1392
    0
1393
};
1394
1395
static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1396
    EVP_PKEY_X448,
1397
    0, 0, 0, 0, 0, 0, 0,
1398
    s390x_pkey_ecx_keygen448,
1399
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1400
    s390x_pkey_ecx_derive448,
1401
    pkey_ecx_ctrl,
1402
    0
1403
};
1404
static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1405
    EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1406
    0, 0, 0, 0, 0, 0,
1407
    s390x_pkey_ecd_keygen25519,
1408
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1409
    pkey_ecd_ctrl,
1410
    0,
1411
    s390x_pkey_ecd_digestsign25519,
1412
    s390x_pkey_ecd_digestverify25519
1413
};
1414
1415
static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1416
    EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1417
    0, 0, 0, 0, 0, 0,
1418
    s390x_pkey_ecd_keygen448,
1419
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1420
    pkey_ecd_ctrl,
1421
    0,
1422
    s390x_pkey_ecd_digestsign448,
1423
    s390x_pkey_ecd_digestverify448
1424
};
1425
#endif
1426
1427
const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1428
0
{
1429
#ifdef S390X_EC_ASM
1430
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1431
        return &ecx25519_s390x_pkey_meth;
1432
#endif
1433
0
    return &ecx25519_pkey_meth;
1434
0
}
1435
1436
const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1437
0
{
1438
#ifdef S390X_EC_ASM
1439
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1440
        return &ecx448_s390x_pkey_meth;
1441
#endif
1442
0
    return &ecx448_pkey_meth;
1443
0
}
1444
1445
const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1446
0
{
1447
#ifdef S390X_EC_ASM
1448
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1449
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1450
        && OPENSSL_s390xcap_P.kdsa[0]
1451
            & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1452
        return &ed25519_s390x_pkey_meth;
1453
#endif
1454
0
    return &ed25519_pkey_meth;
1455
0
}
1456
1457
const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1458
0
{
1459
#ifdef S390X_EC_ASM
1460
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1461
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1462
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1463
        return &ed448_s390x_pkey_meth;
1464
#endif
1465
0
    return &ed448_pkey_meth;
1466
0
}