xref: /aosp_15_r20/external/libwebsockets/minimal-examples/crypto/minimal-crypto-x509/main.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * lws-crypto-x509
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Written in 2010-2019 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 #include <errno.h>
14*1c60b9acSAndroid Build Coastguard Worker 
15*1c60b9acSAndroid Build Coastguard Worker static int
read_pem(const char * filename,char * pembuf,int pembuf_len)16*1c60b9acSAndroid Build Coastguard Worker read_pem(const char *filename, char *pembuf, int pembuf_len)
17*1c60b9acSAndroid Build Coastguard Worker {
18*1c60b9acSAndroid Build Coastguard Worker 	int n, fd = open(filename, LWS_O_RDONLY);
19*1c60b9acSAndroid Build Coastguard Worker 	if (fd == -1)
20*1c60b9acSAndroid Build Coastguard Worker 		return -1;
21*1c60b9acSAndroid Build Coastguard Worker 
22*1c60b9acSAndroid Build Coastguard Worker 	n = (int)read(fd, pembuf, (unsigned int)pembuf_len - 1);
23*1c60b9acSAndroid Build Coastguard Worker 	close(fd);
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker 	pembuf[n++] = '\0';
26*1c60b9acSAndroid Build Coastguard Worker 
27*1c60b9acSAndroid Build Coastguard Worker 	return n;
28*1c60b9acSAndroid Build Coastguard Worker }
29*1c60b9acSAndroid Build Coastguard Worker 
30*1c60b9acSAndroid Build Coastguard Worker static int
read_pem_c509_cert(struct lws_x509_cert ** x509,const char * filename,char * pembuf,int pembuf_len)31*1c60b9acSAndroid Build Coastguard Worker read_pem_c509_cert(struct lws_x509_cert **x509, const char *filename,
32*1c60b9acSAndroid Build Coastguard Worker 		   char *pembuf, int pembuf_len)
33*1c60b9acSAndroid Build Coastguard Worker {
34*1c60b9acSAndroid Build Coastguard Worker 	int n;
35*1c60b9acSAndroid Build Coastguard Worker 
36*1c60b9acSAndroid Build Coastguard Worker 	n = read_pem(filename, pembuf, pembuf_len);
37*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
38*1c60b9acSAndroid Build Coastguard Worker 		return -1;
39*1c60b9acSAndroid Build Coastguard Worker 
40*1c60b9acSAndroid Build Coastguard Worker 	if (lws_x509_create(x509)) {
41*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: failed to create x509\n", __func__);
42*1c60b9acSAndroid Build Coastguard Worker 
43*1c60b9acSAndroid Build Coastguard Worker 		return -1;
44*1c60b9acSAndroid Build Coastguard Worker 	}
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker 	if (lws_x509_parse_from_pem(*x509, pembuf, (unsigned int)n) < 0) {
47*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: unable to parse PEM %s\n", __func__, filename);
48*1c60b9acSAndroid Build Coastguard Worker 		lws_x509_destroy(x509);
49*1c60b9acSAndroid Build Coastguard Worker 
50*1c60b9acSAndroid Build Coastguard Worker 		return -1;
51*1c60b9acSAndroid Build Coastguard Worker 	}
52*1c60b9acSAndroid Build Coastguard Worker 
53*1c60b9acSAndroid Build Coastguard Worker 	return 0;
54*1c60b9acSAndroid Build Coastguard Worker }
55*1c60b9acSAndroid Build Coastguard Worker 
main(int argc,const char ** argv)56*1c60b9acSAndroid Build Coastguard Worker int main(int argc, const char **argv)
57*1c60b9acSAndroid Build Coastguard Worker {
58*1c60b9acSAndroid Build Coastguard Worker 	int n, result = 1, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
59*1c60b9acSAndroid Build Coastguard Worker 	struct lws_x509_cert *x509 = NULL, *x509_trusted = NULL;
60*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_creation_info info;
61*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context;
62*1c60b9acSAndroid Build Coastguard Worker 	struct lws_jwk jwk;
63*1c60b9acSAndroid Build Coastguard Worker 	char pembuf[6144];
64*1c60b9acSAndroid Build Coastguard Worker 	const char *p;
65*1c60b9acSAndroid Build Coastguard Worker 
66*1c60b9acSAndroid Build Coastguard Worker 	memset(&jwk, 0, sizeof(jwk));
67*1c60b9acSAndroid Build Coastguard Worker 
68*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "-d")))
69*1c60b9acSAndroid Build Coastguard Worker 		logs = atoi(p);
70*1c60b9acSAndroid Build Coastguard Worker 
71*1c60b9acSAndroid Build Coastguard Worker 	lws_set_log_level(logs, NULL);
72*1c60b9acSAndroid Build Coastguard Worker 	lwsl_user("LWS X509 api example\n");
73*1c60b9acSAndroid Build Coastguard Worker 
74*1c60b9acSAndroid Build Coastguard Worker 	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
75*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_NETWORK)
76*1c60b9acSAndroid Build Coastguard Worker 	info.port = CONTEXT_PORT_NO_LISTEN;
77*1c60b9acSAndroid Build Coastguard Worker #endif
78*1c60b9acSAndroid Build Coastguard Worker 	info.options = 0;
79*1c60b9acSAndroid Build Coastguard Worker 
80*1c60b9acSAndroid Build Coastguard Worker 	context = lws_create_context(&info);
81*1c60b9acSAndroid Build Coastguard Worker 	if (!context) {
82*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("lws init failed\n");
83*1c60b9acSAndroid Build Coastguard Worker 		return 1;
84*1c60b9acSAndroid Build Coastguard Worker 	}
85*1c60b9acSAndroid Build Coastguard Worker 
86*1c60b9acSAndroid Build Coastguard Worker 
87*1c60b9acSAndroid Build Coastguard Worker 	p = lws_cmdline_option(argc, argv, "-c");
88*1c60b9acSAndroid Build Coastguard Worker 	if (!p) {
89*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: missing -c <cert pem file>\n", __func__);
90*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
91*1c60b9acSAndroid Build Coastguard Worker 	}
92*1c60b9acSAndroid Build Coastguard Worker 	if (read_pem_c509_cert(&x509, p, pembuf, sizeof(pembuf))) {
93*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: unable to read \"%s\": errno %d\n",
94*1c60b9acSAndroid Build Coastguard Worker 			 __func__, p, errno);
95*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
96*1c60b9acSAndroid Build Coastguard Worker 	}
97*1c60b9acSAndroid Build Coastguard Worker 
98*1c60b9acSAndroid Build Coastguard Worker 	p = lws_cmdline_option(argc, argv, "-t");
99*1c60b9acSAndroid Build Coastguard Worker 	if (p) {
100*1c60b9acSAndroid Build Coastguard Worker 
101*1c60b9acSAndroid Build Coastguard Worker 		if (read_pem_c509_cert(&x509_trusted, p, pembuf,
102*1c60b9acSAndroid Build Coastguard Worker 				       sizeof(pembuf))) {
103*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: unable to read \"%s\": errno %d\n",
104*1c60b9acSAndroid Build Coastguard Worker 				 __func__, p, errno);
105*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
106*1c60b9acSAndroid Build Coastguard Worker 		}
107*1c60b9acSAndroid Build Coastguard Worker 
108*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: certs loaded OK\n", __func__);
109*1c60b9acSAndroid Build Coastguard Worker 
110*1c60b9acSAndroid Build Coastguard Worker 		if (lws_x509_verify(x509, x509_trusted, NULL)) {
111*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: verify failed\n", __func__);
112*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
113*1c60b9acSAndroid Build Coastguard Worker 		}
114*1c60b9acSAndroid Build Coastguard Worker 
115*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: verified OK\n", __func__);
116*1c60b9acSAndroid Build Coastguard Worker 	}
117*1c60b9acSAndroid Build Coastguard Worker 
118*1c60b9acSAndroid Build Coastguard Worker 	if (x509_trusted) {
119*1c60b9acSAndroid Build Coastguard Worker 
120*1c60b9acSAndroid Build Coastguard Worker 		/* show the trusted cert public key as a JWK */
121*1c60b9acSAndroid Build Coastguard Worker 
122*1c60b9acSAndroid Build Coastguard Worker 		if (lws_x509_public_to_jwk(&jwk, x509_trusted,
123*1c60b9acSAndroid Build Coastguard Worker 					   "P-256,P-384,P-521", 4096)) {
124*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: unable to get trusted cert pubkey as JWK\n",
125*1c60b9acSAndroid Build Coastguard Worker 				 __func__);
126*1c60b9acSAndroid Build Coastguard Worker 
127*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
128*1c60b9acSAndroid Build Coastguard Worker 		}
129*1c60b9acSAndroid Build Coastguard Worker 
130*1c60b9acSAndroid Build Coastguard Worker 		if ((p = lws_cmdline_option(argc, argv, "--alg")))
131*1c60b9acSAndroid Build Coastguard Worker 			lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p));
132*1c60b9acSAndroid Build Coastguard Worker 
133*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("JWK version of trusted cert:\n");
134*1c60b9acSAndroid Build Coastguard Worker 		lws_jwk_dump(&jwk);
135*1c60b9acSAndroid Build Coastguard Worker 		lws_jwk_destroy(&jwk);
136*1c60b9acSAndroid Build Coastguard Worker 	}
137*1c60b9acSAndroid Build Coastguard Worker 
138*1c60b9acSAndroid Build Coastguard Worker 	/* get the cert public key as a JWK */
139*1c60b9acSAndroid Build Coastguard Worker 
140*1c60b9acSAndroid Build Coastguard Worker 	if (lws_x509_public_to_jwk(&jwk, x509, "P-256,P-384,P-521", 4096)) {
141*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: unable to get cert pubkey as JWK\n", __func__);
142*1c60b9acSAndroid Build Coastguard Worker 
143*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
144*1c60b9acSAndroid Build Coastguard Worker 	}
145*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("JWK version of cert:\n");
146*1c60b9acSAndroid Build Coastguard Worker 
147*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "--alg")))
148*1c60b9acSAndroid Build Coastguard Worker 		lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p));
149*1c60b9acSAndroid Build Coastguard Worker 
150*1c60b9acSAndroid Build Coastguard Worker 	lws_jwk_dump(&jwk);
151*1c60b9acSAndroid Build Coastguard Worker 	/* only print public if he doesn't provide private */
152*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_cmdline_option(argc, argv, "-p")) {
153*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("Issuing Cert Public JWK on stdout\n");
154*1c60b9acSAndroid Build Coastguard Worker 		n = sizeof(pembuf);
155*1c60b9acSAndroid Build Coastguard Worker 		if (lws_jwk_export(&jwk, 0, pembuf, &n))
156*1c60b9acSAndroid Build Coastguard Worker 			puts(pembuf);
157*1c60b9acSAndroid Build Coastguard Worker 	}
158*1c60b9acSAndroid Build Coastguard Worker 
159*1c60b9acSAndroid Build Coastguard Worker 	/* if we know where the cert private key is, add that to the cert JWK */
160*1c60b9acSAndroid Build Coastguard Worker 
161*1c60b9acSAndroid Build Coastguard Worker 	p = lws_cmdline_option(argc, argv, "-p");
162*1c60b9acSAndroid Build Coastguard Worker 	if (p) {
163*1c60b9acSAndroid Build Coastguard Worker 		n = read_pem(p, pembuf, sizeof(pembuf));
164*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
165*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: unable read privkey %s\n", __func__, p);
166*1c60b9acSAndroid Build Coastguard Worker 
167*1c60b9acSAndroid Build Coastguard Worker 			goto bail3;
168*1c60b9acSAndroid Build Coastguard Worker 		}
169*1c60b9acSAndroid Build Coastguard Worker 		if (lws_x509_jwk_privkey_pem(context, &jwk, pembuf,
170*1c60b9acSAndroid Build Coastguard Worker 						(unsigned int)n, NULL)) {
171*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: unable to parse privkey %s\n",
172*1c60b9acSAndroid Build Coastguard Worker 					__func__, p);
173*1c60b9acSAndroid Build Coastguard Worker 
174*1c60b9acSAndroid Build Coastguard Worker 			goto bail3;
175*1c60b9acSAndroid Build Coastguard Worker 		}
176*1c60b9acSAndroid Build Coastguard Worker 
177*1c60b9acSAndroid Build Coastguard Worker 		if ((p = lws_cmdline_option(argc, argv, "--alg")))
178*1c60b9acSAndroid Build Coastguard Worker 			lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p));
179*1c60b9acSAndroid Build Coastguard Worker 
180*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("JWK version of cert + privkey:\n");
181*1c60b9acSAndroid Build Coastguard Worker 		lws_jwk_dump(&jwk);
182*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("Issuing Cert + Private JWK on stdout\n");
183*1c60b9acSAndroid Build Coastguard Worker 		n = sizeof(pembuf);
184*1c60b9acSAndroid Build Coastguard Worker 		if (lws_jwk_export(&jwk, LWSJWKF_EXPORT_PRIVATE, pembuf, &n))
185*1c60b9acSAndroid Build Coastguard Worker 			puts(pembuf);
186*1c60b9acSAndroid Build Coastguard Worker 	}
187*1c60b9acSAndroid Build Coastguard Worker 
188*1c60b9acSAndroid Build Coastguard Worker 	result = 0;
189*1c60b9acSAndroid Build Coastguard Worker 
190*1c60b9acSAndroid Build Coastguard Worker bail3:
191*1c60b9acSAndroid Build Coastguard Worker 	lws_jwk_destroy(&jwk);
192*1c60b9acSAndroid Build Coastguard Worker bail2:
193*1c60b9acSAndroid Build Coastguard Worker 	lws_x509_destroy(&x509_trusted);
194*1c60b9acSAndroid Build Coastguard Worker bail1:
195*1c60b9acSAndroid Build Coastguard Worker 	lws_x509_destroy(&x509);
196*1c60b9acSAndroid Build Coastguard Worker bail:
197*1c60b9acSAndroid Build Coastguard Worker 	lws_context_destroy(context);
198*1c60b9acSAndroid Build Coastguard Worker 
199*1c60b9acSAndroid Build Coastguard Worker 	if (result)
200*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: failed\n", __func__);
201*1c60b9acSAndroid Build Coastguard Worker 	else
202*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: OK\n", __func__);
203*1c60b9acSAndroid Build Coastguard Worker 
204*1c60b9acSAndroid Build Coastguard Worker 	return result;
205*1c60b9acSAndroid Build Coastguard Worker }
206