1d4afb5ceSopenharmony_ci /* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci * 24d4afb5ceSopenharmony_ci * JOSE is actually specified as part of JWS RFC7515. JWE references RFC7515 25d4afb5ceSopenharmony_ci * to specify its JOSE JSON object. So it lives in ./lib/jose/jws/jose.c. 26d4afb5ceSopenharmony_ci */ 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_ci#include "private-lib-core.h" 29d4afb5ceSopenharmony_ci#include "jose/private-lib-jose.h" 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_ci#include <stdint.h> 32d4afb5ceSopenharmony_ci 33d4afb5ceSopenharmony_cistatic const char * const jws_jose[] = { 34d4afb5ceSopenharmony_ci "alg", /* REQUIRED */ 35d4afb5ceSopenharmony_ci "jku", 36d4afb5ceSopenharmony_ci "jwk", 37d4afb5ceSopenharmony_ci "kid", 38d4afb5ceSopenharmony_ci "x5u", 39d4afb5ceSopenharmony_ci "x5c", 40d4afb5ceSopenharmony_ci "x5t", 41d4afb5ceSopenharmony_ci "x5t#S256", 42d4afb5ceSopenharmony_ci "typ", 43d4afb5ceSopenharmony_ci "cty", 44d4afb5ceSopenharmony_ci "crit", 45d4afb5ceSopenharmony_ci 46d4afb5ceSopenharmony_ci /* valid for JWE only below here */ 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_ci "recipients[].header", 49d4afb5ceSopenharmony_ci "recipients[].header.alg", 50d4afb5ceSopenharmony_ci "recipients[].header.kid", 51d4afb5ceSopenharmony_ci "recipients[].encrypted_key", 52d4afb5ceSopenharmony_ci 53d4afb5ceSopenharmony_ci "enc", 54d4afb5ceSopenharmony_ci "zip", /* ("DEF" = deflate) */ 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci "epk", /* valid for JWE ECDH only */ 57d4afb5ceSopenharmony_ci "apu", /* valid for JWE ECDH only */ 58d4afb5ceSopenharmony_ci "apv", /* valid for JWE ECDH only */ 59d4afb5ceSopenharmony_ci "iv", /* valid for JWE AES only */ 60d4afb5ceSopenharmony_ci "tag", /* valid for JWE AES only */ 61d4afb5ceSopenharmony_ci "p2s", /* valid for JWE PBES2 only */ 62d4afb5ceSopenharmony_ci "p2c" /* valid for JWE PBES2 only */ 63d4afb5ceSopenharmony_ci}; 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_cistruct jose_cb_args { 66d4afb5ceSopenharmony_ci struct lws_jose *jose; 67d4afb5ceSopenharmony_ci 68d4afb5ceSopenharmony_ci struct lejp_ctx jwk_jctx; /* fake lejp context used to parse epk */ 69d4afb5ceSopenharmony_ci struct lws_jwk_parse_state jps; /* fake jwk parse state */ 70d4afb5ceSopenharmony_ci 71d4afb5ceSopenharmony_ci char *temp; 72d4afb5ceSopenharmony_ci int *temp_len; 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ci unsigned int is_jwe; 75d4afb5ceSopenharmony_ci unsigned int recipients_array; 76d4afb5ceSopenharmony_ci 77d4afb5ceSopenharmony_ci int recip; 78d4afb5ceSopenharmony_ci}; 79d4afb5ceSopenharmony_ci 80d4afb5ceSopenharmony_ci/* 81d4afb5ceSopenharmony_ci * JWE A.4.7 Complete JWE JSON Serialization example 82d4afb5ceSopenharmony_ci * 83d4afb5ceSopenharmony_ci * LEJPCB_CONSTRUCTED 84d4afb5ceSopenharmony_ci * LEJPCB_START 85d4afb5ceSopenharmony_ci * LEJPCB_OBJECT_START 86d4afb5ceSopenharmony_ci * 87d4afb5ceSopenharmony_ci * protected LEJPCB_PAIR_NAME 88d4afb5ceSopenharmony_ci * protected LEJPCB_VAL_STR_START 89d4afb5ceSopenharmony_ci * protected LEJPCB_VAL_STR_END 90d4afb5ceSopenharmony_ci * 91d4afb5ceSopenharmony_ci * unprotected LEJPCB_PAIR_NAME 92d4afb5ceSopenharmony_ci * unprotected LEJPCB_OBJECT_START 93d4afb5ceSopenharmony_ci * unprotected.jku LEJPCB_PAIR_NAME 94d4afb5ceSopenharmony_ci * unprotected.jku LEJPCB_VAL_STR_START 95d4afb5ceSopenharmony_ci * unprotected.jku LEJPCB_VAL_STR_END 96d4afb5ceSopenharmony_ci * unprotected.jku LEJPCB_OBJECT_END 97d4afb5ceSopenharmony_ci * 98d4afb5ceSopenharmony_ci * recipients LEJPCB_PAIR_NAME 99d4afb5ceSopenharmony_ci * recipients[] LEJPCB_ARRAY_START 100d4afb5ceSopenharmony_ci * 101d4afb5ceSopenharmony_ci * recipients[] LEJPCB_OBJECT_START 102d4afb5ceSopenharmony_ci * recipients[].header LEJPCB_PAIR_NAME 103d4afb5ceSopenharmony_ci * recipients[].header LEJPCB_OBJECT_START 104d4afb5ceSopenharmony_ci * recipients[].header.alg LEJPCB_PAIR_NAME 105d4afb5ceSopenharmony_ci * recipients[].header.alg LEJPCB_VAL_STR_START 106d4afb5ceSopenharmony_ci * recipients[].header.alg LEJPCB_VAL_STR_END 107d4afb5ceSopenharmony_ci * recipients[].header.kid LEJPCB_PAIR_NAME 108d4afb5ceSopenharmony_ci * recipients[].header.kid LEJPCB_VAL_STR_START 109d4afb5ceSopenharmony_ci * recipients[].header.kid LEJPCB_VAL_STR_END 110d4afb5ceSopenharmony_ci * recipients[] LEJPCB_OBJECT_END 111d4afb5ceSopenharmony_ci * recipients[].encrypted_key LEJPCB_PAIR_NAME 112d4afb5ceSopenharmony_ci * recipients[].encrypted_key LEJPCB_VAL_STR_START 113d4afb5ceSopenharmony_ci * recipients[].encrypted_key LEJPCB_VAL_STR_CHUNK 114d4afb5ceSopenharmony_ci * recipients[].encrypted_key LEJPCB_VAL_STR_END 115d4afb5ceSopenharmony_ci * recipients[] LEJPCB_OBJECT_END (ctx->sp = 1) 116d4afb5ceSopenharmony_ci * 117d4afb5ceSopenharmony_ci * recipients[] LEJPCB_OBJECT_START 118d4afb5ceSopenharmony_ci * recipients[].header LEJPCB_PAIR_NAME 119d4afb5ceSopenharmony_ci * recipients[].header LEJPCB_OBJECT_START 120d4afb5ceSopenharmony_ci * recipients[].header.alg LEJPCB_PAIR_NAME 121d4afb5ceSopenharmony_ci * recipients[].header.alg LEJPCB_VAL_STR_START 122d4afb5ceSopenharmony_ci * recipients[].header.alg LEJPCB_VAL_STR_END 123d4afb5ceSopenharmony_ci * recipients[].header.kid LEJPCB_PAIR_NAME 124d4afb5ceSopenharmony_ci * recipients[].header.kid LEJPCB_VAL_STR_START 125d4afb5ceSopenharmony_ci * recipients[].header.kid LEJPCB_VAL_STR_END 126d4afb5ceSopenharmony_ci * recipients[] LEJPCB_OBJECT_END 127d4afb5ceSopenharmony_ci * recipients[].encrypted_key LEJPCB_PAIR_NAME 128d4afb5ceSopenharmony_ci * recipients[].encrypted_key LEJPCB_VAL_STR_START 129d4afb5ceSopenharmony_ci * recipients[].encrypted_key LEJPCB_VAL_STR_END 130d4afb5ceSopenharmony_ci * recipients[] LEJPCB_OBJECT_END (ctx->sp = 1) 131d4afb5ceSopenharmony_ci * 132d4afb5ceSopenharmony_ci * recipients[] LEJPCB_ARRAY_END 133d4afb5ceSopenharmony_ci * 134d4afb5ceSopenharmony_ci * iv LEJPCB_PAIR_NAME 135d4afb5ceSopenharmony_ci * iv LEJPCB_VAL_STR_START 136d4afb5ceSopenharmony_ci * iv LEJPCB_VAL_STR_END 137d4afb5ceSopenharmony_ci * ciphertext LEJPCB_PAIR_NAME 138d4afb5ceSopenharmony_ci * ciphertext LEJPCB_VAL_STR_START 139d4afb5ceSopenharmony_ci * ciphertext LEJPCB_VAL_STR_END 140d4afb5ceSopenharmony_ci * tag LEJPCB_PAIR_NAME 141d4afb5ceSopenharmony_ci * tag LEJPCB_VAL_STR_START 142d4afb5ceSopenharmony_ci * tag LEJPCB_VAL_STR_END 143d4afb5ceSopenharmony_ci * 144d4afb5ceSopenharmony_ci * tag LEJPCB_OBJECT_END 145d4afb5ceSopenharmony_ci * tag LEJPCB_COMPLETE 146d4afb5ceSopenharmony_ci * tag LEJPCB_DESTRUCTED 147d4afb5ceSopenharmony_ci * 148d4afb5ceSopenharmony_ci */ 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci/* 151d4afb5ceSopenharmony_ci * RFC7516 7.2.2 152d4afb5ceSopenharmony_ci * 153d4afb5ceSopenharmony_ci * Note that when using the flattened syntax, just as when using the 154d4afb5ceSopenharmony_ci * general syntax, any unprotected Header Parameter values can reside in 155d4afb5ceSopenharmony_ci * either the "unprotected" member or the "header" member, or in both. 156d4afb5ceSopenharmony_ci */ 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_cistatic signed char 159d4afb5ceSopenharmony_cilws_jws_jose_cb(struct lejp_ctx *ctx, char reason) 160d4afb5ceSopenharmony_ci{ 161d4afb5ceSopenharmony_ci struct jose_cb_args *args = (struct jose_cb_args *)ctx->user; 162d4afb5ceSopenharmony_ci int n; //, dest; 163d4afb5ceSopenharmony_ci 164d4afb5ceSopenharmony_ci /* 165d4afb5ceSopenharmony_ci * In JOSE JSON, the element "epk" contains a fully-formed JWK. 166d4afb5ceSopenharmony_ci * 167d4afb5ceSopenharmony_ci * For JOSE paths beginning "epk.", we pass them through to a JWK 168d4afb5ceSopenharmony_ci * LEJP subcontext to parse using the JWK parser directly. 169d4afb5ceSopenharmony_ci */ 170d4afb5ceSopenharmony_ci 171d4afb5ceSopenharmony_ci if (args->is_jwe && !strncmp(ctx->path, "epk.", 4)) { 172d4afb5ceSopenharmony_ci memcpy(args->jwk_jctx.path, ctx->path + 4, 173d4afb5ceSopenharmony_ci sizeof(ctx->path) - 4); 174d4afb5ceSopenharmony_ci memcpy(args->jwk_jctx.buf, ctx->buf, ctx->npos); 175d4afb5ceSopenharmony_ci args->jwk_jctx.npos = ctx->npos; 176d4afb5ceSopenharmony_ci 177d4afb5ceSopenharmony_ci if (!ctx->path_match) 178d4afb5ceSopenharmony_ci args->jwk_jctx.path_match = 0; 179d4afb5ceSopenharmony_ci lejp_check_path_match(&args->jwk_jctx); 180d4afb5ceSopenharmony_ci 181d4afb5ceSopenharmony_ci if (args->jwk_jctx.path_match) 182d4afb5ceSopenharmony_ci args->jwk_jctx.pst[args->jwk_jctx.pst_sp]. 183d4afb5ceSopenharmony_ci callback(&args->jwk_jctx, reason); 184d4afb5ceSopenharmony_ci } 185d4afb5ceSopenharmony_ci 186d4afb5ceSopenharmony_ci // lwsl_notice("%s: %s %d (%d)\n", __func__, ctx->path, reason, ctx->sp); 187d4afb5ceSopenharmony_ci 188d4afb5ceSopenharmony_ci /* at the end of each recipients[] entry, bump recipients count */ 189d4afb5ceSopenharmony_ci 190d4afb5ceSopenharmony_ci if (args->is_jwe && reason == LEJPCB_OBJECT_END && ctx->sp == 1 && 191d4afb5ceSopenharmony_ci !strcmp(ctx->path, "recipients[]")) 192d4afb5ceSopenharmony_ci args->jose->recipients++; 193d4afb5ceSopenharmony_ci 194d4afb5ceSopenharmony_ci if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match) 195d4afb5ceSopenharmony_ci return 0; 196d4afb5ceSopenharmony_ci 197d4afb5ceSopenharmony_ci //dest = ctx->path_match - 1; 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci switch (ctx->path_match - 1) { 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci /* strings */ 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ci case LJJHI_ALG: /* REQUIRED */ 204d4afb5ceSopenharmony_ci 205d4afb5ceSopenharmony_ci /* 206d4afb5ceSopenharmony_ci * look up whether we support this alg and point the caller at 207d4afb5ceSopenharmony_ci * its definition if so 208d4afb5ceSopenharmony_ci */ 209d4afb5ceSopenharmony_ci 210d4afb5ceSopenharmony_ci if (!args->is_jwe && 211d4afb5ceSopenharmony_ci lws_gencrypto_jws_alg_to_definition(ctx->buf, 212d4afb5ceSopenharmony_ci &args->jose->alg)) { 213d4afb5ceSopenharmony_ci lwsl_notice("%s: unknown alg '%s'\n", __func__, 214d4afb5ceSopenharmony_ci ctx->buf); 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci return -1; 217d4afb5ceSopenharmony_ci } 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_ci if (args->is_jwe && 220d4afb5ceSopenharmony_ci lws_gencrypto_jwe_alg_to_definition(ctx->buf, 221d4afb5ceSopenharmony_ci &args->jose->alg)) { 222d4afb5ceSopenharmony_ci lwsl_notice("%s: unknown JWE alg '%s'\n", __func__, 223d4afb5ceSopenharmony_ci ctx->buf); 224d4afb5ceSopenharmony_ci 225d4afb5ceSopenharmony_ci return -1; 226d4afb5ceSopenharmony_ci } 227d4afb5ceSopenharmony_ci 228d4afb5ceSopenharmony_ci return 0; 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_ci case LJJHI_TYP: /* Optional: string: media type */ 231d4afb5ceSopenharmony_ci lws_strnncpy(args->jose->typ, ctx->buf, ctx->npos, 232d4afb5ceSopenharmony_ci sizeof(args->jose->typ)); 233d4afb5ceSopenharmony_ci break; 234d4afb5ceSopenharmony_ci 235d4afb5ceSopenharmony_ci case LJJHI_JKU: /* Optional: string */ 236d4afb5ceSopenharmony_ci case LJJHI_KID: /* Optional: string */ 237d4afb5ceSopenharmony_ci case LJJHI_X5U: /* Optional: string: url of public key cert / chain */ 238d4afb5ceSopenharmony_ci case LJJHI_CTY: /* Optional: string: content media type */ 239d4afb5ceSopenharmony_ci 240d4afb5ceSopenharmony_ci /* base64 */ 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_ci case LJJHI_X5C: /* Optional: base64 (NOT -url): actual cert */ 243d4afb5ceSopenharmony_ci 244d4afb5ceSopenharmony_ci /* base64-url */ 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci case LJJHI_X5T: /* Optional: base64url: SHA-1 of actual cert */ 247d4afb5ceSopenharmony_ci case LJJHI_X5T_S256: /* Optional: base64url: SHA-256 of actual cert */ 248d4afb5ceSopenharmony_ci 249d4afb5ceSopenharmony_ci /* array of strings */ 250d4afb5ceSopenharmony_ci 251d4afb5ceSopenharmony_ci case LJJHI_CRIT: /* Optional for send, REQUIRED: array of strings: 252d4afb5ceSopenharmony_ci * mustn't contain standardized strings or null set */ 253d4afb5ceSopenharmony_ci break; 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci /* jwk child */ 256d4afb5ceSopenharmony_ci 257d4afb5ceSopenharmony_ci case LJJHI_JWK: /* Optional: jwk JSON object: public key: */ 258d4afb5ceSopenharmony_ci 259d4afb5ceSopenharmony_ci /* past here, JWE only */ 260d4afb5ceSopenharmony_ci 261d4afb5ceSopenharmony_ci case LJJHI_RECIPS_HDR: 262d4afb5ceSopenharmony_ci if (!args->is_jwe) { 263d4afb5ceSopenharmony_ci lwsl_info("%s: recipients in jws\n", __func__); 264d4afb5ceSopenharmony_ci return -1; 265d4afb5ceSopenharmony_ci } 266d4afb5ceSopenharmony_ci args->recipients_array = 1; 267d4afb5ceSopenharmony_ci break; 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_ci case LJJHI_RECIPS_HDR_ALG: 270d4afb5ceSopenharmony_ci case LJJHI_RECIPS_HDR_KID: 271d4afb5ceSopenharmony_ci break; 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ci case LJJHI_RECIPS_EKEY: 274d4afb5ceSopenharmony_ci if (!args->is_jwe) { 275d4afb5ceSopenharmony_ci lwsl_info("%s: recipients in jws\n", __func__); 276d4afb5ceSopenharmony_ci return -1; 277d4afb5ceSopenharmony_ci } 278d4afb5ceSopenharmony_ci args->recipients_array = 1; 279d4afb5ceSopenharmony_ci //dest = ; 280d4afb5ceSopenharmony_ci goto append_string; 281d4afb5ceSopenharmony_ci 282d4afb5ceSopenharmony_ci case LJJHI_ENC: /* JWE only: Mandatory: string */ 283d4afb5ceSopenharmony_ci if (!args->is_jwe) { 284d4afb5ceSopenharmony_ci lwsl_info("%s: enc in jws\n", __func__); 285d4afb5ceSopenharmony_ci return -1; 286d4afb5ceSopenharmony_ci } 287d4afb5ceSopenharmony_ci if (lws_gencrypto_jwe_enc_to_definition(ctx->buf, 288d4afb5ceSopenharmony_ci &args->jose->enc_alg)) { 289d4afb5ceSopenharmony_ci lwsl_notice("%s: unknown enc '%s'\n", __func__, 290d4afb5ceSopenharmony_ci ctx->buf); 291d4afb5ceSopenharmony_ci 292d4afb5ceSopenharmony_ci return -1; 293d4afb5ceSopenharmony_ci } 294d4afb5ceSopenharmony_ci break; 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_ci case LJJHI_ZIP: /* JWE only: Optional: string ("DEF" = deflate) */ 297d4afb5ceSopenharmony_ci if (!args->is_jwe) 298d4afb5ceSopenharmony_ci return -1; 299d4afb5ceSopenharmony_ci goto append_string; 300d4afb5ceSopenharmony_ci 301d4afb5ceSopenharmony_ci case LJJHI_EPK: /* Additional arg for JWE ECDH */ 302d4afb5ceSopenharmony_ci if (!args->is_jwe) 303d4afb5ceSopenharmony_ci return -1; 304d4afb5ceSopenharmony_ci /* Ephemeral key... this JSON subsection is actually a JWK */ 305d4afb5ceSopenharmony_ci lwsl_err("LJJHI_EPK\n"); 306d4afb5ceSopenharmony_ci break; 307d4afb5ceSopenharmony_ci 308d4afb5ceSopenharmony_ci case LJJHI_APU: /* Additional arg for JWE ECDH */ 309d4afb5ceSopenharmony_ci if (!args->is_jwe) 310d4afb5ceSopenharmony_ci return -1; 311d4afb5ceSopenharmony_ci /* Agreement Party U */ 312d4afb5ceSopenharmony_ci goto append_string; 313d4afb5ceSopenharmony_ci 314d4afb5ceSopenharmony_ci case LJJHI_APV: /* Additional arg for JWE ECDH */ 315d4afb5ceSopenharmony_ci if (!args->is_jwe) 316d4afb5ceSopenharmony_ci return -1; 317d4afb5ceSopenharmony_ci /* Agreement Party V */ 318d4afb5ceSopenharmony_ci goto append_string; 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_ci case LJJHI_IV: /* Additional arg for JWE AES */ 321d4afb5ceSopenharmony_ci if (!args->is_jwe) 322d4afb5ceSopenharmony_ci return -1; 323d4afb5ceSopenharmony_ci goto append_string; 324d4afb5ceSopenharmony_ci 325d4afb5ceSopenharmony_ci case LJJHI_TAG: /* Additional arg for JWE AES */ 326d4afb5ceSopenharmony_ci if (!args->is_jwe) 327d4afb5ceSopenharmony_ci return -1; 328d4afb5ceSopenharmony_ci goto append_string; 329d4afb5ceSopenharmony_ci 330d4afb5ceSopenharmony_ci case LJJHI_P2S: /* Additional arg for JWE PBES2 */ 331d4afb5ceSopenharmony_ci if (!args->is_jwe) 332d4afb5ceSopenharmony_ci return -1; 333d4afb5ceSopenharmony_ci goto append_string; 334d4afb5ceSopenharmony_ci case LJJHI_P2C: /* Additional arg for JWE PBES2 */ 335d4afb5ceSopenharmony_ci if (!args->is_jwe) 336d4afb5ceSopenharmony_ci return -1; 337d4afb5ceSopenharmony_ci goto append_string; 338d4afb5ceSopenharmony_ci 339d4afb5ceSopenharmony_ci /* ignore what we don't understand */ 340d4afb5ceSopenharmony_ci 341d4afb5ceSopenharmony_ci default: 342d4afb5ceSopenharmony_ci return 0; 343d4afb5ceSopenharmony_ci } 344d4afb5ceSopenharmony_ci 345d4afb5ceSopenharmony_ci return 0; 346d4afb5ceSopenharmony_ci 347d4afb5ceSopenharmony_ciappend_string: 348d4afb5ceSopenharmony_ci 349d4afb5ceSopenharmony_ci if (*args->temp_len < ctx->npos) { 350d4afb5ceSopenharmony_ci lwsl_err("%s: out of parsing space\n", __func__); 351d4afb5ceSopenharmony_ci return -1; 352d4afb5ceSopenharmony_ci } 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_ci if (!args->jose->e[ctx->path_match - 1].buf) { 355d4afb5ceSopenharmony_ci args->jose->e[ctx->path_match - 1].buf = (uint8_t *)args->temp; 356d4afb5ceSopenharmony_ci args->jose->e[ctx->path_match - 1].len = 0; 357d4afb5ceSopenharmony_ci } 358d4afb5ceSopenharmony_ci 359d4afb5ceSopenharmony_ci memcpy(args->temp, ctx->buf, ctx->npos); 360d4afb5ceSopenharmony_ci args->temp += ctx->npos; 361d4afb5ceSopenharmony_ci *args->temp_len -= ctx->npos; 362d4afb5ceSopenharmony_ci args->jose->e[ctx->path_match - 1].len += ctx->npos; 363d4afb5ceSopenharmony_ci 364d4afb5ceSopenharmony_ci if (reason == LEJPCB_VAL_STR_END) { 365d4afb5ceSopenharmony_ci n = lws_b64_decode_string_len( 366d4afb5ceSopenharmony_ci (const char *)args->jose->e[ctx->path_match - 1].buf, 367d4afb5ceSopenharmony_ci (int)args->jose->e[ctx->path_match - 1].len, 368d4afb5ceSopenharmony_ci (char *)args->jose->e[ctx->path_match - 1].buf, 369d4afb5ceSopenharmony_ci (int)args->jose->e[ctx->path_match - 1].len + 1); 370d4afb5ceSopenharmony_ci if (n < 0) { 371d4afb5ceSopenharmony_ci lwsl_err("%s: b64 decode failed\n", __func__); 372d4afb5ceSopenharmony_ci return -1; 373d4afb5ceSopenharmony_ci } 374d4afb5ceSopenharmony_ci 375d4afb5ceSopenharmony_ci args->temp -= (int)args->jose->e[ctx->path_match - 1].len - n - 1; 376d4afb5ceSopenharmony_ci *args->temp_len += 377d4afb5ceSopenharmony_ci (int)args->jose->e[ctx->path_match - 1].len - n - 1; 378d4afb5ceSopenharmony_ci 379d4afb5ceSopenharmony_ci args->jose->e[ctx->path_match - 1].len = (uint32_t)n; 380d4afb5ceSopenharmony_ci } 381d4afb5ceSopenharmony_ci 382d4afb5ceSopenharmony_ci return 0; 383d4afb5ceSopenharmony_ci} 384d4afb5ceSopenharmony_ci 385d4afb5ceSopenharmony_civoid 386d4afb5ceSopenharmony_cilws_jose_init(struct lws_jose *jose) 387d4afb5ceSopenharmony_ci{ 388d4afb5ceSopenharmony_ci memset(jose, 0, sizeof(*jose)); 389d4afb5ceSopenharmony_ci} 390d4afb5ceSopenharmony_ci 391d4afb5ceSopenharmony_cistatic void 392d4afb5ceSopenharmony_cilws_jose_recip_destroy(struct lws_jws_recpient *r) 393d4afb5ceSopenharmony_ci{ 394d4afb5ceSopenharmony_ci lws_jwk_destroy(&r->jwk_ephemeral); 395d4afb5ceSopenharmony_ci lws_jwk_destroy(&r->jwk); 396d4afb5ceSopenharmony_ci} 397d4afb5ceSopenharmony_ci 398d4afb5ceSopenharmony_civoid 399d4afb5ceSopenharmony_cilws_jose_destroy(struct lws_jose *jose) 400d4afb5ceSopenharmony_ci{ 401d4afb5ceSopenharmony_ci int n; 402d4afb5ceSopenharmony_ci 403d4afb5ceSopenharmony_ci for (n = 0; n < (int)LWS_ARRAY_SIZE(jose->recipient); n++) 404d4afb5ceSopenharmony_ci lws_jose_recip_destroy(&jose->recipient[n]); 405d4afb5ceSopenharmony_ci} 406d4afb5ceSopenharmony_ci 407d4afb5ceSopenharmony_cistatic int 408d4afb5ceSopenharmony_cilws_jose_parse(struct lws_jose *jose, const uint8_t *buf, int n, 409d4afb5ceSopenharmony_ci char *temp, int *temp_len, int is_jwe) 410d4afb5ceSopenharmony_ci{ 411d4afb5ceSopenharmony_ci struct lejp_ctx jctx; 412d4afb5ceSopenharmony_ci struct jose_cb_args args; 413d4afb5ceSopenharmony_ci int m; 414d4afb5ceSopenharmony_ci 415d4afb5ceSopenharmony_ci if (is_jwe) { 416d4afb5ceSopenharmony_ci /* prepare a context for JOSE epk ephemeral jwk parsing */ 417d4afb5ceSopenharmony_ci lws_jwk_init_jps(&args.jps, 418d4afb5ceSopenharmony_ci &jose->recipient[jose->recipients].jwk_ephemeral, 419d4afb5ceSopenharmony_ci NULL, NULL); 420d4afb5ceSopenharmony_ci lejp_construct(&args.jwk_jctx, cb_jwk, &args.jps, 421d4afb5ceSopenharmony_ci jwk_tok, LWS_ARRAY_SIZE(jwk_tok)); 422d4afb5ceSopenharmony_ci } 423d4afb5ceSopenharmony_ci 424d4afb5ceSopenharmony_ci args.is_jwe = (unsigned int)is_jwe; 425d4afb5ceSopenharmony_ci args.temp = temp; 426d4afb5ceSopenharmony_ci args.temp_len = temp_len; 427d4afb5ceSopenharmony_ci args.jose = jose; 428d4afb5ceSopenharmony_ci args.recip = 0; 429d4afb5ceSopenharmony_ci args.recipients_array = 0; 430d4afb5ceSopenharmony_ci jose->recipients = 0; 431d4afb5ceSopenharmony_ci 432d4afb5ceSopenharmony_ci lejp_construct(&jctx, lws_jws_jose_cb, &args, jws_jose, 433d4afb5ceSopenharmony_ci LWS_ARRAY_SIZE(jws_jose)); 434d4afb5ceSopenharmony_ci 435d4afb5ceSopenharmony_ci m = lejp_parse(&jctx, (uint8_t *)buf, n); 436d4afb5ceSopenharmony_ci lejp_destruct(&jctx); 437d4afb5ceSopenharmony_ci if (m < 0) { 438d4afb5ceSopenharmony_ci lwsl_notice("%s: parse returned %d\n", __func__, m); 439d4afb5ceSopenharmony_ci return -1; 440d4afb5ceSopenharmony_ci } 441d4afb5ceSopenharmony_ci 442d4afb5ceSopenharmony_ci if (!args.recipients_array && jose->recipient[0].unprot[LJJHI_ALG].buf) 443d4afb5ceSopenharmony_ci /* if no explicit recipients[], we got one */ 444d4afb5ceSopenharmony_ci jose->recipients++; 445d4afb5ceSopenharmony_ci 446d4afb5ceSopenharmony_ci return 0; 447d4afb5ceSopenharmony_ci} 448d4afb5ceSopenharmony_ci 449d4afb5ceSopenharmony_ciint 450d4afb5ceSopenharmony_cilws_jws_parse_jose(struct lws_jose *jose, 451d4afb5ceSopenharmony_ci const char *buf, int len, char *temp, int *temp_len) 452d4afb5ceSopenharmony_ci{ 453d4afb5ceSopenharmony_ci return lws_jose_parse(jose, (const uint8_t *)buf, len, 454d4afb5ceSopenharmony_ci temp, temp_len, 0); 455d4afb5ceSopenharmony_ci} 456d4afb5ceSopenharmony_ci 457d4afb5ceSopenharmony_ciint 458d4afb5ceSopenharmony_cilws_jwe_parse_jose(struct lws_jose *jose, 459d4afb5ceSopenharmony_ci const char *buf, int len, char *temp, int *temp_len) 460d4afb5ceSopenharmony_ci{ 461d4afb5ceSopenharmony_ci return lws_jose_parse(jose, 462d4afb5ceSopenharmony_ci (const uint8_t *)buf, len, temp, temp_len, 1); 463d4afb5ceSopenharmony_ci} 464d4afb5ceSopenharmony_ci 465d4afb5ceSopenharmony_ciint 466d4afb5ceSopenharmony_cilws_jose_render(struct lws_jose *jose, struct lws_jwk *aux_jwk, 467d4afb5ceSopenharmony_ci char *out, size_t out_len) 468d4afb5ceSopenharmony_ci{ 469d4afb5ceSopenharmony_ci struct lws_jwk *jwk; 470d4afb5ceSopenharmony_ci char *end = out + out_len - 1; 471d4afb5ceSopenharmony_ci int n, m, f, sub = 0, vl; 472d4afb5ceSopenharmony_ci 473d4afb5ceSopenharmony_ci /* JOSE requires an alg */ 474d4afb5ceSopenharmony_ci if (!jose->alg || !jose->alg->alg) 475d4afb5ceSopenharmony_ci goto bail; 476d4afb5ceSopenharmony_ci 477d4afb5ceSopenharmony_ci *out++ = '{'; 478d4afb5ceSopenharmony_ci 479d4afb5ceSopenharmony_ci for (n = 0; n < LWS_COUNT_JOSE_HDR_ELEMENTS; n++) { 480d4afb5ceSopenharmony_ci switch (n) { 481d4afb5ceSopenharmony_ci 482d4afb5ceSopenharmony_ci /* strings */ 483d4afb5ceSopenharmony_ci 484d4afb5ceSopenharmony_ci case LJJHI_ALG: /* REQUIRED */ 485d4afb5ceSopenharmony_ci case LJJHI_JKU: /* Optional: string */ 486d4afb5ceSopenharmony_ci case LJJHI_KID: /* Optional: string */ 487d4afb5ceSopenharmony_ci case LJJHI_TYP: /* Optional: string: media type */ 488d4afb5ceSopenharmony_ci case LJJHI_CTY: /* Optional: string: content media type */ 489d4afb5ceSopenharmony_ci case LJJHI_X5U: /* Optional: string: pubkey cert / chain URL */ 490d4afb5ceSopenharmony_ci case LJJHI_ENC: /* JWE only: Optional: string */ 491d4afb5ceSopenharmony_ci case LJJHI_ZIP: /* JWE only: Optional: string ("DEF"=deflate) */ 492d4afb5ceSopenharmony_ci if (jose->e[n].buf) { 493d4afb5ceSopenharmony_ci out += lws_snprintf(out, lws_ptr_diff_size_t(end, out), 494d4afb5ceSopenharmony_ci "%s\"%s\":\"%s\"", sub ? ",\n" : "", 495d4afb5ceSopenharmony_ci jws_jose[n], jose->e[n].buf); 496d4afb5ceSopenharmony_ci sub = 1; 497d4afb5ceSopenharmony_ci } 498d4afb5ceSopenharmony_ci break; 499d4afb5ceSopenharmony_ci 500d4afb5ceSopenharmony_ci case LJJHI_X5T: /* Optional: base64url: SHA-1 of actual cert */ 501d4afb5ceSopenharmony_ci case LJJHI_X5T_S256: /* Optional: base64url: SHA-256 of cert */ 502d4afb5ceSopenharmony_ci case LJJHI_APU: /* Additional arg for JWE ECDH: b64url */ 503d4afb5ceSopenharmony_ci case LJJHI_APV: /* Additional arg for JWE ECDH: b64url */ 504d4afb5ceSopenharmony_ci case LJJHI_IV: /* Additional arg for JWE AES: b64url */ 505d4afb5ceSopenharmony_ci case LJJHI_TAG: /* Additional arg for JWE AES: b64url */ 506d4afb5ceSopenharmony_ci case LJJHI_P2S: /* Additional arg for JWE PBES2: b64url: salt */ 507d4afb5ceSopenharmony_ci if (jose->e[n].buf) { 508d4afb5ceSopenharmony_ci out += lws_snprintf(out, lws_ptr_diff_size_t(end, out), 509d4afb5ceSopenharmony_ci "%s\"%s\":\"", sub ? ",\n" : "", 510d4afb5ceSopenharmony_ci jws_jose[n]); 511d4afb5ceSopenharmony_ci sub = 1; 512d4afb5ceSopenharmony_ci m = lws_b64_encode_string_url((const char *) 513d4afb5ceSopenharmony_ci jose->e[n].buf, (int)jose->e[n].len, 514d4afb5ceSopenharmony_ci out, lws_ptr_diff(end, out)); 515d4afb5ceSopenharmony_ci if (m < 0) 516d4afb5ceSopenharmony_ci return -1; 517d4afb5ceSopenharmony_ci out += m; 518d4afb5ceSopenharmony_ci out += lws_snprintf(out, lws_ptr_diff_size_t(end, out), "\""); 519d4afb5ceSopenharmony_ci } 520d4afb5ceSopenharmony_ci break; 521d4afb5ceSopenharmony_ci 522d4afb5ceSopenharmony_ci case LJJHI_P2C: /* Additional arg for JWE PBES2: int: count */ 523d4afb5ceSopenharmony_ci break; /* don't support atm */ 524d4afb5ceSopenharmony_ci 525d4afb5ceSopenharmony_ci case LJJHI_X5C: /* Optional: base64 (NOT -url): actual cert */ 526d4afb5ceSopenharmony_ci if (jose->e[n].buf) { 527d4afb5ceSopenharmony_ci out += lws_snprintf(out, lws_ptr_diff_size_t(end, out), 528d4afb5ceSopenharmony_ci "%s\"%s\":\"", sub ? ",\n" : "", 529d4afb5ceSopenharmony_ci jws_jose[n]); 530d4afb5ceSopenharmony_ci sub = 1; 531d4afb5ceSopenharmony_ci m = lws_b64_encode_string((const char *) 532d4afb5ceSopenharmony_ci jose->e[n].buf, (int)jose->e[n].len, 533d4afb5ceSopenharmony_ci out, lws_ptr_diff(end, out)); 534d4afb5ceSopenharmony_ci if (m < 0) 535d4afb5ceSopenharmony_ci return -1; 536d4afb5ceSopenharmony_ci out += m; 537d4afb5ceSopenharmony_ci out += lws_snprintf(out, lws_ptr_diff_size_t(end, out), "\""); 538d4afb5ceSopenharmony_ci } 539d4afb5ceSopenharmony_ci break; 540d4afb5ceSopenharmony_ci 541d4afb5ceSopenharmony_ci case LJJHI_EPK: /* Additional arg for JWE ECDH: eph pubkey */ 542d4afb5ceSopenharmony_ci case LJJHI_JWK: /* Optional: jwk JSON object: public key: */ 543d4afb5ceSopenharmony_ci 544d4afb5ceSopenharmony_ci jwk = n == LJJHI_EPK ? &jose->recipient[0].jwk_ephemeral : aux_jwk; 545d4afb5ceSopenharmony_ci if (!jwk || !jwk->kty) 546d4afb5ceSopenharmony_ci break; 547d4afb5ceSopenharmony_ci 548d4afb5ceSopenharmony_ci out += lws_snprintf(out, lws_ptr_diff_size_t(end, out), "%s\"%s\":", 549d4afb5ceSopenharmony_ci sub ? ",\n" : "", jws_jose[n]); 550d4afb5ceSopenharmony_ci sub = 1; 551d4afb5ceSopenharmony_ci vl = lws_ptr_diff(end, out); 552d4afb5ceSopenharmony_ci m = lws_jwk_export(jwk, 0, out, &vl); 553d4afb5ceSopenharmony_ci if (m < 0) { 554d4afb5ceSopenharmony_ci lwsl_notice("%s: failed to export key\n", 555d4afb5ceSopenharmony_ci __func__); 556d4afb5ceSopenharmony_ci 557d4afb5ceSopenharmony_ci return -1; 558d4afb5ceSopenharmony_ci } 559d4afb5ceSopenharmony_ci out += m; 560d4afb5ceSopenharmony_ci break; 561d4afb5ceSopenharmony_ci 562d4afb5ceSopenharmony_ci case LJJHI_CRIT:/* Optional for send, REQUIRED: array of strings: 563d4afb5ceSopenharmony_ci * mustn't contain standardized strings or null set */ 564d4afb5ceSopenharmony_ci if (!jose->e[n].buf) 565d4afb5ceSopenharmony_ci break; 566d4afb5ceSopenharmony_ci 567d4afb5ceSopenharmony_ci out += lws_snprintf(out, lws_ptr_diff_size_t(end, out), 568d4afb5ceSopenharmony_ci "%s\"%s\":[", sub ? ",\n" : "", jws_jose[n]); 569d4afb5ceSopenharmony_ci sub = 1; 570d4afb5ceSopenharmony_ci 571d4afb5ceSopenharmony_ci m = 0; 572d4afb5ceSopenharmony_ci f = 1; 573d4afb5ceSopenharmony_ci while ((unsigned int)m < jose->e[n].len && (end - out) > 1) { 574d4afb5ceSopenharmony_ci if (jose->e[n].buf[m] == ' ') { 575d4afb5ceSopenharmony_ci if (!f) 576d4afb5ceSopenharmony_ci *out++ = '\"'; 577d4afb5ceSopenharmony_ci 578d4afb5ceSopenharmony_ci m++; 579d4afb5ceSopenharmony_ci f = 1; 580d4afb5ceSopenharmony_ci continue; 581d4afb5ceSopenharmony_ci } 582d4afb5ceSopenharmony_ci 583d4afb5ceSopenharmony_ci if (f) { 584d4afb5ceSopenharmony_ci if (m) 585d4afb5ceSopenharmony_ci *out++ = ','; 586d4afb5ceSopenharmony_ci *out++ = '\"'; 587d4afb5ceSopenharmony_ci f = 0; 588d4afb5ceSopenharmony_ci } 589d4afb5ceSopenharmony_ci 590d4afb5ceSopenharmony_ci *out++ = (char)jose->e[n].buf[m]; 591d4afb5ceSopenharmony_ci m++; 592d4afb5ceSopenharmony_ci } 593d4afb5ceSopenharmony_ci 594d4afb5ceSopenharmony_ci break; 595d4afb5ceSopenharmony_ci } 596d4afb5ceSopenharmony_ci } 597d4afb5ceSopenharmony_ci 598d4afb5ceSopenharmony_ci *out++ = '}'; 599d4afb5ceSopenharmony_ci 600d4afb5ceSopenharmony_ci if (out > end - 2) 601d4afb5ceSopenharmony_ci return -1; 602d4afb5ceSopenharmony_ci 603d4afb5ceSopenharmony_ci return lws_ptr_diff(out_len, (end - out)) - 1; 604d4afb5ceSopenharmony_ci 605d4afb5ceSopenharmony_cibail: 606d4afb5ceSopenharmony_ci return -1; 607d4afb5ceSopenharmony_ci} 608