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