ecx: add key generation support.
[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/evp.h>
15 #include <openssl/rand.h>
16 #include "internal/param_build_set.h"
17 #include "openssl/param_build.h"
18 #include "crypto/ecx.h"
19 #include "prov/implementations.h"
20 #include "prov/providercommon.h"
21 #include "prov/provider_ctx.h"
22 #ifdef S390X_EC_ASM
23 # include "s390x_arch.h"
24
25 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
26 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
27 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
28 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
29 #endif
30
31 static OSSL_OP_keymgmt_new_fn x25519_new_key;
32 static OSSL_OP_keymgmt_new_fn x448_new_key;
33 static OSSL_OP_keymgmt_new_fn ed25519_new_key;
34 static OSSL_OP_keymgmt_new_fn ed448_new_key;
35 static OSSL_OP_keymgmt_gen_init_fn x25519_gen_init;
36 static OSSL_OP_keymgmt_gen_init_fn x448_gen_init;
37 static OSSL_OP_keymgmt_gen_init_fn ed25519_gen_init;
38 static OSSL_OP_keymgmt_gen_init_fn ed448_gen_init;
39 static OSSL_OP_keymgmt_gen_fn x25519_gen;
40 static OSSL_OP_keymgmt_gen_fn x448_gen;
41 static OSSL_OP_keymgmt_gen_fn ed25519_gen;
42 static OSSL_OP_keymgmt_gen_fn ed448_gen;
43 static OSSL_OP_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
44 static OSSL_OP_keymgmt_get_params_fn x25519_get_params;
45 static OSSL_OP_keymgmt_get_params_fn x448_get_params;
46 static OSSL_OP_keymgmt_get_params_fn ed25519_get_params;
47 static OSSL_OP_keymgmt_get_params_fn ed448_get_params;
48 static OSSL_OP_keymgmt_gettable_params_fn ecx_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
63 static void *x25519_new_key(void *provctx)
64 {
65     return ecx_key_new(ECX_KEY_TYPE_X25519, 0);
66 }
67
68 static void *x448_new_key(void *provctx)
69 {
70     return ecx_key_new(ECX_KEY_TYPE_X448, 0);
71 }
72
73 static void *ed25519_new_key(void *provctx)
74 {
75     return ecx_key_new(ECX_KEY_TYPE_ED25519, 0);
76 }
77
78 static void *ed448_new_key(void *provctx)
79 {
80     return ecx_key_new(ECX_KEY_TYPE_ED448, 0);
81 }
82
83 static int ecx_has(void *keydata, int selection)
84 {
85     ECX_KEY *key = keydata;
86     int ok = 0;
87
88     if (key != NULL) {
89         if ((selection & ECX_POSSIBLE_SELECTIONS) != 0)
90             ok = 1;
91
92         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
93             ok = ok && key->haspubkey;
94
95         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
96             ok = ok && key->privkey != NULL;
97     }
98     return ok;
99 }
100
101 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
102 {
103     ECX_KEY *key = keydata;
104     int ok = 1;
105     int include_private = 0;
106
107     if (key == NULL)
108         return 0;
109
110     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
111         return 0;
112
113     include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
114     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
115         ok = ok && ecx_key_fromdata(key, params, include_private);
116
117     return ok;
118 }
119
120 static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
121                          OSSL_PARAM params[])
122 {
123     if (key == NULL)
124         return 0;
125
126     if (!ossl_param_build_set_octet_string(tmpl, params,
127                                            OSSL_PKEY_PARAM_PUB_KEY,
128                                            key->pubkey, key->keylen))
129         return 0;
130
131     if (key->privkey != NULL
132         && !ossl_param_build_set_octet_string(tmpl, params,
133                                               OSSL_PKEY_PARAM_PRIV_KEY,
134                                               key->privkey, key->keylen))
135         return 0;
136
137     return 1;
138 }
139
140 static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
141                       void *cbarg)
142 {
143     ECX_KEY *key = keydata;
144     OSSL_PARAM_BLD *tmpl;
145     OSSL_PARAM *params = NULL;
146     int ret = 0;
147
148     if (key == NULL)
149         return 0;
150
151     tmpl = OSSL_PARAM_BLD_new();
152     if (tmpl == NULL)
153         return 0;
154
155     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
156          && !key_to_params(key, tmpl, NULL))
157         goto err;
158
159     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
160          && !key_to_params(key, tmpl, NULL))
161         goto err;
162
163     params = OSSL_PARAM_BLD_to_param(tmpl);
164     if (params == NULL)
165         goto err;
166
167     ret = param_cb(params, cbarg);
168     OSSL_PARAM_BLD_free_params(params);
169 err:
170     OSSL_PARAM_BLD_free(tmpl);
171     return ret;
172 }
173
174 #define ECX_KEY_TYPES()                                                        \
175 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),                     \
176 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
177
178 static const OSSL_PARAM ecx_key_types[] = {
179     ECX_KEY_TYPES(),
180     OSSL_PARAM_END
181 };
182 static const OSSL_PARAM *ecx_imexport_types(int selection)
183 {
184     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
185         return ecx_key_types;
186     return NULL;
187 }
188
189 static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
190                           int size)
191 {
192     ECX_KEY *ecx = key;
193     OSSL_PARAM *p;
194
195     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
196         && !OSSL_PARAM_set_int(p, bits))
197         return 0;
198     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
199         && !OSSL_PARAM_set_int(p, secbits))
200         return 0;
201     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
202         && !OSSL_PARAM_set_int(p, size))
203         return 0;
204     return key_to_params(ecx, NULL, params);
205 }
206
207 static int x25519_get_params(void *key, OSSL_PARAM params[])
208 {
209     return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
210                           X25519_KEYLEN);
211 }
212
213 static int x448_get_params(void *key, OSSL_PARAM params[])
214 {
215     return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
216                           X448_KEYLEN);
217 }
218
219 static int ed25519_get_params(void *key, OSSL_PARAM params[])
220 {
221     return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
222                           ED25519_KEYLEN);
223 }
224
225 static int ed448_get_params(void *key, OSSL_PARAM params[])
226 {
227     return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
228                           ED448_KEYLEN);
229 }
230
231 static const OSSL_PARAM ecx_params[] = {
232     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
233     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
234     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
235     ECX_KEY_TYPES(),
236     OSSL_PARAM_END
237 };
238
239 static const OSSL_PARAM *ecx_gettable_params(void)
240 {
241     return ecx_params;
242 }
243
244 static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type)
245 {
246     OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
247     struct ecx_gen_ctx *gctx = NULL;
248
249     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
250         return NULL;
251
252     if ((gctx = OPENSSL_malloc(sizeof(*gctx))) != NULL) {
253         gctx->libctx = libctx;
254         gctx->type = type;
255     }
256     return gctx;
257 }
258
259 static void *x25519_gen_init(void *provctx, int selection)
260 {
261     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X25519);
262 }
263
264 static void *x448_gen_init(void *provctx, int selection)
265 {
266     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X448);
267 }
268
269 static void *ed25519_gen_init(void *provctx, int selection)
270 {
271     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED25519);
272 }
273
274 static void *ed448_gen_init(void *provctx, int selection)
275 {
276     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448);
277 }
278
279 static void *ecx_gen(struct ecx_gen_ctx *gctx)
280 {
281     ECX_KEY *key;
282     unsigned char *privkey;
283
284     if (gctx == NULL
285             || (key = ecx_key_new(gctx->type, 0)) == NULL)
286         return NULL;
287     if ((privkey = ecx_key_allocate_privkey(key)) == NULL
288             || RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0)
289         goto err;
290     switch (gctx->type) {
291     case ECX_KEY_TYPE_X25519:
292         privkey[0] &= 248;
293         privkey[X25519_KEYLEN - 1] &= 127;
294         privkey[X25519_KEYLEN - 1] |= 64;
295         X25519_public_from_private(key->pubkey, privkey);
296         break;
297     case ECX_KEY_TYPE_X448:
298         privkey[0] &= 252;
299         privkey[X448_KEYLEN - 1] |= 128;
300         X448_public_from_private(key->pubkey, privkey);
301         break;
302     case ECX_KEY_TYPE_ED25519:
303         if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey))
304             goto err;
305         break;
306     case ECX_KEY_TYPE_ED448:
307         if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey))
308             goto err;
309         break;
310     }
311     return key;
312 err:
313     ecx_key_free(key);
314     return NULL;
315 }
316
317 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
318 {
319     struct ecx_gen_ctx *gctx = genctx;
320
321 #ifdef S390X_EC_ASM
322     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
323         return s390x_ecx_keygen25519(gctx);
324 #endif
325     return ecx_gen(gctx);
326 }
327
328 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
329 {
330     struct ecx_gen_ctx *gctx = genctx;
331
332 #ifdef S390X_EC_ASM
333     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
334         return s390x_ecx_keygen448(gctx);
335 #endif
336     return ecx_gen(gctx);
337 }
338
339 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
340 {
341     struct ecx_gen_ctx *gctx = genctx;
342 #ifdef S390X_EC_ASM
343     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
344         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
345         && OPENSSL_s390xcap_P.kdsa[0]
346             & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
347         return s390x_ecd_keygen25519(gctx);
348 #endif
349     return ecx_gen(gctx);
350 }
351
352 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
353 {
354     struct ecx_gen_ctx *gctx = genctx;
355
356 #ifdef S390X_EC_ASM
357     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
358         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
359         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
360         return s390x_ecd_keygen448(gctx);
361 #endif
362     return ecx_gen(gctx);
363 }
364
365 static void ecx_gen_cleanup(void *genctx)
366 {
367     struct ecx_gen_ctx *gctx = genctx;
368
369     OPENSSL_free(gctx);
370 }
371
372 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
373     const OSSL_DISPATCH alg##_keymgmt_functions[] = { \
374         { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
375         { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, \
376         { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
377         { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ecx_gettable_params }, \
378         { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
379         { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
380         { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
381         { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
382         { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
383         { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
384         { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
385         { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
386         { 0, NULL } \
387     };
388
389 MAKE_KEYMGMT_FUNCTIONS(x25519)
390 MAKE_KEYMGMT_FUNCTIONS(x448)
391 MAKE_KEYMGMT_FUNCTIONS(ed25519)
392 MAKE_KEYMGMT_FUNCTIONS(ed448)
393
394 #ifdef S390X_EC_ASM
395 # include "s390x_arch.h"
396 # include "internal/constant_time.h"
397
398 static void s390x_x25519_mod_p(unsigned char u[32])
399 {
400     unsigned char u_red[32];
401     unsigned int c = 0;
402     int i;
403
404     memcpy(u_red, u, sizeof(u_red));
405
406     c += (unsigned int)u_red[31] + 19;
407     u_red[31] = (unsigned char)c;
408     c >>= 8;
409
410     for (i = 30; i >= 0; i--) {
411         c += (unsigned int)u_red[i];
412         u_red[i] = (unsigned char)c;
413         c >>= 8;
414     }
415
416     c = (u_red[0] & 0x80) >> 7;
417     u_red[0] &= 0x7f;
418     constant_time_cond_swap_buff(0 - (unsigned char)c,
419                                  u, u_red, sizeof(u_red));
420 }
421
422 static void s390x_x448_mod_p(unsigned char u[56])
423 {
424     unsigned char u_red[56];
425     unsigned int c = 0;
426     int i;
427
428     memcpy(u_red, u, sizeof(u_red));
429
430     c += (unsigned int)u_red[55] + 1;
431     u_red[55] = (unsigned char)c;
432     c >>= 8;
433
434     for (i = 54; i >= 28; i--) {
435         c += (unsigned int)u_red[i];
436         u_red[i] = (unsigned char)c;
437         c >>= 8;
438     }
439
440     c += (unsigned int)u_red[27] + 1;
441     u_red[27] = (unsigned char)c;
442     c >>= 8;
443
444     for (i = 26; i >= 0; i--) {
445         c += (unsigned int)u_red[i];
446         u_red[i] = (unsigned char)c;
447         c >>= 8;
448     }
449
450     constant_time_cond_swap_buff(0 - (unsigned char)c,
451                                  u, u_red, sizeof(u_red));
452 }
453
454 int s390x_x25519_mul(unsigned char u_dst[32],
455                      const unsigned char u_src[32],
456                      const unsigned char d_src[32])
457 {
458     union {
459         struct {
460             unsigned char u_dst[32];
461             unsigned char u_src[32];
462             unsigned char d_src[32];
463         } x25519;
464         unsigned long long buff[512];
465     } param;
466     int rc;
467
468     memset(&param, 0, sizeof(param));
469
470     s390x_flip_endian32(param.x25519.u_src, u_src);
471     param.x25519.u_src[0] &= 0x7f;
472     s390x_x25519_mod_p(param.x25519.u_src);
473
474     s390x_flip_endian32(param.x25519.d_src, d_src);
475     param.x25519.d_src[31] &= 248;
476     param.x25519.d_src[0] &= 127;
477     param.x25519.d_src[0] |= 64;
478
479     rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X25519, &param.x25519) ? 0 : 1;
480     if (rc == 1)
481         s390x_flip_endian32(u_dst, param.x25519.u_dst);
482
483     OPENSSL_cleanse(param.x25519.d_src, sizeof(param.x25519.d_src));
484     return rc;
485 }
486
487 int s390x_x448_mul(unsigned char u_dst[56],
488                    const unsigned char u_src[56],
489                    const unsigned char d_src[56])
490 {
491     union {
492         struct {
493             unsigned char u_dst[64];
494             unsigned char u_src[64];
495             unsigned char d_src[64];
496         } x448;
497         unsigned long long buff[512];
498     } param;
499     int rc;
500
501     memset(&param, 0, sizeof(param));
502
503     memcpy(param.x448.u_src, u_src, 56);
504     memcpy(param.x448.d_src, d_src, 56);
505
506     s390x_flip_endian64(param.x448.u_src, param.x448.u_src);
507     s390x_x448_mod_p(param.x448.u_src + 8);
508
509     s390x_flip_endian64(param.x448.d_src, param.x448.d_src);
510     param.x448.d_src[63] &= 252;
511     param.x448.d_src[8] |= 128;
512
513     rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X448, &param.x448) ? 0 : 1;
514     if (rc == 1) {
515         s390x_flip_endian64(param.x448.u_dst, param.x448.u_dst);
516         memcpy(u_dst, param.x448.u_dst, 56);
517     }
518
519     OPENSSL_cleanse(param.x448.d_src, sizeof(param.x448.d_src));
520     return rc;
521 }
522
523 static int s390x_ed25519_mul(unsigned char x_dst[32],
524                              unsigned char y_dst[32],
525                              const unsigned char x_src[32],
526                              const unsigned char y_src[32],
527                              const unsigned char d_src[32])
528 {
529     union {
530         struct {
531             unsigned char x_dst[32];
532             unsigned char y_dst[32];
533             unsigned char x_src[32];
534             unsigned char y_src[32];
535             unsigned char d_src[32];
536         } ed25519;
537         unsigned long long buff[512];
538     } param;
539     int rc;
540
541     memset(&param, 0, sizeof(param));
542
543     s390x_flip_endian32(param.ed25519.x_src, x_src);
544     s390x_flip_endian32(param.ed25519.y_src, y_src);
545     s390x_flip_endian32(param.ed25519.d_src, d_src);
546
547     rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED25519, &param.ed25519) ? 0 : 1;
548     if (rc == 1) {
549         s390x_flip_endian32(x_dst, param.ed25519.x_dst);
550         s390x_flip_endian32(y_dst, param.ed25519.y_dst);
551     }
552
553     OPENSSL_cleanse(param.ed25519.d_src, sizeof(param.ed25519.d_src));
554     return rc;
555 }
556
557 static int s390x_ed448_mul(unsigned char x_dst[57],
558                            unsigned char y_dst[57],
559                            const unsigned char x_src[57],
560                            const unsigned char y_src[57],
561                            const unsigned char d_src[57])
562 {
563     union {
564         struct {
565             unsigned char x_dst[64];
566             unsigned char y_dst[64];
567             unsigned char x_src[64];
568             unsigned char y_src[64];
569             unsigned char d_src[64];
570         } ed448;
571         unsigned long long buff[512];
572     } param;
573     int rc;
574
575     memset(&param, 0, sizeof(param));
576
577     memcpy(param.ed448.x_src, x_src, 57);
578     memcpy(param.ed448.y_src, y_src, 57);
579     memcpy(param.ed448.d_src, d_src, 57);
580     s390x_flip_endian64(param.ed448.x_src, param.ed448.x_src);
581     s390x_flip_endian64(param.ed448.y_src, param.ed448.y_src);
582     s390x_flip_endian64(param.ed448.d_src, param.ed448.d_src);
583
584     rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED448, &param.ed448) ? 0 : 1;
585     if (rc == 1) {
586         s390x_flip_endian64(param.ed448.x_dst, param.ed448.x_dst);
587         s390x_flip_endian64(param.ed448.y_dst, param.ed448.y_dst);
588         memcpy(x_dst, param.ed448.x_dst, 57);
589         memcpy(y_dst, param.ed448.y_dst, 57);
590     }
591
592     OPENSSL_cleanse(param.ed448.d_src, sizeof(param.ed448.d_src));
593     return rc;
594 }
595
596 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
597 {
598     static const unsigned char generator[] = {
599         0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
602     };
603     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X25519, 1);
604     unsigned char *privkey = NULL, *pubkey;
605
606     if (key == NULL) {
607         PROVerr(0, ERR_R_MALLOC_FAILURE);
608         goto err;
609     }
610
611     pubkey = key->pubkey;
612
613     privkey = ecx_key_allocate_privkey(key);
614     if (privkey == NULL) {
615         PROVerr(0, ERR_R_MALLOC_FAILURE);
616         goto err;
617     }
618
619     if (RAND_priv_bytes(privkey, X25519_KEYLEN) <= 0)
620         goto err;
621
622     privkey[0] &= 248;
623     privkey[31] &= 127;
624     privkey[31] |= 64;
625
626     if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
627         goto err;
628
629     return key;
630  err:
631     ecx_key_free(key);
632     return NULL;
633 }
634
635 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
636 {
637     static const unsigned char generator[] = {
638         0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
643     };
644     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X448, 1);
645     unsigned char *privkey = NULL, *pubkey;
646
647     if (key == NULL) {
648         PROVerr(0, ERR_R_MALLOC_FAILURE);
649         goto err;
650     }
651
652     pubkey = key->pubkey;
653
654     privkey = ecx_key_allocate_privkey(key);
655     if (privkey == NULL) {
656         PROVerr(0, ERR_R_MALLOC_FAILURE);
657         goto err;
658     }
659
660     if (RAND_priv_bytes(privkey, X448_KEYLEN) <= 0)
661         goto err;
662
663     privkey[0] &= 252;
664     privkey[55] |= 128;
665
666     if (s390x_x448_mul(pubkey, generator, privkey) != 1)
667         goto err;
668
669     return key;
670  err:
671     ecx_key_free(key);
672     return NULL;
673 }
674
675 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
676 {
677     static const unsigned char generator_x[] = {
678         0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
679         0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
680         0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
681     };
682     static const unsigned char generator_y[] = {
683         0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
684         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
685         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
686     };
687     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
688     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED25519, 1);
689     unsigned char *privkey = NULL, *pubkey;
690     unsigned int sz;
691
692     if (key == NULL) {
693         PROVerr(0, ERR_R_MALLOC_FAILURE);
694         goto err;
695     }
696
697     pubkey = key->pubkey;
698
699     privkey = ecx_key_allocate_privkey(key);
700     if (privkey == NULL) {
701         PROVerr(0, ERR_R_MALLOC_FAILURE);
702         goto err;
703     }
704
705     if (RAND_priv_bytes(privkey, ED25519_KEYLEN) <= 0)
706         goto err;
707
708     if (!EVP_Digest(privkey, 32, buff, &sz, EVP_sha512(), NULL))
709         goto err;
710
711     buff[0] &= 248;
712     buff[31] &= 63;
713     buff[31] |= 64;
714
715     if (s390x_ed25519_mul(x_dst, pubkey,
716                           generator_x, generator_y, buff) != 1)
717         goto err;
718
719     pubkey[31] |= ((x_dst[0] & 0x01) << 7);
720     return key;
721  err:
722     ecx_key_free(key);
723     return NULL;
724 }
725
726 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
727 {
728     static const unsigned char generator_x[] = {
729         0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
730         0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
731         0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
732         0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
733         0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
734     };
735     static const unsigned char generator_y[] = {
736         0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
737         0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
738         0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
739         0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
740         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
741     };
742     unsigned char x_dst[57], buff[114];
743     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED448, 1);
744     unsigned char *privkey = NULL, *pubkey;
745     EVP_MD_CTX *hashctx = NULL;
746
747     if (key == NULL) {
748         PROVerr(0, ERR_R_MALLOC_FAILURE);
749         goto err;
750     }
751
752     pubkey = key->pubkey;
753
754     privkey = ecx_key_allocate_privkey(key);
755     if (privkey == NULL) {
756         PROVerr(0, ERR_R_MALLOC_FAILURE);
757         goto err;
758     }
759
760     if (RAND_priv_bytes(privkey, ED448_KEYLEN) <= 0)
761         goto err;
762
763     hashctx = EVP_MD_CTX_new();
764     if (hashctx == NULL)
765         goto err;
766     if (EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL) != 1)
767         goto err;
768     if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
769         goto err;
770     if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
771         goto err;
772
773     buff[0] &= -4;
774     buff[55] |= 0x80;
775     buff[56] = 0;
776
777     if (s390x_ed448_mul(x_dst, pubkey,
778                         generator_x, generator_y, buff) != 1)
779         goto err;
780
781     pubkey[56] |= ((x_dst[0] & 0x01) << 7);
782
783     EVP_MD_CTX_free(hashctx);
784     return key;
785  err:
786     ecx_key_free(key);
787     EVP_MD_CTX_free(hashctx);
788     return NULL;
789 }
790 #endif