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