xref: /aosp_15_r20/external/libwebsockets/minimal-examples/crypto/minimal-crypto-cose-key/main.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * lws-minimal-crypto-cose-key
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Written in 2010-2021 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/select.h>
12*1c60b9acSAndroid Build Coastguard Worker #include <sys/types.h>
13*1c60b9acSAndroid Build Coastguard Worker #include <stdlib.h>
14*1c60b9acSAndroid Build Coastguard Worker #include <fcntl.h>
15*1c60b9acSAndroid Build Coastguard Worker 
16*1c60b9acSAndroid Build Coastguard Worker static int fdin = 0, fdout = 1;
17*1c60b9acSAndroid Build Coastguard Worker 
18*1c60b9acSAndroid Build Coastguard Worker static const char *meta_names[] = {
19*1c60b9acSAndroid Build Coastguard Worker 	"kty", "kid", "use", "key_ops", "base_iv", "alg"
20*1c60b9acSAndroid Build Coastguard Worker };
21*1c60b9acSAndroid Build Coastguard Worker 
22*1c60b9acSAndroid Build Coastguard Worker static const char *oct_names[] = {
23*1c60b9acSAndroid Build Coastguard Worker 	"k"
24*1c60b9acSAndroid Build Coastguard Worker };
25*1c60b9acSAndroid Build Coastguard Worker 
26*1c60b9acSAndroid Build Coastguard Worker static const char *rsa_names[] = {
27*1c60b9acSAndroid Build Coastguard Worker 	"e", "n", "d", "p", "q", "dp", "dq", "qi", "other", "ri", "di", "ti"
28*1c60b9acSAndroid Build Coastguard Worker };
29*1c60b9acSAndroid Build Coastguard Worker 
30*1c60b9acSAndroid Build Coastguard Worker static const char *ec_names[] = {
31*1c60b9acSAndroid Build Coastguard Worker 	"crv", "x", "d", "y",
32*1c60b9acSAndroid Build Coastguard Worker };
33*1c60b9acSAndroid Build Coastguard Worker 
34*1c60b9acSAndroid Build Coastguard Worker static void
cose_key_dump(const struct lws_cose_key * ck)35*1c60b9acSAndroid Build Coastguard Worker cose_key_dump(const struct lws_cose_key *ck)
36*1c60b9acSAndroid Build Coastguard Worker {
37*1c60b9acSAndroid Build Coastguard Worker 	const char **enames;
38*1c60b9acSAndroid Build Coastguard Worker 	char hex[2048], dump[3072];
39*1c60b9acSAndroid Build Coastguard Worker 	int elems;
40*1c60b9acSAndroid Build Coastguard Worker 	size_t l;
41*1c60b9acSAndroid Build Coastguard Worker 	int n;
42*1c60b9acSAndroid Build Coastguard Worker 
43*1c60b9acSAndroid Build Coastguard Worker 	(void)enames;
44*1c60b9acSAndroid Build Coastguard Worker 	(void)meta_names;
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker 	switch (ck->gencrypto_kty) {
47*1c60b9acSAndroid Build Coastguard Worker 
48*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_OCT:
49*1c60b9acSAndroid Build Coastguard Worker 		elems = LWS_GENCRYPTO_OCT_KEYEL_COUNT;
50*1c60b9acSAndroid Build Coastguard Worker 		enames = oct_names;
51*1c60b9acSAndroid Build Coastguard Worker 		break;
52*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_RSA:
53*1c60b9acSAndroid Build Coastguard Worker 		elems = LWS_GENCRYPTO_RSA_KEYEL_COUNT;
54*1c60b9acSAndroid Build Coastguard Worker 		enames = rsa_names;
55*1c60b9acSAndroid Build Coastguard Worker 		break;
56*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_EC:
57*1c60b9acSAndroid Build Coastguard Worker 		elems = LWS_GENCRYPTO_EC_KEYEL_COUNT;
58*1c60b9acSAndroid Build Coastguard Worker 		enames = ec_names;
59*1c60b9acSAndroid Build Coastguard Worker 		break;
60*1c60b9acSAndroid Build Coastguard Worker 
61*1c60b9acSAndroid Build Coastguard Worker 	default:
62*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: jwk %p: unknown type\n", __func__, ck);
63*1c60b9acSAndroid Build Coastguard Worker 
64*1c60b9acSAndroid Build Coastguard Worker 		return;
65*1c60b9acSAndroid Build Coastguard Worker 	}
66*1c60b9acSAndroid Build Coastguard Worker 
67*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < LWS_COUNT_COSE_KEY_ELEMENTS; n++) {
68*1c60b9acSAndroid Build Coastguard Worker 		if (ck->meta[n].buf) {
69*1c60b9acSAndroid Build Coastguard Worker 			if (n < 2) {
70*1c60b9acSAndroid Build Coastguard Worker 				l = (size_t)lws_snprintf(dump, sizeof(dump),
71*1c60b9acSAndroid Build Coastguard Worker 						 "  %s: %.*s\n", meta_names[n],
72*1c60b9acSAndroid Build Coastguard Worker 						 (int)ck->meta[n].len,
73*1c60b9acSAndroid Build Coastguard Worker 						 ck->meta[n].buf);
74*1c60b9acSAndroid Build Coastguard Worker 				write(fdout, dump, l);
75*1c60b9acSAndroid Build Coastguard Worker 			} else {
76*1c60b9acSAndroid Build Coastguard Worker 				l = (size_t)lws_snprintf(dump, sizeof(dump),
77*1c60b9acSAndroid Build Coastguard Worker 						 "  %s: ", meta_names[n]);
78*1c60b9acSAndroid Build Coastguard Worker 				write(fdout, dump, l);
79*1c60b9acSAndroid Build Coastguard Worker 				lws_hex_from_byte_array(ck->meta[n].buf,
80*1c60b9acSAndroid Build Coastguard Worker 							ck->meta[n].len,
81*1c60b9acSAndroid Build Coastguard Worker 							hex, sizeof(hex));
82*1c60b9acSAndroid Build Coastguard Worker 				write(fdout, hex, strlen(hex));
83*1c60b9acSAndroid Build Coastguard Worker 				write(fdout, "\n", 1);
84*1c60b9acSAndroid Build Coastguard Worker 			}
85*1c60b9acSAndroid Build Coastguard Worker 		}
86*1c60b9acSAndroid Build Coastguard Worker 	}
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < elems; n++) {
89*1c60b9acSAndroid Build Coastguard Worker 		if (ck->e[n].buf) {
90*1c60b9acSAndroid Build Coastguard Worker 			if (!n && ck->gencrypto_kty == LWS_GENCRYPTO_KTY_EC) {
91*1c60b9acSAndroid Build Coastguard Worker 				l = (size_t)lws_snprintf(dump, sizeof(dump),
92*1c60b9acSAndroid Build Coastguard Worker 						 "  %s: %.*s\n", enames[n],
93*1c60b9acSAndroid Build Coastguard Worker 						 (int)ck->e[n].len,
94*1c60b9acSAndroid Build Coastguard Worker 						 ck->e[n].buf);
95*1c60b9acSAndroid Build Coastguard Worker 				write(fdout, dump, l);
96*1c60b9acSAndroid Build Coastguard Worker 			} else {
97*1c60b9acSAndroid Build Coastguard Worker 				l = (size_t)lws_snprintf(dump, sizeof(dump),
98*1c60b9acSAndroid Build Coastguard Worker 						 "  %s: ", enames[n]);
99*1c60b9acSAndroid Build Coastguard Worker 				write(fdout, dump, l);
100*1c60b9acSAndroid Build Coastguard Worker 				lws_hex_from_byte_array(ck->e[n].buf,
101*1c60b9acSAndroid Build Coastguard Worker 							ck->e[n].len,
102*1c60b9acSAndroid Build Coastguard Worker 							hex, sizeof(hex));
103*1c60b9acSAndroid Build Coastguard Worker 				write(fdout, hex, strlen(hex));
104*1c60b9acSAndroid Build Coastguard Worker 				write(fdout, "\n", 1);
105*1c60b9acSAndroid Build Coastguard Worker 			}
106*1c60b9acSAndroid Build Coastguard Worker 		}
107*1c60b9acSAndroid Build Coastguard Worker 	}
108*1c60b9acSAndroid Build Coastguard Worker }
109*1c60b9acSAndroid Build Coastguard Worker 
main(int argc,const char ** argv)110*1c60b9acSAndroid Build Coastguard Worker int main(int argc, const char **argv)
111*1c60b9acSAndroid Build Coastguard Worker {
112*1c60b9acSAndroid Build Coastguard Worker 	uint8_t *kid = NULL, ktmp[4096], set_temp[32 * 1024], temp[256];
113*1c60b9acSAndroid Build Coastguard Worker 	int result = 1, bits = 0,
114*1c60b9acSAndroid Build Coastguard Worker 	    logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
115*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_creation_info info;
116*1c60b9acSAndroid Build Coastguard Worker 	size_t kid_len = 0, stp = 0;
117*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context;
118*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_t *ck = NULL;
119*1c60b9acSAndroid Build Coastguard Worker 	cose_param_t cose_kty = 0;
120*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_owner_t set;
121*1c60b9acSAndroid Build Coastguard Worker 	const char *p, *crv;
122*1c60b9acSAndroid Build Coastguard Worker 	lws_lec_pctx_t lec;
123*1c60b9acSAndroid Build Coastguard Worker 
124*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "-d")))
125*1c60b9acSAndroid Build Coastguard Worker 		logs = atoi(p);
126*1c60b9acSAndroid Build Coastguard Worker 
127*1c60b9acSAndroid Build Coastguard Worker 	lws_set_log_level(logs, NULL);
128*1c60b9acSAndroid Build Coastguard Worker 
129*1c60b9acSAndroid Build Coastguard Worker 	lwsl_user("LWS cose-key example tool -k keyset [-s alg-name kid ]\n");
130*1c60b9acSAndroid Build Coastguard Worker 
131*1c60b9acSAndroid Build Coastguard Worker 	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
132*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_NETWORK)
133*1c60b9acSAndroid Build Coastguard Worker 	info.port = CONTEXT_PORT_NO_LISTEN;
134*1c60b9acSAndroid Build Coastguard Worker #endif
135*1c60b9acSAndroid Build Coastguard Worker 
136*1c60b9acSAndroid Build Coastguard Worker 	context = lws_create_context(&info);
137*1c60b9acSAndroid Build Coastguard Worker 	if (!context) {
138*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("lws init failed\n");
139*1c60b9acSAndroid Build Coastguard Worker 		return 1;
140*1c60b9acSAndroid Build Coastguard Worker 	}
141*1c60b9acSAndroid Build Coastguard Worker 
142*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "--stdin"))) {
143*1c60b9acSAndroid Build Coastguard Worker 		fdin = open(p, LWS_O_RDONLY, 0);
144*1c60b9acSAndroid Build Coastguard Worker 		if (fdin < 0) {
145*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: unable to open stdin file\n", __func__);
146*1c60b9acSAndroid Build Coastguard Worker 			return 1;
147*1c60b9acSAndroid Build Coastguard Worker 		}
148*1c60b9acSAndroid Build Coastguard Worker 	}
149*1c60b9acSAndroid Build Coastguard Worker 
150*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "--stdout"))) {
151*1c60b9acSAndroid Build Coastguard Worker 		fdout = open(p, LWS_O_WRONLY | LWS_O_CREAT | LWS_O_TRUNC, 0600);
152*1c60b9acSAndroid Build Coastguard Worker 		if (fdout < 0) {
153*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: unable to open stdout file\n", __func__);
154*1c60b9acSAndroid Build Coastguard Worker 			goto bail_early;
155*1c60b9acSAndroid Build Coastguard Worker 		}
156*1c60b9acSAndroid Build Coastguard Worker 	}
157*1c60b9acSAndroid Build Coastguard Worker 
158*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "--kid"))) {
159*1c60b9acSAndroid Build Coastguard Worker 		kid = (uint8_t *)p;
160*1c60b9acSAndroid Build Coastguard Worker 		kid_len = strlen(p);
161*1c60b9acSAndroid Build Coastguard Worker 		//lwsl_hexdump_notice(kid, kid_len);
162*1c60b9acSAndroid Build Coastguard Worker 	}
163*1c60b9acSAndroid Build Coastguard Worker 
164*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "--kid-hex"))) {
165*1c60b9acSAndroid Build Coastguard Worker 		kid_len = (size_t)lws_hex_to_byte_array(p, ktmp, sizeof(ktmp));
166*1c60b9acSAndroid Build Coastguard Worker 		kid = (uint8_t *)ktmp;
167*1c60b9acSAndroid Build Coastguard Worker 	}
168*1c60b9acSAndroid Build Coastguard Worker 
169*1c60b9acSAndroid Build Coastguard Worker 	/*
170*1c60b9acSAndroid Build Coastguard Worker 	 * If we have some stdin queued up, we understand we are dumping
171*1c60b9acSAndroid Build Coastguard Worker 	 * an existing cose_key or key_set from stdin
172*1c60b9acSAndroid Build Coastguard Worker 	 */
173*1c60b9acSAndroid Build Coastguard Worker 
174*1c60b9acSAndroid Build Coastguard Worker 	if (!fdin) {
175*1c60b9acSAndroid Build Coastguard Worker 		struct timeval	timeout;
176*1c60b9acSAndroid Build Coastguard Worker 		fd_set	fds;
177*1c60b9acSAndroid Build Coastguard Worker 
178*1c60b9acSAndroid Build Coastguard Worker 		FD_ZERO(&fds);
179*1c60b9acSAndroid Build Coastguard Worker 		FD_SET(0, &fds);
180*1c60b9acSAndroid Build Coastguard Worker 
181*1c60b9acSAndroid Build Coastguard Worker 		timeout.tv_sec  = 0;
182*1c60b9acSAndroid Build Coastguard Worker 		timeout.tv_usec = 1000;
183*1c60b9acSAndroid Build Coastguard Worker 
184*1c60b9acSAndroid Build Coastguard Worker 		if (select(fdin + 1, &fds, NULL, NULL, &timeout) < 0)
185*1c60b9acSAndroid Build Coastguard Worker 			goto no_stdin;
186*1c60b9acSAndroid Build Coastguard Worker 
187*1c60b9acSAndroid Build Coastguard Worker 		if (!FD_ISSET(0, &fds))
188*1c60b9acSAndroid Build Coastguard Worker 			goto no_stdin;
189*1c60b9acSAndroid Build Coastguard Worker 	}
190*1c60b9acSAndroid Build Coastguard Worker 
191*1c60b9acSAndroid Build Coastguard Worker 	do {
192*1c60b9acSAndroid Build Coastguard Worker 		int n = (int)read(fdin, temp, sizeof(temp));
193*1c60b9acSAndroid Build Coastguard Worker 
194*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0)
195*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
196*1c60b9acSAndroid Build Coastguard Worker 		if (!n) {
197*1c60b9acSAndroid Build Coastguard Worker 			int kc = 0;
198*1c60b9acSAndroid Build Coastguard Worker 
199*1c60b9acSAndroid Build Coastguard Worker 			if (!stp)
200*1c60b9acSAndroid Build Coastguard Worker 				/* there was no stdin */
201*1c60b9acSAndroid Build Coastguard Worker 				break;
202*1c60b9acSAndroid Build Coastguard Worker 
203*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: importing\n", __func__);
204*1c60b9acSAndroid Build Coastguard Worker 
205*1c60b9acSAndroid Build Coastguard Worker 			lws_dll2_owner_clear(&set);
206*1c60b9acSAndroid Build Coastguard Worker 			ck = lws_cose_key_import(&set, NULL, NULL, set_temp, stp);
207*1c60b9acSAndroid Build Coastguard Worker 			if (!ck) {
208*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: import failed\n", __func__);
209*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
210*1c60b9acSAndroid Build Coastguard Worker 			}
211*1c60b9acSAndroid Build Coastguard Worker 
212*1c60b9acSAndroid Build Coastguard Worker 			lws_start_foreach_dll(struct lws_dll2 *, p,
213*1c60b9acSAndroid Build Coastguard Worker 						lws_dll2_get_head(&set)) {
214*1c60b9acSAndroid Build Coastguard Worker 				lws_cose_key_t *ck = lws_container_of(p,
215*1c60b9acSAndroid Build Coastguard Worker 							lws_cose_key_t, list);
216*1c60b9acSAndroid Build Coastguard Worker 				struct lws_gencrypto_keyelem *ke =
217*1c60b9acSAndroid Build Coastguard Worker 						&ck->meta[COSEKEY_META_KID];
218*1c60b9acSAndroid Build Coastguard Worker 
219*1c60b9acSAndroid Build Coastguard Worker 				kc++;
220*1c60b9acSAndroid Build Coastguard Worker 
221*1c60b9acSAndroid Build Coastguard Worker 				if (!kid_len || (ke->len &&
222*1c60b9acSAndroid Build Coastguard Worker 				    ke->len == (uint32_t)kid_len &&
223*1c60b9acSAndroid Build Coastguard Worker 				    !memcmp(ke->buf, kid, kid_len))) {
224*1c60b9acSAndroid Build Coastguard Worker 					    printf("Cose key #%d\n", kc);
225*1c60b9acSAndroid Build Coastguard Worker 					    cose_key_dump(ck);
226*1c60b9acSAndroid Build Coastguard Worker 				}
227*1c60b9acSAndroid Build Coastguard Worker 
228*1c60b9acSAndroid Build Coastguard Worker 			} lws_end_foreach_dll(p);
229*1c60b9acSAndroid Build Coastguard Worker 
230*1c60b9acSAndroid Build Coastguard Worker 			lws_cose_key_set_destroy(&set);
231*1c60b9acSAndroid Build Coastguard Worker 			result = 0;
232*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
233*1c60b9acSAndroid Build Coastguard Worker 
234*1c60b9acSAndroid Build Coastguard Worker 		}
235*1c60b9acSAndroid Build Coastguard Worker 
236*1c60b9acSAndroid Build Coastguard Worker 		if (stp + (size_t)n > sizeof(set_temp)) {
237*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: stdin bigger than our buffer\n", __func__);
238*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
239*1c60b9acSAndroid Build Coastguard Worker 		}
240*1c60b9acSAndroid Build Coastguard Worker 		memcpy(set_temp + stp, temp, (size_t)n);
241*1c60b9acSAndroid Build Coastguard Worker 		stp += (size_t)n;
242*1c60b9acSAndroid Build Coastguard Worker 	} while (1);
243*1c60b9acSAndroid Build Coastguard Worker 
244*1c60b9acSAndroid Build Coastguard Worker no_stdin:
245*1c60b9acSAndroid Build Coastguard Worker 
246*1c60b9acSAndroid Build Coastguard Worker 	/*
247*1c60b9acSAndroid Build Coastguard Worker 	 *
248*1c60b9acSAndroid Build Coastguard Worker 	 */
249*1c60b9acSAndroid Build Coastguard Worker 
250*1c60b9acSAndroid Build Coastguard Worker 	p = lws_cmdline_option(argc, argv, "--kty");
251*1c60b9acSAndroid Build Coastguard Worker 	if (!p) {
252*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: use --kty OKP|EC2|RSA|SYMMETRIC\n",
253*1c60b9acSAndroid Build Coastguard Worker 					__func__);
254*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
255*1c60b9acSAndroid Build Coastguard Worker 	}
256*1c60b9acSAndroid Build Coastguard Worker 
257*1c60b9acSAndroid Build Coastguard Worker 	if (!strcmp(p, "OKP"))
258*1c60b9acSAndroid Build Coastguard Worker 		cose_kty = LWSCOSE_WKKTV_OKP;
259*1c60b9acSAndroid Build Coastguard Worker 	if (!strcmp(p, "EC2"))
260*1c60b9acSAndroid Build Coastguard Worker 		cose_kty = LWSCOSE_WKKTV_EC2;
261*1c60b9acSAndroid Build Coastguard Worker 	if (!strcmp(p, "RSA"))
262*1c60b9acSAndroid Build Coastguard Worker 		cose_kty = LWSCOSE_WKKTV_RSA;
263*1c60b9acSAndroid Build Coastguard Worker 	if (!strcmp(p, "SYMMETRIC") || !strcmp(p, "SYM"))
264*1c60b9acSAndroid Build Coastguard Worker 		cose_kty = LWSCOSE_WKKTV_SYMMETRIC;
265*1c60b9acSAndroid Build Coastguard Worker 
266*1c60b9acSAndroid Build Coastguard Worker 	if (!cose_kty) {
267*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: use --kty OKP|EC2|RSA|SYMMETRIC\n",
268*1c60b9acSAndroid Build Coastguard Worker 			 __func__);
269*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
270*1c60b9acSAndroid Build Coastguard Worker 	}
271*1c60b9acSAndroid Build Coastguard Worker 
272*1c60b9acSAndroid Build Coastguard Worker 	crv = NULL;
273*1c60b9acSAndroid Build Coastguard Worker 	if (cose_kty == LWSCOSE_WKKTV_OKP ||
274*1c60b9acSAndroid Build Coastguard Worker 	    cose_kty == LWSCOSE_WKKTV_EC2) {
275*1c60b9acSAndroid Build Coastguard Worker 		crv = lws_cmdline_option(argc, argv, "--curve");
276*1c60b9acSAndroid Build Coastguard Worker 		if (!crv) {
277*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: use --curve P-256 etc\n", __func__);
278*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
279*1c60b9acSAndroid Build Coastguard Worker 		}
280*1c60b9acSAndroid Build Coastguard Worker 	}
281*1c60b9acSAndroid Build Coastguard Worker 
282*1c60b9acSAndroid Build Coastguard Worker 	p = lws_cmdline_option(argc, argv, "--bits");
283*1c60b9acSAndroid Build Coastguard Worker 	if (p)
284*1c60b9acSAndroid Build Coastguard Worker 		bits = atoi(p);
285*1c60b9acSAndroid Build Coastguard Worker 
286*1c60b9acSAndroid Build Coastguard Worker 	ck = lws_cose_key_generate(context, cose_kty, 0, bits, crv,
287*1c60b9acSAndroid Build Coastguard Worker 				   kid, kid_len);
288*1c60b9acSAndroid Build Coastguard Worker 	if (!ck)
289*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
290*1c60b9acSAndroid Build Coastguard Worker 
291*1c60b9acSAndroid Build Coastguard Worker 	lws_lec_init(&lec, ktmp, sizeof(ktmp));
292*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_export(ck, &lec, LWSJWKF_EXPORT_PRIVATE);
293*1c60b9acSAndroid Build Coastguard Worker 	write(fdout, ktmp, lec.used);
294*1c60b9acSAndroid Build Coastguard Worker 
295*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_destroy(&ck);
296*1c60b9acSAndroid Build Coastguard Worker 	result = 0;
297*1c60b9acSAndroid Build Coastguard Worker 
298*1c60b9acSAndroid Build Coastguard Worker bail:
299*1c60b9acSAndroid Build Coastguard Worker 	lws_context_destroy(context);
300*1c60b9acSAndroid Build Coastguard Worker 
301*1c60b9acSAndroid Build Coastguard Worker 	if (result)
302*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: FAIL: %d\n", __func__, result);
303*1c60b9acSAndroid Build Coastguard Worker 	else
304*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: PASS\n", __func__);
305*1c60b9acSAndroid Build Coastguard Worker 
306*1c60b9acSAndroid Build Coastguard Worker bail_early:
307*1c60b9acSAndroid Build Coastguard Worker 	if (fdin > 0)
308*1c60b9acSAndroid Build Coastguard Worker 		close(fdin);
309*1c60b9acSAndroid Build Coastguard Worker 	if (fdout != 1 && fdout >= 0)
310*1c60b9acSAndroid Build Coastguard Worker 		close(fdout);
311*1c60b9acSAndroid Build Coastguard Worker 
312*1c60b9acSAndroid Build Coastguard Worker 	return result;
313*1c60b9acSAndroid Build Coastguard Worker }
314