xref: /aosp_15_r20/external/libwebsockets/minimal-examples/crypto/minimal-crypto-jws/main.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * lws-crypto-jws
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 #define MAX_SIZE (4 * 1024 * 1024)
15*1c60b9acSAndroid Build Coastguard Worker char temp[MAX_SIZE], compact[MAX_SIZE];
16*1c60b9acSAndroid Build Coastguard Worker 
main(int argc,const char ** argv)17*1c60b9acSAndroid Build Coastguard Worker int main(int argc, const char **argv)
18*1c60b9acSAndroid Build Coastguard Worker {
19*1c60b9acSAndroid Build Coastguard Worker 	int n, sign = 0, result = 0,
20*1c60b9acSAndroid Build Coastguard Worker 	    logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
21*1c60b9acSAndroid Build Coastguard Worker 	char *in;
22*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_creation_info info;
23*1c60b9acSAndroid Build Coastguard Worker 	struct lws_jws_map map;
24*1c60b9acSAndroid Build Coastguard Worker 	int temp_len = sizeof(temp);
25*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context;
26*1c60b9acSAndroid Build Coastguard Worker 	struct lws_jose jose;
27*1c60b9acSAndroid Build Coastguard Worker 	struct lws_jwk jwk;
28*1c60b9acSAndroid Build Coastguard Worker 	struct lws_jws jws;
29*1c60b9acSAndroid Build Coastguard Worker 	const char *p;
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "-d")))
32*1c60b9acSAndroid Build Coastguard Worker 		logs = atoi(p);
33*1c60b9acSAndroid Build Coastguard Worker 
34*1c60b9acSAndroid Build Coastguard Worker 	lws_set_log_level(logs, NULL);
35*1c60b9acSAndroid Build Coastguard Worker 	lwsl_user("LWS JWS example tool\n");
36*1c60b9acSAndroid Build Coastguard Worker 
37*1c60b9acSAndroid Build Coastguard Worker 	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
38*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_NETWORK)
39*1c60b9acSAndroid Build Coastguard Worker 	info.port = CONTEXT_PORT_NO_LISTEN;
40*1c60b9acSAndroid Build Coastguard Worker #endif
41*1c60b9acSAndroid Build Coastguard Worker 	info.options = 0;
42*1c60b9acSAndroid Build Coastguard Worker 
43*1c60b9acSAndroid Build Coastguard Worker 	context = lws_create_context(&info);
44*1c60b9acSAndroid Build Coastguard Worker 	if (!context) {
45*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("lws init failed\n");
46*1c60b9acSAndroid Build Coastguard Worker 		return 1;
47*1c60b9acSAndroid Build Coastguard Worker 	}
48*1c60b9acSAndroid Build Coastguard Worker 
49*1c60b9acSAndroid Build Coastguard Worker 	lws_jose_init(&jose);
50*1c60b9acSAndroid Build Coastguard Worker 	lws_jws_init(&jws, &jwk, context);
51*1c60b9acSAndroid Build Coastguard Worker 
52*1c60b9acSAndroid Build Coastguard Worker 	/* if signing, set the ciphers */
53*1c60b9acSAndroid Build Coastguard Worker 
54*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "-s"))) {
55*1c60b9acSAndroid Build Coastguard Worker 
56*1c60b9acSAndroid Build Coastguard Worker 		if (lws_gencrypto_jws_alg_to_definition(p, &jose.alg)) {
57*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("format: -s \"<jws cipher alg>\", eg, "
58*1c60b9acSAndroid Build Coastguard Worker 				 "-e \"RS256\"\n");
59*1c60b9acSAndroid Build Coastguard Worker 
60*1c60b9acSAndroid Build Coastguard Worker 			return 1;
61*1c60b9acSAndroid Build Coastguard Worker 		}
62*1c60b9acSAndroid Build Coastguard Worker 
63*1c60b9acSAndroid Build Coastguard Worker 		/* create JOSE header, also needed for output */
64*1c60b9acSAndroid Build Coastguard Worker 
65*1c60b9acSAndroid Build Coastguard Worker 		if (lws_jws_alloc_element(&jws.map, LJWS_JOSE,
66*1c60b9acSAndroid Build Coastguard Worker 				      lws_concat_temp(temp, temp_len),
67*1c60b9acSAndroid Build Coastguard Worker 				      &temp_len, strlen(p) + 10, 0)) {
68*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: temp space too small\n", __func__);
69*1c60b9acSAndroid Build Coastguard Worker 			return 1;
70*1c60b9acSAndroid Build Coastguard Worker 		}
71*1c60b9acSAndroid Build Coastguard Worker 
72*1c60b9acSAndroid Build Coastguard Worker 		jws.map.len[LJWS_JOSE] = (uint32_t)
73*1c60b9acSAndroid Build Coastguard Worker 				lws_snprintf((char *)jws.map.buf[LJWS_JOSE],
74*1c60b9acSAndroid Build Coastguard Worker 					     (unsigned int)temp_len, "{\"alg\":\"%s\"}", p);
75*1c60b9acSAndroid Build Coastguard Worker 		sign = 1;
76*1c60b9acSAndroid Build Coastguard Worker 	}
77*1c60b9acSAndroid Build Coastguard Worker 
78*1c60b9acSAndroid Build Coastguard Worker 	in = lws_concat_temp(temp, temp_len);
79*1c60b9acSAndroid Build Coastguard Worker 	n = (int)read(0, in, (unsigned int)temp_len);
80*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
81*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("Problem reading from stdin\n");
82*1c60b9acSAndroid Build Coastguard Worker 		return 1;
83*1c60b9acSAndroid Build Coastguard Worker 	}
84*1c60b9acSAndroid Build Coastguard Worker 	temp_len -= n;
85*1c60b9acSAndroid Build Coastguard Worker 
86*1c60b9acSAndroid Build Coastguard Worker 	/* grab the key */
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "-k"))) {
89*1c60b9acSAndroid Build Coastguard Worker 		if (lws_jwk_load(&jwk, p, NULL, NULL)) {
90*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: problem loading JWK %s\n", __func__, p);
91*1c60b9acSAndroid Build Coastguard Worker 
92*1c60b9acSAndroid Build Coastguard Worker 			return 1;
93*1c60b9acSAndroid Build Coastguard Worker 		}
94*1c60b9acSAndroid Build Coastguard Worker 	} else {
95*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("-k <jwk file> is required\n");
96*1c60b9acSAndroid Build Coastguard Worker 
97*1c60b9acSAndroid Build Coastguard Worker 		return 1;
98*1c60b9acSAndroid Build Coastguard Worker 	}
99*1c60b9acSAndroid Build Coastguard Worker 	if (sign) {
100*1c60b9acSAndroid Build Coastguard Worker 
101*1c60b9acSAndroid Build Coastguard Worker 		/* add the plaintext from stdin to the map and a b64 version */
102*1c60b9acSAndroid Build Coastguard Worker 
103*1c60b9acSAndroid Build Coastguard Worker 		jws.map.buf[LJWS_PYLD] = in;
104*1c60b9acSAndroid Build Coastguard Worker 		jws.map.len[LJWS_PYLD] = (unsigned int)n;
105*1c60b9acSAndroid Build Coastguard Worker 
106*1c60b9acSAndroid Build Coastguard Worker 		if (lws_jws_encode_b64_element(&jws.map_b64, LJWS_PYLD,
107*1c60b9acSAndroid Build Coastguard Worker 					       lws_concat_temp(temp, temp_len),
108*1c60b9acSAndroid Build Coastguard Worker 					       &temp_len, jws.map.buf[LJWS_PYLD],
109*1c60b9acSAndroid Build Coastguard Worker 					       jws.map.len[LJWS_PYLD]))
110*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
111*1c60b9acSAndroid Build Coastguard Worker 
112*1c60b9acSAndroid Build Coastguard Worker 		/* add the b64 JOSE header to the b64 map */
113*1c60b9acSAndroid Build Coastguard Worker 
114*1c60b9acSAndroid Build Coastguard Worker 		if (lws_jws_encode_b64_element(&jws.map_b64, LJWS_JOSE,
115*1c60b9acSAndroid Build Coastguard Worker 					       lws_concat_temp(temp, temp_len),
116*1c60b9acSAndroid Build Coastguard Worker 					       &temp_len, jws.map.buf[LJWS_JOSE],
117*1c60b9acSAndroid Build Coastguard Worker 					       jws.map.len[LJWS_JOSE]))
118*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
119*1c60b9acSAndroid Build Coastguard Worker 
120*1c60b9acSAndroid Build Coastguard Worker 		/* prepare the space for the b64 signature in the map */
121*1c60b9acSAndroid Build Coastguard Worker 
122*1c60b9acSAndroid Build Coastguard Worker 		if (lws_jws_alloc_element(&jws.map_b64, LJWS_SIG,
123*1c60b9acSAndroid Build Coastguard Worker 				      lws_concat_temp(temp, temp_len),
124*1c60b9acSAndroid Build Coastguard Worker 				      &temp_len, (unsigned int)lws_base64_size(
125*1c60b9acSAndroid Build Coastguard Worker 					 LWS_JWE_LIMIT_KEY_ELEMENT_BYTES), 0)) {
126*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: temp space too small\n", __func__);
127*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
128*1c60b9acSAndroid Build Coastguard Worker 		}
129*1c60b9acSAndroid Build Coastguard Worker 
130*1c60b9acSAndroid Build Coastguard Worker 
131*1c60b9acSAndroid Build Coastguard Worker 
132*1c60b9acSAndroid Build Coastguard Worker 		/* sign the plaintext */
133*1c60b9acSAndroid Build Coastguard Worker 
134*1c60b9acSAndroid Build Coastguard Worker 		n = lws_jws_sign_from_b64(&jose, &jws,
135*1c60b9acSAndroid Build Coastguard Worker 					  (char *)jws.map_b64.buf[LJWS_SIG],
136*1c60b9acSAndroid Build Coastguard Worker 					  jws.map_b64.len[LJWS_SIG]);
137*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
138*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: failed signing test packet\n", __func__);
139*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
140*1c60b9acSAndroid Build Coastguard Worker 		}
141*1c60b9acSAndroid Build Coastguard Worker 		/* set the actual b64 signature size */
142*1c60b9acSAndroid Build Coastguard Worker 		jws.map_b64.len[LJWS_SIG] = (uint32_t)n;
143*1c60b9acSAndroid Build Coastguard Worker 
144*1c60b9acSAndroid Build Coastguard Worker 		if (lws_cmdline_option(argc, argv, "-f"))
145*1c60b9acSAndroid Build Coastguard Worker 			/* create the flattened representation */
146*1c60b9acSAndroid Build Coastguard Worker 			n = lws_jws_write_flattened_json(&jws, compact, sizeof(compact));
147*1c60b9acSAndroid Build Coastguard Worker 		else
148*1c60b9acSAndroid Build Coastguard Worker 			/* create the compact JWS representation */
149*1c60b9acSAndroid Build Coastguard Worker 			n = lws_jws_write_compact(&jws, compact, sizeof(compact));
150*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
151*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: write_compact failed\n", __func__);
152*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
153*1c60b9acSAndroid Build Coastguard Worker 		}
154*1c60b9acSAndroid Build Coastguard Worker 
155*1c60b9acSAndroid Build Coastguard Worker 		/* dump the compact JWS representation on stdout */
156*1c60b9acSAndroid Build Coastguard Worker 
157*1c60b9acSAndroid Build Coastguard Worker 		if (write(1, compact,
158*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32)
159*1c60b9acSAndroid Build Coastguard Worker 				(unsigned int)
160*1c60b9acSAndroid Build Coastguard Worker #endif
161*1c60b9acSAndroid Build Coastguard Worker 				strlen(compact))  < 0) {
162*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Write stdout failed\n");
163*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
164*1c60b9acSAndroid Build Coastguard Worker 		}
165*1c60b9acSAndroid Build Coastguard Worker 
166*1c60b9acSAndroid Build Coastguard Worker 	} else {
167*1c60b9acSAndroid Build Coastguard Worker 		/* perform the verify directly on the compact representation */
168*1c60b9acSAndroid Build Coastguard Worker 
169*1c60b9acSAndroid Build Coastguard Worker 		if (lws_cmdline_option(argc, argv, "-f")) {
170*1c60b9acSAndroid Build Coastguard Worker 			if (lws_jws_sig_confirm_json(in, (unsigned int)n, &jws, &jwk, context,
171*1c60b9acSAndroid Build Coastguard Worker 					lws_concat_temp(temp, temp_len),
172*1c60b9acSAndroid Build Coastguard Worker 					&temp_len) < 0) {
173*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: confirm rsa sig failed\n",
174*1c60b9acSAndroid Build Coastguard Worker 					    __func__);
175*1c60b9acSAndroid Build Coastguard Worker 				lwsl_hexdump_notice(jws.map.buf[LJWS_JOSE], jws.map.len[LJWS_JOSE]);
176*1c60b9acSAndroid Build Coastguard Worker 				lwsl_hexdump_notice(jws.map.buf[LJWS_PYLD], jws.map.len[LJWS_PYLD]);
177*1c60b9acSAndroid Build Coastguard Worker 				lwsl_hexdump_notice(jws.map.buf[LJWS_SIG], jws.map.len[LJWS_SIG]);
178*1c60b9acSAndroid Build Coastguard Worker 
179*1c60b9acSAndroid Build Coastguard Worker 				lwsl_hexdump_notice(jws.map_b64.buf[LJWS_JOSE], jws.map_b64.len[LJWS_JOSE]);
180*1c60b9acSAndroid Build Coastguard Worker 				lwsl_hexdump_notice(jws.map_b64.buf[LJWS_PYLD], jws.map_b64.len[LJWS_PYLD]);
181*1c60b9acSAndroid Build Coastguard Worker 				lwsl_hexdump_notice(jws.map_b64.buf[LJWS_SIG], jws.map_b64.len[LJWS_SIG]);
182*1c60b9acSAndroid Build Coastguard Worker 				goto bail1;
183*1c60b9acSAndroid Build Coastguard Worker 			}
184*1c60b9acSAndroid Build Coastguard Worker 		} else {
185*1c60b9acSAndroid Build Coastguard Worker 			if (lws_jws_sig_confirm_compact_b64(in,
186*1c60b9acSAndroid Build Coastguard Worker 					lws_concat_used(temp, (unsigned int)temp_len),
187*1c60b9acSAndroid Build Coastguard Worker 					&map, &jwk, context,
188*1c60b9acSAndroid Build Coastguard Worker 					lws_concat_temp(temp, temp_len),
189*1c60b9acSAndroid Build Coastguard Worker 					&temp_len) < 0) {
190*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: confirm rsa sig failed\n",
191*1c60b9acSAndroid Build Coastguard Worker 					    __func__);
192*1c60b9acSAndroid Build Coastguard Worker 				goto bail1;
193*1c60b9acSAndroid Build Coastguard Worker 			}
194*1c60b9acSAndroid Build Coastguard Worker 		}
195*1c60b9acSAndroid Build Coastguard Worker 
196*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("VALID\n");
197*1c60b9acSAndroid Build Coastguard Worker 
198*1c60b9acSAndroid Build Coastguard Worker 		/* dump the verifed plaintext and return 0 */
199*1c60b9acSAndroid Build Coastguard Worker 
200*1c60b9acSAndroid Build Coastguard Worker 		if (write(1, jws.map.buf[LJWS_PYLD], jws.map.len[LJWS_PYLD]) < 0) {
201*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Write stdout failed\n");
202*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
203*1c60b9acSAndroid Build Coastguard Worker 		}
204*1c60b9acSAndroid Build Coastguard Worker 	}
205*1c60b9acSAndroid Build Coastguard Worker 
206*1c60b9acSAndroid Build Coastguard Worker 	result = 0;
207*1c60b9acSAndroid Build Coastguard Worker 
208*1c60b9acSAndroid Build Coastguard Worker bail1:
209*1c60b9acSAndroid Build Coastguard Worker 	lws_jws_destroy(&jws);
210*1c60b9acSAndroid Build Coastguard Worker 	lws_jwk_destroy(&jwk);
211*1c60b9acSAndroid Build Coastguard Worker 
212*1c60b9acSAndroid Build Coastguard Worker 	lws_context_destroy(context);
213*1c60b9acSAndroid Build Coastguard Worker 
214*1c60b9acSAndroid Build Coastguard Worker 	return result;
215*1c60b9acSAndroid Build Coastguard Worker }
216