xref: /aosp_15_r20/external/libwebsockets/lib/tls/tls-jit-trust.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 
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker 
27*1c60b9acSAndroid Build Coastguard Worker void
lws_tls_kid_copy(union lws_tls_cert_info_results * ci,lws_tls_kid_t * kid)28*1c60b9acSAndroid Build Coastguard Worker lws_tls_kid_copy(union lws_tls_cert_info_results *ci, lws_tls_kid_t *kid)
29*1c60b9acSAndroid Build Coastguard Worker {
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker 	/*
32*1c60b9acSAndroid Build Coastguard Worker 	 * KIDs all seem to be 20 bytes / SHA1 or less.  If we get one that
33*1c60b9acSAndroid Build Coastguard Worker 	 * is bigger, treat only the first 20 bytes as significant.
34*1c60b9acSAndroid Build Coastguard Worker 	 */
35*1c60b9acSAndroid Build Coastguard Worker 
36*1c60b9acSAndroid Build Coastguard Worker 	if ((size_t)ci->ns.len > sizeof(kid->kid))
37*1c60b9acSAndroid Build Coastguard Worker 		kid->kid_len = sizeof(kid->kid);
38*1c60b9acSAndroid Build Coastguard Worker 	else
39*1c60b9acSAndroid Build Coastguard Worker 		kid->kid_len = (uint8_t)ci->ns.len;
40*1c60b9acSAndroid Build Coastguard Worker 
41*1c60b9acSAndroid Build Coastguard Worker 	memcpy(kid->kid, ci->ns.name, kid->kid_len);
42*1c60b9acSAndroid Build Coastguard Worker }
43*1c60b9acSAndroid Build Coastguard Worker 
44*1c60b9acSAndroid Build Coastguard Worker void
lws_tls_kid_copy_kid(lws_tls_kid_t * kid,const lws_tls_kid_t * src)45*1c60b9acSAndroid Build Coastguard Worker lws_tls_kid_copy_kid(lws_tls_kid_t *kid, const lws_tls_kid_t *src)
46*1c60b9acSAndroid Build Coastguard Worker {
47*1c60b9acSAndroid Build Coastguard Worker 	int klen = sizeof(kid->kid);
48*1c60b9acSAndroid Build Coastguard Worker 
49*1c60b9acSAndroid Build Coastguard Worker 	if (src->kid_len < klen)
50*1c60b9acSAndroid Build Coastguard Worker 		klen = src->kid_len;
51*1c60b9acSAndroid Build Coastguard Worker 
52*1c60b9acSAndroid Build Coastguard Worker 	kid->kid_len = (uint8_t)klen;
53*1c60b9acSAndroid Build Coastguard Worker 
54*1c60b9acSAndroid Build Coastguard Worker 	memcpy(kid->kid, src->kid, (size_t)klen);
55*1c60b9acSAndroid Build Coastguard Worker }
56*1c60b9acSAndroid Build Coastguard Worker 
57*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_kid_cmp(const lws_tls_kid_t * a,const lws_tls_kid_t * b)58*1c60b9acSAndroid Build Coastguard Worker lws_tls_kid_cmp(const lws_tls_kid_t *a, const lws_tls_kid_t *b)
59*1c60b9acSAndroid Build Coastguard Worker {
60*1c60b9acSAndroid Build Coastguard Worker 	if (a->kid_len != b->kid_len)
61*1c60b9acSAndroid Build Coastguard Worker 		return 1;
62*1c60b9acSAndroid Build Coastguard Worker 
63*1c60b9acSAndroid Build Coastguard Worker 	return memcmp(a->kid, b->kid, a->kid_len);
64*1c60b9acSAndroid Build Coastguard Worker }
65*1c60b9acSAndroid Build Coastguard Worker 
66*1c60b9acSAndroid Build Coastguard Worker /*
67*1c60b9acSAndroid Build Coastguard Worker  * We have the SKID and AKID for every peer cert captured, but they may be
68*1c60b9acSAndroid Build Coastguard Worker  * in any order, and eg, falsely have sent the root CA, or an attacker may
69*1c60b9acSAndroid Build Coastguard Worker  * send unresolveable self-referencing loops of KIDs.
70*1c60b9acSAndroid Build Coastguard Worker  *
71*1c60b9acSAndroid Build Coastguard Worker  * Let's sort them into the SKID -> AKID hierarchy, so the last entry is the
72*1c60b9acSAndroid Build Coastguard Worker  * server cert and the first entry is the highest parent that the server sent.
73*1c60b9acSAndroid Build Coastguard Worker  * Normally the top one will be an intermediate, and its AKID is the ID of the
74*1c60b9acSAndroid Build Coastguard Worker  * root CA cert we would need to trust to validate the chain.
75*1c60b9acSAndroid Build Coastguard Worker  *
76*1c60b9acSAndroid Build Coastguard Worker  * It's not unknown the server is misconfigured to also send the root CA, if so
77*1c60b9acSAndroid Build Coastguard Worker  * the top slot's AKID is empty and we should look for its SKID in the trust
78*1c60b9acSAndroid Build Coastguard Worker  * blob.
79*1c60b9acSAndroid Build Coastguard Worker  *
80*1c60b9acSAndroid Build Coastguard Worker  * If we return 0, we succeeded and the AKID of ch[0] is the SKID we want to see
81*1c60b9acSAndroid Build Coastguard Worker  * try to import from the trust blob.
82*1c60b9acSAndroid Build Coastguard Worker  *
83*1c60b9acSAndroid Build Coastguard Worker  * If we return nonzero, we can't identify what we want and should abandon the
84*1c60b9acSAndroid Build Coastguard Worker  * connection.
85*1c60b9acSAndroid Build Coastguard Worker  */
86*1c60b9acSAndroid Build Coastguard Worker 
87*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_jit_trust_sort_kids(struct lws * wsi,lws_tls_kid_chain_t * ch)88*1c60b9acSAndroid Build Coastguard Worker lws_tls_jit_trust_sort_kids(struct lws *wsi, lws_tls_kid_chain_t *ch)
89*1c60b9acSAndroid Build Coastguard Worker {
90*1c60b9acSAndroid Build Coastguard Worker 	size_t hl;
91*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_jit_inflight_t *inf;
92*1c60b9acSAndroid Build Coastguard Worker 	int n, m, sanity = 10;
93*1c60b9acSAndroid Build Coastguard Worker 	const char *host = wsi->cli_hostname_copy;
94*1c60b9acSAndroid Build Coastguard Worker 	char more = 1;
95*1c60b9acSAndroid Build Coastguard Worker 
96*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s\n", __func__);
97*1c60b9acSAndroid Build Coastguard Worker 
98*1c60b9acSAndroid Build Coastguard Worker 	if (!host) {
99*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->stash && wsi->stash->cis[CIS_HOST])
100*1c60b9acSAndroid Build Coastguard Worker 			host = wsi->stash->cis[CIS_HOST];
101*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
102*1c60b9acSAndroid Build Coastguard Worker 		else
103*1c60b9acSAndroid Build Coastguard Worker 			host = lws_hdr_simple_ptr(wsi,
104*1c60b9acSAndroid Build Coastguard Worker 					      _WSI_TOKEN_CLIENT_PEER_ADDRESS);
105*1c60b9acSAndroid Build Coastguard Worker 	}
106*1c60b9acSAndroid Build Coastguard Worker #endif
107*1c60b9acSAndroid Build Coastguard Worker 	if (!host)
108*1c60b9acSAndroid Build Coastguard Worker 		return 1;
109*1c60b9acSAndroid Build Coastguard Worker 
110*1c60b9acSAndroid Build Coastguard Worker 	hl = strlen(host);
111*1c60b9acSAndroid Build Coastguard Worker 
112*1c60b9acSAndroid Build Coastguard Worker 	/* something to work with? */
113*1c60b9acSAndroid Build Coastguard Worker 
114*1c60b9acSAndroid Build Coastguard Worker 	if (!ch->count)
115*1c60b9acSAndroid Build Coastguard Worker 		return 1;
116*1c60b9acSAndroid Build Coastguard Worker 
117*1c60b9acSAndroid Build Coastguard Worker 	/* do we need to sort? */
118*1c60b9acSAndroid Build Coastguard Worker 
119*1c60b9acSAndroid Build Coastguard Worker 	if (ch->count > 1) {
120*1c60b9acSAndroid Build Coastguard Worker 
121*1c60b9acSAndroid Build Coastguard Worker 		/* okie... */
122*1c60b9acSAndroid Build Coastguard Worker 
123*1c60b9acSAndroid Build Coastguard Worker 		while (more) {
124*1c60b9acSAndroid Build Coastguard Worker 
125*1c60b9acSAndroid Build Coastguard Worker 			if (!sanity--)
126*1c60b9acSAndroid Build Coastguard Worker 				/* let's not get fooled into spinning */
127*1c60b9acSAndroid Build Coastguard Worker 				return 1;
128*1c60b9acSAndroid Build Coastguard Worker 
129*1c60b9acSAndroid Build Coastguard Worker 			more = 0;
130*1c60b9acSAndroid Build Coastguard Worker 			for (n = 0; n < ch->count - 1; n++) {
131*1c60b9acSAndroid Build Coastguard Worker 
132*1c60b9acSAndroid Build Coastguard Worker 				if (!lws_tls_kid_cmp(&ch->skid[n],
133*1c60b9acSAndroid Build Coastguard Worker 						     &ch->akid[n + 1]))
134*1c60b9acSAndroid Build Coastguard Worker 					/* next belongs with this one */
135*1c60b9acSAndroid Build Coastguard Worker 					continue;
136*1c60b9acSAndroid Build Coastguard Worker 
137*1c60b9acSAndroid Build Coastguard Worker 				/*
138*1c60b9acSAndroid Build Coastguard Worker 				 * next doesn't belong with this one, let's
139*1c60b9acSAndroid Build Coastguard Worker 				 * try to figure out where this one does belong
140*1c60b9acSAndroid Build Coastguard Worker 				 * then
141*1c60b9acSAndroid Build Coastguard Worker 				 */
142*1c60b9acSAndroid Build Coastguard Worker 
143*1c60b9acSAndroid Build Coastguard Worker 				for (m = 0; m < ch->count; m++) {
144*1c60b9acSAndroid Build Coastguard Worker 					if (n == m)
145*1c60b9acSAndroid Build Coastguard Worker 						continue;
146*1c60b9acSAndroid Build Coastguard Worker 					if (!lws_tls_kid_cmp(&ch->skid[n],
147*1c60b9acSAndroid Build Coastguard Worker 							     &ch->akid[m])) {
148*1c60b9acSAndroid Build Coastguard Worker 						lws_tls_kid_t t;
149*1c60b9acSAndroid Build Coastguard Worker 
150*1c60b9acSAndroid Build Coastguard Worker 						/*
151*1c60b9acSAndroid Build Coastguard Worker 						 * m references us, so we
152*1c60b9acSAndroid Build Coastguard Worker 						 * need to go one step above m,
153*1c60b9acSAndroid Build Coastguard Worker 						 * swap m and n
154*1c60b9acSAndroid Build Coastguard Worker 						 */
155*1c60b9acSAndroid Build Coastguard Worker 
156*1c60b9acSAndroid Build Coastguard Worker 						more = 1;
157*1c60b9acSAndroid Build Coastguard Worker 						t = ch->akid[m];
158*1c60b9acSAndroid Build Coastguard Worker 						ch->akid[m] = ch->akid[n];
159*1c60b9acSAndroid Build Coastguard Worker 						ch->akid[n] = t;
160*1c60b9acSAndroid Build Coastguard Worker 						t = ch->skid[m];
161*1c60b9acSAndroid Build Coastguard Worker 						ch->skid[m] = ch->skid[n];
162*1c60b9acSAndroid Build Coastguard Worker 						ch->skid[n] = t;
163*1c60b9acSAndroid Build Coastguard Worker 
164*1c60b9acSAndroid Build Coastguard Worker 						break;
165*1c60b9acSAndroid Build Coastguard Worker 					}
166*1c60b9acSAndroid Build Coastguard Worker 				}
167*1c60b9acSAndroid Build Coastguard Worker 
168*1c60b9acSAndroid Build Coastguard Worker 				if (more)
169*1c60b9acSAndroid Build Coastguard Worker 					break;
170*1c60b9acSAndroid Build Coastguard Worker 			}
171*1c60b9acSAndroid Build Coastguard Worker 		}
172*1c60b9acSAndroid Build Coastguard Worker 
173*1c60b9acSAndroid Build Coastguard Worker 		/* then we should be sorted */
174*1c60b9acSAndroid Build Coastguard Worker 	}
175*1c60b9acSAndroid Build Coastguard Worker 
176*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < ch->count; n++) {
177*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: AKID[%d]\n", __func__, n);
178*1c60b9acSAndroid Build Coastguard Worker 		lwsl_hexdump_info(ch->akid[n].kid, ch->akid[n].kid_len);
179*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: SKID[%d]\n", __func__, n);
180*1c60b9acSAndroid Build Coastguard Worker 		lwsl_hexdump_info(ch->skid[n].kid, ch->skid[n].kid_len);
181*1c60b9acSAndroid Build Coastguard Worker 	}
182*1c60b9acSAndroid Build Coastguard Worker 
183*1c60b9acSAndroid Build Coastguard Worker 	/* to go further, user must provide a lookup helper */
184*1c60b9acSAndroid Build Coastguard Worker 
185*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->a.context->system_ops ||
186*1c60b9acSAndroid Build Coastguard Worker 	    !wsi->a.context->system_ops->jit_trust_query)
187*1c60b9acSAndroid Build Coastguard Worker 		return 1;
188*1c60b9acSAndroid Build Coastguard Worker 
189*1c60b9acSAndroid Build Coastguard Worker 	/*
190*1c60b9acSAndroid Build Coastguard Worker 	 * If there's already a pending lookup for this host, let's bail and
191*1c60b9acSAndroid Build Coastguard Worker 	 * just wait for that to complete (since it will be done async if we
192*1c60b9acSAndroid Build Coastguard Worker 	 * can see it)
193*1c60b9acSAndroid Build Coastguard Worker 	 */
194*1c60b9acSAndroid Build Coastguard Worker 
195*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll(struct lws_dll2 *, d,
196*1c60b9acSAndroid Build Coastguard Worker 			      wsi->a.context->jit_inflight.head) {
197*1c60b9acSAndroid Build Coastguard Worker 		inf = lws_container_of(d, lws_tls_jit_inflight_t, list);
198*1c60b9acSAndroid Build Coastguard Worker 
199*1c60b9acSAndroid Build Coastguard Worker 		if (!strcmp((const char *)&inf[1], host))
200*1c60b9acSAndroid Build Coastguard Worker 			/* already being handled */
201*1c60b9acSAndroid Build Coastguard Worker 			return 1;
202*1c60b9acSAndroid Build Coastguard Worker 
203*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll(d);
204*1c60b9acSAndroid Build Coastguard Worker 
205*1c60b9acSAndroid Build Coastguard Worker 	/*
206*1c60b9acSAndroid Build Coastguard Worker 	 * No... let's make an inflight entry for this host, then
207*1c60b9acSAndroid Build Coastguard Worker 	 */
208*1c60b9acSAndroid Build Coastguard Worker 
209*1c60b9acSAndroid Build Coastguard Worker 	inf = lws_zalloc(sizeof(*inf) + hl + 1, __func__);
210*1c60b9acSAndroid Build Coastguard Worker 	if (!inf)
211*1c60b9acSAndroid Build Coastguard Worker 		return 1;
212*1c60b9acSAndroid Build Coastguard Worker 
213*1c60b9acSAndroid Build Coastguard Worker 	memcpy(&inf[1], host, hl + 1);
214*1c60b9acSAndroid Build Coastguard Worker 	inf->refcount = (char)ch->count;
215*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_add_tail(&inf->list, &wsi->a.context->jit_inflight);
216*1c60b9acSAndroid Build Coastguard Worker 
217*1c60b9acSAndroid Build Coastguard Worker 	/*
218*1c60b9acSAndroid Build Coastguard Worker 	 * ...kid_chain[0] AKID should indicate the right CA SKID that we want.
219*1c60b9acSAndroid Build Coastguard Worker 	 *
220*1c60b9acSAndroid Build Coastguard Worker 	 * Because of cross-signing, we check all of them and accept we may get
221*1c60b9acSAndroid Build Coastguard Worker 	 * multiple (the inflight accepts up to 2) CAs needed.
222*1c60b9acSAndroid Build Coastguard Worker 	 */
223*1c60b9acSAndroid Build Coastguard Worker 
224*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < ch->count; n++)
225*1c60b9acSAndroid Build Coastguard Worker 		wsi->a.context->system_ops->jit_trust_query(wsi->a.context,
226*1c60b9acSAndroid Build Coastguard Worker 			ch->akid[n].kid, (size_t)ch->akid[n].kid_len,
227*1c60b9acSAndroid Build Coastguard Worker 			(void *)inf);
228*1c60b9acSAndroid Build Coastguard Worker 
229*1c60b9acSAndroid Build Coastguard Worker 	return 0;
230*1c60b9acSAndroid Build Coastguard Worker }
231*1c60b9acSAndroid Build Coastguard Worker 
232*1c60b9acSAndroid Build Coastguard Worker static void
tag_to_vh_name(char * result,size_t max,uint32_t tag)233*1c60b9acSAndroid Build Coastguard Worker tag_to_vh_name(char *result, size_t max, uint32_t tag)
234*1c60b9acSAndroid Build Coastguard Worker {
235*1c60b9acSAndroid Build Coastguard Worker 	lws_snprintf(result, max, "jitt-%08X", tag);
236*1c60b9acSAndroid Build Coastguard Worker }
237*1c60b9acSAndroid Build Coastguard Worker 
238*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_jit_trust_vhost_bind(struct lws_context * cx,const char * address,struct lws_vhost ** pvh)239*1c60b9acSAndroid Build Coastguard Worker lws_tls_jit_trust_vhost_bind(struct lws_context *cx, const char *address,
240*1c60b9acSAndroid Build Coastguard Worker 			     struct lws_vhost **pvh)
241*1c60b9acSAndroid Build Coastguard Worker {
242*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_jit_cache_item_t *ci, jci;
243*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_jit_inflight_t *inf;
244*1c60b9acSAndroid Build Coastguard Worker 	char vhtag[32];
245*1c60b9acSAndroid Build Coastguard Worker 	size_t size;
246*1c60b9acSAndroid Build Coastguard Worker 	int n;
247*1c60b9acSAndroid Build Coastguard Worker 
248*1c60b9acSAndroid Build Coastguard Worker 	if (lws_cache_item_get(cx->trust_cache, address, (const void **)&ci,
249*1c60b9acSAndroid Build Coastguard Worker 									&size))
250*1c60b9acSAndroid Build Coastguard Worker 		/*
251*1c60b9acSAndroid Build Coastguard Worker 		 * There's no cached info, we have to start from scratch on
252*1c60b9acSAndroid Build Coastguard Worker 		 * this one
253*1c60b9acSAndroid Build Coastguard Worker 		 */
254*1c60b9acSAndroid Build Coastguard Worker 		return 1;
255*1c60b9acSAndroid Build Coastguard Worker 
256*1c60b9acSAndroid Build Coastguard Worker 	/* gotten cache item may be evicted by jit_trust_query */
257*1c60b9acSAndroid Build Coastguard Worker 	jci = *ci;
258*1c60b9acSAndroid Build Coastguard Worker 
259*1c60b9acSAndroid Build Coastguard Worker 	/*
260*1c60b9acSAndroid Build Coastguard Worker 	 * We have some trust cache information for this host already, it tells
261*1c60b9acSAndroid Build Coastguard Worker 	 * us the trusted CA SKIDs we found before, and the xor tag used to name
262*1c60b9acSAndroid Build Coastguard Worker 	 * the vhost configured for these trust CAs in its SSL_CTX.
263*1c60b9acSAndroid Build Coastguard Worker 	 *
264*1c60b9acSAndroid Build Coastguard Worker 	 * Let's check first if the correct prepared vhost already exists, if
265*1c60b9acSAndroid Build Coastguard Worker 	 * so, we can just bind to that and go.
266*1c60b9acSAndroid Build Coastguard Worker 	 */
267*1c60b9acSAndroid Build Coastguard Worker 
268*1c60b9acSAndroid Build Coastguard Worker 	tag_to_vh_name(vhtag, sizeof(vhtag), jci.xor_tag);
269*1c60b9acSAndroid Build Coastguard Worker 
270*1c60b9acSAndroid Build Coastguard Worker 	*pvh = lws_get_vhost_by_name(cx, vhtag);
271*1c60b9acSAndroid Build Coastguard Worker 	if (*pvh) {
272*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %s -> existing %s\n", __func__, address, vhtag);
273*1c60b9acSAndroid Build Coastguard Worker 		/* hit, let's just use that then */
274*1c60b9acSAndroid Build Coastguard Worker 		return 0;
275*1c60b9acSAndroid Build Coastguard Worker 	}
276*1c60b9acSAndroid Build Coastguard Worker 
277*1c60b9acSAndroid Build Coastguard Worker 	/*
278*1c60b9acSAndroid Build Coastguard Worker 	 * ... so, we know the SKIDs of the missing CAs, but we don't have the
279*1c60b9acSAndroid Build Coastguard Worker 	 * DERs for them, and so no configured vhost trusting them yet.  We have
280*1c60b9acSAndroid Build Coastguard Worker 	 * had the DERs at some point, but we can't afford to cache them, so
281*1c60b9acSAndroid Build Coastguard Worker 	 * we will have to get them again.
282*1c60b9acSAndroid Build Coastguard Worker 	 *
283*1c60b9acSAndroid Build Coastguard Worker 	 * Let's make an inflight for this, it will create the vhost when it
284*1c60b9acSAndroid Build Coastguard Worker 	 * completes.  If syncrhronous, then it will complete before we leave
285*1c60b9acSAndroid Build Coastguard Worker 	 * here, otherwise it will have a life of its own until all the
286*1c60b9acSAndroid Build Coastguard Worker 	 * queries use the cb to succeed or fail.
287*1c60b9acSAndroid Build Coastguard Worker 	 */
288*1c60b9acSAndroid Build Coastguard Worker 
289*1c60b9acSAndroid Build Coastguard Worker 	size = strlen(address);
290*1c60b9acSAndroid Build Coastguard Worker 	inf = lws_zalloc(sizeof(*inf) + size + 1, __func__);
291*1c60b9acSAndroid Build Coastguard Worker 	if (!inf)
292*1c60b9acSAndroid Build Coastguard Worker 		return 1;
293*1c60b9acSAndroid Build Coastguard Worker 
294*1c60b9acSAndroid Build Coastguard Worker 	memcpy(&inf[1], address, size + 1);
295*1c60b9acSAndroid Build Coastguard Worker 	inf->refcount = (char)jci.count_skids;
296*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_add_tail(&inf->list, &cx->jit_inflight);
297*1c60b9acSAndroid Build Coastguard Worker 
298*1c60b9acSAndroid Build Coastguard Worker 	/*
299*1c60b9acSAndroid Build Coastguard Worker 	 * ...kid_chain[0] AKID should indicate the right CA SKID that we want.
300*1c60b9acSAndroid Build Coastguard Worker 	 *
301*1c60b9acSAndroid Build Coastguard Worker 	 * Because of cross-signing, we check all of them and accept we may get
302*1c60b9acSAndroid Build Coastguard Worker 	 * multiple (we can handle 3) CAs needed.
303*1c60b9acSAndroid Build Coastguard Worker 	 */
304*1c60b9acSAndroid Build Coastguard Worker 
305*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < jci.count_skids; n++)
306*1c60b9acSAndroid Build Coastguard Worker 		cx->system_ops->jit_trust_query(cx, jci.skids[n].kid,
307*1c60b9acSAndroid Build Coastguard Worker 						(size_t)jci.skids[n].kid_len,
308*1c60b9acSAndroid Build Coastguard Worker 						(void *)inf);
309*1c60b9acSAndroid Build Coastguard Worker 
310*1c60b9acSAndroid Build Coastguard Worker 	/* ... in case synchronous and it already finished the queries */
311*1c60b9acSAndroid Build Coastguard Worker 
312*1c60b9acSAndroid Build Coastguard Worker 	*pvh = lws_get_vhost_by_name(cx, vhtag);
313*1c60b9acSAndroid Build Coastguard Worker 	if (*pvh) {
314*1c60b9acSAndroid Build Coastguard Worker 		/* hit, let's just use that then */
315*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: bind to created vhost %s\n", __func__, vhtag);
316*1c60b9acSAndroid Build Coastguard Worker 		return 0;
317*1c60b9acSAndroid Build Coastguard Worker 	} else
318*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: unable to bind to %s\n", __func__, vhtag);
319*1c60b9acSAndroid Build Coastguard Worker 
320*1c60b9acSAndroid Build Coastguard Worker 	/* right now, nothing to offer */
321*1c60b9acSAndroid Build Coastguard Worker 
322*1c60b9acSAndroid Build Coastguard Worker 	return 1;
323*1c60b9acSAndroid Build Coastguard Worker }
324*1c60b9acSAndroid Build Coastguard Worker 
325*1c60b9acSAndroid Build Coastguard Worker void
lws_tls_jit_trust_inflight_destroy(lws_tls_jit_inflight_t * inf)326*1c60b9acSAndroid Build Coastguard Worker lws_tls_jit_trust_inflight_destroy(lws_tls_jit_inflight_t *inf)
327*1c60b9acSAndroid Build Coastguard Worker {
328*1c60b9acSAndroid Build Coastguard Worker 	int n;
329*1c60b9acSAndroid Build Coastguard Worker 
330*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < inf->ders; n++)
331*1c60b9acSAndroid Build Coastguard Worker 		lws_free_set_NULL(inf->der[n]);
332*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_remove(&inf->list);
333*1c60b9acSAndroid Build Coastguard Worker 
334*1c60b9acSAndroid Build Coastguard Worker 	lws_free(inf);
335*1c60b9acSAndroid Build Coastguard Worker }
336*1c60b9acSAndroid Build Coastguard Worker 
337*1c60b9acSAndroid Build Coastguard Worker static int
inflight_destroy(struct lws_dll2 * d,void * user)338*1c60b9acSAndroid Build Coastguard Worker inflight_destroy(struct lws_dll2 *d, void *user)
339*1c60b9acSAndroid Build Coastguard Worker {
340*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_jit_inflight_t *inf;
341*1c60b9acSAndroid Build Coastguard Worker 
342*1c60b9acSAndroid Build Coastguard Worker 	inf = lws_container_of(d, lws_tls_jit_inflight_t, list);
343*1c60b9acSAndroid Build Coastguard Worker 
344*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_jit_trust_inflight_destroy(inf);
345*1c60b9acSAndroid Build Coastguard Worker 
346*1c60b9acSAndroid Build Coastguard Worker 	return 0;
347*1c60b9acSAndroid Build Coastguard Worker }
348*1c60b9acSAndroid Build Coastguard Worker 
349*1c60b9acSAndroid Build Coastguard Worker void
lws_tls_jit_trust_inflight_destroy_all(struct lws_context * cx)350*1c60b9acSAndroid Build Coastguard Worker lws_tls_jit_trust_inflight_destroy_all(struct lws_context *cx)
351*1c60b9acSAndroid Build Coastguard Worker {
352*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_foreach_safe(&cx->jit_inflight, cx, inflight_destroy);
353*1c60b9acSAndroid Build Coastguard Worker }
354*1c60b9acSAndroid Build Coastguard Worker 
355*1c60b9acSAndroid Build Coastguard Worker static void
unref_vh_grace_cb(lws_sorted_usec_list_t * sul)356*1c60b9acSAndroid Build Coastguard Worker unref_vh_grace_cb(lws_sorted_usec_list_t *sul)
357*1c60b9acSAndroid Build Coastguard Worker {
358*1c60b9acSAndroid Build Coastguard Worker 	struct lws_vhost *vh = lws_container_of(sul, struct lws_vhost,
359*1c60b9acSAndroid Build Coastguard Worker 						sul_unref);
360*1c60b9acSAndroid Build Coastguard Worker 
361*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %s\n", __func__, vh->lc.gutag);
362*1c60b9acSAndroid Build Coastguard Worker 
363*1c60b9acSAndroid Build Coastguard Worker 	lws_vhost_destroy(vh);
364*1c60b9acSAndroid Build Coastguard Worker }
365*1c60b9acSAndroid Build Coastguard Worker 
366*1c60b9acSAndroid Build Coastguard Worker void
lws_tls_jit_trust_vh_start_grace(struct lws_vhost * vh)367*1c60b9acSAndroid Build Coastguard Worker lws_tls_jit_trust_vh_start_grace(struct lws_vhost *vh)
368*1c60b9acSAndroid Build Coastguard Worker {
369*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %s: unused, grace %dms\n", __func__, vh->lc.gutag,
370*1c60b9acSAndroid Build Coastguard Worker 			vh->context->vh_idle_grace_ms);
371*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_schedule(vh->context, 0, &vh->sul_unref, unref_vh_grace_cb,
372*1c60b9acSAndroid Build Coastguard Worker 			 (lws_usec_t)vh->context->vh_idle_grace_ms *
373*1c60b9acSAndroid Build Coastguard Worker 								LWS_US_PER_MS);
374*1c60b9acSAndroid Build Coastguard Worker }
375*1c60b9acSAndroid Build Coastguard Worker 
376*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
377*1c60b9acSAndroid Build Coastguard Worker static void
lws_tls_jit_trust_cert_info(const uint8_t * der,size_t der_len)378*1c60b9acSAndroid Build Coastguard Worker lws_tls_jit_trust_cert_info(const uint8_t *der, size_t der_len)
379*1c60b9acSAndroid Build Coastguard Worker {
380*1c60b9acSAndroid Build Coastguard Worker 	struct lws_x509_cert *x;
381*1c60b9acSAndroid Build Coastguard Worker 	union lws_tls_cert_info_results *u;
382*1c60b9acSAndroid Build Coastguard Worker 	char p = 0, buf[192 + sizeof(*u)];
383*1c60b9acSAndroid Build Coastguard Worker 
384*1c60b9acSAndroid Build Coastguard Worker 	if (lws_x509_create(&x))
385*1c60b9acSAndroid Build Coastguard Worker 		return;
386*1c60b9acSAndroid Build Coastguard Worker 
387*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_x509_parse_from_pem(x, der, der_len)) {
388*1c60b9acSAndroid Build Coastguard Worker 
389*1c60b9acSAndroid Build Coastguard Worker 		u = (union lws_tls_cert_info_results *)buf;
390*1c60b9acSAndroid Build Coastguard Worker 
391*1c60b9acSAndroid Build Coastguard Worker 		if (!lws_x509_info(x, LWS_TLS_CERT_INFO_ISSUER_NAME, u, 192)) {
392*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("ISS: %s\n", u->ns.name);
393*1c60b9acSAndroid Build Coastguard Worker 			p = 1;
394*1c60b9acSAndroid Build Coastguard Worker 		}
395*1c60b9acSAndroid Build Coastguard Worker 		if (!lws_x509_info(x, LWS_TLS_CERT_INFO_COMMON_NAME, u, 192)) {
396*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("CN: %s\n", u->ns.name);
397*1c60b9acSAndroid Build Coastguard Worker 			p = 1;
398*1c60b9acSAndroid Build Coastguard Worker 		}
399*1c60b9acSAndroid Build Coastguard Worker 
400*1c60b9acSAndroid Build Coastguard Worker 		if (!p) {
401*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: unable to get any info\n", __func__);
402*1c60b9acSAndroid Build Coastguard Worker 			lwsl_hexdump_err(der, der_len);
403*1c60b9acSAndroid Build Coastguard Worker 		}
404*1c60b9acSAndroid Build Coastguard Worker 	} else
405*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: unable to load DER\n", __func__);
406*1c60b9acSAndroid Build Coastguard Worker 
407*1c60b9acSAndroid Build Coastguard Worker 	lws_x509_destroy(&x);
408*1c60b9acSAndroid Build Coastguard Worker }
409*1c60b9acSAndroid Build Coastguard Worker #endif
410*1c60b9acSAndroid Build Coastguard Worker 
411*1c60b9acSAndroid Build Coastguard Worker /*
412*1c60b9acSAndroid Build Coastguard Worker  * This processes the JIT Trust lookup results independent of the tls backend.
413*1c60b9acSAndroid Build Coastguard Worker  */
414*1c60b9acSAndroid Build Coastguard Worker 
415*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_jit_trust_got_cert_cb(struct lws_context * cx,void * got_opaque,const uint8_t * skid,size_t skid_len,const uint8_t * der,size_t der_len)416*1c60b9acSAndroid Build Coastguard Worker lws_tls_jit_trust_got_cert_cb(struct lws_context *cx, void *got_opaque,
417*1c60b9acSAndroid Build Coastguard Worker 			      const uint8_t *skid, size_t skid_len,
418*1c60b9acSAndroid Build Coastguard Worker 			      const uint8_t *der, size_t der_len)
419*1c60b9acSAndroid Build Coastguard Worker {
420*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_jit_inflight_t *inf = (lws_tls_jit_inflight_t *)got_opaque;
421*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_creation_info info;
422*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_jit_cache_item_t jci;
423*1c60b9acSAndroid Build Coastguard Worker 	struct lws_vhost *v;
424*1c60b9acSAndroid Build Coastguard Worker 	char vhtag[20];
425*1c60b9acSAndroid Build Coastguard Worker 	char hit = 0;
426*1c60b9acSAndroid Build Coastguard Worker 	int n;
427*1c60b9acSAndroid Build Coastguard Worker 
428*1c60b9acSAndroid Build Coastguard Worker 	/*
429*1c60b9acSAndroid Build Coastguard Worker 	 * Before anything else, check the inf is still valid.  In the low
430*1c60b9acSAndroid Build Coastguard Worker 	 * probability but possible case it was reallocated to be a different
431*1c60b9acSAndroid Build Coastguard Worker 	 * inflight, that may cause different CA certs to apply to a connection,
432*1c60b9acSAndroid Build Coastguard Worker 	 * but since mbedtls will then validate the server cert using the wrong
433*1c60b9acSAndroid Build Coastguard Worker 	 * trusted CA, it will just cause temporary conn fail.
434*1c60b9acSAndroid Build Coastguard Worker 	 */
435*1c60b9acSAndroid Build Coastguard Worker 
436*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll(struct lws_dll2 *, e, cx->jit_inflight.head) {
437*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_jit_inflight_t *i = lws_container_of(e,
438*1c60b9acSAndroid Build Coastguard Worker 						lws_tls_jit_inflight_t, list);
439*1c60b9acSAndroid Build Coastguard Worker 		if (i == inf) {
440*1c60b9acSAndroid Build Coastguard Worker 			hit = 1;
441*1c60b9acSAndroid Build Coastguard Worker 			break;
442*1c60b9acSAndroid Build Coastguard Worker 		}
443*1c60b9acSAndroid Build Coastguard Worker 
444*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll(e);
445*1c60b9acSAndroid Build Coastguard Worker 
446*1c60b9acSAndroid Build Coastguard Worker 	if (!hit)
447*1c60b9acSAndroid Build Coastguard Worker 		/* inf has already gone */
448*1c60b9acSAndroid Build Coastguard Worker 		return 1;
449*1c60b9acSAndroid Build Coastguard Worker 
450*1c60b9acSAndroid Build Coastguard Worker 	inf->refcount--;
451*1c60b9acSAndroid Build Coastguard Worker 
452*1c60b9acSAndroid Build Coastguard Worker 	if (skid_len >= 4)
453*1c60b9acSAndroid Build Coastguard Worker 		inf->tag ^= *((uint32_t *)skid);
454*1c60b9acSAndroid Build Coastguard Worker 
455*1c60b9acSAndroid Build Coastguard Worker 	if (der && inf->ders < (int)LWS_ARRAY_SIZE(inf->der) && inf->refcount) {
456*1c60b9acSAndroid Build Coastguard Worker 		/*
457*1c60b9acSAndroid Build Coastguard Worker 		 * We have a trusted CA, but more results coming... stash it
458*1c60b9acSAndroid Build Coastguard Worker 		 * in heap.
459*1c60b9acSAndroid Build Coastguard Worker 		 */
460*1c60b9acSAndroid Build Coastguard Worker 
461*1c60b9acSAndroid Build Coastguard Worker 		inf->kid[inf->ders].kid_len = (uint8_t)((skid_len >
462*1c60b9acSAndroid Build Coastguard Worker 				     (uint8_t)sizeof(inf->kid[inf->ders].kid)) ?
463*1c60b9acSAndroid Build Coastguard Worker 				     sizeof(inf->kid[inf->ders].kid) : skid_len);
464*1c60b9acSAndroid Build Coastguard Worker 		memcpy(inf->kid[inf->ders].kid, skid,
465*1c60b9acSAndroid Build Coastguard Worker 		       inf->kid[inf->ders].kid_len);
466*1c60b9acSAndroid Build Coastguard Worker 
467*1c60b9acSAndroid Build Coastguard Worker 		inf->der[inf->ders] = lws_malloc(der_len, __func__);
468*1c60b9acSAndroid Build Coastguard Worker 		if (!inf->der[inf->ders])
469*1c60b9acSAndroid Build Coastguard Worker 			return 1;
470*1c60b9acSAndroid Build Coastguard Worker 		memcpy(inf->der[inf->ders], der, der_len);
471*1c60b9acSAndroid Build Coastguard Worker 		inf->der_len[inf->ders] = (short)der_len;
472*1c60b9acSAndroid Build Coastguard Worker 		inf->ders++;
473*1c60b9acSAndroid Build Coastguard Worker 
474*1c60b9acSAndroid Build Coastguard Worker 		return 0;
475*1c60b9acSAndroid Build Coastguard Worker 	}
476*1c60b9acSAndroid Build Coastguard Worker 
477*1c60b9acSAndroid Build Coastguard Worker 	/*
478*1c60b9acSAndroid Build Coastguard Worker 	 * We accept up to three valid CA, and then end the inflight early.
479*1c60b9acSAndroid Build Coastguard Worker 	 * Any further pending results are dropped, since we got all we could
480*1c60b9acSAndroid Build Coastguard Worker 	 * use.  Up to two valid CA would be held in the inflight and the other
481*1c60b9acSAndroid Build Coastguard Worker 	 * provided in the params.
482*1c60b9acSAndroid Build Coastguard Worker 	 *
483*1c60b9acSAndroid Build Coastguard Worker 	 * If we did not already fill up the inflight, keep waiting for any
484*1c60b9acSAndroid Build Coastguard Worker 	 * others expected
485*1c60b9acSAndroid Build Coastguard Worker 	 */
486*1c60b9acSAndroid Build Coastguard Worker 
487*1c60b9acSAndroid Build Coastguard Worker 	if (inf->refcount && inf->ders < (int)LWS_ARRAY_SIZE(inf->der))
488*1c60b9acSAndroid Build Coastguard Worker 		return 0;
489*1c60b9acSAndroid Build Coastguard Worker 
490*1c60b9acSAndroid Build Coastguard Worker 	if (!der && !inf->ders) {
491*1c60b9acSAndroid Build Coastguard Worker 		lwsl_warn("%s: no trusted CA certs matching\n", __func__);
492*1c60b9acSAndroid Build Coastguard Worker 
493*1c60b9acSAndroid Build Coastguard Worker 		goto destroy_inf;
494*1c60b9acSAndroid Build Coastguard Worker 	}
495*1c60b9acSAndroid Build Coastguard Worker 
496*1c60b9acSAndroid Build Coastguard Worker 	tag_to_vh_name(vhtag, sizeof(vhtag), inf->tag);
497*1c60b9acSAndroid Build Coastguard Worker 
498*1c60b9acSAndroid Build Coastguard Worker 	/*
499*1c60b9acSAndroid Build Coastguard Worker 	 * We have got at least one CA, it's all the CAs we're going to get,
500*1c60b9acSAndroid Build Coastguard Worker 	 * or that we can handle.  So we have to process and drop the inf.
501*1c60b9acSAndroid Build Coastguard Worker 	 *
502*1c60b9acSAndroid Build Coastguard Worker 	 * First let's make a cache entry with a shortish ttl, mapping the
503*1c60b9acSAndroid Build Coastguard Worker 	 * hostname we were trying to connect to, to the SKIDs that actually
504*1c60b9acSAndroid Build Coastguard Worker 	 * had trust results.  This may come in handy later when we want to
505*1c60b9acSAndroid Build Coastguard Worker 	 * connect to the same host again, but any vhost from before has been
506*1c60b9acSAndroid Build Coastguard Worker 	 * removed... we can just ask for the specific CAs to regenerate the
507*1c60b9acSAndroid Build Coastguard Worker 	 * vhost, without having to first fail the connection attempt to get the
508*1c60b9acSAndroid Build Coastguard Worker 	 * server cert.
509*1c60b9acSAndroid Build Coastguard Worker 	 *
510*1c60b9acSAndroid Build Coastguard Worker 	 * The cache entry can be evicted at any time, so it is selfcontained.
511*1c60b9acSAndroid Build Coastguard Worker 	 * If it's also lost, we start over with the initial failing connection
512*1c60b9acSAndroid Build Coastguard Worker 	 * to figure out what we need to make it work.
513*1c60b9acSAndroid Build Coastguard Worker 	 */
514*1c60b9acSAndroid Build Coastguard Worker 
515*1c60b9acSAndroid Build Coastguard Worker 	memset(&jci, 0, sizeof(jci));
516*1c60b9acSAndroid Build Coastguard Worker 
517*1c60b9acSAndroid Build Coastguard Worker 	jci.xor_tag = inf->tag;
518*1c60b9acSAndroid Build Coastguard Worker 
519*1c60b9acSAndroid Build Coastguard Worker 	/* copy the SKIDs from the inflight and params into the cache item */
520*1c60b9acSAndroid Build Coastguard Worker 
521*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < (int)LWS_ARRAY_SIZE(inf->der); n++)
522*1c60b9acSAndroid Build Coastguard Worker 		if (inf->kid[n].kid_len)
523*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_kid_copy_kid(&jci.skids[jci.count_skids++],
524*1c60b9acSAndroid Build Coastguard Worker 						&inf->kid[n]);
525*1c60b9acSAndroid Build Coastguard Worker 
526*1c60b9acSAndroid Build Coastguard Worker 	if (skid_len) {
527*1c60b9acSAndroid Build Coastguard Worker 		if (skid_len > sizeof(inf->kid[0].kid))
528*1c60b9acSAndroid Build Coastguard Worker 			skid_len = sizeof(inf->kid[0].kid);
529*1c60b9acSAndroid Build Coastguard Worker 		jci.skids[jci.count_skids].kid_len = (uint8_t)skid_len;
530*1c60b9acSAndroid Build Coastguard Worker 		memcpy(jci.skids[jci.count_skids++].kid, skid, skid_len);
531*1c60b9acSAndroid Build Coastguard Worker 	}
532*1c60b9acSAndroid Build Coastguard Worker 
533*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: adding cache mapping %s -> %s\n", __func__,
534*1c60b9acSAndroid Build Coastguard Worker 			(const char *)&inf[1], vhtag);
535*1c60b9acSAndroid Build Coastguard Worker 
536*1c60b9acSAndroid Build Coastguard Worker 	if (lws_cache_write_through(cx->trust_cache, (const char *)&inf[1],
537*1c60b9acSAndroid Build Coastguard Worker 				    (const uint8_t *)&jci, sizeof(jci),
538*1c60b9acSAndroid Build Coastguard Worker 				    lws_now_usecs() + (3600ll *LWS_US_PER_SEC),
539*1c60b9acSAndroid Build Coastguard Worker 				    NULL))
540*1c60b9acSAndroid Build Coastguard Worker 		lwsl_warn("%s: add to cache failed\n", __func__);
541*1c60b9acSAndroid Build Coastguard Worker 
542*1c60b9acSAndroid Build Coastguard Worker 	/* is there already a vhost for this commutative-xor SKID trust? */
543*1c60b9acSAndroid Build Coastguard Worker 
544*1c60b9acSAndroid Build Coastguard Worker 	if (lws_get_vhost_by_name(cx, vhtag)) {
545*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: tag vhost %s already exists, skipping\n",
546*1c60b9acSAndroid Build Coastguard Worker 				__func__, vhtag);
547*1c60b9acSAndroid Build Coastguard Worker 		goto destroy_inf;
548*1c60b9acSAndroid Build Coastguard Worker 	}
549*1c60b9acSAndroid Build Coastguard Worker 
550*1c60b9acSAndroid Build Coastguard Worker 	/*
551*1c60b9acSAndroid Build Coastguard Worker 	 * We only end up here when we attempted a connection to this hostname.
552*1c60b9acSAndroid Build Coastguard Worker 	 *
553*1c60b9acSAndroid Build Coastguard Worker 	 * We have the identified CA trust DER(s) to hand, let's create the
554*1c60b9acSAndroid Build Coastguard Worker 	 * necessary vhost + prepared SSL_CTX for it to use on the retry, it
555*1c60b9acSAndroid Build Coastguard Worker 	 * will be used straight away if the retry comes before the idle vhost
556*1c60b9acSAndroid Build Coastguard Worker 	 * timeout.
557*1c60b9acSAndroid Build Coastguard Worker 	 *
558*1c60b9acSAndroid Build Coastguard Worker 	 * We also use this path in the case we have the cache entry but no
559*1c60b9acSAndroid Build Coastguard Worker 	 * matching vhost already existing, to create one.
560*1c60b9acSAndroid Build Coastguard Worker 	 */
561*1c60b9acSAndroid Build Coastguard Worker 
562*1c60b9acSAndroid Build Coastguard Worker 	memset(&info, 0, sizeof(info));
563*1c60b9acSAndroid Build Coastguard Worker 	info.vhost_name = vhtag;
564*1c60b9acSAndroid Build Coastguard Worker 	info.port = CONTEXT_PORT_NO_LISTEN;
565*1c60b9acSAndroid Build Coastguard Worker 	info.options = cx->options;
566*1c60b9acSAndroid Build Coastguard Worker 
567*1c60b9acSAndroid Build Coastguard Worker 	/*
568*1c60b9acSAndroid Build Coastguard Worker 	 * We have to create the vhost with the first valid trusted DER...
569*1c60b9acSAndroid Build Coastguard Worker 	 * if we have a params one, use that so the rest are all from inflight
570*1c60b9acSAndroid Build Coastguard Worker 	 */
571*1c60b9acSAndroid Build Coastguard Worker 
572*1c60b9acSAndroid Build Coastguard Worker 	if (der) {
573*1c60b9acSAndroid Build Coastguard Worker 		info.client_ssl_ca_mem = der;
574*1c60b9acSAndroid Build Coastguard Worker 		info.client_ssl_ca_mem_len = (unsigned int)der_len;
575*1c60b9acSAndroid Build Coastguard Worker 		n = 0;
576*1c60b9acSAndroid Build Coastguard Worker 	} else {
577*1c60b9acSAndroid Build Coastguard Worker 		info.client_ssl_ca_mem = inf->der[0];
578*1c60b9acSAndroid Build Coastguard Worker 		info.client_ssl_ca_mem_len = (unsigned int)inf->der_len[0];
579*1c60b9acSAndroid Build Coastguard Worker 		n = 1;
580*1c60b9acSAndroid Build Coastguard Worker 	}
581*1c60b9acSAndroid Build Coastguard Worker 
582*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
583*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_jit_trust_cert_info(info.client_ssl_ca_mem,
584*1c60b9acSAndroid Build Coastguard Worker 				    info.client_ssl_ca_mem_len);
585*1c60b9acSAndroid Build Coastguard Worker #endif
586*1c60b9acSAndroid Build Coastguard Worker 
587*1c60b9acSAndroid Build Coastguard Worker 	info.protocols = cx->protocols_copy;
588*1c60b9acSAndroid Build Coastguard Worker 
589*1c60b9acSAndroid Build Coastguard Worker 	v = lws_create_vhost(cx, &info);
590*1c60b9acSAndroid Build Coastguard Worker 	if (!v)
591*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: failed to create vh %s\n", __func__, vhtag);
592*1c60b9acSAndroid Build Coastguard Worker 
593*1c60b9acSAndroid Build Coastguard Worker 	v->grace_after_unref = 1;
594*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_jit_trust_vh_start_grace(v);
595*1c60b9acSAndroid Build Coastguard Worker 
596*1c60b9acSAndroid Build Coastguard Worker 	/*
597*1c60b9acSAndroid Build Coastguard Worker 	 * Do we need to add more trusted certs from inflight?
598*1c60b9acSAndroid Build Coastguard Worker 	 */
599*1c60b9acSAndroid Build Coastguard Worker 
600*1c60b9acSAndroid Build Coastguard Worker 	while (n < inf->ders) {
601*1c60b9acSAndroid Build Coastguard Worker 
602*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
603*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_jit_trust_cert_info(inf->der[n],
604*1c60b9acSAndroid Build Coastguard Worker 					    (size_t)inf->der_len[n]);
605*1c60b9acSAndroid Build Coastguard Worker #endif
606*1c60b9acSAndroid Build Coastguard Worker 
607*1c60b9acSAndroid Build Coastguard Worker 		if (lws_tls_client_vhost_extra_cert_mem(v, inf->der[n],
608*1c60b9acSAndroid Build Coastguard Worker 						(size_t)inf->der_len[n]))
609*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: add extra cert failed\n", __func__);
610*1c60b9acSAndroid Build Coastguard Worker 		n++;
611*1c60b9acSAndroid Build Coastguard Worker 	}
612*1c60b9acSAndroid Build Coastguard Worker 
613*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: created jitt %s -> vh %s\n", __func__,
614*1c60b9acSAndroid Build Coastguard Worker 				(const char *)&inf[1], vhtag);
615*1c60b9acSAndroid Build Coastguard Worker 
616*1c60b9acSAndroid Build Coastguard Worker destroy_inf:
617*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_jit_trust_inflight_destroy(inf);
618*1c60b9acSAndroid Build Coastguard Worker 
619*1c60b9acSAndroid Build Coastguard Worker 	return 0;
620*1c60b9acSAndroid Build Coastguard Worker }
621*1c60b9acSAndroid Build Coastguard Worker 
622*1c60b9acSAndroid Build Coastguard Worker /*
623*1c60b9acSAndroid Build Coastguard Worker  * Refer to ./READMEs/README.jit-trust.md for blob layout specification
624*1c60b9acSAndroid Build Coastguard Worker  */
625*1c60b9acSAndroid Build Coastguard Worker 
626*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_jit_trust_blob_queury_skid(const void * _blob,size_t blen,const uint8_t * skid,size_t skid_len,const uint8_t ** prpder,size_t * prder_len)627*1c60b9acSAndroid Build Coastguard Worker lws_tls_jit_trust_blob_queury_skid(const void *_blob, size_t blen,
628*1c60b9acSAndroid Build Coastguard Worker 				   const uint8_t *skid, size_t skid_len,
629*1c60b9acSAndroid Build Coastguard Worker 				   const uint8_t **prpder, size_t *prder_len)
630*1c60b9acSAndroid Build Coastguard Worker {
631*1c60b9acSAndroid Build Coastguard Worker 	const uint8_t *pskidlen, *pskids, *pder, *blob = (uint8_t *)_blob;
632*1c60b9acSAndroid Build Coastguard Worker 	const uint16_t *pderlen;
633*1c60b9acSAndroid Build Coastguard Worker 	int certs;
634*1c60b9acSAndroid Build Coastguard Worker 
635*1c60b9acSAndroid Build Coastguard Worker 	/* sanity check blob length and magic */
636*1c60b9acSAndroid Build Coastguard Worker 
637*1c60b9acSAndroid Build Coastguard Worker 	if (blen < 32768 ||
638*1c60b9acSAndroid Build Coastguard Worker 	   lws_ser_ru32be(blob) != LWS_JIT_TRUST_MAGIC_BE ||
639*1c60b9acSAndroid Build Coastguard Worker 	   lws_ser_ru32be(blob + LJT_OFS_END) != blen) {
640*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: blob not sane\n", __func__);
641*1c60b9acSAndroid Build Coastguard Worker 
642*1c60b9acSAndroid Build Coastguard Worker 		return -1;
643*1c60b9acSAndroid Build Coastguard Worker 	}
644*1c60b9acSAndroid Build Coastguard Worker 
645*1c60b9acSAndroid Build Coastguard Worker 	if (!skid_len)
646*1c60b9acSAndroid Build Coastguard Worker 		return 1;
647*1c60b9acSAndroid Build Coastguard Worker 
648*1c60b9acSAndroid Build Coastguard Worker 	/* point into the various sub-tables */
649*1c60b9acSAndroid Build Coastguard Worker 
650*1c60b9acSAndroid Build Coastguard Worker 	certs		= (int)lws_ser_ru16be(blob + LJT_OFS_32_COUNT_CERTS);
651*1c60b9acSAndroid Build Coastguard Worker 
652*1c60b9acSAndroid Build Coastguard Worker 	pderlen		= (uint16_t *)(blob + lws_ser_ru32be(blob +
653*1c60b9acSAndroid Build Coastguard Worker 							LJT_OFS_32_DERLEN));
654*1c60b9acSAndroid Build Coastguard Worker 	pskidlen	= blob + lws_ser_ru32be(blob + LJT_OFS_32_SKIDLEN);
655*1c60b9acSAndroid Build Coastguard Worker 	pskids		= blob + lws_ser_ru32be(blob + LJT_OFS_32_SKID);
656*1c60b9acSAndroid Build Coastguard Worker 	pder		= blob + LJT_OFS_DER;
657*1c60b9acSAndroid Build Coastguard Worker 
658*1c60b9acSAndroid Build Coastguard Worker 	/* check each cert SKID in turn, return the DER if found */
659*1c60b9acSAndroid Build Coastguard Worker 
660*1c60b9acSAndroid Build Coastguard Worker 	while (certs--) {
661*1c60b9acSAndroid Build Coastguard Worker 
662*1c60b9acSAndroid Build Coastguard Worker 		/* paranoia / sanity */
663*1c60b9acSAndroid Build Coastguard Worker 
664*1c60b9acSAndroid Build Coastguard Worker 		assert(pskids < blob + blen);
665*1c60b9acSAndroid Build Coastguard Worker 		assert(pder < blob + blen);
666*1c60b9acSAndroid Build Coastguard Worker 		assert(pskidlen < blob + blen);
667*1c60b9acSAndroid Build Coastguard Worker 		assert((uint8_t *)pderlen < blob + blen);
668*1c60b9acSAndroid Build Coastguard Worker 
669*1c60b9acSAndroid Build Coastguard Worker 		/* we will accept to match on truncated SKIDs */
670*1c60b9acSAndroid Build Coastguard Worker 
671*1c60b9acSAndroid Build Coastguard Worker 		if (*pskidlen >= skid_len &&
672*1c60b9acSAndroid Build Coastguard Worker 		    !memcmp(skid, pskids, skid_len)) {
673*1c60b9acSAndroid Build Coastguard Worker 			/*
674*1c60b9acSAndroid Build Coastguard Worker 			 * We found a trusted CA cert of the right SKID
675*1c60b9acSAndroid Build Coastguard Worker 			 */
676*1c60b9acSAndroid Build Coastguard Worker 		        *prpder = pder;
677*1c60b9acSAndroid Build Coastguard Worker 		        *prder_len = lws_ser_ru16be((uint8_t *)pderlen);
678*1c60b9acSAndroid Build Coastguard Worker 
679*1c60b9acSAndroid Build Coastguard Worker 		        return 0;
680*1c60b9acSAndroid Build Coastguard Worker 		}
681*1c60b9acSAndroid Build Coastguard Worker 
682*1c60b9acSAndroid Build Coastguard Worker 		pder += lws_ser_ru16be((uint8_t *)pderlen);
683*1c60b9acSAndroid Build Coastguard Worker 		pskids += *pskidlen;
684*1c60b9acSAndroid Build Coastguard Worker 		pderlen++;
685*1c60b9acSAndroid Build Coastguard Worker 		pskidlen++;
686*1c60b9acSAndroid Build Coastguard Worker 	}
687*1c60b9acSAndroid Build Coastguard Worker 
688*1c60b9acSAndroid Build Coastguard Worker 	return 1;
689*1c60b9acSAndroid Build Coastguard Worker }
690