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