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 *siglen = ED25519_SIGSIZE;
816 if (*siglen < ED25519_SIGSIZE) {
817 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
821 if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
824 *siglen = ED25519_SIGSIZE;
828 static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
829 size_t *siglen, const unsigned char *tbs,
832 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
835 *siglen = ED448_SIGSIZE;
838 if (*siglen < ED448_SIGSIZE) {
839 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
843 if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
844 edkey->privkey, NULL, 0, edkey->propq) == 0)
846 *siglen = ED448_SIGSIZE;
850 static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
851 size_t siglen, const unsigned char *tbs,
854 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
856 if (siglen != ED25519_SIGSIZE)
859 return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
860 edkey->libctx, edkey->propq);
863 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
864 size_t siglen, const unsigned char *tbs,
867 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
869 if (siglen != ED448_SIGSIZE)
872 return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
873 NULL, 0, edkey->propq);
876 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
879 case EVP_PKEY_CTRL_MD:
880 /* Only NULL allowed as digest */
881 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
883 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
886 case EVP_PKEY_CTRL_DIGESTINIT:
892 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
893 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
896 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
899 pkey_ecd_digestsign25519,
900 pkey_ecd_digestverify25519
903 static const EVP_PKEY_METHOD ed448_pkey_meth = {
904 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
907 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
910 pkey_ecd_digestsign448,
911 pkey_ecd_digestverify448
915 # include "s390x_arch.h"
917 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
919 static const unsigned char generator[] = {
920 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
922 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
924 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
926 unsigned char *privkey = NULL, *pubkey;
929 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
933 pubkey = key->pubkey;
935 privkey = ossl_ecx_key_allocate_privkey(key);
936 if (privkey == NULL) {
937 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
941 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
948 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
951 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
954 ossl_ecx_key_free(key);
958 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
960 static const unsigned char generator[] = {
961 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
963 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
964 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
965 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
967 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
969 unsigned char *privkey = NULL, *pubkey;
972 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
976 pubkey = key->pubkey;
978 privkey = ossl_ecx_key_allocate_privkey(key);
979 if (privkey == NULL) {
980 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
984 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
990 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
993 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
996 ossl_ecx_key_free(key);
1000 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1002 static const unsigned char generator_x[] = {
1003 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1004 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1005 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1007 static const unsigned char generator_y[] = {
1008 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1009 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1010 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1012 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1013 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1015 unsigned char *privkey = NULL, *pubkey;
1021 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1025 pubkey = key->pubkey;
1027 privkey = ossl_ecx_key_allocate_privkey(key);
1028 if (privkey == NULL) {
1029 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1033 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1036 md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1040 rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1049 if (s390x_ed25519_mul(x_dst, pubkey,
1050 generator_x, generator_y, buff) != 1)
1053 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1055 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1058 ossl_ecx_key_free(key);
1062 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1064 static const unsigned char generator_x[] = {
1065 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1066 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1067 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1068 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1069 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1071 static const unsigned char generator_y[] = {
1072 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1073 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1074 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1075 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1076 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1078 unsigned char x_dst[57], buff[114];
1079 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1081 unsigned char *privkey = NULL, *pubkey;
1082 EVP_MD_CTX *hashctx = NULL;
1087 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1091 pubkey = key->pubkey;
1093 privkey = ossl_ecx_key_allocate_privkey(key);
1094 if (privkey == NULL) {
1095 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1099 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1102 hashctx = EVP_MD_CTX_new();
1103 if (hashctx == NULL)
1106 md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1110 rv = EVP_DigestInit_ex(hashctx, md, NULL);
1115 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1117 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1124 if (s390x_ed448_mul(x_dst, pubkey,
1125 generator_x, generator_y, buff) != 1)
1128 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1130 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1131 EVP_MD_CTX_free(hashctx);
1134 ossl_ecx_key_free(key);
1135 EVP_MD_CTX_free(hashctx);
1139 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1142 const unsigned char *privkey, *pubkey;
1144 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1148 return s390x_x25519_mul(key, pubkey, privkey);
1150 *keylen = X25519_KEYLEN;
1154 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1157 const unsigned char *privkey, *pubkey;
1159 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1163 return s390x_x448_mul(key, pubkey, privkey);
1165 *keylen = X448_KEYLEN;
1169 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1170 unsigned char *sig, size_t *siglen,
1171 const unsigned char *tbs,
1176 unsigned char sig[64];
1177 unsigned char priv[32];
1179 unsigned long long buff[512];
1181 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1185 *siglen = ED25519_SIGSIZE;
1189 if (*siglen < ED25519_SIGSIZE) {
1190 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1194 memset(¶m, 0, sizeof(param));
1195 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1197 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, ¶m.ed25519, tbs, tbslen);
1198 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1202 s390x_flip_endian32(sig, param.ed25519.sig);
1203 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1205 *siglen = ED25519_SIGSIZE;
1209 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1210 unsigned char *sig, size_t *siglen,
1211 const unsigned char *tbs,
1216 unsigned char sig[128];
1217 unsigned char priv[64];
1219 unsigned long long buff[512];
1221 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1225 *siglen = ED448_SIGSIZE;
1229 if (*siglen < ED448_SIGSIZE) {
1230 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1234 memset(¶m, 0, sizeof(param));
1235 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1237 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, ¶m.ed448, tbs, tbslen);
1238 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1242 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1243 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1244 memcpy(sig, param.ed448.sig, 57);
1245 memcpy(sig + 57, param.ed448.sig + 64, 57);
1247 *siglen = ED448_SIGSIZE;
1251 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1252 const unsigned char *sig,
1254 const unsigned char *tbs,
1259 unsigned char sig[64];
1260 unsigned char pub[32];
1262 unsigned long long buff[512];
1264 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1266 if (siglen != ED25519_SIGSIZE)
1269 memset(¶m, 0, sizeof(param));
1270 s390x_flip_endian32(param.ed25519.sig, sig);
1271 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1272 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1274 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1275 ¶m.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1278 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1279 const unsigned char *sig,
1281 const unsigned char *tbs,
1286 unsigned char sig[128];
1287 unsigned char pub[64];
1289 unsigned long long buff[512];
1291 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1293 if (siglen != ED448_SIGSIZE)
1296 memset(¶m, 0, sizeof(param));
1297 memcpy(param.ed448.sig, sig, 57);
1298 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1299 memcpy(param.ed448.sig + 64, sig + 57, 57);
1300 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1301 memcpy(param.ed448.pub, edkey->pubkey, 57);
1302 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1304 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1305 ¶m.ed448, tbs, tbslen) == 0 ? 1 : 0;
1308 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1310 0, 0, 0, 0, 0, 0, 0,
1311 s390x_pkey_ecx_keygen25519,
1312 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1313 s390x_pkey_ecx_derive25519,
1318 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1320 0, 0, 0, 0, 0, 0, 0,
1321 s390x_pkey_ecx_keygen448,
1322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1323 s390x_pkey_ecx_derive448,
1327 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1328 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1330 s390x_pkey_ecd_keygen25519,
1331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1334 s390x_pkey_ecd_digestsign25519,
1335 s390x_pkey_ecd_digestverify25519
1338 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1339 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1341 s390x_pkey_ecd_keygen448,
1342 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1345 s390x_pkey_ecd_digestsign448,
1346 s390x_pkey_ecd_digestverify448
1350 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1353 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1354 return &ecx25519_s390x_pkey_meth;
1356 return &ecx25519_pkey_meth;
1359 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1362 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1363 return &ecx448_s390x_pkey_meth;
1365 return &ecx448_pkey_meth;
1368 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1371 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1372 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1373 && OPENSSL_s390xcap_P.kdsa[0]
1374 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1375 return &ed25519_s390x_pkey_meth;
1377 return &ed25519_pkey_meth;
1380 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1383 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1384 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1385 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1386 return &ed448_s390x_pkey_meth;
1388 return &ed448_pkey_meth;