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
25 #include "private-lib-core.h"
26 #include "private-lib-jose.h"
27
28 #if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_DEV_KIT)
29 #include <fcntl.h>
30 #endif
31
32 static const char * const kty_names[] = {
33 "unknown", /* LWS_GENCRYPTO_KTY_UNKNOWN */
34 "oct", /* LWS_GENCRYPTO_KTY_OCT */
35 "RSA", /* LWS_GENCRYPTO_KTY_RSA */
36 "EC" /* LWS_GENCRYPTO_KTY_EC */
37 };
38
39 /*
40 * These are the entire legal token set for names in jwk.
41 *
42 * The first version is used to parse a detached single jwk that don't have any
43 * parent JSON context. The second version is used to parse full jwk objects
44 * that has a "keys": [ ] array containing the keys.
45 */
46
47 static const char * const jwk_tok[] = {
48 "keys[]", /* dummy */
49 "e", "n", "d", "p", "q", "dp", "dq", "qi", /* RSA */
50 "kty", /* generic */
51 "k", /* symmetric key data */
52 "crv", "x", "y", /* EC (also "D") */
53 "kid", /* generic */
54 "use" /* mutually exclusive with "key_ops" */,
55 "key_ops" /* mutually exclusive with "use" */,
56 "x5c", /* generic */
57 "alg" /* generic */
58 }, * const jwk_outer_tok[] = {
59 "keys[]",
60 "keys[].e", "keys[].n", "keys[].d", "keys[].p", "keys[].q", "keys[].dp",
61 "keys[].dq", "keys[].qi",
62
63 "keys[].kty", "keys[].k", /* generic */
64 "keys[].crv", "keys[].x", "keys[].y", /* EC (also "D") */
65 "keys[].kid", "keys[].use" /* mutually exclusive with "key_ops" */,
66 "keys[].key_ops", /* mutually exclusive with "use" */
67 "keys[].x5c", "keys[].alg"
68 };
69
70 /* information about each token declared above */
71
72 #define F_M (1 << 9) /* Mandatory for key type */
73 #define F_B64 (1 << 10) /* Base64 coded octets */
74 #define F_B64U (1 << 11) /* Base64 Url coded octets */
75 #define F_META (1 << 12) /* JWK key metainformation */
76 #define F_RSA (1 << 13) /* RSA key */
77 #define F_EC (1 << 14) /* Elliptic curve key */
78 #define F_OCT (1 << 15) /* octet key */
79
80 static unsigned short tok_map[] = {
81 F_RSA | F_EC | F_OCT | F_META | 0xff,
82 F_RSA | F_B64U | F_M | LWS_GENCRYPTO_RSA_KEYEL_E,
83 F_RSA | F_B64U | F_M | LWS_GENCRYPTO_RSA_KEYEL_N,
84 F_RSA | F_EC | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_D,
85 F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_P,
86 F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_Q,
87 F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_DP,
88 F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_DQ,
89 F_RSA | F_B64U | LWS_GENCRYPTO_RSA_KEYEL_QI,
90
91 F_RSA | F_EC | F_OCT | F_META | F_M | JWK_META_KTY,
92 F_OCT | F_B64U | F_M | LWS_GENCRYPTO_OCT_KEYEL_K,
93
94 F_EC | F_M | LWS_GENCRYPTO_EC_KEYEL_CRV,
95 F_EC | F_B64U | F_M | LWS_GENCRYPTO_EC_KEYEL_X,
96 F_EC | F_B64U | F_M | LWS_GENCRYPTO_EC_KEYEL_Y,
97
98 F_RSA | F_EC | F_OCT | F_META | JWK_META_KID,
99 F_RSA | F_EC | F_OCT | F_META | JWK_META_USE,
100
101 F_RSA | F_EC | F_OCT | F_META | JWK_META_KEY_OPS,
102 F_RSA | F_EC | F_OCT | F_META | F_B64 | JWK_META_X5C,
103 F_RSA | F_EC | F_OCT | F_META | JWK_META_ALG,
104 };
105
106 static const char *meta_names[] = {
107 "kty", "kid", "use", "key_ops", "x5c", "alg"
108 };
109
110 struct lexico {
111 const char *name;
112 int idx;
113 char meta;
114 } lexico_ec[] = {
115 { "alg", JWK_META_ALG, 1 },
116 { "crv", LWS_GENCRYPTO_EC_KEYEL_CRV, 0 },
117 { "d", LWS_GENCRYPTO_EC_KEYEL_D, 2 | 0 },
118 { "key_ops", JWK_META_KEY_OPS, 1 },
119 { "kid", JWK_META_KID, 1 },
120 { "kty", JWK_META_KTY, 1 },
121 { "use", JWK_META_USE, 1 },
122 { "x", LWS_GENCRYPTO_EC_KEYEL_X, 0 },
123 { "x5c", JWK_META_X5C, 1 },
124 { "y", LWS_GENCRYPTO_EC_KEYEL_Y, 0 }
125 }, lexico_oct[] = {
126 { "alg", JWK_META_ALG, 1 },
127 { "k", LWS_GENCRYPTO_OCT_KEYEL_K, 0 },
128 { "key_ops", JWK_META_KEY_OPS, 1 },
129 { "kid", JWK_META_KID, 1 },
130 { "kty", JWK_META_KTY, 1 },
131 { "use", JWK_META_USE, 1 },
132 { "x5c", JWK_META_X5C, 1 }
133 }, lexico_rsa[] = {
134 { "alg", JWK_META_ALG, 1 },
135 { "d", LWS_GENCRYPTO_RSA_KEYEL_D, 2 | 0 },
136 { "dp", LWS_GENCRYPTO_RSA_KEYEL_DP, 2 | 0 },
137 { "dq", LWS_GENCRYPTO_RSA_KEYEL_DQ, 2 | 0 },
138 { "e", LWS_GENCRYPTO_RSA_KEYEL_E, 0 },
139 { "key_ops", JWK_META_KEY_OPS, 1 },
140 { "kid", JWK_META_KID, 1 },
141 { "kty", JWK_META_KTY, 1 },
142 { "n", LWS_GENCRYPTO_RSA_KEYEL_N, 0 },
143 { "p", LWS_GENCRYPTO_RSA_KEYEL_P, 2 | 0 },
144 { "q", LWS_GENCRYPTO_RSA_KEYEL_Q, 2 | 0 },
145 { "qi", LWS_GENCRYPTO_RSA_KEYEL_QI, 2 | 0 },
146 { "use", JWK_META_USE, 1 },
147 { "x5c", JWK_META_X5C, 1 }
148 };
149
150 static const char meta_b64[] = { 0, 0, 0, 0, 1, 0 };
151
152 static const char *oct_names[] = {
153 "k"
154 };
155 static const char oct_b64[] = { 1 };
156
157 static const char *rsa_names[] = {
158 "e", "n", "d", "p", "q", "dp", "dq", "qi"
159 };
160 static const char rsa_b64[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
161
162 static const char *ec_names[] = {
163 "crv", "x", "d", "y",
164 };
165 static const char ec_b64[] = { 0, 1, 1, 1 };
166
167 int
lws_jwk_dump(struct lws_jwk * jwk)168 lws_jwk_dump(struct lws_jwk *jwk)
169 {
170 const char **enames, *b64;
171 int elems;
172 int n;
173
174 (void)enames;
175 (void)meta_names;
176
177 switch (jwk->kty) {
178 default:
179 case LWS_GENCRYPTO_KTY_UNKNOWN:
180 lwsl_err("%s: jwk %p: unknown type\n", __func__, jwk);
181
182 return 1;
183 case LWS_GENCRYPTO_KTY_OCT:
184 elems = LWS_GENCRYPTO_OCT_KEYEL_COUNT;
185 enames = oct_names;
186 b64 = oct_b64;
187 break;
188 case LWS_GENCRYPTO_KTY_RSA:
189 elems = LWS_GENCRYPTO_RSA_KEYEL_COUNT;
190 enames = rsa_names;
191 b64 = rsa_b64;
192 break;
193 case LWS_GENCRYPTO_KTY_EC:
194 elems = LWS_GENCRYPTO_EC_KEYEL_COUNT;
195 enames = ec_names;
196 b64 = ec_b64;
197 break;
198 }
199
200 lwsl_info("%s: jwk %p\n", __func__, jwk);
201
202 for (n = 0; n < LWS_COUNT_JWK_ELEMENTS; n++) {
203 if (jwk->meta[n].buf && meta_b64[n]) {
204 lwsl_info(" meta: %s\n", meta_names[n]);
205 lwsl_hexdump_info(jwk->meta[n].buf, jwk->meta[n].len);
206 }
207 if (jwk->meta[n].buf && !meta_b64[n])
208 lwsl_info(" meta: %s: '%s'\n", meta_names[n],
209 jwk->meta[n].buf);
210 }
211
212 for (n = 0; n < elems; n++) {
213 if (jwk->e[n].buf && b64[n]) {
214 lwsl_info(" e: %s\n", enames[n]);
215 lwsl_hexdump_info(jwk->e[n].buf, jwk->e[n].len);
216 }
217 if (jwk->e[n].buf && !b64[n])
218 lwsl_info(" e: %s: '%s'\n", enames[n], jwk->e[n].buf);
219 }
220
221 return 0;
222 }
223
224 static int
_lws_jwk_set_el_jwk(struct lws_gencrypto_keyelem * e,char * in,size_t len)225 _lws_jwk_set_el_jwk(struct lws_gencrypto_keyelem *e, char *in, size_t len)
226 {
227 e->buf = lws_malloc(len + 1, "jwk");
228 if (!e->buf)
229 return -1;
230
231 memcpy(e->buf, in, len);
232 e->buf[len] = '\0';
233 e->len = (uint32_t)len;
234
235 return 0;
236 }
237
238 static int
_lws_jwk_set_el_jwk_b64(struct lws_gencrypto_keyelem * e,char * in,int len)239 _lws_jwk_set_el_jwk_b64(struct lws_gencrypto_keyelem *e, char *in, int len)
240 {
241 size_t dec_size = (unsigned int)lws_base64_size(len);
242 int n;
243
244 e->buf = lws_malloc(dec_size, "jwk");
245 if (!e->buf)
246 return -1;
247
248 /* same decoder accepts both url or original styles */
249
250 n = lws_b64_decode_string_len(in, len, (char *)e->buf, (int)dec_size - 1);
251 if (n < 0)
252 return -1;
253 e->len = (uint32_t)n;
254
255 return 0;
256 }
257
258 static int
_lws_jwk_set_el_jwk_b64u(struct lws_gencrypto_keyelem * e,char * in,int len)259 _lws_jwk_set_el_jwk_b64u(struct lws_gencrypto_keyelem *e, char *in, int len)
260 {
261 size_t dec_size = (size_t)lws_base64_size(len);
262 int n;
263
264 e->buf = lws_malloc(dec_size, "jwk");
265 if (!e->buf)
266 return -1;
267
268 /* same decoder accepts both url or original styles */
269
270 n = lws_b64_decode_string_len(in, len, (char *)e->buf, (int)dec_size - 1);
271 if (n < 0)
272 return -1;
273 e->len = (uint32_t)n;
274
275 return 0;
276 }
277
278 void
lws_jwk_destroy_elements(struct lws_gencrypto_keyelem * el,int m)279 lws_jwk_destroy_elements(struct lws_gencrypto_keyelem *el, int m)
280 {
281 int n;
282
283 for (n = 0; n < m; n++)
284 if (el[n].buf) {
285 /* wipe all key material when it goes out of scope */
286 lws_explicit_bzero(el[n].buf, el[n].len);
287 lws_free_set_NULL(el[n].buf);
288 el[n].len = 0;
289 }
290 }
291
292 void
lws_jwk_destroy(struct lws_jwk * jwk)293 lws_jwk_destroy(struct lws_jwk *jwk)
294 {
295 lws_jwk_destroy_elements(jwk->e, LWS_ARRAY_SIZE(jwk->e));
296 lws_jwk_destroy_elements(jwk->meta, LWS_ARRAY_SIZE(jwk->meta));
297 }
298
299 static signed char
cb_jwk(struct lejp_ctx * ctx,char reason)300 cb_jwk(struct lejp_ctx *ctx, char reason)
301 {
302 struct lws_jwk_parse_state *jps = (struct lws_jwk_parse_state *)ctx->user;
303 struct lws_jwk *jwk = jps->jwk;
304 unsigned int idx, n;
305 unsigned short poss;
306 char dotstar[64];
307
308 if (reason == LEJPCB_VAL_STR_START)
309 jps->pos = 0;
310
311 if (reason == LEJPCB_OBJECT_START && ctx->path_match == 0 + 1)
312 /*
313 * new keys[] member is starting
314 *
315 * Until we see some JSON names, it could be anything...
316 * there is no requirement for kty to be given first and eg,
317 * ACME specifies the keys must be ordered in lexographic
318 * order - where kty is not first.
319 */
320 jps->possible = F_RSA | F_EC | F_OCT;
321
322 if (reason == LEJPCB_OBJECT_END && ctx->path_match == 0 + 1) {
323 /* we completed parsing a key */
324 if (jps->per_key_cb && jps->possible) {
325 if (jps->per_key_cb(jps->jwk, jps->user)) {
326
327 lwsl_notice("%s: user cb halts import\n",
328 __func__);
329
330 return -2;
331 }
332
333 /* clear it down */
334 lws_jwk_destroy(jps->jwk);
335 jps->possible = 0;
336 }
337 }
338
339 if (reason == LEJPCB_COMPLETE) {
340
341 /*
342 * Now we saw the whole jwk and know the key type, let'jwk insist
343 * that as a whole, it must be consistent and complete.
344 *
345 * The tracking of ->possible bits from even before we know the
346 * kty already makes certain we cannot have key element members
347 * defined that are inconsistent with the key type.
348 */
349
350 for (n = 0; n < LWS_ARRAY_SIZE(tok_map); n++)
351 /*
352 * All mandataory elements for the key type
353 * must be present
354 */
355 if ((tok_map[n] & jps->possible) && (
356 ((tok_map[n] & (F_M | F_META)) == (F_M | F_META) &&
357 !jwk->meta[tok_map[n] & 0xff].buf) ||
358 ((tok_map[n] & (F_M | F_META)) == F_M &&
359 !jwk->e[tok_map[n] & 0xff].buf))) {
360 lwsl_notice("%s: missing %s\n", __func__,
361 jwk_tok[n]);
362 return -3;
363 }
364
365 /*
366 * When the key may be public or public + private, ensure the
367 * intra-key members related to that are consistent.
368 *
369 * Only RSA keys need extra care, since EC keys are already
370 * confirmed by making CRV, X and Y mandatory and only D
371 * (the singular private part) optional. For RSA, N and E are
372 * also already known to be present using mandatory checking.
373 */
374
375 /*
376 * If a private key, it must have all D, P and Q. Public key
377 * must have none of them.
378 */
379 if (jwk->kty == LWS_GENCRYPTO_KTY_RSA &&
380 !(((!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf) &&
381 (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) &&
382 (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf)) ||
383 (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf &&
384 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf &&
385 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf))
386 ) {
387 lwsl_notice("%s: RSA requires D, P and Q for private\n",
388 __func__);
389 return -3;
390 }
391
392 /*
393 * If the precomputed private key terms appear, they must all
394 * appear together.
395 */
396 if (jwk->kty == LWS_GENCRYPTO_KTY_RSA &&
397 !(((!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DP].buf) &&
398 (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf) &&
399 (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_QI].buf)) ||
400 (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DP].buf &&
401 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf &&
402 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_QI].buf))
403 ) {
404 lwsl_notice("%s: RSA DP, DQ, QI must all appear "
405 "or none\n", __func__);
406 return -3;
407 }
408
409 /*
410 * The precomputed private key terms must not appear without
411 * the private key itself also appearing.
412 */
413 if (jwk->kty == LWS_GENCRYPTO_KTY_RSA &&
414 !jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf &&
415 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf) {
416 lwsl_notice("%s: RSA DP, DQ, QI can appear only with "
417 "private key\n", __func__);
418 return -3;
419 }
420
421 if ((jwk->kty == LWS_GENCRYPTO_KTY_RSA ||
422 jwk->kty == LWS_GENCRYPTO_KTY_EC) &&
423 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf)
424 jwk->private_key = 1;
425 }
426
427 if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
428 return 0;
429
430 if (ctx->path_match == 0 + 1)
431 return 0;
432
433 idx = tok_map[ctx->path_match - 1];
434 if ((idx & 0xff) == 0xff)
435 return 0;
436
437 switch (idx) {
438 /* note: kty is not necessarily first... we have to keep track of
439 * what could match given which element names have already been
440 * seen. Once kty comes, we confirm it'jwk still possible (ie, it'jwk
441 * not trying to tell us that it'jwk RSA now when we saw a "crv"
442 * earlier) and then reduce the possibilities to just the one that
443 * kty told. */
444 case F_RSA | F_EC | F_OCT | F_META | F_M | JWK_META_KTY:
445
446 if (ctx->npos == 3 && !strncmp(ctx->buf, "oct", 3)) {
447 if (!(jps->possible & F_OCT))
448 goto elements_mismatch;
449 jwk->kty = LWS_GENCRYPTO_KTY_OCT;
450 jps->possible = F_OCT;
451 goto cont;
452 }
453 if (ctx->npos == 3 && !strncmp(ctx->buf, "RSA", 3)) {
454 if (!(jps->possible & F_RSA))
455 goto elements_mismatch;
456 jwk->kty = LWS_GENCRYPTO_KTY_RSA;
457 jps->possible = F_RSA;
458 goto cont;
459 }
460 if (ctx->npos == 2 && !strncmp(ctx->buf, "EC", 2)) {
461 if (!(jps->possible & F_EC))
462 goto elements_mismatch;
463 jwk->kty = LWS_GENCRYPTO_KTY_EC;
464 jps->possible = F_EC;
465 goto cont;
466 }
467 lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar));
468 lwsl_err("%s: Unknown KTY '%s'\n", __func__, dotstar);
469 return -1;
470
471 default:
472 cont:
473 if (jps->pos + ctx->npos >= (int)sizeof(jps->b64))
474 goto bail;
475
476 memcpy(jps->b64 + jps->pos, ctx->buf, ctx->npos);
477 jps->pos += ctx->npos;
478
479 if (reason == LEJPCB_VAL_STR_CHUNK)
480 return 0;
481
482 /* chunking has been collated */
483
484 poss = idx & (F_RSA | F_EC | F_OCT);
485 jps->possible &= poss;
486 if (!jps->possible)
487 goto elements_mismatch;
488
489 if (idx & F_META) {
490 if (_lws_jwk_set_el_jwk(&jwk->meta[idx & 0x7f],
491 jps->b64, (unsigned int)jps->pos) < 0)
492 goto bail;
493
494 break;
495 }
496
497 if (idx & F_B64U) {
498 /* key data... do the base64 decode as needed */
499 if (_lws_jwk_set_el_jwk_b64u(&jwk->e[idx & 0x7f],
500 jps->b64, jps->pos) < 0)
501 goto bail;
502
503 if (jwk->e[idx & 0x7f].len >
504 LWS_JWE_LIMIT_KEY_ELEMENT_BYTES) {
505 lwsl_notice("%s: oversize keydata\n", __func__);
506 goto bail;
507 }
508
509 return 0;
510 }
511
512 if (idx & F_B64) {
513
514 /* cert data... do non-urlcoded base64 decode */
515 if (_lws_jwk_set_el_jwk_b64(&jwk->e[idx & 0x7f],
516 jps->b64, jps->pos) < 0)
517 goto bail;
518 return 0;
519 }
520
521 if (_lws_jwk_set_el_jwk(&jwk->e[idx & 0x7f],
522 jps->b64, (unsigned int)jps->pos) < 0)
523 goto bail;
524 break;
525 }
526
527 return 0;
528
529 elements_mismatch:
530 lwsl_err("%s: jwk elements mismatch\n", __func__);
531
532 bail:
533 lwsl_err("%s: element failed\n", __func__);
534
535 return -1;
536 }
537
538 void
lws_jwk_init_jps(struct lejp_ctx * jctx,struct lws_jwk_parse_state * jps,struct lws_jwk * jwk,lws_jwk_key_import_callback cb,void * user)539 lws_jwk_init_jps(struct lejp_ctx *jctx, struct lws_jwk_parse_state *jps,
540 struct lws_jwk *jwk, lws_jwk_key_import_callback cb,
541 void *user)
542 {
543 if (jwk)
544 memset(jwk, 0, sizeof(*jwk));
545
546 jps->jwk = jwk;
547 jps->possible = F_RSA | F_EC | F_OCT;
548 jps->per_key_cb = cb;
549 jps->user = user;
550 jps->pos = 0;
551
552 lejp_construct(jctx, cb_jwk, jps, cb ? jwk_outer_tok: jwk_tok,
553 LWS_ARRAY_SIZE(jwk_tok));
554 }
555
556 int
lws_jwk_dup_oct(struct lws_jwk * jwk,const void * key,int len)557 lws_jwk_dup_oct(struct lws_jwk *jwk, const void *key, int len)
558 {
559 unsigned int ulen = (unsigned int)len;
560
561 jwk->e[LWS_GENCRYPTO_KTY_OCT].buf = lws_malloc(ulen, __func__);
562 if (!jwk->e[LWS_GENCRYPTO_KTY_OCT].buf)
563 return -1;
564
565 jwk->kty = LWS_GENCRYPTO_KTY_OCT;
566 jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].len = ulen;
567
568 memcpy(jwk->e[LWS_GENCRYPTO_KTY_OCT].buf, key, ulen);
569
570 return 0;
571 }
572
573 int
lws_jwk_generate(struct lws_context * context,struct lws_jwk * jwk,enum lws_gencrypto_kty kty,int bits,const char * curve)574 lws_jwk_generate(struct lws_context *context, struct lws_jwk *jwk,
575 enum lws_gencrypto_kty kty, int bits, const char *curve)
576 {
577 size_t sn;
578 int n;
579
580 memset(jwk, 0, sizeof(*jwk));
581
582 jwk->kty = (int)kty;
583 jwk->private_key = 1;
584
585 switch (kty) {
586 case LWS_GENCRYPTO_KTY_RSA:
587 {
588 struct lws_genrsa_ctx ctx;
589
590 lwsl_notice("%s: generating %d bit RSA key\n", __func__, bits);
591 n = lws_genrsa_new_keypair(context, &ctx, LGRSAM_PKCS1_1_5,
592 jwk->e, bits);
593 lws_genrsa_destroy(&ctx);
594 if (n) {
595 lwsl_err("%s: problem generating RSA key\n", __func__);
596 return 1;
597 }
598 }
599 break;
600 case LWS_GENCRYPTO_KTY_OCT:
601 sn = (unsigned int)lws_gencrypto_bits_to_bytes(bits);
602 jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf = lws_malloc(sn, "oct");
603 jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].len = (uint32_t)sn;
604 if (lws_get_random(context,
605 jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf, sn) != sn) {
606 lwsl_err("%s: problem getting random\n", __func__);
607 return 1;
608 }
609 break;
610 case LWS_GENCRYPTO_KTY_EC:
611 {
612 struct lws_genec_ctx ctx;
613
614 if (!curve) {
615 lwsl_err("%s: must have a named curve\n", __func__);
616
617 return 1;
618 }
619
620 if (lws_genecdsa_create(&ctx, context, NULL))
621 return 1;
622
623 lwsl_notice("%s: generating ECDSA key on curve %s\n", __func__,
624 curve);
625
626 n = lws_genecdsa_new_keypair(&ctx, curve, jwk->e);
627 lws_genec_destroy(&ctx);
628 if (n) {
629 lwsl_err("%s: problem generating ECDSA key\n", __func__);
630 return 1;
631 }
632 }
633 break;
634
635 case LWS_GENCRYPTO_KTY_UNKNOWN:
636 default:
637 lwsl_err("%s: unknown kty\n", __func__);
638 return 1;
639 }
640
641 return 0;
642 }
643
644 int
lws_jwk_import(struct lws_jwk * jwk,lws_jwk_key_import_callback cb,void * user,const char * in,size_t len)645 lws_jwk_import(struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user,
646 const char *in, size_t len)
647 {
648 struct lejp_ctx jctx;
649 struct lws_jwk_parse_state jps;
650 int m;
651
652 lws_jwk_init_jps(&jctx, &jps, jwk, cb, user);
653
654 m = lejp_parse(&jctx, (uint8_t *)in, (int)len);
655 lejp_destruct(&jctx);
656
657 if (m < 0) {
658 lwsl_notice("%s: parse got %d\n", __func__, m);
659 lws_jwk_destroy(jwk);
660 return -1;
661 }
662
663 switch (jwk->kty) {
664 case LWS_GENCRYPTO_KTY_UNKNOWN:
665 lwsl_notice("%s: missing or unknown kyt\n", __func__);
666 lws_jwk_destroy(jwk);
667 return -1;
668 default:
669 break;
670 }
671
672 return 0;
673 }
674
675
676 int
lws_jwk_export(struct lws_jwk * jwk,int flags,char * p,int * len)677 lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len)
678 {
679 char *start = p, *end = &p[*len - 1];
680 int n, m, limit, first = 1, asym = 0;
681 struct lexico *l;
682
683 /* RFC7638 lexicographic order requires
684 * RSA: e -> kty -> n
685 * oct: k -> kty
686 *
687 * ie, meta and key data elements appear interleaved in name alpha order
688 */
689
690 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{");
691
692 switch (jwk->kty) {
693 case LWS_GENCRYPTO_KTY_OCT:
694 l = lexico_oct;
695 limit = LWS_ARRAY_SIZE(lexico_oct);
696 break;
697 case LWS_GENCRYPTO_KTY_RSA:
698 l = lexico_rsa;
699 limit = LWS_ARRAY_SIZE(lexico_rsa);
700 asym = 1;
701 break;
702 case LWS_GENCRYPTO_KTY_EC:
703 l = lexico_ec;
704 limit = LWS_ARRAY_SIZE(lexico_ec);
705 asym = 1;
706 break;
707 default:
708 return -1;
709 }
710
711 for (n = 0; n < limit; n++) {
712 const char *q, *q_end;
713 char tok[12];
714 int pos = 0, f = 1;
715
716 if ((l->meta & 1) && (jwk->meta[l->idx].buf ||
717 l->idx == (int)JWK_META_KTY)) {
718
719 switch (l->idx) {
720 case JWK_META_KTY:
721 if (!first)
722 *p++ = ',';
723 first = 0;
724 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"%s\"",
725 l->name, kty_names[jwk->kty]);
726 break;
727 case JWK_META_KEY_OPS:
728 if (!first)
729 *p++ = ',';
730 first = 0;
731 q = (const char *)jwk->meta[l->idx].buf;
732 q_end = q + jwk->meta[l->idx].len;
733
734 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
735 "\"%s\":[", l->name);
736 /*
737 * For the public version, usages that
738 * require the private part must be
739 * snipped
740 */
741
742 while (q < q_end) {
743 if (*q != ' ' && pos < (int)sizeof(tok) - 1) {
744 tok[pos++] = *q++;
745 if (q != q_end)
746 continue;
747 }
748 tok[pos] = '\0';
749 pos = 0;
750 if ((flags & LWSJWKF_EXPORT_PRIVATE) ||
751 !asym || (strcmp(tok, "sign") &&
752 strcmp(tok, "encrypt"))) {
753 if (!f)
754 *p++ = ',';
755 f = 0;
756 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
757 "\"%s\"", tok);
758 }
759 q++;
760 }
761
762 *p++ = ']';
763
764 break;
765
766 default:
767 /* both sig and enc require asym private key */
768 if (!(flags & LWSJWKF_EXPORT_PRIVATE) &&
769 asym && l->idx == (int)JWK_META_USE)
770 break;
771 if (!first)
772 *p++ = ',';
773 first = 0;
774 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"",
775 l->name);
776 lws_strnncpy(p, (const char *)jwk->meta[l->idx].buf,
777 jwk->meta[l->idx].len, end - p);
778 p += strlen(p);
779 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"");
780 break;
781 }
782 }
783
784 if ((!(l->meta & 1)) && jwk->e[l->idx].buf &&
785 ((flags & LWSJWKF_EXPORT_PRIVATE) || !(l->meta & 2))) {
786 if (!first)
787 *p++ = ',';
788 first = 0;
789
790 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"", l->name);
791
792 if (jwk->kty == LWS_GENCRYPTO_KTY_EC &&
793 l->idx == (int)LWS_GENCRYPTO_EC_KEYEL_CRV) {
794 lws_strnncpy(p,
795 (const char *)jwk->e[l->idx].buf,
796 jwk->e[l->idx].len, end - p);
797 m = (int)strlen(p);
798 } else
799 m = lws_jws_base64_enc(
800 (const char *)jwk->e[l->idx].buf,
801 jwk->e[l->idx].len, p, lws_ptr_diff_size_t(end, p) - 4);
802 if (m < 0) {
803 lwsl_notice("%s: enc failed\n", __func__);
804 return -1;
805 }
806 p += m;
807 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"");
808 }
809
810 l++;
811 }
812
813 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
814 (flags & LWSJWKF_EXPORT_NOCRLF) ? "}" : "}\n");
815
816 *len -= lws_ptr_diff(p, start);
817
818 return lws_ptr_diff(p, start);
819 }
820
821 int
lws_jwk_rfc7638_fingerprint(struct lws_jwk * jwk,char * digest32)822 lws_jwk_rfc7638_fingerprint(struct lws_jwk *jwk, char *digest32)
823 {
824 struct lws_genhash_ctx hash_ctx;
825 size_t tmpsize = 2536;
826 char *tmp;
827 int n, m = (int)tmpsize;
828
829 tmp = lws_malloc(tmpsize, "rfc7638 tmp");
830
831 n = lws_jwk_export(jwk, LWSJWKF_EXPORT_NOCRLF, tmp, &m);
832 if (n < 0)
833 goto bail;
834
835 if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256))
836 goto bail;
837
838 if (lws_genhash_update(&hash_ctx, tmp, (unsigned int)n)) {
839 lws_genhash_destroy(&hash_ctx, NULL);
840
841 goto bail;
842 }
843 lws_free(tmp);
844
845 if (lws_genhash_destroy(&hash_ctx, digest32))
846 return -1;
847
848 return 0;
849
850 bail:
851 lws_free(tmp);
852
853 return -1;
854 }
855
856 int
lws_jwk_strdup_meta(struct lws_jwk * jwk,enum enum_jwk_meta_tok idx,const char * in,int len)857 lws_jwk_strdup_meta(struct lws_jwk *jwk, enum enum_jwk_meta_tok idx,
858 const char *in, int len)
859 {
860 jwk->meta[idx].buf = lws_malloc((unsigned int)len, __func__);
861 if (!jwk->meta[idx].buf)
862 return 1;
863 jwk->meta[idx].len = (uint32_t)(unsigned int)len;
864 memcpy(jwk->meta[idx].buf, in, (unsigned int)len);
865
866 return 0;
867 }
868
869 int
lws_jwk_load(struct lws_jwk * jwk,const char * filename,lws_jwk_key_import_callback cb,void * user)870 lws_jwk_load(struct lws_jwk *jwk, const char *filename,
871 lws_jwk_key_import_callback cb, void *user)
872 {
873 unsigned int buflen = 4096;
874 char *buf = lws_malloc(buflen, "jwk-load");
875 int n;
876
877 if (!buf)
878 return -1;
879
880 n = lws_plat_read_file(filename, buf, buflen);
881 if (n < 0)
882 goto bail;
883
884 n = lws_jwk_import(jwk, cb, user, buf, (unsigned int)n);
885 lws_free(buf);
886
887 return n;
888 bail:
889 lws_free(buf);
890
891 return -1;
892 }
893
894 int
lws_jwk_save(struct lws_jwk * jwk,const char * filename)895 lws_jwk_save(struct lws_jwk *jwk, const char *filename)
896 {
897 int buflen = 4096;
898 char *buf = lws_malloc((unsigned int)buflen, "jwk-save");
899 int n, m;
900
901 if (!buf)
902 return -1;
903
904 n = lws_jwk_export(jwk, LWSJWKF_EXPORT_PRIVATE, buf, &buflen);
905 if (n < 0)
906 goto bail;
907
908 m = lws_plat_write_file(filename, buf, (size_t)n);
909
910 lws_free(buf);
911 if (m)
912 return -1;
913
914 return 0;
915
916 bail:
917 lws_free(buf);
918
919 return -1;
920 }
921