2 * Copyright 2006-2020 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 "internal/cryptlib.h"
18 #include <openssl/x509.h>
19 #include <openssl/ec.h>
20 #include <openssl/rand.h>
21 #include <openssl/core_names.h>
22 #include "openssl/param_build.h"
23 #include "crypto/asn1.h"
24 #include "crypto/evp.h"
25 #include "crypto/ecx.h"
27 #include "curve448/curve448_local.h"
28 #include "ecx_backend.h"
36 /* Setup EVP_PKEY using public, private or generation */
37 static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
38 const unsigned char *p, int plen, ecx_key_op_t op,
39 OPENSSL_CTX *libctx, const char *propq)
42 unsigned char *privkey, *pubkey;
44 if (op != KEY_OP_KEYGEN) {
48 /* Algorithm parameters must be absent */
49 X509_ALGOR_get0(NULL, &ptype, NULL, palg);
50 if (ptype != V_ASN1_UNDEF) {
51 ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
56 if (p == NULL || plen != KEYLENID(id)) {
57 ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
62 key = ecx_key_new(libctx, KEYNID2TYPE(id), 1);
64 ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
69 if (op == KEY_OP_PUBLIC) {
70 memcpy(pubkey, p, plen);
72 privkey = ecx_key_allocate_privkey(key);
73 if (privkey == NULL) {
74 ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
77 if (op == KEY_OP_KEYGEN) {
78 if (RAND_priv_bytes(privkey, KEYLENID(id)) <= 0)
80 if (id == EVP_PKEY_X25519) {
82 privkey[X25519_KEYLEN - 1] &= 127;
83 privkey[X25519_KEYLEN - 1] |= 64;
84 } else if (id == EVP_PKEY_X448) {
86 privkey[X448_KEYLEN - 1] |= 128;
89 memcpy(privkey, p, KEYLENID(id));
91 if (!ecx_public_from_private(key)) {
92 ECerr(EC_F_ECX_KEY_OP, EC_R_FAILED_MAKING_PUBLIC_KEY);
97 EVP_PKEY_assign(pkey, id, key);
104 static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
106 const ECX_KEY *ecxkey = pkey->pkey.ecx;
109 if (ecxkey == NULL) {
110 ECerr(EC_F_ECX_PUB_ENCODE, EC_R_INVALID_KEY);
114 penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
116 ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
120 if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
121 V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
123 ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
129 static int ecx_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
131 const unsigned char *p;
135 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
137 return ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, pklen,
138 KEY_OP_PUBLIC, NULL, NULL);
141 static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
143 const ECX_KEY *akey = a->pkey.ecx;
144 const ECX_KEY *bkey = b->pkey.ecx;
146 if (akey == NULL || bkey == NULL)
149 return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
152 static int ecx_priv_decode_with_libctx(EVP_PKEY *pkey,
153 const PKCS8_PRIV_KEY_INFO *p8,
154 OPENSSL_CTX *libctx, const char *propq)
156 const unsigned char *p;
158 ASN1_OCTET_STRING *oct = NULL;
159 const X509_ALGOR *palg;
162 if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8))
165 oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen);
170 p = ASN1_STRING_get0_data(oct);
171 plen = ASN1_STRING_length(oct);
174 rv = ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, plen, KEY_OP_PRIVATE,
176 ASN1_STRING_clear_free(oct);
180 static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
182 const ECX_KEY *ecxkey = pkey->pkey.ecx;
183 ASN1_OCTET_STRING oct;
184 unsigned char *penc = NULL;
187 if (ecxkey == NULL || ecxkey->privkey == NULL) {
188 ECerr(EC_F_ECX_PRIV_ENCODE, EC_R_INVALID_PRIVATE_KEY);
192 oct.data = ecxkey->privkey;
193 oct.length = KEYLEN(pkey);
196 penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
198 ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
202 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
203 V_ASN1_UNDEF, NULL, penc, penclen)) {
204 OPENSSL_clear_free(penc, penclen);
205 ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
212 static int ecx_size(const EVP_PKEY *pkey)
217 static int ecx_bits(const EVP_PKEY *pkey)
219 if (IS25519(pkey->ameth->pkey_id)) {
221 } else if(ISX448(pkey->ameth->pkey_id)) {
228 static int ecx_security_bits(const EVP_PKEY *pkey)
230 if (IS25519(pkey->ameth->pkey_id)) {
231 return X25519_SECURITY_BITS;
233 return X448_SECURITY_BITS;
237 static void ecx_free(EVP_PKEY *pkey)
239 ecx_key_free(pkey->pkey.ecx);
242 /* "parameters" are always equal */
243 static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
248 static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
249 ASN1_PCTX *ctx, ecx_key_op_t op)
251 const ECX_KEY *ecxkey = pkey->pkey.ecx;
252 const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
254 if (op == KEY_OP_PRIVATE) {
255 if (ecxkey == NULL || ecxkey->privkey == NULL) {
256 if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
260 if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
262 if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
264 if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
268 if (ecxkey == NULL) {
269 if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
273 if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
276 if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
279 if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
285 static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
288 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
291 static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
294 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
297 static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
301 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
302 return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, arg2, arg1,
303 KEY_OP_PUBLIC, NULL, NULL);
305 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
306 if (pkey->pkey.ecx != NULL) {
307 unsigned char **ppt = arg2;
309 *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
321 static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
324 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
325 /* We currently only support Pure EdDSA which takes no digest */
326 *(int *)arg2 = NID_undef;
335 static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
338 /* TODO(3.0): We should pass a libctx here */
339 return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, priv, len,
340 KEY_OP_PRIVATE, NULL, NULL);
343 static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
345 return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, pub, len,
346 KEY_OP_PUBLIC, NULL, NULL);
349 static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
352 const ECX_KEY *key = pkey->pkey.ecx;
355 *len = KEYLENID(pkey->ameth->pkey_id);
360 || key->privkey == NULL
361 || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
364 *len = KEYLENID(pkey->ameth->pkey_id);
365 memcpy(priv, key->privkey, *len);
370 static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
373 const ECX_KEY *key = pkey->pkey.ecx;
376 *len = KEYLENID(pkey->ameth->pkey_id);
381 || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
384 *len = KEYLENID(pkey->ameth->pkey_id);
385 memcpy(pub, key->pubkey, *len);
390 static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey)
393 * We provide no mechanism to "update" an ECX key once it has been set,
394 * therefore we do not have to maintain a dirty count.
399 static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
400 EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx,
403 const ECX_KEY *key = from->pkey.ecx;
404 OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
405 OSSL_PARAM *params = NULL;
412 /* A key must at least have a public part */
413 if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
414 key->pubkey, key->keylen))
416 selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
418 if (key->privkey != NULL) {
419 if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
420 OSSL_PKEY_PARAM_PRIV_KEY,
421 key->privkey, key->keylen))
423 selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
426 params = OSSL_PARAM_BLD_to_param(tmpl);
428 /* We export, the provider imports */
429 rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
432 OSSL_PARAM_BLD_free(tmpl);
433 OSSL_PARAM_BLD_free_params(params);
437 static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
440 EVP_PKEY_CTX *pctx = vpctx;
441 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
442 ECX_KEY *ecx = ecx_key_new(pctx->libctx, KEYNID2TYPE(keytype), 0);
445 ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
449 if (!ecx_key_fromdata(ecx, params, 1)
450 || !EVP_PKEY_assign(pkey, keytype, ecx)) {
457 static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
459 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
462 const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
467 "OpenSSL X25519 algorithm",
507 ecx_priv_decode_with_libctx
510 static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
512 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
515 const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
520 "OpenSSL X448 algorithm",
560 ecx_priv_decode_with_libctx
563 static int ecd_size25519(const EVP_PKEY *pkey)
565 return ED25519_SIGSIZE;
568 static int ecd_size448(const EVP_PKEY *pkey)
570 return ED448_SIGSIZE;
573 static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
574 const void *asn, const X509_ALGOR *sigalg,
575 const ASN1_BIT_STRING *str, EVP_PKEY *pkey)
577 const ASN1_OBJECT *obj;
581 /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
582 X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
583 nid = OBJ_obj2nid(obj);
584 if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
585 ECerr(EC_F_ECD_ITEM_VERIFY, EC_R_INVALID_ENCODING);
589 if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
595 static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
597 X509_ALGOR *alg1, X509_ALGOR *alg2,
598 ASN1_BIT_STRING *str)
600 /* Set algorithms identifiers */
601 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
603 X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
604 /* Algorithm identifiers set: carry on as normal */
608 static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
609 const ASN1_STRING *sig)
611 X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
616 static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
618 X509_ALGOR *alg1, X509_ALGOR *alg2,
619 ASN1_BIT_STRING *str)
621 /* Set algorithm identifier */
622 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
624 X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
625 /* Algorithm identifier set: carry on as normal */
629 static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
630 const ASN1_STRING *sig)
632 X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
637 static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
639 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
642 const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
647 "OpenSSL ED25519 algorithm",
672 ecd_sig_info_set25519,
686 ecx_priv_decode_with_libctx
689 static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
691 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
694 const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
699 "OpenSSL ED448 algorithm",
738 ecx_priv_decode_with_libctx
741 static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
743 return ecx_key_op(pkey, ctx->pmeth->pkey_id, NULL, NULL, 0, KEY_OP_KEYGEN,
747 static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
749 const unsigned char **privkey,
750 const unsigned char **pubkey)
752 const ECX_KEY *ecxkey, *peerkey;
754 if (ctx->pkey == NULL || ctx->peerkey == NULL) {
755 ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_KEYS_NOT_SET);
758 ecxkey = ctx->pkey->pkey.ecx;
759 peerkey = ctx->peerkey->pkey.ecx;
760 if (ecxkey == NULL || ecxkey->privkey == NULL) {
761 ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PRIVATE_KEY);
764 if (peerkey == NULL) {
765 ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PEER_KEY);
768 *privkey = ecxkey->privkey;
769 *pubkey = peerkey->pubkey;
774 static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
777 const unsigned char *privkey, *pubkey;
779 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
781 && X25519(key, privkey, pubkey) == 0))
783 *keylen = X25519_KEYLEN;
787 static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
790 const unsigned char *privkey, *pubkey;
792 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
794 && X448(key, privkey, pubkey) == 0))
796 *keylen = X448_KEYLEN;
800 static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
802 /* Only need to handle peer key for derivation */
803 if (type == EVP_PKEY_CTRL_PEER_KEY)
808 static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
812 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
813 pkey_ecx_derive25519,
818 static const EVP_PKEY_METHOD ecx448_pkey_meth = {
822 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
828 static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
829 size_t *siglen, const unsigned char *tbs,
832 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
835 *siglen = ED25519_SIGSIZE;
838 if (*siglen < ED25519_SIGSIZE) {
839 ECerr(EC_F_PKEY_ECD_DIGESTSIGN25519, EC_R_BUFFER_TOO_SMALL);
843 if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
846 *siglen = ED25519_SIGSIZE;
850 static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
851 size_t *siglen, const unsigned char *tbs,
854 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
857 *siglen = ED448_SIGSIZE;
860 if (*siglen < ED448_SIGSIZE) {
861 ECerr(EC_F_PKEY_ECD_DIGESTSIGN448, EC_R_BUFFER_TOO_SMALL);
866 * TODO(3.0): We use NULL for the library context for now. Will need to
869 if (ED448_sign(NULL, sig, tbs, tbslen, edkey->pubkey, edkey->privkey,
872 *siglen = ED448_SIGSIZE;
876 static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
877 size_t siglen, const unsigned char *tbs,
880 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
882 if (siglen != ED25519_SIGSIZE)
885 return ED25519_verify(tbs, tbslen, sig, edkey->pubkey, NULL, NULL);
888 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
889 size_t siglen, const unsigned char *tbs,
892 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
894 if (siglen != ED448_SIGSIZE)
898 * TODO(3.0): We send NULL for the OPENSSL_CTX for now. This will need to
901 return ED448_verify(NULL, tbs, tbslen, sig, edkey->pubkey, NULL, 0);
904 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
907 case EVP_PKEY_CTRL_MD:
908 /* Only NULL allowed as digest */
909 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
911 ECerr(EC_F_PKEY_ECD_CTRL, EC_R_INVALID_DIGEST_TYPE);
914 case EVP_PKEY_CTRL_DIGESTINIT:
920 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
921 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
924 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
927 pkey_ecd_digestsign25519,
928 pkey_ecd_digestverify25519
931 static const EVP_PKEY_METHOD ed448_pkey_meth = {
932 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
935 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
938 pkey_ecd_digestsign448,
939 pkey_ecd_digestverify448
943 # include "s390x_arch.h"
945 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
947 static const unsigned char generator[] = {
948 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
949 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
950 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
952 ECX_KEY *key = ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1);
953 unsigned char *privkey = NULL, *pubkey;
956 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN25519, ERR_R_MALLOC_FAILURE);
960 pubkey = key->pubkey;
962 privkey = ecx_key_allocate_privkey(key);
963 if (privkey == NULL) {
964 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN25519, ERR_R_MALLOC_FAILURE);
968 if (RAND_priv_bytes(privkey, X25519_KEYLEN) <= 0)
975 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
978 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
985 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
987 static const unsigned char generator[] = {
988 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
989 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
990 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
992 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
994 ECX_KEY *key = ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1);
995 unsigned char *privkey = NULL, *pubkey;
998 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN448, ERR_R_MALLOC_FAILURE);
1002 pubkey = key->pubkey;
1004 privkey = ecx_key_allocate_privkey(key);
1005 if (privkey == NULL) {
1006 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN448, ERR_R_MALLOC_FAILURE);
1010 if (RAND_priv_bytes(privkey, X448_KEYLEN) <= 0)
1016 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1019 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1026 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1028 static const unsigned char generator_x[] = {
1029 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1030 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1031 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1033 static const unsigned char generator_y[] = {
1034 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1035 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1036 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1038 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1039 ECX_KEY *key = ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1);
1040 unsigned char *privkey = NULL, *pubkey;
1044 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN25519, ERR_R_MALLOC_FAILURE);
1048 pubkey = key->pubkey;
1050 privkey = ecx_key_allocate_privkey(key);
1051 if (privkey == NULL) {
1052 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN25519, ERR_R_MALLOC_FAILURE);
1056 if (RAND_priv_bytes(privkey, ED25519_KEYLEN) <= 0)
1059 if (!EVP_Digest(privkey, 32, buff, &sz, EVP_sha512(), NULL))
1066 if (s390x_ed25519_mul(x_dst, pubkey,
1067 generator_x, generator_y, buff) != 1)
1070 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1072 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1079 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1081 static const unsigned char generator_x[] = {
1082 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1083 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1084 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1085 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1086 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1088 static const unsigned char generator_y[] = {
1089 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1090 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1091 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1092 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1093 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1095 unsigned char x_dst[57], buff[114];
1096 ECX_KEY *key = ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1);
1097 unsigned char *privkey = NULL, *pubkey;
1098 EVP_MD_CTX *hashctx = NULL;
1101 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN448, ERR_R_MALLOC_FAILURE);
1105 pubkey = key->pubkey;
1107 privkey = ecx_key_allocate_privkey(key);
1108 if (privkey == NULL) {
1109 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN448, ERR_R_MALLOC_FAILURE);
1113 if (RAND_priv_bytes(privkey, ED448_KEYLEN) <= 0)
1116 hashctx = EVP_MD_CTX_new();
1117 if (hashctx == NULL)
1119 if (EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL) != 1)
1121 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1123 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1130 if (s390x_ed448_mul(x_dst, pubkey,
1131 generator_x, generator_y, buff) != 1)
1134 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1136 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1137 EVP_MD_CTX_free(hashctx);
1141 EVP_MD_CTX_free(hashctx);
1145 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1148 const unsigned char *privkey, *pubkey;
1150 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1154 return s390x_x25519_mul(key, pubkey, privkey);
1156 *keylen = X25519_KEYLEN;
1160 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1163 const unsigned char *privkey, *pubkey;
1165 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1169 return s390x_x448_mul(key, pubkey, privkey);
1171 *keylen = X448_KEYLEN;
1175 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1176 unsigned char *sig, size_t *siglen,
1177 const unsigned char *tbs,
1182 unsigned char sig[64];
1183 unsigned char priv[32];
1185 unsigned long long buff[512];
1187 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1191 *siglen = ED25519_SIGSIZE;
1195 if (*siglen < ED25519_SIGSIZE) {
1196 ECerr(EC_F_S390X_PKEY_ECD_DIGESTSIGN25519, EC_R_BUFFER_TOO_SMALL);
1200 memset(¶m, 0, sizeof(param));
1201 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1203 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, ¶m.ed25519, tbs, tbslen);
1204 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1208 s390x_flip_endian32(sig, param.ed25519.sig);
1209 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1211 *siglen = ED25519_SIGSIZE;
1215 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1216 unsigned char *sig, size_t *siglen,
1217 const unsigned char *tbs,
1222 unsigned char sig[128];
1223 unsigned char priv[64];
1225 unsigned long long buff[512];
1227 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1231 *siglen = ED448_SIGSIZE;
1235 if (*siglen < ED448_SIGSIZE) {
1236 ECerr(EC_F_S390X_PKEY_ECD_DIGESTSIGN448, EC_R_BUFFER_TOO_SMALL);
1240 memset(¶m, 0, sizeof(param));
1241 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1243 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, ¶m.ed448, tbs, tbslen);
1244 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1248 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1249 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1250 memcpy(sig, param.ed448.sig, 57);
1251 memcpy(sig + 57, param.ed448.sig + 64, 57);
1253 *siglen = ED448_SIGSIZE;
1257 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1258 const unsigned char *sig,
1260 const unsigned char *tbs,
1265 unsigned char sig[64];
1266 unsigned char pub[32];
1268 unsigned long long buff[512];
1270 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1272 if (siglen != ED25519_SIGSIZE)
1275 memset(¶m, 0, sizeof(param));
1276 s390x_flip_endian32(param.ed25519.sig, sig);
1277 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1278 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1280 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1281 ¶m.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1284 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1285 const unsigned char *sig,
1287 const unsigned char *tbs,
1292 unsigned char sig[128];
1293 unsigned char pub[64];
1295 unsigned long long buff[512];
1297 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1299 if (siglen != ED448_SIGSIZE)
1302 memset(¶m, 0, sizeof(param));
1303 memcpy(param.ed448.sig, sig, 57);
1304 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1305 memcpy(param.ed448.sig + 64, sig + 57, 57);
1306 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1307 memcpy(param.ed448.pub, edkey->pubkey, 57);
1308 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1310 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1311 ¶m.ed448, tbs, tbslen) == 0 ? 1 : 0;
1314 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1316 0, 0, 0, 0, 0, 0, 0,
1317 s390x_pkey_ecx_keygen25519,
1318 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1319 s390x_pkey_ecx_derive25519,
1324 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1326 0, 0, 0, 0, 0, 0, 0,
1327 s390x_pkey_ecx_keygen448,
1328 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1329 s390x_pkey_ecx_derive448,
1333 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1334 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1336 s390x_pkey_ecd_keygen25519,
1337 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1340 s390x_pkey_ecd_digestsign25519,
1341 s390x_pkey_ecd_digestverify25519
1344 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1345 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1347 s390x_pkey_ecd_keygen448,
1348 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1351 s390x_pkey_ecd_digestsign448,
1352 s390x_pkey_ecd_digestverify448
1356 const EVP_PKEY_METHOD *ecx25519_pkey_method(void)
1359 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1360 return &ecx25519_s390x_pkey_meth;
1362 return &ecx25519_pkey_meth;
1365 const EVP_PKEY_METHOD *ecx448_pkey_method(void)
1368 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1369 return &ecx448_s390x_pkey_meth;
1371 return &ecx448_pkey_meth;
1374 const EVP_PKEY_METHOD *ed25519_pkey_method(void)
1377 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1378 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1379 && OPENSSL_s390xcap_P.kdsa[0]
1380 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1381 return &ed25519_s390x_pkey_meth;
1383 return &ed25519_pkey_meth;
1386 const EVP_PKEY_METHOD *ed448_pkey_method(void)
1389 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1390 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1391 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1392 return &ed448_s390x_pkey_meth;
1394 return &ed448_pkey_meth;