2 * Copyright 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 #include <openssl/core_numbers.h>
12 #include <openssl/core_names.h>
13 #include <openssl/params.h>
14 #include <openssl/err.h>
15 #include <openssl/evp.h>
16 #include <openssl/rand.h>
17 #include "internal/param_build_set.h"
18 #include "openssl/param_build.h"
19 #include "crypto/ecx.h"
20 #include "prov/implementations.h"
21 #include "prov/providercommon.h"
22 #include "prov/provider_ctx.h"
24 # include "s390x_arch.h"
25 # include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
28 static OSSL_OP_keymgmt_new_fn x25519_new_key;
29 static OSSL_OP_keymgmt_new_fn x448_new_key;
30 static OSSL_OP_keymgmt_new_fn ed25519_new_key;
31 static OSSL_OP_keymgmt_new_fn ed448_new_key;
32 static OSSL_OP_keymgmt_gen_init_fn x25519_gen_init;
33 static OSSL_OP_keymgmt_gen_init_fn x448_gen_init;
34 static OSSL_OP_keymgmt_gen_init_fn ed25519_gen_init;
35 static OSSL_OP_keymgmt_gen_init_fn ed448_gen_init;
36 static OSSL_OP_keymgmt_gen_fn x25519_gen;
37 static OSSL_OP_keymgmt_gen_fn x448_gen;
38 static OSSL_OP_keymgmt_gen_fn ed25519_gen;
39 static OSSL_OP_keymgmt_gen_fn ed448_gen;
40 static OSSL_OP_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
41 static OSSL_OP_keymgmt_get_params_fn x25519_get_params;
42 static OSSL_OP_keymgmt_get_params_fn x448_get_params;
43 static OSSL_OP_keymgmt_get_params_fn ed25519_get_params;
44 static OSSL_OP_keymgmt_get_params_fn ed448_get_params;
45 static OSSL_OP_keymgmt_gettable_params_fn x25519_gettable_params;
46 static OSSL_OP_keymgmt_gettable_params_fn x448_gettable_params;
47 static OSSL_OP_keymgmt_gettable_params_fn ed25519_gettable_params;
48 static OSSL_OP_keymgmt_gettable_params_fn ed448_gettable_params;
49 static OSSL_OP_keymgmt_has_fn ecx_has;
50 static OSSL_OP_keymgmt_match_fn ecx_match;
51 static OSSL_OP_keymgmt_import_fn ecx_import;
52 static OSSL_OP_keymgmt_import_types_fn ecx_imexport_types;
53 static OSSL_OP_keymgmt_export_fn ecx_export;
54 static OSSL_OP_keymgmt_export_types_fn ecx_imexport_types;
56 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
64 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
65 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
66 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
67 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
70 static void *x25519_new_key(void *provctx)
72 return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_X25519, 0);
75 static void *x448_new_key(void *provctx)
77 return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_X448, 0);
80 static void *ed25519_new_key(void *provctx)
82 return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_ED25519, 0);
85 static void *ed448_new_key(void *provctx)
87 return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_ED448, 0);
90 static int ecx_has(void *keydata, int selection)
92 ECX_KEY *key = keydata;
96 if ((selection & ECX_POSSIBLE_SELECTIONS) != 0)
99 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
100 ok = ok && key->haspubkey;
102 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
103 ok = ok && key->privkey != NULL;
108 static int ecx_match(const void *keydata1, const void *keydata2, int selection)
110 const ECX_KEY *key1 = keydata1;
111 const ECX_KEY *key2 = keydata2;
114 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
115 ok = ok && key1->type == key2->type;
116 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
117 if ((key1->privkey == NULL && key2->privkey != NULL)
118 || (key1->privkey != NULL && key2->privkey == NULL)
119 || key1->type != key2->type)
122 ok = ok && (key1->privkey == NULL /* implies key2->privkey == NULL */
123 || CRYPTO_memcmp(key1->privkey, key2->privkey,
126 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
127 if (key1->haspubkey != key2->haspubkey
128 || key1->type != key2->type)
131 ok = ok && (key1->haspubkey == 0 /* implies key2->haspubkey == 0 */
132 || CRYPTO_memcmp(key1->pubkey, key2->pubkey,
138 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
140 ECX_KEY *key = keydata;
142 int include_private = 0;
147 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
150 include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
151 ok = ok && ecx_key_fromdata(key, params, include_private);
156 static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
162 if (!ossl_param_build_set_octet_string(tmpl, params,
163 OSSL_PKEY_PARAM_PUB_KEY,
164 key->pubkey, key->keylen))
167 if (key->privkey != NULL
168 && !ossl_param_build_set_octet_string(tmpl, params,
169 OSSL_PKEY_PARAM_PRIV_KEY,
170 key->privkey, key->keylen))
176 static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
179 ECX_KEY *key = keydata;
180 OSSL_PARAM_BLD *tmpl;
181 OSSL_PARAM *params = NULL;
187 tmpl = OSSL_PARAM_BLD_new();
191 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
192 && !key_to_params(key, tmpl, NULL))
195 params = OSSL_PARAM_BLD_to_param(tmpl);
199 ret = param_cb(params, cbarg);
200 OSSL_PARAM_BLD_free_params(params);
202 OSSL_PARAM_BLD_free(tmpl);
206 #define ECX_KEY_TYPES() \
207 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \
208 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
210 static const OSSL_PARAM ecx_key_types[] = {
214 static const OSSL_PARAM *ecx_imexport_types(int selection)
216 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
217 return ecx_key_types;
221 static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
227 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
228 && !OSSL_PARAM_set_int(p, bits))
230 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
231 && !OSSL_PARAM_set_int(p, secbits))
233 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
234 && !OSSL_PARAM_set_int(p, size))
236 return key_to_params(ecx, NULL, params);
239 static int ed_get_params(void *key, OSSL_PARAM params[])
243 if ((p = OSSL_PARAM_locate(params,
244 OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
245 && !OSSL_PARAM_set_utf8_string(p, ""))
250 static int x25519_get_params(void *key, OSSL_PARAM params[])
252 return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
256 static int x448_get_params(void *key, OSSL_PARAM params[])
258 return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
262 static int ed25519_get_params(void *key, OSSL_PARAM params[])
264 return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
266 && ed_get_params(key, params);
269 static int ed448_get_params(void *key, OSSL_PARAM params[])
271 return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
273 && ed_get_params(key, params);
276 static const OSSL_PARAM ecx_params[] = {
277 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
278 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
279 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
280 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
285 static const OSSL_PARAM ed_params[] = {
286 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
287 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
288 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
293 static const OSSL_PARAM *x25519_gettable_params(void)
298 static const OSSL_PARAM *x448_gettable_params(void)
303 static const OSSL_PARAM *ed25519_gettable_params(void)
308 static const OSSL_PARAM *ed448_gettable_params(void)
313 static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type)
315 OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
316 struct ecx_gen_ctx *gctx = NULL;
318 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
321 if ((gctx = OPENSSL_malloc(sizeof(*gctx))) != NULL) {
322 gctx->libctx = libctx;
328 static void *x25519_gen_init(void *provctx, int selection)
330 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X25519);
333 static void *x448_gen_init(void *provctx, int selection)
335 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X448);
338 static void *ed25519_gen_init(void *provctx, int selection)
340 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED25519);
343 static void *ed448_gen_init(void *provctx, int selection)
345 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448);
348 static void *ecx_gen(struct ecx_gen_ctx *gctx)
351 unsigned char *privkey;
355 if ((key = ecx_key_new(gctx->libctx, gctx->type, 0)) == NULL) {
356 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
359 if ((privkey = ecx_key_allocate_privkey(key)) == NULL) {
360 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
363 if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0)
365 switch (gctx->type) {
366 case ECX_KEY_TYPE_X25519:
368 privkey[X25519_KEYLEN - 1] &= 127;
369 privkey[X25519_KEYLEN - 1] |= 64;
370 X25519_public_from_private(key->pubkey, privkey);
372 case ECX_KEY_TYPE_X448:
374 privkey[X448_KEYLEN - 1] |= 128;
375 X448_public_from_private(key->pubkey, privkey);
377 case ECX_KEY_TYPE_ED25519:
378 if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey))
381 case ECX_KEY_TYPE_ED448:
382 if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey))
392 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
394 struct ecx_gen_ctx *gctx = genctx;
397 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
398 return s390x_ecx_keygen25519(gctx);
400 return ecx_gen(gctx);
403 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
405 struct ecx_gen_ctx *gctx = genctx;
408 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
409 return s390x_ecx_keygen448(gctx);
411 return ecx_gen(gctx);
414 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
416 struct ecx_gen_ctx *gctx = genctx;
418 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
419 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
420 && OPENSSL_s390xcap_P.kdsa[0]
421 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
422 return s390x_ecd_keygen25519(gctx);
424 return ecx_gen(gctx);
427 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
429 struct ecx_gen_ctx *gctx = genctx;
432 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
433 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
434 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
435 return s390x_ecd_keygen448(gctx);
437 return ecx_gen(gctx);
440 static void ecx_gen_cleanup(void *genctx)
442 struct ecx_gen_ctx *gctx = genctx;
447 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
448 const OSSL_DISPATCH alg##_keymgmt_functions[] = { \
449 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
450 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, \
451 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
452 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
453 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
454 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
455 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
456 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
457 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
458 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
459 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
460 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
461 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
465 MAKE_KEYMGMT_FUNCTIONS(x25519)
466 MAKE_KEYMGMT_FUNCTIONS(x448)
467 MAKE_KEYMGMT_FUNCTIONS(ed25519)
468 MAKE_KEYMGMT_FUNCTIONS(ed448)
471 # include "s390x_arch.h"
473 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
475 static const unsigned char generator[] = {
476 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
480 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1);
481 unsigned char *privkey = NULL, *pubkey;
484 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
488 pubkey = key->pubkey;
490 privkey = ecx_key_allocate_privkey(key);
491 if (privkey == NULL) {
492 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
496 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN) <= 0)
503 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
511 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
513 static const unsigned char generator[] = {
514 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
520 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1);
521 unsigned char *privkey = NULL, *pubkey;
524 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
528 pubkey = key->pubkey;
530 privkey = ecx_key_allocate_privkey(key);
531 if (privkey == NULL) {
532 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
536 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN) <= 0)
542 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
550 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
552 static const unsigned char generator_x[] = {
553 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
554 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
555 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
557 static const unsigned char generator_y[] = {
558 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
559 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
560 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
562 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
563 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1);
564 unsigned char *privkey = NULL, *pubkey;
570 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
574 pubkey = key->pubkey;
576 privkey = ecx_key_allocate_privkey(key);
577 if (privkey == NULL) {
578 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
582 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN) <= 0)
585 sha = EVP_MD_fetch(gctx->libctx, "SHA512", NULL);
588 j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
597 if (s390x_ed25519_mul(x_dst, pubkey,
598 generator_x, generator_y, buff) != 1)
601 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
608 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
610 static const unsigned char generator_x[] = {
611 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
612 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
613 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
614 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
615 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
617 static const unsigned char generator_y[] = {
618 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
619 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
620 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
621 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
622 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
624 unsigned char x_dst[57], buff[114];
625 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1);
626 unsigned char *privkey = NULL, *pubkey;
627 EVP_MD_CTX *hashctx = NULL;
628 EVP_MD *shake = NULL;
631 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
635 pubkey = key->pubkey;
637 privkey = ecx_key_allocate_privkey(key);
638 if (privkey == NULL) {
639 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
643 shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", NULL);
646 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN) <= 0)
649 hashctx = EVP_MD_CTX_new();
652 if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
654 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
656 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
663 if (s390x_ed448_mul(x_dst, pubkey,
664 generator_x, generator_y, buff) != 1)
667 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
668 EVP_MD_CTX_free(hashctx);
673 EVP_MD_CTX_free(hashctx);