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