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));
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_get0_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_get0_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 OSSL_FUNC_keymgmt_import_fn *importer,
350 OSSL_LIB_CTX *libctx, const char *propq)
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 = importer(to_keydata, selection, params);
381 OSSL_PARAM_BLD_free(tmpl);
382 OSSL_PARAM_free(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, *dupkey = NULL;
413 dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL);
418 ret = EVP_PKEY_assign(to, from->type, dupkey);
420 ossl_ecx_key_free(dupkey);
424 static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
426 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
429 const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = {
434 "OpenSSL X25519 algorithm",
478 static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
480 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
483 const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = {
488 "OpenSSL X448 algorithm",
532 static int ecd_size25519(const EVP_PKEY *pkey)
534 return ED25519_SIGSIZE;
537 static int ecd_size448(const EVP_PKEY *pkey)
539 return ED448_SIGSIZE;
542 static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
543 const void *asn, const X509_ALGOR *sigalg,
544 const ASN1_BIT_STRING *str, EVP_PKEY *pkey)
546 const ASN1_OBJECT *obj;
550 /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
551 X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
552 nid = OBJ_obj2nid(obj);
553 if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
554 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
558 if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
564 static int ecd_item_sign(X509_ALGOR *alg1, X509_ALGOR *alg2, int nid)
566 /* Note that X509_ALGOR_set0(..., ..., V_ASN1_UNDEF, ...) cannot fail */
567 /* Set algorithms identifiers */
568 (void)X509_ALGOR_set0(alg1, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
570 (void)X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
571 /* Algorithm identifiers set: carry on as normal */
575 static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
577 X509_ALGOR *alg1, X509_ALGOR *alg2,
578 ASN1_BIT_STRING *str)
580 return ecd_item_sign(alg1, alg2, NID_ED25519);
583 static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
584 const ASN1_STRING *sig)
586 X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
591 static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
593 X509_ALGOR *alg1, X509_ALGOR *alg2,
594 ASN1_BIT_STRING *str)
596 return ecd_item_sign(alg1, alg2, NID_ED448);
599 static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
600 const ASN1_STRING *sig)
602 X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
607 static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
609 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
612 const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
617 "OpenSSL ED25519 algorithm",
642 ecd_sig_info_set25519,
660 static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
662 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
665 const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
670 "OpenSSL ED448 algorithm",
713 static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
715 ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
716 KEY_OP_PUBLIC, NULL, NULL);
719 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
725 static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
727 const unsigned char **privkey,
728 const unsigned char **pubkey)
730 const ECX_KEY *ecxkey, *peerkey;
732 if (ctx->pkey == NULL || ctx->peerkey == NULL) {
733 ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
736 ecxkey = evp_pkey_get_legacy(ctx->pkey);
737 peerkey = evp_pkey_get_legacy(ctx->peerkey);
738 if (ecxkey == NULL || ecxkey->privkey == NULL) {
739 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
742 if (peerkey == NULL) {
743 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
746 *privkey = ecxkey->privkey;
747 *pubkey = peerkey->pubkey;
752 static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
755 const unsigned char *privkey, *pubkey;
757 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
759 && ossl_x25519(key, privkey, pubkey) == 0))
761 *keylen = X25519_KEYLEN;
765 static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
768 const unsigned char *privkey, *pubkey;
770 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
772 && ossl_x448(key, privkey, pubkey) == 0))
774 *keylen = X448_KEYLEN;
778 static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
780 /* Only need to handle peer key for derivation */
781 if (type == EVP_PKEY_CTRL_PEER_KEY)
786 static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
790 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
791 pkey_ecx_derive25519,
796 static const EVP_PKEY_METHOD ecx448_pkey_meth = {
800 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
806 static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
807 size_t *siglen, const unsigned char *tbs,
810 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
813 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
818 *siglen = ED25519_SIGSIZE;
821 if (*siglen < ED25519_SIGSIZE) {
822 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
826 if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
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, 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,
875 edkey->libctx, edkey->propq);
878 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
879 size_t siglen, const unsigned char *tbs,
882 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
885 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
889 if (siglen != ED448_SIGSIZE)
892 return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
893 NULL, 0, edkey->propq);
896 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
899 case EVP_PKEY_CTRL_MD:
900 /* Only NULL allowed as digest */
901 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
903 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
906 case EVP_PKEY_CTRL_DIGESTINIT:
912 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
913 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
916 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
919 pkey_ecd_digestsign25519,
920 pkey_ecd_digestverify25519
923 static const EVP_PKEY_METHOD ed448_pkey_meth = {
924 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
927 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
930 pkey_ecd_digestsign448,
931 pkey_ecd_digestverify448
935 # include "s390x_arch.h"
937 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
939 static const unsigned char generator[] = {
940 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
941 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
942 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
944 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
946 unsigned char *privkey = NULL, *pubkey;
949 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
953 pubkey = key->pubkey;
955 privkey = ossl_ecx_key_allocate_privkey(key);
956 if (privkey == NULL) {
957 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
961 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
968 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
971 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
974 ossl_ecx_key_free(key);
978 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
980 static const unsigned char generator[] = {
981 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
982 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
983 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
984 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
985 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
987 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
989 unsigned char *privkey = NULL, *pubkey;
992 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
996 pubkey = key->pubkey;
998 privkey = ossl_ecx_key_allocate_privkey(key);
999 if (privkey == NULL) {
1000 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1004 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1010 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1013 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1016 ossl_ecx_key_free(key);
1020 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1022 static const unsigned char generator_x[] = {
1023 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1024 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1025 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1027 static const unsigned char generator_y[] = {
1028 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1029 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1030 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1032 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1033 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1035 unsigned char *privkey = NULL, *pubkey;
1041 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1045 pubkey = key->pubkey;
1047 privkey = ossl_ecx_key_allocate_privkey(key);
1048 if (privkey == NULL) {
1049 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1053 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1056 md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1060 rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1069 if (s390x_ed25519_mul(x_dst, pubkey,
1070 generator_x, generator_y, buff) != 1)
1073 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1075 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1078 ossl_ecx_key_free(key);
1082 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1084 static const unsigned char generator_x[] = {
1085 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1086 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1087 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1088 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1089 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1091 static const unsigned char generator_y[] = {
1092 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1093 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1094 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1095 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1096 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1098 unsigned char x_dst[57], buff[114];
1099 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1101 unsigned char *privkey = NULL, *pubkey;
1102 EVP_MD_CTX *hashctx = NULL;
1107 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1111 pubkey = key->pubkey;
1113 privkey = ossl_ecx_key_allocate_privkey(key);
1114 if (privkey == NULL) {
1115 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1119 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1122 hashctx = EVP_MD_CTX_new();
1123 if (hashctx == NULL)
1126 md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1130 rv = EVP_DigestInit_ex(hashctx, md, NULL);
1135 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1137 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1144 if (s390x_ed448_mul(x_dst, pubkey,
1145 generator_x, generator_y, buff) != 1)
1148 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1150 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1151 EVP_MD_CTX_free(hashctx);
1154 ossl_ecx_key_free(key);
1155 EVP_MD_CTX_free(hashctx);
1159 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1162 const unsigned char *privkey, *pubkey;
1164 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1166 && s390x_x25519_mul(key, privkey, pubkey) == 0))
1168 *keylen = X25519_KEYLEN;
1172 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1175 const unsigned char *privkey, *pubkey;
1177 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1179 && s390x_x448_mul(key, pubkey, privkey) == 0))
1181 *keylen = X448_KEYLEN;
1185 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1186 unsigned char *sig, size_t *siglen,
1187 const unsigned char *tbs,
1192 unsigned char sig[64];
1193 unsigned char priv[32];
1195 unsigned long long buff[512];
1197 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1200 if (edkey == NULL) {
1201 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1206 *siglen = ED25519_SIGSIZE;
1210 if (*siglen < ED25519_SIGSIZE) {
1211 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1215 memset(¶m, 0, sizeof(param));
1216 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1218 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, ¶m.ed25519, tbs, tbslen);
1219 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1223 s390x_flip_endian32(sig, param.ed25519.sig);
1224 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1226 *siglen = ED25519_SIGSIZE;
1230 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1231 unsigned char *sig, size_t *siglen,
1232 const unsigned char *tbs,
1237 unsigned char sig[128];
1238 unsigned char priv[64];
1240 unsigned long long buff[512];
1242 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1245 if (edkey == NULL) {
1246 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1251 *siglen = ED448_SIGSIZE;
1255 if (*siglen < ED448_SIGSIZE) {
1256 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1260 memset(¶m, 0, sizeof(param));
1261 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1263 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, ¶m.ed448, tbs, tbslen);
1264 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1268 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1269 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1270 memcpy(sig, param.ed448.sig, 57);
1271 memcpy(sig + 57, param.ed448.sig + 64, 57);
1273 *siglen = ED448_SIGSIZE;
1277 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1278 const unsigned char *sig,
1280 const unsigned char *tbs,
1285 unsigned char sig[64];
1286 unsigned char pub[32];
1288 unsigned long long buff[512];
1290 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1292 if (edkey == NULL) {
1293 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1297 if (siglen != ED25519_SIGSIZE)
1300 memset(¶m, 0, sizeof(param));
1301 s390x_flip_endian32(param.ed25519.sig, sig);
1302 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1303 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1305 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1306 ¶m.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1309 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1310 const unsigned char *sig,
1312 const unsigned char *tbs,
1317 unsigned char sig[128];
1318 unsigned char pub[64];
1320 unsigned long long buff[512];
1322 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1324 if (edkey == NULL) {
1325 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1329 if (siglen != ED448_SIGSIZE)
1332 memset(¶m, 0, sizeof(param));
1333 memcpy(param.ed448.sig, sig, 57);
1334 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1335 memcpy(param.ed448.sig + 64, sig + 57, 57);
1336 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1337 memcpy(param.ed448.pub, edkey->pubkey, 57);
1338 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1340 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1341 ¶m.ed448, tbs, tbslen) == 0 ? 1 : 0;
1344 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1346 0, 0, 0, 0, 0, 0, 0,
1347 s390x_pkey_ecx_keygen25519,
1348 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1349 s390x_pkey_ecx_derive25519,
1354 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1356 0, 0, 0, 0, 0, 0, 0,
1357 s390x_pkey_ecx_keygen448,
1358 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1359 s390x_pkey_ecx_derive448,
1363 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1364 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1366 s390x_pkey_ecd_keygen25519,
1367 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1370 s390x_pkey_ecd_digestsign25519,
1371 s390x_pkey_ecd_digestverify25519
1374 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1375 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1377 s390x_pkey_ecd_keygen448,
1378 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1381 s390x_pkey_ecd_digestsign448,
1382 s390x_pkey_ecd_digestverify448
1386 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1389 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1390 return &ecx25519_s390x_pkey_meth;
1392 return &ecx25519_pkey_meth;
1395 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1398 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1399 return &ecx448_s390x_pkey_meth;
1401 return &ecx448_pkey_meth;
1404 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1407 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1408 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1409 && OPENSSL_s390xcap_P.kdsa[0]
1410 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1411 return &ed25519_s390x_pkey_meth;
1413 return &ed25519_pkey_meth;
1416 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1419 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1420 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1421 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1422 return &ed448_s390x_pkey_meth;
1424 return &ed448_pkey_meth;