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