xref: /aosp_15_r20/external/libwebsockets/minimal-examples/crypto/minimal-crypto-jwe/main.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * lws-crypto-jwe
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Written in 2010-2020 by Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * This file is made available under the Creative Commons CC0 1.0
7*1c60b9acSAndroid Build Coastguard Worker  * Universal Public Domain Dedication.
8*1c60b9acSAndroid Build Coastguard Worker  */
9*1c60b9acSAndroid Build Coastguard Worker 
10*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
11*1c60b9acSAndroid Build Coastguard Worker #include <sys/types.h>
12*1c60b9acSAndroid Build Coastguard Worker #include <fcntl.h>
13*1c60b9acSAndroid Build Coastguard Worker 
14*1c60b9acSAndroid Build Coastguard Worker /*
15*1c60b9acSAndroid Build Coastguard Worker  * handles escapes and line wrapping suitable for use
16*1c60b9acSAndroid Build Coastguard Worker  * defining a C char array ( -c option )
17*1c60b9acSAndroid Build Coastguard Worker  */
18*1c60b9acSAndroid Build Coastguard Worker 
19*1c60b9acSAndroid Build Coastguard Worker static void
format_c(const char * key)20*1c60b9acSAndroid Build Coastguard Worker format_c(const char *key)
21*1c60b9acSAndroid Build Coastguard Worker {
22*1c60b9acSAndroid Build Coastguard Worker 	const char *k = key;
23*1c60b9acSAndroid Build Coastguard Worker 	int seq = 0;
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker 	while (*k) {
26*1c60b9acSAndroid Build Coastguard Worker 		if (*k == '{') {
27*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
28*1c60b9acSAndroid Build Coastguard Worker 			putchar('{');
29*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
30*1c60b9acSAndroid Build Coastguard Worker 			putchar('\n');
31*1c60b9acSAndroid Build Coastguard Worker 			putchar('\t');
32*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
33*1c60b9acSAndroid Build Coastguard Worker 			k++;
34*1c60b9acSAndroid Build Coastguard Worker 			seq = 0;
35*1c60b9acSAndroid Build Coastguard Worker 			continue;
36*1c60b9acSAndroid Build Coastguard Worker 		}
37*1c60b9acSAndroid Build Coastguard Worker 		if (*k == '}') {
38*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
39*1c60b9acSAndroid Build Coastguard Worker 			putchar('\n');
40*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
41*1c60b9acSAndroid Build Coastguard Worker 			putchar('}');
42*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
43*1c60b9acSAndroid Build Coastguard Worker 			putchar('\n');
44*1c60b9acSAndroid Build Coastguard Worker 			k++;
45*1c60b9acSAndroid Build Coastguard Worker 			seq = 0;
46*1c60b9acSAndroid Build Coastguard Worker 			continue;
47*1c60b9acSAndroid Build Coastguard Worker 		}
48*1c60b9acSAndroid Build Coastguard Worker 		if (*k == '\"') {
49*1c60b9acSAndroid Build Coastguard Worker 			putchar('\\');
50*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
51*1c60b9acSAndroid Build Coastguard Worker 			seq += 2;
52*1c60b9acSAndroid Build Coastguard Worker 			k++;
53*1c60b9acSAndroid Build Coastguard Worker 			continue;
54*1c60b9acSAndroid Build Coastguard Worker 		}
55*1c60b9acSAndroid Build Coastguard Worker 		if (*k == ',') {
56*1c60b9acSAndroid Build Coastguard Worker 			putchar(',');
57*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
58*1c60b9acSAndroid Build Coastguard Worker 			putchar('\n');
59*1c60b9acSAndroid Build Coastguard Worker 			putchar('\t');
60*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
61*1c60b9acSAndroid Build Coastguard Worker 			k++;
62*1c60b9acSAndroid Build Coastguard Worker 			seq = 0;
63*1c60b9acSAndroid Build Coastguard Worker 			continue;
64*1c60b9acSAndroid Build Coastguard Worker 		}
65*1c60b9acSAndroid Build Coastguard Worker 		putchar(*k);
66*1c60b9acSAndroid Build Coastguard Worker 		seq++;
67*1c60b9acSAndroid Build Coastguard Worker 		if (seq >= 60) {
68*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
69*1c60b9acSAndroid Build Coastguard Worker 			putchar('\n');
70*1c60b9acSAndroid Build Coastguard Worker 			putchar('\t');
71*1c60b9acSAndroid Build Coastguard Worker 			putchar(' ');
72*1c60b9acSAndroid Build Coastguard Worker 			putchar('\"');
73*1c60b9acSAndroid Build Coastguard Worker 			seq = 1;
74*1c60b9acSAndroid Build Coastguard Worker 		}
75*1c60b9acSAndroid Build Coastguard Worker 		k++;
76*1c60b9acSAndroid Build Coastguard Worker 	}
77*1c60b9acSAndroid Build Coastguard Worker }
78*1c60b9acSAndroid Build Coastguard Worker 
79*1c60b9acSAndroid Build Coastguard Worker #define MAX_SIZE (4 * 1024 * 1024)
80*1c60b9acSAndroid Build Coastguard Worker 	char temp[MAX_SIZE], compact[MAX_SIZE];
81*1c60b9acSAndroid Build Coastguard Worker 
main(int argc,const char ** argv)82*1c60b9acSAndroid Build Coastguard Worker int main(int argc, const char **argv)
83*1c60b9acSAndroid Build Coastguard Worker {
84*1c60b9acSAndroid Build Coastguard Worker 	int n, enc = 0, result = 0,
85*1c60b9acSAndroid Build Coastguard Worker 	    logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
86*1c60b9acSAndroid Build Coastguard Worker 	char *in;
87*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_creation_info info;
88*1c60b9acSAndroid Build Coastguard Worker 	int temp_len = sizeof(temp);
89*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context;
90*1c60b9acSAndroid Build Coastguard Worker 	struct lws_jwe jwe;
91*1c60b9acSAndroid Build Coastguard Worker 	const char *p;
92*1c60b9acSAndroid Build Coastguard Worker 
93*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "-d")))
94*1c60b9acSAndroid Build Coastguard Worker 		logs = atoi(p);
95*1c60b9acSAndroid Build Coastguard Worker 
96*1c60b9acSAndroid Build Coastguard Worker 	lws_set_log_level(logs, NULL);
97*1c60b9acSAndroid Build Coastguard Worker 	lwsl_user("LWS JWE example tool\n");
98*1c60b9acSAndroid Build Coastguard Worker 
99*1c60b9acSAndroid Build Coastguard Worker 	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
100*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_NETWORK)
101*1c60b9acSAndroid Build Coastguard Worker 	info.port = CONTEXT_PORT_NO_LISTEN;
102*1c60b9acSAndroid Build Coastguard Worker #endif
103*1c60b9acSAndroid Build Coastguard Worker 	info.options = 0;
104*1c60b9acSAndroid Build Coastguard Worker 
105*1c60b9acSAndroid Build Coastguard Worker 	context = lws_create_context(&info);
106*1c60b9acSAndroid Build Coastguard Worker 	if (!context) {
107*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("lws init failed\n");
108*1c60b9acSAndroid Build Coastguard Worker 		return 1;
109*1c60b9acSAndroid Build Coastguard Worker 	}
110*1c60b9acSAndroid Build Coastguard Worker 
111*1c60b9acSAndroid Build Coastguard Worker 	lws_jwe_init(&jwe, context);
112*1c60b9acSAndroid Build Coastguard Worker 
113*1c60b9acSAndroid Build Coastguard Worker 	/* if encrypting, set the ciphers */
114*1c60b9acSAndroid Build Coastguard Worker 
115*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "-e"))) {
116*1c60b9acSAndroid Build Coastguard Worker 		char *sp = strchr(p, ' ');
117*1c60b9acSAndroid Build Coastguard Worker 
118*1c60b9acSAndroid Build Coastguard Worker 		if (!sp) {
119*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("format: -e \"<cek cipher alg> "
120*1c60b9acSAndroid Build Coastguard Worker 				 "<payload enc alg>\", eg, "
121*1c60b9acSAndroid Build Coastguard Worker 				 "-e \"RSA1_5 A128CBC-HS256\"\n");
122*1c60b9acSAndroid Build Coastguard Worker 
123*1c60b9acSAndroid Build Coastguard Worker 			return 1;
124*1c60b9acSAndroid Build Coastguard Worker 		}
125*1c60b9acSAndroid Build Coastguard Worker 		*sp = '\0';
126*1c60b9acSAndroid Build Coastguard Worker 		if (lws_gencrypto_jwe_alg_to_definition(p, &jwe.jose.alg)) {
127*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Unknown cipher alg %s\n", p);
128*1c60b9acSAndroid Build Coastguard Worker 			return 1;
129*1c60b9acSAndroid Build Coastguard Worker 		}
130*1c60b9acSAndroid Build Coastguard Worker 		if (lws_gencrypto_jwe_enc_to_definition(sp + 1, &jwe.jose.enc_alg)) {
131*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Unknown payload enc alg %s\n", sp + 1);
132*1c60b9acSAndroid Build Coastguard Worker 			return 1;
133*1c60b9acSAndroid Build Coastguard Worker 		}
134*1c60b9acSAndroid Build Coastguard Worker 
135*1c60b9acSAndroid Build Coastguard Worker 		/* create JOSE header, also needed for output */
136*1c60b9acSAndroid Build Coastguard Worker 
137*1c60b9acSAndroid Build Coastguard Worker 		if (lws_jws_alloc_element(&jwe.jws.map, LJWS_JOSE,
138*1c60b9acSAndroid Build Coastguard Worker 					  lws_concat_temp(temp, temp_len),
139*1c60b9acSAndroid Build Coastguard Worker 					  &temp_len, strlen(p) +
140*1c60b9acSAndroid Build Coastguard Worker 					  strlen(sp + 1) + 32, 0)) {
141*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: temp space too small\n", __func__);
142*1c60b9acSAndroid Build Coastguard Worker 			return 1;
143*1c60b9acSAndroid Build Coastguard Worker 		}
144*1c60b9acSAndroid Build Coastguard Worker 
145*1c60b9acSAndroid Build Coastguard Worker 		jwe.jws.map.len[LJWS_JOSE] = (uint32_t)lws_snprintf(
146*1c60b9acSAndroid Build Coastguard Worker 				(char *)jwe.jws.map.buf[LJWS_JOSE], (unsigned int)temp_len,
147*1c60b9acSAndroid Build Coastguard Worker 				"{\"alg\":\"%s\",\"enc\":\"%s\"}", p, sp + 1);
148*1c60b9acSAndroid Build Coastguard Worker 
149*1c60b9acSAndroid Build Coastguard Worker 		enc = 1;
150*1c60b9acSAndroid Build Coastguard Worker 	}
151*1c60b9acSAndroid Build Coastguard Worker 
152*1c60b9acSAndroid Build Coastguard Worker 	in = lws_concat_temp(temp, temp_len);
153*1c60b9acSAndroid Build Coastguard Worker 	n = (int)read(0, in, (unsigned int)temp_len);
154*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
155*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("Problem reading from stdin\n");
156*1c60b9acSAndroid Build Coastguard Worker 		return 1;
157*1c60b9acSAndroid Build Coastguard Worker 	}
158*1c60b9acSAndroid Build Coastguard Worker 
159*1c60b9acSAndroid Build Coastguard Worker 	/* account for padding as well */
160*1c60b9acSAndroid Build Coastguard Worker 
161*1c60b9acSAndroid Build Coastguard Worker 	temp_len -= (int)lws_gencrypto_padded_length(LWS_AES_CBC_BLOCKLEN, (unsigned int)n);
162*1c60b9acSAndroid Build Coastguard Worker 
163*1c60b9acSAndroid Build Coastguard Worker 	/* grab the key */
164*1c60b9acSAndroid Build Coastguard Worker 
165*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "-k"))) {
166*1c60b9acSAndroid Build Coastguard Worker 		if (lws_jwk_load(&jwe.jwk, p, NULL, NULL)) {
167*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: problem loading JWK %s\n", __func__, p);
168*1c60b9acSAndroid Build Coastguard Worker 
169*1c60b9acSAndroid Build Coastguard Worker 			return 1;
170*1c60b9acSAndroid Build Coastguard Worker 		}
171*1c60b9acSAndroid Build Coastguard Worker 	} else {
172*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("-k <jwk file> is required\n");
173*1c60b9acSAndroid Build Coastguard Worker 
174*1c60b9acSAndroid Build Coastguard Worker 		return 1;
175*1c60b9acSAndroid Build Coastguard Worker 	}
176*1c60b9acSAndroid Build Coastguard Worker 
177*1c60b9acSAndroid Build Coastguard Worker 	if (enc) {
178*1c60b9acSAndroid Build Coastguard Worker 
179*1c60b9acSAndroid Build Coastguard Worker 		/* point CTXT to the plaintext we read from stdin */
180*1c60b9acSAndroid Build Coastguard Worker 
181*1c60b9acSAndroid Build Coastguard Worker 		jwe.jws.map.buf[LJWE_CTXT] = in;
182*1c60b9acSAndroid Build Coastguard Worker 		jwe.jws.map.len[LJWE_CTXT] = (uint32_t)n;
183*1c60b9acSAndroid Build Coastguard Worker 
184*1c60b9acSAndroid Build Coastguard Worker 		/*
185*1c60b9acSAndroid Build Coastguard Worker 		 * Create a random CEK and set EKEY to it
186*1c60b9acSAndroid Build Coastguard Worker 		 * CEK size is determined by hash / hmac size
187*1c60b9acSAndroid Build Coastguard Worker 		 */
188*1c60b9acSAndroid Build Coastguard Worker 
189*1c60b9acSAndroid Build Coastguard Worker 		n = lws_gencrypto_bits_to_bytes(jwe.jose.enc_alg->keybits_fixed);
190*1c60b9acSAndroid Build Coastguard Worker 		if (lws_jws_randomize_element(context, &jwe.jws.map, LJWE_EKEY,
191*1c60b9acSAndroid Build Coastguard Worker 					      lws_concat_temp(temp, temp_len),
192*1c60b9acSAndroid Build Coastguard Worker 					      &temp_len, (unsigned int)n,
193*1c60b9acSAndroid Build Coastguard Worker 					      LWS_JWE_LIMIT_KEY_ELEMENT_BYTES)) {
194*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Problem getting random\n");
195*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
196*1c60b9acSAndroid Build Coastguard Worker 		}
197*1c60b9acSAndroid Build Coastguard Worker 
198*1c60b9acSAndroid Build Coastguard Worker 		/* perform the encryption of the CEK and the plaintext */
199*1c60b9acSAndroid Build Coastguard Worker 
200*1c60b9acSAndroid Build Coastguard Worker 		n = lws_jwe_encrypt(&jwe, lws_concat_temp(temp, temp_len),
201*1c60b9acSAndroid Build Coastguard Worker 				    &temp_len);
202*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
203*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: lws_jwe_encrypt failed\n", __func__);
204*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
205*1c60b9acSAndroid Build Coastguard Worker 		}
206*1c60b9acSAndroid Build Coastguard Worker 		if (lws_cmdline_option(argc, argv, "-f"))
207*1c60b9acSAndroid Build Coastguard Worker 			/* output the JWE in flattened form */
208*1c60b9acSAndroid Build Coastguard Worker 			n = lws_jwe_render_flattened(&jwe, compact,
209*1c60b9acSAndroid Build Coastguard Worker 						     sizeof(compact));
210*1c60b9acSAndroid Build Coastguard Worker 		else
211*1c60b9acSAndroid Build Coastguard Worker 			/* output the JWE in compact form */
212*1c60b9acSAndroid Build Coastguard Worker 			n = lws_jwe_render_compact(&jwe, compact,
213*1c60b9acSAndroid Build Coastguard Worker 						   sizeof(compact));
214*1c60b9acSAndroid Build Coastguard Worker 
215*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
216*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: lws_jwe_render failed: %d\n",
217*1c60b9acSAndroid Build Coastguard Worker 				 __func__, n);
218*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
219*1c60b9acSAndroid Build Coastguard Worker 		}
220*1c60b9acSAndroid Build Coastguard Worker 
221*1c60b9acSAndroid Build Coastguard Worker 		if (lws_cmdline_option(argc, argv, "-c"))
222*1c60b9acSAndroid Build Coastguard Worker 			format_c(compact);
223*1c60b9acSAndroid Build Coastguard Worker 		else
224*1c60b9acSAndroid Build Coastguard Worker 			if (write(1, compact,
225*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32)
226*1c60b9acSAndroid Build Coastguard Worker 					(unsigned int)
227*1c60b9acSAndroid Build Coastguard Worker #endif
228*1c60b9acSAndroid Build Coastguard Worker 					strlen(compact)) < 0) {
229*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("Write stdout failed\n");
230*1c60b9acSAndroid Build Coastguard Worker 				goto bail1;
231*1c60b9acSAndroid Build Coastguard Worker 			}
232*1c60b9acSAndroid Build Coastguard Worker 	} else {
233*1c60b9acSAndroid Build Coastguard Worker 		if (lws_cmdline_option(argc, argv, "-f")) {
234*1c60b9acSAndroid Build Coastguard Worker 			if (lws_jwe_json_parse(&jwe, (uint8_t *)in, n,
235*1c60b9acSAndroid Build Coastguard Worker 					       lws_concat_temp(temp, temp_len),
236*1c60b9acSAndroid Build Coastguard Worker 					       &temp_len)) {
237*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: lws_jwe_json_parse failed\n",
238*1c60b9acSAndroid Build Coastguard Worker 								 __func__);
239*1c60b9acSAndroid Build Coastguard Worker 				goto bail1;
240*1c60b9acSAndroid Build Coastguard Worker 			}
241*1c60b9acSAndroid Build Coastguard Worker 		} else
242*1c60b9acSAndroid Build Coastguard Worker 			/*
243*1c60b9acSAndroid Build Coastguard Worker 			 * converts a compact serialization to b64 + decoded maps
244*1c60b9acSAndroid Build Coastguard Worker 			 * held in jws
245*1c60b9acSAndroid Build Coastguard Worker 			 */
246*1c60b9acSAndroid Build Coastguard Worker 			if (lws_jws_compact_decode(in, n, &jwe.jws.map,
247*1c60b9acSAndroid Build Coastguard Worker 						   &jwe.jws.map_b64,
248*1c60b9acSAndroid Build Coastguard Worker 						   lws_concat_temp(temp, temp_len),
249*1c60b9acSAndroid Build Coastguard Worker 						   &temp_len) != 5) {
250*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: lws_jws_compact_decode failed\n",
251*1c60b9acSAndroid Build Coastguard Worker 					 __func__);
252*1c60b9acSAndroid Build Coastguard Worker 				goto bail1;
253*1c60b9acSAndroid Build Coastguard Worker 			}
254*1c60b9acSAndroid Build Coastguard Worker 
255*1c60b9acSAndroid Build Coastguard Worker 		/*
256*1c60b9acSAndroid Build Coastguard Worker 		 * Do the crypto according to what we parsed into the jose
257*1c60b9acSAndroid Build Coastguard Worker 		 * (information on the ciphers) and the jws (plaintext and
258*1c60b9acSAndroid Build Coastguard Worker 		 * signature info)
259*1c60b9acSAndroid Build Coastguard Worker 		 */
260*1c60b9acSAndroid Build Coastguard Worker 
261*1c60b9acSAndroid Build Coastguard Worker 		n = lws_jwe_auth_and_decrypt(&jwe,
262*1c60b9acSAndroid Build Coastguard Worker 					     lws_concat_temp(temp, temp_len),
263*1c60b9acSAndroid Build Coastguard Worker 					     &temp_len);
264*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
265*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: lws_jwe_auth_and_decrypt failed\n",
266*1c60b9acSAndroid Build Coastguard Worker 				 __func__);
267*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
268*1c60b9acSAndroid Build Coastguard Worker 		}
269*1c60b9acSAndroid Build Coastguard Worker 
270*1c60b9acSAndroid Build Coastguard Worker 		/* if it's valid, dump the plaintext and return 0 */
271*1c60b9acSAndroid Build Coastguard Worker 
272*1c60b9acSAndroid Build Coastguard Worker 		if (write(1, jwe.jws.map.buf[LJWE_CTXT],
273*1c60b9acSAndroid Build Coastguard Worker 			     jwe.jws.map.len[LJWE_CTXT]) < 0) {
274*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Write stdout failed\n");
275*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
276*1c60b9acSAndroid Build Coastguard Worker 		}
277*1c60b9acSAndroid Build Coastguard Worker 	}
278*1c60b9acSAndroid Build Coastguard Worker 
279*1c60b9acSAndroid Build Coastguard Worker 	result = 0;
280*1c60b9acSAndroid Build Coastguard Worker 
281*1c60b9acSAndroid Build Coastguard Worker bail1:
282*1c60b9acSAndroid Build Coastguard Worker 
283*1c60b9acSAndroid Build Coastguard Worker 	lws_jwe_destroy(&jwe);
284*1c60b9acSAndroid Build Coastguard Worker 
285*1c60b9acSAndroid Build Coastguard Worker 	lws_context_destroy(context);
286*1c60b9acSAndroid Build Coastguard Worker 
287*1c60b9acSAndroid Build Coastguard Worker 	return result;
288*1c60b9acSAndroid Build Coastguard Worker }
289