PROV: Ensure that ED25519 & ED448 keys have a mandatory digest
[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 <openssl/core_numbers.h>
12 #include <openssl/core_names.h>
13 #include <openssl/params.h>
14 #include <openssl/err.h>
15 #include <openssl/evp.h>
16 #include <openssl/rand.h>
17 #include "internal/param_build_set.h"
18 #include "openssl/param_build.h"
19 #include "crypto/ecx.h"
20 #include "prov/implementations.h"
21 #include "prov/providercommon.h"
22 #include "prov/provider_ctx.h"
23 #ifdef S390X_EC_ASM
24 # include "s390x_arch.h"
25 # include <openssl/sha.h>   /* For SHA512_DIGEST_LENGTH */
26 #endif
27
28 static OSSL_OP_keymgmt_new_fn x25519_new_key;
29 static OSSL_OP_keymgmt_new_fn x448_new_key;
30 static OSSL_OP_keymgmt_new_fn ed25519_new_key;
31 static OSSL_OP_keymgmt_new_fn ed448_new_key;
32 static OSSL_OP_keymgmt_gen_init_fn x25519_gen_init;
33 static OSSL_OP_keymgmt_gen_init_fn x448_gen_init;
34 static OSSL_OP_keymgmt_gen_init_fn ed25519_gen_init;
35 static OSSL_OP_keymgmt_gen_init_fn ed448_gen_init;
36 static OSSL_OP_keymgmt_gen_fn x25519_gen;
37 static OSSL_OP_keymgmt_gen_fn x448_gen;
38 static OSSL_OP_keymgmt_gen_fn ed25519_gen;
39 static OSSL_OP_keymgmt_gen_fn ed448_gen;
40 static OSSL_OP_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
41 static OSSL_OP_keymgmt_get_params_fn x25519_get_params;
42 static OSSL_OP_keymgmt_get_params_fn x448_get_params;
43 static OSSL_OP_keymgmt_get_params_fn ed25519_get_params;
44 static OSSL_OP_keymgmt_get_params_fn ed448_get_params;
45 static OSSL_OP_keymgmt_gettable_params_fn x25519_gettable_params;
46 static OSSL_OP_keymgmt_gettable_params_fn x448_gettable_params;
47 static OSSL_OP_keymgmt_gettable_params_fn ed25519_gettable_params;
48 static OSSL_OP_keymgmt_gettable_params_fn ed448_gettable_params;
49 static OSSL_OP_keymgmt_has_fn ecx_has;
50 static OSSL_OP_keymgmt_import_fn ecx_import;
51 static OSSL_OP_keymgmt_import_types_fn ecx_imexport_types;
52 static OSSL_OP_keymgmt_export_fn ecx_export;
53 static OSSL_OP_keymgmt_export_types_fn ecx_imexport_types;
54
55 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
56
57 struct ecx_gen_ctx {
58     OPENSSL_CTX *libctx;
59     ECX_KEY_TYPE type;
60 };
61
62 #ifdef S390X_EC_ASM
63 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
64 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
65 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
66 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
67 #endif
68
69 static void *x25519_new_key(void *provctx)
70 {
71     return ecx_key_new(ECX_KEY_TYPE_X25519, 0);
72 }
73
74 static void *x448_new_key(void *provctx)
75 {
76     return ecx_key_new(ECX_KEY_TYPE_X448, 0);
77 }
78
79 static void *ed25519_new_key(void *provctx)
80 {
81     return ecx_key_new(ECX_KEY_TYPE_ED25519, 0);
82 }
83
84 static void *ed448_new_key(void *provctx)
85 {
86     return ecx_key_new(ECX_KEY_TYPE_ED448, 0);
87 }
88
89 static int ecx_has(void *keydata, int selection)
90 {
91     ECX_KEY *key = keydata;
92     int ok = 0;
93
94     if (key != NULL) {
95         if ((selection & ECX_POSSIBLE_SELECTIONS) != 0)
96             ok = 1;
97
98         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
99             ok = ok && key->haspubkey;
100
101         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
102             ok = ok && key->privkey != NULL;
103     }
104     return ok;
105 }
106
107 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
108 {
109     ECX_KEY *key = keydata;
110     int ok = 1;
111     int include_private = 0;
112
113     if (key == NULL)
114         return 0;
115
116     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
117         return 0;
118
119     include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
120     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
121         ok = ok && ecx_key_fromdata(key, params, include_private);
122
123     return ok;
124 }
125
126 static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
127                          OSSL_PARAM params[])
128 {
129     if (key == NULL)
130         return 0;
131
132     if (!ossl_param_build_set_octet_string(tmpl, params,
133                                            OSSL_PKEY_PARAM_PUB_KEY,
134                                            key->pubkey, key->keylen))
135         return 0;
136
137     if (key->privkey != NULL
138         && !ossl_param_build_set_octet_string(tmpl, params,
139                                               OSSL_PKEY_PARAM_PRIV_KEY,
140                                               key->privkey, key->keylen))
141         return 0;
142
143     return 1;
144 }
145
146 static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
147                       void *cbarg)
148 {
149     ECX_KEY *key = keydata;
150     OSSL_PARAM_BLD *tmpl;
151     OSSL_PARAM *params = NULL;
152     int ret = 0;
153
154     if (key == NULL)
155         return 0;
156
157     tmpl = OSSL_PARAM_BLD_new();
158     if (tmpl == NULL)
159         return 0;
160
161     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
162          && !key_to_params(key, tmpl, NULL))
163         goto err;
164
165     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
166          && !key_to_params(key, tmpl, NULL))
167         goto err;
168
169     params = OSSL_PARAM_BLD_to_param(tmpl);
170     if (params == NULL)
171         goto err;
172
173     ret = param_cb(params, cbarg);
174     OSSL_PARAM_BLD_free_params(params);
175 err:
176     OSSL_PARAM_BLD_free(tmpl);
177     return ret;
178 }
179
180 #define ECX_KEY_TYPES()                                                        \
181 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),                     \
182 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
183
184 static const OSSL_PARAM ecx_key_types[] = {
185     ECX_KEY_TYPES(),
186     OSSL_PARAM_END
187 };
188 static const OSSL_PARAM *ecx_imexport_types(int selection)
189 {
190     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
191         return ecx_key_types;
192     return NULL;
193 }
194
195 static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
196                           int size)
197 {
198     ECX_KEY *ecx = key;
199     OSSL_PARAM *p;
200
201     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
202         && !OSSL_PARAM_set_int(p, bits))
203         return 0;
204     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
205         && !OSSL_PARAM_set_int(p, secbits))
206         return 0;
207     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
208         && !OSSL_PARAM_set_int(p, size))
209         return 0;
210     return key_to_params(ecx, NULL, params);
211 }
212
213 static int ed_get_params(void *key, OSSL_PARAM params[])
214 {
215     OSSL_PARAM *p;
216
217     if ((p = OSSL_PARAM_locate(params,
218                                OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
219         && !OSSL_PARAM_set_utf8_string(p, ""))
220         return 0;
221     return 1;
222 }
223
224 static int x25519_get_params(void *key, OSSL_PARAM params[])
225 {
226     return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
227                           X25519_KEYLEN);
228 }
229
230 static int x448_get_params(void *key, OSSL_PARAM params[])
231 {
232     return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
233                           X448_KEYLEN);
234 }
235
236 static int ed25519_get_params(void *key, OSSL_PARAM params[])
237 {
238     return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
239                           ED25519_KEYLEN)
240         && ed_get_params(key, params);
241 }
242
243 static int ed448_get_params(void *key, OSSL_PARAM params[])
244 {
245     return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
246                           ED448_KEYLEN)
247         && ed_get_params(key, params);
248 }
249
250 static const OSSL_PARAM ecx_params[] = {
251     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
252     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
253     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
254     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
255     ECX_KEY_TYPES(),
256     OSSL_PARAM_END
257 };
258
259 static const OSSL_PARAM ed_params[] = {
260     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
261     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
262     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
263     ECX_KEY_TYPES(),
264     OSSL_PARAM_END
265 };
266
267 static const OSSL_PARAM *x25519_gettable_params(void)
268 {
269     return ecx_params;
270 }
271
272 static const OSSL_PARAM *x448_gettable_params(void)
273 {
274     return ecx_params;
275 }
276
277 static const OSSL_PARAM *ed25519_gettable_params(void)
278 {
279     return ed_params;
280 }
281
282 static const OSSL_PARAM *ed448_gettable_params(void)
283 {
284     return ed_params;
285 }
286
287 static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type)
288 {
289     OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
290     struct ecx_gen_ctx *gctx = NULL;
291
292     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
293         return NULL;
294
295     if ((gctx = OPENSSL_malloc(sizeof(*gctx))) != NULL) {
296         gctx->libctx = libctx;
297         gctx->type = type;
298     }
299     return gctx;
300 }
301
302 static void *x25519_gen_init(void *provctx, int selection)
303 {
304     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X25519);
305 }
306
307 static void *x448_gen_init(void *provctx, int selection)
308 {
309     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X448);
310 }
311
312 static void *ed25519_gen_init(void *provctx, int selection)
313 {
314     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED25519);
315 }
316
317 static void *ed448_gen_init(void *provctx, int selection)
318 {
319     return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448);
320 }
321
322 static void *ecx_gen(struct ecx_gen_ctx *gctx)
323 {
324     ECX_KEY *key;
325     unsigned char *privkey;
326
327     if (gctx == NULL)
328         return NULL;
329     if ((key = ecx_key_new(gctx->type, 0)) == NULL) {
330         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
331         return NULL;
332     }
333     if ((privkey = ecx_key_allocate_privkey(key)) == NULL) {
334         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
335         goto err;
336     }
337     if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0)
338         goto err;
339     switch (gctx->type) {
340     case ECX_KEY_TYPE_X25519:
341         privkey[0] &= 248;
342         privkey[X25519_KEYLEN - 1] &= 127;
343         privkey[X25519_KEYLEN - 1] |= 64;
344         X25519_public_from_private(key->pubkey, privkey);
345         break;
346     case ECX_KEY_TYPE_X448:
347         privkey[0] &= 252;
348         privkey[X448_KEYLEN - 1] |= 128;
349         X448_public_from_private(key->pubkey, privkey);
350         break;
351     case ECX_KEY_TYPE_ED25519:
352         if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey))
353             goto err;
354         break;
355     case ECX_KEY_TYPE_ED448:
356         if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey))
357             goto err;
358         break;
359     }
360     return key;
361 err:
362     ecx_key_free(key);
363     return NULL;
364 }
365
366 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
367 {
368     struct ecx_gen_ctx *gctx = genctx;
369
370 #ifdef S390X_EC_ASM
371     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
372         return s390x_ecx_keygen25519(gctx);
373 #endif
374     return ecx_gen(gctx);
375 }
376
377 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
378 {
379     struct ecx_gen_ctx *gctx = genctx;
380
381 #ifdef S390X_EC_ASM
382     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
383         return s390x_ecx_keygen448(gctx);
384 #endif
385     return ecx_gen(gctx);
386 }
387
388 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
389 {
390     struct ecx_gen_ctx *gctx = genctx;
391 #ifdef S390X_EC_ASM
392     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
393         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
394         && OPENSSL_s390xcap_P.kdsa[0]
395             & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
396         return s390x_ecd_keygen25519(gctx);
397 #endif
398     return ecx_gen(gctx);
399 }
400
401 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
402 {
403     struct ecx_gen_ctx *gctx = genctx;
404
405 #ifdef S390X_EC_ASM
406     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
407         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
408         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
409         return s390x_ecd_keygen448(gctx);
410 #endif
411     return ecx_gen(gctx);
412 }
413
414 static void ecx_gen_cleanup(void *genctx)
415 {
416     struct ecx_gen_ctx *gctx = genctx;
417
418     OPENSSL_free(gctx);
419 }
420
421 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
422     const OSSL_DISPATCH alg##_keymgmt_functions[] = { \
423         { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
424         { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, \
425         { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
426         { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
427         { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
428         { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
429         { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
430         { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
431         { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
432         { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
433         { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
434         { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
435         { 0, NULL } \
436     };
437
438 MAKE_KEYMGMT_FUNCTIONS(x25519)
439 MAKE_KEYMGMT_FUNCTIONS(x448)
440 MAKE_KEYMGMT_FUNCTIONS(ed25519)
441 MAKE_KEYMGMT_FUNCTIONS(ed448)
442
443 #ifdef S390X_EC_ASM
444 # include "s390x_arch.h"
445
446 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
447 {
448     static const unsigned char generator[] = {
449         0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
452     };
453     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X25519, 1);
454     unsigned char *privkey = NULL, *pubkey;
455
456     if (key == NULL) {
457         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
458         goto err;
459     }
460
461     pubkey = key->pubkey;
462
463     privkey = ecx_key_allocate_privkey(key);
464     if (privkey == NULL) {
465         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
466         goto err;
467     }
468
469     if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN) <= 0)
470         goto err;
471
472     privkey[0] &= 248;
473     privkey[31] &= 127;
474     privkey[31] |= 64;
475
476     if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
477         goto err;
478     return key;
479  err:
480     ecx_key_free(key);
481     return NULL;
482 }
483
484 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
485 {
486     static const unsigned char generator[] = {
487         0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
492     };
493     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X448, 1);
494     unsigned char *privkey = NULL, *pubkey;
495
496     if (key == NULL) {
497         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
498         goto err;
499     }
500
501     pubkey = key->pubkey;
502
503     privkey = ecx_key_allocate_privkey(key);
504     if (privkey == NULL) {
505         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
506         goto err;
507     }
508
509     if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN) <= 0)
510         goto err;
511
512     privkey[0] &= 252;
513     privkey[55] |= 128;
514
515     if (s390x_x448_mul(pubkey, generator, privkey) != 1)
516         goto err;
517     return key;
518  err:
519     ecx_key_free(key);
520     return NULL;
521 }
522
523 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
524 {
525     static const unsigned char generator_x[] = {
526         0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
527         0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
528         0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
529     };
530     static const unsigned char generator_y[] = {
531         0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
532         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
533         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
534     };
535     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
536     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED25519, 1);
537     unsigned char *privkey = NULL, *pubkey;
538     unsigned int sz;
539     EVP_MD *sha = NULL;
540     int j;
541
542     if (key == NULL) {
543         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
544         goto err;
545     }
546
547     pubkey = key->pubkey;
548
549     privkey = ecx_key_allocate_privkey(key);
550     if (privkey == NULL) {
551         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
552         goto err;
553     }
554
555     if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN) <= 0)
556         goto err;
557
558     sha = EVP_MD_fetch(gctx->libctx, "SHA512", NULL);
559     if (sha == NULL)
560         goto err;
561     j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
562     EVP_MD_free(sha);
563     if (!j)
564         goto err;
565
566     buff[0] &= 248;
567     buff[31] &= 63;
568     buff[31] |= 64;
569
570     if (s390x_ed25519_mul(x_dst, pubkey,
571                           generator_x, generator_y, buff) != 1)
572         goto err;
573
574     pubkey[31] |= ((x_dst[0] & 0x01) << 7);
575     return key;
576  err:
577     ecx_key_free(key);
578     return NULL;
579 }
580
581 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
582 {
583     static const unsigned char generator_x[] = {
584         0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
585         0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
586         0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
587         0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
588         0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
589     };
590     static const unsigned char generator_y[] = {
591         0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
592         0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
593         0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
594         0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
595         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
596     };
597     unsigned char x_dst[57], buff[114];
598     ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED448, 1);
599     unsigned char *privkey = NULL, *pubkey;
600     EVP_MD_CTX *hashctx = NULL;
601     EVP_MD *shake = NULL;
602
603     if (key == NULL) {
604         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
605         goto err;
606     }
607
608     pubkey = key->pubkey;
609
610     privkey = ecx_key_allocate_privkey(key);
611     if (privkey == NULL) {
612         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
613         goto err;
614     }
615
616     shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", NULL);
617     if (shake == NULL)
618         goto err;
619     if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN) <= 0)
620         goto err;
621
622     hashctx = EVP_MD_CTX_new();
623     if (hashctx == NULL)
624         goto err;
625     if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
626         goto err;
627     if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
628         goto err;
629     if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
630         goto err;
631
632     buff[0] &= -4;
633     buff[55] |= 0x80;
634     buff[56] = 0;
635
636     if (s390x_ed448_mul(x_dst, pubkey,
637                         generator_x, generator_y, buff) != 1)
638         goto err;
639
640     pubkey[56] |= ((x_dst[0] & 0x01) << 7);
641     EVP_MD_CTX_free(hashctx);
642     EVP_MD_free(shake);
643     return key;
644  err:
645     ecx_key_free(key);
646     EVP_MD_CTX_free(hashctx);
647     EVP_MD_free(shake);
648     return NULL;
649 }
650 #endif