Coverage Report

Created: 2025-12-10 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/ec/ecx_meth.c
Line
Count
Source
1
/*
2
 * Copyright 2006-2025 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)
184
0
            == 0)
185
0
            return 0;
186
0
    } 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
0
    if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
196
0
        return 0;
197
198
0
    if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
199
0
            indent + 4)
200
0
        == 0)
201
0
        return 0;
202
0
    return 1;
203
0
}
204
205
static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
206
    ASN1_PCTX *ctx)
207
0
{
208
0
    return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
209
0
}
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, (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)
830
0
        == 0)
831
0
        return 0;
832
0
    *siglen = ED25519_SIGSIZE;
833
0
    return 1;
834
0
}
835
836
static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
837
    size_t *siglen, const unsigned char *tbs,
838
    size_t tbslen)
839
0
{
840
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
841
842
0
    if (edkey == NULL) {
843
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
844
0
        return 0;
845
0
    }
846
847
0
    if (sig == NULL) {
848
0
        *siglen = ED448_SIGSIZE;
849
0
        return 1;
850
0
    }
851
0
    if (*siglen < ED448_SIGSIZE) {
852
0
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
853
0
        return 0;
854
0
    }
855
856
0
    if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
857
0
            edkey->privkey, NULL, 0, 0, edkey->propq)
858
0
        == 0)
859
0
        return 0;
860
0
    *siglen = ED448_SIGSIZE;
861
0
    return 1;
862
0
}
863
864
static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
865
    size_t siglen, const unsigned char *tbs,
866
    size_t tbslen)
867
0
{
868
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
869
870
0
    if (edkey == NULL) {
871
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
872
0
        return 0;
873
0
    }
874
875
0
    if (siglen != ED25519_SIGSIZE)
876
0
        return 0;
877
878
0
    return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
879
0
        0, 0, 0,
880
0
        NULL, 0,
881
0
        edkey->libctx, edkey->propq);
882
0
}
883
884
static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
885
    size_t siglen, const unsigned char *tbs,
886
    size_t tbslen)
887
0
{
888
0
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
889
890
0
    if (edkey == NULL) {
891
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
892
0
        return 0;
893
0
    }
894
895
0
    if (siglen != ED448_SIGSIZE)
896
0
        return 0;
897
898
0
    return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
899
0
        NULL, 0, 0, edkey->propq);
900
0
}
901
902
static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
903
0
{
904
0
    switch (type) {
905
0
    case EVP_PKEY_CTRL_MD:
906
        /* Only NULL allowed as digest */
907
0
        if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
908
0
            return 1;
909
0
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
910
0
        return 0;
911
912
0
    case EVP_PKEY_CTRL_DIGESTINIT:
913
0
        return 1;
914
0
    }
915
0
    return -2;
916
0
}
917
918
static const EVP_PKEY_METHOD ed25519_pkey_meth = {
919
    EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
920
    0, 0, 0, 0, 0, 0,
921
    pkey_ecx_keygen,
922
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
923
    pkey_ecd_ctrl,
924
    0,
925
    pkey_ecd_digestsign25519,
926
    pkey_ecd_digestverify25519
927
};
928
929
static const EVP_PKEY_METHOD ed448_pkey_meth = {
930
    EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
931
    0, 0, 0, 0, 0, 0,
932
    pkey_ecx_keygen,
933
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
934
    pkey_ecd_ctrl,
935
    0,
936
    pkey_ecd_digestsign448,
937
    pkey_ecd_digestverify448
938
};
939
940
#ifdef S390X_EC_ASM
941
#include "s390x_arch.h"
942
943
static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
944
{
945
    static const unsigned char generator[] = {
946
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
947
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
948
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
949
    };
950
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
951
        ctx->propquery);
952
    unsigned char *privkey = NULL, *pubkey;
953
954
    if (key == NULL) {
955
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
956
        goto err;
957
    }
958
959
    pubkey = key->pubkey;
960
961
    privkey = ossl_ecx_key_allocate_privkey(key);
962
    if (privkey == NULL) {
963
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
964
        goto err;
965
    }
966
967
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
968
        goto err;
969
970
    privkey[0] &= 248;
971
    privkey[31] &= 127;
972
    privkey[31] |= 64;
973
974
    if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
975
        goto err;
976
977
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
978
    return 1;
979
err:
980
    ossl_ecx_key_free(key);
981
    return 0;
982
}
983
984
static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
985
{
986
    static const unsigned char generator[] = {
987
        0x05, 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, 0x00, 0x00, 0x00, 0x00,
990
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
991
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
992
    };
993
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
994
        ctx->propquery);
995
    unsigned char *privkey = NULL, *pubkey;
996
997
    if (key == NULL) {
998
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
999
        goto err;
1000
    }
1001
1002
    pubkey = key->pubkey;
1003
1004
    privkey = ossl_ecx_key_allocate_privkey(key);
1005
    if (privkey == NULL) {
1006
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1007
        goto err;
1008
    }
1009
1010
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1011
        goto err;
1012
1013
    privkey[0] &= 252;
1014
    privkey[55] |= 128;
1015
1016
    if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1017
        goto err;
1018
1019
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1020
    return 1;
1021
err:
1022
    ossl_ecx_key_free(key);
1023
    return 0;
1024
}
1025
1026
static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1027
{
1028
    static const unsigned char generator_x[] = {
1029
        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1030
        0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1031
        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1032
    };
1033
    static const unsigned char generator_y[] = {
1034
        0x58,
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
        0x66,
1065
        0x66,
1066
    };
1067
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1068
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1069
        ctx->propquery);
1070
    unsigned char *privkey = NULL, *pubkey;
1071
    unsigned int sz;
1072
    EVP_MD *md = NULL;
1073
    int rv;
1074
1075
    if (key == NULL) {
1076
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1077
        goto err;
1078
    }
1079
1080
    pubkey = key->pubkey;
1081
1082
    privkey = ossl_ecx_key_allocate_privkey(key);
1083
    if (privkey == NULL) {
1084
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1085
        goto err;
1086
    }
1087
1088
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1089
        goto err;
1090
1091
    md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1092
    if (md == NULL)
1093
        goto err;
1094
1095
    rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1096
    EVP_MD_free(md);
1097
    if (!rv)
1098
        goto err;
1099
1100
    buff[0] &= 248;
1101
    buff[31] &= 63;
1102
    buff[31] |= 64;
1103
1104
    if (s390x_ed25519_mul(x_dst, pubkey,
1105
            generator_x, generator_y, buff)
1106
        != 1)
1107
        goto err;
1108
1109
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1110
1111
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1112
    return 1;
1113
err:
1114
    ossl_ecx_key_free(key);
1115
    return 0;
1116
}
1117
1118
static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1119
{
1120
    static const unsigned char generator_x[] = {
1121
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1122
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1123
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1124
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1125
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1126
    };
1127
    static const unsigned char generator_y[] = {
1128
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1129
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1130
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1131
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1132
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1133
    };
1134
    unsigned char x_dst[57], buff[114];
1135
    ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1136
        ctx->propquery);
1137
    unsigned char *privkey = NULL, *pubkey;
1138
    EVP_MD_CTX *hashctx = NULL;
1139
    EVP_MD *md = NULL;
1140
    int rv;
1141
1142
    if (key == NULL) {
1143
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1144
        goto err;
1145
    }
1146
1147
    pubkey = key->pubkey;
1148
1149
    privkey = ossl_ecx_key_allocate_privkey(key);
1150
    if (privkey == NULL) {
1151
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1152
        goto err;
1153
    }
1154
1155
    if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1156
        goto err;
1157
1158
    hashctx = EVP_MD_CTX_new();
1159
    if (hashctx == NULL)
1160
        goto err;
1161
1162
    md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1163
    if (md == NULL)
1164
        goto err;
1165
1166
    rv = EVP_DigestInit_ex(hashctx, md, NULL);
1167
    EVP_MD_free(md);
1168
    if (rv != 1)
1169
        goto err;
1170
1171
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1172
        goto err;
1173
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1174
        goto err;
1175
1176
    buff[0] &= -4;
1177
    buff[55] |= 0x80;
1178
    buff[56] = 0;
1179
1180
    if (s390x_ed448_mul(x_dst, pubkey,
1181
            generator_x, generator_y, buff)
1182
        != 1)
1183
        goto err;
1184
1185
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1186
1187
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1188
    EVP_MD_CTX_free(hashctx);
1189
    return 1;
1190
err:
1191
    ossl_ecx_key_free(key);
1192
    EVP_MD_CTX_free(hashctx);
1193
    return 0;
1194
}
1195
1196
static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1197
    size_t *keylen)
1198
{
1199
    const unsigned char *privkey, *pubkey;
1200
1201
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1202
        || (key != NULL
1203
            && s390x_x25519_mul(key, privkey, pubkey) == 0))
1204
        return 0;
1205
    *keylen = X25519_KEYLEN;
1206
    return 1;
1207
}
1208
1209
static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1210
    size_t *keylen)
1211
{
1212
    const unsigned char *privkey, *pubkey;
1213
1214
    if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1215
        || (key != NULL
1216
            && s390x_x448_mul(key, pubkey, privkey) == 0))
1217
        return 0;
1218
    *keylen = X448_KEYLEN;
1219
    return 1;
1220
}
1221
1222
static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1223
    unsigned char *sig, size_t *siglen,
1224
    const unsigned char *tbs,
1225
    size_t tbslen)
1226
{
1227
    union {
1228
        struct {
1229
            unsigned char sig[64];
1230
            unsigned char priv[32];
1231
        } ed25519;
1232
        unsigned long long buff[512];
1233
    } param;
1234
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1235
    int rc;
1236
1237
    if (edkey == NULL) {
1238
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1239
        return 0;
1240
    }
1241
1242
    if (sig == NULL) {
1243
        *siglen = ED25519_SIGSIZE;
1244
        return 1;
1245
    }
1246
1247
    if (*siglen < ED25519_SIGSIZE) {
1248
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1249
        return 0;
1250
    }
1251
1252
    memset(&param, 0, sizeof(param));
1253
    memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1254
1255
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1256
    OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1257
    if (rc != 0)
1258
        return 0;
1259
1260
    s390x_flip_endian32(sig, param.ed25519.sig);
1261
    s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1262
1263
    *siglen = ED25519_SIGSIZE;
1264
    return 1;
1265
}
1266
1267
static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1268
    unsigned char *sig, size_t *siglen,
1269
    const unsigned char *tbs,
1270
    size_t tbslen)
1271
{
1272
    union {
1273
        struct {
1274
            unsigned char sig[128];
1275
            unsigned char priv[64];
1276
        } ed448;
1277
        unsigned long long buff[512];
1278
    } param;
1279
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1280
    int rc;
1281
1282
    if (edkey == NULL) {
1283
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1284
        return 0;
1285
    }
1286
1287
    if (sig == NULL) {
1288
        *siglen = ED448_SIGSIZE;
1289
        return 1;
1290
    }
1291
1292
    if (*siglen < ED448_SIGSIZE) {
1293
        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1294
        return 0;
1295
    }
1296
1297
    memset(&param, 0, sizeof(param));
1298
    memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1299
1300
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1301
    OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1302
    if (rc != 0)
1303
        return 0;
1304
1305
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1306
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1307
    memcpy(sig, param.ed448.sig, 57);
1308
    memcpy(sig + 57, param.ed448.sig + 64, 57);
1309
1310
    *siglen = ED448_SIGSIZE;
1311
    return 1;
1312
}
1313
1314
static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1315
    const unsigned char *sig,
1316
    size_t siglen,
1317
    const unsigned char *tbs,
1318
    size_t tbslen)
1319
{
1320
    union {
1321
        struct {
1322
            unsigned char sig[64];
1323
            unsigned char pub[32];
1324
        } ed25519;
1325
        unsigned long long buff[512];
1326
    } param;
1327
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1328
1329
    if (edkey == NULL) {
1330
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1331
        return 0;
1332
    }
1333
1334
    if (siglen != ED25519_SIGSIZE)
1335
        return 0;
1336
1337
    memset(&param, 0, sizeof(param));
1338
    s390x_flip_endian32(param.ed25519.sig, sig);
1339
    s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1340
    s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1341
1342
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1343
               &param.ed25519, tbs, tbslen)
1344
            == 0
1345
        ? 1
1346
        : 0;
1347
}
1348
1349
static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1350
    const unsigned char *sig,
1351
    size_t siglen,
1352
    const unsigned char *tbs,
1353
    size_t tbslen)
1354
{
1355
    union {
1356
        struct {
1357
            unsigned char sig[128];
1358
            unsigned char pub[64];
1359
        } ed448;
1360
        unsigned long long buff[512];
1361
    } param;
1362
    const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1363
1364
    if (edkey == NULL) {
1365
        ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1366
        return 0;
1367
    }
1368
1369
    if (siglen != ED448_SIGSIZE)
1370
        return 0;
1371
1372
    memset(&param, 0, sizeof(param));
1373
    memcpy(param.ed448.sig, sig, 57);
1374
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1375
    memcpy(param.ed448.sig + 64, sig + 57, 57);
1376
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1377
    memcpy(param.ed448.pub, edkey->pubkey, 57);
1378
    s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1379
1380
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1381
               &param.ed448, tbs, tbslen)
1382
            == 0
1383
        ? 1
1384
        : 0;
1385
}
1386
1387
static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1388
    EVP_PKEY_X25519,
1389
    0, 0, 0, 0, 0, 0, 0,
1390
    s390x_pkey_ecx_keygen25519,
1391
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1392
    s390x_pkey_ecx_derive25519,
1393
    pkey_ecx_ctrl,
1394
    0
1395
};
1396
1397
static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1398
    EVP_PKEY_X448,
1399
    0, 0, 0, 0, 0, 0, 0,
1400
    s390x_pkey_ecx_keygen448,
1401
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1402
    s390x_pkey_ecx_derive448,
1403
    pkey_ecx_ctrl,
1404
    0
1405
};
1406
static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1407
    EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1408
    0, 0, 0, 0, 0, 0,
1409
    s390x_pkey_ecd_keygen25519,
1410
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1411
    pkey_ecd_ctrl,
1412
    0,
1413
    s390x_pkey_ecd_digestsign25519,
1414
    s390x_pkey_ecd_digestverify25519
1415
};
1416
1417
static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1418
    EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1419
    0, 0, 0, 0, 0, 0,
1420
    s390x_pkey_ecd_keygen448,
1421
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1422
    pkey_ecd_ctrl,
1423
    0,
1424
    s390x_pkey_ecd_digestsign448,
1425
    s390x_pkey_ecd_digestverify448
1426
};
1427
#endif
1428
1429
const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1430
0
{
1431
#ifdef S390X_EC_ASM
1432
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1433
        return &ecx25519_s390x_pkey_meth;
1434
#endif
1435
0
    return &ecx25519_pkey_meth;
1436
0
}
1437
1438
const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1439
0
{
1440
#ifdef S390X_EC_ASM
1441
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1442
        return &ecx448_s390x_pkey_meth;
1443
#endif
1444
0
    return &ecx448_pkey_meth;
1445
0
}
1446
1447
const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1448
0
{
1449
#ifdef S390X_EC_ASM
1450
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1451
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1452
        && OPENSSL_s390xcap_P.kdsa[0]
1453
            & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1454
        return &ed25519_s390x_pkey_meth;
1455
#endif
1456
0
    return &ed25519_pkey_meth;
1457
0
}
1458
1459
const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1460
0
{
1461
#ifdef S390X_EC_ASM
1462
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1463
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1464
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1465
        return &ed448_s390x_pkey_meth;
1466
#endif
1467
0
    return &ed448_pkey_meth;
1468
0
}