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