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