Coverage Report

Created: 2024-11-21 07:03

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