Coverage Report

Created: 2025-06-13 06:56

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