2 * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
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
11 * ECDSA low level APIs are deprecated for public use, but still ok for
14 #include "internal/deprecated.h"
17 #include "internal/cryptlib.h"
18 #include <openssl/x509.h>
19 #include <openssl/ec.h>
20 #include <openssl/rand.h>
21 #include <openssl/core_names.h>
22 #include "openssl/param_build.h"
23 #include "crypto/asn1.h"
24 #include "crypto/evp.h"
25 #include "crypto/ecx.h"
27 #include "curve448/curve448_local.h"
28 #include "ecx_backend.h"
36 /* Setup EVP_PKEY using public, private or generation */
37 static int ecx_key_op(EVP_PKEY
*pkey
, int id
, const X509_ALGOR
*palg
,
38 const unsigned char *p
, int plen
, ecx_key_op_t op
)
41 unsigned char *privkey
, *pubkey
;
43 if (op
!= KEY_OP_KEYGEN
) {
47 /* Algorithm parameters must be absent */
48 X509_ALGOR_get0(NULL
, &ptype
, NULL
, palg
);
49 if (ptype
!= V_ASN1_UNDEF
) {
50 ECerr(EC_F_ECX_KEY_OP
, EC_R_INVALID_ENCODING
);
55 if (p
== NULL
|| plen
!= KEYLENID(id
)) {
56 ECerr(EC_F_ECX_KEY_OP
, EC_R_INVALID_ENCODING
);
61 key
= ecx_key_new(KEYNID2TYPE(id
), 1);
63 ECerr(EC_F_ECX_KEY_OP
, ERR_R_MALLOC_FAILURE
);
68 if (op
== KEY_OP_PUBLIC
) {
69 memcpy(pubkey
, p
, plen
);
71 privkey
= ecx_key_allocate_privkey(key
);
72 if (privkey
== NULL
) {
73 ECerr(EC_F_ECX_KEY_OP
, ERR_R_MALLOC_FAILURE
);
76 if (op
== KEY_OP_KEYGEN
) {
77 if (RAND_priv_bytes(privkey
, KEYLENID(id
)) <= 0)
79 if (id
== EVP_PKEY_X25519
) {
81 privkey
[X25519_KEYLEN
- 1] &= 127;
82 privkey
[X25519_KEYLEN
- 1] |= 64;
83 } else if (id
== EVP_PKEY_X448
) {
85 privkey
[X448_KEYLEN
- 1] |= 128;
88 memcpy(privkey
, p
, KEYLENID(id
));
92 X25519_public_from_private(pubkey
, privkey
);
94 case EVP_PKEY_ED25519
:
95 ED25519_public_from_private(pubkey
, privkey
);
98 X448_public_from_private(pubkey
, privkey
);
102 * TODO(3.0): We set the library context to NULL for now. This will
105 ED448_public_from_private(NULL
, pubkey
, privkey
);
110 EVP_PKEY_assign(pkey
, id
, key
);
117 static int ecx_pub_encode(X509_PUBKEY
*pk
, const EVP_PKEY
*pkey
)
119 const ECX_KEY
*ecxkey
= pkey
->pkey
.ecx
;
122 if (ecxkey
== NULL
) {
123 ECerr(EC_F_ECX_PUB_ENCODE
, EC_R_INVALID_KEY
);
127 penc
= OPENSSL_memdup(ecxkey
->pubkey
, KEYLEN(pkey
));
129 ECerr(EC_F_ECX_PUB_ENCODE
, ERR_R_MALLOC_FAILURE
);
133 if (!X509_PUBKEY_set0_param(pk
, OBJ_nid2obj(pkey
->ameth
->pkey_id
),
134 V_ASN1_UNDEF
, NULL
, penc
, KEYLEN(pkey
))) {
136 ECerr(EC_F_ECX_PUB_ENCODE
, ERR_R_MALLOC_FAILURE
);
142 static int ecx_pub_decode(EVP_PKEY
*pkey
, X509_PUBKEY
*pubkey
)
144 const unsigned char *p
;
148 if (!X509_PUBKEY_get0_param(NULL
, &p
, &pklen
, &palg
, pubkey
))
150 return ecx_key_op(pkey
, pkey
->ameth
->pkey_id
, palg
, p
, pklen
,
154 static int ecx_pub_cmp(const EVP_PKEY
*a
, const EVP_PKEY
*b
)
156 const ECX_KEY
*akey
= a
->pkey
.ecx
;
157 const ECX_KEY
*bkey
= b
->pkey
.ecx
;
159 if (akey
== NULL
|| bkey
== NULL
)
162 return CRYPTO_memcmp(akey
->pubkey
, bkey
->pubkey
, KEYLEN(a
)) == 0;
165 static int ecx_priv_decode(EVP_PKEY
*pkey
, const PKCS8_PRIV_KEY_INFO
*p8
)
167 const unsigned char *p
;
169 ASN1_OCTET_STRING
*oct
= NULL
;
170 const X509_ALGOR
*palg
;
173 if (!PKCS8_pkey_get0(NULL
, &p
, &plen
, &palg
, p8
))
176 oct
= d2i_ASN1_OCTET_STRING(NULL
, &p
, plen
);
181 p
= ASN1_STRING_get0_data(oct
);
182 plen
= ASN1_STRING_length(oct
);
185 rv
= ecx_key_op(pkey
, pkey
->ameth
->pkey_id
, palg
, p
, plen
, KEY_OP_PRIVATE
);
186 ASN1_STRING_clear_free(oct
);
190 static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO
*p8
, const EVP_PKEY
*pkey
)
192 const ECX_KEY
*ecxkey
= pkey
->pkey
.ecx
;
193 ASN1_OCTET_STRING oct
;
194 unsigned char *penc
= NULL
;
197 if (ecxkey
== NULL
|| ecxkey
->privkey
== NULL
) {
198 ECerr(EC_F_ECX_PRIV_ENCODE
, EC_R_INVALID_PRIVATE_KEY
);
202 oct
.data
= ecxkey
->privkey
;
203 oct
.length
= KEYLEN(pkey
);
206 penclen
= i2d_ASN1_OCTET_STRING(&oct
, &penc
);
208 ECerr(EC_F_ECX_PRIV_ENCODE
, ERR_R_MALLOC_FAILURE
);
212 if (!PKCS8_pkey_set0(p8
, OBJ_nid2obj(pkey
->ameth
->pkey_id
), 0,
213 V_ASN1_UNDEF
, NULL
, penc
, penclen
)) {
214 OPENSSL_clear_free(penc
, penclen
);
215 ECerr(EC_F_ECX_PRIV_ENCODE
, ERR_R_MALLOC_FAILURE
);
222 static int ecx_size(const EVP_PKEY
*pkey
)
227 static int ecx_bits(const EVP_PKEY
*pkey
)
229 if (IS25519(pkey
->ameth
->pkey_id
)) {
231 } else if(ISX448(pkey
->ameth
->pkey_id
)) {
238 static int ecx_security_bits(const EVP_PKEY
*pkey
)
240 if (IS25519(pkey
->ameth
->pkey_id
)) {
241 return X25519_SECURITY_BITS
;
243 return X448_SECURITY_BITS
;
247 static void ecx_free(EVP_PKEY
*pkey
)
249 ecx_key_free(pkey
->pkey
.ecx
);
252 /* "parameters" are always equal */
253 static int ecx_cmp_parameters(const EVP_PKEY
*a
, const EVP_PKEY
*b
)
258 static int ecx_key_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
259 ASN1_PCTX
*ctx
, ecx_key_op_t op
)
261 const ECX_KEY
*ecxkey
= pkey
->pkey
.ecx
;
262 const char *nm
= OBJ_nid2ln(pkey
->ameth
->pkey_id
);
264 if (op
== KEY_OP_PRIVATE
) {
265 if (ecxkey
== NULL
|| ecxkey
->privkey
== NULL
) {
266 if (BIO_printf(bp
, "%*s<INVALID PRIVATE KEY>\n", indent
, "") <= 0)
270 if (BIO_printf(bp
, "%*s%s Private-Key:\n", indent
, "", nm
) <= 0)
272 if (BIO_printf(bp
, "%*spriv:\n", indent
, "") <= 0)
274 if (ASN1_buf_print(bp
, ecxkey
->privkey
, KEYLEN(pkey
),
278 if (ecxkey
== NULL
) {
279 if (BIO_printf(bp
, "%*s<INVALID PUBLIC KEY>\n", indent
, "") <= 0)
283 if (BIO_printf(bp
, "%*s%s Public-Key:\n", indent
, "", nm
) <= 0)
286 if (BIO_printf(bp
, "%*spub:\n", indent
, "") <= 0)
289 if (ASN1_buf_print(bp
, ecxkey
->pubkey
, KEYLEN(pkey
),
295 static int ecx_priv_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
298 return ecx_key_print(bp
, pkey
, indent
, ctx
, KEY_OP_PRIVATE
);
301 static int ecx_pub_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
304 return ecx_key_print(bp
, pkey
, indent
, ctx
, KEY_OP_PUBLIC
);
307 static int ecx_ctrl(EVP_PKEY
*pkey
, int op
, long arg1
, void *arg2
)
311 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT
:
312 return ecx_key_op(pkey
, pkey
->ameth
->pkey_id
, NULL
, arg2
, arg1
,
315 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT
:
316 if (pkey
->pkey
.ecx
!= NULL
) {
317 unsigned char **ppt
= arg2
;
319 *ppt
= OPENSSL_memdup(pkey
->pkey
.ecx
->pubkey
, KEYLEN(pkey
));
331 static int ecd_ctrl(EVP_PKEY
*pkey
, int op
, long arg1
, void *arg2
)
334 case ASN1_PKEY_CTRL_DEFAULT_MD_NID
:
335 /* We currently only support Pure EdDSA which takes no digest */
336 *(int *)arg2
= NID_undef
;
345 static int ecx_set_priv_key(EVP_PKEY
*pkey
, const unsigned char *priv
,
348 return ecx_key_op(pkey
, pkey
->ameth
->pkey_id
, NULL
, priv
, len
,
352 static int ecx_set_pub_key(EVP_PKEY
*pkey
, const unsigned char *pub
, size_t len
)
354 return ecx_key_op(pkey
, pkey
->ameth
->pkey_id
, NULL
, pub
, len
,
358 static int ecx_get_priv_key(const EVP_PKEY
*pkey
, unsigned char *priv
,
361 const ECX_KEY
*key
= pkey
->pkey
.ecx
;
364 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
369 || key
->privkey
== NULL
370 || *len
< (size_t)KEYLENID(pkey
->ameth
->pkey_id
))
373 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
374 memcpy(priv
, key
->privkey
, *len
);
379 static int ecx_get_pub_key(const EVP_PKEY
*pkey
, unsigned char *pub
,
382 const ECX_KEY
*key
= pkey
->pkey
.ecx
;
385 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
390 || *len
< (size_t)KEYLENID(pkey
->ameth
->pkey_id
))
393 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
394 memcpy(pub
, key
->pubkey
, *len
);
399 static size_t ecx_pkey_dirty_cnt(const EVP_PKEY
*pkey
)
402 * We provide no mechanism to "update" an ECX key once it has been set,
403 * therefore we do not have to maintain a dirty count.
408 static int ecx_pkey_export_to(const EVP_PKEY
*from
, void *to_keydata
,
409 EVP_KEYMGMT
*to_keymgmt
)
411 const ECX_KEY
*key
= from
->pkey
.ecx
;
413 OSSL_PARAM
*params
= NULL
;
417 OSSL_PARAM_BLD_init(&tmpl
);
419 /* A key must at least have a public part */
420 if (!OSSL_PARAM_BLD_push_octet_string(&tmpl
, OSSL_PKEY_PARAM_PUB_KEY
,
421 key
->pubkey
, key
->keylen
))
423 selection
|= OSSL_KEYMGMT_SELECT_PUBLIC_KEY
;
425 if (key
->privkey
!= NULL
) {
426 if (!OSSL_PARAM_BLD_push_octet_string(&tmpl
,
427 OSSL_PKEY_PARAM_PRIV_KEY
,
428 key
->privkey
, key
->keylen
))
430 selection
|= OSSL_KEYMGMT_SELECT_PRIVATE_KEY
;
433 params
= OSSL_PARAM_BLD_to_param(&tmpl
);
435 /* We export, the provider imports */
436 rv
= evp_keymgmt_import(to_keymgmt
, to_keydata
, selection
, params
);
439 OSSL_PARAM_BLD_free(params
);
443 static int ecx_generic_import_from(const OSSL_PARAM params
[], void *key
,
446 EVP_PKEY
*pkey
= key
;
447 ECX_KEY
*ecx
= ecx_key_new(KEYNID2TYPE(keytype
), 0);
450 ERR_raise(ERR_LIB_DH
, ERR_R_MALLOC_FAILURE
);
454 if (!ecx_key_fromdata(ecx
, params
, 1)
455 || !EVP_PKEY_assign(pkey
, keytype
, ecx
)) {
462 static int x25519_import_from(const OSSL_PARAM params
[], void *key
)
464 return ecx_generic_import_from(params
, key
, EVP_PKEY_X25519
);
467 const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth
= {
472 "OpenSSL X25519 algorithm",
513 static int x448_import_from(const OSSL_PARAM params
[], void *key
)
515 return ecx_generic_import_from(params
, key
, EVP_PKEY_X448
);
518 const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth
= {
523 "OpenSSL X448 algorithm",
564 static int ecd_size25519(const EVP_PKEY
*pkey
)
566 return ED25519_SIGSIZE
;
569 static int ecd_size448(const EVP_PKEY
*pkey
)
571 return ED448_SIGSIZE
;
574 static int ecd_item_verify(EVP_MD_CTX
*ctx
, const ASN1_ITEM
*it
, void *asn
,
575 X509_ALGOR
*sigalg
, ASN1_BIT_STRING
*str
,
578 const ASN1_OBJECT
*obj
;
582 /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
583 X509_ALGOR_get0(&obj
, &ptype
, NULL
, sigalg
);
584 nid
= OBJ_obj2nid(obj
);
585 if ((nid
!= NID_ED25519
&& nid
!= NID_ED448
) || ptype
!= V_ASN1_UNDEF
) {
586 ECerr(EC_F_ECD_ITEM_VERIFY
, EC_R_INVALID_ENCODING
);
590 if (!EVP_DigestVerifyInit(ctx
, NULL
, NULL
, NULL
, pkey
))
596 static int ecd_item_sign25519(EVP_MD_CTX
*ctx
, const ASN1_ITEM
*it
, void *asn
,
597 X509_ALGOR
*alg1
, X509_ALGOR
*alg2
,
598 ASN1_BIT_STRING
*str
)
600 /* Set algorithms identifiers */
601 X509_ALGOR_set0(alg1
, OBJ_nid2obj(NID_ED25519
), V_ASN1_UNDEF
, NULL
);
603 X509_ALGOR_set0(alg2
, OBJ_nid2obj(NID_ED25519
), V_ASN1_UNDEF
, NULL
);
604 /* Algorithm identifiers set: carry on as normal */
608 static int ecd_sig_info_set25519(X509_SIG_INFO
*siginf
, const X509_ALGOR
*alg
,
609 const ASN1_STRING
*sig
)
611 X509_SIG_INFO_set(siginf
, NID_undef
, NID_ED25519
, X25519_SECURITY_BITS
,
616 static int ecd_item_sign448(EVP_MD_CTX
*ctx
, const ASN1_ITEM
*it
, void *asn
,
617 X509_ALGOR
*alg1
, X509_ALGOR
*alg2
,
618 ASN1_BIT_STRING
*str
)
620 /* Set algorithm identifier */
621 X509_ALGOR_set0(alg1
, OBJ_nid2obj(NID_ED448
), V_ASN1_UNDEF
, NULL
);
623 X509_ALGOR_set0(alg2
, OBJ_nid2obj(NID_ED448
), V_ASN1_UNDEF
, NULL
);
624 /* Algorithm identifier set: carry on as normal */
628 static int ecd_sig_info_set448(X509_SIG_INFO
*siginf
, const X509_ALGOR
*alg
,
629 const ASN1_STRING
*sig
)
631 X509_SIG_INFO_set(siginf
, NID_undef
, NID_ED448
, X448_SECURITY_BITS
,
636 static int ed25519_import_from(const OSSL_PARAM params
[], void *key
)
638 return ecx_generic_import_from(params
, key
, EVP_PKEY_ED25519
);
641 const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth
= {
646 "OpenSSL ED25519 algorithm",
671 ecd_sig_info_set25519
,
686 static int ed448_import_from(const OSSL_PARAM params
[], void *key
)
688 return ecx_generic_import_from(params
, key
, EVP_PKEY_ED448
);
691 const EVP_PKEY_ASN1_METHOD ed448_asn1_meth
= {
696 "OpenSSL ED448 algorithm",
736 static int pkey_ecx_keygen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
738 return ecx_key_op(pkey
, ctx
->pmeth
->pkey_id
, NULL
, NULL
, 0, KEY_OP_KEYGEN
);
741 static int validate_ecx_derive(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
743 const unsigned char **privkey
,
744 const unsigned char **pubkey
)
746 const ECX_KEY
*ecxkey
, *peerkey
;
748 if (ctx
->pkey
== NULL
|| ctx
->peerkey
== NULL
) {
749 ECerr(EC_F_VALIDATE_ECX_DERIVE
, EC_R_KEYS_NOT_SET
);
752 ecxkey
= ctx
->pkey
->pkey
.ecx
;
753 peerkey
= ctx
->peerkey
->pkey
.ecx
;
754 if (ecxkey
== NULL
|| ecxkey
->privkey
== NULL
) {
755 ECerr(EC_F_VALIDATE_ECX_DERIVE
, EC_R_INVALID_PRIVATE_KEY
);
758 if (peerkey
== NULL
) {
759 ECerr(EC_F_VALIDATE_ECX_DERIVE
, EC_R_INVALID_PEER_KEY
);
762 *privkey
= ecxkey
->privkey
;
763 *pubkey
= peerkey
->pubkey
;
768 static int pkey_ecx_derive25519(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
771 const unsigned char *privkey
, *pubkey
;
773 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
)
775 && X25519(key
, privkey
, pubkey
) == 0))
777 *keylen
= X25519_KEYLEN
;
781 static int pkey_ecx_derive448(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
784 const unsigned char *privkey
, *pubkey
;
786 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
)
788 && X448(key
, privkey
, pubkey
) == 0))
790 *keylen
= X448_KEYLEN
;
794 static int pkey_ecx_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
796 /* Only need to handle peer key for derivation */
797 if (type
== EVP_PKEY_CTRL_PEER_KEY
)
802 static const EVP_PKEY_METHOD ecx25519_pkey_meth
= {
806 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
807 pkey_ecx_derive25519
,
812 static const EVP_PKEY_METHOD ecx448_pkey_meth
= {
816 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
822 static int pkey_ecd_digestsign25519(EVP_MD_CTX
*ctx
, unsigned char *sig
,
823 size_t *siglen
, const unsigned char *tbs
,
826 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
829 *siglen
= ED25519_SIGSIZE
;
832 if (*siglen
< ED25519_SIGSIZE
) {
833 ECerr(EC_F_PKEY_ECD_DIGESTSIGN25519
, EC_R_BUFFER_TOO_SMALL
);
837 if (ED25519_sign(sig
, tbs
, tbslen
, edkey
->pubkey
, edkey
->privkey
) == 0)
839 *siglen
= ED25519_SIGSIZE
;
843 static int pkey_ecd_digestsign448(EVP_MD_CTX
*ctx
, unsigned char *sig
,
844 size_t *siglen
, const unsigned char *tbs
,
847 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
850 *siglen
= ED448_SIGSIZE
;
853 if (*siglen
< ED448_SIGSIZE
) {
854 ECerr(EC_F_PKEY_ECD_DIGESTSIGN448
, EC_R_BUFFER_TOO_SMALL
);
859 * TODO(3.0): We use NULL for the library context for now. Will need to
862 if (ED448_sign(NULL
, sig
, tbs
, tbslen
, edkey
->pubkey
, edkey
->privkey
,
865 *siglen
= ED448_SIGSIZE
;
869 static int pkey_ecd_digestverify25519(EVP_MD_CTX
*ctx
, const unsigned char *sig
,
870 size_t siglen
, const unsigned char *tbs
,
873 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
875 if (siglen
!= ED25519_SIGSIZE
)
878 return ED25519_verify(tbs
, tbslen
, sig
, edkey
->pubkey
);
881 static int pkey_ecd_digestverify448(EVP_MD_CTX
*ctx
, const unsigned char *sig
,
882 size_t siglen
, const unsigned char *tbs
,
885 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
887 if (siglen
!= ED448_SIGSIZE
)
891 * TODO(3.0): We send NULL for the OPENSSL_CTX for now. This will need to
894 return ED448_verify(NULL
, tbs
, tbslen
, sig
, edkey
->pubkey
, NULL
, 0);
897 static int pkey_ecd_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
900 case EVP_PKEY_CTRL_MD
:
901 /* Only NULL allowed as digest */
902 if (p2
== NULL
|| (const EVP_MD
*)p2
== EVP_md_null())
904 ECerr(EC_F_PKEY_ECD_CTRL
, EC_R_INVALID_DIGEST_TYPE
);
907 case EVP_PKEY_CTRL_DIGESTINIT
:
913 static const EVP_PKEY_METHOD ed25519_pkey_meth
= {
914 EVP_PKEY_ED25519
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
917 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
920 pkey_ecd_digestsign25519
,
921 pkey_ecd_digestverify25519
924 static const EVP_PKEY_METHOD ed448_pkey_meth
= {
925 EVP_PKEY_ED448
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
928 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
931 pkey_ecd_digestsign448
,
932 pkey_ecd_digestverify448
936 # include "s390x_arch.h"
937 # include "internal/constant_time.h"
939 static void s390x_x25519_mod_p(unsigned char u
[32])
941 unsigned char u_red
[32];
945 memcpy(u_red
, u
, sizeof(u_red
));
947 c
+= (unsigned int)u_red
[31] + 19;
948 u_red
[31] = (unsigned char)c
;
951 for (i
= 30; i
>= 0; i
--) {
952 c
+= (unsigned int)u_red
[i
];
953 u_red
[i
] = (unsigned char)c
;
957 c
= (u_red
[0] & 0x80) >> 7;
959 constant_time_cond_swap_buff(0 - (unsigned char)c
,
960 u
, u_red
, sizeof(u_red
));
963 static void s390x_x448_mod_p(unsigned char u
[56])
965 unsigned char u_red
[56];
969 memcpy(u_red
, u
, sizeof(u_red
));
971 c
+= (unsigned int)u_red
[55] + 1;
972 u_red
[55] = (unsigned char)c
;
975 for (i
= 54; i
>= 28; i
--) {
976 c
+= (unsigned int)u_red
[i
];
977 u_red
[i
] = (unsigned char)c
;
981 c
+= (unsigned int)u_red
[27] + 1;
982 u_red
[27] = (unsigned char)c
;
985 for (i
= 26; i
>= 0; i
--) {
986 c
+= (unsigned int)u_red
[i
];
987 u_red
[i
] = (unsigned char)c
;
991 constant_time_cond_swap_buff(0 - (unsigned char)c
,
992 u
, u_red
, sizeof(u_red
));
995 int s390x_x25519_mul(unsigned char u_dst
[32],
996 const unsigned char u_src
[32],
997 const unsigned char d_src
[32])
1001 unsigned char u_dst
[32];
1002 unsigned char u_src
[32];
1003 unsigned char d_src
[32];
1005 unsigned long long buff
[512];
1009 memset(¶m
, 0, sizeof(param
));
1011 s390x_flip_endian32(param
.x25519
.u_src
, u_src
);
1012 param
.x25519
.u_src
[0] &= 0x7f;
1013 s390x_x25519_mod_p(param
.x25519
.u_src
);
1015 s390x_flip_endian32(param
.x25519
.d_src
, d_src
);
1016 param
.x25519
.d_src
[31] &= 248;
1017 param
.x25519
.d_src
[0] &= 127;
1018 param
.x25519
.d_src
[0] |= 64;
1020 rc
= s390x_pcc(S390X_SCALAR_MULTIPLY_X25519
, ¶m
.x25519
) ? 0 : 1;
1022 s390x_flip_endian32(u_dst
, param
.x25519
.u_dst
);
1024 OPENSSL_cleanse(param
.x25519
.d_src
, sizeof(param
.x25519
.d_src
));
1028 int s390x_x448_mul(unsigned char u_dst
[56],
1029 const unsigned char u_src
[56],
1030 const unsigned char d_src
[56])
1034 unsigned char u_dst
[64];
1035 unsigned char u_src
[64];
1036 unsigned char d_src
[64];
1038 unsigned long long buff
[512];
1042 memset(¶m
, 0, sizeof(param
));
1044 memcpy(param
.x448
.u_src
, u_src
, 56);
1045 memcpy(param
.x448
.d_src
, d_src
, 56);
1047 s390x_flip_endian64(param
.x448
.u_src
, param
.x448
.u_src
);
1048 s390x_x448_mod_p(param
.x448
.u_src
+ 8);
1050 s390x_flip_endian64(param
.x448
.d_src
, param
.x448
.d_src
);
1051 param
.x448
.d_src
[63] &= 252;
1052 param
.x448
.d_src
[8] |= 128;
1054 rc
= s390x_pcc(S390X_SCALAR_MULTIPLY_X448
, ¶m
.x448
) ? 0 : 1;
1056 s390x_flip_endian64(param
.x448
.u_dst
, param
.x448
.u_dst
);
1057 memcpy(u_dst
, param
.x448
.u_dst
, 56);
1060 OPENSSL_cleanse(param
.x448
.d_src
, sizeof(param
.x448
.d_src
));
1064 static int s390x_ed25519_mul(unsigned char x_dst
[32],
1065 unsigned char y_dst
[32],
1066 const unsigned char x_src
[32],
1067 const unsigned char y_src
[32],
1068 const unsigned char d_src
[32])
1072 unsigned char x_dst
[32];
1073 unsigned char y_dst
[32];
1074 unsigned char x_src
[32];
1075 unsigned char y_src
[32];
1076 unsigned char d_src
[32];
1078 unsigned long long buff
[512];
1082 memset(¶m
, 0, sizeof(param
));
1084 s390x_flip_endian32(param
.ed25519
.x_src
, x_src
);
1085 s390x_flip_endian32(param
.ed25519
.y_src
, y_src
);
1086 s390x_flip_endian32(param
.ed25519
.d_src
, d_src
);
1088 rc
= s390x_pcc(S390X_SCALAR_MULTIPLY_ED25519
, ¶m
.ed25519
) ? 0 : 1;
1090 s390x_flip_endian32(x_dst
, param
.ed25519
.x_dst
);
1091 s390x_flip_endian32(y_dst
, param
.ed25519
.y_dst
);
1094 OPENSSL_cleanse(param
.ed25519
.d_src
, sizeof(param
.ed25519
.d_src
));
1098 static int s390x_ed448_mul(unsigned char x_dst
[57],
1099 unsigned char y_dst
[57],
1100 const unsigned char x_src
[57],
1101 const unsigned char y_src
[57],
1102 const unsigned char d_src
[57])
1106 unsigned char x_dst
[64];
1107 unsigned char y_dst
[64];
1108 unsigned char x_src
[64];
1109 unsigned char y_src
[64];
1110 unsigned char d_src
[64];
1112 unsigned long long buff
[512];
1116 memset(¶m
, 0, sizeof(param
));
1118 memcpy(param
.ed448
.x_src
, x_src
, 57);
1119 memcpy(param
.ed448
.y_src
, y_src
, 57);
1120 memcpy(param
.ed448
.d_src
, d_src
, 57);
1121 s390x_flip_endian64(param
.ed448
.x_src
, param
.ed448
.x_src
);
1122 s390x_flip_endian64(param
.ed448
.y_src
, param
.ed448
.y_src
);
1123 s390x_flip_endian64(param
.ed448
.d_src
, param
.ed448
.d_src
);
1125 rc
= s390x_pcc(S390X_SCALAR_MULTIPLY_ED448
, ¶m
.ed448
) ? 0 : 1;
1127 s390x_flip_endian64(param
.ed448
.x_dst
, param
.ed448
.x_dst
);
1128 s390x_flip_endian64(param
.ed448
.y_dst
, param
.ed448
.y_dst
);
1129 memcpy(x_dst
, param
.ed448
.x_dst
, 57);
1130 memcpy(y_dst
, param
.ed448
.y_dst
, 57);
1133 OPENSSL_cleanse(param
.ed448
.d_src
, sizeof(param
.ed448
.d_src
));
1137 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
1139 static const unsigned char generator
[] = {
1140 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1144 ECX_KEY
*key
= ecx_key_new(ECX_KEY_TYPE_X25519
, 1);
1145 unsigned char *privkey
= NULL
, *pubkey
;
1148 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN25519
, ERR_R_MALLOC_FAILURE
);
1152 pubkey
= key
->pubkey
;
1154 privkey
= ecx_key_allocate_privkey(key
);
1155 if (privkey
== NULL
) {
1156 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN25519
, ERR_R_MALLOC_FAILURE
);
1160 if (RAND_priv_bytes(privkey
, X25519_KEYLEN
) <= 0)
1167 if (s390x_x25519_mul(pubkey
, generator
, privkey
) != 1)
1170 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
1177 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
1179 static const unsigned char generator
[] = {
1180 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1186 ECX_KEY
*key
= ecx_key_new(ECX_KEY_TYPE_X448
, 1);
1187 unsigned char *privkey
= NULL
, *pubkey
;
1190 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN448
, ERR_R_MALLOC_FAILURE
);
1194 pubkey
= key
->pubkey
;
1196 privkey
= ecx_key_allocate_privkey(key
);
1197 if (privkey
== NULL
) {
1198 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN448
, ERR_R_MALLOC_FAILURE
);
1202 if (RAND_priv_bytes(privkey
, X448_KEYLEN
) <= 0)
1208 if (s390x_x448_mul(pubkey
, generator
, privkey
) != 1)
1211 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
1218 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
1220 static const unsigned char generator_x
[] = {
1221 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1222 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1223 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1225 static const unsigned char generator_y
[] = {
1226 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1227 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1228 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1230 unsigned char x_dst
[32], buff
[SHA512_DIGEST_LENGTH
];
1231 ECX_KEY
*key
= ecx_key_new(ECX_KEY_TYPE_ED25519
, 1);
1232 unsigned char *privkey
= NULL
, *pubkey
;
1236 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN25519
, ERR_R_MALLOC_FAILURE
);
1240 pubkey
= key
->pubkey
;
1242 privkey
= ecx_key_allocate_privkey(key
);
1243 if (privkey
== NULL
) {
1244 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN25519
, ERR_R_MALLOC_FAILURE
);
1248 if (RAND_priv_bytes(privkey
, ED25519_KEYLEN
) <= 0)
1251 if (!EVP_Digest(privkey
, 32, buff
, &sz
, EVP_sha512(), NULL
))
1258 if (s390x_ed25519_mul(x_dst
, pubkey
,
1259 generator_x
, generator_y
, buff
) != 1)
1262 pubkey
[31] |= ((x_dst
[0] & 0x01) << 7);
1264 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
1271 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
1273 static const unsigned char generator_x
[] = {
1274 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1275 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1276 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1277 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1278 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1280 static const unsigned char generator_y
[] = {
1281 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1282 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1283 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1284 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1285 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1287 unsigned char x_dst
[57], buff
[114];
1288 ECX_KEY
*key
= ecx_key_new(ECX_KEY_TYPE_ED448
, 1);
1289 unsigned char *privkey
= NULL
, *pubkey
;
1290 EVP_MD_CTX
*hashctx
= NULL
;
1293 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN448
, ERR_R_MALLOC_FAILURE
);
1297 pubkey
= key
->pubkey
;
1299 privkey
= ecx_key_allocate_privkey(key
);
1300 if (privkey
== NULL
) {
1301 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN448
, ERR_R_MALLOC_FAILURE
);
1305 if (RAND_priv_bytes(privkey
, ED448_KEYLEN
) <= 0)
1308 hashctx
= EVP_MD_CTX_new();
1309 if (hashctx
== NULL
)
1311 if (EVP_DigestInit_ex(hashctx
, EVP_shake256(), NULL
) != 1)
1313 if (EVP_DigestUpdate(hashctx
, privkey
, 57) != 1)
1315 if (EVP_DigestFinalXOF(hashctx
, buff
, sizeof(buff
)) != 1)
1322 if (s390x_ed448_mul(x_dst
, pubkey
,
1323 generator_x
, generator_y
, buff
) != 1)
1326 pubkey
[56] |= ((x_dst
[0] & 0x01) << 7);
1328 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
1329 EVP_MD_CTX_free(hashctx
);
1333 EVP_MD_CTX_free(hashctx
);
1337 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
1340 const unsigned char *privkey
, *pubkey
;
1342 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
))
1346 return s390x_x25519_mul(key
, pubkey
, privkey
);
1348 *keylen
= X25519_KEYLEN
;
1352 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
1355 const unsigned char *privkey
, *pubkey
;
1357 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
))
1361 return s390x_x448_mul(key
, pubkey
, privkey
);
1363 *keylen
= X448_KEYLEN
;
1367 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX
*ctx
,
1368 unsigned char *sig
, size_t *siglen
,
1369 const unsigned char *tbs
,
1374 unsigned char sig
[64];
1375 unsigned char priv
[32];
1377 unsigned long long buff
[512];
1379 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
1383 *siglen
= ED25519_SIGSIZE
;
1387 if (*siglen
< ED25519_SIGSIZE
) {
1388 ECerr(EC_F_S390X_PKEY_ECD_DIGESTSIGN25519
, EC_R_BUFFER_TOO_SMALL
);
1392 memset(¶m
, 0, sizeof(param
));
1393 memcpy(param
.ed25519
.priv
, edkey
->privkey
, sizeof(param
.ed25519
.priv
));
1395 rc
= s390x_kdsa(S390X_EDDSA_SIGN_ED25519
, ¶m
.ed25519
, tbs
, tbslen
);
1396 OPENSSL_cleanse(param
.ed25519
.priv
, sizeof(param
.ed25519
.priv
));
1400 s390x_flip_endian32(sig
, param
.ed25519
.sig
);
1401 s390x_flip_endian32(sig
+ 32, param
.ed25519
.sig
+ 32);
1403 *siglen
= ED25519_SIGSIZE
;
1407 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX
*ctx
,
1408 unsigned char *sig
, size_t *siglen
,
1409 const unsigned char *tbs
,
1414 unsigned char sig
[128];
1415 unsigned char priv
[64];
1417 unsigned long long buff
[512];
1419 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
1423 *siglen
= ED448_SIGSIZE
;
1427 if (*siglen
< ED448_SIGSIZE
) {
1428 ECerr(EC_F_S390X_PKEY_ECD_DIGESTSIGN448
, EC_R_BUFFER_TOO_SMALL
);
1432 memset(¶m
, 0, sizeof(param
));
1433 memcpy(param
.ed448
.priv
+ 64 - 57, edkey
->privkey
, 57);
1435 rc
= s390x_kdsa(S390X_EDDSA_SIGN_ED448
, ¶m
.ed448
, tbs
, tbslen
);
1436 OPENSSL_cleanse(param
.ed448
.priv
, sizeof(param
.ed448
.priv
));
1440 s390x_flip_endian64(param
.ed448
.sig
, param
.ed448
.sig
);
1441 s390x_flip_endian64(param
.ed448
.sig
+ 64, param
.ed448
.sig
+ 64);
1442 memcpy(sig
, param
.ed448
.sig
, 57);
1443 memcpy(sig
+ 57, param
.ed448
.sig
+ 64, 57);
1445 *siglen
= ED448_SIGSIZE
;
1449 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX
*ctx
,
1450 const unsigned char *sig
,
1452 const unsigned char *tbs
,
1457 unsigned char sig
[64];
1458 unsigned char pub
[32];
1460 unsigned long long buff
[512];
1462 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
1464 if (siglen
!= ED25519_SIGSIZE
)
1467 memset(¶m
, 0, sizeof(param
));
1468 s390x_flip_endian32(param
.ed25519
.sig
, sig
);
1469 s390x_flip_endian32(param
.ed25519
.sig
+ 32, sig
+ 32);
1470 s390x_flip_endian32(param
.ed25519
.pub
, edkey
->pubkey
);
1472 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519
,
1473 ¶m
.ed25519
, tbs
, tbslen
) == 0 ? 1 : 0;
1476 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX
*ctx
,
1477 const unsigned char *sig
,
1479 const unsigned char *tbs
,
1484 unsigned char sig
[128];
1485 unsigned char pub
[64];
1487 unsigned long long buff
[512];
1489 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
1491 if (siglen
!= ED448_SIGSIZE
)
1494 memset(¶m
, 0, sizeof(param
));
1495 memcpy(param
.ed448
.sig
, sig
, 57);
1496 s390x_flip_endian64(param
.ed448
.sig
, param
.ed448
.sig
);
1497 memcpy(param
.ed448
.sig
+ 64, sig
+ 57, 57);
1498 s390x_flip_endian64(param
.ed448
.sig
+ 64, param
.ed448
.sig
+ 64);
1499 memcpy(param
.ed448
.pub
, edkey
->pubkey
, 57);
1500 s390x_flip_endian64(param
.ed448
.pub
, param
.ed448
.pub
);
1502 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448
,
1503 ¶m
.ed448
, tbs
, tbslen
) == 0 ? 1 : 0;
1506 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth
= {
1508 0, 0, 0, 0, 0, 0, 0,
1509 s390x_pkey_ecx_keygen25519
,
1510 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1511 s390x_pkey_ecx_derive25519
,
1516 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth
= {
1518 0, 0, 0, 0, 0, 0, 0,
1519 s390x_pkey_ecx_keygen448
,
1520 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1521 s390x_pkey_ecx_derive448
,
1525 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth
= {
1526 EVP_PKEY_ED25519
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
1528 s390x_pkey_ecd_keygen25519
,
1529 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1532 s390x_pkey_ecd_digestsign25519
,
1533 s390x_pkey_ecd_digestverify25519
1536 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth
= {
1537 EVP_PKEY_ED448
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
1539 s390x_pkey_ecd_keygen448
,
1540 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1543 s390x_pkey_ecd_digestsign448
,
1544 s390x_pkey_ecd_digestverify448
1548 const EVP_PKEY_METHOD
*ecx25519_pkey_method(void)
1551 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519
))
1552 return &ecx25519_s390x_pkey_meth
;
1554 return &ecx25519_pkey_meth
;
1557 const EVP_PKEY_METHOD
*ecx448_pkey_method(void)
1560 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448
))
1561 return &ecx448_s390x_pkey_meth
;
1563 return &ecx448_pkey_meth
;
1566 const EVP_PKEY_METHOD
*ed25519_pkey_method(void)
1569 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519
)
1570 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519
)
1571 && OPENSSL_s390xcap_P
.kdsa
[0]
1572 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519
))
1573 return &ed25519_s390x_pkey_meth
;
1575 return &ed25519_pkey_meth
;
1578 const EVP_PKEY_METHOD
*ed448_pkey_method(void)
1581 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448
)
1582 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448
)
1583 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448
))
1584 return &ed448_s390x_pkey_meth
;
1586 return &ed448_pkey_meth
;