e2b613e5e08bf62a89d0d1cd07ee007814b6bb7d
[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_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;
55
56 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
57
58 struct ecx_gen_ctx {
59     OPENSSL_CTX *libctx;
60     ECX_KEY_TYPE type;
61 };
62
63 #ifdef S390X_EC_ASM
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);
68 #endif
69
70 static void *x25519_new_key(void *provctx)
71 {
72     return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_X25519, 0);
73 }
74
75 static void *x448_new_key(void *provctx)
76 {
77     return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_X448, 0);
78 }
79
80 static void *ed25519_new_key(void *provctx)
81 {
82     return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_ED25519, 0);
83 }
84
85 static void *ed448_new_key(void *provctx)
86 {
87     return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_ED448, 0);
88 }
89
90 static int ecx_has(void *keydata, int selection)
91 {
92     ECX_KEY *key = keydata;
93     int ok = 0;
94
95     if (key != NULL) {
96         if ((selection & ECX_POSSIBLE_SELECTIONS) != 0)
97             ok = 1;
98
99         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
100             ok = ok && key->haspubkey;
101
102         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
103             ok = ok && key->privkey != NULL;
104     }
105     return ok;
106 }
107
108 static int ecx_match(const void *keydata1, const void *keydata2, int selection)
109 {
110     const ECX_KEY *key1 = keydata1;
111     const ECX_KEY *key2 = keydata2;
112     int ok = 1;
113
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)
120             ok = 0;
121         else
122             ok = ok && (key1->privkey == NULL /* implies key2->privkey == NULL */
123                         || CRYPTO_memcmp(key1->privkey, key2->privkey,
124                                          key1->keylen) == 0);
125     }
126     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
127         if (key1->haspubkey != key2->haspubkey
128                 || key1->type != key2->type)
129             ok = 0;
130         else
131             ok = ok && (key1->haspubkey == 0 /* implies key2->haspubkey == 0 */
132                         || CRYPTO_memcmp(key1->pubkey, key2->pubkey,
133                                          key1->keylen) == 0);
134     }
135     return ok;
136 }
137
138 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
139 {
140     ECX_KEY *key = keydata;
141     int ok = 1;
142     int include_private = 0;
143
144     if (key == NULL)
145         return 0;
146
147     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
148         return 0;
149
150     include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
151     ok = ok && ecx_key_fromdata(key, params, include_private);
152
153     return ok;
154 }
155
156 static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
157                          OSSL_PARAM params[])
158 {
159     if (key == NULL)
160         return 0;
161
162     if (!ossl_param_build_set_octet_string(tmpl, params,
163                                            OSSL_PKEY_PARAM_PUB_KEY,
164                                            key->pubkey, key->keylen))
165         return 0;
166
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))
171         return 0;
172
173     return 1;
174 }
175
176 static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
177                       void *cbarg)
178 {
179     ECX_KEY *key = keydata;
180     OSSL_PARAM_BLD *tmpl;
181     OSSL_PARAM *params = NULL;
182     int ret = 0;
183
184     if (key == NULL)
185         return 0;
186
187     tmpl = OSSL_PARAM_BLD_new();
188     if (tmpl == NULL)
189         return 0;
190
191     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
192          && !key_to_params(key, tmpl, NULL))
193         goto err;
194
195     params = OSSL_PARAM_BLD_to_param(tmpl);
196     if (params == NULL)
197         goto err;
198
199     ret = param_cb(params, cbarg);
200     OSSL_PARAM_BLD_free_params(params);
201 err:
202     OSSL_PARAM_BLD_free(tmpl);
203     return ret;
204 }
205
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)
209
210 static const OSSL_PARAM ecx_key_types[] = {
211     ECX_KEY_TYPES(),
212     OSSL_PARAM_END
213 };
214 static const OSSL_PARAM *ecx_imexport_types(int selection)
215 {
216     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
217         return ecx_key_types;
218     return NULL;
219 }
220
221 static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
222                           int size)
223 {
224     ECX_KEY *ecx = key;
225     OSSL_PARAM *p;
226
227     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
228         && !OSSL_PARAM_set_int(p, bits))
229         return 0;
230     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
231         && !OSSL_PARAM_set_int(p, secbits))
232         return 0;
233     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
234         && !OSSL_PARAM_set_int(p, size))
235         return 0;
236     return key_to_params(ecx, NULL, params);
237 }
238
239 static int ed_get_params(void *key, OSSL_PARAM params[])
240 {
241     OSSL_PARAM *p;
242
243     if ((p = OSSL_PARAM_locate(params,
244                                OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
245         && !OSSL_PARAM_set_utf8_string(p, ""))
246         return 0;
247     return 1;
248 }
249
250 static int x25519_get_params(void *key, OSSL_PARAM params[])
251 {
252     return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
253                           X25519_KEYLEN);
254 }
255
256 static int x448_get_params(void *key, OSSL_PARAM params[])
257 {
258     return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
259                           X448_KEYLEN);
260 }
261
262 static int ed25519_get_params(void *key, OSSL_PARAM params[])
263 {
264     return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
265                           ED25519_KEYLEN)
266         && ed_get_params(key, params);
267 }
268
269 static int ed448_get_params(void *key, OSSL_PARAM params[])
270 {
271     return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
272                           ED448_KEYLEN)
273         && ed_get_params(key, params);
274 }
275
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),
281     ECX_KEY_TYPES(),
282     OSSL_PARAM_END
283 };
284
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),
289     ECX_KEY_TYPES(),
290     OSSL_PARAM_END
291 };
292
293 static const OSSL_PARAM *x25519_gettable_params(void)
294 {
295     return ecx_params;
296 }
297
298 static const OSSL_PARAM *x448_gettable_params(void)
299 {
300     return ecx_params;
301 }
302
303 static const OSSL_PARAM *ed25519_gettable_params(void)
304 {
305     return ed_params;
306 }
307
308 static const OSSL_PARAM *ed448_gettable_params(void)
309 {
310     return ed_params;
311 }
312
313 static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type)
314 {
315     OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
316     struct ecx_gen_ctx *gctx = NULL;
317
318     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
319         return NULL;
320
321     if ((gctx = OPENSSL_malloc(sizeof(*gctx))) != NULL) {
322         gctx->libctx = libctx;
323         gctx->type = type;
324     }
325     return gctx;
326 }
327
328 static void *x25519_gen_init(void *provctx, int selection)
329 {
330     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X25519);
331 }
332
333 static void *x448_gen_init(void *provctx, int selection)
334 {
335     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X448);
336 }
337
338 static void *ed25519_gen_init(void *provctx, int selection)
339 {
340     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED25519);
341 }
342
343 static void *ed448_gen_init(void *provctx, int selection)
344 {
345     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448);
346 }
347
348 static void *ecx_gen(struct ecx_gen_ctx *gctx)
349 {
350     ECX_KEY *key;
351     unsigned char *privkey;
352
353     if (gctx == NULL)
354         return NULL;
355     if ((key = ecx_key_new(gctx->libctx, gctx->type, 0)) == NULL) {
356         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
357         return NULL;
358     }
359     if ((privkey = ecx_key_allocate_privkey(key)) == NULL) {
360         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
361         goto err;
362     }
363     if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0)
364         goto err;
365     switch (gctx->type) {
366     case ECX_KEY_TYPE_X25519:
367         privkey[0] &= 248;
368         privkey[X25519_KEYLEN - 1] &= 127;
369         privkey[X25519_KEYLEN - 1] |= 64;
370         X25519_public_from_private(key->pubkey, privkey);
371         break;
372     case ECX_KEY_TYPE_X448:
373         privkey[0] &= 252;
374         privkey[X448_KEYLEN - 1] |= 128;
375         X448_public_from_private(key->pubkey, privkey);
376         break;
377     case ECX_KEY_TYPE_ED25519:
378         if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey))
379             goto err;
380         break;
381     case ECX_KEY_TYPE_ED448:
382         if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey))
383             goto err;
384         break;
385     }
386     return key;
387 err:
388     ecx_key_free(key);
389     return NULL;
390 }
391
392 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
393 {
394     struct ecx_gen_ctx *gctx = genctx;
395
396 #ifdef S390X_EC_ASM
397     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
398         return s390x_ecx_keygen25519(gctx);
399 #endif
400     return ecx_gen(gctx);
401 }
402
403 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
404 {
405     struct ecx_gen_ctx *gctx = genctx;
406
407 #ifdef S390X_EC_ASM
408     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
409         return s390x_ecx_keygen448(gctx);
410 #endif
411     return ecx_gen(gctx);
412 }
413
414 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
415 {
416     struct ecx_gen_ctx *gctx = genctx;
417 #ifdef S390X_EC_ASM
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);
423 #endif
424     return ecx_gen(gctx);
425 }
426
427 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
428 {
429     struct ecx_gen_ctx *gctx = genctx;
430
431 #ifdef S390X_EC_ASM
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);
436 #endif
437     return ecx_gen(gctx);
438 }
439
440 static void ecx_gen_cleanup(void *genctx)
441 {
442     struct ecx_gen_ctx *gctx = genctx;
443
444     OPENSSL_free(gctx);
445 }
446
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 }, \
462         { 0, NULL } \
463     };
464
465 MAKE_KEYMGMT_FUNCTIONS(x25519)
466 MAKE_KEYMGMT_FUNCTIONS(x448)
467 MAKE_KEYMGMT_FUNCTIONS(ed25519)
468 MAKE_KEYMGMT_FUNCTIONS(ed448)
469
470 #ifdef S390X_EC_ASM
471 # include "s390x_arch.h"
472
473 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
474 {
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
479     };
480     ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1);
481     unsigned char *privkey = NULL, *pubkey;
482
483     if (key == NULL) {
484         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
485         goto err;
486     }
487
488     pubkey = key->pubkey;
489
490     privkey = ecx_key_allocate_privkey(key);
491     if (privkey == NULL) {
492         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
493         goto err;
494     }
495
496     if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN) <= 0)
497         goto err;
498
499     privkey[0] &= 248;
500     privkey[31] &= 127;
501     privkey[31] |= 64;
502
503     if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
504         goto err;
505     return key;
506  err:
507     ecx_key_free(key);
508     return NULL;
509 }
510
511 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
512 {
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
519     };
520     ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1);
521     unsigned char *privkey = NULL, *pubkey;
522
523     if (key == NULL) {
524         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
525         goto err;
526     }
527
528     pubkey = key->pubkey;
529
530     privkey = ecx_key_allocate_privkey(key);
531     if (privkey == NULL) {
532         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
533         goto err;
534     }
535
536     if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN) <= 0)
537         goto err;
538
539     privkey[0] &= 252;
540     privkey[55] |= 128;
541
542     if (s390x_x448_mul(pubkey, generator, privkey) != 1)
543         goto err;
544     return key;
545  err:
546     ecx_key_free(key);
547     return NULL;
548 }
549
550 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
551 {
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
556     };
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,
561     };
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;
565     unsigned int sz;
566     EVP_MD *sha = NULL;
567     int j;
568
569     if (key == NULL) {
570         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
571         goto err;
572     }
573
574     pubkey = key->pubkey;
575
576     privkey = ecx_key_allocate_privkey(key);
577     if (privkey == NULL) {
578         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
579         goto err;
580     }
581
582     if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN) <= 0)
583         goto err;
584
585     sha = EVP_MD_fetch(gctx->libctx, "SHA512", NULL);
586     if (sha == NULL)
587         goto err;
588     j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
589     EVP_MD_free(sha);
590     if (!j)
591         goto err;
592
593     buff[0] &= 248;
594     buff[31] &= 63;
595     buff[31] |= 64;
596
597     if (s390x_ed25519_mul(x_dst, pubkey,
598                           generator_x, generator_y, buff) != 1)
599         goto err;
600
601     pubkey[31] |= ((x_dst[0] & 0x01) << 7);
602     return key;
603  err:
604     ecx_key_free(key);
605     return NULL;
606 }
607
608 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
609 {
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
616     };
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
623     };
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;
629
630     if (key == NULL) {
631         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
632         goto err;
633     }
634
635     pubkey = key->pubkey;
636
637     privkey = ecx_key_allocate_privkey(key);
638     if (privkey == NULL) {
639         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
640         goto err;
641     }
642
643     shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", NULL);
644     if (shake == NULL)
645         goto err;
646     if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN) <= 0)
647         goto err;
648
649     hashctx = EVP_MD_CTX_new();
650     if (hashctx == NULL)
651         goto err;
652     if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
653         goto err;
654     if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
655         goto err;
656     if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
657         goto err;
658
659     buff[0] &= -4;
660     buff[55] |= 0x80;
661     buff[56] = 0;
662
663     if (s390x_ed448_mul(x_dst, pubkey,
664                         generator_x, generator_y, buff) != 1)
665         goto err;
666
667     pubkey[56] |= ((x_dst[0] & 0x01) << 7);
668     EVP_MD_CTX_free(hashctx);
669     EVP_MD_free(shake);
670     return key;
671  err:
672     ecx_key_free(key);
673     EVP_MD_CTX_free(hashctx);
674     EVP_MD_free(shake);
675     return NULL;
676 }
677 #endif