1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2021 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 * cose_sign handling 25d4afb5ceSopenharmony_ci * 26d4afb5ceSopenharmony_ci * Validation: 27d4afb5ceSopenharmony_ci * 28d4afb5ceSopenharmony_ci * - we put all our pieces and results in an lwsac in the parse state object 29d4afb5ceSopenharmony_ci * 30d4afb5ceSopenharmony_ci * - we collect pieces needed for sig validation into lwsac elements 31d4afb5ceSopenharmony_ci * 32d4afb5ceSopenharmony_ci * - we go through each signature making discrete results in the lwsac for 33d4afb5ceSopenharmony_ci * the user code to assess 34d4afb5ceSopenharmony_ci */ 35d4afb5ceSopenharmony_ci 36d4afb5ceSopenharmony_ci#include "private-lib-core.h" 37d4afb5ceSopenharmony_ci#include "private-lib-cose.h" 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_ciconst uint8_t *sig_mctx[] = { (uint8_t *)"", 40d4afb5ceSopenharmony_ci (uint8_t *)"\x85\x69""Signature", 41d4afb5ceSopenharmony_ci (uint8_t *)"\x84\x6a""Signature1", 42d4afb5ceSopenharmony_ci (uint8_t *)"\x85\x6f""CounterSignature", 43d4afb5ceSopenharmony_ci (uint8_t *)"\x84\x63""MAC", 44d4afb5ceSopenharmony_ci (uint8_t *)"\x84\x64""MAC0", 45d4afb5ceSopenharmony_ci}; 46d4afb5ceSopenharmony_ciuint8_t sig_mctx_len[] = { 0, 11, 12, 17, 5, 6 }; 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_cistruct alg_names { 49d4afb5ceSopenharmony_ci const char *name; 50d4afb5ceSopenharmony_ci cose_param_t alg; 51d4afb5ceSopenharmony_ci} alg_names[] = { 52d4afb5ceSopenharmony_ci { "ES256", LWSCOSE_WKAECDSA_ALG_ES256 }, 53d4afb5ceSopenharmony_ci { "ES384", LWSCOSE_WKAECDSA_ALG_ES384 }, 54d4afb5ceSopenharmony_ci { "ES512", LWSCOSE_WKAECDSA_ALG_ES512 }, 55d4afb5ceSopenharmony_ci { "HS256_64", LWSCOSE_WKAHMAC_256_64 }, 56d4afb5ceSopenharmony_ci { "HS256", LWSCOSE_WKAHMAC_256_256 }, 57d4afb5ceSopenharmony_ci { "HS384", LWSCOSE_WKAHMAC_384_384 }, 58d4afb5ceSopenharmony_ci { "HS512", LWSCOSE_WKAHMAC_512_512 }, 59d4afb5ceSopenharmony_ci { "RS256", LWSCOSE_WKARSA_ALG_RS256 }, 60d4afb5ceSopenharmony_ci { "RS384", LWSCOSE_WKARSA_ALG_RS384 }, 61d4afb5ceSopenharmony_ci { "RS512", LWSCOSE_WKARSA_ALG_RS512 }, 62d4afb5ceSopenharmony_ci}; 63d4afb5ceSopenharmony_ci 64d4afb5ceSopenharmony_ci/* 65d4afb5ceSopenharmony_ci * The Sig_structure plaintext is new temp CBOR made up from pieces from the 66d4afb5ceSopenharmony_ci * cose_sign, cose_signature, and payload in a specific order 67d4afb5ceSopenharmony_ci * 68d4afb5ceSopenharmony_ci * tstr context string 69d4afb5ceSopenharmony_ci * bstr 0-len or protected body headers 70d4afb5ceSopenharmony_ci * bstr (Missing for sign1) 0-len or protected signer headers 71d4afb5ceSopenharmony_ci * bstr 0-len or protected application part 72d4afb5ceSopenharmony_ci * bstr the payload 73d4afb5ceSopenharmony_ci * 74d4afb5ceSopenharmony_ci * We are getting CBOR with an optional outer tag and then an array of exactly 75d4afb5ceSopenharmony_ci * 4 items in a fixed order 76d4afb5ceSopenharmony_ci * 77d4afb5ceSopenharmony_ci * [ 78d4afb5ceSopenharmony_ci * protected headers: bstr containing a map (captured as CBOR in cps->ph[]) 79d4afb5ceSopenharmony_ci * unprotected: map: for sign1, eg, the alg (!?), the kid 80d4afb5ceSopenharmony_ci * payload: bstr 81d4afb5ceSopenharmony_ci * if sign: signatures: [ cose_signature struct array, 82d4afb5ceSopenharmony_ci * each is a 3-element array 83d4afb5ceSopenharmony_ci * [ 84d4afb5ceSopenharmony_ci * protected: bstr containing a map: (eg, the alg) (captured as CBOR) 85d4afb5ceSopenharmony_ci * unprotected: map: (eg, the kid) 86d4afb5ceSopenharmony_ci * signature: bstr 87d4afb5ceSopenharmony_ci * ] 88d4afb5ceSopenharmony_ci * if sign1: bstr containing signature 89d4afb5ceSopenharmony_ci * ] 90d4afb5ceSopenharmony_ci * 91d4afb5ceSopenharmony_ci * The last signatures field may be an array of signatures, or a single 92d4afb5ceSopenharmony_ci * cose_signature object for cose_sign1. 93d4afb5ceSopenharmony_ci * 94d4afb5ceSopenharmony_ci * For cose_sign1, we know the signature alg before the payload and can do it 95d4afb5ceSopenharmony_ci * in a single pass. But for sign, we do not know the signature algs until 96d4afb5ceSopenharmony_ci * after the payload, which is an unfortunate oversight in cose_sign, meaning we 97d4afb5ceSopenharmony_ci * cannot hash the payload one or more ways in a single pass. 98d4afb5ceSopenharmony_ci */ 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci#if defined(VERBOSE) 101d4afb5ceSopenharmony_ciconst char *cose_sections[] = { 102d4afb5ceSopenharmony_ci "ST_UNKNOWN", 103d4afb5ceSopenharmony_ci 104d4afb5ceSopenharmony_ci "ST_OUTER_PROTECTED", 105d4afb5ceSopenharmony_ci "ST_OUTER_UNPROTECTED", 106d4afb5ceSopenharmony_ci "ST_OUTER_PAYLOAD", 107d4afb5ceSopenharmony_ci "ST_OUTER_SIGN1_SIGNATURE", 108d4afb5ceSopenharmony_ci 109d4afb5ceSopenharmony_ci "ST_OUTER_SIGN_SIGARRAY", 110d4afb5ceSopenharmony_ci 111d4afb5ceSopenharmony_ci "ST_OUTER_MACTAG", 112d4afb5ceSopenharmony_ci 113d4afb5ceSopenharmony_ci "ST_INNER_PROTECTED", 114d4afb5ceSopenharmony_ci "ST_INNER_UNPROTECTED", 115d4afb5ceSopenharmony_ci "ST_INNER_SIGNATURE", 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_ci "ST_INNER_EXCESS", 118d4afb5ceSopenharmony_ci}; 119d4afb5ceSopenharmony_ci#endif 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ciconst char * 122d4afb5ceSopenharmony_cilws_cose_alg_to_name(cose_param_t alg) 123d4afb5ceSopenharmony_ci{ 124d4afb5ceSopenharmony_ci size_t n; 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci for (n = 0; n < LWS_ARRAY_SIZE(alg_names); n++) 127d4afb5ceSopenharmony_ci if (alg_names[n].alg == alg) 128d4afb5ceSopenharmony_ci return alg_names[n].name; 129d4afb5ceSopenharmony_ci 130d4afb5ceSopenharmony_ci return "unknown_alg"; 131d4afb5ceSopenharmony_ci} 132d4afb5ceSopenharmony_ci 133d4afb5ceSopenharmony_cicose_param_t 134d4afb5ceSopenharmony_cilws_cose_name_to_alg(const char *name) 135d4afb5ceSopenharmony_ci{ 136d4afb5ceSopenharmony_ci size_t n; 137d4afb5ceSopenharmony_ci 138d4afb5ceSopenharmony_ci for (n = 0; n < LWS_ARRAY_SIZE(alg_names); n++) 139d4afb5ceSopenharmony_ci if (!strcmp(alg_names[n].name, name)) 140d4afb5ceSopenharmony_ci return alg_names[n].alg; 141d4afb5ceSopenharmony_ci 142d4afb5ceSopenharmony_ci return 0; 143d4afb5ceSopenharmony_ci} 144d4afb5ceSopenharmony_ci 145d4afb5ceSopenharmony_cistatic size_t 146d4afb5ceSopenharmony_cibstr_len(uint8_t *t, size_t buflen, uint8_t opcode, uint64_t len) 147d4afb5ceSopenharmony_ci{ 148d4afb5ceSopenharmony_ci uint8_t *ot = t; 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci if (buflen < 9) 151d4afb5ceSopenharmony_ci return 0; 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci if (len < 24) { 154d4afb5ceSopenharmony_ci *t = (uint8_t)(opcode | len); 155d4afb5ceSopenharmony_ci 156d4afb5ceSopenharmony_ci return 1; 157d4afb5ceSopenharmony_ci } 158d4afb5ceSopenharmony_ci if (len < 256) { 159d4afb5ceSopenharmony_ci *t++ = opcode | LWS_CBOR_1; 160d4afb5ceSopenharmony_ci goto b; 161d4afb5ceSopenharmony_ci } 162d4afb5ceSopenharmony_ci if (len < 65536) { 163d4afb5ceSopenharmony_ci *t++ = opcode | LWS_CBOR_2; 164d4afb5ceSopenharmony_ci goto b1; 165d4afb5ceSopenharmony_ci } 166d4afb5ceSopenharmony_ci if (len < 0xffffffffu) { 167d4afb5ceSopenharmony_ci *t++ = opcode | LWS_CBOR_4; 168d4afb5ceSopenharmony_ci goto b2; 169d4afb5ceSopenharmony_ci } 170d4afb5ceSopenharmony_ci 171d4afb5ceSopenharmony_ci *t++ = opcode | LWS_CBOR_8; 172d4afb5ceSopenharmony_ci 173d4afb5ceSopenharmony_ci *t++ = (uint8_t)(len >> 56); 174d4afb5ceSopenharmony_ci *t++ = (uint8_t)(len >> 48); 175d4afb5ceSopenharmony_ci *t++ = (uint8_t)(len >> 40); 176d4afb5ceSopenharmony_ci *t++ = (uint8_t)(len >> 32); 177d4afb5ceSopenharmony_ci 178d4afb5ceSopenharmony_cib2: 179d4afb5ceSopenharmony_ci *t++ = (uint8_t)(len >> 24); 180d4afb5ceSopenharmony_ci *t++ = (uint8_t)(len >> 16); 181d4afb5ceSopenharmony_cib1: 182d4afb5ceSopenharmony_ci *t++ = (uint8_t)(len >> 8); 183d4afb5ceSopenharmony_cib: 184d4afb5ceSopenharmony_ci *t++ = (uint8_t)len; 185d4afb5ceSopenharmony_ci 186d4afb5ceSopenharmony_ci return lws_ptr_diff_size_t(t, ot); 187d4afb5ceSopenharmony_ci} 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_cistatic int 190d4afb5ceSopenharmony_ciapply_external(struct lws_cose_validate_context *cps) 191d4afb5ceSopenharmony_ci{ 192d4afb5ceSopenharmony_ci lws_cose_sig_alg_t *alg; 193d4afb5ceSopenharmony_ci uint8_t t[9]; 194d4afb5ceSopenharmony_ci 195d4afb5ceSopenharmony_ci alg = lws_container_of(cps->algs.head, lws_cose_sig_alg_t, list); 196d4afb5ceSopenharmony_ci if (!alg) 197d4afb5ceSopenharmony_ci /* expected if no key */ 198d4afb5ceSopenharmony_ci return 0; 199d4afb5ceSopenharmony_ci 200d4afb5ceSopenharmony_ci /* get the external payload first, if any indicated */ 201d4afb5ceSopenharmony_ci 202d4afb5ceSopenharmony_ci if (cps->info.ext_len) { 203d4afb5ceSopenharmony_ci lws_cose_sig_ext_pay_t ex; 204d4afb5ceSopenharmony_ci size_t s; 205d4afb5ceSopenharmony_ci 206d4afb5ceSopenharmony_ci s = bstr_len(t, sizeof(t), LWS_CBOR_MAJTYP_BSTR, 207d4afb5ceSopenharmony_ci cps->info.ext_len); 208d4afb5ceSopenharmony_ci if (lws_cose_val_alg_hash(alg, t, s)) 209d4afb5ceSopenharmony_ci return 1; 210d4afb5ceSopenharmony_ci 211d4afb5ceSopenharmony_ci memset(&ex, 0, sizeof(ex)); 212d4afb5ceSopenharmony_ci ex.cps = cps; 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci do { 215d4afb5ceSopenharmony_ci int n; 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_ci ex.xl = 0; 218d4afb5ceSopenharmony_ci n = cps->info.ext_cb(&ex); 219d4afb5ceSopenharmony_ci 220d4afb5ceSopenharmony_ci if (ex.xl && 221d4afb5ceSopenharmony_ci lws_cose_val_alg_hash(alg, ex.ext, ex.xl)) 222d4afb5ceSopenharmony_ci return 1; 223d4afb5ceSopenharmony_ci 224d4afb5ceSopenharmony_ci if (n == LCOSESIGEXTCB_RET_ERROR) 225d4afb5ceSopenharmony_ci return 1; 226d4afb5ceSopenharmony_ci 227d4afb5ceSopenharmony_ci if (n == LCOSESIGEXTCB_RET_FINISHED) 228d4afb5ceSopenharmony_ci break; 229d4afb5ceSopenharmony_ci } while (1); 230d4afb5ceSopenharmony_ci } 231d4afb5ceSopenharmony_ci 232d4afb5ceSopenharmony_ci return 0; 233d4afb5ceSopenharmony_ci} 234d4afb5ceSopenharmony_ci 235d4afb5ceSopenharmony_cistatic int 236d4afb5ceSopenharmony_cicreate_alg(struct lecp_ctx *ctx, struct lws_cose_validate_context *cps) 237d4afb5ceSopenharmony_ci{ 238d4afb5ceSopenharmony_ci lws_cose_validate_param_stack_t *sl = &cps->st[cps->sp], *sl0 = &cps->st[0]; 239d4afb5ceSopenharmony_ci lws_cose_validate_res_t *res; 240d4afb5ceSopenharmony_ci lws_cose_sig_alg_t *alg; 241d4afb5ceSopenharmony_ci lws_cose_key_t *ck; 242d4afb5ceSopenharmony_ci uint8_t *p; 243d4afb5ceSopenharmony_ci size_t s; 244d4afb5ceSopenharmony_ci 245d4afb5ceSopenharmony_ci /* with sign1, we can hash the payload in a 246d4afb5ceSopenharmony_ci * single pass */ 247d4afb5ceSopenharmony_ci 248d4afb5ceSopenharmony_ci ck = lws_cose_key_from_set(cps->info.keyset, sl->kid.buf, sl->kid.len); 249d4afb5ceSopenharmony_ci if (!ck) { 250d4afb5ceSopenharmony_ci lwsl_notice("%s: no key\n", __func__); 251d4afb5ceSopenharmony_ci lwsl_hexdump_notice(sl->kid.buf, sl->kid.len); 252d4afb5ceSopenharmony_ci goto no_key_or_alg; 253d4afb5ceSopenharmony_ci } 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci // lwsl_notice("%s: cps->alg %d\n", __func__, (int)cps->alg); 256d4afb5ceSopenharmony_ci 257d4afb5ceSopenharmony_ci alg = lws_cose_val_alg_create(cps->info.cx, ck, cps->st[0].alg, 258d4afb5ceSopenharmony_ci LWSCOSE_WKKO_VERIFY); 259d4afb5ceSopenharmony_ci if (!alg) { 260d4afb5ceSopenharmony_ci lwsl_info("%s: no alg\n", __func__); 261d4afb5ceSopenharmony_ci 262d4afb5ceSopenharmony_cino_key_or_alg: 263d4afb5ceSopenharmony_ci /* 264d4afb5ceSopenharmony_ci * We can't create the alg then, so we can't normally 265d4afb5ceSopenharmony_ci * create a result object. Create one especially for this 266d4afb5ceSopenharmony_ci * case and continue on 267d4afb5ceSopenharmony_ci */ 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_ci res = lws_zalloc(sizeof(*res), __func__); 270d4afb5ceSopenharmony_ci if (res) { 271d4afb5ceSopenharmony_ci res->result = -1001; 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ci lws_dll2_add_tail(&res->list, &cps->results); 274d4afb5ceSopenharmony_ci } 275d4afb5ceSopenharmony_ci 276d4afb5ceSopenharmony_ci return 0; 277d4afb5ceSopenharmony_ci } 278d4afb5ceSopenharmony_ci 279d4afb5ceSopenharmony_ci lws_dll2_add_tail(&alg->list, &cps->algs); 280d4afb5ceSopenharmony_ci 281d4afb5ceSopenharmony_ci /* 282d4afb5ceSopenharmony_ci * Hash step 1: The first hash content depends on 283d4afb5ceSopenharmony_ci * sign/sign1/csign/mac/mac0 constant bstr 284d4afb5ceSopenharmony_ci */ 285d4afb5ceSopenharmony_ci 286d4afb5ceSopenharmony_ci if (lws_cose_val_alg_hash(alg, sig_mctx[cps->info.sigtype], 287d4afb5ceSopenharmony_ci sig_mctx_len[cps->info.sigtype])) 288d4afb5ceSopenharmony_ci goto bail; 289d4afb5ceSopenharmony_ci 290d4afb5ceSopenharmony_ci /* 291d4afb5ceSopenharmony_ci * Hash step 2: A zero-length bstr, or a copy of the 292d4afb5ceSopenharmony_ci * OUTER protected headers 293d4afb5ceSopenharmony_ci * 294d4afb5ceSopenharmony_ci * A zero-entry map alone becomes a zero- 295d4afb5ceSopenharmony_ci * length bstr 296d4afb5ceSopenharmony_ci */ 297d4afb5ceSopenharmony_ci 298d4afb5ceSopenharmony_ci if (sl0->ph_pos[0] < 2) { 299d4afb5ceSopenharmony_ci /* nothing to speak of */ 300d4afb5ceSopenharmony_ci sl0->ph[0][0] = LWS_CBOR_MAJTYP_BSTR; 301d4afb5ceSopenharmony_ci p = &sl0->ph[0][0]; 302d4afb5ceSopenharmony_ci s = 1; 303d4afb5ceSopenharmony_ci } else { 304d4afb5ceSopenharmony_ci if (sl0->ph_pos[0] < 24) { 305d4afb5ceSopenharmony_ci sl0->ph[0][2] = (uint8_t) 306d4afb5ceSopenharmony_ci (LWS_CBOR_MAJTYP_BSTR | sl0->ph_pos[0]); 307d4afb5ceSopenharmony_ci p = &sl0->ph[0][2]; 308d4afb5ceSopenharmony_ci s = (size_t)sl0->ph_pos[0] + 1; 309d4afb5ceSopenharmony_ci } else { 310d4afb5ceSopenharmony_ci sl0->ph[0][1] = LWS_CBOR_MAJTYP_BSTR | 311d4afb5ceSopenharmony_ci LWS_CBOR_1; 312d4afb5ceSopenharmony_ci sl0->ph[0][2] = (uint8_t)sl0->ph_pos[0]; 313d4afb5ceSopenharmony_ci p = &sl0->ph[0][1]; 314d4afb5ceSopenharmony_ci s = (size_t)sl0->ph_pos[0] + 2; 315d4afb5ceSopenharmony_ci } 316d4afb5ceSopenharmony_ci } 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci if (lws_cose_val_alg_hash(alg, p, s)) 319d4afb5ceSopenharmony_ci goto bail; 320d4afb5ceSopenharmony_ci 321d4afb5ceSopenharmony_ci /* 322d4afb5ceSopenharmony_ci * Hash step 3: Protected signer headers (Elided for sign1) 323d4afb5ceSopenharmony_ci */ 324d4afb5ceSopenharmony_ci 325d4afb5ceSopenharmony_ci if (cps->info.sigtype == SIGTYPE_MULTI) { 326d4afb5ceSopenharmony_ci if (sl->ph_pos[2] < 2) { 327d4afb5ceSopenharmony_ci /* nothing to speak of */ 328d4afb5ceSopenharmony_ci sl->ph[2][0] = LWS_CBOR_MAJTYP_BSTR; 329d4afb5ceSopenharmony_ci p = &sl->ph[2][0]; 330d4afb5ceSopenharmony_ci s = 1; 331d4afb5ceSopenharmony_ci } else { 332d4afb5ceSopenharmony_ci if (sl->ph_pos[2] < 24) { 333d4afb5ceSopenharmony_ci sl->ph[2][2] = (uint8_t) 334d4afb5ceSopenharmony_ci (LWS_CBOR_MAJTYP_BSTR | sl->ph_pos[2]); 335d4afb5ceSopenharmony_ci p = &sl->ph[2][2]; 336d4afb5ceSopenharmony_ci s = (size_t)sl->ph_pos[2] + 1; 337d4afb5ceSopenharmony_ci } else { 338d4afb5ceSopenharmony_ci sl->ph[2][1] = LWS_CBOR_MAJTYP_BSTR | 339d4afb5ceSopenharmony_ci LWS_CBOR_1; 340d4afb5ceSopenharmony_ci sl->ph[2][2] = (uint8_t)sl->ph_pos[2]; 341d4afb5ceSopenharmony_ci p = &sl->ph[2][1]; 342d4afb5ceSopenharmony_ci s = (size_t)sl->ph_pos[2] + 2; 343d4afb5ceSopenharmony_ci } 344d4afb5ceSopenharmony_ci } 345d4afb5ceSopenharmony_ci 346d4afb5ceSopenharmony_ci if (lws_cose_val_alg_hash(alg, p, s)) 347d4afb5ceSopenharmony_ci goto bail; 348d4afb5ceSopenharmony_ci } 349d4afb5ceSopenharmony_ci 350d4afb5ceSopenharmony_ci /* Hash step 4: bstr for applictation protected pieces 351d4afb5ceSopenharmony_ci * empty for now 352d4afb5ceSopenharmony_ci */ 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_ci if (!cps->info.ext_len) { /* ie, if no app data */ 355d4afb5ceSopenharmony_ci uint8_t u = LWS_CBOR_MAJTYP_BSTR; 356d4afb5ceSopenharmony_ci if (lws_cose_val_alg_hash(alg, &u, 1)) 357d4afb5ceSopenharmony_ci goto bail; 358d4afb5ceSopenharmony_ci } 359d4afb5ceSopenharmony_ci 360d4afb5ceSopenharmony_ci /* 361d4afb5ceSopenharmony_ci * The final part is the payload in its own bstr, as 362d4afb5ceSopenharmony_ci * we get it if sign1, else replayed from a cache in heap 363d4afb5ceSopenharmony_ci */ 364d4afb5ceSopenharmony_ci 365d4afb5ceSopenharmony_ci if (cps->info.sigtype == SIGTYPE_SINGLE) 366d4afb5ceSopenharmony_ci return 0; 367d4afb5ceSopenharmony_ci 368d4afb5ceSopenharmony_ci if (!cps->payload_stash) { 369d4afb5ceSopenharmony_ci lwsl_notice("%s: no payload stash\n", __func__); 370d4afb5ceSopenharmony_ci goto bail; 371d4afb5ceSopenharmony_ci } 372d4afb5ceSopenharmony_ci 373d4afb5ceSopenharmony_ci apply_external(cps); 374d4afb5ceSopenharmony_ci 375d4afb5ceSopenharmony_ci if (lws_cose_val_alg_hash(alg, cps->payload_stash, cps->payload_pos)) 376d4afb5ceSopenharmony_ci goto bail; 377d4afb5ceSopenharmony_cilwsl_notice("a %d\n", (int)cps->sig_agg_pos); 378d4afb5ceSopenharmony_ci 379d4afb5ceSopenharmony_ci lws_cose_val_alg_destroy(cps, &alg, (const uint8_t *)cps->sig_agg, 380d4afb5ceSopenharmony_ci cps->sig_agg_pos); 381d4afb5ceSopenharmony_ci 382d4afb5ceSopenharmony_ci return 0; 383d4afb5ceSopenharmony_ci 384d4afb5ceSopenharmony_cibail: 385d4afb5ceSopenharmony_ci return 1; 386d4afb5ceSopenharmony_ci} 387d4afb5ceSopenharmony_ci 388d4afb5ceSopenharmony_ci#if defined(VERBOSE) 389d4afb5ceSopenharmony_cistatic const char * const reason_names[] = { 390d4afb5ceSopenharmony_ci "LECPCB_CONSTRUCTED", 391d4afb5ceSopenharmony_ci "LECPCB_DESTRUCTED", 392d4afb5ceSopenharmony_ci "LECPCB_START", 393d4afb5ceSopenharmony_ci "LECPCB_COMPLETE", 394d4afb5ceSopenharmony_ci "LECPCB_FAILED", 395d4afb5ceSopenharmony_ci "LECPCB_PAIR_NAME", 396d4afb5ceSopenharmony_ci "LECPCB_VAL_TRUE", 397d4afb5ceSopenharmony_ci "LECPCB_VAL_FALSE", 398d4afb5ceSopenharmony_ci "LECPCB_VAL_NULL", 399d4afb5ceSopenharmony_ci "LECPCB_VAL_NUM_INT", 400d4afb5ceSopenharmony_ci "LECPCB_VAL_RESERVED", /* float in lejp */ 401d4afb5ceSopenharmony_ci "LECPCB_VAL_STR_START", 402d4afb5ceSopenharmony_ci "LECPCB_VAL_STR_CHUNK", 403d4afb5ceSopenharmony_ci "LECPCB_VAL_STR_END", 404d4afb5ceSopenharmony_ci "LECPCB_ARRAY_START", 405d4afb5ceSopenharmony_ci "LECPCB_ARRAY_END", 406d4afb5ceSopenharmony_ci "LECPCB_OBJECT_START", 407d4afb5ceSopenharmony_ci "LECPCB_OBJECT_END", 408d4afb5ceSopenharmony_ci "LECPCB_TAG_START", 409d4afb5ceSopenharmony_ci "LECPCB_TAG_END", 410d4afb5ceSopenharmony_ci "LECPCB_VAL_NUM_UINT", 411d4afb5ceSopenharmony_ci "LECPCB_VAL_UNDEFINED", 412d4afb5ceSopenharmony_ci "LECPCB_VAL_FLOAT16", 413d4afb5ceSopenharmony_ci "LECPCB_VAL_FLOAT32", 414d4afb5ceSopenharmony_ci "LECPCB_VAL_FLOAT64", 415d4afb5ceSopenharmony_ci "LECPCB_VAL_SIMPLE", 416d4afb5ceSopenharmony_ci "LECPCB_VAL_BLOB_START", 417d4afb5ceSopenharmony_ci "LECPCB_VAL_BLOB_CHUNK", 418d4afb5ceSopenharmony_ci "LECPCB_VAL_BLOB_END", 419d4afb5ceSopenharmony_ci "LECPCB_ARRAY_ITEM_START", 420d4afb5ceSopenharmony_ci "LECPCB_ARRAY_ITEM_END", 421d4afb5ceSopenharmony_ci "LECPCB_LITERAL_CBOR" 422d4afb5ceSopenharmony_ci}; 423d4afb5ceSopenharmony_ci#endif 424d4afb5ceSopenharmony_ci 425d4afb5ceSopenharmony_cistatic int 426d4afb5ceSopenharmony_ciph_index(struct lws_cose_validate_context *cps) 427d4afb5ceSopenharmony_ci{ 428d4afb5ceSopenharmony_ci switch (cps->tli) { 429d4afb5ceSopenharmony_ci case ST_OUTER_PROTECTED: 430d4afb5ceSopenharmony_ci return 0; 431d4afb5ceSopenharmony_ci case ST_OUTER_UNPROTECTED: 432d4afb5ceSopenharmony_ci return 1; 433d4afb5ceSopenharmony_ci case ST_INNER_PROTECTED: 434d4afb5ceSopenharmony_ci return 2; 435d4afb5ceSopenharmony_ci case ST_INNER_UNPROTECTED: 436d4afb5ceSopenharmony_ci return 3; 437d4afb5ceSopenharmony_ci } 438d4afb5ceSopenharmony_ci 439d4afb5ceSopenharmony_ci assert(0); 440d4afb5ceSopenharmony_ci return 0; 441d4afb5ceSopenharmony_ci} 442d4afb5ceSopenharmony_ci 443d4afb5ceSopenharmony_cistatic signed char 444d4afb5ceSopenharmony_cicb_cose_sig(struct lecp_ctx *ctx, char reason) 445d4afb5ceSopenharmony_ci{ 446d4afb5ceSopenharmony_ci struct lws_cose_validate_context *cps = 447d4afb5ceSopenharmony_ci (struct lws_cose_validate_context *)ctx->user; 448d4afb5ceSopenharmony_ci lws_cose_validate_param_stack_t *sl; 449d4afb5ceSopenharmony_ci struct lws_gencrypto_keyelem *ke; 450d4afb5ceSopenharmony_ci lws_cose_sig_alg_t *alg; 451d4afb5ceSopenharmony_ci uint8_t t[9]; 452d4afb5ceSopenharmony_ci size_t s; 453d4afb5ceSopenharmony_ci int hi; 454d4afb5ceSopenharmony_ci 455d4afb5ceSopenharmony_ci#if defined(VERBOSE) 456d4afb5ceSopenharmony_ci lwsl_notice("%s: %s, tli %s, sub %d, ppos %d, sp %d\n", __func__, 457d4afb5ceSopenharmony_ci reason_names[reason & 0x1f], cose_sections[cps->tli], 458d4afb5ceSopenharmony_ci cps->sub, ctx->pst[ctx->pst_sp].ppos, cps->sp); 459d4afb5ceSopenharmony_ci#endif 460d4afb5ceSopenharmony_ci 461d4afb5ceSopenharmony_ci switch (reason) { 462d4afb5ceSopenharmony_ci case LECPCB_CONSTRUCTED: 463d4afb5ceSopenharmony_ci break; 464d4afb5ceSopenharmony_ci 465d4afb5ceSopenharmony_ci case LECPCB_TAG_START: 466d4afb5ceSopenharmony_ci 467d4afb5ceSopenharmony_ci lwsl_notice("%s: tag sigtype %d\n", __func__, cps->info.sigtype); 468d4afb5ceSopenharmony_ci 469d4afb5ceSopenharmony_ci switch (cps->info.sigtype) { 470d4afb5ceSopenharmony_ci default: 471d4afb5ceSopenharmony_ci assert(0); 472d4afb5ceSopenharmony_ci break; 473d4afb5ceSopenharmony_ci case SIGTYPE_UNKNOWN: 474d4afb5ceSopenharmony_ci /* it means use the tag value to set the type */ 475d4afb5ceSopenharmony_ci switch (ctx->item.u.u64) { 476d4afb5ceSopenharmony_ci case LWSCOAP_CONTENTFORMAT_COSE_SIGN: 477d4afb5ceSopenharmony_ci cps->info.sigtype = SIGTYPE_MULTI; 478d4afb5ceSopenharmony_ci break; 479d4afb5ceSopenharmony_ci case LWSCOAP_CONTENTFORMAT_COSE_SIGN1: 480d4afb5ceSopenharmony_ci cps->info.sigtype = SIGTYPE_SINGLE; 481d4afb5ceSopenharmony_ci break; 482d4afb5ceSopenharmony_ci// case LWSCOAP_CONTENTFORMAT_COSE_SIGN__: 483d4afb5ceSopenharmony_ci// cps->info.sigtype = SIGTYPE_COUNTERSIGNED; 484d4afb5ceSopenharmony_ci// break; 485d4afb5ceSopenharmony_ci case LWSCOAP_CONTENTFORMAT_COSE_MAC0: 486d4afb5ceSopenharmony_ci cps->info.sigtype = SIGTYPE_MAC0; 487d4afb5ceSopenharmony_ci break; 488d4afb5ceSopenharmony_ci case LWSCOAP_CONTENTFORMAT_COSE_MAC: 489d4afb5ceSopenharmony_ci cps->info.sigtype = SIGTYPE_MAC; 490d4afb5ceSopenharmony_ci break; 491d4afb5ceSopenharmony_ci default: 492d4afb5ceSopenharmony_ci goto unexpected_tag; 493d4afb5ceSopenharmony_ci } 494d4afb5ceSopenharmony_ci break; 495d4afb5ceSopenharmony_ci case SIGTYPE_MULTI: 496d4afb5ceSopenharmony_ci if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_SIGN) 497d4afb5ceSopenharmony_ci goto unexpected_tag; 498d4afb5ceSopenharmony_ci break; 499d4afb5ceSopenharmony_ci case SIGTYPE_SINGLE: 500d4afb5ceSopenharmony_ci if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_SIGN1) 501d4afb5ceSopenharmony_ci goto unexpected_tag; 502d4afb5ceSopenharmony_ci break; 503d4afb5ceSopenharmony_ci case SIGTYPE_COUNTERSIGNED: 504d4afb5ceSopenharmony_ci if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_SIGN) 505d4afb5ceSopenharmony_ci goto unexpected_tag; 506d4afb5ceSopenharmony_ci break; 507d4afb5ceSopenharmony_ci case SIGTYPE_MAC0: 508d4afb5ceSopenharmony_ci if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_MAC0) 509d4afb5ceSopenharmony_ci goto unexpected_tag; 510d4afb5ceSopenharmony_ci break; 511d4afb5ceSopenharmony_ci case SIGTYPE_MAC: 512d4afb5ceSopenharmony_ci if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_MAC) { 513d4afb5ceSopenharmony_ciunexpected_tag: 514d4afb5ceSopenharmony_ci lwsl_warn("%s: unexpected tag %d\n", __func__, 515d4afb5ceSopenharmony_ci (int)ctx->item.u.u64); 516d4afb5ceSopenharmony_ci goto bail; 517d4afb5ceSopenharmony_ci } 518d4afb5ceSopenharmony_ci break; 519d4afb5ceSopenharmony_ci } 520d4afb5ceSopenharmony_ci 521d4afb5ceSopenharmony_ci cps->depth++; 522d4afb5ceSopenharmony_ci break; 523d4afb5ceSopenharmony_ci 524d4afb5ceSopenharmony_ci case LECPCB_ARRAY_ITEM_START: 525d4afb5ceSopenharmony_ci 526d4afb5ceSopenharmony_ci if (cps->sub) 527d4afb5ceSopenharmony_ci break; 528d4afb5ceSopenharmony_ci 529d4afb5ceSopenharmony_ci if (ctx->pst[ctx->pst_sp].ppos == 4 || 530d4afb5ceSopenharmony_ci ctx->pst[ctx->pst_sp].ppos == 6) { 531d4afb5ceSopenharmony_ci switch (cps->tli) { 532d4afb5ceSopenharmony_ci case ST_INNER_UNPROTECTED: 533d4afb5ceSopenharmony_ci case ST_INNER_PROTECTED: 534d4afb5ceSopenharmony_ci hi = ph_index(cps); 535d4afb5ceSopenharmony_ci sl = &cps->st[cps->sp]; 536d4afb5ceSopenharmony_ci sl->ph_pos[hi] = 0; 537d4afb5ceSopenharmony_ci lecp_parse_report_raw(ctx, 1); 538d4afb5ceSopenharmony_ci break; 539d4afb5ceSopenharmony_ci default: 540d4afb5ceSopenharmony_ci break; 541d4afb5ceSopenharmony_ci } 542d4afb5ceSopenharmony_ci break; 543d4afb5ceSopenharmony_ci } 544d4afb5ceSopenharmony_ci 545d4afb5ceSopenharmony_ci if (ctx->pst[ctx->pst_sp].ppos != 2) 546d4afb5ceSopenharmony_ci break; 547d4afb5ceSopenharmony_ci 548d4afb5ceSopenharmony_ci switch (cps->tli) { 549d4afb5ceSopenharmony_ci case ST_OUTER_UNPROTECTED: 550d4afb5ceSopenharmony_ci case ST_OUTER_PROTECTED: 551d4afb5ceSopenharmony_ci /* 552d4afb5ceSopenharmony_ci * Holy type confusion, Batman... this is a CBOR bstr 553d4afb5ceSopenharmony_ci * containing valid CBOR that must also be parsed as 554d4afb5ceSopenharmony_ci * part of the containing array... we need to collect 555d4afb5ceSopenharmony_ci * it anyway since it is part of the signing plaintext 556d4afb5ceSopenharmony_ci * in bstr form, let's get it and then parse it at the 557d4afb5ceSopenharmony_ci * END of the bstr. 558d4afb5ceSopenharmony_ci */ 559d4afb5ceSopenharmony_ci lecp_parse_report_raw(ctx, 1); 560d4afb5ceSopenharmony_ci break; 561d4afb5ceSopenharmony_ci 562d4afb5ceSopenharmony_ci case ST_OUTER_PAYLOAD: 563d4afb5ceSopenharmony_ci if (cps->info.sigtype != SIGTYPE_SINGLE) 564d4afb5ceSopenharmony_ci break; 565d4afb5ceSopenharmony_ci 566d4afb5ceSopenharmony_ci if (create_alg(ctx, cps)) 567d4afb5ceSopenharmony_ci goto bail; 568d4afb5ceSopenharmony_ci 569d4afb5ceSopenharmony_ci break; 570d4afb5ceSopenharmony_ci 571d4afb5ceSopenharmony_ci case ST_OUTER_SIGN_SIGARRAY: 572d4afb5ceSopenharmony_ci cps->tli = ST_INNER_PROTECTED; 573d4afb5ceSopenharmony_ci break; 574d4afb5ceSopenharmony_ci } 575d4afb5ceSopenharmony_ci break; 576d4afb5ceSopenharmony_ci 577d4afb5ceSopenharmony_ci case LECPCB_ARRAY_ITEM_END: 578d4afb5ceSopenharmony_ci 579d4afb5ceSopenharmony_ci if (cps->sub) 580d4afb5ceSopenharmony_ci break; 581d4afb5ceSopenharmony_ci 582d4afb5ceSopenharmony_ci if (ctx->pst[ctx->pst_sp].ppos == 2) { 583d4afb5ceSopenharmony_ci sl = &cps->st[cps->sp]; 584d4afb5ceSopenharmony_ci switch (cps->tli) { 585d4afb5ceSopenharmony_ci case ST_OUTER_UNPROTECTED: 586d4afb5ceSopenharmony_ci break; 587d4afb5ceSopenharmony_ci /* fallthru */ 588d4afb5ceSopenharmony_ci case ST_OUTER_PROTECTED: 589d4afb5ceSopenharmony_ci lecp_parse_report_raw(ctx, 0); 590d4afb5ceSopenharmony_ci 591d4afb5ceSopenharmony_ci hi = ph_index(cps); 592d4afb5ceSopenharmony_ci 593d4afb5ceSopenharmony_ci if (!sl->ph_pos[hi] || cps->sub) 594d4afb5ceSopenharmony_ci break; 595d4afb5ceSopenharmony_ci 596d4afb5ceSopenharmony_ci cps->sub = 1; 597d4afb5ceSopenharmony_ci s = (size_t)sl->ph_pos[hi]; 598d4afb5ceSopenharmony_ci 599d4afb5ceSopenharmony_ci if (lecp_parse_subtree(&cps->ctx, 600d4afb5ceSopenharmony_ci sl->ph[hi] + 3, s) != 601d4afb5ceSopenharmony_ci LECP_CONTINUE) 602d4afb5ceSopenharmony_ci goto bail; 603d4afb5ceSopenharmony_ci cps->sub = 0; 604d4afb5ceSopenharmony_ci break; 605d4afb5ceSopenharmony_ci 606d4afb5ceSopenharmony_ci case ST_OUTER_PAYLOAD: 607d4afb5ceSopenharmony_ci switch (cps->info.sigtype) { 608d4afb5ceSopenharmony_ci case SIGTYPE_MULTI: 609d4afb5ceSopenharmony_ci cps->tli = ST_OUTER_SIGN_SIGARRAY - 1; 610d4afb5ceSopenharmony_ci break; 611d4afb5ceSopenharmony_ci case SIGTYPE_MAC: 612d4afb5ceSopenharmony_ci case SIGTYPE_MAC0: 613d4afb5ceSopenharmony_ci cps->tli = ST_OUTER_MACTAG - 1; 614d4afb5ceSopenharmony_ci break; 615d4afb5ceSopenharmony_ci case SIGTYPE_COUNTERSIGNED: 616d4afb5ceSopenharmony_ci break; 617d4afb5ceSopenharmony_ci default: 618d4afb5ceSopenharmony_ci break; 619d4afb5ceSopenharmony_ci } 620d4afb5ceSopenharmony_ci break; 621d4afb5ceSopenharmony_ci 622d4afb5ceSopenharmony_ci case ST_OUTER_SIGN1_SIGNATURE: 623d4afb5ceSopenharmony_ci case ST_OUTER_MACTAG: 624d4afb5ceSopenharmony_ci cps->sp++; 625d4afb5ceSopenharmony_ci cps->tli = ST_INNER_PROTECTED - 1; 626d4afb5ceSopenharmony_ci break; 627d4afb5ceSopenharmony_ci 628d4afb5ceSopenharmony_ci case ST_INNER_UNPROTECTED: 629d4afb5ceSopenharmony_ci lwsl_notice("ST_INNER_UNPROTECTED end\n"); 630d4afb5ceSopenharmony_ci break; 631d4afb5ceSopenharmony_ci case ST_INNER_PROTECTED: 632d4afb5ceSopenharmony_ci lwsl_notice("ST_INNER_PROTECTED end\n"); 633d4afb5ceSopenharmony_ci break; 634d4afb5ceSopenharmony_ci 635d4afb5ceSopenharmony_ci case ST_INNER_EXCESS: 636d4afb5ceSopenharmony_ci case ST_OUTER_SIGN_SIGARRAY: 637d4afb5ceSopenharmony_ci cps->tli--; /* so no change */ 638d4afb5ceSopenharmony_ci break; 639d4afb5ceSopenharmony_ci } 640d4afb5ceSopenharmony_ci if (!cps->sub) 641d4afb5ceSopenharmony_ci cps->tli++; 642d4afb5ceSopenharmony_ci } 643d4afb5ceSopenharmony_ci 644d4afb5ceSopenharmony_ci if (ctx->pst[ctx->pst_sp].ppos >= 4) { 645d4afb5ceSopenharmony_ci uint8_t *p; 646d4afb5ceSopenharmony_ci uint8_t u; 647d4afb5ceSopenharmony_ci size_t s1; 648d4afb5ceSopenharmony_ci 649d4afb5ceSopenharmony_ci switch (cps->tli) { 650d4afb5ceSopenharmony_ci case ST_INNER_UNPROTECTED: 651d4afb5ceSopenharmony_ci case ST_INNER_PROTECTED: 652d4afb5ceSopenharmony_ci 653d4afb5ceSopenharmony_ci hi = ph_index(cps); 654d4afb5ceSopenharmony_ci sl = &cps->st[cps->sp]; 655d4afb5ceSopenharmony_ci p = sl->ph[hi] + 3; 656d4afb5ceSopenharmony_ci lecp_parse_report_raw(ctx, 0); 657d4afb5ceSopenharmony_ci 658d4afb5ceSopenharmony_ci if (!sl->ph_pos[hi] || cps->sub) { 659d4afb5ceSopenharmony_ci if (!cps->sub) 660d4afb5ceSopenharmony_ci cps->tli++; 661d4afb5ceSopenharmony_ci break; 662d4afb5ceSopenharmony_ci } 663d4afb5ceSopenharmony_ci 664d4afb5ceSopenharmony_ci cps->sub = 1; 665d4afb5ceSopenharmony_ci s = (size_t)sl->ph_pos[hi]; 666d4afb5ceSopenharmony_ci 667d4afb5ceSopenharmony_ci /* 668d4afb5ceSopenharmony_ci * somehow the raw captures the 669d4afb5ceSopenharmony_ci * initial BSTR container length, 670d4afb5ceSopenharmony_ci * let's strip it 671d4afb5ceSopenharmony_ci */ 672d4afb5ceSopenharmony_ci 673d4afb5ceSopenharmony_ci u = (*p) & LWS_CBOR_SUBMASK; 674d4afb5ceSopenharmony_ci if (((*p) & LWS_CBOR_MAJTYP_MASK) == 675d4afb5ceSopenharmony_ci LWS_CBOR_MAJTYP_BSTR) { 676d4afb5ceSopenharmony_ci s1 = 1; 677d4afb5ceSopenharmony_ci if (u == LWS_CBOR_1) 678d4afb5ceSopenharmony_ci s1 = 2; 679d4afb5ceSopenharmony_ci else if (u == LWS_CBOR_2) 680d4afb5ceSopenharmony_ci s1 = 3; 681d4afb5ceSopenharmony_ci else if (u == LWS_CBOR_4) 682d4afb5ceSopenharmony_ci s1 = 5; 683d4afb5ceSopenharmony_ci else if (u == LWS_CBOR_8) 684d4afb5ceSopenharmony_ci s1 = 9; 685d4afb5ceSopenharmony_ci 686d4afb5ceSopenharmony_ci if (s1 > s) 687d4afb5ceSopenharmony_ci goto bail; 688d4afb5ceSopenharmony_ci 689d4afb5ceSopenharmony_ci sl->ph_pos[hi] = (int) 690d4afb5ceSopenharmony_ci (sl->ph_pos[hi] - (ssize_t)s1); 691d4afb5ceSopenharmony_ci s = s - s1; 692d4afb5ceSopenharmony_ci memmove(p, p + s1, s); 693d4afb5ceSopenharmony_ci } 694d4afb5ceSopenharmony_ci 695d4afb5ceSopenharmony_ci if (lecp_parse_subtree(&cps->ctx, p, s) != 696d4afb5ceSopenharmony_ci LECP_CONTINUE) 697d4afb5ceSopenharmony_ci goto bail; 698d4afb5ceSopenharmony_ci 699d4afb5ceSopenharmony_ci cps->sub = 0; 700d4afb5ceSopenharmony_ci 701d4afb5ceSopenharmony_ci if (!cps->sub) 702d4afb5ceSopenharmony_ci cps->tli++; 703d4afb5ceSopenharmony_ci break; 704d4afb5ceSopenharmony_ci 705d4afb5ceSopenharmony_ci case ST_INNER_SIGNATURE: 706d4afb5ceSopenharmony_ci if (cps->info.sigtype == SIGTYPE_MAC) { 707d4afb5ceSopenharmony_ci // lwsl_err("Y: alg %d\n", (int)cps->alg); 708d4afb5ceSopenharmony_ci if (create_alg(ctx, cps)) 709d4afb5ceSopenharmony_ci goto bail; 710d4afb5ceSopenharmony_ci } 711d4afb5ceSopenharmony_ci cps->tli++; 712d4afb5ceSopenharmony_ci break; 713d4afb5ceSopenharmony_ci default: 714d4afb5ceSopenharmony_ci break; 715d4afb5ceSopenharmony_ci } 716d4afb5ceSopenharmony_ci } 717d4afb5ceSopenharmony_ci 718d4afb5ceSopenharmony_ci break; 719d4afb5ceSopenharmony_ci 720d4afb5ceSopenharmony_ci case LECPCB_VAL_NUM_INT: 721d4afb5ceSopenharmony_ci case LECPCB_VAL_NUM_UINT: 722d4afb5ceSopenharmony_ci switch (cps->tli) { 723d4afb5ceSopenharmony_ci case ST_INNER_PROTECTED: 724d4afb5ceSopenharmony_ci case ST_INNER_UNPROTECTED: 725d4afb5ceSopenharmony_ci case ST_INNER_SIGNATURE: 726d4afb5ceSopenharmony_ci case ST_OUTER_PROTECTED: 727d4afb5ceSopenharmony_ci case ST_OUTER_UNPROTECTED: 728d4afb5ceSopenharmony_ci if (lecp_parse_map_is_key(ctx)) { 729d4afb5ceSopenharmony_ci cps->map_key = ctx->item.u.i64; 730d4afb5ceSopenharmony_ci // lwsl_notice("%s: key %d\n", __func__, (int)cps->map_key); 731d4afb5ceSopenharmony_ci break; 732d4afb5ceSopenharmony_ci } 733d4afb5ceSopenharmony_ci 734d4afb5ceSopenharmony_ci // lwsl_notice("%s: key %d val %d\n", __func__, (int)cps->map_key, (int)ctx->item.u.i64); 735d4afb5ceSopenharmony_ci 736d4afb5ceSopenharmony_ci if (cps->map_key == LWSCOSE_WKL_ALG) { 737d4afb5ceSopenharmony_ci sl = &cps->st[cps->sp]; 738d4afb5ceSopenharmony_ci cps->map_key = 0; 739d4afb5ceSopenharmony_ci if (cps->tli == ST_INNER_PROTECTED || 740d4afb5ceSopenharmony_ci cps->tli == ST_INNER_UNPROTECTED || 741d4afb5ceSopenharmony_ci cps->tli == ST_INNER_SIGNATURE) { 742d4afb5ceSopenharmony_ci sl->alg = ctx->item.u.i64; 743d4afb5ceSopenharmony_ci if (!cps->st[0].alg) 744d4afb5ceSopenharmony_ci cps->st[0].alg = sl->alg; 745d4afb5ceSopenharmony_ci } else 746d4afb5ceSopenharmony_ci sl->alg = ctx->item.u.i64; 747d4afb5ceSopenharmony_ci break; 748d4afb5ceSopenharmony_ci } 749d4afb5ceSopenharmony_ci break; 750d4afb5ceSopenharmony_ci } 751d4afb5ceSopenharmony_ci break; 752d4afb5ceSopenharmony_ci 753d4afb5ceSopenharmony_ci case LECPCB_VAL_STR_END: 754d4afb5ceSopenharmony_ci switch (cps->tli) { 755d4afb5ceSopenharmony_ci case ST_OUTER_UNPROTECTED: 756d4afb5ceSopenharmony_ci break; 757d4afb5ceSopenharmony_ci } 758d4afb5ceSopenharmony_ci break; 759d4afb5ceSopenharmony_ci 760d4afb5ceSopenharmony_ci case LECPCB_VAL_BLOB_START: 761d4afb5ceSopenharmony_ci 762d4afb5ceSopenharmony_ci lwsl_notice("%s: blob size %d\n", __func__, (int)ctx->item.u.u64); 763d4afb5ceSopenharmony_ci 764d4afb5ceSopenharmony_ci if (cps->tli == ST_OUTER_SIGN1_SIGNATURE || 765d4afb5ceSopenharmony_ci cps->tli == ST_INNER_SIGNATURE) { 766d4afb5ceSopenharmony_ci if (ctx->item.u.u64 > sizeof(cps->sig_agg)) 767d4afb5ceSopenharmony_ci goto bail; 768d4afb5ceSopenharmony_ci cps->sig_agg_pos = 0; 769d4afb5ceSopenharmony_ci break; 770d4afb5ceSopenharmony_ci } 771d4afb5ceSopenharmony_ci 772d4afb5ceSopenharmony_ci if (cps->tli != ST_OUTER_PAYLOAD) 773d4afb5ceSopenharmony_ci break; 774d4afb5ceSopenharmony_ci 775d4afb5ceSopenharmony_ci if (apply_external(cps)) { 776d4afb5ceSopenharmony_ci lwsl_notice("%s: ext\n", __func__); 777d4afb5ceSopenharmony_ci goto bail; 778d4afb5ceSopenharmony_ci } 779d4afb5ceSopenharmony_ci 780d4afb5ceSopenharmony_ci s = bstr_len(t, sizeof(t), LWS_CBOR_MAJTYP_BSTR, 781d4afb5ceSopenharmony_ci ctx->item.u.u64); 782d4afb5ceSopenharmony_ci 783d4afb5ceSopenharmony_ci if (cps->info.sigtype == SIGTYPE_SINGLE) { 784d4afb5ceSopenharmony_ci alg = lws_container_of(cps->algs.head, 785d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 786d4afb5ceSopenharmony_ci if (!alg) 787d4afb5ceSopenharmony_ci /* expected if no key */ 788d4afb5ceSopenharmony_ci break; 789d4afb5ceSopenharmony_ci if (lws_cose_val_alg_hash(alg, t, s)) { 790d4afb5ceSopenharmony_ci lwsl_notice("%s: hash failed\n", __func__); 791d4afb5ceSopenharmony_ci goto bail; 792d4afb5ceSopenharmony_ci } 793d4afb5ceSopenharmony_ci 794d4afb5ceSopenharmony_ci break; 795d4afb5ceSopenharmony_ci } 796d4afb5ceSopenharmony_ci 797d4afb5ceSopenharmony_ci cps->payload_stash_size = (size_t)(ctx->item.u.u64 + s); 798d4afb5ceSopenharmony_ci cps->payload_stash = lws_malloc(cps->payload_stash_size, 799d4afb5ceSopenharmony_ci __func__); 800d4afb5ceSopenharmony_ci if (!cps->payload_stash) { 801d4afb5ceSopenharmony_ci lwsl_notice("%s: oom\n", __func__); 802d4afb5ceSopenharmony_ci goto bail; 803d4afb5ceSopenharmony_ci } 804d4afb5ceSopenharmony_ci 805d4afb5ceSopenharmony_ci memcpy(cps->payload_stash, t, s); 806d4afb5ceSopenharmony_ci cps->payload_pos = s; 807d4afb5ceSopenharmony_ci 808d4afb5ceSopenharmony_ci break; 809d4afb5ceSopenharmony_ci 810d4afb5ceSopenharmony_ci case LECPCB_VAL_BLOB_CHUNK: 811d4afb5ceSopenharmony_ci switch (cps->tli) { 812d4afb5ceSopenharmony_ci case ST_OUTER_PAYLOAD: 813d4afb5ceSopenharmony_ci 814d4afb5ceSopenharmony_ci if (cps->info.pay_cb && ctx->npos) 815d4afb5ceSopenharmony_ci cps->info.pay_cb(cps, cps->info.pay_opaque, 816d4afb5ceSopenharmony_ci (uint8_t *)ctx->buf, ctx->npos); 817d4afb5ceSopenharmony_ci 818d4afb5ceSopenharmony_ci if (cps->payload_stash) { 819d4afb5ceSopenharmony_ci if (cps->payload_pos + ctx->npos > 820d4afb5ceSopenharmony_ci cps->payload_stash_size) 821d4afb5ceSopenharmony_ci goto bail; 822d4afb5ceSopenharmony_ci memcpy(cps->payload_stash + cps->payload_pos, 823d4afb5ceSopenharmony_ci ctx->buf, ctx->npos); 824d4afb5ceSopenharmony_ci cps->payload_pos += ctx->npos; 825d4afb5ceSopenharmony_ci break; 826d4afb5ceSopenharmony_ci } 827d4afb5ceSopenharmony_ci alg = lws_container_of(cps->algs.head, 828d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 829d4afb5ceSopenharmony_ci if (!alg) 830d4afb5ceSopenharmony_ci /* expected if no key */ 831d4afb5ceSopenharmony_ci break; 832d4afb5ceSopenharmony_ci if (ctx->npos && 833d4afb5ceSopenharmony_ci lws_cose_val_alg_hash(alg, (uint8_t *)ctx->buf, 834d4afb5ceSopenharmony_ci ctx->npos)) { 835d4afb5ceSopenharmony_ci lwsl_notice("%s: chunk fail\n", __func__); 836d4afb5ceSopenharmony_ci goto bail; 837d4afb5ceSopenharmony_ci } 838d4afb5ceSopenharmony_ci break; 839d4afb5ceSopenharmony_ci case ST_INNER_SIGNATURE: 840d4afb5ceSopenharmony_ci case ST_OUTER_SIGN1_SIGNATURE: 841d4afb5ceSopenharmony_ci /* the sig is big compared to ctx->buf... we need to 842d4afb5ceSopenharmony_ci * stash it then */ 843d4afb5ceSopenharmony_ci memcpy(cps->sig_agg + cps->sig_agg_pos, ctx->buf, 844d4afb5ceSopenharmony_ci ctx->npos); 845d4afb5ceSopenharmony_ci cps->sig_agg_pos = cps->sig_agg_pos + ctx->npos; 846d4afb5ceSopenharmony_ci break; 847d4afb5ceSopenharmony_ci } 848d4afb5ceSopenharmony_ci break; 849d4afb5ceSopenharmony_ci 850d4afb5ceSopenharmony_ci case LECPCB_VAL_BLOB_END: 851d4afb5ceSopenharmony_ci switch (cps->tli) { 852d4afb5ceSopenharmony_ci 853d4afb5ceSopenharmony_ci case ST_INNER_SIGNATURE: 854d4afb5ceSopenharmony_ci if (cps->info.sigtype == SIGTYPE_MULTI) { 855d4afb5ceSopenharmony_ci memcpy(cps->sig_agg + cps->sig_agg_pos, ctx->buf, 856d4afb5ceSopenharmony_ci ctx->npos); 857d4afb5ceSopenharmony_ci cps->sig_agg_pos = cps->sig_agg_pos + ctx->npos; 858d4afb5ceSopenharmony_ci // lwsl_err("Y: alg %d\n", (int)cps->alg); 859d4afb5ceSopenharmony_ci if (create_alg(ctx, cps)) 860d4afb5ceSopenharmony_ci goto bail; 861d4afb5ceSopenharmony_ci break; 862d4afb5ceSopenharmony_ci } 863d4afb5ceSopenharmony_ci if (cps->info.sigtype != SIGTYPE_MAC) 864d4afb5ceSopenharmony_ci break; 865d4afb5ceSopenharmony_ci /* fallthru */ 866d4afb5ceSopenharmony_ci case ST_OUTER_PROTECTED: 867d4afb5ceSopenharmony_ci case ST_OUTER_UNPROTECTED: 868d4afb5ceSopenharmony_ci case ST_INNER_PROTECTED: 869d4afb5ceSopenharmony_ci case ST_INNER_UNPROTECTED: 870d4afb5ceSopenharmony_ci if (cps->map_key == LWSCOSE_WKL_KID) { 871d4afb5ceSopenharmony_ci sl = &cps->st[cps->sp]; 872d4afb5ceSopenharmony_ci ke = &sl->kid; 873d4afb5ceSopenharmony_ci if (ke->buf) 874d4afb5ceSopenharmony_ci lws_free(ke->buf); 875d4afb5ceSopenharmony_ci ke->buf = lws_malloc(ctx->npos, __func__); 876d4afb5ceSopenharmony_ci if (!ke->buf) 877d4afb5ceSopenharmony_ci goto bail; 878d4afb5ceSopenharmony_ci ke->len = ctx->npos; 879d4afb5ceSopenharmony_ci memcpy(ke->buf, ctx->buf, ctx->npos); 880d4afb5ceSopenharmony_ci cps->map_key = 0; 881d4afb5ceSopenharmony_ci } 882d4afb5ceSopenharmony_ci break; 883d4afb5ceSopenharmony_ci 884d4afb5ceSopenharmony_ci case ST_OUTER_PAYLOAD: 885d4afb5ceSopenharmony_ci if (cps->info.pay_cb && ctx->npos) 886d4afb5ceSopenharmony_ci cps->info.pay_cb(cps, cps->info.pay_opaque, 887d4afb5ceSopenharmony_ci (uint8_t *)ctx->buf, ctx->npos); 888d4afb5ceSopenharmony_ci if (cps->payload_stash) { 889d4afb5ceSopenharmony_ci if (cps->payload_pos + ctx->npos > 890d4afb5ceSopenharmony_ci cps->payload_stash_size) 891d4afb5ceSopenharmony_ci goto bail; 892d4afb5ceSopenharmony_ci memcpy(cps->payload_stash + cps->payload_pos, 893d4afb5ceSopenharmony_ci ctx->buf, ctx->npos); 894d4afb5ceSopenharmony_ci cps->payload_pos += ctx->npos; 895d4afb5ceSopenharmony_ci break; 896d4afb5ceSopenharmony_ci } 897d4afb5ceSopenharmony_ci alg = lws_container_of(cps->algs.head, 898d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 899d4afb5ceSopenharmony_ci if (!alg) 900d4afb5ceSopenharmony_ci /* expected if no key */ 901d4afb5ceSopenharmony_ci break; 902d4afb5ceSopenharmony_ci 903d4afb5ceSopenharmony_ci if (ctx->npos && 904d4afb5ceSopenharmony_ci lws_cose_val_alg_hash(alg, (uint8_t *)ctx->buf, 905d4afb5ceSopenharmony_ci ctx->npos)) 906d4afb5ceSopenharmony_ci goto bail; 907d4afb5ceSopenharmony_ci break; 908d4afb5ceSopenharmony_ci 909d4afb5ceSopenharmony_ci case ST_OUTER_SIGN1_SIGNATURE: 910d4afb5ceSopenharmony_ci if (cps->info.sigtype == SIGTYPE_MULTI) 911d4afb5ceSopenharmony_ci break; 912d4afb5ceSopenharmony_ci 913d4afb5ceSopenharmony_ci memcpy(cps->sig_agg + cps->sig_agg_pos, ctx->buf, 914d4afb5ceSopenharmony_ci ctx->npos); 915d4afb5ceSopenharmony_ci cps->sig_agg_pos += ctx->npos; 916d4afb5ceSopenharmony_ci 917d4afb5ceSopenharmony_ci alg = lws_container_of(cps->algs.head, 918d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 919d4afb5ceSopenharmony_ci lwsl_notice("b\n"); 920d4afb5ceSopenharmony_ci if (alg) 921d4afb5ceSopenharmony_ci lws_cose_val_alg_destroy(cps, &alg, 922d4afb5ceSopenharmony_ci cps->sig_agg, 923d4afb5ceSopenharmony_ci cps->sig_agg_pos); 924d4afb5ceSopenharmony_ci break; 925d4afb5ceSopenharmony_ci 926d4afb5ceSopenharmony_ci case ST_OUTER_MACTAG: 927d4afb5ceSopenharmony_ci if (cps->mac_pos + ctx->npos > sizeof(cps->mac)) 928d4afb5ceSopenharmony_ci goto bail; 929d4afb5ceSopenharmony_ci memcpy(cps->mac + cps->mac_pos, ctx->buf, ctx->npos); 930d4afb5ceSopenharmony_ci cps->mac_pos += ctx->npos; 931d4afb5ceSopenharmony_ci 932d4afb5ceSopenharmony_ci if (cps->info.sigtype == SIGTYPE_MAC0) { 933d4afb5ceSopenharmony_ci if (create_alg(ctx, cps)) 934d4afb5ceSopenharmony_ci goto bail; 935d4afb5ceSopenharmony_ci } 936d4afb5ceSopenharmony_ci 937d4afb5ceSopenharmony_ci break; 938d4afb5ceSopenharmony_ci } 939d4afb5ceSopenharmony_ci break; 940d4afb5ceSopenharmony_ci 941d4afb5ceSopenharmony_ci case LECPCB_LITERAL_CBOR: 942d4afb5ceSopenharmony_ci /* only used for protected headers */ 943d4afb5ceSopenharmony_ci switch (cps->tli) { 944d4afb5ceSopenharmony_ci case ST_INNER_PROTECTED: 945d4afb5ceSopenharmony_ci case ST_OUTER_PROTECTED: 946d4afb5ceSopenharmony_ci case ST_INNER_UNPROTECTED: 947d4afb5ceSopenharmony_ci case ST_OUTER_UNPROTECTED: 948d4afb5ceSopenharmony_ci sl = &cps->st[cps->sp]; 949d4afb5ceSopenharmony_ci hi = ph_index(cps); 950d4afb5ceSopenharmony_ci if (sl->ph_pos[hi] + 3 + ctx->cbor_pos > 951d4afb5ceSopenharmony_ci (int)sizeof(sl->ph[hi]) - 3) 952d4afb5ceSopenharmony_ci /* more protected cbor than we can handle */ 953d4afb5ceSopenharmony_ci goto bail; 954d4afb5ceSopenharmony_ci memcpy(sl->ph[hi] + 3 + sl->ph_pos[hi], ctx->cbor, 955d4afb5ceSopenharmony_ci ctx->cbor_pos); 956d4afb5ceSopenharmony_ci sl->ph_pos[hi] += ctx->cbor_pos; 957d4afb5ceSopenharmony_ci break; 958d4afb5ceSopenharmony_ci } 959d4afb5ceSopenharmony_ci } 960d4afb5ceSopenharmony_ci 961d4afb5ceSopenharmony_ci return 0; 962d4afb5ceSopenharmony_ci 963d4afb5ceSopenharmony_cibail: 964d4afb5ceSopenharmony_ci 965d4afb5ceSopenharmony_ci return -1; 966d4afb5ceSopenharmony_ci} 967d4afb5ceSopenharmony_ci 968d4afb5ceSopenharmony_cistruct lws_cose_validate_context * 969d4afb5ceSopenharmony_cilws_cose_validate_create(const lws_cose_validate_create_info_t *info) 970d4afb5ceSopenharmony_ci{ 971d4afb5ceSopenharmony_ci struct lws_cose_validate_context *cps; 972d4afb5ceSopenharmony_ci 973d4afb5ceSopenharmony_ci /* you have to provide at least one key in a cose_keyset */ 974d4afb5ceSopenharmony_ci assert(info->keyset); 975d4afb5ceSopenharmony_ci /* you have to provide an lws_context (for crypto random) */ 976d4afb5ceSopenharmony_ci assert(info->cx); 977d4afb5ceSopenharmony_ci 978d4afb5ceSopenharmony_ci cps = lws_zalloc(sizeof(*cps), __func__); 979d4afb5ceSopenharmony_ci if (!cps) 980d4afb5ceSopenharmony_ci return NULL; 981d4afb5ceSopenharmony_ci 982d4afb5ceSopenharmony_ci cps->info = *info; 983d4afb5ceSopenharmony_ci cps->tli = ST_OUTER_PROTECTED; 984d4afb5ceSopenharmony_ci 985d4afb5ceSopenharmony_ci lecp_construct(&cps->ctx, cb_cose_sig, cps, NULL, 0); 986d4afb5ceSopenharmony_ci 987d4afb5ceSopenharmony_ci return cps; 988d4afb5ceSopenharmony_ci} 989d4afb5ceSopenharmony_ci 990d4afb5ceSopenharmony_ciint 991d4afb5ceSopenharmony_cilws_cose_validate_chunk(struct lws_cose_validate_context *cps, 992d4afb5ceSopenharmony_ci const uint8_t *in, size_t in_len, size_t *used_in) 993d4afb5ceSopenharmony_ci{ 994d4afb5ceSopenharmony_ci int n; 995d4afb5ceSopenharmony_ci 996d4afb5ceSopenharmony_ci n = lecp_parse(&cps->ctx, in, in_len); 997d4afb5ceSopenharmony_ci if (used_in) 998d4afb5ceSopenharmony_ci *used_in = cps->ctx.used_in; 999d4afb5ceSopenharmony_ci 1000d4afb5ceSopenharmony_ci if (n == LECP_CONTINUE) 1001d4afb5ceSopenharmony_ci return LECP_CONTINUE; 1002d4afb5ceSopenharmony_ci 1003d4afb5ceSopenharmony_ci lecp_destruct(&cps->ctx); 1004d4afb5ceSopenharmony_ci 1005d4afb5ceSopenharmony_ci return n; 1006d4afb5ceSopenharmony_ci} 1007d4afb5ceSopenharmony_ci 1008d4afb5ceSopenharmony_cilws_dll2_owner_t * 1009d4afb5ceSopenharmony_cilws_cose_validate_results(struct lws_cose_validate_context *cps) 1010d4afb5ceSopenharmony_ci{ 1011d4afb5ceSopenharmony_ci return &cps->results; 1012d4afb5ceSopenharmony_ci} 1013d4afb5ceSopenharmony_ci 1014d4afb5ceSopenharmony_civoid 1015d4afb5ceSopenharmony_cilws_cose_validate_destroy(struct lws_cose_validate_context **_cps) 1016d4afb5ceSopenharmony_ci{ 1017d4afb5ceSopenharmony_ci struct lws_cose_validate_context *cps = *_cps; 1018d4afb5ceSopenharmony_ci 1019d4afb5ceSopenharmony_ci if (!cps) 1020d4afb5ceSopenharmony_ci return; 1021d4afb5ceSopenharmony_ci 1022d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, 1023d4afb5ceSopenharmony_ci lws_dll2_get_head(&cps->algs)) { 1024d4afb5ceSopenharmony_ci lws_cose_sig_alg_t *alg = lws_container_of(p, 1025d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 1026d4afb5ceSopenharmony_ci 1027d4afb5ceSopenharmony_ci lws_dll2_remove(p); 1028d4afb5ceSopenharmony_ci lws_cose_val_alg_destroy(cps, &alg, NULL, 0); 1029d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(p, tp); 1030d4afb5ceSopenharmony_ci 1031d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, 1032d4afb5ceSopenharmony_ci lws_dll2_get_head(&cps->results)) { 1033d4afb5ceSopenharmony_ci lws_cose_validate_res_t *res = lws_container_of(p, 1034d4afb5ceSopenharmony_ci lws_cose_validate_res_t, list); 1035d4afb5ceSopenharmony_ci 1036d4afb5ceSopenharmony_ci lws_dll2_remove(p); 1037d4afb5ceSopenharmony_ci lws_free(res); 1038d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(p, tp); 1039d4afb5ceSopenharmony_ci 1040d4afb5ceSopenharmony_ci lws_free_set_NULL(cps->payload_stash); 1041d4afb5ceSopenharmony_ci 1042d4afb5ceSopenharmony_ci lwsac_free(&cps->ac); 1043d4afb5ceSopenharmony_ci 1044d4afb5ceSopenharmony_ci while (cps->sp >= 0) { 1045d4afb5ceSopenharmony_ci if (cps->st[cps->sp].kid.buf) 1046d4afb5ceSopenharmony_ci lws_free(cps->st[cps->sp].kid.buf); 1047d4afb5ceSopenharmony_ci cps->sp--; 1048d4afb5ceSopenharmony_ci } 1049d4afb5ceSopenharmony_ci 1050d4afb5ceSopenharmony_ci lws_free_set_NULL(*_cps); 1051d4afb5ceSopenharmony_ci} 1052