2 * Copyright 2006-2022 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
));
45 if (!X509_PUBKEY_set0_param(pk
, OBJ_nid2obj(pkey
->ameth
->pkey_id
),
46 V_ASN1_UNDEF
, NULL
, penc
, KEYLEN(pkey
))) {
48 ERR_raise(ERR_LIB_EC
, ERR_R_X509_LIB
);
54 static int ecx_pub_decode(EVP_PKEY
*pkey
, const X509_PUBKEY
*pubkey
)
56 const unsigned char *p
;
62 if (!X509_PUBKEY_get0_param(NULL
, &p
, &pklen
, &palg
, pubkey
))
64 ecx
= ossl_ecx_key_op(palg
, p
, pklen
, pkey
->ameth
->pkey_id
,
65 KEY_OP_PUBLIC
, NULL
, NULL
);
68 EVP_PKEY_assign(pkey
, pkey
->ameth
->pkey_id
, ecx
);
73 static int ecx_pub_cmp(const EVP_PKEY
*a
, const EVP_PKEY
*b
)
75 const ECX_KEY
*akey
= a
->pkey
.ecx
;
76 const ECX_KEY
*bkey
= b
->pkey
.ecx
;
78 if (akey
== NULL
|| bkey
== NULL
)
81 return CRYPTO_memcmp(akey
->pubkey
, bkey
->pubkey
, KEYLEN(a
)) == 0;
84 static int ecx_priv_decode_ex(EVP_PKEY
*pkey
, const PKCS8_PRIV_KEY_INFO
*p8
,
85 OSSL_LIB_CTX
*libctx
, const char *propq
)
88 ECX_KEY
*ecx
= ossl_ecx_key_from_pkcs8(p8
, libctx
, propq
);
92 EVP_PKEY_assign(pkey
, pkey
->ameth
->pkey_id
, ecx
);
98 static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO
*p8
, const EVP_PKEY
*pkey
)
100 const ECX_KEY
*ecxkey
= pkey
->pkey
.ecx
;
101 ASN1_OCTET_STRING oct
;
102 unsigned char *penc
= NULL
;
105 if (ecxkey
== NULL
|| ecxkey
->privkey
== NULL
) {
106 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_PRIVATE_KEY
);
110 oct
.data
= ecxkey
->privkey
;
111 oct
.length
= KEYLEN(pkey
);
114 penclen
= i2d_ASN1_OCTET_STRING(&oct
, &penc
);
116 ERR_raise(ERR_LIB_EC
, ERR_R_ASN1_LIB
);
120 if (!PKCS8_pkey_set0(p8
, OBJ_nid2obj(pkey
->ameth
->pkey_id
), 0,
121 V_ASN1_UNDEF
, NULL
, penc
, penclen
)) {
122 OPENSSL_clear_free(penc
, penclen
);
123 ERR_raise(ERR_LIB_EC
, ERR_R_ASN1_LIB
);
130 static int ecx_size(const EVP_PKEY
*pkey
)
135 static int ecx_bits(const EVP_PKEY
*pkey
)
137 if (IS25519(pkey
->ameth
->pkey_id
)) {
139 } else if (ISX448(pkey
->ameth
->pkey_id
)) {
146 static int ecx_security_bits(const EVP_PKEY
*pkey
)
148 if (IS25519(pkey
->ameth
->pkey_id
)) {
149 return X25519_SECURITY_BITS
;
151 return X448_SECURITY_BITS
;
155 static void ecx_free(EVP_PKEY
*pkey
)
157 ossl_ecx_key_free(pkey
->pkey
.ecx
);
160 /* "parameters" are always equal */
161 static int ecx_cmp_parameters(const EVP_PKEY
*a
, const EVP_PKEY
*b
)
166 static int ecx_key_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
167 ASN1_PCTX
*ctx
, ecx_key_op_t op
)
169 const ECX_KEY
*ecxkey
= pkey
->pkey
.ecx
;
170 const char *nm
= OBJ_nid2ln(pkey
->ameth
->pkey_id
);
172 if (op
== KEY_OP_PRIVATE
) {
173 if (ecxkey
== NULL
|| ecxkey
->privkey
== NULL
) {
174 if (BIO_printf(bp
, "%*s<INVALID PRIVATE KEY>\n", indent
, "") <= 0)
178 if (BIO_printf(bp
, "%*s%s Private-Key:\n", indent
, "", nm
) <= 0)
180 if (BIO_printf(bp
, "%*spriv:\n", indent
, "") <= 0)
182 if (ASN1_buf_print(bp
, ecxkey
->privkey
, KEYLEN(pkey
),
186 if (ecxkey
== NULL
) {
187 if (BIO_printf(bp
, "%*s<INVALID PUBLIC KEY>\n", indent
, "") <= 0)
191 if (BIO_printf(bp
, "%*s%s Public-Key:\n", indent
, "", nm
) <= 0)
194 if (BIO_printf(bp
, "%*spub:\n", indent
, "") <= 0)
197 if (ASN1_buf_print(bp
, ecxkey
->pubkey
, KEYLEN(pkey
),
203 static int ecx_priv_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
206 return ecx_key_print(bp
, pkey
, indent
, ctx
, KEY_OP_PRIVATE
);
209 static int ecx_pub_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
212 return ecx_key_print(bp
, pkey
, indent
, ctx
, KEY_OP_PUBLIC
);
215 static int ecx_ctrl(EVP_PKEY
*pkey
, int op
, long arg1
, void *arg2
)
219 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT
: {
220 ECX_KEY
*ecx
= ossl_ecx_key_op(NULL
, arg2
, arg1
, pkey
->ameth
->pkey_id
,
221 KEY_OP_PUBLIC
, NULL
, NULL
);
224 EVP_PKEY_assign(pkey
, pkey
->ameth
->pkey_id
, ecx
);
229 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT
:
230 if (pkey
->pkey
.ecx
!= NULL
) {
231 unsigned char **ppt
= arg2
;
233 *ppt
= OPENSSL_memdup(pkey
->pkey
.ecx
->pubkey
, KEYLEN(pkey
));
245 static int ecd_ctrl(EVP_PKEY
*pkey
, int op
, long arg1
, void *arg2
)
248 case ASN1_PKEY_CTRL_DEFAULT_MD_NID
:
249 /* We currently only support Pure EdDSA which takes no digest */
250 *(int *)arg2
= NID_undef
;
259 static int ecx_set_priv_key(EVP_PKEY
*pkey
, const unsigned char *priv
,
262 OSSL_LIB_CTX
*libctx
= NULL
;
265 if (pkey
->keymgmt
!= NULL
)
266 libctx
= ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey
->keymgmt
));
268 ecx
= ossl_ecx_key_op(NULL
, priv
, len
, pkey
->ameth
->pkey_id
,
269 KEY_OP_PRIVATE
, libctx
, NULL
);
272 EVP_PKEY_assign(pkey
, pkey
->ameth
->pkey_id
, ecx
);
278 static int ecx_set_pub_key(EVP_PKEY
*pkey
, const unsigned char *pub
, size_t len
)
280 OSSL_LIB_CTX
*libctx
= NULL
;
283 if (pkey
->keymgmt
!= NULL
)
284 libctx
= ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey
->keymgmt
));
286 ecx
= ossl_ecx_key_op(NULL
, pub
, len
, pkey
->ameth
->pkey_id
,
287 KEY_OP_PUBLIC
, libctx
, NULL
);
290 EVP_PKEY_assign(pkey
, pkey
->ameth
->pkey_id
, ecx
);
296 static int ecx_get_priv_key(const EVP_PKEY
*pkey
, unsigned char *priv
,
299 const ECX_KEY
*key
= pkey
->pkey
.ecx
;
302 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
307 || key
->privkey
== NULL
308 || *len
< (size_t)KEYLENID(pkey
->ameth
->pkey_id
))
311 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
312 memcpy(priv
, key
->privkey
, *len
);
317 static int ecx_get_pub_key(const EVP_PKEY
*pkey
, unsigned char *pub
,
320 const ECX_KEY
*key
= pkey
->pkey
.ecx
;
323 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
328 || *len
< (size_t)KEYLENID(pkey
->ameth
->pkey_id
))
331 *len
= KEYLENID(pkey
->ameth
->pkey_id
);
332 memcpy(pub
, key
->pubkey
, *len
);
337 static size_t ecx_pkey_dirty_cnt(const EVP_PKEY
*pkey
)
340 * We provide no mechanism to "update" an ECX key once it has been set,
341 * therefore we do not have to maintain a dirty count.
346 static int ecx_pkey_export_to(const EVP_PKEY
*from
, void *to_keydata
,
347 OSSL_FUNC_keymgmt_import_fn
*importer
,
348 OSSL_LIB_CTX
*libctx
, const char *propq
)
350 const ECX_KEY
*key
= from
->pkey
.ecx
;
351 OSSL_PARAM_BLD
*tmpl
= OSSL_PARAM_BLD_new();
352 OSSL_PARAM
*params
= NULL
;
359 /* A key must at least have a public part */
360 if (!OSSL_PARAM_BLD_push_octet_string(tmpl
, OSSL_PKEY_PARAM_PUB_KEY
,
361 key
->pubkey
, key
->keylen
))
363 selection
|= OSSL_KEYMGMT_SELECT_PUBLIC_KEY
;
365 if (key
->privkey
!= NULL
) {
366 if (!OSSL_PARAM_BLD_push_octet_string(tmpl
,
367 OSSL_PKEY_PARAM_PRIV_KEY
,
368 key
->privkey
, key
->keylen
))
370 selection
|= OSSL_KEYMGMT_SELECT_PRIVATE_KEY
;
373 params
= OSSL_PARAM_BLD_to_param(tmpl
);
375 /* We export, the provider imports */
376 rv
= importer(to_keydata
, selection
, params
);
379 OSSL_PARAM_BLD_free(tmpl
);
380 OSSL_PARAM_free(params
);
384 static int ecx_generic_import_from(const OSSL_PARAM params
[], void *vpctx
,
387 EVP_PKEY_CTX
*pctx
= vpctx
;
388 EVP_PKEY
*pkey
= EVP_PKEY_CTX_get0_pkey(pctx
);
389 ECX_KEY
*ecx
= ossl_ecx_key_new(pctx
->libctx
, KEYNID2TYPE(keytype
), 0,
393 ERR_raise(ERR_LIB_DH
, ERR_R_EC_LIB
);
397 if (!ossl_ecx_key_fromdata(ecx
, params
, 1)
398 || !EVP_PKEY_assign(pkey
, keytype
, ecx
)) {
399 ossl_ecx_key_free(ecx
);
405 static int ecx_pkey_copy(EVP_PKEY
*to
, EVP_PKEY
*from
)
407 ECX_KEY
*ecx
= from
->pkey
.ecx
, *dupkey
= NULL
;
411 dupkey
= ossl_ecx_key_dup(ecx
, OSSL_KEYMGMT_SELECT_ALL
);
416 ret
= EVP_PKEY_assign(to
, from
->type
, dupkey
);
418 ossl_ecx_key_free(dupkey
);
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_sign(X509_ALGOR
*alg1
, X509_ALGOR
*alg2
, int nid
)
564 /* Note that X509_ALGOR_set0(..., ..., V_ASN1_UNDEF, ...) cannot fail */
565 /* Set algorithms identifiers */
566 (void)X509_ALGOR_set0(alg1
, OBJ_nid2obj(nid
), V_ASN1_UNDEF
, NULL
);
568 (void)X509_ALGOR_set0(alg2
, OBJ_nid2obj(nid
), V_ASN1_UNDEF
, NULL
);
569 /* Algorithm identifiers set: carry on as normal */
573 static int ecd_item_sign25519(EVP_MD_CTX
*ctx
, const ASN1_ITEM
*it
,
575 X509_ALGOR
*alg1
, X509_ALGOR
*alg2
,
576 ASN1_BIT_STRING
*str
)
578 return ecd_item_sign(alg1
, alg2
, NID_ED25519
);
581 static int ecd_sig_info_set25519(X509_SIG_INFO
*siginf
, const X509_ALGOR
*alg
,
582 const ASN1_STRING
*sig
)
584 X509_SIG_INFO_set(siginf
, NID_undef
, NID_ED25519
, X25519_SECURITY_BITS
,
589 static int ecd_item_sign448(EVP_MD_CTX
*ctx
, const ASN1_ITEM
*it
,
591 X509_ALGOR
*alg1
, X509_ALGOR
*alg2
,
592 ASN1_BIT_STRING
*str
)
594 return ecd_item_sign(alg1
, alg2
, NID_ED448
);
597 static int ecd_sig_info_set448(X509_SIG_INFO
*siginf
, const X509_ALGOR
*alg
,
598 const ASN1_STRING
*sig
)
600 X509_SIG_INFO_set(siginf
, NID_undef
, NID_ED448
, X448_SECURITY_BITS
,
605 static int ed25519_import_from(const OSSL_PARAM params
[], void *vpctx
)
607 return ecx_generic_import_from(params
, vpctx
, EVP_PKEY_ED25519
);
610 const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth
= {
615 "OpenSSL ED25519 algorithm",
640 ecd_sig_info_set25519
,
658 static int ed448_import_from(const OSSL_PARAM params
[], void *vpctx
)
660 return ecx_generic_import_from(params
, vpctx
, EVP_PKEY_ED448
);
663 const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth
= {
668 "OpenSSL ED448 algorithm",
711 static int pkey_ecx_keygen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
713 ECX_KEY
*ecx
= ossl_ecx_key_op(NULL
, NULL
, 0, ctx
->pmeth
->pkey_id
,
714 KEY_OP_PUBLIC
, NULL
, NULL
);
717 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, ecx
);
723 static int validate_ecx_derive(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
725 const unsigned char **privkey
,
726 const unsigned char **pubkey
)
728 const ECX_KEY
*ecxkey
, *peerkey
;
730 if (ctx
->pkey
== NULL
|| ctx
->peerkey
== NULL
) {
731 ERR_raise(ERR_LIB_EC
, EC_R_KEYS_NOT_SET
);
734 ecxkey
= evp_pkey_get_legacy(ctx
->pkey
);
735 peerkey
= evp_pkey_get_legacy(ctx
->peerkey
);
736 if (ecxkey
== NULL
|| ecxkey
->privkey
== NULL
) {
737 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_PRIVATE_KEY
);
740 if (peerkey
== NULL
) {
741 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_PEER_KEY
);
744 *privkey
= ecxkey
->privkey
;
745 *pubkey
= peerkey
->pubkey
;
750 static int pkey_ecx_derive25519(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
753 const unsigned char *privkey
, *pubkey
;
755 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
)
757 && ossl_x25519(key
, privkey
, pubkey
) == 0))
759 *keylen
= X25519_KEYLEN
;
763 static int pkey_ecx_derive448(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
766 const unsigned char *privkey
, *pubkey
;
768 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
)
770 && ossl_x448(key
, privkey
, pubkey
) == 0))
772 *keylen
= X448_KEYLEN
;
776 static int pkey_ecx_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
778 /* Only need to handle peer key for derivation */
779 if (type
== EVP_PKEY_CTRL_PEER_KEY
)
784 static const EVP_PKEY_METHOD ecx25519_pkey_meth
= {
788 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
789 pkey_ecx_derive25519
,
794 static const EVP_PKEY_METHOD ecx448_pkey_meth
= {
798 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
804 static int pkey_ecd_digestsign25519(EVP_MD_CTX
*ctx
, unsigned char *sig
,
805 size_t *siglen
, const unsigned char *tbs
,
808 const ECX_KEY
*edkey
= evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx
)->pkey
);
811 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_KEY
);
816 *siglen
= ED25519_SIGSIZE
;
819 if (*siglen
< ED25519_SIGSIZE
) {
820 ERR_raise(ERR_LIB_EC
, EC_R_BUFFER_TOO_SMALL
);
824 if (ossl_ed25519_sign(sig
, tbs
, tbslen
, edkey
->pubkey
, edkey
->privkey
, NULL
,
827 *siglen
= ED25519_SIGSIZE
;
831 static int pkey_ecd_digestsign448(EVP_MD_CTX
*ctx
, unsigned char *sig
,
832 size_t *siglen
, const unsigned char *tbs
,
835 const ECX_KEY
*edkey
= evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx
)->pkey
);
838 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_KEY
);
843 *siglen
= ED448_SIGSIZE
;
846 if (*siglen
< ED448_SIGSIZE
) {
847 ERR_raise(ERR_LIB_EC
, EC_R_BUFFER_TOO_SMALL
);
851 if (ossl_ed448_sign(edkey
->libctx
, sig
, tbs
, tbslen
, edkey
->pubkey
,
852 edkey
->privkey
, NULL
, 0, edkey
->propq
) == 0)
854 *siglen
= ED448_SIGSIZE
;
858 static int pkey_ecd_digestverify25519(EVP_MD_CTX
*ctx
, const unsigned char *sig
,
859 size_t siglen
, const unsigned char *tbs
,
862 const ECX_KEY
*edkey
= evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx
)->pkey
);
865 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_KEY
);
869 if (siglen
!= ED25519_SIGSIZE
)
872 return ossl_ed25519_verify(tbs
, tbslen
, sig
, edkey
->pubkey
,
873 edkey
->libctx
, edkey
->propq
);
876 static int pkey_ecd_digestverify448(EVP_MD_CTX
*ctx
, const unsigned char *sig
,
877 size_t siglen
, const unsigned char *tbs
,
880 const ECX_KEY
*edkey
= evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx
)->pkey
);
883 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_KEY
);
887 if (siglen
!= ED448_SIGSIZE
)
890 return ossl_ed448_verify(edkey
->libctx
, tbs
, tbslen
, sig
, edkey
->pubkey
,
891 NULL
, 0, edkey
->propq
);
894 static int pkey_ecd_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
897 case EVP_PKEY_CTRL_MD
:
898 /* Only NULL allowed as digest */
899 if (p2
== NULL
|| (const EVP_MD
*)p2
== EVP_md_null())
901 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_DIGEST_TYPE
);
904 case EVP_PKEY_CTRL_DIGESTINIT
:
910 static const EVP_PKEY_METHOD ed25519_pkey_meth
= {
911 EVP_PKEY_ED25519
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
917 pkey_ecd_digestsign25519
,
918 pkey_ecd_digestverify25519
921 static const EVP_PKEY_METHOD ed448_pkey_meth
= {
922 EVP_PKEY_ED448
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
925 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
928 pkey_ecd_digestsign448
,
929 pkey_ecd_digestverify448
933 # include "s390x_arch.h"
935 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
937 static const unsigned char generator
[] = {
938 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
939 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
940 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
942 ECX_KEY
*key
= ossl_ecx_key_new(ctx
->libctx
, ECX_KEY_TYPE_X25519
, 1,
944 unsigned char *privkey
= NULL
, *pubkey
;
947 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
951 pubkey
= key
->pubkey
;
953 privkey
= ossl_ecx_key_allocate_privkey(key
);
954 if (privkey
== NULL
) {
955 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
959 if (RAND_priv_bytes_ex(ctx
->libctx
, privkey
, X25519_KEYLEN
, 0) <= 0)
966 if (s390x_x25519_mul(pubkey
, generator
, privkey
) != 1)
969 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
972 ossl_ecx_key_free(key
);
976 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
978 static const unsigned char generator
[] = {
979 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
980 0x00, 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
985 ECX_KEY
*key
= ossl_ecx_key_new(ctx
->libctx
, ECX_KEY_TYPE_X448
, 1,
987 unsigned char *privkey
= NULL
, *pubkey
;
990 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
994 pubkey
= key
->pubkey
;
996 privkey
= ossl_ecx_key_allocate_privkey(key
);
997 if (privkey
== NULL
) {
998 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
1002 if (RAND_priv_bytes_ex(ctx
->libctx
, privkey
, X448_KEYLEN
, 0) <= 0)
1008 if (s390x_x448_mul(pubkey
, generator
, privkey
) != 1)
1011 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
1014 ossl_ecx_key_free(key
);
1018 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
1020 static const unsigned char generator_x
[] = {
1021 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1022 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1023 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1025 static const unsigned char generator_y
[] = {
1026 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1027 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1028 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1030 unsigned char x_dst
[32], buff
[SHA512_DIGEST_LENGTH
];
1031 ECX_KEY
*key
= ossl_ecx_key_new(ctx
->libctx
, ECX_KEY_TYPE_ED25519
, 1,
1033 unsigned char *privkey
= NULL
, *pubkey
;
1039 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
1043 pubkey
= key
->pubkey
;
1045 privkey
= ossl_ecx_key_allocate_privkey(key
);
1046 if (privkey
== NULL
) {
1047 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
1051 if (RAND_priv_bytes_ex(ctx
->libctx
, privkey
, ED25519_KEYLEN
, 0) <= 0)
1054 md
= EVP_MD_fetch(ctx
->libctx
, "SHA512", ctx
->propquery
);
1058 rv
= EVP_Digest(privkey
, 32, buff
, &sz
, md
, NULL
);
1067 if (s390x_ed25519_mul(x_dst
, pubkey
,
1068 generator_x
, generator_y
, buff
) != 1)
1071 pubkey
[31] |= ((x_dst
[0] & 0x01) << 7);
1073 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
1076 ossl_ecx_key_free(key
);
1080 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
1082 static const unsigned char generator_x
[] = {
1083 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1084 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1085 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1086 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1087 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1089 static const unsigned char generator_y
[] = {
1090 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1091 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1092 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1093 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1094 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1096 unsigned char x_dst
[57], buff
[114];
1097 ECX_KEY
*key
= ossl_ecx_key_new(ctx
->libctx
, ECX_KEY_TYPE_ED448
, 1,
1099 unsigned char *privkey
= NULL
, *pubkey
;
1100 EVP_MD_CTX
*hashctx
= NULL
;
1105 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
1109 pubkey
= key
->pubkey
;
1111 privkey
= ossl_ecx_key_allocate_privkey(key
);
1112 if (privkey
== NULL
) {
1113 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
1117 if (RAND_priv_bytes_ex(ctx
->libctx
, privkey
, ED448_KEYLEN
, 0) <= 0)
1120 hashctx
= EVP_MD_CTX_new();
1121 if (hashctx
== NULL
)
1124 md
= EVP_MD_fetch(ctx
->libctx
, "SHAKE256", ctx
->propquery
);
1128 rv
= EVP_DigestInit_ex(hashctx
, md
, NULL
);
1133 if (EVP_DigestUpdate(hashctx
, privkey
, 57) != 1)
1135 if (EVP_DigestFinalXOF(hashctx
, buff
, sizeof(buff
)) != 1)
1142 if (s390x_ed448_mul(x_dst
, pubkey
,
1143 generator_x
, generator_y
, buff
) != 1)
1146 pubkey
[56] |= ((x_dst
[0] & 0x01) << 7);
1148 EVP_PKEY_assign(pkey
, ctx
->pmeth
->pkey_id
, key
);
1149 EVP_MD_CTX_free(hashctx
);
1152 ossl_ecx_key_free(key
);
1153 EVP_MD_CTX_free(hashctx
);
1157 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
1160 const unsigned char *privkey
, *pubkey
;
1162 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
)
1164 && s390x_x25519_mul(key
, privkey
, pubkey
) == 0))
1166 *keylen
= X25519_KEYLEN
;
1170 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
1173 const unsigned char *privkey
, *pubkey
;
1175 if (!validate_ecx_derive(ctx
, key
, keylen
, &privkey
, &pubkey
)
1177 && s390x_x448_mul(key
, pubkey
, privkey
) == 0))
1179 *keylen
= X448_KEYLEN
;
1183 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX
*ctx
,
1184 unsigned char *sig
, size_t *siglen
,
1185 const unsigned char *tbs
,
1190 unsigned char sig
[64];
1191 unsigned char priv
[32];
1193 unsigned long long buff
[512];
1195 const ECX_KEY
*edkey
= evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx
)->pkey
);
1198 if (edkey
== NULL
) {
1199 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_KEY
);
1204 *siglen
= ED25519_SIGSIZE
;
1208 if (*siglen
< ED25519_SIGSIZE
) {
1209 ERR_raise(ERR_LIB_EC
, EC_R_BUFFER_TOO_SMALL
);
1213 memset(¶m
, 0, sizeof(param
));
1214 memcpy(param
.ed25519
.priv
, edkey
->privkey
, sizeof(param
.ed25519
.priv
));
1216 rc
= s390x_kdsa(S390X_EDDSA_SIGN_ED25519
, ¶m
.ed25519
, tbs
, tbslen
);
1217 OPENSSL_cleanse(param
.ed25519
.priv
, sizeof(param
.ed25519
.priv
));
1221 s390x_flip_endian32(sig
, param
.ed25519
.sig
);
1222 s390x_flip_endian32(sig
+ 32, param
.ed25519
.sig
+ 32);
1224 *siglen
= ED25519_SIGSIZE
;
1228 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX
*ctx
,
1229 unsigned char *sig
, size_t *siglen
,
1230 const unsigned char *tbs
,
1235 unsigned char sig
[128];
1236 unsigned char priv
[64];
1238 unsigned long long buff
[512];
1240 const ECX_KEY
*edkey
= evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx
)->pkey
);
1243 if (edkey
== NULL
) {
1244 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_KEY
);
1249 *siglen
= ED448_SIGSIZE
;
1253 if (*siglen
< ED448_SIGSIZE
) {
1254 ERR_raise(ERR_LIB_EC
, EC_R_BUFFER_TOO_SMALL
);
1258 memset(¶m
, 0, sizeof(param
));
1259 memcpy(param
.ed448
.priv
+ 64 - 57, edkey
->privkey
, 57);
1261 rc
= s390x_kdsa(S390X_EDDSA_SIGN_ED448
, ¶m
.ed448
, tbs
, tbslen
);
1262 OPENSSL_cleanse(param
.ed448
.priv
, sizeof(param
.ed448
.priv
));
1266 s390x_flip_endian64(param
.ed448
.sig
, param
.ed448
.sig
);
1267 s390x_flip_endian64(param
.ed448
.sig
+ 64, param
.ed448
.sig
+ 64);
1268 memcpy(sig
, param
.ed448
.sig
, 57);
1269 memcpy(sig
+ 57, param
.ed448
.sig
+ 64, 57);
1271 *siglen
= ED448_SIGSIZE
;
1275 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX
*ctx
,
1276 const unsigned char *sig
,
1278 const unsigned char *tbs
,
1283 unsigned char sig
[64];
1284 unsigned char pub
[32];
1286 unsigned long long buff
[512];
1288 const ECX_KEY
*edkey
= evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx
)->pkey
);
1290 if (edkey
== NULL
) {
1291 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_KEY
);
1295 if (siglen
!= ED25519_SIGSIZE
)
1298 memset(¶m
, 0, sizeof(param
));
1299 s390x_flip_endian32(param
.ed25519
.sig
, sig
);
1300 s390x_flip_endian32(param
.ed25519
.sig
+ 32, sig
+ 32);
1301 s390x_flip_endian32(param
.ed25519
.pub
, edkey
->pubkey
);
1303 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519
,
1304 ¶m
.ed25519
, tbs
, tbslen
) == 0 ? 1 : 0;
1307 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX
*ctx
,
1308 const unsigned char *sig
,
1310 const unsigned char *tbs
,
1315 unsigned char sig
[128];
1316 unsigned char pub
[64];
1318 unsigned long long buff
[512];
1320 const ECX_KEY
*edkey
= evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx
)->pkey
);
1322 if (edkey
== NULL
) {
1323 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_KEY
);
1327 if (siglen
!= ED448_SIGSIZE
)
1330 memset(¶m
, 0, sizeof(param
));
1331 memcpy(param
.ed448
.sig
, sig
, 57);
1332 s390x_flip_endian64(param
.ed448
.sig
, param
.ed448
.sig
);
1333 memcpy(param
.ed448
.sig
+ 64, sig
+ 57, 57);
1334 s390x_flip_endian64(param
.ed448
.sig
+ 64, param
.ed448
.sig
+ 64);
1335 memcpy(param
.ed448
.pub
, edkey
->pubkey
, 57);
1336 s390x_flip_endian64(param
.ed448
.pub
, param
.ed448
.pub
);
1338 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448
,
1339 ¶m
.ed448
, tbs
, tbslen
) == 0 ? 1 : 0;
1342 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth
= {
1344 0, 0, 0, 0, 0, 0, 0,
1345 s390x_pkey_ecx_keygen25519
,
1346 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1347 s390x_pkey_ecx_derive25519
,
1352 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth
= {
1354 0, 0, 0, 0, 0, 0, 0,
1355 s390x_pkey_ecx_keygen448
,
1356 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1357 s390x_pkey_ecx_derive448
,
1361 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth
= {
1362 EVP_PKEY_ED25519
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
1364 s390x_pkey_ecd_keygen25519
,
1365 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1368 s390x_pkey_ecd_digestsign25519
,
1369 s390x_pkey_ecd_digestverify25519
1372 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth
= {
1373 EVP_PKEY_ED448
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
1375 s390x_pkey_ecd_keygen448
,
1376 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1379 s390x_pkey_ecd_digestsign448
,
1380 s390x_pkey_ecd_digestverify448
1384 const EVP_PKEY_METHOD
*ossl_ecx25519_pkey_method(void)
1387 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519
))
1388 return &ecx25519_s390x_pkey_meth
;
1390 return &ecx25519_pkey_meth
;
1393 const EVP_PKEY_METHOD
*ossl_ecx448_pkey_method(void)
1396 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448
))
1397 return &ecx448_s390x_pkey_meth
;
1399 return &ecx448_pkey_meth
;
1402 const EVP_PKEY_METHOD
*ossl_ed25519_pkey_method(void)
1405 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519
)
1406 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519
)
1407 && OPENSSL_s390xcap_P
.kdsa
[0]
1408 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519
))
1409 return &ed25519_s390x_pkey_meth
;
1411 return &ed25519_pkey_meth
;
1414 const EVP_PKEY_METHOD
*ossl_ed448_pkey_method(void)
1417 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448
)
1418 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448
)
1419 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448
))
1420 return &ed448_s390x_pkey_meth
;
1422 return &ed448_pkey_meth
;