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-mbedtls.h"
29d4afb5ceSopenharmony_ci
30d4afb5ceSopenharmony_ci#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
31d4afb5ceSopenharmony_ci#define ECDHCTX(_c, _ins) _c->u.ctx_ecdh->MBEDTLS_PRIVATE(ctx).\
32d4afb5ceSopenharmony_ci			MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(_ins)
33d4afb5ceSopenharmony_ci#define ECDSACTX(_c, _ins) _c->u.ctx_ecdsa->MBEDTLS_PRIVATE(_ins)
34d4afb5ceSopenharmony_ci#else
35d4afb5ceSopenharmony_ci#define ECDHCTX(_c, _ins) _c->u.ctx_ecdh->_ins
36d4afb5ceSopenharmony_ci#define ECDSACTX(_c, _ins) _c->u.ctx_ecdsa->_ins
37d4afb5ceSopenharmony_ci#endif
38d4afb5ceSopenharmony_ci
39d4afb5ceSopenharmony_ciconst struct lws_ec_curves lws_ec_curves[] = {
40d4afb5ceSopenharmony_ci	/*
41d4afb5ceSopenharmony_ci	 * These are the curves we are willing to use by default...
42d4afb5ceSopenharmony_ci	 *
43d4afb5ceSopenharmony_ci	 * The 3 recommended+ (P-256) and optional curves in RFC7518 7.6
44d4afb5ceSopenharmony_ci	 *
45d4afb5ceSopenharmony_ci	 * Specific keys lengths from RFC8422 p20
46d4afb5ceSopenharmony_ci	 */
47d4afb5ceSopenharmony_ci	{ "P-256", MBEDTLS_ECP_DP_SECP256R1, 32 },
48d4afb5ceSopenharmony_ci	{ "P-384", MBEDTLS_ECP_DP_SECP384R1, 48 },
49d4afb5ceSopenharmony_ci	{ "P-521", MBEDTLS_ECP_DP_SECP521R1, 66 },
50d4afb5ceSopenharmony_ci
51d4afb5ceSopenharmony_ci	{ NULL, 0, 0 }
52d4afb5ceSopenharmony_ci};
53d4afb5ceSopenharmony_ci
54d4afb5ceSopenharmony_cistatic int
55d4afb5ceSopenharmony_cilws_genec_keypair_import(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side,
56d4afb5ceSopenharmony_ci			 const struct lws_gencrypto_keyelem *el)
57d4afb5ceSopenharmony_ci{
58d4afb5ceSopenharmony_ci	const struct lws_ec_curves *curve;
59d4afb5ceSopenharmony_ci	mbedtls_ecp_keypair kp;
60d4afb5ceSopenharmony_ci	int ret = -1;
61d4afb5ceSopenharmony_ci
62d4afb5ceSopenharmony_ci	if (el[LWS_GENCRYPTO_EC_KEYEL_CRV].len < 4) {
63d4afb5ceSopenharmony_ci		lwsl_notice("%s: crv '%s' (%d)\n", __func__,
64d4afb5ceSopenharmony_ci			    el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf ?
65d4afb5ceSopenharmony_ci				    (char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf :
66d4afb5ceSopenharmony_ci					    "null",
67d4afb5ceSopenharmony_ci			    el[LWS_GENCRYPTO_EC_KEYEL_CRV].len);
68d4afb5ceSopenharmony_ci		return -21;
69d4afb5ceSopenharmony_ci	}
70d4afb5ceSopenharmony_ci
71d4afb5ceSopenharmony_ci	curve = lws_genec_curve(ctx->curve_table,
72d4afb5ceSopenharmony_ci				(char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf);
73d4afb5ceSopenharmony_ci	if (!curve)
74d4afb5ceSopenharmony_ci		return -22;
75d4afb5ceSopenharmony_ci
76d4afb5ceSopenharmony_ci	/*
77d4afb5ceSopenharmony_ci	 * d (the private part) may be missing, otherwise it and everything
78d4afb5ceSopenharmony_ci	 * else must match the expected bignum size
79d4afb5ceSopenharmony_ci	 */
80d4afb5ceSopenharmony_ci
81d4afb5ceSopenharmony_ci	if ((el[LWS_GENCRYPTO_EC_KEYEL_D].len &&
82d4afb5ceSopenharmony_ci	     el[LWS_GENCRYPTO_EC_KEYEL_D].len != curve->key_bytes) ||
83d4afb5ceSopenharmony_ci	    el[LWS_GENCRYPTO_EC_KEYEL_X].len != curve->key_bytes ||
84d4afb5ceSopenharmony_ci	    el[LWS_GENCRYPTO_EC_KEYEL_Y].len != curve->key_bytes)
85d4afb5ceSopenharmony_ci		return -23;
86d4afb5ceSopenharmony_ci
87d4afb5ceSopenharmony_ci	mbedtls_ecp_keypair_init(&kp);
88d4afb5ceSopenharmony_ci	if (mbedtls_ecp_group_load(&kp.MBEDTLS_PRIVATE(grp),
89d4afb5ceSopenharmony_ci				   (mbedtls_ecp_group_id)curve->tls_lib_nid))
90d4afb5ceSopenharmony_ci		goto bail1;
91d4afb5ceSopenharmony_ci
92d4afb5ceSopenharmony_ci	ctx->has_private = !!el[LWS_GENCRYPTO_EC_KEYEL_D].len;
93d4afb5ceSopenharmony_ci
94d4afb5ceSopenharmony_ci	/* d (the private key) is directly an mpi */
95d4afb5ceSopenharmony_ci
96d4afb5ceSopenharmony_ci	if (ctx->has_private &&
97d4afb5ceSopenharmony_ci	    mbedtls_mpi_read_binary(&kp.MBEDTLS_PRIVATE(d),
98d4afb5ceSopenharmony_ci				    el[LWS_GENCRYPTO_EC_KEYEL_D].buf,
99d4afb5ceSopenharmony_ci				    el[LWS_GENCRYPTO_EC_KEYEL_D].len))
100d4afb5ceSopenharmony_ci		goto bail1;
101d4afb5ceSopenharmony_ci
102d4afb5ceSopenharmony_ci	mbedtls_ecp_set_zero(&kp.MBEDTLS_PRIVATE(Q));
103d4afb5ceSopenharmony_ci
104d4afb5ceSopenharmony_ci	if (mbedtls_mpi_read_binary(&kp.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X),
105d4afb5ceSopenharmony_ci				    el[LWS_GENCRYPTO_EC_KEYEL_X].buf,
106d4afb5ceSopenharmony_ci				    el[LWS_GENCRYPTO_EC_KEYEL_X].len))
107d4afb5ceSopenharmony_ci		goto bail1;
108d4afb5ceSopenharmony_ci
109d4afb5ceSopenharmony_ci	if (mbedtls_mpi_read_binary(&kp.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y),
110d4afb5ceSopenharmony_ci				    el[LWS_GENCRYPTO_EC_KEYEL_Y].buf,
111d4afb5ceSopenharmony_ci				    el[LWS_GENCRYPTO_EC_KEYEL_Y].len))
112d4afb5ceSopenharmony_ci		goto bail1;
113d4afb5ceSopenharmony_ci
114d4afb5ceSopenharmony_ci	mbedtls_mpi_lset(&kp.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1);
115d4afb5ceSopenharmony_ci
116d4afb5ceSopenharmony_ci	switch (ctx->genec_alg) {
117d4afb5ceSopenharmony_ci	case LEGENEC_ECDH:
118d4afb5ceSopenharmony_ci		if (mbedtls_ecdh_get_params(ctx->u.ctx_ecdh, &kp,
119d4afb5ceSopenharmony_ci					    (mbedtls_ecdh_side)side))
120d4afb5ceSopenharmony_ci			goto bail1;
121d4afb5ceSopenharmony_ci		/* verify the key is consistent with the claimed curve */
122d4afb5ceSopenharmony_ci		if (ctx->has_private &&
123d4afb5ceSopenharmony_ci		    mbedtls_ecp_check_privkey(&ECDHCTX(ctx, grp),
124d4afb5ceSopenharmony_ci					      &ECDHCTX(ctx, d)))
125d4afb5ceSopenharmony_ci			goto bail1;
126d4afb5ceSopenharmony_ci		if (mbedtls_ecp_check_pubkey(&ECDHCTX(ctx, grp),
127d4afb5ceSopenharmony_ci					     &ECDHCTX(ctx, Q)))
128d4afb5ceSopenharmony_ci			goto bail1;
129d4afb5ceSopenharmony_ci		break;
130d4afb5ceSopenharmony_ci	case LEGENEC_ECDSA:
131d4afb5ceSopenharmony_ci		if (mbedtls_ecdsa_from_keypair(ctx->u.ctx_ecdsa, &kp))
132d4afb5ceSopenharmony_ci			goto bail1;
133d4afb5ceSopenharmony_ci		/* verify the key is consistent with the claimed curve */
134d4afb5ceSopenharmony_ci		if (ctx->has_private &&
135d4afb5ceSopenharmony_ci		    mbedtls_ecp_check_privkey(&ECDSACTX(ctx, grp),
136d4afb5ceSopenharmony_ci					      &ECDSACTX(ctx, d)))
137d4afb5ceSopenharmony_ci			goto bail1;
138d4afb5ceSopenharmony_ci		if (mbedtls_ecp_check_pubkey(&ECDSACTX(ctx, grp),
139d4afb5ceSopenharmony_ci					     &ECDSACTX(ctx, Q)))
140d4afb5ceSopenharmony_ci			goto bail1;
141d4afb5ceSopenharmony_ci		break;
142d4afb5ceSopenharmony_ci	default:
143d4afb5ceSopenharmony_ci		goto bail1;
144d4afb5ceSopenharmony_ci	}
145d4afb5ceSopenharmony_ci
146d4afb5ceSopenharmony_ci	ret = 0;
147d4afb5ceSopenharmony_ci
148d4afb5ceSopenharmony_cibail1:
149d4afb5ceSopenharmony_ci	mbedtls_ecp_keypair_free(&kp);
150d4afb5ceSopenharmony_ci
151d4afb5ceSopenharmony_ci	return ret;
152d4afb5ceSopenharmony_ci}
153d4afb5ceSopenharmony_ci
154d4afb5ceSopenharmony_ciint
155d4afb5ceSopenharmony_cilws_genecdh_create(struct lws_genec_ctx *ctx, struct lws_context *context,
156d4afb5ceSopenharmony_ci		   const struct lws_ec_curves *curve_table)
157d4afb5ceSopenharmony_ci{
158d4afb5ceSopenharmony_ci	memset(ctx, 0, sizeof(*ctx));
159d4afb5ceSopenharmony_ci
160d4afb5ceSopenharmony_ci	ctx->context = context;
161d4afb5ceSopenharmony_ci	ctx->curve_table = curve_table;
162d4afb5ceSopenharmony_ci	ctx->genec_alg = LEGENEC_ECDH;
163d4afb5ceSopenharmony_ci
164d4afb5ceSopenharmony_ci	ctx->u.ctx_ecdh = lws_zalloc(sizeof(*ctx->u.ctx_ecdh), "genecdh");
165d4afb5ceSopenharmony_ci	if (!ctx->u.ctx_ecdh)
166d4afb5ceSopenharmony_ci		return 1;
167d4afb5ceSopenharmony_ci
168d4afb5ceSopenharmony_ci	mbedtls_ecdh_init(ctx->u.ctx_ecdh);
169d4afb5ceSopenharmony_ci
170d4afb5ceSopenharmony_ci	return 0;
171d4afb5ceSopenharmony_ci}
172d4afb5ceSopenharmony_ci
173d4afb5ceSopenharmony_ciint
174d4afb5ceSopenharmony_cilws_genecdsa_create(struct lws_genec_ctx *ctx, struct lws_context *context,
175d4afb5ceSopenharmony_ci		    const struct lws_ec_curves *curve_table)
176d4afb5ceSopenharmony_ci{
177d4afb5ceSopenharmony_ci	memset(ctx, 0, sizeof(*ctx));
178d4afb5ceSopenharmony_ci
179d4afb5ceSopenharmony_ci	ctx->context = context;
180d4afb5ceSopenharmony_ci	ctx->curve_table = curve_table;
181d4afb5ceSopenharmony_ci	ctx->genec_alg = LEGENEC_ECDSA;
182d4afb5ceSopenharmony_ci
183d4afb5ceSopenharmony_ci	ctx->u.ctx_ecdsa = lws_zalloc(sizeof(*ctx->u.ctx_ecdsa), "genecdsa");
184d4afb5ceSopenharmony_ci	if (!ctx->u.ctx_ecdsa)
185d4afb5ceSopenharmony_ci		return 1;
186d4afb5ceSopenharmony_ci
187d4afb5ceSopenharmony_ci	mbedtls_ecdsa_init(ctx->u.ctx_ecdsa);
188d4afb5ceSopenharmony_ci
189d4afb5ceSopenharmony_ci	return 0;
190d4afb5ceSopenharmony_ci}
191d4afb5ceSopenharmony_ci
192d4afb5ceSopenharmony_ci
193d4afb5ceSopenharmony_ciint
194d4afb5ceSopenharmony_cilws_genecdh_set_key(struct lws_genec_ctx *ctx, struct lws_gencrypto_keyelem *el,
195d4afb5ceSopenharmony_ci		    enum enum_lws_dh_side side)
196d4afb5ceSopenharmony_ci{
197d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDH)
198d4afb5ceSopenharmony_ci		return -1;
199d4afb5ceSopenharmony_ci
200d4afb5ceSopenharmony_ci	return lws_genec_keypair_import(ctx, side, el);
201d4afb5ceSopenharmony_ci}
202d4afb5ceSopenharmony_ci
203d4afb5ceSopenharmony_ciint
204d4afb5ceSopenharmony_cilws_genecdsa_set_key(struct lws_genec_ctx *ctx,
205d4afb5ceSopenharmony_ci		     const struct lws_gencrypto_keyelem *el)
206d4afb5ceSopenharmony_ci{
207d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDSA)
208d4afb5ceSopenharmony_ci		return -1;
209d4afb5ceSopenharmony_ci
210d4afb5ceSopenharmony_ci	return lws_genec_keypair_import(ctx, 0, el);
211d4afb5ceSopenharmony_ci}
212d4afb5ceSopenharmony_ci
213d4afb5ceSopenharmony_civoid
214d4afb5ceSopenharmony_cilws_genec_destroy(struct lws_genec_ctx *ctx)
215d4afb5ceSopenharmony_ci{
216d4afb5ceSopenharmony_ci	switch (ctx->genec_alg) {
217d4afb5ceSopenharmony_ci	case LEGENEC_ECDH:
218d4afb5ceSopenharmony_ci		if (ctx->u.ctx_ecdh) {
219d4afb5ceSopenharmony_ci			mbedtls_ecdh_free(ctx->u.ctx_ecdh);
220d4afb5ceSopenharmony_ci			lws_free(ctx->u.ctx_ecdh);
221d4afb5ceSopenharmony_ci			ctx->u.ctx_ecdh = NULL;
222d4afb5ceSopenharmony_ci		}
223d4afb5ceSopenharmony_ci		break;
224d4afb5ceSopenharmony_ci	case LEGENEC_ECDSA:
225d4afb5ceSopenharmony_ci		if (ctx->u.ctx_ecdsa) {
226d4afb5ceSopenharmony_ci			mbedtls_ecdsa_free(ctx->u.ctx_ecdsa);
227d4afb5ceSopenharmony_ci			lws_free(ctx->u.ctx_ecdsa);
228d4afb5ceSopenharmony_ci			ctx->u.ctx_ecdsa = NULL;
229d4afb5ceSopenharmony_ci		}
230d4afb5ceSopenharmony_ci		break;
231d4afb5ceSopenharmony_ci	default:
232d4afb5ceSopenharmony_ci		break;
233d4afb5ceSopenharmony_ci	}
234d4afb5ceSopenharmony_ci}
235d4afb5ceSopenharmony_ci
236d4afb5ceSopenharmony_ciint
237d4afb5ceSopenharmony_cilws_genecdh_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side,
238d4afb5ceSopenharmony_ci			const char *curve_name,
239d4afb5ceSopenharmony_ci			struct lws_gencrypto_keyelem *el)
240d4afb5ceSopenharmony_ci{
241d4afb5ceSopenharmony_ci	const struct lws_ec_curves *curve;
242d4afb5ceSopenharmony_ci	mbedtls_ecdsa_context ecdsa;
243d4afb5ceSopenharmony_ci	mbedtls_ecp_keypair *kp;
244d4afb5ceSopenharmony_ci	mbedtls_mpi *mpi[3];
245d4afb5ceSopenharmony_ci	int n;
246d4afb5ceSopenharmony_ci
247d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDH)
248d4afb5ceSopenharmony_ci		return -1;
249d4afb5ceSopenharmony_ci
250d4afb5ceSopenharmony_ci	curve = lws_genec_curve(ctx->curve_table, curve_name);
251d4afb5ceSopenharmony_ci	if (!curve) {
252d4afb5ceSopenharmony_ci		lwsl_err("%s: curve '%s' not supported\n",
253d4afb5ceSopenharmony_ci			 __func__, curve_name);
254d4afb5ceSopenharmony_ci
255d4afb5ceSopenharmony_ci		return -22;
256d4afb5ceSopenharmony_ci	}
257d4afb5ceSopenharmony_ci
258d4afb5ceSopenharmony_ci	mbedtls_ecdsa_init(&ecdsa);
259d4afb5ceSopenharmony_ci	n = mbedtls_ecdsa_genkey(&ecdsa, (mbedtls_ecp_group_id)curve->tls_lib_nid,
260d4afb5ceSopenharmony_ci				 lws_gencrypto_mbedtls_rngf,
261d4afb5ceSopenharmony_ci				 ctx->context);
262d4afb5ceSopenharmony_ci	if (n) {
263d4afb5ceSopenharmony_ci		lwsl_err("mbedtls_ecdsa_genkey failed 0x%x\n", -n);
264d4afb5ceSopenharmony_ci		goto bail1;
265d4afb5ceSopenharmony_ci	}
266d4afb5ceSopenharmony_ci
267d4afb5ceSopenharmony_ci	kp = (mbedtls_ecp_keypair *)&ecdsa;
268d4afb5ceSopenharmony_ci
269d4afb5ceSopenharmony_ci	n = mbedtls_ecdh_get_params(ctx->u.ctx_ecdh, kp,
270d4afb5ceSopenharmony_ci				    (mbedtls_ecdh_side)side);
271d4afb5ceSopenharmony_ci	if (n) {
272d4afb5ceSopenharmony_ci		lwsl_err("mbedtls_ecdh_get_params failed 0x%x\n", -n);
273d4afb5ceSopenharmony_ci		goto bail1;
274d4afb5ceSopenharmony_ci	}
275d4afb5ceSopenharmony_ci
276d4afb5ceSopenharmony_ci	/*
277d4afb5ceSopenharmony_ci	 * we need to capture the individual element BIGNUMs into
278d4afb5ceSopenharmony_ci	 * lws_gencrypto_keyelem, so they can be serialized, used in jwk etc
279d4afb5ceSopenharmony_ci	 */
280d4afb5ceSopenharmony_ci
281d4afb5ceSopenharmony_ci	mpi[0] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X);
282d4afb5ceSopenharmony_ci	mpi[1] = &kp->MBEDTLS_PRIVATE(d);
283d4afb5ceSopenharmony_ci	mpi[2] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y);
284d4afb5ceSopenharmony_ci
285d4afb5ceSopenharmony_ci	el[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve_name) + 1;
286d4afb5ceSopenharmony_ci	el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf =
287d4afb5ceSopenharmony_ci			lws_malloc(el[LWS_GENCRYPTO_EC_KEYEL_CRV].len, "ec");
288d4afb5ceSopenharmony_ci	if (!el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf)
289d4afb5ceSopenharmony_ci		goto bail1;
290d4afb5ceSopenharmony_ci	strcpy((char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf, curve_name);
291d4afb5ceSopenharmony_ci
292d4afb5ceSopenharmony_ci	for (n = LWS_GENCRYPTO_EC_KEYEL_X; n < LWS_GENCRYPTO_EC_KEYEL_COUNT;
293d4afb5ceSopenharmony_ci	     n++) {
294d4afb5ceSopenharmony_ci		el[n].len = curve->key_bytes;
295d4afb5ceSopenharmony_ci		el[n].buf = lws_malloc(curve->key_bytes, "ec");
296d4afb5ceSopenharmony_ci		if (!el[n].buf)
297d4afb5ceSopenharmony_ci			goto bail2;
298d4afb5ceSopenharmony_ci
299d4afb5ceSopenharmony_ci		if (mbedtls_mpi_write_binary(mpi[n - 1], el[n].buf,
300d4afb5ceSopenharmony_ci					     curve->key_bytes))
301d4afb5ceSopenharmony_ci			goto bail2;
302d4afb5ceSopenharmony_ci	}
303d4afb5ceSopenharmony_ci
304d4afb5ceSopenharmony_ci	mbedtls_ecdsa_free(&ecdsa);
305d4afb5ceSopenharmony_ci
306d4afb5ceSopenharmony_ci	return 0;
307d4afb5ceSopenharmony_ci
308d4afb5ceSopenharmony_cibail2:
309d4afb5ceSopenharmony_ci	for (n = 0; n < LWS_GENCRYPTO_EC_KEYEL_COUNT; n++)
310d4afb5ceSopenharmony_ci		if (el[n].buf)
311d4afb5ceSopenharmony_ci			lws_free_set_NULL(el[n].buf);
312d4afb5ceSopenharmony_cibail1:
313d4afb5ceSopenharmony_ci	mbedtls_ecdsa_free(&ecdsa);
314d4afb5ceSopenharmony_ci
315d4afb5ceSopenharmony_ci	lws_free_set_NULL(ctx->u.ctx_ecdh);
316d4afb5ceSopenharmony_ci
317d4afb5ceSopenharmony_ci	return -1;
318d4afb5ceSopenharmony_ci}
319d4afb5ceSopenharmony_ci
320d4afb5ceSopenharmony_ciint
321d4afb5ceSopenharmony_cilws_genecdsa_new_keypair(struct lws_genec_ctx *ctx, const char *curve_name,
322d4afb5ceSopenharmony_ci			 struct lws_gencrypto_keyelem *el)
323d4afb5ceSopenharmony_ci{
324d4afb5ceSopenharmony_ci	const struct lws_ec_curves *curve;
325d4afb5ceSopenharmony_ci	mbedtls_ecp_keypair *kp;
326d4afb5ceSopenharmony_ci	mbedtls_mpi *mpi[3];
327d4afb5ceSopenharmony_ci	int n;
328d4afb5ceSopenharmony_ci
329d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDSA)
330d4afb5ceSopenharmony_ci		return -1;
331d4afb5ceSopenharmony_ci
332d4afb5ceSopenharmony_ci	curve = lws_genec_curve(ctx->curve_table, curve_name);
333d4afb5ceSopenharmony_ci	if (!curve) {
334d4afb5ceSopenharmony_ci		lwsl_err("%s: curve '%s' not supported\n",
335d4afb5ceSopenharmony_ci			 __func__, curve_name);
336d4afb5ceSopenharmony_ci
337d4afb5ceSopenharmony_ci		return -22;
338d4afb5ceSopenharmony_ci	}
339d4afb5ceSopenharmony_ci
340d4afb5ceSopenharmony_ci	//mbedtls_ecdsa_init(ctx->u.ctx_ecdsa);
341d4afb5ceSopenharmony_ci	n = mbedtls_ecdsa_genkey(ctx->u.ctx_ecdsa, (mbedtls_ecp_group_id)curve->tls_lib_nid,
342d4afb5ceSopenharmony_ci				 lws_gencrypto_mbedtls_rngf, ctx->context);
343d4afb5ceSopenharmony_ci	if (n) {
344d4afb5ceSopenharmony_ci		lwsl_err("mbedtls_ecdsa_genkey failed 0x%x\n", -n);
345d4afb5ceSopenharmony_ci		goto bail1;
346d4afb5ceSopenharmony_ci	}
347d4afb5ceSopenharmony_ci
348d4afb5ceSopenharmony_ci	/*
349d4afb5ceSopenharmony_ci	 * we need to capture the individual element BIGNUMs into
350d4afb5ceSopenharmony_ci	 * lws_gencrypto_keyelems, so they can be serialized, used in jwk etc
351d4afb5ceSopenharmony_ci	 */
352d4afb5ceSopenharmony_ci
353d4afb5ceSopenharmony_ci	kp = (mbedtls_ecp_keypair *)ctx->u.ctx_ecdsa;
354d4afb5ceSopenharmony_ci
355d4afb5ceSopenharmony_ci	mpi[0] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X);
356d4afb5ceSopenharmony_ci	mpi[1] = &kp->MBEDTLS_PRIVATE(d);
357d4afb5ceSopenharmony_ci	mpi[2] = &kp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y);
358d4afb5ceSopenharmony_ci
359d4afb5ceSopenharmony_ci	el[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve_name) + 1;
360d4afb5ceSopenharmony_ci	el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf =
361d4afb5ceSopenharmony_ci			lws_malloc(el[LWS_GENCRYPTO_EC_KEYEL_CRV].len, "ec");
362d4afb5ceSopenharmony_ci	if (!el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf)
363d4afb5ceSopenharmony_ci		goto bail1;
364d4afb5ceSopenharmony_ci	strcpy((char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf, curve_name);
365d4afb5ceSopenharmony_ci
366d4afb5ceSopenharmony_ci	for (n = LWS_GENCRYPTO_EC_KEYEL_X; n < LWS_GENCRYPTO_EC_KEYEL_COUNT;
367d4afb5ceSopenharmony_ci	     n++) {
368d4afb5ceSopenharmony_ci		el[n].len = curve->key_bytes;
369d4afb5ceSopenharmony_ci		el[n].buf = lws_malloc(curve->key_bytes, "ec");
370d4afb5ceSopenharmony_ci		if (!el[n].buf)
371d4afb5ceSopenharmony_ci			goto bail2;
372d4afb5ceSopenharmony_ci
373d4afb5ceSopenharmony_ci
374d4afb5ceSopenharmony_ci		if (mbedtls_mpi_write_binary(mpi[n - 1], el[n].buf, el[n].len)) {
375d4afb5ceSopenharmony_ci			lwsl_err("%s: mbedtls_mpi_write_binary failed\n", __func__);
376d4afb5ceSopenharmony_ci			goto bail2;
377d4afb5ceSopenharmony_ci		}
378d4afb5ceSopenharmony_ci	}
379d4afb5ceSopenharmony_ci
380d4afb5ceSopenharmony_ci	return 0;
381d4afb5ceSopenharmony_ci
382d4afb5ceSopenharmony_cibail2:
383d4afb5ceSopenharmony_ci	for (n = 0; n < LWS_GENCRYPTO_EC_KEYEL_COUNT; n++)
384d4afb5ceSopenharmony_ci		if (el[n].buf)
385d4afb5ceSopenharmony_ci			lws_free_set_NULL(el[n].buf);
386d4afb5ceSopenharmony_cibail1:
387d4afb5ceSopenharmony_ci
388d4afb5ceSopenharmony_ci	lws_free_set_NULL(ctx->u.ctx_ecdsa);
389d4afb5ceSopenharmony_ci
390d4afb5ceSopenharmony_ci	return -1;
391d4afb5ceSopenharmony_ci}
392d4afb5ceSopenharmony_ci
393d4afb5ceSopenharmony_ciint
394d4afb5ceSopenharmony_cilws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
395d4afb5ceSopenharmony_ci			   enum lws_genhash_types hash_type, int keybits,
396d4afb5ceSopenharmony_ci			   uint8_t *sig, size_t sig_len)
397d4afb5ceSopenharmony_ci{
398d4afb5ceSopenharmony_ci	int n, keybytes = lws_gencrypto_bits_to_bytes(keybits);
399d4afb5ceSopenharmony_ci	size_t hlen = lws_genhash_size(hash_type);
400d4afb5ceSopenharmony_ci	mbedtls_mpi mpi_r, mpi_s;
401d4afb5ceSopenharmony_ci	size_t slen = sig_len;
402d4afb5ceSopenharmony_ci
403d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDSA)
404d4afb5ceSopenharmony_ci		return -1;
405d4afb5ceSopenharmony_ci
406d4afb5ceSopenharmony_ci	/*
407d4afb5ceSopenharmony_ci	 * The ECDSA P-256 SHA-256 digital signature is generated as follows:
408d4afb5ceSopenharmony_ci	 *
409d4afb5ceSopenharmony_ci	 * 1.  Generate a digital signature of the JWS Signing Input using ECDSA
410d4afb5ceSopenharmony_ci	 *     P-256 SHA-256 with the desired private key.  The output will be
411d4afb5ceSopenharmony_ci	 *     the pair (R, S), where R and S are 256-bit unsigned integers.
412d4afb5ceSopenharmony_ci	 *
413d4afb5ceSopenharmony_ci	 * 2.  Turn R and S into octet sequences in big-endian order, with each
414d4afb5ceSopenharmony_ci	 *     array being be 32 octets long.  The octet sequence
415d4afb5ceSopenharmony_ci	 *     representations MUST NOT be shortened to omit any leading zero
416d4afb5ceSopenharmony_ci	 *     octets contained in the values.
417d4afb5ceSopenharmony_ci	 *
418d4afb5ceSopenharmony_ci	 * 3.  Concatenate the two octet sequences in the order R and then S.
419d4afb5ceSopenharmony_ci	 *     (Note that many ECDSA implementations will directly produce this
420d4afb5ceSopenharmony_ci	 *     concatenation as their output.)
421d4afb5ceSopenharmony_ci	 *
422d4afb5ceSopenharmony_ci	 * 4.  The resulting 64-octet sequence is the JWS Signature value.
423d4afb5ceSopenharmony_ci	 */
424d4afb5ceSopenharmony_ci
425d4afb5ceSopenharmony_ci	mbedtls_mpi_init(&mpi_r);
426d4afb5ceSopenharmony_ci	mbedtls_mpi_init(&mpi_s);
427d4afb5ceSopenharmony_ci
428d4afb5ceSopenharmony_ci	n = mbedtls_ecdsa_sign(&ECDSACTX(ctx, grp), &mpi_r, &mpi_s,
429d4afb5ceSopenharmony_ci			       &ECDSACTX(ctx, d), in, hlen,
430d4afb5ceSopenharmony_ci			lws_gencrypto_mbedtls_rngf, ctx->context);
431d4afb5ceSopenharmony_ci	if (n) {
432d4afb5ceSopenharmony_ci		lwsl_err("%s: mbedtls_ecdsa_sign failed: -0x%x\n",
433d4afb5ceSopenharmony_ci			 __func__, -n);
434d4afb5ceSopenharmony_ci
435d4afb5ceSopenharmony_ci		goto bail2;
436d4afb5ceSopenharmony_ci	}
437d4afb5ceSopenharmony_ci
438d4afb5ceSopenharmony_ci	if (mbedtls_mpi_write_binary(&mpi_r, sig, (unsigned int)keybytes))
439d4afb5ceSopenharmony_ci		goto bail2;
440d4afb5ceSopenharmony_ci	mbedtls_mpi_free(&mpi_r);
441d4afb5ceSopenharmony_ci	if (mbedtls_mpi_write_binary(&mpi_s, sig + keybytes, (unsigned int)keybytes))
442d4afb5ceSopenharmony_ci		goto bail1;
443d4afb5ceSopenharmony_ci	mbedtls_mpi_free(&mpi_s);
444d4afb5ceSopenharmony_ci
445d4afb5ceSopenharmony_ci	return (int)slen;
446d4afb5ceSopenharmony_ci
447d4afb5ceSopenharmony_cibail2:
448d4afb5ceSopenharmony_ci	mbedtls_mpi_free(&mpi_r);
449d4afb5ceSopenharmony_cibail1:
450d4afb5ceSopenharmony_ci	mbedtls_mpi_free(&mpi_s);
451d4afb5ceSopenharmony_ci
452d4afb5ceSopenharmony_ci	return -3;
453d4afb5ceSopenharmony_ci}
454d4afb5ceSopenharmony_ci
455d4afb5ceSopenharmony_ciint
456d4afb5ceSopenharmony_cilws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
457d4afb5ceSopenharmony_ci				 enum lws_genhash_types hash_type, int keybits,
458d4afb5ceSopenharmony_ci				 const uint8_t *sig, size_t sig_len)
459d4afb5ceSopenharmony_ci{
460d4afb5ceSopenharmony_ci	int n, keybytes = lws_gencrypto_bits_to_bytes(keybits);
461d4afb5ceSopenharmony_ci	size_t hlen = lws_genhash_size(hash_type);
462d4afb5ceSopenharmony_ci	mbedtls_mpi mpi_r, mpi_s;
463d4afb5ceSopenharmony_ci
464d4afb5ceSopenharmony_ci	if (ctx->genec_alg != LEGENEC_ECDSA)
465d4afb5ceSopenharmony_ci		return -1;
466d4afb5ceSopenharmony_ci
467d4afb5ceSopenharmony_ci	if ((int)sig_len != keybytes * 2)
468d4afb5ceSopenharmony_ci		return -1;
469d4afb5ceSopenharmony_ci
470d4afb5ceSopenharmony_ci	/*
471d4afb5ceSopenharmony_ci	 * 1.  The JWS Signature value MUST be a 64-octet sequence.  If it is
472d4afb5ceSopenharmony_ci	 *     not a 64-octet sequence, the validation has failed.
473d4afb5ceSopenharmony_ci	 *
474d4afb5ceSopenharmony_ci	 * 2.  Split the 64-octet sequence into two 32-octet sequences.  The
475d4afb5ceSopenharmony_ci	 *     first octet sequence represents R and the second S.  The values R
476d4afb5ceSopenharmony_ci	 *     and S are represented as octet sequences using the Integer-to-
477d4afb5ceSopenharmony_ci	 *     OctetString Conversion defined in Section 2.3.7 of SEC1 [SEC1]
478d4afb5ceSopenharmony_ci	 *     (in big-endian octet order).
479d4afb5ceSopenharmony_ci	 *
480d4afb5ceSopenharmony_ci	 * 3.  Submit the JWS Signing Input, R, S, and the public key (x, y) to
481d4afb5ceSopenharmony_ci	 *     the ECDSA P-256 SHA-256 validator.
482d4afb5ceSopenharmony_ci	 */
483d4afb5ceSopenharmony_ci
484d4afb5ceSopenharmony_ci	mbedtls_mpi_init(&mpi_r);
485d4afb5ceSopenharmony_ci	mbedtls_mpi_init(&mpi_s);
486d4afb5ceSopenharmony_ci
487d4afb5ceSopenharmony_ci	if (mbedtls_mpi_read_binary(&mpi_r, sig, (unsigned int)keybytes))
488d4afb5ceSopenharmony_ci		return -1;
489d4afb5ceSopenharmony_ci	if (mbedtls_mpi_read_binary(&mpi_s, sig + keybytes, (unsigned int)keybytes))
490d4afb5ceSopenharmony_ci		goto bail1;
491d4afb5ceSopenharmony_ci
492d4afb5ceSopenharmony_ci	n = mbedtls_ecdsa_verify(&ECDSACTX(ctx, grp), in, hlen,
493d4afb5ceSopenharmony_ci				 &ECDSACTX(ctx, Q), &mpi_r, &mpi_s);
494d4afb5ceSopenharmony_ci
495d4afb5ceSopenharmony_ci	mbedtls_mpi_free(&mpi_s);
496d4afb5ceSopenharmony_ci	mbedtls_mpi_free(&mpi_r);
497d4afb5ceSopenharmony_ci
498d4afb5ceSopenharmony_ci	if (n) {
499d4afb5ceSopenharmony_ci		lwsl_err("%s: mbedtls_ecdsa_verify failed: -0x%x\n",
500d4afb5ceSopenharmony_ci			 __func__, -n);
501d4afb5ceSopenharmony_ci
502d4afb5ceSopenharmony_ci		goto bail;
503d4afb5ceSopenharmony_ci	}
504d4afb5ceSopenharmony_ci
505d4afb5ceSopenharmony_ci	return 0;
506d4afb5ceSopenharmony_cibail1:
507d4afb5ceSopenharmony_ci	mbedtls_mpi_free(&mpi_r);
508d4afb5ceSopenharmony_ci
509d4afb5ceSopenharmony_cibail:
510d4afb5ceSopenharmony_ci
511d4afb5ceSopenharmony_ci	return -3;
512d4afb5ceSopenharmony_ci}
513d4afb5ceSopenharmony_ci
514d4afb5ceSopenharmony_ciint
515d4afb5ceSopenharmony_cilws_genecdh_compute_shared_secret(struct lws_genec_ctx *ctx, uint8_t *ss,
516d4afb5ceSopenharmony_ci				  int *ss_len)
517d4afb5ceSopenharmony_ci{
518d4afb5ceSopenharmony_ci	int n;
519d4afb5ceSopenharmony_ci	size_t st;
520d4afb5ceSopenharmony_ci	if (mbedtls_ecp_check_pubkey(&ECDHCTX(ctx, grp), &ECDHCTX(ctx, Q)) ||
521d4afb5ceSopenharmony_ci	    mbedtls_ecp_check_pubkey(&ECDHCTX(ctx, grp), &ECDHCTX(ctx, Qp))) {
522d4afb5ceSopenharmony_ci		lwsl_err("%s: both sides must be set up\n", __func__);
523d4afb5ceSopenharmony_ci
524d4afb5ceSopenharmony_ci		return -1;
525d4afb5ceSopenharmony_ci	}
526d4afb5ceSopenharmony_ci
527d4afb5ceSopenharmony_ci	n = mbedtls_ecdh_calc_secret(ctx->u.ctx_ecdh, &st, ss, (size_t)*ss_len,
528d4afb5ceSopenharmony_ci			lws_gencrypto_mbedtls_rngf, ctx->context);
529d4afb5ceSopenharmony_ci	if (n)
530d4afb5ceSopenharmony_ci		return -1;
531d4afb5ceSopenharmony_ci
532d4afb5ceSopenharmony_ci	*ss_len = (int)st;
533d4afb5ceSopenharmony_ci
534d4afb5ceSopenharmony_ci	return 0;
535d4afb5ceSopenharmony_ci}
536