1240116Smarcel/*
2240116Smarcel * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
3240116Smarcel *
4240116Smarcel * Licensed under the Apache License 2.0 (the "License").  You may not use
5240116Smarcel * this file except in compliance with the License.  You can obtain a copy
6240116Smarcel * in the file LICENSE in the source distribution or at
7240116Smarcel * https://www.openssl.org/source/license.html
8240116Smarcel */
9240116Smarcel
10240116Smarcel#include "internal/deprecated.h"
11240116Smarcel
12240116Smarcel#include <openssl/core_names.h>
13240116Smarcel#include <openssl/err.h>
14240116Smarcel#include <openssl/ec.h>
15240116Smarcel#include "crypto/evp.h"
16240116Smarcel#include "crypto/ec.h"
17240116Smarcel
18240116Smarcel/*
19240116Smarcel * This file is meant to contain functions to provide EVP_PKEY support for EC
20240116Smarcel * keys.
21240116Smarcel */
22240116Smarcel
23240116Smarcelstatic ossl_inline
24240116Smarcelint evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX *ctx)
25240116Smarcel{
26240116Smarcel    if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
27240116Smarcel        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
28240116Smarcel        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
29240116Smarcel        return -2;
30240116Smarcel    }
31240116Smarcel
32240116Smarcel    /* If key type not EC return error */
33240116Smarcel    if (evp_pkey_ctx_is_legacy(ctx)
34240116Smarcel        && ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
35240116Smarcel        return -1;
36240116Smarcel
37240116Smarcel    return 1;
38240116Smarcel}
39240116Smarcel
40240116Smarcelint EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode)
41240116Smarcel{
42240116Smarcel    int ret;
43240116Smarcel    OSSL_PARAM params[2], *p = params;
44240116Smarcel
45240116Smarcel    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
46240116Smarcel    if (ret != 1)
47240116Smarcel        return ret;
48240116Smarcel
49240116Smarcel    /*
50240116Smarcel     * Valid input values are:
51240116Smarcel     *  * 0 for disable
52240116Smarcel     *  * 1 for enable
53260029Sjmmv     *  * -1 for reset to default for associated priv key
54240116Smarcel     */
55240116Smarcel    if (cofactor_mode < -1 || cofactor_mode > 1) {
56260029Sjmmv        /* Uses the same return value of pkey_ec_ctrl() */
57240116Smarcel        return -2;
58240116Smarcel    }
59240116Smarcel
60240116Smarcel    *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
61240116Smarcel                                    &cofactor_mode);
62240116Smarcel    *p++ = OSSL_PARAM_construct_end();
63240116Smarcel
64240116Smarcel    ret = evp_pkey_ctx_set_params_strict(ctx, params);
65240116Smarcel    if (ret == -2)
66240116Smarcel        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
67240116Smarcel    return ret;
68240116Smarcel}
69240116Smarcel
70240116Smarcelint EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx)
71240116Smarcel{
72240116Smarcel    int ret, mode;
73240116Smarcel    OSSL_PARAM params[2], *p = params;
74240116Smarcel
75240116Smarcel    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
76240116Smarcel    if (ret != 1)
77240116Smarcel        return ret;
78240116Smarcel
79240116Smarcel    *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
80240116Smarcel                                    &mode);
81240116Smarcel    *p++ = OSSL_PARAM_construct_end();
82240116Smarcel
83240116Smarcel    ret = evp_pkey_ctx_get_params_strict(ctx, params);
84240116Smarcel
85240116Smarcel    switch (ret) {
86240116Smarcel    case -2:
87240116Smarcel        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
88240116Smarcel        break;
89240116Smarcel    case 1:
90240116Smarcel        ret = mode;
91240116Smarcel        if (mode < 0 || mode > 1) {
92240116Smarcel            /*
93240116Smarcel             * The provider should return either 0 or 1, any other value is a
94240116Smarcel             * provider error.
95240116Smarcel             */
96240116Smarcel            ret = -1;
97240116Smarcel        }
98240116Smarcel        break;
99240116Smarcel    default:
100240116Smarcel        ret = -1;
101240116Smarcel        break;
102240116Smarcel    }
103240116Smarcel
104240116Smarcel    return ret;
105240116Smarcel}
106240116Smarcel
107240116Smarcel/*
108240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
109240116Smarcel * simply because that's easier.
110240116Smarcel */
111240116Smarcelint EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
112240116Smarcel{
113240116Smarcel    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
114240116Smarcel                             EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL);
115240116Smarcel}
116240116Smarcel
117240116Smarcel/*
118240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
119240116Smarcel * simply because that's easier.
120240116Smarcel */
121240116Smarcelint EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx)
122240116Smarcel{
123240116Smarcel    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
124240116Smarcel                             EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL);
125240116Smarcel}
126240116Smarcel
127240116Smarcel/*
128240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
129240116Smarcel * simply because that's easier.
130240116Smarcel */
131240116Smarcelint EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
132240116Smarcel{
133240116Smarcel    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
134240116Smarcel                             EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md));
135240116Smarcel}
136240116Smarcel
137240116Smarcel/*
138240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
139240116Smarcel * simply because that's easier.
140240116Smarcel */
141240116Smarcelint EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
142240116Smarcel{
143240116Smarcel    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
144240116Smarcel                             EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd));
145240116Smarcel}
146240116Smarcel
147240116Smarcelint EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int outlen)
148240116Smarcel{
149240116Smarcel    int ret;
150240116Smarcel    size_t len = outlen;
151240116Smarcel    OSSL_PARAM params[2], *p = params;
152240116Smarcel
153240116Smarcel    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
154240116Smarcel    if (ret != 1)
155240116Smarcel        return ret;
156240116Smarcel
157240116Smarcel    if (outlen <= 0) {
158240116Smarcel        /*
159240116Smarcel         * This would ideally be -1 or 0, but we have to retain compatibility
160240116Smarcel         * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
161240116Smarcel         * in <= 0
162240116Smarcel         */
163240116Smarcel        return -2;
164240116Smarcel    }
165240116Smarcel
166240116Smarcel    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
167240116Smarcel                                       &len);
168240116Smarcel    *p++ = OSSL_PARAM_construct_end();
169240116Smarcel
170240116Smarcel    ret = evp_pkey_ctx_set_params_strict(ctx, params);
171240116Smarcel    if (ret == -2)
172240116Smarcel        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
173240116Smarcel    return ret;
174240116Smarcel}
175240116Smarcel
176240116Smarcelint EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
177240116Smarcel{
178240116Smarcel    size_t len = UINT_MAX;
179240116Smarcel    int ret;
180240116Smarcel    OSSL_PARAM params[2], *p = params;
181240116Smarcel
182240116Smarcel    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
183240116Smarcel    if (ret != 1)
184240116Smarcel        return ret;
185240116Smarcel
186240116Smarcel    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
187240116Smarcel                                       &len);
188240116Smarcel    *p++ = OSSL_PARAM_construct_end();
189240116Smarcel
190240116Smarcel    ret = evp_pkey_ctx_get_params_strict(ctx, params);
191240116Smarcel
192240116Smarcel    switch (ret) {
193240116Smarcel    case -2:
194240116Smarcel        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
195240116Smarcel        break;
196240116Smarcel    case 1:
197240116Smarcel        if (len <= INT_MAX)
198240116Smarcel            *plen = (int)len;
199240116Smarcel        else
200240116Smarcel            ret = -1;
201240116Smarcel        break;
202240116Smarcel    default:
203240116Smarcel        ret = -1;
204240116Smarcel        break;
205240116Smarcel    }
206240116Smarcel
207240116Smarcel    return ret;
208240116Smarcel}
209240116Smarcel
210240116Smarcelint EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
211240116Smarcel{
212240116Smarcel    int ret;
213240116Smarcel    OSSL_PARAM params[2], *p = params;
214240116Smarcel
215240116Smarcel    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
216240116Smarcel    if (ret != 1)
217240116Smarcel        return ret;
218240116Smarcel
219240116Smarcel    *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
220240116Smarcel                                            /*
221240116Smarcel                                             * Cast away the const. This is read
222240116Smarcel                                             * only so should be safe
223240116Smarcel                                             */
224240116Smarcel                                            (void *)ukm,
225240116Smarcel                                            (size_t)len);
226240116Smarcel    *p++ = OSSL_PARAM_construct_end();
227240116Smarcel
228240116Smarcel    ret = evp_pkey_ctx_set_params_strict(ctx, params);
229240116Smarcel
230240116Smarcel    switch (ret) {
231240116Smarcel    case -2:
232240116Smarcel        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
233240116Smarcel        break;
234240116Smarcel    case 1:
235240116Smarcel        OPENSSL_free(ukm);
236240116Smarcel        break;
237240116Smarcel    }
238240116Smarcel
239240116Smarcel    return ret;
240240116Smarcel}
241240116Smarcel
242240116Smarcel#ifndef OPENSSL_NO_DEPRECATED_3_0
243240116Smarcelint EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
244240116Smarcel{
245240116Smarcel    size_t ukmlen;
246240116Smarcel    int ret;
247240116Smarcel    OSSL_PARAM params[2], *p = params;
248240116Smarcel
249240116Smarcel    ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
250240116Smarcel    if (ret != 1)
251240116Smarcel        return ret;
252240116Smarcel
253240116Smarcel    *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
254240116Smarcel                                          (void **)pukm, 0);
255240116Smarcel    *p++ = OSSL_PARAM_construct_end();
256240116Smarcel
257240116Smarcel    ret = evp_pkey_ctx_get_params_strict(ctx, params);
258240116Smarcel
259240116Smarcel    switch (ret) {
260240116Smarcel    case -2:
261240116Smarcel        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
262240116Smarcel        break;
263240116Smarcel    case 1:
264240116Smarcel        ret = -1;
265240116Smarcel        ukmlen = params[0].return_size;
266240116Smarcel        if (ukmlen <= INT_MAX)
267240116Smarcel            ret = (int)ukmlen;
268240116Smarcel        break;
269240116Smarcel    default:
270240116Smarcel        ret = -1;
271240116Smarcel        break;
272240116Smarcel    }
273240116Smarcel
274240116Smarcel    return ret;
275240116Smarcel}
276240116Smarcel#endif
277240116Smarcel
278240116Smarcel#ifndef FIPS_MODULE
279240116Smarcel/*
280240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
281240116Smarcel * simply because that's easier.
282240116Smarcel * ASN1_OBJECT (which would be converted to text internally)?
283240116Smarcel */
284240116Smarcelint EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid)
285240116Smarcel{
286240116Smarcel    int keytype = nid == EVP_PKEY_SM2 ? EVP_PKEY_SM2 : EVP_PKEY_EC;
287240116Smarcel
288240116Smarcel    return EVP_PKEY_CTX_ctrl(ctx, keytype, EVP_PKEY_OP_TYPE_GEN,
289240116Smarcel                             EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID,
290240116Smarcel                             nid, NULL);
291240116Smarcel}
292240116Smarcel
293240116Smarcel/*
294240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
295240116Smarcel * simply because that's easier.
296240116Smarcel */
297240116Smarcelint EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc)
298240116Smarcel{
299240116Smarcel    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN,
300240116Smarcel                             EVP_PKEY_CTRL_EC_PARAM_ENC, param_enc, NULL);
301240116Smarcel}
302240116Smarcel#endif
303240116Smarcel