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