Coverage Report

Created: 2025-12-10 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/evp/ec_ctrl.c
Line
Count
Source
1
/*
2
 * Copyright 2020-2023 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 "internal/deprecated.h"
11
12
#include <openssl/core_names.h>
13
#include <openssl/err.h>
14
#include <openssl/ec.h>
15
#include "crypto/evp.h"
16
#include "crypto/ec.h"
17
18
/*
19
 * This file is meant to contain functions to provide EVP_PKEY support for EC
20
 * keys.
21
 */
22
23
static ossl_inline int evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX *ctx)
24
0
{
25
0
    if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
26
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
27
        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
28
0
        return -2;
29
0
    }
30
31
    /* If key type not EC return error */
32
0
    if (evp_pkey_ctx_is_legacy(ctx)
33
0
        && ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
34
0
        return -1;
35
36
0
    return 1;
37
0
}
38
39
int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode)
40
0
{
41
0
    int ret;
42
0
    OSSL_PARAM params[2], *p = params;
43
44
0
    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
45
0
    if (ret != 1)
46
0
        return ret;
47
48
    /*
49
     * Valid input values are:
50
     *  * 0 for disable
51
     *  * 1 for enable
52
     *  * -1 for reset to default for associated priv key
53
     */
54
0
    if (cofactor_mode < -1 || cofactor_mode > 1) {
55
        /* Uses the same return value of pkey_ec_ctrl() */
56
0
        return -2;
57
0
    }
58
59
0
    *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
60
0
        &cofactor_mode);
61
0
    *p++ = OSSL_PARAM_construct_end();
62
63
0
    ret = evp_pkey_ctx_set_params_strict(ctx, params);
64
0
    if (ret == -2)
65
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
66
0
    return ret;
67
0
}
68
69
int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx)
70
0
{
71
0
    int ret, mode;
72
0
    OSSL_PARAM params[2], *p = params;
73
74
0
    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
75
0
    if (ret != 1)
76
0
        return ret;
77
78
0
    *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
79
0
        &mode);
80
0
    *p++ = OSSL_PARAM_construct_end();
81
82
0
    ret = evp_pkey_ctx_get_params_strict(ctx, params);
83
84
0
    switch (ret) {
85
0
    case -2:
86
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
87
0
        break;
88
0
    case 1:
89
0
        ret = mode;
90
0
        if (mode < 0 || mode > 1) {
91
            /*
92
             * The provider should return either 0 or 1, any other value is a
93
             * provider error.
94
             */
95
0
            ret = -1;
96
0
        }
97
0
        break;
98
0
    default:
99
0
        ret = -1;
100
0
        break;
101
0
    }
102
103
0
    return ret;
104
0
}
105
106
/*
107
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
108
 * simply because that's easier.
109
 */
110
int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
111
0
{
112
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
113
0
        EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL);
114
0
}
115
116
/*
117
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
118
 * simply because that's easier.
119
 */
120
int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx)
121
0
{
122
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
123
0
        EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL);
124
0
}
125
126
/*
127
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
128
 * simply because that's easier.
129
 */
130
int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
131
0
{
132
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
133
0
        EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md));
134
0
}
135
136
/*
137
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
138
 * simply because that's easier.
139
 */
140
int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
141
0
{
142
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
143
0
        EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd));
144
0
}
145
146
int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int outlen)
147
0
{
148
0
    int ret;
149
0
    size_t len = outlen;
150
0
    OSSL_PARAM params[2], *p = params;
151
152
0
    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
153
0
    if (ret != 1)
154
0
        return ret;
155
156
0
    if (outlen <= 0) {
157
        /*
158
         * This would ideally be -1 or 0, but we have to retain compatibility
159
         * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
160
         * in <= 0
161
         */
162
0
        return -2;
163
0
    }
164
165
0
    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
166
0
        &len);
167
0
    *p++ = OSSL_PARAM_construct_end();
168
169
0
    ret = evp_pkey_ctx_set_params_strict(ctx, params);
170
0
    if (ret == -2)
171
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
172
0
    return ret;
173
0
}
174
175
int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
176
0
{
177
0
    size_t len = UINT_MAX;
178
0
    int ret;
179
0
    OSSL_PARAM params[2], *p = params;
180
181
0
    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
182
0
    if (ret != 1)
183
0
        return ret;
184
185
0
    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
186
0
        &len);
187
0
    *p++ = OSSL_PARAM_construct_end();
188
189
0
    ret = evp_pkey_ctx_get_params_strict(ctx, params);
190
191
0
    switch (ret) {
192
0
    case -2:
193
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
194
0
        break;
195
0
    case 1:
196
0
        if (len <= INT_MAX)
197
0
            *plen = (int)len;
198
0
        else
199
0
            ret = -1;
200
0
        break;
201
0
    default:
202
0
        ret = -1;
203
0
        break;
204
0
    }
205
206
0
    return ret;
207
0
}
208
209
int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
210
0
{
211
0
    int ret;
212
0
    OSSL_PARAM params[2], *p = params;
213
214
0
    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
215
0
    if (ret != 1)
216
0
        return ret;
217
218
0
    *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
219
        /*
220
         * Cast away the const. This is read
221
         * only so should be safe
222
         */
223
0
        (void *)ukm,
224
0
        (size_t)len);
225
0
    *p++ = OSSL_PARAM_construct_end();
226
227
0
    ret = evp_pkey_ctx_set_params_strict(ctx, params);
228
229
0
    switch (ret) {
230
0
    case -2:
231
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
232
0
        break;
233
0
    case 1:
234
0
        OPENSSL_free(ukm);
235
0
        break;
236
0
    }
237
238
0
    return ret;
239
0
}
240
241
#ifndef OPENSSL_NO_DEPRECATED_3_0
242
int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
243
0
{
244
0
    size_t ukmlen;
245
0
    int ret;
246
0
    OSSL_PARAM params[2], *p = params;
247
248
0
    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
249
0
    if (ret != 1)
250
0
        return ret;
251
252
0
    *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
253
0
        (void **)pukm, 0);
254
0
    *p++ = OSSL_PARAM_construct_end();
255
256
0
    ret = evp_pkey_ctx_get_params_strict(ctx, params);
257
258
0
    switch (ret) {
259
0
    case -2:
260
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
261
0
        break;
262
0
    case 1:
263
0
        ret = -1;
264
0
        ukmlen = params[0].return_size;
265
0
        if (ukmlen <= INT_MAX)
266
0
            ret = (int)ukmlen;
267
0
        break;
268
0
    default:
269
0
        ret = -1;
270
0
        break;
271
0
    }
272
273
0
    return ret;
274
0
}
275
#endif
276
277
#ifndef FIPS_MODULE
278
/*
279
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
280
 * simply because that's easier.
281
 * ASN1_OBJECT (which would be converted to text internally)?
282
 */
283
int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid)
284
0
{
285
0
    int keytype = nid == EVP_PKEY_SM2 ? EVP_PKEY_SM2 : EVP_PKEY_EC;
286
287
0
    return EVP_PKEY_CTX_ctrl(ctx, keytype, EVP_PKEY_OP_TYPE_GEN,
288
0
        EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID,
289
0
        nid, NULL);
290
0
}
291
292
/*
293
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
294
 * simply because that's easier.
295
 */
296
int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc)
297
0
{
298
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN,
299
0
        EVP_PKEY_CTRL_EC_PARAM_ENC, param_enc, NULL);
300
0
}
301
#endif