Add the ability to ECX to import keys with only the private key
[openssl.git] / providers / implementations / keymgmt / ecx_kmgmt.c
1 /*
2  * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
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
8  */
9
10 #include <assert.h>
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"
23 #ifdef S390X_EC_ASM
24 # include "s390x_arch.h"
25 # include <openssl/sha.h>   /* For SHA512_DIGEST_LENGTH */
26 #endif
27
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_import_fn ecx_import;
51 static OSSL_OP_keymgmt_import_types_fn ecx_imexport_types;
52 static OSSL_OP_keymgmt_export_fn ecx_export;
53 static OSSL_OP_keymgmt_export_types_fn ecx_imexport_types;
54
55 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
56
57 struct ecx_gen_ctx {
58     OPENSSL_CTX *libctx;
59     ECX_KEY_TYPE type;
60 };
61
62 #ifdef S390X_EC_ASM
63 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
64 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
65 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
66 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
67 #endif
68
69 static void *x25519_new_key(void *provctx)
70 {
71     return ecx_key_new(ECX_KEY_TYPE_X25519, 0);
72 }
73
74 static void *x448_new_key(void *provctx)
75 {
76     return ecx_key_new(ECX_KEY_TYPE_X448, 0);
77 }
78
79 static void *ed25519_new_key(void *provctx)
80 {
81     return ecx_key_new(ECX_KEY_TYPE_ED25519, 0);
82 }
83
84 static void *ed448_new_key(void *provctx)
85 {
86     return ecx_key_new(ECX_KEY_TYPE_ED448, 0);
87 }
88
89 static int ecx_has(void *keydata, int selection)
90 {
91     ECX_KEY *key = keydata;
92     int ok = 0;
93
94     if (key != NULL) {
95         if ((selection & ECX_POSSIBLE_SELECTIONS) != 0)
96             ok = 1;
97
98         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
99             ok = ok && key->haspubkey;
100
101         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
102             ok = ok && key->privkey != NULL;
103     }
104     return ok;
105 }
106
107 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
108 {
109     ECX_KEY *key = keydata;
110     int ok = 1;
111     int include_private = 0;
112
113     if (key == NULL)
114         return 0;
115
116     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
117         return 0;
118
119     include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
120     ok = ok && ecx_key_fromdata(key, params, include_private);
121
122     return ok;
123 }
124
125 static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
126                          OSSL_PARAM params[])
127 {
128     if (key == NULL)
129         return 0;
130
131     if (!ossl_param_build_set_octet_string(tmpl, params,
132                                            OSSL_PKEY_PARAM_PUB_KEY,
133                                            key->pubkey, key->keylen))
134         return 0;
135
136     if (key->privkey != NULL
137         && !ossl_param_build_set_octet_string(tmpl, params,
138                                               OSSL_PKEY_PARAM_PRIV_KEY,
139                                               key->privkey, key->keylen))
140         return 0;
141
142     return 1;
143 }
144
145 static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
146                       void *cbarg)
147 {
148     ECX_KEY *key = keydata;
149     OSSL_PARAM_BLD *tmpl;
150     OSSL_PARAM *params = NULL;
151     int ret = 0;
152
153     if (key == NULL)
154         return 0;
155
156     tmpl = OSSL_PARAM_BLD_new();
157     if (tmpl == NULL)
158         return 0;
159
160     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
161          && !key_to_params(key, tmpl, NULL))
162         goto err;
163
164     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
165          && !key_to_params(key, tmpl, NULL))
166         goto err;
167
168     params = OSSL_PARAM_BLD_to_param(tmpl);
169     if (params == NULL)
170         goto err;
171
172     ret = param_cb(params, cbarg);
173     OSSL_PARAM_BLD_free_params(params);
174 err:
175     OSSL_PARAM_BLD_free(tmpl);
176     return ret;
177 }
178
179 #define ECX_KEY_TYPES()                                                        \
180 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),                     \
181 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
182
183 static const OSSL_PARAM ecx_key_types[] = {
184     ECX_KEY_TYPES(),
185     OSSL_PARAM_END
186 };
187 static const OSSL_PARAM *ecx_imexport_types(int selection)
188 {
189     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
190         return ecx_key_types;
191     return NULL;
192 }
193
194 static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
195                           int size)
196 {
197     ECX_KEY *ecx = key;
198     OSSL_PARAM *p;
199
200     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
201         && !OSSL_PARAM_set_int(p, bits))
202         return 0;
203     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
204         && !OSSL_PARAM_set_int(p, secbits))
205         return 0;
206     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
207         && !OSSL_PARAM_set_int(p, size))
208         return 0;
209     return key_to_params(ecx, NULL, params);
210 }
211
212 static int ed_get_params(void *key, OSSL_PARAM params[])
213 {
214     OSSL_PARAM *p;
215
216     if ((p = OSSL_PARAM_locate(params,
217                                OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
218         && !OSSL_PARAM_set_utf8_string(p, ""))
219         return 0;
220     return 1;
221 }
222
223 static int x25519_get_params(void *key, OSSL_PARAM params[])
224 {
225     return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
226                           X25519_KEYLEN);
227 }
228
229 static int x448_get_params(void *key, OSSL_PARAM params[])
230 {
231     return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
232                           X448_KEYLEN);
233 }
234
235 static int ed25519_get_params(void *key, OSSL_PARAM params[])
236 {
237     return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
238                           ED25519_KEYLEN)
239         && ed_get_params(key, params);
240 }
241
242 static int ed448_get_params(void *key, OSSL_PARAM params[])
243 {
244     return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
245                           ED448_KEYLEN)
246         && ed_get_params(key, params);
247 }
248
249 static const OSSL_PARAM ecx_params[] = {
250     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
251     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
252     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
253     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
254     ECX_KEY_TYPES(),
255     OSSL_PARAM_END
256 };
257
258 static const OSSL_PARAM ed_params[] = {
259     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
260     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
261     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
262     ECX_KEY_TYPES(),
263     OSSL_PARAM_END
264 };
265
266 static const OSSL_PARAM *x25519_gettable_params(void)
267 {
268     return ecx_params;
269 }
270
271 static const OSSL_PARAM *x448_gettable_params(void)
272 {
273     return ecx_params;
274 }
275
276 static const OSSL_PARAM *ed25519_gettable_params(void)
277 {
278     return ed_params;
279 }
280
281 static const OSSL_PARAM *ed448_gettable_params(void)
282 {
283     return ed_params;
284 }
285
286 static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type)
287 {
288     OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
289     struct ecx_gen_ctx *gctx = NULL;
290
291     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
292         return NULL;
293
294     if ((gctx = OPENSSL_malloc(sizeof(*gctx))) != NULL) {
295         gctx->libctx = libctx;
296         gctx->type = type;
297     }
298     return gctx;
299 }
300
301 static void *x25519_gen_init(void *provctx, int selection)
302 {
303     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X25519);
304 }
305
306 static void *x448_gen_init(void *provctx, int selection)
307 {
308     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X448);
309 }
310
311 static void *ed25519_gen_init(void *provctx, int selection)
312 {
313     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED25519);
314 }
315
316 static void *ed448_gen_init(void *provctx, int selection)
317 {
318     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448);
319 }
320
321 static void *ecx_gen(struct ecx_gen_ctx *gctx)
322 {
323     ECX_KEY *key;
324     unsigned char *privkey;
325
326     if (gctx == NULL)
327         return NULL;
328     if ((key = ecx_key_new(gctx->type, 0)) == NULL) {
329         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
330         return NULL;
331     }
332     if ((privkey = ecx_key_allocate_privkey(key)) == NULL) {
333         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
334         goto err;
335     }
336     if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0)
337         goto err;
338     switch (gctx->type) {
339     case ECX_KEY_TYPE_X25519:
340         privkey[0] &= 248;
341         privkey[X25519_KEYLEN - 1] &= 127;
342         privkey[X25519_KEYLEN - 1] |= 64;
343         X25519_public_from_private(key->pubkey, privkey);
344         break;
345     case ECX_KEY_TYPE_X448:
346         privkey[0] &= 252;
347         privkey[X448_KEYLEN - 1] |= 128;
348         X448_public_from_private(key->pubkey, privkey);
349         break;
350     case ECX_KEY_TYPE_ED25519:
351         if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey))
352             goto err;
353         break;
354     case ECX_KEY_TYPE_ED448:
355         if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey))
356             goto err;
357         break;
358     }
359     return key;
360 err:
361     ecx_key_free(key);
362     return NULL;
363 }
364
365 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
366 {
367     struct ecx_gen_ctx *gctx = genctx;
368
369 #ifdef S390X_EC_ASM
370     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
371         return s390x_ecx_keygen25519(gctx);
372 #endif
373     return ecx_gen(gctx);
374 }
375
376 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
377 {
378     struct ecx_gen_ctx *gctx = genctx;
379
380 #ifdef S390X_EC_ASM
381     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
382         return s390x_ecx_keygen448(gctx);
383 #endif
384     return ecx_gen(gctx);
385 }
386
387 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
388 {
389     struct ecx_gen_ctx *gctx = genctx;
390 #ifdef S390X_EC_ASM
391     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
392         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
393         && OPENSSL_s390xcap_P.kdsa[0]
394             & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
395         return s390x_ecd_keygen25519(gctx);
396 #endif
397     return ecx_gen(gctx);
398 }
399
400 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
401 {
402     struct ecx_gen_ctx *gctx = genctx;
403
404 #ifdef S390X_EC_ASM
405     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
406         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
407         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
408         return s390x_ecd_keygen448(gctx);
409 #endif
410     return ecx_gen(gctx);
411 }
412
413 static void ecx_gen_cleanup(void *genctx)
414 {
415     struct ecx_gen_ctx *gctx = genctx;
416
417     OPENSSL_free(gctx);
418 }
419
420 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
421     const OSSL_DISPATCH alg##_keymgmt_functions[] = { \
422         { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
423         { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, \
424         { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
425         { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
426         { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
427         { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
428         { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
429         { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
430         { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
431         { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
432         { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
433         { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
434         { 0, NULL } \
435     };
436
437 MAKE_KEYMGMT_FUNCTIONS(x25519)
438 MAKE_KEYMGMT_FUNCTIONS(x448)
439 MAKE_KEYMGMT_FUNCTIONS(ed25519)
440 MAKE_KEYMGMT_FUNCTIONS(ed448)
441
442 #ifdef S390X_EC_ASM
443 # include "s390x_arch.h"
444
445 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
446 {
447     static const unsigned char generator[] = {
448         0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
451     };
452     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X25519, 1);
453     unsigned char *privkey = NULL, *pubkey;
454
455     if (key == NULL) {
456         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
457         goto err;
458     }
459
460     pubkey = key->pubkey;
461
462     privkey = ecx_key_allocate_privkey(key);
463     if (privkey == NULL) {
464         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
465         goto err;
466     }
467
468     if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN) <= 0)
469         goto err;
470
471     privkey[0] &= 248;
472     privkey[31] &= 127;
473     privkey[31] |= 64;
474
475     if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
476         goto err;
477     return key;
478  err:
479     ecx_key_free(key);
480     return NULL;
481 }
482
483 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
484 {
485     static const unsigned char generator[] = {
486         0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
491     };
492     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X448, 1);
493     unsigned char *privkey = NULL, *pubkey;
494
495     if (key == NULL) {
496         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
497         goto err;
498     }
499
500     pubkey = key->pubkey;
501
502     privkey = ecx_key_allocate_privkey(key);
503     if (privkey == NULL) {
504         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
505         goto err;
506     }
507
508     if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN) <= 0)
509         goto err;
510
511     privkey[0] &= 252;
512     privkey[55] |= 128;
513
514     if (s390x_x448_mul(pubkey, generator, privkey) != 1)
515         goto err;
516     return key;
517  err:
518     ecx_key_free(key);
519     return NULL;
520 }
521
522 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
523 {
524     static const unsigned char generator_x[] = {
525         0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
526         0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
527         0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
528     };
529     static const unsigned char generator_y[] = {
530         0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
531         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
532         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
533     };
534     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
535     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED25519, 1);
536     unsigned char *privkey = NULL, *pubkey;
537     unsigned int sz;
538     EVP_MD *sha = NULL;
539     int j;
540
541     if (key == NULL) {
542         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
543         goto err;
544     }
545
546     pubkey = key->pubkey;
547
548     privkey = ecx_key_allocate_privkey(key);
549     if (privkey == NULL) {
550         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
551         goto err;
552     }
553
554     if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN) <= 0)
555         goto err;
556
557     sha = EVP_MD_fetch(gctx->libctx, "SHA512", NULL);
558     if (sha == NULL)
559         goto err;
560     j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
561     EVP_MD_free(sha);
562     if (!j)
563         goto err;
564
565     buff[0] &= 248;
566     buff[31] &= 63;
567     buff[31] |= 64;
568
569     if (s390x_ed25519_mul(x_dst, pubkey,
570                           generator_x, generator_y, buff) != 1)
571         goto err;
572
573     pubkey[31] |= ((x_dst[0] & 0x01) << 7);
574     return key;
575  err:
576     ecx_key_free(key);
577     return NULL;
578 }
579
580 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
581 {
582     static const unsigned char generator_x[] = {
583         0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
584         0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
585         0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
586         0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
587         0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
588     };
589     static const unsigned char generator_y[] = {
590         0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
591         0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
592         0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
593         0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
594         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
595     };
596     unsigned char x_dst[57], buff[114];
597     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED448, 1);
598     unsigned char *privkey = NULL, *pubkey;
599     EVP_MD_CTX *hashctx = NULL;
600     EVP_MD *shake = NULL;
601
602     if (key == NULL) {
603         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
604         goto err;
605     }
606
607     pubkey = key->pubkey;
608
609     privkey = ecx_key_allocate_privkey(key);
610     if (privkey == NULL) {
611         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
612         goto err;
613     }
614
615     shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", NULL);
616     if (shake == NULL)
617         goto err;
618     if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN) <= 0)
619         goto err;
620
621     hashctx = EVP_MD_CTX_new();
622     if (hashctx == NULL)
623         goto err;
624     if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
625         goto err;
626     if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
627         goto err;
628     if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
629         goto err;
630
631     buff[0] &= -4;
632     buff[55] |= 0x80;
633     buff[56] = 0;
634
635     if (s390x_ed448_mul(x_dst, pubkey,
636                         generator_x, generator_y, buff) != 1)
637         goto err;
638
639     pubkey[56] |= ((x_dst[0] & 0x01) << 7);
640     EVP_MD_CTX_free(hashctx);
641     EVP_MD_free(shake);
642     return key;
643  err:
644     ecx_key_free(key);
645     EVP_MD_CTX_free(hashctx);
646     EVP_MD_free(shake);
647     return NULL;
648 }
649 #endif