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