Coverage Report

Created: 2025-10-28 06:56

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