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