Coverage Report

Created: 2025-08-28 07:07

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