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