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