1d4afb5ceSopenharmony_ci /*
2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5d4afb5ceSopenharmony_ci *
6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to
8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the
9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions:
12d4afb5ceSopenharmony_ci *
13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in
14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software.
15d4afb5ceSopenharmony_ci *
16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22d4afb5ceSopenharmony_ci * IN THE SOFTWARE.
23d4afb5ceSopenharmony_ci *
24d4afb5ceSopenharmony_ci *  lws_genec provides an EC abstraction api in lws that works the
25d4afb5ceSopenharmony_ci *  same whether you are using openssl or mbedtls crypto functions underneath.
26d4afb5ceSopenharmony_ci */
27d4afb5ceSopenharmony_ci#include "private-lib-core.h"
28d4afb5ceSopenharmony_ci#include "private-lib-tls-openssl.h"
29d4afb5ceSopenharmony_ci
30d4afb5ceSopenharmony_ci#if !defined(OPENSSL_NO_EC) && defined(LWS_HAVE_EC_KEY_new_by_curve_name) && \
31d4afb5ceSopenharmony_ci    (OPENSSL_VERSION_NUMBER >= 0x30000000l) && \
32d4afb5ceSopenharmony_ci     !defined(LWS_SUPPRESS_DEPRECATED_API_WARNINGS)
33d4afb5ceSopenharmony_ci/* msvc doesn't have #warning... */
34d4afb5ceSopenharmony_ci#error "You probably need LWS_SUPPRESS_DEPRECATED_API_WARNINGS"
35d4afb5ceSopenharmony_ci#endif
36d4afb5ceSopenharmony_ci
37d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL)
38d4afb5ceSopenharmony_ci#include "openssl/ecdh.h"
39d4afb5ceSopenharmony_ci#endif
40d4afb5ceSopenharmony_ci
41d4afb5ceSopenharmony_ci/*
42d4afb5ceSopenharmony_ci * Care: many openssl apis return 1 for success.  These are translated to the
43d4afb5ceSopenharmony_ci * lws convention of 0 for success.
44d4afb5ceSopenharmony_ci */
45d4afb5ceSopenharmony_ci
46d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL)
47d4afb5ceSopenharmony_ciEVP_PKEY * EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *p)
48d4afb5ceSopenharmony_ci{
49d4afb5ceSopenharmony_ci	return p->pkey;
50d4afb5ceSopenharmony_ci}
51d4afb5ceSopenharmony_ci#endif
52d4afb5ceSopenharmony_ci
53d4afb5ceSopenharmony_ci#if !defined(LWS_HAVE_ECDSA_SIG_set0)
54d4afb5ceSopenharmony_cistatic void
55d4afb5ceSopenharmony_ciECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
56d4afb5ceSopenharmony_ci{
57d4afb5ceSopenharmony_ci    if (pr != NULL)
58d4afb5ceSopenharmony_ci        *pr = sig->r;
59d4afb5ceSopenharmony_ci    if (ps != NULL)
60d4afb5ceSopenharmony_ci        *ps = sig->s;
61d4afb5ceSopenharmony_ci}
62d4afb5ceSopenharmony_ci
63d4afb5ceSopenharmony_cistatic int
64d4afb5ceSopenharmony_ciECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
65d4afb5ceSopenharmony_ci{
66d4afb5ceSopenharmony_ci	if (r == NULL || s == NULL)
67d4afb5ceSopenharmony_ci		return 0;
68d4afb5ceSopenharmony_ci	BN_clear_free(sig->r);
69d4afb5ceSopenharmony_ci	BN_clear_free(sig->s);
70d4afb5ceSopenharmony_ci	sig->r = r;
71d4afb5ceSopenharmony_ci	sig->s = s;
72d4afb5ceSopenharmony_ci
73d4afb5ceSopenharmony_ci	return 1;
74d4afb5ceSopenharmony_ci}
75d4afb5ceSopenharmony_ci#endif
76d4afb5ceSopenharmony_ci#if !defined(LWS_HAVE_BN_bn2binpad)
77d4afb5ceSopenharmony_ciint BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
78d4afb5ceSopenharmony_ci{
79d4afb5ceSopenharmony_ci    int i;
80d4afb5ceSopenharmony_ci#if !defined(USE_WOLFSSL)
81d4afb5ceSopenharmony_ci    BN_ULONG l;
82d4afb5ceSopenharmony_ci#endif
83d4afb5ceSopenharmony_ci
84d4afb5ceSopenharmony_ci#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(USE_WOLFSSL)
85d4afb5ceSopenharmony_ci    bn_check_top(a);
86d4afb5ceSopenharmony_ci#endif
87d4afb5ceSopenharmony_ci    i = BN_num_bytes(a);
88d4afb5ceSopenharmony_ci
89d4afb5ceSopenharmony_ci    /* Add leading zeroes if necessary */
90d4afb5ceSopenharmony_ci    if (tolen > i) {
91d4afb5ceSopenharmony_ci        memset(to, 0, (size_t)(tolen - i));
92d4afb5ceSopenharmony_ci        to += tolen - i;
93d4afb5ceSopenharmony_ci    }
94d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL)
95d4afb5ceSopenharmony_ci    BN_bn2bin(a, to);
96d4afb5ceSopenharmony_ci#else
97d4afb5ceSopenharmony_ci    while (i--) {
98d4afb5ceSopenharmony_ci        l = a->d[i / BN_BYTES];
99d4afb5ceSopenharmony_ci        *(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
100d4afb5ceSopenharmony_ci    }
101d4afb5ceSopenharmony_ci#endif
102d4afb5ceSopenharmony_ci    return tolen;
103d4afb5ceSopenharmony_ci}
104d4afb5ceSopenharmony_ci#endif
105d4afb5ceSopenharmony_ci
106d4afb5ceSopenharmony_ciconst struct lws_ec_curves lws_ec_curves[4] = {
107d4afb5ceSopenharmony_ci	/*
108d4afb5ceSopenharmony_ci	 * These are the curves we are willing to use by default...
109d4afb5ceSopenharmony_ci	 *
110d4afb5ceSopenharmony_ci	 * The 3 recommended+ (P-256) and optional curves in RFC7518 7.6
111d4afb5ceSopenharmony_ci	 *
112d4afb5ceSopenharmony_ci	 * Specific keys lengths from RFC8422 p20
113d4afb5ceSopenharmony_ci	 */
114d4afb5ceSopenharmony_ci	{ "P-256", NID_X9_62_prime256v1, 32 },
115d4afb5ceSopenharmony_ci	{ "P-384", NID_secp384r1,	 48 },
116d4afb5ceSopenharmony_ci	{ "P-521", NID_secp521r1,	 66 },
117d4afb5ceSopenharmony_ci
118d4afb5ceSopenharmony_ci	{ NULL, 0, 0 }
119d4afb5ceSopenharmony_ci};
120d4afb5ceSopenharmony_ci
121d4afb5ceSopenharmony_cistatic int
122d4afb5ceSopenharmony_cilws_genec_eckey_import(int nid, EVP_PKEY *pkey,
123d4afb5ceSopenharmony_ci		       const struct lws_gencrypto_keyelem *el)
124d4afb5ceSopenharmony_ci{
125d4afb5ceSopenharmony_ci	EC_KEY *ec = EC_KEY_new_by_curve_name(nid);
126d4afb5ceSopenharmony_ci	BIGNUM *bn_d, *bn_x, *bn_y;
127d4afb5ceSopenharmony_ci	int n;
128d4afb5ceSopenharmony_ci
129d4afb5ceSopenharmony_ci	if (!ec)
130d4afb5ceSopenharmony_ci		return -1;
131d4afb5ceSopenharmony_ci
132d4afb5ceSopenharmony_ci	/*
133d4afb5ceSopenharmony_ci	 * EC_KEY contains
134d4afb5ceSopenharmony_ci	 *
135d4afb5ceSopenharmony_ci	 * EC_GROUP * 	group
136d4afb5ceSopenharmony_ci	 * EC_POINT * 	pub_key
137d4afb5ceSopenharmony_ci	 * BIGNUM * 	priv_key  (ie, d)
138d4afb5ceSopenharmony_ci	 */
139d4afb5ceSopenharmony_ci
140d4afb5ceSopenharmony_ci	bn_x = BN_bin2bn(el[LWS_GENCRYPTO_EC_KEYEL_X].buf,
141d4afb5ceSopenharmony_ci			 (int)el[LWS_GENCRYPTO_EC_KEYEL_X].len, NULL);
142d4afb5ceSopenharmony_ci	if (!bn_x) {
143d4afb5ceSopenharmony_ci		lwsl_err("%s: BN_bin2bn (x) fail\n", __func__);
144d4afb5ceSopenharmony_ci		goto bail;
145d4afb5ceSopenharmony_ci	}
146d4afb5ceSopenharmony_ci	bn_y = BN_bin2bn(el[LWS_GENCRYPTO_EC_KEYEL_Y].buf,
147d4afb5ceSopenharmony_ci			(int)el[LWS_GENCRYPTO_EC_KEYEL_Y].len, NULL);
148d4afb5ceSopenharmony_ci	if (!bn_y) {
149d4afb5ceSopenharmony_ci		lwsl_err("%s: BN_bin2bn (y) fail\n", __func__);
150d4afb5ceSopenharmony_ci		goto bail1;
151d4afb5ceSopenharmony_ci	}
152d4afb5ceSopenharmony_ci
153d4afb5ceSopenharmony_ci	/*
154d4afb5ceSopenharmony_ci	 * EC_KEY_set_public_key_affine_coordinates sets the public key for
155d4afb5ceSopenharmony_ci	 * key based on its affine co-ordinates, i.e. it constructs an
156d4afb5ceSopenharmony_ci	 * EC_POINT object based on the supplied x and y values and sets
157d4afb5ceSopenharmony_ci	 * the public key to be this EC_POINT. It will also performs
158d4afb5ceSopenharmony_ci	 * certain sanity checks on the key to confirm that it is valid.
159d4afb5ceSopenharmony_ci	 */
160d4afb5ceSopenharmony_ci
161d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL)
162d4afb5ceSopenharmony_ci	n = wolfSSL_EC_POINT_set_affine_coordinates_GFp(ec->group,
163d4afb5ceSopenharmony_ci                                                ec->pub_key,
164d4afb5ceSopenharmony_ci                                                bn_x, bn_y,
165d4afb5ceSopenharmony_ci                                                NULL);
166d4afb5ceSopenharmony_ci#else
167d4afb5ceSopenharmony_ci	n = EC_KEY_set_public_key_affine_coordinates(ec, bn_x, bn_y);
168d4afb5ceSopenharmony_ci#endif
169d4afb5ceSopenharmony_ci	BN_free(bn_x);
170d4afb5ceSopenharmony_ci	BN_free(bn_y);
171d4afb5ceSopenharmony_ci	if (n != 1) {
172d4afb5ceSopenharmony_ci		lwsl_err("%s: EC_KEY_set_public_key_affine_coordinates fail:\n",
173d4afb5ceSopenharmony_ci			 __func__);
174d4afb5ceSopenharmony_ci		lws_tls_err_describe_clear();
175d4afb5ceSopenharmony_ci		goto bail;
176d4afb5ceSopenharmony_ci	}
177d4afb5ceSopenharmony_ci
178d4afb5ceSopenharmony_ci	if (el[LWS_GENCRYPTO_EC_KEYEL_D].len) {
179d4afb5ceSopenharmony_ci		bn_d = BN_bin2bn(el[LWS_GENCRYPTO_EC_KEYEL_D].buf,
180d4afb5ceSopenharmony_ci				(int)el[LWS_GENCRYPTO_EC_KEYEL_D].len, NULL);
181d4afb5ceSopenharmony_ci		if (!bn_d) {
182d4afb5ceSopenharmony_ci			lwsl_err("%s: BN_bin2bn (d) fail\n", __func__);
183d4afb5ceSopenharmony_ci			goto bail;
184d4afb5ceSopenharmony_ci		}
185d4afb5ceSopenharmony_ci
186d4afb5ceSopenharmony_ci		n = EC_KEY_set_private_key(ec, bn_d);
187d4afb5ceSopenharmony_ci		BN_clear_free(bn_d);
188d4afb5ceSopenharmony_ci		if (n != 1) {
189d4afb5ceSopenharmony_ci			lwsl_err("%s: EC_KEY_set_private_key fail\n", __func__);
190d4afb5ceSopenharmony_ci			goto bail;
191d4afb5ceSopenharmony_ci		}
192d4afb5ceSopenharmony_ci	}
193d4afb5ceSopenharmony_ci
194d4afb5ceSopenharmony_ci	/* explicitly confirm the key pieces are consistent */
195d4afb5ceSopenharmony_ci
196d4afb5ceSopenharmony_ci#if !defined(USE_WOLFSSL)
197d4afb5ceSopenharmony_ci	if (EC_KEY_check_key(ec) != 1) {
198d4afb5ceSopenharmony_ci		lwsl_err("%s: EC_KEY_set_private_key fail\n", __func__);
199d4afb5ceSopenharmony_ci		goto bail;
200d4afb5ceSopenharmony_ci	}
201d4afb5ceSopenharmony_ci#endif
202d4afb5ceSopenharmony_ci
203d4afb5ceSopenharmony_ci	n = EVP_PKEY_assign_EC_KEY(pkey, ec);
204d4afb5ceSopenharmony_ci	if (n != 1) {
205d4afb5ceSopenharmony_ci		lwsl_err("%s: EVP_PKEY_set1_EC_KEY failed\n", __func__);
206d4afb5ceSopenharmony_ci		return -1;
207d4afb5ceSopenharmony_ci	}
208d4afb5ceSopenharmony_ci
209d4afb5ceSopenharmony_ci	return 0;
210d4afb5ceSopenharmony_ci
211d4afb5ceSopenharmony_cibail1:
212d4afb5ceSopenharmony_ci	BN_free(bn_x);
213d4afb5ceSopenharmony_cibail:
214d4afb5ceSopenharmony_ci	EC_KEY_free(ec);
215d4afb5ceSopenharmony_ci
216d4afb5ceSopenharmony_ci	return -1;
217d4afb5ceSopenharmony_ci}
218d4afb5ceSopenharmony_ci
219d4afb5ceSopenharmony_cistatic int
220d4afb5ceSopenharmony_cilws_genec_keypair_import(struct lws_genec_ctx *ctx,
221d4afb5ceSopenharmony_ci			 const struct lws_ec_curves *curve_table,
222d4afb5ceSopenharmony_ci			 EVP_PKEY_CTX **pctx,
223d4afb5ceSopenharmony_ci			 const struct lws_gencrypto_keyelem *el)
224d4afb5ceSopenharmony_ci{
225d4afb5ceSopenharmony_ci	EVP_PKEY *pkey = NULL;
226d4afb5ceSopenharmony_ci	const struct lws_ec_curves *curve;
227d4afb5ceSopenharmony_ci
228d4afb5ceSopenharmony_ci	if (el[LWS_GENCRYPTO_EC_KEYEL_CRV].len < 4)
229d4afb5ceSopenharmony_ci		return -2;
230d4afb5ceSopenharmony_ci
231d4afb5ceSopenharmony_ci	curve = lws_genec_curve(curve_table,
232d4afb5ceSopenharmony_ci				(char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf);
233d4afb5ceSopenharmony_ci	if (!curve)
234d4afb5ceSopenharmony_ci		return -3;
235d4afb5ceSopenharmony_ci
236d4afb5ceSopenharmony_ci	if ((el[LWS_GENCRYPTO_EC_KEYEL_D].len &&
237d4afb5ceSopenharmony_ci	     el[LWS_GENCRYPTO_EC_KEYEL_D].len != curve->key_bytes) ||
238d4afb5ceSopenharmony_ci	    el[LWS_GENCRYPTO_EC_KEYEL_X].len != curve->key_bytes ||
239d4afb5ceSopenharmony_ci	    el[LWS_GENCRYPTO_EC_KEYEL_Y].len != curve->key_bytes)
240d4afb5ceSopenharmony_ci		return -4;
241d4afb5ceSopenharmony_ci
242d4afb5ceSopenharmony_ci	ctx->has_private = !!el[LWS_GENCRYPTO_EC_KEYEL_D].len;
243d4afb5ceSopenharmony_ci
244d4afb5ceSopenharmony_ci	pkey = EVP_PKEY_new();
245d4afb5ceSopenharmony_ci	if (!pkey)
246d4afb5ceSopenharmony_ci		return -7;
247d4afb5ceSopenharmony_ci
248d4afb5ceSopenharmony_ci	if (lws_genec_eckey_import(curve->tls_lib_nid, pkey, el)) {
249d4afb5ceSopenharmony_ci		lwsl_err("%s: lws_genec_eckey_import fail\n", __func__);
250d4afb5ceSopenharmony_ci		goto bail;
251d4afb5ceSopenharmony_ci	}
252d4afb5ceSopenharmony_ci
253d4afb5ceSopenharmony_ci	*pctx = EVP_PKEY_CTX_new(pkey, NULL);
254d4afb5ceSopenharmony_ci	EVP_PKEY_free(pkey);
255d4afb5ceSopenharmony_ci	pkey = NULL;
256d4afb5ceSopenharmony_ci
257d4afb5ceSopenharmony_ci	if (!*pctx)
258d4afb5ceSopenharmony_ci		goto bail;
259d4afb5ceSopenharmony_ci
260d4afb5ceSopenharmony_ci	return 0;
261d4afb5ceSopenharmony_ci
262d4afb5ceSopenharmony_cibail:
263d4afb5ceSopenharmony_ci	if (pkey)
264d4afb5ceSopenharmony_ci		EVP_PKEY_free(pkey);
265d4afb5ceSopenharmony_ci
266d4afb5ceSopenharmony_ci	if (*pctx) {
267d4afb5ceSopenharmony_ci		EVP_PKEY_CTX_free(*pctx);
268d4afb5ceSopenharmony_ci		*pctx = NULL;
269d4afb5ceSopenharmony_ci	}
270d4afb5ceSopenharmony_ci
271d4afb5ceSopenharmony_ci	return -9;
272d4afb5ceSopenharmony_ci}
273d4afb5ceSopenharmony_ci
274d4afb5ceSopenharmony_ciint
275d4afb5ceSopenharmony_cilws_genecdh_create(struct lws_genec_ctx *ctx, struct lws_context *context,
276d4afb5ceSopenharmony_ci		   const struct lws_ec_curves *curve_table)
277d4afb5ceSopenharmony_ci{
278d4afb5ceSopenharmony_ci	ctx->context = context;
279d4afb5ceSopenharmony_ci	ctx->ctx[0] = NULL;
280d4afb5ceSopenharmony_ci	ctx->ctx[1] = NULL;
281d4afb5ceSopenharmony_ci	ctx->curve_table = curve_table;
282d4afb5ceSopenharmony_ci	ctx->genec_alg = LEGENEC_ECDH;
283d4afb5ceSopenharmony_ci
284d4afb5ceSopenharmony_ci	return 0;
285d4afb5ceSopenharmony_ci}
286d4afb5ceSopenharmony_ci
287d4afb5ceSopenharmony_ciint
288d4afb5ceSopenharmony_cilws_genecdsa_create(struct lws_genec_ctx *ctx, struct lws_context *context,
289d4afb5ceSopenharmony_ci		    const struct lws_ec_curves *curve_table)
290d4afb5ceSopenharmony_ci{
291d4afb5ceSopenharmony_ci	ctx->context = context;
292d4afb5ceSopenharmony_ci	ctx->ctx[0] = NULL;
293d4afb5ceSopenharmony_ci	ctx->ctx[1] = NULL;
294d4afb5ceSopenharmony_ci	ctx->curve_table = curve_table;
295d4afb5ceSopenharmony_ci	ctx->genec_alg = LEGENEC_ECDSA;
296d4afb5ceSopenharmony_ci
297d4afb5ceSopenharmony_ci	return 0;
298d4afb5ceSopenharmony_ci}
299d4afb5ceSopenharmony_ci
300d4afb5ceSopenharmony_ciint
301d4afb5ceSopenharmony_cilws_genecdh_set_key(struct lws_genec_ctx *ctx, struct lws_gencrypto_keyelem *el,
302d4afb5ceSopenharmony_ci		    enum enum_lws_dh_side side)
303d4afb5ceSopenharmony_ci{
304d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDH)
305d4afb5ceSopenharmony_ci		return -1;
306d4afb5ceSopenharmony_ci
307d4afb5ceSopenharmony_ci	return lws_genec_keypair_import(ctx, ctx->curve_table, &ctx->ctx[side], el);
308d4afb5ceSopenharmony_ci}
309d4afb5ceSopenharmony_ci
310d4afb5ceSopenharmony_ciint
311d4afb5ceSopenharmony_cilws_genecdsa_set_key(struct lws_genec_ctx *ctx,
312d4afb5ceSopenharmony_ci		     const struct lws_gencrypto_keyelem *el)
313d4afb5ceSopenharmony_ci{
314d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDSA)
315d4afb5ceSopenharmony_ci		return -1;
316d4afb5ceSopenharmony_ci
317d4afb5ceSopenharmony_ci	return lws_genec_keypair_import(ctx, ctx->curve_table, &ctx->ctx[0], el);
318d4afb5ceSopenharmony_ci}
319d4afb5ceSopenharmony_ci
320d4afb5ceSopenharmony_cistatic void
321d4afb5ceSopenharmony_cilws_genec_keypair_destroy(EVP_PKEY_CTX **pctx)
322d4afb5ceSopenharmony_ci{
323d4afb5ceSopenharmony_ci	if (!*pctx)
324d4afb5ceSopenharmony_ci		return;
325d4afb5ceSopenharmony_ci
326d4afb5ceSopenharmony_ci//	lwsl_err("%p\n", EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(*pctx)));
327d4afb5ceSopenharmony_ci
328d4afb5ceSopenharmony_ci//	EC_KEY_free(EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(*pctx)));
329d4afb5ceSopenharmony_ci
330d4afb5ceSopenharmony_ci	EVP_PKEY_CTX_free(*pctx);
331d4afb5ceSopenharmony_ci	*pctx = NULL;
332d4afb5ceSopenharmony_ci}
333d4afb5ceSopenharmony_ci
334d4afb5ceSopenharmony_civoid
335d4afb5ceSopenharmony_cilws_genec_destroy(struct lws_genec_ctx *ctx)
336d4afb5ceSopenharmony_ci{
337d4afb5ceSopenharmony_ci	if (ctx->ctx[0])
338d4afb5ceSopenharmony_ci		lws_genec_keypair_destroy(&ctx->ctx[0]);
339d4afb5ceSopenharmony_ci	if (ctx->ctx[1])
340d4afb5ceSopenharmony_ci		lws_genec_keypair_destroy(&ctx->ctx[1]);
341d4afb5ceSopenharmony_ci}
342d4afb5ceSopenharmony_ci
343d4afb5ceSopenharmony_cistatic int
344d4afb5ceSopenharmony_cilws_genec_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side,
345d4afb5ceSopenharmony_ci		      const char *curve_name, struct lws_gencrypto_keyelem *el)
346d4afb5ceSopenharmony_ci{
347d4afb5ceSopenharmony_ci	const struct lws_ec_curves *curve;
348d4afb5ceSopenharmony_ci	const EC_POINT *pubkey;
349d4afb5ceSopenharmony_ci	EVP_PKEY *pkey = NULL;
350d4afb5ceSopenharmony_ci	int ret = -29, n, m;
351d4afb5ceSopenharmony_ci	BIGNUM *bn[3];
352d4afb5ceSopenharmony_ci	EC_KEY *ec;
353d4afb5ceSopenharmony_ci
354d4afb5ceSopenharmony_ci	curve = lws_genec_curve(ctx->curve_table, curve_name);
355d4afb5ceSopenharmony_ci	if (!curve) {
356d4afb5ceSopenharmony_ci		lwsl_err("%s: curve '%s' not supported\n",
357d4afb5ceSopenharmony_ci			 __func__, curve_name);
358d4afb5ceSopenharmony_ci
359d4afb5ceSopenharmony_ci		return -22;
360d4afb5ceSopenharmony_ci	}
361d4afb5ceSopenharmony_ci
362d4afb5ceSopenharmony_ci	ec = EC_KEY_new_by_curve_name(curve->tls_lib_nid);
363d4afb5ceSopenharmony_ci	if (!ec) {
364d4afb5ceSopenharmony_ci		lwsl_err("%s: unknown nid %d\n", __func__, curve->tls_lib_nid);
365d4afb5ceSopenharmony_ci		return -23;
366d4afb5ceSopenharmony_ci	}
367d4afb5ceSopenharmony_ci
368d4afb5ceSopenharmony_ci	if (EC_KEY_generate_key(ec) != 1) {
369d4afb5ceSopenharmony_ci		lwsl_err("%s: EC_KEY_generate_key failed\n", __func__);
370d4afb5ceSopenharmony_ci		goto bail;
371d4afb5ceSopenharmony_ci	}
372d4afb5ceSopenharmony_ci
373d4afb5ceSopenharmony_ci	pkey = EVP_PKEY_new();
374d4afb5ceSopenharmony_ci	if (!pkey)
375d4afb5ceSopenharmony_ci		goto bail;
376d4afb5ceSopenharmony_ci
377d4afb5ceSopenharmony_ci	if (EVP_PKEY_set1_EC_KEY(pkey, ec) != 1) {
378d4afb5ceSopenharmony_ci		lwsl_err("%s: EVP_PKEY_assign_EC_KEY failed\n", __func__);
379d4afb5ceSopenharmony_ci		goto bail1;
380d4afb5ceSopenharmony_ci	}
381d4afb5ceSopenharmony_ci
382d4afb5ceSopenharmony_ci	ctx->ctx[side] = EVP_PKEY_CTX_new(pkey, NULL);
383d4afb5ceSopenharmony_ci	if (!ctx->ctx[side]) {
384d4afb5ceSopenharmony_ci		lwsl_err("%s: EVP_PKEY_CTX_new failed\n", __func__);
385d4afb5ceSopenharmony_ci		goto bail1;
386d4afb5ceSopenharmony_ci	}
387d4afb5ceSopenharmony_ci
388d4afb5ceSopenharmony_ci	/*
389d4afb5ceSopenharmony_ci	 * we need to capture the individual element BIGNUMs into
390d4afb5ceSopenharmony_ci	 * lws_gencrypto_keyelem, so they can be serialized, used in jwk etc
391d4afb5ceSopenharmony_ci	 */
392d4afb5ceSopenharmony_ci
393d4afb5ceSopenharmony_ci	pubkey = EC_KEY_get0_public_key(ec);
394d4afb5ceSopenharmony_ci	if (!pubkey) {
395d4afb5ceSopenharmony_ci		lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__);
396d4afb5ceSopenharmony_ci		goto bail1;
397d4afb5ceSopenharmony_ci	}
398d4afb5ceSopenharmony_ci
399d4afb5ceSopenharmony_ci	bn[0] = BN_new();
400d4afb5ceSopenharmony_ci	bn[1] = (BIGNUM *)EC_KEY_get0_private_key(ec);
401d4afb5ceSopenharmony_ci	bn[2] = BN_new();
402d4afb5ceSopenharmony_ci
403d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_EC_POINT_get_affine_coordinates)
404d4afb5ceSopenharmony_ci	if (EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
405d4afb5ceSopenharmony_ci#else
406d4afb5ceSopenharmony_ci	if (EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
407d4afb5ceSopenharmony_ci#endif
408d4afb5ceSopenharmony_ci		        pubkey, bn[0], bn[2], NULL) != 1) {
409d4afb5ceSopenharmony_ci		lwsl_err("%s: EC_POINT_get_affine_coordinates_GFp failed\n",
410d4afb5ceSopenharmony_ci			 __func__);
411d4afb5ceSopenharmony_ci		goto bail2;
412d4afb5ceSopenharmony_ci	}
413d4afb5ceSopenharmony_ci
414d4afb5ceSopenharmony_ci	el[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve_name) + 1;
415d4afb5ceSopenharmony_ci	el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf =
416d4afb5ceSopenharmony_ci			lws_malloc(el[LWS_GENCRYPTO_EC_KEYEL_CRV].len, "ec");
417d4afb5ceSopenharmony_ci	if (!el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf) {
418d4afb5ceSopenharmony_ci		lwsl_err("%s: OOM\n", __func__);
419d4afb5ceSopenharmony_ci		goto bail2;
420d4afb5ceSopenharmony_ci	}
421d4afb5ceSopenharmony_ci
422d4afb5ceSopenharmony_ci	strcpy((char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf, curve_name);
423d4afb5ceSopenharmony_ci
424d4afb5ceSopenharmony_ci	for (n = LWS_GENCRYPTO_EC_KEYEL_X; n < LWS_GENCRYPTO_EC_KEYEL_COUNT;
425d4afb5ceSopenharmony_ci	     n++) {
426d4afb5ceSopenharmony_ci		el[n].len = curve->key_bytes;
427d4afb5ceSopenharmony_ci		el[n].buf = lws_malloc(curve->key_bytes, "ec");
428d4afb5ceSopenharmony_ci		if (!el[n].buf)
429d4afb5ceSopenharmony_ci			goto bail2;
430d4afb5ceSopenharmony_ci
431d4afb5ceSopenharmony_ci		m = BN_bn2binpad(bn[n - 1], el[n].buf, (int32_t)el[n].len);
432d4afb5ceSopenharmony_ci		if ((uint32_t)m != el[n].len)
433d4afb5ceSopenharmony_ci			goto bail2;
434d4afb5ceSopenharmony_ci	}
435d4afb5ceSopenharmony_ci
436d4afb5ceSopenharmony_ci	ctx->has_private = 1;
437d4afb5ceSopenharmony_ci
438d4afb5ceSopenharmony_ci	ret = 0;
439d4afb5ceSopenharmony_ci
440d4afb5ceSopenharmony_cibail2:
441d4afb5ceSopenharmony_ci	BN_clear_free(bn[0]);
442d4afb5ceSopenharmony_ci	BN_clear_free(bn[2]);
443d4afb5ceSopenharmony_cibail1:
444d4afb5ceSopenharmony_ci	EVP_PKEY_free(pkey);
445d4afb5ceSopenharmony_cibail:
446d4afb5ceSopenharmony_ci	EC_KEY_free(ec);
447d4afb5ceSopenharmony_ci
448d4afb5ceSopenharmony_ci	return ret;
449d4afb5ceSopenharmony_ci}
450d4afb5ceSopenharmony_ci
451d4afb5ceSopenharmony_ciint
452d4afb5ceSopenharmony_cilws_genecdh_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side,
453d4afb5ceSopenharmony_ci			const char *curve_name,
454d4afb5ceSopenharmony_ci			struct lws_gencrypto_keyelem *el)
455d4afb5ceSopenharmony_ci{
456d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDH)
457d4afb5ceSopenharmony_ci		return -1;
458d4afb5ceSopenharmony_ci
459d4afb5ceSopenharmony_ci	return lws_genec_new_keypair(ctx, side, curve_name, el);
460d4afb5ceSopenharmony_ci}
461d4afb5ceSopenharmony_ci
462d4afb5ceSopenharmony_ciint
463d4afb5ceSopenharmony_cilws_genecdsa_new_keypair(struct lws_genec_ctx *ctx, const char *curve_name,
464d4afb5ceSopenharmony_ci			 struct lws_gencrypto_keyelem *el)
465d4afb5ceSopenharmony_ci{
466d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDSA)
467d4afb5ceSopenharmony_ci		return -1;
468d4afb5ceSopenharmony_ci
469d4afb5ceSopenharmony_ci	return lws_genec_new_keypair(ctx, LDHS_OURS, curve_name, el);
470d4afb5ceSopenharmony_ci}
471d4afb5ceSopenharmony_ci
472d4afb5ceSopenharmony_ci#if 0
473d4afb5ceSopenharmony_ciint
474d4afb5ceSopenharmony_cilws_genecdsa_hash_sign(struct lws_genec_ctx *ctx, const uint8_t *in,
475d4afb5ceSopenharmony_ci		       enum lws_genhash_types hash_type,
476d4afb5ceSopenharmony_ci		       uint8_t *sig, size_t sig_len)
477d4afb5ceSopenharmony_ci{
478d4afb5ceSopenharmony_ci	const EVP_MD *md = lws_gencrypto_openssl_hash_to_EVP_MD(hash_type);
479d4afb5ceSopenharmony_ci	EVP_MD_CTX *mdctx = NULL;
480d4afb5ceSopenharmony_ci
481d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDSA)
482d4afb5ceSopenharmony_ci		return -1;
483d4afb5ceSopenharmony_ci
484d4afb5ceSopenharmony_ci	if (!md)
485d4afb5ceSopenharmony_ci		return -1;
486d4afb5ceSopenharmony_ci
487d4afb5ceSopenharmony_ci	mdctx = EVP_MD_CTX_create();
488d4afb5ceSopenharmony_ci	if (!mdctx)
489d4afb5ceSopenharmony_ci		goto bail;
490d4afb5ceSopenharmony_ci
491d4afb5ceSopenharmony_ci	if (EVP_DigestSignInit(mdctx, NULL, md, NULL,
492d4afb5ceSopenharmony_ci			       EVP_PKEY_CTX_get0_pkey(ctx->ctx))) {
493d4afb5ceSopenharmony_ci		lwsl_err("%s: EVP_DigestSignInit failed\n", __func__);
494d4afb5ceSopenharmony_ci
495d4afb5ceSopenharmony_ci		goto bail;
496d4afb5ceSopenharmony_ci	}
497d4afb5ceSopenharmony_ci	if (EVP_DigestSignUpdate(mdctx, in, EVP_MD_size(md))) {
498d4afb5ceSopenharmony_ci		lwsl_err("%s: EVP_DigestSignUpdate failed\n", __func__);
499d4afb5ceSopenharmony_ci
500d4afb5ceSopenharmony_ci		goto bail;
501d4afb5ceSopenharmony_ci	}
502d4afb5ceSopenharmony_ci	if (EVP_DigestSignFinal(mdctx, sig, &sig_len)) {
503d4afb5ceSopenharmony_ci		lwsl_err("%s: EVP_DigestSignFinal failed\n", __func__);
504d4afb5ceSopenharmony_ci
505d4afb5ceSopenharmony_ci		goto bail;
506d4afb5ceSopenharmony_ci	}
507d4afb5ceSopenharmony_ci
508d4afb5ceSopenharmony_ci	EVP_MD_CTX_free(mdctx);
509d4afb5ceSopenharmony_ci
510d4afb5ceSopenharmony_ci	return (int)sig_len;
511d4afb5ceSopenharmony_cibail:
512d4afb5ceSopenharmony_ci	if (mdctx)
513d4afb5ceSopenharmony_ci		EVP_MD_CTX_free(mdctx);
514d4afb5ceSopenharmony_ci
515d4afb5ceSopenharmony_ci	return -1;
516d4afb5ceSopenharmony_ci}
517d4afb5ceSopenharmony_ci#endif
518d4afb5ceSopenharmony_ci
519d4afb5ceSopenharmony_ciint
520d4afb5ceSopenharmony_cilws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
521d4afb5ceSopenharmony_ci			   enum lws_genhash_types hash_type, int keybits,
522d4afb5ceSopenharmony_ci			   uint8_t *sig, size_t sig_len)
523d4afb5ceSopenharmony_ci{
524d4afb5ceSopenharmony_ci	int ret = -1, n, keybytes = lws_gencrypto_bits_to_bytes(keybits);
525d4afb5ceSopenharmony_ci	size_t hs = lws_genhash_size(hash_type);
526d4afb5ceSopenharmony_ci	const BIGNUM *r = NULL, *s = NULL;
527d4afb5ceSopenharmony_ci	ECDSA_SIG *ecdsasig;
528d4afb5ceSopenharmony_ci	EC_KEY *eckey;
529d4afb5ceSopenharmony_ci
530d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDSA) {
531d4afb5ceSopenharmony_ci		lwsl_notice("%s: ctx alg %d\n", __func__, ctx->genec_alg);
532d4afb5ceSopenharmony_ci		return -1;
533d4afb5ceSopenharmony_ci	}
534d4afb5ceSopenharmony_ci
535d4afb5ceSopenharmony_ci	if (!ctx->has_private)
536d4afb5ceSopenharmony_ci		return -1;
537d4afb5ceSopenharmony_ci
538d4afb5ceSopenharmony_ci	if ((int)sig_len != (int)(keybytes * 2)) {
539d4afb5ceSopenharmony_ci		lwsl_notice("%s: sig buff %d < %d\n", __func__,
540d4afb5ceSopenharmony_ci			    (int)sig_len, (int)(hs * 2));
541d4afb5ceSopenharmony_ci		return -1;
542d4afb5ceSopenharmony_ci	}
543d4afb5ceSopenharmony_ci
544d4afb5ceSopenharmony_ci	eckey = EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(ctx->ctx[0]));
545d4afb5ceSopenharmony_ci
546d4afb5ceSopenharmony_ci	/*
547d4afb5ceSopenharmony_ci	 * The ECDSA P-256 SHA-256 digital signature is generated as follows:
548d4afb5ceSopenharmony_ci	 *
549d4afb5ceSopenharmony_ci	 * 1.  Generate a digital signature of the JWS Signing Input using ECDSA
550d4afb5ceSopenharmony_ci	 *     P-256 SHA-256 with the desired private key.  The output will be
551d4afb5ceSopenharmony_ci	 *     the pair (R, S), where R and S are 256-bit unsigned integers.
552d4afb5ceSopenharmony_ci	 *
553d4afb5ceSopenharmony_ci	 * 2.  Turn R and S into octet sequences in big-endian order, with each
554d4afb5ceSopenharmony_ci	 *     array being be 32 octets long.  The octet sequence
555d4afb5ceSopenharmony_ci	 *     representations MUST NOT be shortened to omit any leading zero
556d4afb5ceSopenharmony_ci	 *     octets contained in the values.
557d4afb5ceSopenharmony_ci	 *
558d4afb5ceSopenharmony_ci	 * 3.  Concatenate the two octet sequences in the order R and then S.
559d4afb5ceSopenharmony_ci	 *     (Note that many ECDSA implementations will directly produce this
560d4afb5ceSopenharmony_ci	 *     concatenation as their output.)
561d4afb5ceSopenharmony_ci	 *
562d4afb5ceSopenharmony_ci	 * 4.  The resulting 64-octet sequence is the JWS Signature value.
563d4afb5ceSopenharmony_ci	 */
564d4afb5ceSopenharmony_ci
565d4afb5ceSopenharmony_ci	ecdsasig = ECDSA_do_sign(in, (int)hs, eckey);
566d4afb5ceSopenharmony_ci	EC_KEY_free(eckey);
567d4afb5ceSopenharmony_ci	if (!ecdsasig) {
568d4afb5ceSopenharmony_ci		lwsl_notice("%s: ECDSA_do_sign fail\n", __func__);
569d4afb5ceSopenharmony_ci		goto bail;
570d4afb5ceSopenharmony_ci	}
571d4afb5ceSopenharmony_ci
572d4afb5ceSopenharmony_ci	ECDSA_SIG_get0(ecdsasig, &r, &s);
573d4afb5ceSopenharmony_ci
574d4afb5ceSopenharmony_ci	/*
575d4afb5ceSopenharmony_ci	 * in the 521-bit case, we have to pad the last byte as it only
576d4afb5ceSopenharmony_ci	 * generates 65 bytes
577d4afb5ceSopenharmony_ci	 */
578d4afb5ceSopenharmony_ci
579d4afb5ceSopenharmony_ci	n = BN_bn2binpad(r, sig, keybytes);
580d4afb5ceSopenharmony_ci	if (n != keybytes) {
581d4afb5ceSopenharmony_ci		lwsl_notice("%s: bignum r fail %d %d\n", __func__, n, keybytes);
582d4afb5ceSopenharmony_ci		goto bail;
583d4afb5ceSopenharmony_ci	}
584d4afb5ceSopenharmony_ci
585d4afb5ceSopenharmony_ci	n = BN_bn2binpad(s, sig + keybytes, keybytes);
586d4afb5ceSopenharmony_ci	if (n != keybytes) {
587d4afb5ceSopenharmony_ci		lwsl_notice("%s: bignum s fail %d %d\n", __func__, n, keybytes);
588d4afb5ceSopenharmony_ci		goto bail;
589d4afb5ceSopenharmony_ci	}
590d4afb5ceSopenharmony_ci
591d4afb5ceSopenharmony_ci	ret = 0;
592d4afb5ceSopenharmony_ci
593d4afb5ceSopenharmony_cibail:
594d4afb5ceSopenharmony_ci	if (ecdsasig)
595d4afb5ceSopenharmony_ci		ECDSA_SIG_free(ecdsasig);
596d4afb5ceSopenharmony_ci
597d4afb5ceSopenharmony_ci	return ret;
598d4afb5ceSopenharmony_ci}
599d4afb5ceSopenharmony_ci
600d4afb5ceSopenharmony_ci/* in is the JWS Signing Input hash */
601d4afb5ceSopenharmony_ci
602d4afb5ceSopenharmony_ciint
603d4afb5ceSopenharmony_cilws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
604d4afb5ceSopenharmony_ci				 enum lws_genhash_types hash_type, int keybits,
605d4afb5ceSopenharmony_ci				 const uint8_t *sig, size_t sig_len)
606d4afb5ceSopenharmony_ci{
607d4afb5ceSopenharmony_ci	int ret = -1, n, hlen = (int)lws_genhash_size(hash_type),
608d4afb5ceSopenharmony_ci			keybytes = lws_gencrypto_bits_to_bytes(keybits);
609d4afb5ceSopenharmony_ci	ECDSA_SIG *ecsig = ECDSA_SIG_new();
610d4afb5ceSopenharmony_ci	BIGNUM *r = NULL, *s = NULL;
611d4afb5ceSopenharmony_ci	EC_KEY *eckey;
612d4afb5ceSopenharmony_ci
613d4afb5ceSopenharmony_ci	if (!ecsig)
614d4afb5ceSopenharmony_ci		return -1;
615d4afb5ceSopenharmony_ci
616d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDSA)
617d4afb5ceSopenharmony_ci		goto bail;
618d4afb5ceSopenharmony_ci
619d4afb5ceSopenharmony_ci	if ((int)sig_len != keybytes * 2) {
620d4afb5ceSopenharmony_ci		lwsl_err("%s: sig buf size %d vs %d\n", __func__,
621d4afb5ceSopenharmony_ci			 (int)sig_len, keybytes * 2);
622d4afb5ceSopenharmony_ci		goto bail;
623d4afb5ceSopenharmony_ci	}
624d4afb5ceSopenharmony_ci	/*
625d4afb5ceSopenharmony_ci	 * 1.  The JWS Signature value MUST be a 64-octet sequence.  If it is
626d4afb5ceSopenharmony_ci	 *     not a 64-octet sequence, the validation has failed.
627d4afb5ceSopenharmony_ci	 *
628d4afb5ceSopenharmony_ci	 * 2.  Split the 64-octet sequence into two 32-octet sequences.  The
629d4afb5ceSopenharmony_ci	 *     first octet sequence represents R and the second S.  The values R
630d4afb5ceSopenharmony_ci	 *     and S are represented as octet sequences using the Integer-to-
631d4afb5ceSopenharmony_ci	 *     OctetString Conversion defined in Section 2.3.7 of SEC1 [SEC1]
632d4afb5ceSopenharmony_ci	 *     (in big-endian octet order).
633d4afb5ceSopenharmony_ci	 *
634d4afb5ceSopenharmony_ci	 * 3.  Submit the JWS Signing Input, R, S, and the public key (x, y) to
635d4afb5ceSopenharmony_ci	 *     the ECDSA P-256 SHA-256 validator.
636d4afb5ceSopenharmony_ci	 */
637d4afb5ceSopenharmony_ci
638d4afb5ceSopenharmony_ci	r = BN_bin2bn(sig, keybytes, NULL);
639d4afb5ceSopenharmony_ci	if (!r) {
640d4afb5ceSopenharmony_ci		lwsl_err("%s: BN_bin2bn (r) fail\n", __func__);
641d4afb5ceSopenharmony_ci		goto bail;
642d4afb5ceSopenharmony_ci	}
643d4afb5ceSopenharmony_ci
644d4afb5ceSopenharmony_ci	s = BN_bin2bn(sig + keybytes, keybytes, NULL);
645d4afb5ceSopenharmony_ci	if (!s) {
646d4afb5ceSopenharmony_ci		lwsl_err("%s: BN_bin2bn (s) fail\n", __func__);
647d4afb5ceSopenharmony_ci		goto bail1;
648d4afb5ceSopenharmony_ci	}
649d4afb5ceSopenharmony_ci
650d4afb5ceSopenharmony_ci	if (ECDSA_SIG_set0(ecsig, r, s) != 1) {
651d4afb5ceSopenharmony_ci		lwsl_err("%s: ECDSA_SIG_set0 fail\n", __func__);
652d4afb5ceSopenharmony_ci		goto bail1;
653d4afb5ceSopenharmony_ci	}
654d4afb5ceSopenharmony_ci
655d4afb5ceSopenharmony_ci	eckey = EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(ctx->ctx[0]));
656d4afb5ceSopenharmony_ci
657d4afb5ceSopenharmony_ci	n = ECDSA_do_verify(in, hlen, ecsig, eckey);
658d4afb5ceSopenharmony_ci	EC_KEY_free(eckey);
659d4afb5ceSopenharmony_ci	if (n != 1) {
660d4afb5ceSopenharmony_ci		lwsl_err("%s: ECDSA_do_verify fail, hlen %d\n", __func__, (int)hlen);
661d4afb5ceSopenharmony_ci		lws_tls_err_describe_clear();
662d4afb5ceSopenharmony_ci		goto bail;
663d4afb5ceSopenharmony_ci	}
664d4afb5ceSopenharmony_ci
665d4afb5ceSopenharmony_ci	ret = 0;
666d4afb5ceSopenharmony_ci	goto bail;
667d4afb5ceSopenharmony_ci
668d4afb5ceSopenharmony_cibail1:
669d4afb5ceSopenharmony_ci	if (r)
670d4afb5ceSopenharmony_ci		BN_free(r);
671d4afb5ceSopenharmony_ci	if (s)
672d4afb5ceSopenharmony_ci		BN_free(s);
673d4afb5ceSopenharmony_ci
674d4afb5ceSopenharmony_cibail:
675d4afb5ceSopenharmony_ci	ECDSA_SIG_free(ecsig);
676d4afb5ceSopenharmony_ci
677d4afb5ceSopenharmony_ci	return ret;
678d4afb5ceSopenharmony_ci}
679d4afb5ceSopenharmony_ci
680d4afb5ceSopenharmony_ciint
681d4afb5ceSopenharmony_cilws_genecdh_compute_shared_secret(struct lws_genec_ctx *ctx, uint8_t *ss,
682d4afb5ceSopenharmony_ci				  int *ss_len)
683d4afb5ceSopenharmony_ci{
684d4afb5ceSopenharmony_ci	int len, ret = -1;
685d4afb5ceSopenharmony_ci	EC_KEY *eckey[2];
686d4afb5ceSopenharmony_ci
687d4afb5ceSopenharmony_ci	if (!ctx->ctx[LDHS_OURS] || !ctx->ctx[LDHS_THEIRS]) {
688d4afb5ceSopenharmony_ci		lwsl_err("%s: both sides must be set up\n", __func__);
689d4afb5ceSopenharmony_ci
690d4afb5ceSopenharmony_ci		return -1;
691d4afb5ceSopenharmony_ci	}
692d4afb5ceSopenharmony_ci
693d4afb5ceSopenharmony_ci	eckey[LDHS_OURS] = EVP_PKEY_get1_EC_KEY(
694d4afb5ceSopenharmony_ci				EVP_PKEY_CTX_get0_pkey(ctx->ctx[LDHS_OURS]));
695d4afb5ceSopenharmony_ci	eckey[LDHS_THEIRS] = EVP_PKEY_get1_EC_KEY(
696d4afb5ceSopenharmony_ci				EVP_PKEY_CTX_get0_pkey(ctx->ctx[LDHS_THEIRS]));
697d4afb5ceSopenharmony_ci
698d4afb5ceSopenharmony_ci	len = (EC_GROUP_get_degree(EC_KEY_get0_group(eckey[LDHS_OURS])) + 7) / 8;
699d4afb5ceSopenharmony_ci	if (len <= *ss_len) {
700d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL)
701d4afb5ceSopenharmony_ci		*ss_len = wolfSSL_ECDH_compute_key(
702d4afb5ceSopenharmony_ci#else
703d4afb5ceSopenharmony_ci		*ss_len = ECDH_compute_key(
704d4afb5ceSopenharmony_ci#endif
705d4afb5ceSopenharmony_ci				ss, (unsigned int)len,
706d4afb5ceSopenharmony_ci				EC_KEY_get0_public_key(eckey[LDHS_THEIRS]),
707d4afb5ceSopenharmony_ci				eckey[LDHS_OURS], NULL);
708d4afb5ceSopenharmony_ci		ret = -(*ss_len < 0);
709d4afb5ceSopenharmony_ci	}
710d4afb5ceSopenharmony_ci
711d4afb5ceSopenharmony_ci	EC_KEY_free(eckey[LDHS_OURS]);
712d4afb5ceSopenharmony_ci	EC_KEY_free(eckey[LDHS_THEIRS]);
713d4afb5ceSopenharmony_ci
714d4afb5ceSopenharmony_ci	return ret;
715d4afb5ceSopenharmony_ci}
716