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