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