• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * lws-crypto-jwk
3  *
4  * Written in 2010-2019 by Andy Green <andy@warmcat.com>
5  *
6  * This file is made available under the Creative Commons CC0 1.0
7  * Universal Public Domain Dedication.
8  */
9 
10 #include <libwebsockets.h>
11 #include <sys/types.h>
12 #include <fcntl.h>
13 
14 /*
15  * handles escapes and line wrapping suitable for use
16  * defining a C char array ( -c option )
17  */
18 
19 static int
format_c(int fd,const char * key)20 format_c(int fd, const char *key)
21 {
22 	const char *k = key;
23 	int seq = 0;
24 
25 	while (*k) {
26 		if (*k == '{') {
27 			if (write(fd, "\"{\"\n\t\"", 6) < 6)
28 				return -1;
29 			k++;
30 			seq = 0;
31 			continue;
32 		}
33 		if (*k == '}') {
34 			if (write(fd, "\"\n\"}\"\n", 6) < 6)
35 				return -1;
36 			k++;
37 			seq = 0;
38 			continue;
39 		}
40 		if (*k == '\"') {
41 			if (write(fd, "\\\"", 2) < 2)
42 				return -1;
43 			seq += 2;
44 			k++;
45 			continue;
46 		}
47 		if (*k == ',') {
48 			if (write(fd, ",\"\n\t\"", 5) < 5)
49 				return -1;
50 			k++;
51 			seq = 0;
52 			continue;
53 		}
54 		if (write(fd, k, 1) < 1)
55 			return -1;
56 		seq++;
57 		if (seq >= 60) {
58 			if (write(fd, "\"\n\t \"", 5) < 5)
59 				return -1;
60 			seq = 1;
61 		}
62 		k++;
63 	}
64 
65 	return 0;
66 }
67 
main(int argc,const char ** argv)68 int main(int argc, const char **argv)
69 {
70 	int result = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
71 	enum lws_gencrypto_kty kty = LWS_GENCRYPTO_KTY_RSA;
72 	struct lws_context_creation_info info;
73 	const char *curve = "P-256", *p;
74 	struct lws_context *context;
75 	struct lws_jwk jwk;
76 	int bits = 4096;
77 	char key[32768];
78 	int vl = sizeof(key);
79 
80 	if ((p = lws_cmdline_option(argc, argv, "-d")))
81 		logs = atoi(p);
82 
83 	lws_set_log_level(logs, NULL);
84 	lwsl_user("LWS JWK example\n");
85 
86 	if ((p = lws_cmdline_option(argc, argv, "-b")))
87 		bits = atoi(p);
88 
89 	if ((p = lws_cmdline_option(argc, argv, "-t"))) {
90 		if (!strcmp(p, "RSA"))
91 			kty = LWS_GENCRYPTO_KTY_RSA;
92 		else
93 			if (!strcmp(p, "OCT"))
94 				kty = LWS_GENCRYPTO_KTY_OCT;
95 			else
96 				if (!strcmp(p, "EC"))
97 					kty = LWS_GENCRYPTO_KTY_EC;
98 				else {
99 					lwsl_err("Unknown key type (must be "
100 						 "OCT, RSA or EC)\n");
101 
102 					return 1;
103 				}
104 	}
105 
106 	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
107 #if defined(LWS_WITH_NETWORK)
108 	info.port = CONTEXT_PORT_NO_LISTEN;
109 #endif
110 	info.options = 0;
111 
112 	context = lws_create_context(&info);
113 	if (!context) {
114 		lwsl_err("lws init failed\n");
115 		return 1;
116 	}
117 
118 	if ((p = lws_cmdline_option(argc, argv, "-v")))
119 		curve = p;
120 
121 	if (lws_jwk_generate(context, &jwk, kty, bits, curve)) {
122 		lwsl_err("lws_jwk_generate failed\n");
123 
124 		return 1;
125 	}
126 
127 	if ((p = lws_cmdline_option(argc, argv, "--kid")))
128 		lws_jwk_strdup_meta(&jwk, JWK_META_KID, p, (int)strlen(p));
129 
130 	if ((p = lws_cmdline_option(argc, argv, "--use")))
131 		lws_jwk_strdup_meta(&jwk, JWK_META_USE, p, (int)strlen(p));
132 
133 	if ((p = lws_cmdline_option(argc, argv, "--alg")))
134 		lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, (int)strlen(p));
135 
136 	if ((p = lws_cmdline_option(argc, argv, "--key-ops")))
137 		lws_jwk_strdup_meta(&jwk, JWK_META_KEY_OPS, p, (int)strlen(p));
138 
139 	if ((p = lws_cmdline_option(argc, argv, "--public")) &&
140 	    kty != LWS_GENCRYPTO_KTY_OCT) {
141 
142 		int fd;
143 
144 		/* public version */
145 
146 		if (lws_jwk_export(&jwk, 0, key, &vl) < 0) {
147 			lwsl_err("lws_jwk_export failed\n");
148 
149 			return 1;
150 		}
151 
152 		fd = open(p, LWS_O_CREAT | LWS_O_TRUNC | LWS_O_WRONLY, 0600);
153 		if (fd < 0) {
154 			lwsl_err("Can't open public key file %s\n", p);
155 			return 1;
156 		}
157 
158 		if (lws_cmdline_option(argc, argv, "-c"))
159 			format_c(fd, key);
160 		else {
161 			if (write(fd, key,
162 #if defined(WIN32)
163 					(unsigned int)
164 #endif
165 					strlen(key)) < 0) {
166 				lwsl_err("Write public failed\n");
167 				return 1;
168 			}
169 		}
170 
171 		close(fd);
172 	}
173 
174 	/* private version */
175 
176 	if (lws_jwk_export(&jwk, LWSJWKF_EXPORT_PRIVATE, key, &vl) < 0) {
177 		lwsl_err("lws_jwk_export failed\n");
178 
179 		return 1;
180 	}
181 
182 	if (lws_cmdline_option(argc, argv, "-c")) {
183 		if (format_c(1, key) < 0)
184 			return 1;
185 	} else
186 		if (write(1, key,
187 #if defined(WIN32)
188 				(unsigned int)
189 #endif
190 				strlen(key)) < 0) {
191 			lwsl_err("Write stdout failed\n");
192 			return 1;
193 		}
194 
195 	lws_jwk_destroy(&jwk);
196 
197 	lws_context_destroy(context);
198 
199 	return result;
200 }
201