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