2 * Copyright 2006-2023 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_KEYGEN, 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,
829 *siglen = ED25519_SIGSIZE;
833 static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
834 size_t *siglen, const unsigned char *tbs,
837 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
840 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
845 *siglen = ED448_SIGSIZE;
848 if (*siglen < ED448_SIGSIZE) {
849 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
853 if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
854 edkey->privkey, NULL, 0, 0, edkey->propq) == 0)
856 *siglen = ED448_SIGSIZE;
860 static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
861 size_t siglen, const unsigned char *tbs,
864 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
867 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
871 if (siglen != ED25519_SIGSIZE)
874 return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
877 edkey->libctx, edkey->propq);
880 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
881 size_t siglen, const unsigned char *tbs,
884 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
887 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
891 if (siglen != ED448_SIGSIZE)
894 return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
895 NULL, 0, 0, edkey->propq);
898 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
901 case EVP_PKEY_CTRL_MD:
902 /* Only NULL allowed as digest */
903 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
905 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
908 case EVP_PKEY_CTRL_DIGESTINIT:
914 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
915 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
918 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
921 pkey_ecd_digestsign25519,
922 pkey_ecd_digestverify25519
925 static const EVP_PKEY_METHOD ed448_pkey_meth = {
926 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
929 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
932 pkey_ecd_digestsign448,
933 pkey_ecd_digestverify448
937 # include "s390x_arch.h"
939 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
941 static const unsigned char generator[] = {
942 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
943 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
944 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
946 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
948 unsigned char *privkey = NULL, *pubkey;
951 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
955 pubkey = key->pubkey;
957 privkey = ossl_ecx_key_allocate_privkey(key);
958 if (privkey == NULL) {
959 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
963 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
970 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
973 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
976 ossl_ecx_key_free(key);
980 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
982 static const unsigned char generator[] = {
983 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
984 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
985 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
986 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
989 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
991 unsigned char *privkey = NULL, *pubkey;
994 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
998 pubkey = key->pubkey;
1000 privkey = ossl_ecx_key_allocate_privkey(key);
1001 if (privkey == NULL) {
1002 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1006 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1012 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1015 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1018 ossl_ecx_key_free(key);
1022 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1024 static const unsigned char generator_x[] = {
1025 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1026 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1027 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1029 static const unsigned char generator_y[] = {
1030 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1031 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1032 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1034 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1035 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1037 unsigned char *privkey = NULL, *pubkey;
1043 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1047 pubkey = key->pubkey;
1049 privkey = ossl_ecx_key_allocate_privkey(key);
1050 if (privkey == NULL) {
1051 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1055 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1058 md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1062 rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1071 if (s390x_ed25519_mul(x_dst, pubkey,
1072 generator_x, generator_y, buff) != 1)
1075 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1077 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1080 ossl_ecx_key_free(key);
1084 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1086 static const unsigned char generator_x[] = {
1087 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1088 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1089 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1090 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1091 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1093 static const unsigned char generator_y[] = {
1094 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1095 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1096 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1097 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1098 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1100 unsigned char x_dst[57], buff[114];
1101 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1103 unsigned char *privkey = NULL, *pubkey;
1104 EVP_MD_CTX *hashctx = NULL;
1109 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1113 pubkey = key->pubkey;
1115 privkey = ossl_ecx_key_allocate_privkey(key);
1116 if (privkey == NULL) {
1117 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1121 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1124 hashctx = EVP_MD_CTX_new();
1125 if (hashctx == NULL)
1128 md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1132 rv = EVP_DigestInit_ex(hashctx, md, NULL);
1137 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1139 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1146 if (s390x_ed448_mul(x_dst, pubkey,
1147 generator_x, generator_y, buff) != 1)
1150 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1152 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1153 EVP_MD_CTX_free(hashctx);
1156 ossl_ecx_key_free(key);
1157 EVP_MD_CTX_free(hashctx);
1161 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1164 const unsigned char *privkey, *pubkey;
1166 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1168 && s390x_x25519_mul(key, privkey, pubkey) == 0))
1170 *keylen = X25519_KEYLEN;
1174 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1177 const unsigned char *privkey, *pubkey;
1179 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1181 && s390x_x448_mul(key, pubkey, privkey) == 0))
1183 *keylen = X448_KEYLEN;
1187 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1188 unsigned char *sig, size_t *siglen,
1189 const unsigned char *tbs,
1194 unsigned char sig[64];
1195 unsigned char priv[32];
1197 unsigned long long buff[512];
1199 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1202 if (edkey == NULL) {
1203 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1208 *siglen = ED25519_SIGSIZE;
1212 if (*siglen < ED25519_SIGSIZE) {
1213 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1217 memset(¶m, 0, sizeof(param));
1218 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1220 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, ¶m.ed25519, tbs, tbslen);
1221 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1225 s390x_flip_endian32(sig, param.ed25519.sig);
1226 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1228 *siglen = ED25519_SIGSIZE;
1232 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1233 unsigned char *sig, size_t *siglen,
1234 const unsigned char *tbs,
1239 unsigned char sig[128];
1240 unsigned char priv[64];
1242 unsigned long long buff[512];
1244 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1247 if (edkey == NULL) {
1248 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1253 *siglen = ED448_SIGSIZE;
1257 if (*siglen < ED448_SIGSIZE) {
1258 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1262 memset(¶m, 0, sizeof(param));
1263 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1265 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, ¶m.ed448, tbs, tbslen);
1266 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1270 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1271 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1272 memcpy(sig, param.ed448.sig, 57);
1273 memcpy(sig + 57, param.ed448.sig + 64, 57);
1275 *siglen = ED448_SIGSIZE;
1279 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1280 const unsigned char *sig,
1282 const unsigned char *tbs,
1287 unsigned char sig[64];
1288 unsigned char pub[32];
1290 unsigned long long buff[512];
1292 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1294 if (edkey == NULL) {
1295 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1299 if (siglen != ED25519_SIGSIZE)
1302 memset(¶m, 0, sizeof(param));
1303 s390x_flip_endian32(param.ed25519.sig, sig);
1304 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1305 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1307 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1308 ¶m.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1311 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1312 const unsigned char *sig,
1314 const unsigned char *tbs,
1319 unsigned char sig[128];
1320 unsigned char pub[64];
1322 unsigned long long buff[512];
1324 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1326 if (edkey == NULL) {
1327 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1331 if (siglen != ED448_SIGSIZE)
1334 memset(¶m, 0, sizeof(param));
1335 memcpy(param.ed448.sig, sig, 57);
1336 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1337 memcpy(param.ed448.sig + 64, sig + 57, 57);
1338 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1339 memcpy(param.ed448.pub, edkey->pubkey, 57);
1340 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1342 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1343 ¶m.ed448, tbs, tbslen) == 0 ? 1 : 0;
1346 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1348 0, 0, 0, 0, 0, 0, 0,
1349 s390x_pkey_ecx_keygen25519,
1350 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1351 s390x_pkey_ecx_derive25519,
1356 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1358 0, 0, 0, 0, 0, 0, 0,
1359 s390x_pkey_ecx_keygen448,
1360 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1361 s390x_pkey_ecx_derive448,
1365 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1366 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1368 s390x_pkey_ecd_keygen25519,
1369 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1372 s390x_pkey_ecd_digestsign25519,
1373 s390x_pkey_ecd_digestverify25519
1376 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1377 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1379 s390x_pkey_ecd_keygen448,
1380 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1383 s390x_pkey_ecd_digestsign448,
1384 s390x_pkey_ecd_digestverify448
1388 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1391 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1392 return &ecx25519_s390x_pkey_meth;
1394 return &ecx25519_pkey_meth;
1397 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1400 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1401 return &ecx448_s390x_pkey_meth;
1403 return &ecx448_pkey_meth;
1406 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1409 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1410 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1411 && OPENSSL_s390xcap_P.kdsa[0]
1412 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1413 return &ed25519_s390x_pkey_meth;
1415 return &ed25519_pkey_meth;
1418 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1421 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1422 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1423 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1424 return &ed448_s390x_pkey_meth;
1426 return &ed448_pkey_meth;