2 * Copyright 2006-2021 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 <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"
28 #include "curve448/curve448_local.h"
29 #include "ecx_backend.h"
31 static int ecx_pub_encode(X509_PUBKEY
*pk
, const EVP_PKEY
*pkey
)
33 const ECX_KEY
*ecxkey
= pkey
->pkey
.ecx
;
37 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_KEY
);
41 penc
= OPENSSL_memdup(ecxkey
->pubkey
, KEYLEN(pkey
));
43 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
47 if (!X509_PUBKEY_set0_param(pk
, OBJ_nid2obj(pkey
->ameth
->pkey_id
),
48 V_ASN1_UNDEF
, NULL
, penc
, KEYLEN(pkey
))) {
50 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
56 static int ecx_pub_decode(EVP_PKEY
*pkey
, const X509_PUBKEY
*pubkey
)
58 const unsigned char *p
;
64 if (!X509_PUBKEY_get0_param(NULL
, &p
, &pklen
, &palg
, pubkey
))
66 ecx
= ossl_ecx_key_op(palg
, p
, pklen
, pkey
->ameth
->pkey_id
,
67 KEY_OP_PUBLIC
, NULL
, NULL
);
70 EVP_PKEY_assign(pkey
, pkey
->ameth
->pkey_id
, ecx
);
75 static int ecx_pub_cmp(const EVP_PKEY
*a
, const EVP_PKEY
*b
)
77 const ECX_KEY
*akey
= a
->pkey
.ecx
;
78 const ECX_KEY
*bkey
= b
->pkey
.ecx
;
80 if (akey
== NULL
|| bkey
== NULL
)
83 return CRYPTO_memcmp(akey
->pubkey
, bkey
->pubkey
, KEYLEN(a
)) == 0;
86 static int ecx_priv_decode_ex(EVP_PKEY
*pkey
, const PKCS8_PRIV_KEY_INFO
*p8
,
87 OSSL_LIB_CTX
*libctx
, const char *propq
)
90 ECX_KEY
*ecx
= ossl_ecx_key_from_pkcs8(p8
, libctx
, propq
);
94 EVP_PKEY_assign(pkey
, pkey
->ameth
->pkey_id
, ecx
);
100 static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO
*p8
, const EVP_PKEY
*pkey
)
102 const ECX_KEY
*ecxkey
= pkey
->pkey
.ecx
;
103 ASN1_OCTET_STRING oct
;
104 unsigned char *penc
= NULL
;
107 if (ecxkey
== NULL
|| ecxkey
->privkey
== NULL
) {
108 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_PRIVATE_KEY
);
112 oct
.data
= ecxkey
->privkey
;
113 oct
.length
= KEYLEN(pkey
);
116 penclen
= i2d_ASN1_OCTET_STRING(&oct
, &penc
);
118 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
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
);
132 static int ecx_size(const EVP_PKEY
*pkey
)
137 static int ecx_bits(const EVP_PKEY
*pkey
)
139 if (IS25519(pkey
->ameth
->pkey_id
)) {
141 } else if(ISX448(pkey
->ameth
->pkey_id
)) {
148 static int ecx_security_bits(const EVP_PKEY
*pkey
)
150 if (IS25519(pkey
->ameth
->pkey_id
)) {
151 return X25519_SECURITY_BITS
;
153 return X448_SECURITY_BITS
;
157 static void ecx_free(EVP_PKEY
*pkey
)
159 ossl_ecx_key_free(pkey
->pkey
.ecx
);
162 /* "parameters" are always equal */
163 static int ecx_cmp_parameters(const EVP_PKEY
*a
, const EVP_PKEY
*b
)
168 static int ecx_key_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
169 ASN1_PCTX
*ctx
, ecx_key_op_t op
)
171 const ECX_KEY
*ecxkey
= pkey
->pkey
.ecx
;
172 const char *nm
= OBJ_nid2ln(pkey
->ameth
->pkey_id
);
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)
180 if (BIO_printf(bp
, "%*s%s Private-Key:\n", indent
, "", nm
) <= 0)
182 if (BIO_printf(bp
, "%*spriv:\n", indent
, "") <= 0)
184 if (ASN1_buf_print(bp
, ecxkey
->privkey
, KEYLEN(pkey
),
188 if (ecxkey
== NULL
) {
189 if (BIO_printf(bp
, "%*s<INVALID PUBLIC KEY>\n", indent
, "") <= 0)
193 if (BIO_printf(bp
, "%*s%s Public-Key:\n", indent
, "", nm
) <= 0)
196 if (BIO_printf(bp
, "%*spub:\n", indent
, "") <= 0)
199 if (ASN1_buf_print(bp
, ecxkey
->pubkey
, KEYLEN(pkey
),
205 static int ecx_priv_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
208 return ecx_key_print(bp
, pkey
, indent
, ctx
, KEY_OP_PRIVATE
);
211 static int ecx_pub_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
214 return ecx_key_print(bp
, pkey
, indent
, ctx
, KEY_OP_PUBLIC
);
217 static int ecx_ctrl(EVP_PKEY
*pkey
, int op
, long arg1
, void *arg2
)
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
);
226 EVP_PKEY_assign(pkey
, pkey
->ameth
->pkey_id
, ecx
);
231 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT
:
232 if (pkey
->pkey
.ecx
!= NULL
) {
233 unsigned char **ppt
= arg2
;
235 *ppt
= OPENSSL_memdup(pkey
->pkey
.ecx
->pubkey
, KEYLEN(pkey
));
247 static int ecd_ctrl(EVP_PKEY
*pkey
, int op
, long arg1
, void *arg2
)
250 case ASN1_PKEY_CTRL_DEFAULT_MD_NID
:
251 /* We currently only support Pure EdDSA which takes no digest */
252 *(int *)arg2
= NID_undef
;
261 static int ecx_set_priv_key(EVP_PKEY
*pkey
, const unsigned char *priv
,
264 OSSL_LIB_CTX
*libctx
= NULL
;
267 if (pkey
->keymgmt
!= NULL
)
268 libctx
= ossl_provider_libctx(EVP_KEYMGMT_provider(pkey
->keymgmt
));
270 ecx
= ossl_ecx_key_op(NULL
, priv
, len
, pkey
->ameth
->pkey_id
,
271 KEY_OP_PRIVATE
, libctx
, NULL
);
274 EVP_PKEY_assign(pkey
, pkey
->ameth
->pkey_id
, ecx
);
280 static int ecx_set_pub_key(EVP_PKEY
*pkey
, const unsigned char *pub
, size_t len
)
282 OSSL_LIB_CTX
*libctx
= NULL
;
285 if (pkey
->keymgmt
!= NULL
)
286 libctx
= ossl_provider_libctx(EVP_KEYMGMT_provider(pkey
->keymgmt
));
288 ecx
= ossl_ecx_key_op(NULL
, pub
, len
, pkey
->ameth
->pkey_id
,
289 KEY_OP_PUBLIC
, libctx
, NULL
);
292 EVP_PKEY_assign(pkey
, pkey
->ameth
->pkey_id
, ecx
);
298 static int ecx_get_priv_key(const EVP_PKEY
*pkey
, unsigned char *priv
,
301 const ECX_KEY
*key
= pkey
->pkey
.ecx
;
304 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
309 || key
->privkey
== NULL
310 || *len
< (size_t)KEYLENID(pkey
->ameth
->pkey_id
))
313 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
314 memcpy(priv
, key
->privkey
, *len
);
319 static int ecx_get_pub_key(const EVP_PKEY
*pkey
, unsigned char *pub
,
322 const ECX_KEY
*key
= pkey
->pkey
.ecx
;
325 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
330 || *len
< (size_t)KEYLENID(pkey
->ameth
->pkey_id
))
333 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
334 memcpy(pub
, key
->pubkey
, *len
);
339 static size_t ecx_pkey_dirty_cnt(const EVP_PKEY
*pkey
)
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.
348 static int ecx_pkey_export_to(const EVP_PKEY
*from
, void *to_keydata
,
349 EVP_KEYMGMT
*to_keymgmt
, OSSL_LIB_CTX
*libctx
,
352 const ECX_KEY
*key
= from
->pkey
.ecx
;
353 OSSL_PARAM_BLD
*tmpl
= OSSL_PARAM_BLD_new();
354 OSSL_PARAM
*params
= NULL
;
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
))
365 selection
|= OSSL_KEYMGMT_SELECT_PUBLIC_KEY
;
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
))
372 selection
|= OSSL_KEYMGMT_SELECT_PRIVATE_KEY
;
375 params
= OSSL_PARAM_BLD_to_param(tmpl
);
377 /* We export, the provider imports */
378 rv
= evp_keymgmt_import(to_keymgmt
, to_keydata
, selection
, params
);
381 OSSL_PARAM_BLD_free(tmpl
);
382 OSSL_PARAM_BLD_free_params(params
);
386 static int ecx_generic_import_from(const OSSL_PARAM params
[], void *vpctx
,
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,
395 ERR_raise(ERR_LIB_DH
, ERR_R_MALLOC_FAILURE
);
399 if (!ossl_ecx_key_fromdata(ecx
, params
, 1)
400 || !EVP_PKEY_assign(pkey
, keytype
, ecx
)) {
401 ossl_ecx_key_free(ecx
);
407 static int ecx_pkey_copy(EVP_PKEY
*to
, EVP_PKEY
*from
)
409 ECX_KEY
*ecx
= from
->pkey
.ecx
;
412 /* We can do just up-ref as ECX keys are immutable */
413 if (ecx
!= NULL
&& !ossl_ecx_key_up_ref(ecx
))
416 ret
= EVP_PKEY_assign(to
, from
->type
, ecx
);
418 ossl_ecx_key_free(ecx
);
422 static int x25519_import_from(const OSSL_PARAM params
[], void *vpctx
)
424 return ecx_generic_import_from(params
, vpctx
, EVP_PKEY_X25519
);
427 const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth
= {
432 "OpenSSL X25519 algorithm",
476 static int x448_import_from(const OSSL_PARAM params
[], void *vpctx
)
478 return ecx_generic_import_from(params
, vpctx
, EVP_PKEY_X448
);
481 const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth
= {
486 "OpenSSL X448 algorithm",
530 static int ecd_size25519(const EVP_PKEY
*pkey
)
532 return ED25519_SIGSIZE
;
535 static int ecd_size448(const EVP_PKEY
*pkey
)
537 return ED448_SIGSIZE
;
540 static int ecd_item_verify(EVP_MD_CTX
*ctx
, const ASN1_ITEM
*it
,
541 const void *asn
, const X509_ALGOR
*sigalg
,
542 const ASN1_BIT_STRING
*str
, EVP_PKEY
*pkey
)
544 const ASN1_OBJECT
*obj
;
548 /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
549 X509_ALGOR_get0(&obj
, &ptype
, NULL
, sigalg
);
550 nid
= OBJ_obj2nid(obj
);
551 if ((nid
!= NID_ED25519
&& nid
!= NID_ED448
) || ptype
!= V_ASN1_UNDEF
) {
552 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_ENCODING
);
556 if (!EVP_DigestVerifyInit(ctx
, NULL
, NULL
, NULL
, pkey
))
562 static int ecd_item_sign25519(EVP_MD_CTX
*ctx
, const ASN1_ITEM
*it
,
564 X509_ALGOR
*alg1
, X509_ALGOR
*alg2
,
565 ASN1_BIT_STRING
*str
)
567 /* Set algorithms identifiers */
568 X509_ALGOR_set0(alg1
, OBJ_nid2obj(NID_ED25519
), V_ASN1_UNDEF
, NULL
);
570 X509_ALGOR_set0(alg2
, OBJ_nid2obj(NID_ED25519
), V_ASN1_UNDEF
, NULL
);
571 /* Algorithm identifiers set: carry on as normal */
575 static int ecd_sig_info_set25519(X509_SIG_INFO
*siginf
, const X509_ALGOR
*alg
,
576 const ASN1_STRING
*sig
)
578 X509_SIG_INFO_set(siginf
, NID_undef
, NID_ED25519
, X25519_SECURITY_BITS
,
583 static int ecd_item_sign448(EVP_MD_CTX
*ctx
, const ASN1_ITEM
*it
,
585 X509_ALGOR
*alg1
, X509_ALGOR
*alg2
,
586 ASN1_BIT_STRING
*str
)
588 /* Set algorithm identifier */
589 X509_ALGOR_set0(alg1
, OBJ_nid2obj(NID_ED448
), V_ASN1_UNDEF
, NULL
);
591 X509_ALGOR_set0(alg2
, OBJ_nid2obj(NID_ED448
), V_ASN1_UNDEF
, NULL
);
592 /* Algorithm identifier set: carry on as normal */
596 static int ecd_sig_info_set448(X509_SIG_INFO
*siginf
, const X509_ALGOR
*alg
,
597 const ASN1_STRING
*sig
)
599 X509_SIG_INFO_set(siginf
, NID_undef
, NID_ED448
, X448_SECURITY_BITS
,
604 static int ed25519_import_from(const OSSL_PARAM params
[], void *vpctx
)
606 return ecx_generic_import_from(params
, vpctx
, EVP_PKEY_ED25519
);
609 const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth
= {
614 "OpenSSL ED25519 algorithm",
639 ecd_sig_info_set25519
,
657 static int ed448_import_from(const OSSL_PARAM params
[], void *vpctx
)
659 return ecx_generic_import_from(params
, vpctx
, EVP_PKEY_ED448
);
662 const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth
= {
667 "OpenSSL ED448 algorithm",
710 static int pkey_ecx_keygen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
712 ECX_KEY
*ecx
= ossl_ecx_key_op(NULL
, NULL
, 0, ctx
->pmeth
->pkey_id
,
713 KEY_OP_PUBLIC
, NULL
, NULL
);
716 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, ecx
);
722 static int validate_ecx_derive(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
724 const unsigned char **privkey
,
725 const unsigned char **pubkey
)
727 const ECX_KEY
*ecxkey
, *peerkey
;
729 if (ctx
->pkey
== NULL
|| ctx
->peerkey
== NULL
) {
730 ERR_raise(ERR_LIB_EC
, EC_R_KEYS_NOT_SET
);
733 ecxkey
= ctx
->pkey
->pkey
.ecx
;
734 peerkey
= EVP_PKEY_get0(ctx
->peerkey
);
735 if (ecxkey
== NULL
|| ecxkey
->privkey
== NULL
) {
736 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_PRIVATE_KEY
);
739 if (peerkey
== NULL
) {
740 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_PEER_KEY
);
743 *privkey
= ecxkey
->privkey
;
744 *pubkey
= peerkey
->pubkey
;
749 static int pkey_ecx_derive25519(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
752 const unsigned char *privkey
, *pubkey
;
754 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
)
756 && ossl_x25519(key
, privkey
, pubkey
) == 0))
758 *keylen
= X25519_KEYLEN
;
762 static int pkey_ecx_derive448(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
765 const unsigned char *privkey
, *pubkey
;
767 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
)
769 && ossl_x448(key
, privkey
, pubkey
) == 0))
771 *keylen
= X448_KEYLEN
;
775 static int pkey_ecx_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
777 /* Only need to handle peer key for derivation */
778 if (type
== EVP_PKEY_CTRL_PEER_KEY
)
783 static const EVP_PKEY_METHOD ecx25519_pkey_meth
= {
787 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
788 pkey_ecx_derive25519
,
793 static const EVP_PKEY_METHOD ecx448_pkey_meth
= {
797 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
803 static int pkey_ecd_digestsign25519(EVP_MD_CTX
*ctx
, unsigned char *sig
,
804 size_t *siglen
, const unsigned char *tbs
,
807 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
810 *siglen
= ED25519_SIGSIZE
;
813 if (*siglen
< ED25519_SIGSIZE
) {
814 ERR_raise(ERR_LIB_EC
, EC_R_BUFFER_TOO_SMALL
);
818 if (ossl_ed25519_sign(sig
, tbs
, tbslen
, edkey
->pubkey
, edkey
->privkey
, NULL
,
821 *siglen
= ED25519_SIGSIZE
;
825 static int pkey_ecd_digestsign448(EVP_MD_CTX
*ctx
, unsigned char *sig
,
826 size_t *siglen
, const unsigned char *tbs
,
829 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
832 *siglen
= ED448_SIGSIZE
;
835 if (*siglen
< ED448_SIGSIZE
) {
836 ERR_raise(ERR_LIB_EC
, EC_R_BUFFER_TOO_SMALL
);
840 if (ossl_ed448_sign(edkey
->libctx
, sig
, tbs
, tbslen
, edkey
->pubkey
,
841 edkey
->privkey
, NULL
, 0, edkey
->propq
) == 0)
843 *siglen
= ED448_SIGSIZE
;
847 static int pkey_ecd_digestverify25519(EVP_MD_CTX
*ctx
, const unsigned char *sig
,
848 size_t siglen
, const unsigned char *tbs
,
851 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
853 if (siglen
!= ED25519_SIGSIZE
)
856 return ossl_ed25519_verify(tbs
, tbslen
, sig
, edkey
->pubkey
,
857 edkey
->libctx
, edkey
->propq
);
860 static int pkey_ecd_digestverify448(EVP_MD_CTX
*ctx
, const unsigned char *sig
,
861 size_t siglen
, const unsigned char *tbs
,
864 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
866 if (siglen
!= ED448_SIGSIZE
)
869 return ossl_ed448_verify(edkey
->libctx
, tbs
, tbslen
, sig
, edkey
->pubkey
,
870 NULL
, 0, edkey
->propq
);
873 static int pkey_ecd_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
876 case EVP_PKEY_CTRL_MD
:
877 /* Only NULL allowed as digest */
878 if (p2
== NULL
|| (const EVP_MD
*)p2
== EVP_md_null())
880 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_DIGEST_TYPE
);
883 case EVP_PKEY_CTRL_DIGESTINIT
:
889 static const EVP_PKEY_METHOD ed25519_pkey_meth
= {
890 EVP_PKEY_ED25519
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
893 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
896 pkey_ecd_digestsign25519
,
897 pkey_ecd_digestverify25519
900 static const EVP_PKEY_METHOD ed448_pkey_meth
= {
901 EVP_PKEY_ED448
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
904 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
907 pkey_ecd_digestsign448
,
908 pkey_ecd_digestverify448
912 # include "s390x_arch.h"
914 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
916 static const unsigned char generator
[] = {
917 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
918 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
921 ECX_KEY
*key
= ossl_ecx_key_new(ctx
->libctx
, ECX_KEY_TYPE_X25519
, 1,
923 unsigned char *privkey
= NULL
, *pubkey
;
926 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
930 pubkey
= key
->pubkey
;
932 privkey
= ossl_ecx_key_allocate_privkey(key
);
933 if (privkey
== NULL
) {
934 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
938 if (RAND_priv_bytes_ex(ctx
->libctx
, privkey
, X25519_KEYLEN
) <= 0)
945 if (s390x_x25519_mul(pubkey
, generator
, privkey
) != 1)
948 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
951 ossl_ecx_key_free(key
);
955 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
957 static const unsigned char generator
[] = {
958 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
959 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
964 ECX_KEY
*key
= ossl_ecx_key_new(ctx
->libctx
, ECX_KEY_TYPE_X448
, 1,
966 unsigned char *privkey
= NULL
, *pubkey
;
969 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
973 pubkey
= key
->pubkey
;
975 privkey
= ossl_ecx_key_allocate_privkey(key
);
976 if (privkey
== NULL
) {
977 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
981 if (RAND_priv_bytes_ex(ctx
->libctx
, privkey
, X448_KEYLEN
) <= 0)
987 if (s390x_x448_mul(pubkey
, generator
, privkey
) != 1)
990 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
993 ossl_ecx_key_free(key
);
997 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
999 static const unsigned char generator_x
[] = {
1000 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1001 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1002 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1004 static const unsigned char generator_y
[] = {
1005 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1006 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1007 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1009 unsigned char x_dst
[32], buff
[SHA512_DIGEST_LENGTH
];
1010 ECX_KEY
*key
= ossl_ecx_key_new(ctx
->libctx
, ECX_KEY_TYPE_ED25519
, 1,
1012 unsigned char *privkey
= NULL
, *pubkey
;
1018 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
1022 pubkey
= key
->pubkey
;
1024 privkey
= ossl_ecx_key_allocate_privkey(key
);
1025 if (privkey
== NULL
) {
1026 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
1030 if (RAND_priv_bytes_ex(ctx
->libctx
, privkey
, ED25519_KEYLEN
) <= 0)
1033 md
= EVP_MD_fetch(ctx
->libctx
, "SHA512", ctx
->propquery
);
1037 rv
= EVP_Digest(privkey
, 32, buff
, &sz
, md
, NULL
);
1046 if (s390x_ed25519_mul(x_dst
, pubkey
,
1047 generator_x
, generator_y
, buff
) != 1)
1050 pubkey
[31] |= ((x_dst
[0] & 0x01) << 7);
1052 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
1055 ossl_ecx_key_free(key
);
1059 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
1061 static const unsigned char generator_x
[] = {
1062 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1063 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1064 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1065 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1066 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1068 static const unsigned char generator_y
[] = {
1069 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1070 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1071 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1072 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1073 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1075 unsigned char x_dst
[57], buff
[114];
1076 ECX_KEY
*key
= ossl_ecx_key_new(ctx
->libctx
, ECX_KEY_TYPE_ED448
, 1,
1078 unsigned char *privkey
= NULL
, *pubkey
;
1079 EVP_MD_CTX
*hashctx
= NULL
;
1084 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
1088 pubkey
= key
->pubkey
;
1090 privkey
= ossl_ecx_key_allocate_privkey(key
);
1091 if (privkey
== NULL
) {
1092 ERR_raise(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
1096 if (RAND_priv_bytes_ex(ctx
->libctx
, privkey
, ED448_KEYLEN
) <= 0)
1099 hashctx
= EVP_MD_CTX_new();
1100 if (hashctx
== NULL
)
1103 md
= EVP_MD_fetch(ctx
->libctx
, "SHAKE256", ctx
->propquery
);
1107 rv
= EVP_DigestInit_ex(hashctx
, md
, NULL
);
1112 if (EVP_DigestUpdate(hashctx
, privkey
, 57) != 1)
1114 if (EVP_DigestFinalXOF(hashctx
, buff
, sizeof(buff
)) != 1)
1121 if (s390x_ed448_mul(x_dst
, pubkey
,
1122 generator_x
, generator_y
, buff
) != 1)
1125 pubkey
[56] |= ((x_dst
[0] & 0x01) << 7);
1127 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
1128 EVP_MD_CTX_free(hashctx
);
1131 ossl_ecx_key_free(key
);
1132 EVP_MD_CTX_free(hashctx
);
1136 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
1139 const unsigned char *privkey
, *pubkey
;
1141 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
))
1145 return s390x_x25519_mul(key
, pubkey
, privkey
);
1147 *keylen
= X25519_KEYLEN
;
1151 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
1154 const unsigned char *privkey
, *pubkey
;
1156 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
))
1160 return s390x_x448_mul(key
, pubkey
, privkey
);
1162 *keylen
= X448_KEYLEN
;
1166 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX
*ctx
,
1167 unsigned char *sig
, size_t *siglen
,
1168 const unsigned char *tbs
,
1173 unsigned char sig
[64];
1174 unsigned char priv
[32];
1176 unsigned long long buff
[512];
1178 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
1182 *siglen
= ED25519_SIGSIZE
;
1186 if (*siglen
< ED25519_SIGSIZE
) {
1187 ERR_raise(ERR_LIB_EC
, EC_R_BUFFER_TOO_SMALL
);
1191 memset(¶m
, 0, sizeof(param
));
1192 memcpy(param
.ed25519
.priv
, edkey
->privkey
, sizeof(param
.ed25519
.priv
));
1194 rc
= s390x_kdsa(S390X_EDDSA_SIGN_ED25519
, ¶m
.ed25519
, tbs
, tbslen
);
1195 OPENSSL_cleanse(param
.ed25519
.priv
, sizeof(param
.ed25519
.priv
));
1199 s390x_flip_endian32(sig
, param
.ed25519
.sig
);
1200 s390x_flip_endian32(sig
+ 32, param
.ed25519
.sig
+ 32);
1202 *siglen
= ED25519_SIGSIZE
;
1206 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX
*ctx
,
1207 unsigned char *sig
, size_t *siglen
,
1208 const unsigned char *tbs
,
1213 unsigned char sig
[128];
1214 unsigned char priv
[64];
1216 unsigned long long buff
[512];
1218 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
1222 *siglen
= ED448_SIGSIZE
;
1226 if (*siglen
< ED448_SIGSIZE
) {
1227 ERR_raise(ERR_LIB_EC
, EC_R_BUFFER_TOO_SMALL
);
1231 memset(¶m
, 0, sizeof(param
));
1232 memcpy(param
.ed448
.priv
+ 64 - 57, edkey
->privkey
, 57);
1234 rc
= s390x_kdsa(S390X_EDDSA_SIGN_ED448
, ¶m
.ed448
, tbs
, tbslen
);
1235 OPENSSL_cleanse(param
.ed448
.priv
, sizeof(param
.ed448
.priv
));
1239 s390x_flip_endian64(param
.ed448
.sig
, param
.ed448
.sig
);
1240 s390x_flip_endian64(param
.ed448
.sig
+ 64, param
.ed448
.sig
+ 64);
1241 memcpy(sig
, param
.ed448
.sig
, 57);
1242 memcpy(sig
+ 57, param
.ed448
.sig
+ 64, 57);
1244 *siglen
= ED448_SIGSIZE
;
1248 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX
*ctx
,
1249 const unsigned char *sig
,
1251 const unsigned char *tbs
,
1256 unsigned char sig
[64];
1257 unsigned char pub
[32];
1259 unsigned long long buff
[512];
1261 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
1263 if (siglen
!= ED25519_SIGSIZE
)
1266 memset(¶m
, 0, sizeof(param
));
1267 s390x_flip_endian32(param
.ed25519
.sig
, sig
);
1268 s390x_flip_endian32(param
.ed25519
.sig
+ 32, sig
+ 32);
1269 s390x_flip_endian32(param
.ed25519
.pub
, edkey
->pubkey
);
1271 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519
,
1272 ¶m
.ed25519
, tbs
, tbslen
) == 0 ? 1 : 0;
1275 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX
*ctx
,
1276 const unsigned char *sig
,
1278 const unsigned char *tbs
,
1283 unsigned char sig
[128];
1284 unsigned char pub
[64];
1286 unsigned long long buff
[512];
1288 const ECX_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ecx
;
1290 if (siglen
!= ED448_SIGSIZE
)
1293 memset(¶m
, 0, sizeof(param
));
1294 memcpy(param
.ed448
.sig
, sig
, 57);
1295 s390x_flip_endian64(param
.ed448
.sig
, param
.ed448
.sig
);
1296 memcpy(param
.ed448
.sig
+ 64, sig
+ 57, 57);
1297 s390x_flip_endian64(param
.ed448
.sig
+ 64, param
.ed448
.sig
+ 64);
1298 memcpy(param
.ed448
.pub
, edkey
->pubkey
, 57);
1299 s390x_flip_endian64(param
.ed448
.pub
, param
.ed448
.pub
);
1301 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448
,
1302 ¶m
.ed448
, tbs
, tbslen
) == 0 ? 1 : 0;
1305 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth
= {
1307 0, 0, 0, 0, 0, 0, 0,
1308 s390x_pkey_ecx_keygen25519
,
1309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1310 s390x_pkey_ecx_derive25519
,
1315 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth
= {
1317 0, 0, 0, 0, 0, 0, 0,
1318 s390x_pkey_ecx_keygen448
,
1319 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1320 s390x_pkey_ecx_derive448
,
1324 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth
= {
1325 EVP_PKEY_ED25519
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
1327 s390x_pkey_ecd_keygen25519
,
1328 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1331 s390x_pkey_ecd_digestsign25519
,
1332 s390x_pkey_ecd_digestverify25519
1335 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth
= {
1336 EVP_PKEY_ED448
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
1338 s390x_pkey_ecd_keygen448
,
1339 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1342 s390x_pkey_ecd_digestsign448
,
1343 s390x_pkey_ecd_digestverify448
1347 const EVP_PKEY_METHOD
*ossl_ecx25519_pkey_method(void)
1350 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519
))
1351 return &ecx25519_s390x_pkey_meth
;
1353 return &ecx25519_pkey_meth
;
1356 const EVP_PKEY_METHOD
*ossl_ecx448_pkey_method(void)
1359 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448
))
1360 return &ecx448_s390x_pkey_meth
;
1362 return &ecx448_pkey_meth
;
1365 const EVP_PKEY_METHOD
*ossl_ed25519_pkey_method(void)
1368 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519
)
1369 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519
)
1370 && OPENSSL_s390xcap_P
.kdsa
[0]
1371 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519
))
1372 return &ed25519_s390x_pkey_meth
;
1374 return &ed25519_pkey_meth
;
1377 const EVP_PKEY_METHOD
*ossl_ed448_pkey_method(void)
1380 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448
)
1381 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448
)
1382 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448
))
1383 return &ed448_s390x_pkey_meth
;
1385 return &ed448_pkey_meth
;