Coverage Report

Created: 2026-05-24 07:14

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