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 42 enum 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 61 struct 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 68 struct 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 */ 85 LWS_VISIBLE LWS_EXTERN void 86 lws_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 */ 98 LWS_VISIBLE LWS_EXTERN void 99 lws_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. 115 */ 116 LWS_VISIBLE LWS_EXTERN int 117 lws_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 121 LWS_VISIBLE LWS_EXTERN int 122 lws_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. 143 */ 144 LWS_VISIBLE LWS_EXTERN int 145 lws_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. 167 */ 168 LWS_VISIBLE LWS_EXTERN int 169 lws_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 * Returns the length of the encoded signature written to \p b64_sig, or -1. 191 */ 192 LWS_VISIBLE LWS_EXTERN int 193 lws_jws_sign_from_b64(struct lws_jose *jose, struct lws_jws *jws, char *b64_sig, 194 size_t sig_len); 195 196 /** 197 * lws_jws_compact_decode() - converts and maps compact serialization b64 sections 198 * 199 * \param in: the incoming compact serialized b64 200 * \param len: the length of the incoming compact serialized b64 201 * \param map: pointer to the results structure 202 * \param map_b64: NULL, or pointer to a second results structure taking block 203 * information about the undecoded b64 204 * \param out: buffer to hold decoded results 205 * \param out_len: size of out in bytes 206 * 207 * Returns number of sections (2 if "none", else 3), or -1 if illegal. 208 * 209 * map is set to point to the start and hold the length of each decoded block. 210 * If map_b64 is non-NULL, then it's set with information about the input b64 211 * blocks. 212 */ 213 LWS_VISIBLE LWS_EXTERN int 214 lws_jws_compact_decode(const char *in, int len, struct lws_jws_map *map, 215 struct lws_jws_map *map_b64, char *out, int *out_len); 216 217 LWS_VISIBLE LWS_EXTERN int 218 lws_jws_compact_encode(struct lws_jws_map *map_b64, /* b64-encoded */ 219 const struct lws_jws_map *map, /* non-b64 */ 220 char *buf, int *out_len); 221 222 LWS_VISIBLE LWS_EXTERN int 223 lws_jws_sig_confirm_json(const char *in, size_t len, 224 struct lws_jws *jws, struct lws_jwk *jwk, 225 struct lws_context *context, 226 char *temp, int *temp_len); 227 228 /** 229 * lws_jws_write_flattened_json() - create flattened JSON sig 230 * 231 * \param jws: information to include in the signature 232 * \param flattened: output buffer for JSON 233 * \param len: size of \p flattened output buffer 234 * 235 */ 236 LWS_VISIBLE LWS_EXTERN int 237 lws_jws_write_flattened_json(struct lws_jws *jws, char *flattened, size_t len); 238 239 /** 240 * lws_jws_write_compact() - create flattened JSON sig 241 * 242 * \param jws: information to include in the signature 243 * \param compact: output buffer for compact format 244 * \param len: size of \p flattened output buffer 245 * 246 */ 247 LWS_VISIBLE LWS_EXTERN int 248 lws_jws_write_compact(struct lws_jws *jws, char *compact, size_t len); 249 250 251 252 /* 253 * below apis are not normally needed if dealing with whole JWS... they're 254 * useful for creating from scratch 255 */ 256 257 258 /** 259 * lws_jws_dup_element() - allocate space for an element and copy data into it 260 * 261 * \param map: map to create the element in 262 * \param idx: index of element in the map to create 263 * \param temp: space to allocate in 264 * \param temp_len: available space at temp 265 * \param in: data to duplicate into element 266 * \param in_len: length of data to duplicate 267 * \param actual_alloc: 0 for same as in_len, else actual allocation size 268 * 269 * Copies in_len from in to temp, if temp_len is sufficient. 270 * 271 * Returns 0 or -1 if not enough space in temp / temp_len. 272 * 273 * Over-allocation can be acheived by setting actual_alloc to the real 274 * allocation desired... in_len will be copied into it. 275 * 276 * *temp_len is reduced by actual_alloc if successful. 277 */ 278 LWS_VISIBLE LWS_EXTERN int 279 lws_jws_dup_element(struct lws_jws_map *map, int idx, 280 char *temp, int *temp_len, const void *in, size_t in_len, 281 size_t actual_alloc); 282 283 /** 284 * lws_jws_randomize_element() - create an element and fill with random 285 * 286 * \param context: lws_context used for random 287 * \param map: map to create the element in 288 * \param idx: index of element in the map to create 289 * \param temp: space to allocate in 290 * \param temp_len: available space at temp 291 * \param random_len: length of data to fill with random 292 * \param actual_alloc: 0 for same as random_len, else actual allocation size 293 * 294 * Randomize random_len bytes at temp, if temp_len is sufficient. 295 * 296 * Returns 0 or -1 if not enough space in temp / temp_len. 297 * 298 * Over-allocation can be acheived by setting actual_alloc to the real 299 * allocation desired... the first random_len will be filled with random. 300 * 301 * *temp_len is reduced by actual_alloc if successful. 302 */ 303 LWS_VISIBLE LWS_EXTERN int 304 lws_jws_randomize_element(struct lws_context *context, 305 struct lws_jws_map *map, 306 int idx, char *temp, int *temp_len, size_t random_len, 307 size_t actual_alloc); 308 309 /** 310 * lws_jws_alloc_element() - create an element and reserve space for content 311 * 312 * \param map: map to create the element in 313 * \param idx: index of element in the map to create 314 * \param temp: space to allocate in 315 * \param temp_len: available space at temp 316 * \param len: logical length of element 317 * \param actual_alloc: 0 for same as len, else actual allocation size 318 * 319 * Allocate len bytes at temp, if temp_len is sufficient. 320 * 321 * Returns 0 or -1 if not enough space in temp / temp_len. 322 * 323 * Over-allocation can be acheived by setting actual_alloc to the real 324 * allocation desired... the element logical length will be set to len. 325 * 326 * *temp_len is reduced by actual_alloc if successful. 327 */ 328 LWS_VISIBLE LWS_EXTERN int 329 lws_jws_alloc_element(struct lws_jws_map *map, int idx, char *temp, 330 int *temp_len, size_t len, size_t actual_alloc); 331 332 /** 333 * lws_jws_encode_b64_element() - create an b64-encoded element 334 * 335 * \param map: map to create the element in 336 * \param idx: index of element in the map to create 337 * \param temp: space to allocate in 338 * \param temp_len: available space at temp 339 * \param in: pointer to unencoded input 340 * \param in_len: length of unencoded input 341 * 342 * Allocate len bytes at temp, if temp_len is sufficient. 343 * 344 * Returns 0 or -1 if not enough space in temp / temp_len. 345 * 346 * Over-allocation can be acheived by setting actual_alloc to the real 347 * allocation desired... the element logical length will be set to len. 348 * 349 * *temp_len is reduced by actual_alloc if successful. 350 */ 351 LWS_VISIBLE LWS_EXTERN int 352 lws_jws_encode_b64_element(struct lws_jws_map *map, int idx, 353 char *temp, int *temp_len, const void *in, 354 size_t in_len); 355 356 357 /** 358 * lws_jws_b64_compact_map() - find block starts and lengths in compact b64 359 * 360 * \param in: pointer to b64 jose.payload[.hdr].sig 361 * \param len: bytes available at \p in 362 * \param map: output struct with pointers and lengths for each JWS element 363 * 364 * Scans a jose.payload[.hdr].sig b64 string and notes where the blocks start 365 * and their length into \p map. 366 * 367 * Returns number of blocks if OK. May return <0 if malformed. 368 * May not fill all map entries. 369 */ 370 371 LWS_VISIBLE LWS_EXTERN int 372 lws_jws_b64_compact_map(const char *in, int len, struct lws_jws_map *map); 373 374 375 /** 376 * lws_jws_base64_enc() - encode input data into b64url data 377 * 378 * \param in: the incoming plaintext 379 * \param in_len: the length of the incoming plaintext in bytes 380 * \param out: the buffer to store the b64url encoded data to 381 * \param out_max: the length of \p out in bytes 382 * 383 * Returns either -1 if problems, or the number of bytes written to \p out. 384 */ 385 LWS_VISIBLE LWS_EXTERN int 386 lws_jws_base64_enc(const char *in, size_t in_len, char *out, size_t out_max); 387 388 /** 389 * lws_jws_encode_section() - encode input data into b64url data, 390 * prepending . if not first 391 * 392 * \param in: the incoming plaintext 393 * \param in_len: the length of the incoming plaintext in bytes 394 * \param first: nonzero if the first section 395 * \param p: the buffer to store the b64url encoded data to 396 * \param end: just past the end of p 397 * 398 * Returns either -1 if problems, or the number of bytes written to \p out. 399 * If the section is not the first one, '.' is prepended. 400 */ 401 LWS_VISIBLE LWS_EXTERN int 402 lws_jws_encode_section(const char *in, size_t in_len, int first, char **p, 403 char *end); 404 405 /** 406 * lws_jwt_signed_validate() - check a compact JWT against a key and alg 407 * 408 * \param ctx: the lws_context 409 * \param jwk: the key for checking the signature 410 * \param alg_list: the expected alg name, like "ES512" 411 * \param com: the compact JWT 412 * \param len: the length of com 413 * \param temp: a temp scratchpad 414 * \param tl: available length of temp scratchpad 415 * \param out: the output buffer to hold the validated plaintext 416 * \param out_len: on entry, max length of out; on exit, used length of out 417 * 418 * Returns nonzero if the JWT cannot be validated or the plaintext can't fit the 419 * provided output buffer, or 0 if it is validated as being signed by the 420 * provided jwk. 421 * 422 * If validated, the plaintext in the JWT is copied into out and out_len set to 423 * the used length. 424 * 425 * temp can be discarded or reused after the call returned, it's used to hold 426 * transformations of the B64 JWS in the JWT. 427 */ 428 LWS_VISIBLE LWS_EXTERN int 429 lws_jwt_signed_validate(struct lws_context *ctx, struct lws_jwk *jwk, 430 const char *alg_list, const char *com, size_t len, 431 char *temp, int tl, char *out, size_t *out_len); 432 433 /** 434 * lws_jwt_sign_compact() - generate a compact JWT using a key and alg 435 * 436 * \param ctx: the lws_context 437 * \param jwk: the signing key 438 * \param alg: the signing alg name, like "ES512" 439 * \param out: the output buffer to hold the signed JWT in compact form 440 * \param out_len: on entry, the length of out; on exit, the used amount of out 441 * \param temp: a temp scratchpad 442 * \param tl: available length of temp scratchpad 443 * \param format: a printf style format specification 444 * \param ...: zero or more args for the format specification 445 * 446 * Creates a JWT in a single step, from the format string and args through to 447 * outputting a well-formed compact JWT representation in out. 448 * 449 * Returns 0 if all is well and *out_len is the amount of data in out, else 450 * nonzero if failed. Temp must be large enough to hold various intermediate 451 * representations. 452 */ 453 LWS_VISIBLE LWS_EXTERN int 454 lws_jwt_sign_compact(struct lws_context *ctx, struct lws_jwk *jwk, 455 const char *alg, char *out, size_t *out_len, char *temp, 456 int tl, const char *format, ...) LWS_FORMAT(8); 457 458 struct lws_jwt_sign_info { 459 const char *alg; 460 /**< entry: signing alg name, like "RS256" */ 461 const char *jose_hdr; 462 /**< entry: optional JOSE hdr; if present, alg field is ignored; instead the 463 * whole claim object has to be provided in this parameter */ 464 size_t jose_hdr_len; 465 /**< entry: if jose_hdr is not NULL, JOSE header length without terminating '\0' */ 466 char *out; 467 /**< exit: signed JWT in compact form*/ 468 size_t *out_len; 469 /**< entry,exit: buffer size of out; actual size of JWT on exit */ 470 char *temp; 471 /**< exit undefined content, used by the function as a temporary scratchpad; MUST 472 * be large enogh to store various intermediate representations */ 473 int tl; 474 /**< entry: size of temp buffer */ 475 }; 476 477 /** 478 * lws_jwt_sign_compact() - generate a compact JWT using a key and JOSE header 479 * 480 * \param ctx: the lws_context 481 * \param jwk: the signing key 482 * \param info: info describing the JWT's content and output/temp buffers 483 * \param format: a printf style format specification of the claims object 484 * \param ...: zero or more args for the format specification 485 * 486 * Creates a JWT in a single step, from the format string and args through to 487 * outputting a well-formed compact JWT representation in out. The provided 488 * JOSE header's syntax is checked before it is added to the JWT. 489 * 490 * Returns 0 if all is well and *out_len is the amount of data in out, else 491 * nonzero if failed. Temp must be large enough to hold various intermediate 492 * representations. 493 */ 494 LWS_VISIBLE LWS_EXTERN int 495 lws_jwt_sign_via_info(struct lws_context *ctx, struct lws_jwk *jwk, 496 const struct lws_jwt_sign_info *info, const char *format, ...) LWS_FORMAT(4); 497 498 /** 499 * lws_jwt_token_sanity() - check a validated jwt payload for sanity 500 * 501 * \param in: the JWT payload 502 * \param in_len: the length of the JWT payload 503 * \param iss: the expected issuer of the token 504 * \param aud: the expected audience of the token 505 * \param csrf_in: NULL, or the csrf token that came in on a URL 506 * \param sub: a buffer to hold the subject name in the JWT (eg, account name) 507 * \param sub_len: the max length of the sub buffer 508 * \param secs_left: set to the number of seconds of valid auth left if valid 509 * 510 * This performs some generic sanity tests on validated JWT payload... 511 * 512 * - the issuer is as expected 513 * - the audience is us 514 * - current time is OK for nbf ("not before") in the token 515 * - current time is OK for exp ("expiry") in the token 516 * - if csrf_in is not NULL, that the JWK has a csrf and it matches it 517 * - if sub is not NULL, that the JWK provides a subject (and copies it to sub) 518 * 519 * If the tests pass, *secs_left is set to the number of remaining seconds the 520 * auth is valid. 521 * 522 * Returns 0 if no inconsistency, else nonzero. 523 */ 524 LWS_VISIBLE LWS_EXTERN int 525 lws_jwt_token_sanity(const char *in, size_t in_len, 526 const char *iss, const char *aud, const char *csrf_in, 527 char *sub, size_t sub_len, unsigned long *exp_unix_time); 528 529 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 530 531 struct lws_jwt_sign_set_cookie { 532 struct lws_jwk *jwk; 533 /**< entry: required signing key */ 534 const char *alg; 535 /**< entry: required signing alg, eg, "ES512" */ 536 const char *iss; 537 /**< entry: issuer name to use */ 538 const char *aud; 539 /**< entry: audience */ 540 const char *cookie_name; 541 /**< entry: the name of the cookie */ 542 char sub[33]; 543 /**< sign-entry, validate-exit: subject */ 544 const char *extra_json; 545 /**< sign-entry, validate-exit: 546 * optional "ext" JSON object contents for the JWT */ 547 size_t extra_json_len; 548 /**< validate-exit: 549 * length of optional "ext" JSON object contents for the JWT */ 550 const char *csrf_in; 551 /**< validate-entry: 552 * NULL, or an external CSRF token to check against what is in the JWT */ 553 unsigned long expiry_unix_time; 554 /**< sign-entry: seconds the JWT and cookie may live, 555 * validate-exit: expiry unix time */ 556 }; 557 558 /** 559 * lws_jwt_sign_token_set_cookie() - creates sets a JWT in a wsi cookie 560 * 561 * \param wsi: the wsi to create the cookie header on 562 * \param i: structure describing what should be in the JWT 563 * \param p: wsi headers area 564 * \param end: end of wsi headers area 565 * 566 * Creates a JWT specified \p i, and attaches it to the outgoing headers on 567 * wsi. Returns 0 if successful. 568 * 569 * Best-practice security restrictions are applied to the cookie set action, 570 * including forcing httponly, and __Host- prefix. As required by __Host-, the 571 * cookie Path is set to /. __Host- is applied by the function, the cookie_name 572 * should just be "xyz" for "__Host-xyz". 573 * 574 * \p extra_json should just be the bare JSON, a { } is provided around it by 575 * the function if it's non-NULL. For example, "\"authorization\": 1". 576 * 577 * It's recommended the secs parameter is kept as small as consistent with one 578 * user session on the site if possible, eg, 10 minutes or 20 minutes. At the 579 * server, it can determine how much time is left in the auth and inform the 580 * client; if the JWT validity expires, the page should reload so the UI always 581 * reflects what's possible to do with the authorization state correctly. If 582 * the JWT expires, the user can log back in using credentials usually stored in 583 * the browser and auto-filled-in, so this is not very inconvenient. 584 * 585 * This is a helper on top of the other JOSE and JWT apis that somewhat crosses 586 * over between JWT and HTTP, since it knows about cookies. So it is only built 587 * if both LWS_WITH_JOSE and one of the http-related roles enabled. 588 */ 589 LWS_VISIBLE LWS_EXTERN int 590 lws_jwt_sign_token_set_http_cookie(struct lws *wsi, 591 const struct lws_jwt_sign_set_cookie *i, 592 uint8_t **p, uint8_t *end); 593 LWS_VISIBLE LWS_EXTERN int 594 lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi, 595 struct lws_jwt_sign_set_cookie *i, 596 char *out, size_t *out_len); 597 #endif 598 599 ///@} 600