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 info.port = CONTEXT_PORT_NO_LISTEN;
108 info.options = 0;
109
110 context = lws_create_context(&info);
111 if (!context) {
112 lwsl_err("lws init failed\n");
113 return 1;
114 }
115
116 if ((p = lws_cmdline_option(argc, argv, "-v")))
117 curve = p;
118
119 if (lws_jwk_generate(context, &jwk, kty, bits, curve)) {
120 lwsl_err("lws_jwk_generate failed\n");
121
122 return 1;
123 }
124
125 if ((p = lws_cmdline_option(argc, argv, "--kid")))
126 lws_jwk_strdup_meta(&jwk, JWK_META_KID, p, strlen(p));
127
128 if ((p = lws_cmdline_option(argc, argv, "--use")))
129 lws_jwk_strdup_meta(&jwk, JWK_META_USE, p, strlen(p));
130
131 if ((p = lws_cmdline_option(argc, argv, "--alg")))
132 lws_jwk_strdup_meta(&jwk, JWK_META_ALG, p, strlen(p));
133
134 if ((p = lws_cmdline_option(argc, argv, "--key-ops")))
135 lws_jwk_strdup_meta(&jwk, JWK_META_KEY_OPS, p, strlen(p));
136
137 if ((p = lws_cmdline_option(argc, argv, "--public")) &&
138 kty != LWS_GENCRYPTO_KTY_OCT) {
139
140 int fd;
141
142 /* public version */
143
144 if (lws_jwk_export(&jwk, 0, key, &vl) < 0) {
145 lwsl_err("lws_jwk_export failed\n");
146
147 return 1;
148 }
149
150 fd = open(p, LWS_O_CREAT | LWS_O_TRUNC | LWS_O_WRONLY, 0600);
151 if (fd < 0) {
152 lwsl_err("Can't open public key file %s\n", p);
153 return 1;
154 }
155
156 if (lws_cmdline_option(argc, argv, "-c"))
157 format_c(fd, key);
158 else {
159 if (write(fd, key, strlen(key)) < 0) {
160 lwsl_err("Write public failed\n");
161 return 1;
162 }
163 }
164
165 close(fd);
166 }
167
168 /* private version */
169
170 if (lws_jwk_export(&jwk, LWSJWKF_EXPORT_PRIVATE, key, &vl) < 0) {
171 lwsl_err("lws_jwk_export failed\n");
172
173 return 1;
174 }
175
176 if (lws_cmdline_option(argc, argv, "-c")) {
177 if (format_c(1, key) < 0)
178 return 1;
179 } else
180 if (write(1, key, strlen(key)) < 0) {
181 lwsl_err("Write stdout failed\n");
182 return 1;
183 }
184
185 lws_jwk_destroy(&jwk);
186
187 lws_context_destroy(context);
188
189 return result;
190 }
191