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