Coverage Report

Created: 2025-12-08 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/evp/pmeth_gn.c
Line
Count
Source
1
/*
2
 * Copyright 2006-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 <stdio.h>
11
#include <stdlib.h>
12
#include <openssl/core.h>
13
#include <openssl/core_names.h>
14
#include "internal/cryptlib.h"
15
#include "internal/core.h"
16
#include "internal/common.h"
17
#include <openssl/objects.h>
18
#include <openssl/evp.h>
19
#include "crypto/bn.h"
20
#ifndef FIPS_MODULE
21
# include "crypto/asn1.h"
22
#endif
23
#include "crypto/evp.h"
24
#include "evp_local.h"
25
26
static int gen_init(EVP_PKEY_CTX *ctx, int operation)
27
0
{
28
0
    int ret = 0;
29
30
0
    if (ctx == NULL)
31
0
        goto not_supported;
32
33
0
    evp_pkey_ctx_free_old_ops(ctx);
34
0
    ctx->operation = operation;
35
36
0
    if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL)
37
0
        goto legacy;
38
39
0
    switch (operation) {
40
0
    case EVP_PKEY_OP_PARAMGEN:
41
0
        ctx->op.keymgmt.genctx =
42
0
            evp_keymgmt_gen_init(ctx->keymgmt,
43
0
                                 OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, NULL);
44
0
        break;
45
0
    case EVP_PKEY_OP_KEYGEN:
46
0
        ctx->op.keymgmt.genctx =
47
0
            evp_keymgmt_gen_init(ctx->keymgmt, OSSL_KEYMGMT_SELECT_KEYPAIR,
48
0
                                 NULL);
49
0
        break;
50
0
    }
51
52
0
    if (ctx->op.keymgmt.genctx == NULL)
53
0
        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
54
0
    else
55
0
        ret = 1;
56
0
    goto end;
57
58
0
 legacy:
59
#ifdef FIPS_MODULE
60
    goto not_supported;
61
#else
62
0
    if (ctx->pmeth == NULL
63
0
        || (operation == EVP_PKEY_OP_PARAMGEN
64
0
            && ctx->pmeth->paramgen == NULL)
65
0
        || (operation == EVP_PKEY_OP_KEYGEN
66
0
            && ctx->pmeth->keygen == NULL))
67
0
        goto not_supported;
68
69
0
    ret = 1;
70
0
    switch (operation) {
71
0
    case EVP_PKEY_OP_PARAMGEN:
72
0
        if (ctx->pmeth->paramgen_init != NULL)
73
0
            ret = ctx->pmeth->paramgen_init(ctx);
74
0
        break;
75
0
    case EVP_PKEY_OP_KEYGEN:
76
0
        if (ctx->pmeth->keygen_init != NULL)
77
0
            ret = ctx->pmeth->keygen_init(ctx);
78
0
        break;
79
0
    }
80
0
#endif
81
82
0
 end:
83
0
    if (ret <= 0 && ctx != NULL) {
84
0
        evp_pkey_ctx_free_old_ops(ctx);
85
0
        ctx->operation = EVP_PKEY_OP_UNDEFINED;
86
0
    }
87
0
    return ret;
88
89
0
 not_supported:
90
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
91
0
    ret = -2;
92
0
    goto end;
93
0
}
94
95
int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
96
0
{
97
0
    return gen_init(ctx, EVP_PKEY_OP_PARAMGEN);
98
0
}
99
100
int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
101
0
{
102
0
    return gen_init(ctx, EVP_PKEY_OP_KEYGEN);
103
0
}
104
105
static int ossl_callback_to_pkey_gencb(const OSSL_PARAM params[], void *arg)
106
0
{
107
0
    EVP_PKEY_CTX *ctx = arg;
108
0
    const OSSL_PARAM *param = NULL;
109
0
    int p = -1, n = -1;
110
111
0
    if (ctx->pkey_gencb == NULL)
112
0
        return 1;                /* No callback?  That's fine */
113
114
0
    if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_POTENTIAL))
115
0
        == NULL
116
0
        || !OSSL_PARAM_get_int(param, &p))
117
0
        return 0;
118
0
    if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_ITERATION))
119
0
        == NULL
120
0
        || !OSSL_PARAM_get_int(param, &n))
121
0
        return 0;
122
123
0
    ctx->keygen_info[0] = p;
124
0
    ctx->keygen_info[1] = n;
125
126
0
    return ctx->pkey_gencb(ctx);
127
0
}
128
129
int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
130
0
{
131
0
    int ret = 0;
132
0
    EVP_PKEY *allocated_pkey = NULL;
133
    /* Legacy compatible keygen callback info, only used with provider impls */
134
0
    int gentmp[2];
135
136
0
    if (ppkey == NULL)
137
0
        return -1;
138
139
0
    if (ctx == NULL)
140
0
        goto not_supported;
141
142
0
    if ((ctx->operation & EVP_PKEY_OP_TYPE_GEN) == 0)
143
0
        goto not_initialized;
144
145
0
    if (*ppkey == NULL)
146
0
        *ppkey = allocated_pkey = EVP_PKEY_new();
147
148
0
    if (*ppkey == NULL) {
149
0
        ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
150
0
        return -1;
151
0
    }
152
153
0
    if (ctx->op.keymgmt.genctx == NULL)
154
0
        goto legacy;
155
156
    /*
157
     * Assigning gentmp to ctx->keygen_info is something our legacy
158
     * implementations do.  Because the provider implementations aren't
159
     * allowed to reach into our EVP_PKEY_CTX, we need to provide similar
160
     * space for backward compatibility.  It's ok that we attach a local
161
     * variable, as it should only be useful in the calls down from here.
162
     * This is cleared as soon as it isn't useful any more, i.e. directly
163
     * after the evp_keymgmt_util_gen() call.
164
     */
165
0
    ctx->keygen_info = gentmp;
166
0
    ctx->keygen_info_count = 2;
167
168
0
    ret = 1;
169
0
    if (ctx->pkey != NULL) {
170
0
        EVP_KEYMGMT *tmp_keymgmt = ctx->keymgmt;
171
0
        void *keydata =
172
0
            evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
173
0
                                        &tmp_keymgmt, ctx->propquery);
174
175
0
        if (tmp_keymgmt == NULL)
176
0
            goto not_supported;
177
        /*
178
         * It's ok if keydata is NULL here.  The backend is expected to deal
179
         * with that as it sees fit.
180
         */
181
0
        ret = evp_keymgmt_gen_set_template(ctx->keymgmt,
182
0
                                           ctx->op.keymgmt.genctx, keydata);
183
0
    }
184
185
    /*
186
     * the returned value from evp_keymgmt_util_gen() is cached in *ppkey,
187
     * so we do not need to save it, just check it.
188
     */
189
0
    ret = ret
190
0
        && (evp_keymgmt_util_gen(*ppkey, ctx->keymgmt, ctx->op.keymgmt.genctx,
191
0
                                 ossl_callback_to_pkey_gencb, ctx)
192
0
            != NULL);
193
194
0
    ctx->keygen_info = NULL;
195
196
0
#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_DEPRECATED_3_6)
197
    /* In case |*ppkey| was originally a legacy key */
198
0
    if (ret)
199
0
        evp_pkey_free_legacy(*ppkey);
200
0
#endif
201
202
    /*
203
     * Because we still have legacy keys
204
     */
205
0
    (*ppkey)->type = ctx->legacy_keytype;
206
207
0
    goto end;
208
209
0
 legacy:
210
#ifdef FIPS_MODULE
211
    goto not_supported;
212
#else
213
    /*
214
     * If we get here then we're using legacy paramgen/keygen. In that case
215
     * the pkey in ctx (if there is one) had better not be provided (because the
216
     * legacy methods may not know how to handle it). However we can only get
217
     * here if ctx->op.keymgmt.genctx == NULL, but that should never be the case
218
     * if ctx->pkey is provided because we don't allow this when we initialise
219
     * the ctx.
220
     */
221
0
    if (ctx->pkey != NULL && !ossl_assert(!evp_pkey_is_provided(ctx->pkey)))
222
0
        goto not_accessible;
223
224
0
    switch (ctx->operation) {
225
0
    case EVP_PKEY_OP_PARAMGEN:
226
0
        ret = ctx->pmeth->paramgen(ctx, *ppkey);
227
0
        break;
228
0
    case EVP_PKEY_OP_KEYGEN:
229
0
        ret = ctx->pmeth->keygen(ctx, *ppkey);
230
0
        break;
231
0
    default:
232
0
        goto not_supported;
233
0
    }
234
0
#endif
235
236
0
 end:
237
0
    if (ret <= 0) {
238
0
        if (allocated_pkey != NULL)
239
0
            *ppkey = NULL;
240
0
        EVP_PKEY_free(allocated_pkey);
241
0
    }
242
0
    return ret;
243
244
0
 not_supported:
245
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
246
0
    ret = -2;
247
0
    goto end;
248
0
 not_initialized:
249
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
250
0
    ret = -1;
251
0
    goto end;
252
0
#ifndef FIPS_MODULE
253
0
 not_accessible:
254
0
    ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS);
255
0
    ret = -1;
256
0
    goto end;
257
0
#endif
258
0
}
259
260
int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
261
0
{
262
0
    if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
263
0
        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
264
0
        return -1;
265
0
    }
266
0
    return EVP_PKEY_generate(ctx, ppkey);
267
0
}
268
269
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
270
0
{
271
0
    if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
272
0
        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
273
0
        return -1;
274
0
    }
275
0
    return EVP_PKEY_generate(ctx, ppkey);
276
0
}
277
278
void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
279
0
{
280
0
    ctx->pkey_gencb = cb;
281
0
}
282
283
EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx)
284
0
{
285
0
    return ctx->pkey_gencb;
286
0
}
287
288
/*
289
 * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style
290
 * callbacks.
291
 */
292
293
static int trans_cb(int a, int b, BN_GENCB *gcb)
294
0
{
295
0
    EVP_PKEY_CTX *ctx = BN_GENCB_get_arg(gcb);
296
0
    ctx->keygen_info[0] = a;
297
0
    ctx->keygen_info[1] = b;
298
0
    return ctx->pkey_gencb(ctx);
299
0
}
300
301
void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx)
302
0
{
303
0
    BN_GENCB_set(cb, trans_cb, ctx);
304
0
}
305
306
int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
307
0
{
308
0
    if (idx == -1)
309
0
        return ctx->keygen_info_count;
310
0
    if (idx < 0 || idx > ctx->keygen_info_count)
311
0
        return 0;
312
0
    return ctx->keygen_info[idx];
313
0
}
314
315
#ifndef FIPS_MODULE
316
317
EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
318
                               const unsigned char *key, int keylen)
319
0
{
320
0
    EVP_PKEY_CTX *mac_ctx = NULL;
321
0
    EVP_PKEY *mac_key = NULL;
322
323
0
    if (!ossl_assert(e == NULL))
324
0
        return NULL;
325
0
    mac_ctx = EVP_PKEY_CTX_new_id(type, NULL);
326
0
    if (!mac_ctx)
327
0
        return NULL;
328
0
    if (EVP_PKEY_keygen_init(mac_ctx) <= 0)
329
0
        goto merr;
330
0
    if (EVP_PKEY_CTX_set_mac_key(mac_ctx, key, keylen) <= 0)
331
0
        goto merr;
332
0
    if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0)
333
0
        goto merr;
334
0
 merr:
335
0
    EVP_PKEY_CTX_free(mac_ctx);
336
0
    return mac_key;
337
0
}
338
339
#endif /* FIPS_MODULE */
340
341
/*- All methods below can also be used in FIPS_MODULE */
342
343
static int fromdata_init(EVP_PKEY_CTX *ctx, int operation)
344
0
{
345
0
    if (ctx == NULL || ctx->keytype == NULL)
346
0
        goto not_supported;
347
348
0
    evp_pkey_ctx_free_old_ops(ctx);
349
0
    if (ctx->keymgmt == NULL)
350
0
        goto not_supported;
351
352
0
    ctx->operation = operation;
353
0
    return 1;
354
355
0
 not_supported:
356
0
    if (ctx != NULL)
357
0
        ctx->operation = EVP_PKEY_OP_UNDEFINED;
358
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
359
0
    return -2;
360
0
}
361
362
int EVP_PKEY_fromdata_init(EVP_PKEY_CTX *ctx)
363
0
{
364
0
    return fromdata_init(ctx, EVP_PKEY_OP_FROMDATA);
365
0
}
366
367
int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, int selection,
368
                      OSSL_PARAM params[])
369
0
{
370
0
    void *keydata = NULL;
371
0
    EVP_PKEY *allocated_pkey = NULL;
372
373
0
    if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_FROMDATA) == 0) {
374
0
        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
375
0
        return -2;
376
0
    }
377
378
0
    if (ppkey == NULL)
379
0
        return -1;
380
381
0
    if (*ppkey == NULL)
382
0
        allocated_pkey = *ppkey = EVP_PKEY_new();
383
384
0
    if (*ppkey == NULL) {
385
0
        ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
386
0
        return -1;
387
0
    }
388
389
0
    keydata = evp_keymgmt_util_fromdata(*ppkey, ctx->keymgmt, selection, params);
390
0
    if (keydata == NULL) {
391
0
        if (allocated_pkey != NULL) {
392
0
            *ppkey = NULL;
393
0
            EVP_PKEY_free(allocated_pkey);
394
0
        }
395
0
        return 0;
396
0
    }
397
    /* keydata is cached in *ppkey, so we need not bother with it further */
398
0
    return 1;
399
0
}
400
401
const OSSL_PARAM *EVP_PKEY_fromdata_settable(EVP_PKEY_CTX *ctx, int selection)
402
0
{
403
    /* We call fromdata_init to get ctx->keymgmt populated */
404
0
    if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED) == 1)
405
0
        return evp_keymgmt_import_types(ctx->keymgmt, selection);
406
0
    return NULL;
407
0
}
408
409
static OSSL_CALLBACK ossl_pkey_todata_cb;
410
411
static int ossl_pkey_todata_cb(const OSSL_PARAM params[], void *arg)
412
0
{
413
0
    OSSL_PARAM **ret = arg;
414
415
0
    *ret = OSSL_PARAM_dup(params);
416
0
    return 1;
417
0
}
418
419
int EVP_PKEY_todata(const EVP_PKEY *pkey, int selection, OSSL_PARAM **params)
420
0
{
421
0
    if (params == NULL)
422
0
        return 0;
423
0
    return EVP_PKEY_export(pkey, selection, ossl_pkey_todata_cb, params);
424
0
}
425
426
#ifndef FIPS_MODULE
427
struct fake_import_data_st {
428
    OSSL_CALLBACK *export_cb;
429
    void *export_cbarg;
430
};
431
432
static OSSL_FUNC_keymgmt_import_fn pkey_fake_import;
433
static int pkey_fake_import(void *fake_keydata, int ignored_selection,
434
                            const OSSL_PARAM params[])
435
0
{
436
0
    struct fake_import_data_st *data = fake_keydata;
437
438
0
    return data->export_cb(params, data->export_cbarg);
439
0
}
440
#endif
441
442
int EVP_PKEY_export(const EVP_PKEY *pkey, int selection,
443
                    OSSL_CALLBACK *export_cb, void *export_cbarg)
444
0
{
445
0
    if (pkey == NULL) {
446
0
        ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
447
0
        return 0;
448
0
    }
449
0
#ifndef FIPS_MODULE
450
0
    if (evp_pkey_is_legacy(pkey)) {
451
0
        struct fake_import_data_st data;
452
453
0
        data.export_cb = export_cb;
454
0
        data.export_cbarg = export_cbarg;
455
456
        /*
457
         * We don't need to care about libctx or propq here, as we're only
458
         * interested in the resulting OSSL_PARAM array.
459
         */
460
0
        return pkey->ameth->export_to(pkey, &data, pkey_fake_import,
461
0
                                      NULL, NULL);
462
0
    }
463
0
#endif
464
0
    return evp_keymgmt_util_export(pkey, selection, export_cb, export_cbarg);
465
0
}