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/*! \defgroup jws JSON Web Signature
26 * ## JSON Web Signature API
27 *
28 * Lws provides an API to check and create RFC7515 JSON Web Signatures
29 *
30 * SHA256/384/512 HMAC, and RSA 256/384/512 are supported.
31 *
32 * The API uses your TLS library crypto, but works exactly the same no matter
33 * what your TLS backend is.
34 */
35///@{
36
37/*
38 * The maps are built to work with both JWS (LJWS_) and JWE (LJWE_), and are
39 * sized to the slightly larger JWE case.
40 */
41
42enum enum_jws_sig_elements {
43
44 /* JWS block namespace */
45 LJWS_JOSE,
46 LJWS_PYLD,
47 LJWS_SIG,
48 LJWS_UHDR,
49
50 /* JWE block namespace */
51 LJWE_JOSE = 0,
52 LJWE_EKEY,
53 LJWE_IV,
54 LJWE_CTXT,
55 LJWE_ATAG,
56 LJWE_AAD,
57
58 LWS_JWS_MAX_COMPACT_BLOCKS
59};
60
61struct lws_jws_map {
62 const char *buf[LWS_JWS_MAX_COMPACT_BLOCKS];
63 uint32_t len[LWS_JWS_MAX_COMPACT_BLOCKS];
64};
65
66#define LWS_JWS_MAX_SIGS 3
67
68struct lws_jws {
69 struct lws_jwk *jwk; /* the struct lws_jwk containing the signing key */
70 struct lws_context *context; /* the lws context (used to get random) */
71 struct lws_jws_map map, map_b64;
72};
73
74/* jws EC signatures do not have ASN.1 in them, meaning they're incompatible
75 * with generic signatures.
76 */
77
78/**
79 * lws_jws_init() - initialize a jws for use
80 *
81 * \param jws: pointer to the jws to initialize
82 * \param jwk: the jwk to use with this jws
83 * \param context: the lws_context to use
84 */
85LWS_VISIBLE LWS_EXTERN void
86lws_jws_init(struct lws_jws *jws, struct lws_jwk *jwk,
87 struct lws_context *context);
88
89/**
90 * lws_jws_destroy() - scrub a jws
91 *
92 * \param jws: pointer to the jws to destroy
93 *
94 * Call before the jws goes out of scope.
95 *
96 * Elements defined in the jws are zeroed.
97 */
98LWS_VISIBLE LWS_EXTERN void
99lws_jws_destroy(struct lws_jws *jws);
100
101/**
102 * lws_jws_sig_confirm_compact() - check signature
103 *
104 * \param map: pointers and lengths for each of the unencoded JWS elements
105 * \param jwk: public key
106 * \param context: lws_context
107 * \param temp: scratchpad
108 * \param temp_len: length of scratchpad
109 *
110 * Confirms the signature on a JWS. Use if you have non-b64 plain JWS elements
111 * in a map... it'll make a temp b64 version needed for comparison. See below
112 * for other variants.
113 *
114 * Returns 0 on match, else nonzero.
115 */
116LWS_VISIBLE LWS_EXTERN int
117lws_jws_sig_confirm_compact(struct lws_jws_map *map, struct lws_jwk *jwk,
118 struct lws_context *context,
119 char *temp, int *temp_len);
120
121LWS_VISIBLE LWS_EXTERN int
122lws_jws_sig_confirm_compact_b64_map(struct lws_jws_map *map_b64,
123 struct lws_jwk *jwk,
124 struct lws_context *context,
125 char *temp, int *temp_len);
126
127/**
128 * lws_jws_sig_confirm_compact_b64() - check signature on b64 compact JWS
129 *
130 * \param in: pointer to b64 jose.payload[.hdr].sig
131 * \param len: bytes available at \p in
132 * \param map: map to take decoded non-b64 content
133 * \param jwk: public key
134 * \param context: lws_context
135 * \param temp: scratchpad
136 * \param temp_len: size of scratchpad
137 *
138 * Confirms the signature on a JWS. Use if you have you have b64 compact layout
139 * (jose.payload.hdr.sig) as an aggregated string... it'll make a temp plain
140 * version needed for comparison.
141 *
142 * Returns 0 on match, else nonzero.
143 */
144LWS_VISIBLE LWS_EXTERN int
145lws_jws_sig_confirm_compact_b64(const char *in, size_t len,
146 struct lws_jws_map *map,
147 struct lws_jwk *jwk,
148 struct lws_context *context,
149 char *temp, int *temp_len);
150
151/**
152 * lws_jws_sig_confirm() - check signature on plain + b64 JWS elements
153 *
154 * \param map_b64: pointers and lengths for each of the b64-encoded JWS elements
155 * \param map: pointers and lengths for each of the unencoded JWS elements
156 * \param jwk: public key
157 * \param context: lws_context
158 *
159 * Confirms the signature on a JWS. Use if you have you already have both b64
160 * compact layout (jose.payload.hdr.sig) and decoded JWS elements in maps.
161 *
162 * If you had the b64 string and called lws_jws_compact_decode() on it, you
163 * will end up with both maps, and can use this api version, saving needlessly
164 * regenerating any temp map.
165 *
166 * Returns 0 on match, else nonzero.
167 */
168LWS_VISIBLE LWS_EXTERN int
169lws_jws_sig_confirm(struct lws_jws_map *map_b64, /* b64-encoded */
170 struct lws_jws_map *map, /* non-b64 */
171 struct lws_jwk *jwk, struct lws_context *context);
172
173/**
174 * lws_jws_sign_from_b64() - add b64 sig to b64 hdr + payload
175 *
176 * \param jose: jose header information
177 * \param jws: information to include in the signature
178 * \param b64_sig: output buffer for b64 signature
179 * \param sig_len: size of \p b64_sig output buffer
180 *
181 * This adds a b64-coded JWS signature of the b64-encoded protected header
182 * and b64-encoded payload, at \p b64_sig. The signature will be as large
183 * as the N element of the RSA key when the RSA key is used, eg, 512 bytes for
184 * a 4096-bit key, and then b64-encoding on top.
185 *
186 * In some special cases, there is only payload to sign and no header, in that
187 * case \p b64_hdr may be NULL, and only the payload will be hashed before
188 * signing.
189 *
190 * If successful, returns the length of the encoded signature written to
191 * \p b64_sig. If the jose signing type is unknown, 0 is returned. Otherwise
192 * -1 indicates failure.
193 */
194LWS_VISIBLE LWS_EXTERN int
195lws_jws_sign_from_b64(struct lws_jose *jose, struct lws_jws *jws, char *b64_sig,
196 size_t sig_len);
197
198/**
199 * lws_jws_compact_decode() - converts and maps compact serialization b64 sections
200 *
201 * \param in: the incoming compact serialized b64
202 * \param len: the length of the incoming compact serialized b64
203 * \param map: pointer to the results structure
204 * \param map_b64: NULL, or pointer to a second results structure taking block
205 * information about the undecoded b64
206 * \param out: buffer to hold decoded results
207 * \param out_len: size of out in bytes
208 *
209 * Returns number of sections (2 if "none", else 3), or -1 if illegal.
210 *
211 * map is set to point to the start and hold the length of each decoded block.
212 * If map_b64 is non-NULL, then it's set with information about the input b64
213 * blocks.
214 */
215LWS_VISIBLE LWS_EXTERN int
216lws_jws_compact_decode(const char *in, int len, struct lws_jws_map *map,
217 struct lws_jws_map *map_b64, char *out, int *out_len);
218
219LWS_VISIBLE LWS_EXTERN int
220lws_jws_compact_encode(struct lws_jws_map *map_b64, /* b64-encoded */
221 const struct lws_jws_map *map, /* non-b64 */
222 char *buf, int *out_len);
223
224LWS_VISIBLE LWS_EXTERN int
225lws_jws_sig_confirm_json(const char *in, size_t len,
226 struct lws_jws *jws, struct lws_jwk *jwk,
227 struct lws_context *context,
228 char *temp, int *temp_len);
229
230/**
231 * lws_jws_write_flattened_json() - create flattened JSON sig
232 *
233 * \param jws: information to include in the signature
234 * \param flattened: output buffer for JSON
235 * \param len: size of \p flattened output buffer
236 *
237 */
238LWS_VISIBLE LWS_EXTERN int
239lws_jws_write_flattened_json(struct lws_jws *jws, char *flattened, size_t len);
240
241/**
242 * lws_jws_write_compact() - create flattened JSON sig
243 *
244 * \param jws: information to include in the signature
245 * \param compact: output buffer for compact format
246 * \param len: size of \p flattened output buffer
247 *
248 */
249LWS_VISIBLE LWS_EXTERN int
250lws_jws_write_compact(struct lws_jws *jws, char *compact, size_t len);
251
252
253
254/*
255 * below apis are not normally needed if dealing with whole JWS... they're
256 * useful for creating from scratch
257 */
258
259
260/**
261 * lws_jws_dup_element() - allocate space for an element and copy data into it
262 *
263 * \param map: map to create the element in
264 * \param idx: index of element in the map to create
265 * \param temp: space to allocate in
266 * \param temp_len: available space at temp
267 * \param in: data to duplicate into element
268 * \param in_len: length of data to duplicate
269 * \param actual_alloc: 0 for same as in_len, else actual allocation size
270 *
271 * Copies in_len from in to temp, if temp_len is sufficient.
272 *
273 * Returns 0 or -1 if not enough space in temp / temp_len.
274 *
275 * Over-allocation can be acheived by setting actual_alloc to the real
276 * allocation desired... in_len will be copied into it.
277 *
278 * *temp_len is reduced by actual_alloc if successful.
279 */
280LWS_VISIBLE LWS_EXTERN int
281lws_jws_dup_element(struct lws_jws_map *map, int idx,
282 char *temp, int *temp_len, const void *in, size_t in_len,
283 size_t actual_alloc);
284
285/**
286 * lws_jws_randomize_element() - create an element and fill with random
287 *
288 * \param context: lws_context used for random
289 * \param map: map to create the element in
290 * \param idx: index of element in the map to create
291 * \param temp: space to allocate in
292 * \param temp_len: available space at temp
293 * \param random_len: length of data to fill with random
294 * \param actual_alloc: 0 for same as random_len, else actual allocation size
295 *
296 * Randomize random_len bytes at temp, if temp_len is sufficient.
297 *
298 * Returns 0 or -1 if not enough space in temp / temp_len.
299 *
300 * Over-allocation can be acheived by setting actual_alloc to the real
301 * allocation desired... the first random_len will be filled with random.
302 *
303 * *temp_len is reduced by actual_alloc if successful.
304 */
305LWS_VISIBLE LWS_EXTERN int
306lws_jws_randomize_element(struct lws_context *context,
307 struct lws_jws_map *map,
308 int idx, char *temp, int *temp_len, size_t random_len,
309 size_t actual_alloc);
310
311/**
312 * lws_jws_alloc_element() - create an element and reserve space for content
313 *
314 * \param map: map to create the element in
315 * \param idx: index of element in the map to create
316 * \param temp: space to allocate in
317 * \param temp_len: available space at temp
318 * \param len: logical length of element
319 * \param actual_alloc: 0 for same as len, else actual allocation size
320 *
321 * Allocate len bytes at temp, if temp_len is sufficient.
322 *
323 * Returns 0 or -1 if not enough space in temp / temp_len.
324 *
325 * Over-allocation can be acheived by setting actual_alloc to the real
326 * allocation desired... the element logical length will be set to len.
327 *
328 * *temp_len is reduced by actual_alloc if successful.
329 */
330LWS_VISIBLE LWS_EXTERN int
331lws_jws_alloc_element(struct lws_jws_map *map, int idx, char *temp,
332 int *temp_len, size_t len, size_t actual_alloc);
333
334/**
335 * lws_jws_encode_b64_element() - create an b64-encoded element
336 *
337 * \param map: map to create the element in
338 * \param idx: index of element in the map to create
339 * \param temp: space to allocate in
340 * \param temp_len: available space at temp
341 * \param in: pointer to unencoded input
342 * \param in_len: length of unencoded input
343 *
344 * Allocate len bytes at temp, if temp_len is sufficient.
345 *
346 * Returns 0 or -1 if not enough space in temp / temp_len.
347 *
348 * Over-allocation can be acheived by setting actual_alloc to the real
349 * allocation desired... the element logical length will be set to len.
350 *
351 * *temp_len is reduced by actual_alloc if successful.
352 */
353LWS_VISIBLE LWS_EXTERN int
354lws_jws_encode_b64_element(struct lws_jws_map *map, int idx,
355 char *temp, int *temp_len, const void *in,
356 size_t in_len);
357
358
359/**
360 * lws_jws_b64_compact_map() - find block starts and lengths in compact b64
361 *
362 * \param in: pointer to b64 jose.payload[.hdr].sig
363 * \param len: bytes available at \p in
364 * \param map: output struct with pointers and lengths for each JWS element
365 *
366 * Scans a jose.payload[.hdr].sig b64 string and notes where the blocks start
367 * and their length into \p map.
368 *
369 * Returns number of blocks if OK. May return <0 if malformed.
370 * May not fill all map entries.
371 */
372
373LWS_VISIBLE LWS_EXTERN int
374lws_jws_b64_compact_map(const char *in, int len, struct lws_jws_map *map);
375
376
377/**
378 * lws_jws_base64_enc() - encode input data into b64url data
379 *
380 * \param in: the incoming plaintext
381 * \param in_len: the length of the incoming plaintext in bytes
382 * \param out: the buffer to store the b64url encoded data to
383 * \param out_max: the length of \p out in bytes
384 *
385 * Returns either -1 if problems, or the number of bytes written to \p out.
386 */
387LWS_VISIBLE LWS_EXTERN int
388lws_jws_base64_enc(const char *in, size_t in_len, char *out, size_t out_max);
389
390/**
391 * lws_jws_encode_section() - encode input data into b64url data,
392 * prepending . if not first
393 *
394 * \param in: the incoming plaintext
395 * \param in_len: the length of the incoming plaintext in bytes
396 * \param first: nonzero if the first section
397 * \param p: the buffer to store the b64url encoded data to
398 * \param end: just past the end of p
399 *
400 * Returns either -1 if problems, or the number of bytes written to \p out.
401 * If the section is not the first one, '.' is prepended.
402 */
403LWS_VISIBLE LWS_EXTERN int
404lws_jws_encode_section(const char *in, size_t in_len, int first, char **p,
405 char *end);
406
407/**
408 * lws_jwt_signed_validate() - check a compact JWT against a key and alg
409 *
410 * \param ctx: the lws_context
411 * \param jwk: the key for checking the signature
412 * \param alg_list: the expected alg name, like "ES512"
413 * \param com: the compact JWT
414 * \param len: the length of com
415 * \param temp: a temp scratchpad
416 * \param tl: available length of temp scratchpad
417 * \param out: the output buffer to hold the validated plaintext
418 * \param out_len: on entry, max length of out; on exit, used length of out
419 *
420 * Returns nonzero if the JWT cannot be validated or the plaintext can't fit the
421 * provided output buffer, or 0 if it is validated as being signed by the
422 * provided jwk.
423 *
424 * If validated, the plaintext in the JWT is copied into out and out_len set to
425 * the used length.
426 *
427 * temp can be discarded or reused after the call returned, it's used to hold
428 * transformations of the B64 JWS in the JWT.
429 */
430LWS_VISIBLE LWS_EXTERN int
431lws_jwt_signed_validate(struct lws_context *ctx, struct lws_jwk *jwk,
432 const char *alg_list, const char *com, size_t len,
433 char *temp, int tl, char *out, size_t *out_len);
434
435/**
436 * lws_jwt_sign_compact() - generate a compact JWT using a key and alg
437 *
438 * \param ctx: the lws_context
439 * \param jwk: the signing key
440 * \param alg: the signing alg name, like "ES512"
441 * \param out: the output buffer to hold the signed JWT in compact form
442 * \param out_len: on entry, the length of out; on exit, the used amount of out
443 * \param temp: a temp scratchpad
444 * \param tl: available length of temp scratchpad
445 * \param format: a printf style format specification
446 * \param ...: zero or more args for the format specification
447 *
448 * Creates a JWT in a single step, from the format string and args through to
449 * outputting a well-formed compact JWT representation in out.
450 *
451 * Returns 0 if all is well and *out_len is the amount of data in out, else
452 * nonzero if failed. Temp must be large enough to hold various intermediate
453 * representations.
454 */
455LWS_VISIBLE LWS_EXTERN int
456lws_jwt_sign_compact(struct lws_context *ctx, struct lws_jwk *jwk,
457 const char *alg, char *out, size_t *out_len, char *temp,
458 int tl, const char *format, ...) LWS_FORMAT(8);
459
460struct lws_jwt_sign_info {
461 const char *alg;
462 /**< entry: signing alg name, like "RS256" */
463 const char *jose_hdr;
464 /**< entry: optional JOSE hdr; if present, alg field is ignored; instead the
465 * whole claim object has to be provided in this parameter */
466 size_t jose_hdr_len;
467 /**< entry: if jose_hdr is not NULL, JOSE header length without terminating '\0' */
468 char *out;
469 /**< exit: signed JWT in compact form*/
470 size_t *out_len;
471 /**< entry,exit: buffer size of out; actual size of JWT on exit */
472 char *temp;
473 /**< exit undefined content, used by the function as a temporary scratchpad; MUST
474 * be large enogh to store various intermediate representations */
475 int tl;
476 /**< entry: size of temp buffer */
477};
478
479/**
480 * lws_jwt_sign_compact() - generate a compact JWT using a key and JOSE header
481 *
482 * \param ctx: the lws_context
483 * \param jwk: the signing key
484 * \param info: info describing the JWT's content and output/temp buffers
485 * \param format: a printf style format specification of the claims object
486 * \param ...: zero or more args for the format specification
487 *
488 * Creates a JWT in a single step, from the format string and args through to
489 * outputting a well-formed compact JWT representation in out. The provided
490 * JOSE header's syntax is checked before it is added to the JWT.
491 *
492 * Returns 0 if all is well and *out_len is the amount of data in out, else
493 * nonzero if failed. Temp must be large enough to hold various intermediate
494 * representations.
495 */
496LWS_VISIBLE LWS_EXTERN int
497lws_jwt_sign_via_info(struct lws_context *ctx, struct lws_jwk *jwk,
498 const struct lws_jwt_sign_info *info, const char *format, ...) LWS_FORMAT(4);
499
500/**
501 * lws_jwt_token_sanity() - check a validated jwt payload for sanity
502 *
503 * \param in: the JWT payload
504 * \param in_len: the length of the JWT payload
505 * \param iss: the expected issuer of the token
506 * \param aud: the expected audience of the token
507 * \param csrf_in: NULL, or the csrf token that came in on a URL
508 * \param sub: a buffer to hold the subject name in the JWT (eg, account name)
509 * \param sub_len: the max length of the sub buffer
510 * \param secs_left: set to the number of seconds of valid auth left if valid
511 *
512 * This performs some generic sanity tests on validated JWT payload...
513 *
514 * - the issuer is as expected
515 * - the audience is us
516 * - current time is OK for nbf ("not before") in the token
517 * - current time is OK for exp ("expiry") in the token
518 * - if csrf_in is not NULL, that the JWK has a csrf and it matches it
519 * - if sub is not NULL, that the JWK provides a subject (and copies it to sub)
520 *
521 * If the tests pass, *secs_left is set to the number of remaining seconds the
522 * auth is valid.
523 *
524 * Returns 0 if no inconsistency, else nonzero.
525 */
526LWS_VISIBLE LWS_EXTERN int
527lws_jwt_token_sanity(const char *in, size_t in_len,
528 const char *iss, const char *aud, const char *csrf_in,
529 char *sub, size_t sub_len, unsigned long *exp_unix_time);
530
531#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
532
533struct lws_jwt_sign_set_cookie {
534 struct lws_jwk *jwk;
535 /**< entry: required signing key */
536 const char *alg;
537 /**< entry: required signing alg, eg, "ES512" */
538 const char *iss;
539 /**< entry: issuer name to use */
540 const char *aud;
541 /**< entry: audience */
542 const char *cookie_name;
543 /**< entry: the name of the cookie */
544 char sub[33];
545 /**< sign-entry, validate-exit: subject */
546 const char *extra_json;
547 /**< sign-entry, validate-exit:
548 * optional "ext" JSON object contents for the JWT */
549 size_t extra_json_len;
550 /**< validate-exit:
551 * length of optional "ext" JSON object contents for the JWT */
552 const char *csrf_in;
553 /**< validate-entry:
554 * NULL, or an external CSRF token to check against what is in the JWT */
555 unsigned long expiry_unix_time;
556 /**< sign-entry: seconds the JWT and cookie may live,
557 * validate-exit: expiry unix time */
558};
559
560/**
561 * lws_jwt_sign_token_set_http_cookie() - creates sets a JWT in a wsi cookie
562 *
563 * \param wsi: the wsi to create the cookie header on
564 * \param i: structure describing what should be in the JWT
565 * \param p: wsi headers area
566 * \param end: end of wsi headers area
567 *
568 * Creates a JWT specified \p i, and attaches it to the outgoing headers on
569 * wsi. Returns 0 if successful.
570 *
571 * Best-practice security restrictions are applied to the cookie set action,
572 * including forcing httponly, and __Host- prefix. As required by __Host-, the
573 * cookie Path is set to /. __Host- is applied by the function, the cookie_name
574 * should just be "xyz" for "__Host-xyz".
575 *
576 * \p extra_json should just be the bare JSON, a { } is provided around it by
577 * the function if it's non-NULL. For example, "\"authorization\": 1".
578 *
579 * It's recommended the secs parameter is kept as small as consistent with one
580 * user session on the site if possible, eg, 10 minutes or 20 minutes. At the
581 * server, it can determine how much time is left in the auth and inform the
582 * client; if the JWT validity expires, the page should reload so the UI always
583 * reflects what's possible to do with the authorization state correctly. If
584 * the JWT expires, the user can log back in using credentials usually stored in
585 * the browser and auto-filled-in, so this is not very inconvenient.
586 *
587 * This is a helper on top of the other JOSE and JWT apis that somewhat crosses
588 * over between JWT and HTTP, since it knows about cookies. So it is only built
589 * if both LWS_WITH_JOSE and one of the http-related roles enabled.
590 */
591LWS_VISIBLE LWS_EXTERN int
592lws_jwt_sign_token_set_http_cookie(struct lws *wsi,
593 const struct lws_jwt_sign_set_cookie *i,
594 uint8_t **p, uint8_t *end);
595LWS_VISIBLE LWS_EXTERN int
596lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi,
597 struct lws_jwt_sign_set_cookie *i,
598 char *out, size_t *out_len);
599#endif
600
601///@}
602