Coverage Report

Created: 2025-06-13 06:56

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