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