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