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
39const 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
54static int
55lws_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
148bail1:
149	mbedtls_ecp_keypair_free(&kp);
150
151	return ret;
152}
153
154int
155lws_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
173int
174lws_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
193int
194lws_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
203int
204lws_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
213void
214lws_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
236int
237lws_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
308bail2:
309	for (n = 0; n < LWS_GENCRYPTO_EC_KEYEL_COUNT; n++)
310		if (el[n].buf)
311			lws_free_set_NULL(el[n].buf);
312bail1:
313	mbedtls_ecdsa_free(&ecdsa);
314
315	lws_free_set_NULL(ctx->u.ctx_ecdh);
316
317	return -1;
318}
319
320int
321lws_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
382bail2:
383	for (n = 0; n < LWS_GENCRYPTO_EC_KEYEL_COUNT; n++)
384		if (el[n].buf)
385			lws_free_set_NULL(el[n].buf);
386bail1:
387
388	lws_free_set_NULL(ctx->u.ctx_ecdsa);
389
390	return -1;
391}
392
393int
394lws_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
447bail2:
448	mbedtls_mpi_free(&mpi_r);
449bail1:
450	mbedtls_mpi_free(&mpi_s);
451
452	return -3;
453}
454
455int
456lws_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;
506bail1:
507	mbedtls_mpi_free(&mpi_r);
508
509bail:
510
511	return -3;
512}
513
514int
515lws_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