• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  *
24  * Shared JWK handling that's the same whether JOSE or COSE
25  */
26 
27 #include "private-lib-core.h"
28 #include "private-lib-jose.h"
29 
30 static const char *meta_names[] = {
31 	"kty", "kid", "use", "key_ops", "x5c", "alg"
32 };
33 
34 static const char meta_b64[] = { 0, 0, 0, 0, 1, 0 };
35 
36 static const char *oct_names[] = {
37 	"k"
38 };
39 static const char oct_b64[] = { 1 };
40 
41 static const char *rsa_names[] = {
42 	"e", "n", "d", "p", "q", "dp", "dq", "qi"
43 };
44 static const char rsa_b64[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
45 
46 static const char *ec_names[] = {
47 	"crv", "x", "d", "y",
48 };
49 static const char ec_b64[] = { 0, 1, 1, 1 };
50 
51 int
lws_jwk_dump(struct lws_jwk * jwk)52 lws_jwk_dump(struct lws_jwk *jwk)
53 {
54 	const char **enames, *b64;
55 	int elems;
56 	int n;
57 
58 	(void)enames;
59 	(void)meta_names;
60 
61 	switch (jwk->kty) {
62 	default:
63 	case LWS_GENCRYPTO_KTY_UNKNOWN:
64 		lwsl_err("%s: jwk %p: unknown type\n", __func__, jwk);
65 
66 		return 1;
67 	case LWS_GENCRYPTO_KTY_OCT:
68 		elems = LWS_GENCRYPTO_OCT_KEYEL_COUNT;
69 		enames = oct_names;
70 		b64 = oct_b64;
71 		break;
72 	case LWS_GENCRYPTO_KTY_RSA:
73 		elems = LWS_GENCRYPTO_RSA_KEYEL_COUNT;
74 		enames = rsa_names;
75 		b64 = rsa_b64;
76 		break;
77 	case LWS_GENCRYPTO_KTY_EC:
78 		elems = LWS_GENCRYPTO_EC_KEYEL_COUNT;
79 		enames = ec_names;
80 		b64 = ec_b64;
81 		break;
82 	}
83 
84 	lwsl_info("%s: jwk %p\n", __func__, jwk);
85 
86 	for (n = 0; n < LWS_COUNT_JWK_ELEMENTS; n++) {
87 		if (jwk->meta[n].buf && meta_b64[n]) {
88 			lwsl_info("  meta: %s\n", meta_names[n]);
89 			lwsl_hexdump_info(jwk->meta[n].buf, jwk->meta[n].len);
90 		}
91 		if (jwk->meta[n].buf && !meta_b64[n])
92 			lwsl_info("  meta: %s: '%s'\n", meta_names[n],
93 					jwk->meta[n].buf);
94 	}
95 
96 	for (n = 0; n < elems; n++) {
97 		if (jwk->e[n].buf && b64[n]) {
98 			lwsl_info("  e: %s\n", enames[n]);
99 			lwsl_hexdump_info(jwk->e[n].buf, jwk->e[n].len);
100 		}
101 		if (jwk->e[n].buf && !b64[n])
102 			lwsl_info("  e: %s: '%s'\n", enames[n], jwk->e[n].buf);
103 	}
104 
105 	return 0;
106 }
107 
108 int
_lws_jwk_set_el_jwk(struct lws_gencrypto_keyelem * e,char * in,size_t len)109 _lws_jwk_set_el_jwk(struct lws_gencrypto_keyelem *e, char *in, size_t len)
110 {
111 	e->buf = lws_malloc(len + 1, "jwk");
112 	if (!e->buf)
113 		return -1;
114 
115 	memcpy(e->buf, in, len);
116 	e->buf[len] = '\0';
117 	e->len = (uint32_t)len;
118 
119 	return 0;
120 }
121 
122 void
lws_jwk_destroy_elements(struct lws_gencrypto_keyelem * el,int m)123 lws_jwk_destroy_elements(struct lws_gencrypto_keyelem *el, int m)
124 {
125 	int n;
126 
127 	for (n = 0; n < m; n++)
128 		if (el[n].buf) {
129 			/* wipe all key material when it goes out of scope */
130 			lws_explicit_bzero(el[n].buf, el[n].len);
131 			lws_free_set_NULL(el[n].buf);
132 			el[n].len = 0;
133 		}
134 }
135 
136 void
lws_jwk_destroy(struct lws_jwk * jwk)137 lws_jwk_destroy(struct lws_jwk *jwk)
138 {
139 	lws_jwk_destroy_elements(jwk->e, LWS_ARRAY_SIZE(jwk->e));
140 	lws_jwk_destroy_elements(jwk->meta, LWS_ARRAY_SIZE(jwk->meta));
141 }
142 
143 void
lws_jwk_init_jps(struct lws_jwk_parse_state * jps,struct lws_jwk * jwk,lws_jwk_key_import_callback cb,void * user)144 lws_jwk_init_jps(struct lws_jwk_parse_state *jps,
145 		 struct lws_jwk *jwk, lws_jwk_key_import_callback cb,
146 		 void *user)
147 {
148 	if (jwk)
149 		memset(jwk, 0, sizeof(*jwk));
150 
151 	jps->jwk		= jwk;
152 	jps->possible		= F_RSA | F_EC | F_OCT;
153 	jps->per_key_cb		= cb;
154 	jps->user		= user;
155 	jps->pos		= 0;
156 	jps->seen		= 0;
157 	jps->cose_state		= 0;
158 }
159 
160 int
lws_jwk_dup_oct(struct lws_jwk * jwk,const void * key,int len)161 lws_jwk_dup_oct(struct lws_jwk *jwk, const void *key, int len)
162 {
163 	unsigned int ulen = (unsigned int)len;
164 
165 	jwk->e[LWS_GENCRYPTO_KTY_OCT].buf = lws_malloc(ulen, __func__);
166 	if (!jwk->e[LWS_GENCRYPTO_KTY_OCT].buf)
167 		return -1;
168 
169 	jwk->kty = LWS_GENCRYPTO_KTY_OCT;
170 	jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].len = ulen;
171 
172 	memcpy(jwk->e[LWS_GENCRYPTO_KTY_OCT].buf, key, ulen);
173 
174 	return 0;
175 }
176 
177 int
lws_jwk_generate(struct lws_context * context,struct lws_jwk * jwk,enum lws_gencrypto_kty kty,int bits,const char * curve)178 lws_jwk_generate(struct lws_context *context, struct lws_jwk *jwk,
179 	         enum lws_gencrypto_kty kty, int bits, const char *curve)
180 {
181 	size_t sn;
182 	int n;
183 
184 	memset(jwk, 0, sizeof(*jwk));
185 
186 	jwk->kty = (int)kty;
187 	jwk->private_key = 1;
188 
189 	switch (kty) {
190 	case LWS_GENCRYPTO_KTY_RSA:
191 	{
192 		struct lws_genrsa_ctx ctx;
193 
194 		lwsl_notice("%s: generating %d bit RSA key\n", __func__, bits);
195 		n = lws_genrsa_new_keypair(context, &ctx, LGRSAM_PKCS1_1_5,
196 					    jwk->e, bits);
197 		lws_genrsa_destroy(&ctx);
198 		if (n) {
199 			lwsl_err("%s: problem generating RSA key\n", __func__);
200 			return 1;
201 		}
202 	}
203 		break;
204 	case LWS_GENCRYPTO_KTY_OCT:
205 		sn = (unsigned int)lws_gencrypto_bits_to_bytes(bits);
206 		jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf = lws_malloc(sn, "oct");
207 		if (!jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf)
208 			return 1;
209 		jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].len = (uint32_t)sn;
210 		if (lws_get_random(context,
211 			     jwk->e[LWS_GENCRYPTO_OCT_KEYEL_K].buf, sn) != sn) {
212 			lwsl_err("%s: problem getting random\n", __func__);
213 			return 1;
214 		}
215 		break;
216 	case LWS_GENCRYPTO_KTY_EC:
217 	{
218 		struct lws_genec_ctx ctx;
219 
220 		if (!curve) {
221 			lwsl_err("%s: must have a named curve\n", __func__);
222 
223 			return 1;
224 		}
225 
226 		if (lws_genecdsa_create(&ctx, context, NULL))
227 			return 1;
228 
229 		lwsl_notice("%s: generating ECDSA key on curve %s\n", __func__,
230 				curve);
231 
232 		n = lws_genecdsa_new_keypair(&ctx, curve, jwk->e);
233 		lws_genec_destroy(&ctx);
234 		if (n) {
235 			lwsl_err("%s: problem generating ECDSA key\n", __func__);
236 			return 1;
237 		}
238 	}
239 		break;
240 
241 	case LWS_GENCRYPTO_KTY_UNKNOWN:
242 	default:
243 		lwsl_err("%s: unknown kty\n", __func__);
244 		return 1;
245 	}
246 
247 	return 0;
248 }
249 
250 int
lws_jwk_rfc7638_fingerprint(struct lws_jwk * jwk,char * digest32)251 lws_jwk_rfc7638_fingerprint(struct lws_jwk *jwk, char *digest32)
252 {
253 	struct lws_genhash_ctx hash_ctx;
254 	size_t tmpsize = 2536;
255 	char *tmp;
256 	int n, m = (int)tmpsize;
257 
258 	tmp = lws_malloc(tmpsize, "rfc7638 tmp");
259 
260 	n = lws_jwk_export(jwk, LWSJWKF_EXPORT_NOCRLF, tmp, &m);
261 	if (n < 0)
262 		goto bail;
263 
264 	if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256))
265 		goto bail;
266 
267 	if (lws_genhash_update(&hash_ctx, tmp, (unsigned int)n)) {
268 		lws_genhash_destroy(&hash_ctx, NULL);
269 
270 		goto bail;
271 	}
272 	lws_free(tmp);
273 
274 	if (lws_genhash_destroy(&hash_ctx, digest32))
275 		return -1;
276 
277 	return 0;
278 
279 bail:
280 	lws_free(tmp);
281 
282 	return -1;
283 }
284 
285 int
lws_jwk_strdup_meta(struct lws_jwk * jwk,enum enum_jwk_meta_tok idx,const char * in,int len)286 lws_jwk_strdup_meta(struct lws_jwk *jwk, enum enum_jwk_meta_tok idx,
287 		    const char *in, int len)
288 {
289 	jwk->meta[idx].buf = lws_malloc((unsigned int)len, __func__);
290 	if (!jwk->meta[idx].buf)
291 		return 1;
292 	jwk->meta[idx].len = (uint32_t)(unsigned int)len;
293 	memcpy(jwk->meta[idx].buf, in, (unsigned int)len);
294 
295 	return 0;
296 }
297 
298