xref: /aosp_15_r20/external/libwebsockets/lib/jose/jwk/jose_key.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2021 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  *
24*1c60b9acSAndroid Build Coastguard Worker  * JOSE-specific JWK code
25*1c60b9acSAndroid Build Coastguard Worker  */
26*1c60b9acSAndroid Build Coastguard Worker 
27*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
28*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-jose.h"
29*1c60b9acSAndroid Build Coastguard Worker 
30*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_DEV_KIT)
31*1c60b9acSAndroid Build Coastguard Worker #include <fcntl.h>
32*1c60b9acSAndroid Build Coastguard Worker #endif
33*1c60b9acSAndroid Build Coastguard Worker 
34*1c60b9acSAndroid Build Coastguard Worker static const char * const kty_names[] = {
35*1c60b9acSAndroid Build Coastguard Worker 	"unknown",	/* LWS_GENCRYPTO_KTY_UNKNOWN */
36*1c60b9acSAndroid Build Coastguard Worker 	"oct",		/* LWS_GENCRYPTO_KTY_OCT */
37*1c60b9acSAndroid Build Coastguard Worker 	"RSA",		/* LWS_GENCRYPTO_KTY_RSA */
38*1c60b9acSAndroid Build Coastguard Worker 	"EC"		/* LWS_GENCRYPTO_KTY_EC */
39*1c60b9acSAndroid Build Coastguard Worker };
40*1c60b9acSAndroid Build Coastguard Worker 
41*1c60b9acSAndroid Build Coastguard Worker /*
42*1c60b9acSAndroid Build Coastguard Worker  * These are the entire legal token set for names in jwk.
43*1c60b9acSAndroid Build Coastguard Worker  *
44*1c60b9acSAndroid Build Coastguard Worker  * The first version is used to parse a detached single jwk that don't have any
45*1c60b9acSAndroid Build Coastguard Worker  * parent JSON context.  The second version is used to parse full jwk objects
46*1c60b9acSAndroid Build Coastguard Worker  * that has a "keys": [ ] array containing the keys.
47*1c60b9acSAndroid Build Coastguard Worker  */
48*1c60b9acSAndroid Build Coastguard Worker 
49*1c60b9acSAndroid Build Coastguard Worker const char * const jwk_tok[] = {
50*1c60b9acSAndroid Build Coastguard Worker 	"keys[]",			/* dummy */
51*1c60b9acSAndroid Build Coastguard Worker 	"e", "n", "d", "p", "q", "dp", "dq", "qi", /* RSA */
52*1c60b9acSAndroid Build Coastguard Worker 	"kty",				/* generic */
53*1c60b9acSAndroid Build Coastguard Worker 	"k",				/* symmetric key data */
54*1c60b9acSAndroid Build Coastguard Worker 	"crv", "x", "y",		/* EC (also "D") */
55*1c60b9acSAndroid Build Coastguard Worker 	"kid",				/* generic */
56*1c60b9acSAndroid Build Coastguard Worker 	"use"				/* mutually exclusive with "key_ops" */,
57*1c60b9acSAndroid Build Coastguard Worker 	"key_ops"			/* mutually exclusive with "use" */,
58*1c60b9acSAndroid Build Coastguard Worker 	"x5c",				/* generic */
59*1c60b9acSAndroid Build Coastguard Worker 	"alg"				/* generic */
60*1c60b9acSAndroid Build Coastguard Worker }, * const jwk_outer_tok[] = {
61*1c60b9acSAndroid Build Coastguard Worker 	"keys[]",
62*1c60b9acSAndroid Build Coastguard Worker 	"keys[].e", "keys[].n", "keys[].d", "keys[].p", "keys[].q", "keys[].dp",
63*1c60b9acSAndroid Build Coastguard Worker 	"keys[].dq", "keys[].qi",
64*1c60b9acSAndroid Build Coastguard Worker 
65*1c60b9acSAndroid Build Coastguard Worker 	"keys[].kty", "keys[].k",		/* generic */
66*1c60b9acSAndroid Build Coastguard Worker 	"keys[].crv", "keys[].x", "keys[].y",	/* EC (also "D") */
67*1c60b9acSAndroid Build Coastguard Worker 	"keys[].kid", "keys[].use"	/* mutually exclusive with "key_ops" */,
68*1c60b9acSAndroid Build Coastguard Worker 	"keys[].key_ops",		/* mutually exclusive with "use" */
69*1c60b9acSAndroid Build Coastguard Worker 	"keys[].x5c", "keys[].alg"
70*1c60b9acSAndroid Build Coastguard Worker };
71*1c60b9acSAndroid Build Coastguard Worker 
72*1c60b9acSAndroid Build Coastguard Worker static unsigned short tok_map[] = {
73*1c60b9acSAndroid Build Coastguard Worker 	F_RSA | F_EC | F_OCT | F_META |		 0xff,
74*1c60b9acSAndroid Build Coastguard Worker 	F_RSA |				F_B64U | F_M | LWS_GENCRYPTO_RSA_KEYEL_E,
75*1c60b9acSAndroid Build Coastguard Worker 	F_RSA |				F_B64U | F_M | LWS_GENCRYPTO_RSA_KEYEL_N,
76*1c60b9acSAndroid Build Coastguard Worker 	F_RSA | F_EC |			F_B64U |       LWS_GENCRYPTO_RSA_KEYEL_D,
77*1c60b9acSAndroid Build Coastguard Worker 	F_RSA |				F_B64U |       LWS_GENCRYPTO_RSA_KEYEL_P,
78*1c60b9acSAndroid Build Coastguard Worker 	F_RSA |				F_B64U |       LWS_GENCRYPTO_RSA_KEYEL_Q,
79*1c60b9acSAndroid Build Coastguard Worker 	F_RSA |				F_B64U |       LWS_GENCRYPTO_RSA_KEYEL_DP,
80*1c60b9acSAndroid Build Coastguard Worker 	F_RSA |				F_B64U |       LWS_GENCRYPTO_RSA_KEYEL_DQ,
81*1c60b9acSAndroid Build Coastguard Worker 	F_RSA |				F_B64U |       LWS_GENCRYPTO_RSA_KEYEL_QI,
82*1c60b9acSAndroid Build Coastguard Worker 
83*1c60b9acSAndroid Build Coastguard Worker 	F_RSA | F_EC | F_OCT | F_META |		 F_M | JWK_META_KTY,
84*1c60b9acSAndroid Build Coastguard Worker 		       F_OCT |		F_B64U | F_M | LWS_GENCRYPTO_OCT_KEYEL_K,
85*1c60b9acSAndroid Build Coastguard Worker 
86*1c60b9acSAndroid Build Coastguard Worker 		F_EC |				 F_M | LWS_GENCRYPTO_EC_KEYEL_CRV,
87*1c60b9acSAndroid Build Coastguard Worker 		F_EC |			F_B64U | F_M | LWS_GENCRYPTO_EC_KEYEL_X,
88*1c60b9acSAndroid Build Coastguard Worker 		F_EC |			F_B64U | F_M | LWS_GENCRYPTO_EC_KEYEL_Y,
89*1c60b9acSAndroid Build Coastguard Worker 
90*1c60b9acSAndroid Build Coastguard Worker 	F_RSA | F_EC | F_OCT | F_META |		       JWK_META_KID,
91*1c60b9acSAndroid Build Coastguard Worker 	F_RSA | F_EC | F_OCT | F_META |		       JWK_META_USE,
92*1c60b9acSAndroid Build Coastguard Worker 
93*1c60b9acSAndroid Build Coastguard Worker 	F_RSA | F_EC | F_OCT | F_META |		       JWK_META_KEY_OPS,
94*1c60b9acSAndroid Build Coastguard Worker 	F_RSA | F_EC | F_OCT | F_META | F_B64 |	       JWK_META_X5C,
95*1c60b9acSAndroid Build Coastguard Worker 	F_RSA | F_EC | F_OCT | F_META |		       JWK_META_ALG,
96*1c60b9acSAndroid Build Coastguard Worker };
97*1c60b9acSAndroid Build Coastguard Worker 
98*1c60b9acSAndroid Build Coastguard Worker struct lexico {
99*1c60b9acSAndroid Build Coastguard Worker 	const char *name;
100*1c60b9acSAndroid Build Coastguard Worker 	int idx;
101*1c60b9acSAndroid Build Coastguard Worker 	char meta;
102*1c60b9acSAndroid Build Coastguard Worker } lexico_ec[] =  {
103*1c60b9acSAndroid Build Coastguard Worker 	{ "alg",	JWK_META_ALG,			1 },
104*1c60b9acSAndroid Build Coastguard Worker 	{ "crv",	LWS_GENCRYPTO_EC_KEYEL_CRV,	0 },
105*1c60b9acSAndroid Build Coastguard Worker 	{ "d",		LWS_GENCRYPTO_EC_KEYEL_D,	2 | 0 },
106*1c60b9acSAndroid Build Coastguard Worker 	{ "key_ops",	JWK_META_KEY_OPS,		1 },
107*1c60b9acSAndroid Build Coastguard Worker 	{ "kid",	JWK_META_KID,			1 },
108*1c60b9acSAndroid Build Coastguard Worker 	{ "kty",	JWK_META_KTY,			1 },
109*1c60b9acSAndroid Build Coastguard Worker 	{ "use",	JWK_META_USE,			1 },
110*1c60b9acSAndroid Build Coastguard Worker 	{ "x",		LWS_GENCRYPTO_EC_KEYEL_X,	0 },
111*1c60b9acSAndroid Build Coastguard Worker 	{ "x5c",	JWK_META_X5C,			1 },
112*1c60b9acSAndroid Build Coastguard Worker 	{ "y",		LWS_GENCRYPTO_EC_KEYEL_Y,	0 }
113*1c60b9acSAndroid Build Coastguard Worker }, lexico_oct[] =  {
114*1c60b9acSAndroid Build Coastguard Worker 	{ "alg",	JWK_META_ALG,			1 },
115*1c60b9acSAndroid Build Coastguard Worker 	{ "k",		LWS_GENCRYPTO_OCT_KEYEL_K,	0 },
116*1c60b9acSAndroid Build Coastguard Worker 	{ "key_ops",	JWK_META_KEY_OPS,		1 },
117*1c60b9acSAndroid Build Coastguard Worker 	{ "kid",	JWK_META_KID,			1 },
118*1c60b9acSAndroid Build Coastguard Worker 	{ "kty",	JWK_META_KTY,			1 },
119*1c60b9acSAndroid Build Coastguard Worker 	{ "use",	JWK_META_USE,			1 },
120*1c60b9acSAndroid Build Coastguard Worker 	{ "x5c",	JWK_META_X5C,			1 }
121*1c60b9acSAndroid Build Coastguard Worker }, lexico_rsa[] =  {
122*1c60b9acSAndroid Build Coastguard Worker 	{ "alg",	JWK_META_ALG,			1 },
123*1c60b9acSAndroid Build Coastguard Worker 	{ "d",		LWS_GENCRYPTO_RSA_KEYEL_D,	2 | 0 },
124*1c60b9acSAndroid Build Coastguard Worker 	{ "dp",		LWS_GENCRYPTO_RSA_KEYEL_DP,	2 | 0 },
125*1c60b9acSAndroid Build Coastguard Worker 	{ "dq",		LWS_GENCRYPTO_RSA_KEYEL_DQ,	2 | 0 },
126*1c60b9acSAndroid Build Coastguard Worker 	{ "e",		LWS_GENCRYPTO_RSA_KEYEL_E,	0 },
127*1c60b9acSAndroid Build Coastguard Worker 	{ "key_ops",	JWK_META_KEY_OPS,		1 },
128*1c60b9acSAndroid Build Coastguard Worker 	{ "kid",	JWK_META_KID,			1 },
129*1c60b9acSAndroid Build Coastguard Worker 	{ "kty",	JWK_META_KTY,			1 },
130*1c60b9acSAndroid Build Coastguard Worker 	{ "n",		LWS_GENCRYPTO_RSA_KEYEL_N,	0 },
131*1c60b9acSAndroid Build Coastguard Worker 	{ "p",		LWS_GENCRYPTO_RSA_KEYEL_P,	2 | 0 },
132*1c60b9acSAndroid Build Coastguard Worker 	{ "q",		LWS_GENCRYPTO_RSA_KEYEL_Q,	2 | 0 },
133*1c60b9acSAndroid Build Coastguard Worker 	{ "qi",		LWS_GENCRYPTO_RSA_KEYEL_QI,	2 | 0 },
134*1c60b9acSAndroid Build Coastguard Worker 	{ "use",	JWK_META_USE,			1 },
135*1c60b9acSAndroid Build Coastguard Worker 	{ "x5c",	JWK_META_X5C,			1 }
136*1c60b9acSAndroid Build Coastguard Worker };
137*1c60b9acSAndroid Build Coastguard Worker 
138*1c60b9acSAndroid Build Coastguard Worker static int
_lws_jwk_set_el_jwk_b64(struct lws_gencrypto_keyelem * e,char * in,int len)139*1c60b9acSAndroid Build Coastguard Worker _lws_jwk_set_el_jwk_b64(struct lws_gencrypto_keyelem *e, char *in, int len)
140*1c60b9acSAndroid Build Coastguard Worker {
141*1c60b9acSAndroid Build Coastguard Worker 	size_t dec_size = (unsigned int)lws_base64_size(len);
142*1c60b9acSAndroid Build Coastguard Worker 	int n;
143*1c60b9acSAndroid Build Coastguard Worker 
144*1c60b9acSAndroid Build Coastguard Worker 	e->buf = lws_malloc(dec_size, "jwk");
145*1c60b9acSAndroid Build Coastguard Worker 	if (!e->buf)
146*1c60b9acSAndroid Build Coastguard Worker 		return -1;
147*1c60b9acSAndroid Build Coastguard Worker 
148*1c60b9acSAndroid Build Coastguard Worker 	/* same decoder accepts both url or original styles */
149*1c60b9acSAndroid Build Coastguard Worker 
150*1c60b9acSAndroid Build Coastguard Worker 	n = lws_b64_decode_string_len(in, len, (char *)e->buf, (int)dec_size - 1);
151*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
152*1c60b9acSAndroid Build Coastguard Worker 		return -1;
153*1c60b9acSAndroid Build Coastguard Worker 	e->len = (uint32_t)n;
154*1c60b9acSAndroid Build Coastguard Worker 
155*1c60b9acSAndroid Build Coastguard Worker 	return 0;
156*1c60b9acSAndroid Build Coastguard Worker }
157*1c60b9acSAndroid Build Coastguard Worker 
158*1c60b9acSAndroid Build Coastguard Worker static int
_lws_jwk_set_el_jwk_b64u(struct lws_gencrypto_keyelem * e,char * in,int len)159*1c60b9acSAndroid Build Coastguard Worker _lws_jwk_set_el_jwk_b64u(struct lws_gencrypto_keyelem *e, char *in, int len)
160*1c60b9acSAndroid Build Coastguard Worker {
161*1c60b9acSAndroid Build Coastguard Worker 	size_t dec_size = (size_t)lws_base64_size(len);
162*1c60b9acSAndroid Build Coastguard Worker 	int n;
163*1c60b9acSAndroid Build Coastguard Worker 
164*1c60b9acSAndroid Build Coastguard Worker 	e->buf = lws_malloc(dec_size, "jwk");
165*1c60b9acSAndroid Build Coastguard Worker 	if (!e->buf)
166*1c60b9acSAndroid Build Coastguard Worker 		return -1;
167*1c60b9acSAndroid Build Coastguard Worker 
168*1c60b9acSAndroid Build Coastguard Worker 	/* same decoder accepts both url or original styles */
169*1c60b9acSAndroid Build Coastguard Worker 
170*1c60b9acSAndroid Build Coastguard Worker 	n = lws_b64_decode_string_len(in, len, (char *)e->buf, (int)dec_size - 1);
171*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
172*1c60b9acSAndroid Build Coastguard Worker 		return -1;
173*1c60b9acSAndroid Build Coastguard Worker 	e->len = (uint32_t)n;
174*1c60b9acSAndroid Build Coastguard Worker 
175*1c60b9acSAndroid Build Coastguard Worker 	return 0;
176*1c60b9acSAndroid Build Coastguard Worker }
177*1c60b9acSAndroid Build Coastguard Worker 
178*1c60b9acSAndroid Build Coastguard Worker 
179*1c60b9acSAndroid Build Coastguard Worker signed char
cb_jwk(struct lejp_ctx * ctx,char reason)180*1c60b9acSAndroid Build Coastguard Worker cb_jwk(struct lejp_ctx *ctx, char reason)
181*1c60b9acSAndroid Build Coastguard Worker {
182*1c60b9acSAndroid Build Coastguard Worker 	struct lws_jwk_parse_state *jps = (struct lws_jwk_parse_state *)ctx->user;
183*1c60b9acSAndroid Build Coastguard Worker 	struct lws_jwk *jwk = jps->jwk;
184*1c60b9acSAndroid Build Coastguard Worker 	unsigned int idx, n;
185*1c60b9acSAndroid Build Coastguard Worker 	unsigned short poss;
186*1c60b9acSAndroid Build Coastguard Worker 	char dotstar[64];
187*1c60b9acSAndroid Build Coastguard Worker 
188*1c60b9acSAndroid Build Coastguard Worker 	if (reason == LEJPCB_VAL_STR_START)
189*1c60b9acSAndroid Build Coastguard Worker 		jps->pos = 0;
190*1c60b9acSAndroid Build Coastguard Worker 
191*1c60b9acSAndroid Build Coastguard Worker 	if (reason == LEJPCB_OBJECT_START && ctx->path_match == 0 + 1)
192*1c60b9acSAndroid Build Coastguard Worker 		/*
193*1c60b9acSAndroid Build Coastguard Worker 		 * new keys[] member is starting
194*1c60b9acSAndroid Build Coastguard Worker 		 *
195*1c60b9acSAndroid Build Coastguard Worker 		 * Until we see some JSON names, it could be anything...
196*1c60b9acSAndroid Build Coastguard Worker 		 * there is no requirement for kty to be given first and eg,
197*1c60b9acSAndroid Build Coastguard Worker 		 * ACME specifies the keys must be ordered in lexographic
198*1c60b9acSAndroid Build Coastguard Worker 		 * order - where kty is not first.
199*1c60b9acSAndroid Build Coastguard Worker 		 */
200*1c60b9acSAndroid Build Coastguard Worker 		jps->possible = F_RSA | F_EC | F_OCT;
201*1c60b9acSAndroid Build Coastguard Worker 
202*1c60b9acSAndroid Build Coastguard Worker 	if (reason == LEJPCB_OBJECT_END && ctx->path_match == 0 + 1) {
203*1c60b9acSAndroid Build Coastguard Worker 		/* we completed parsing a key */
204*1c60b9acSAndroid Build Coastguard Worker 		if (jps->per_key_cb && jps->possible) {
205*1c60b9acSAndroid Build Coastguard Worker 			if (jps->per_key_cb(jps->jwk, jps->user)) {
206*1c60b9acSAndroid Build Coastguard Worker 
207*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: user cb halts import\n",
208*1c60b9acSAndroid Build Coastguard Worker 					    __func__);
209*1c60b9acSAndroid Build Coastguard Worker 
210*1c60b9acSAndroid Build Coastguard Worker 				return -2;
211*1c60b9acSAndroid Build Coastguard Worker 			}
212*1c60b9acSAndroid Build Coastguard Worker 
213*1c60b9acSAndroid Build Coastguard Worker 			/* clear it down */
214*1c60b9acSAndroid Build Coastguard Worker 			lws_jwk_destroy(jps->jwk);
215*1c60b9acSAndroid Build Coastguard Worker 			jps->possible = 0;
216*1c60b9acSAndroid Build Coastguard Worker 		}
217*1c60b9acSAndroid Build Coastguard Worker 	}
218*1c60b9acSAndroid Build Coastguard Worker 
219*1c60b9acSAndroid Build Coastguard Worker 	if (reason == LEJPCB_COMPLETE) {
220*1c60b9acSAndroid Build Coastguard Worker 
221*1c60b9acSAndroid Build Coastguard Worker 		/*
222*1c60b9acSAndroid Build Coastguard Worker 		 * Now we saw the whole jwk and know the key type, let'jwk insist
223*1c60b9acSAndroid Build Coastguard Worker 		 * that as a whole, it must be consistent and complete.
224*1c60b9acSAndroid Build Coastguard Worker 		 *
225*1c60b9acSAndroid Build Coastguard Worker 		 * The tracking of ->possible bits from even before we know the
226*1c60b9acSAndroid Build Coastguard Worker 		 * kty already makes certain we cannot have key element members
227*1c60b9acSAndroid Build Coastguard Worker 		 * defined that are inconsistent with the key type.
228*1c60b9acSAndroid Build Coastguard Worker 		 */
229*1c60b9acSAndroid Build Coastguard Worker 
230*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n < LWS_ARRAY_SIZE(tok_map); n++)
231*1c60b9acSAndroid Build Coastguard Worker 			/*
232*1c60b9acSAndroid Build Coastguard Worker 			 * All mandataory elements for the key type
233*1c60b9acSAndroid Build Coastguard Worker 			 * must be present
234*1c60b9acSAndroid Build Coastguard Worker 			 */
235*1c60b9acSAndroid Build Coastguard Worker 			if ((tok_map[n] & jps->possible) && (
236*1c60b9acSAndroid Build Coastguard Worker 			    ((tok_map[n] & (F_M | F_META)) == (F_M | F_META) &&
237*1c60b9acSAndroid Build Coastguard Worker 			     !jwk->meta[tok_map[n] & 0xff].buf) ||
238*1c60b9acSAndroid Build Coastguard Worker 			    ((tok_map[n] & (F_M | F_META)) == F_M &&
239*1c60b9acSAndroid Build Coastguard Worker 			     !jwk->e[tok_map[n] & 0xff].buf))) {
240*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: missing %s\n", __func__,
241*1c60b9acSAndroid Build Coastguard Worker 					    jwk_tok[n]);
242*1c60b9acSAndroid Build Coastguard Worker 					return -3;
243*1c60b9acSAndroid Build Coastguard Worker 				}
244*1c60b9acSAndroid Build Coastguard Worker 
245*1c60b9acSAndroid Build Coastguard Worker 		/*
246*1c60b9acSAndroid Build Coastguard Worker 		 * When the key may be public or public + private, ensure the
247*1c60b9acSAndroid Build Coastguard Worker 		 * intra-key members related to that are consistent.
248*1c60b9acSAndroid Build Coastguard Worker 		 *
249*1c60b9acSAndroid Build Coastguard Worker 		 * Only RSA keys need extra care, since EC keys are already
250*1c60b9acSAndroid Build Coastguard Worker 		 * confirmed by making CRV, X and Y mandatory and only D
251*1c60b9acSAndroid Build Coastguard Worker 		 * (the singular private part) optional.  For RSA, N and E are
252*1c60b9acSAndroid Build Coastguard Worker 		 * also already known to be present using mandatory checking.
253*1c60b9acSAndroid Build Coastguard Worker 		 */
254*1c60b9acSAndroid Build Coastguard Worker 
255*1c60b9acSAndroid Build Coastguard Worker 		/*
256*1c60b9acSAndroid Build Coastguard Worker 		 * If a private key, it must have all D, P and Q.  Public key
257*1c60b9acSAndroid Build Coastguard Worker 		 * must have none of them.
258*1c60b9acSAndroid Build Coastguard Worker 		 */
259*1c60b9acSAndroid Build Coastguard Worker 		if (jwk->kty == LWS_GENCRYPTO_KTY_RSA &&
260*1c60b9acSAndroid Build Coastguard Worker 		    !(((!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf) &&
261*1c60b9acSAndroid Build Coastguard Worker 		      (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) &&
262*1c60b9acSAndroid Build Coastguard Worker 		      (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf)) ||
263*1c60b9acSAndroid Build Coastguard Worker 		      (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf &&
264*1c60b9acSAndroid Build Coastguard Worker 		       jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf &&
265*1c60b9acSAndroid Build Coastguard Worker 		       jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf))
266*1c60b9acSAndroid Build Coastguard Worker 		      ) {
267*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: RSA requires D, P and Q for private\n",
268*1c60b9acSAndroid Build Coastguard Worker 				    __func__);
269*1c60b9acSAndroid Build Coastguard Worker 			return -3;
270*1c60b9acSAndroid Build Coastguard Worker 		}
271*1c60b9acSAndroid Build Coastguard Worker 
272*1c60b9acSAndroid Build Coastguard Worker 		/*
273*1c60b9acSAndroid Build Coastguard Worker 		 * If the precomputed private key terms appear, they must all
274*1c60b9acSAndroid Build Coastguard Worker 		 * appear together.
275*1c60b9acSAndroid Build Coastguard Worker 		 */
276*1c60b9acSAndroid Build Coastguard Worker 		if (jwk->kty == LWS_GENCRYPTO_KTY_RSA &&
277*1c60b9acSAndroid Build Coastguard Worker 		    !(((!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DP].buf) &&
278*1c60b9acSAndroid Build Coastguard Worker 		      (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf) &&
279*1c60b9acSAndroid Build Coastguard Worker 		      (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_QI].buf)) ||
280*1c60b9acSAndroid Build Coastguard Worker 		      (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DP].buf &&
281*1c60b9acSAndroid Build Coastguard Worker 		       jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf &&
282*1c60b9acSAndroid Build Coastguard Worker 		       jwk->e[LWS_GENCRYPTO_RSA_KEYEL_QI].buf))
283*1c60b9acSAndroid Build Coastguard Worker 		      ) {
284*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: RSA DP, DQ, QI must all appear "
285*1c60b9acSAndroid Build Coastguard Worker 				    "or none\n", __func__);
286*1c60b9acSAndroid Build Coastguard Worker 			return -3;
287*1c60b9acSAndroid Build Coastguard Worker 		}
288*1c60b9acSAndroid Build Coastguard Worker 
289*1c60b9acSAndroid Build Coastguard Worker 		/*
290*1c60b9acSAndroid Build Coastguard Worker 		 * The precomputed private key terms must not appear without
291*1c60b9acSAndroid Build Coastguard Worker 		 * the private key itself also appearing.
292*1c60b9acSAndroid Build Coastguard Worker 		 */
293*1c60b9acSAndroid Build Coastguard Worker 		if (jwk->kty == LWS_GENCRYPTO_KTY_RSA &&
294*1c60b9acSAndroid Build Coastguard Worker 		    !jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf &&
295*1c60b9acSAndroid Build Coastguard Worker 		     jwk->e[LWS_GENCRYPTO_RSA_KEYEL_DQ].buf) {
296*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: RSA DP, DQ, QI can appear only with "
297*1c60b9acSAndroid Build Coastguard Worker 				    "private key\n", __func__);
298*1c60b9acSAndroid Build Coastguard Worker 			return -3;
299*1c60b9acSAndroid Build Coastguard Worker 		}
300*1c60b9acSAndroid Build Coastguard Worker 
301*1c60b9acSAndroid Build Coastguard Worker 		if ((jwk->kty == LWS_GENCRYPTO_KTY_RSA ||
302*1c60b9acSAndroid Build Coastguard Worker 		     jwk->kty == LWS_GENCRYPTO_KTY_EC) &&
303*1c60b9acSAndroid Build Coastguard Worker 		    jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf)
304*1c60b9acSAndroid Build Coastguard Worker 		jwk->private_key = 1;
305*1c60b9acSAndroid Build Coastguard Worker 	}
306*1c60b9acSAndroid Build Coastguard Worker 
307*1c60b9acSAndroid Build Coastguard Worker 	if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
308*1c60b9acSAndroid Build Coastguard Worker 		return 0;
309*1c60b9acSAndroid Build Coastguard Worker 
310*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->path_match == 0 + 1)
311*1c60b9acSAndroid Build Coastguard Worker 		return 0;
312*1c60b9acSAndroid Build Coastguard Worker 
313*1c60b9acSAndroid Build Coastguard Worker 	idx = tok_map[ctx->path_match - 1];
314*1c60b9acSAndroid Build Coastguard Worker 	if ((idx & 0xff) == 0xff)
315*1c60b9acSAndroid Build Coastguard Worker 		return 0;
316*1c60b9acSAndroid Build Coastguard Worker 
317*1c60b9acSAndroid Build Coastguard Worker 	switch (idx) {
318*1c60b9acSAndroid Build Coastguard Worker 	/* note: kty is not necessarily first... we have to keep track of
319*1c60b9acSAndroid Build Coastguard Worker 	 * what could match given which element names have already been
320*1c60b9acSAndroid Build Coastguard Worker 	 * seen.  Once kty comes, we confirm it'jwk still possible (ie, it'jwk
321*1c60b9acSAndroid Build Coastguard Worker 	 * not trying to tell us that it'jwk RSA now when we saw a "crv"
322*1c60b9acSAndroid Build Coastguard Worker 	 * earlier) and then reduce the possibilities to just the one that
323*1c60b9acSAndroid Build Coastguard Worker 	 * kty told. */
324*1c60b9acSAndroid Build Coastguard Worker 	case F_RSA | F_EC | F_OCT | F_META | F_M | JWK_META_KTY:
325*1c60b9acSAndroid Build Coastguard Worker 
326*1c60b9acSAndroid Build Coastguard Worker 		if (ctx->npos == 3 && !strncmp(ctx->buf, "oct", 3)) {
327*1c60b9acSAndroid Build Coastguard Worker 			if (!(jps->possible & F_OCT))
328*1c60b9acSAndroid Build Coastguard Worker 				goto elements_mismatch;
329*1c60b9acSAndroid Build Coastguard Worker 			jwk->kty = LWS_GENCRYPTO_KTY_OCT;
330*1c60b9acSAndroid Build Coastguard Worker 			jps->possible = F_OCT;
331*1c60b9acSAndroid Build Coastguard Worker 			goto cont;
332*1c60b9acSAndroid Build Coastguard Worker 		}
333*1c60b9acSAndroid Build Coastguard Worker 		if (ctx->npos == 3 && !strncmp(ctx->buf, "RSA", 3)) {
334*1c60b9acSAndroid Build Coastguard Worker 			if (!(jps->possible & F_RSA))
335*1c60b9acSAndroid Build Coastguard Worker 				goto elements_mismatch;
336*1c60b9acSAndroid Build Coastguard Worker 			jwk->kty = LWS_GENCRYPTO_KTY_RSA;
337*1c60b9acSAndroid Build Coastguard Worker 			jps->possible = F_RSA;
338*1c60b9acSAndroid Build Coastguard Worker 			goto cont;
339*1c60b9acSAndroid Build Coastguard Worker 		}
340*1c60b9acSAndroid Build Coastguard Worker 		if (ctx->npos == 2 && !strncmp(ctx->buf, "EC", 2)) {
341*1c60b9acSAndroid Build Coastguard Worker 			if (!(jps->possible & F_EC))
342*1c60b9acSAndroid Build Coastguard Worker 				goto elements_mismatch;
343*1c60b9acSAndroid Build Coastguard Worker 			jwk->kty = LWS_GENCRYPTO_KTY_EC;
344*1c60b9acSAndroid Build Coastguard Worker 			jps->possible = F_EC;
345*1c60b9acSAndroid Build Coastguard Worker 			goto cont;
346*1c60b9acSAndroid Build Coastguard Worker 		}
347*1c60b9acSAndroid Build Coastguard Worker 		lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar));
348*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: Unknown KTY '%s'\n", __func__, dotstar);
349*1c60b9acSAndroid Build Coastguard Worker 		return -1;
350*1c60b9acSAndroid Build Coastguard Worker 
351*1c60b9acSAndroid Build Coastguard Worker 	default:
352*1c60b9acSAndroid Build Coastguard Worker cont:
353*1c60b9acSAndroid Build Coastguard Worker 		if (jps->pos + ctx->npos >= (int)sizeof(jps->b64))
354*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
355*1c60b9acSAndroid Build Coastguard Worker 
356*1c60b9acSAndroid Build Coastguard Worker 		memcpy(jps->b64 + jps->pos, ctx->buf, ctx->npos);
357*1c60b9acSAndroid Build Coastguard Worker 		jps->pos += ctx->npos;
358*1c60b9acSAndroid Build Coastguard Worker 
359*1c60b9acSAndroid Build Coastguard Worker 		if (reason == LEJPCB_VAL_STR_CHUNK)
360*1c60b9acSAndroid Build Coastguard Worker 			return 0;
361*1c60b9acSAndroid Build Coastguard Worker 
362*1c60b9acSAndroid Build Coastguard Worker 		/* chunking has been collated */
363*1c60b9acSAndroid Build Coastguard Worker 
364*1c60b9acSAndroid Build Coastguard Worker 		poss = idx & (F_RSA | F_EC | F_OCT);
365*1c60b9acSAndroid Build Coastguard Worker 		jps->possible &= poss;
366*1c60b9acSAndroid Build Coastguard Worker 		if (!jps->possible)
367*1c60b9acSAndroid Build Coastguard Worker 			goto elements_mismatch;
368*1c60b9acSAndroid Build Coastguard Worker 
369*1c60b9acSAndroid Build Coastguard Worker 		if (idx & F_META) {
370*1c60b9acSAndroid Build Coastguard Worker 			if (_lws_jwk_set_el_jwk(&jwk->meta[idx & 0x7f],
371*1c60b9acSAndroid Build Coastguard Worker 						jps->b64, (unsigned int)jps->pos) < 0)
372*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
373*1c60b9acSAndroid Build Coastguard Worker 
374*1c60b9acSAndroid Build Coastguard Worker 			break;
375*1c60b9acSAndroid Build Coastguard Worker 		}
376*1c60b9acSAndroid Build Coastguard Worker 
377*1c60b9acSAndroid Build Coastguard Worker 		if (idx & F_B64U) {
378*1c60b9acSAndroid Build Coastguard Worker 			/* key data... do the base64 decode as needed */
379*1c60b9acSAndroid Build Coastguard Worker 			if (_lws_jwk_set_el_jwk_b64u(&jwk->e[idx & 0x7f],
380*1c60b9acSAndroid Build Coastguard Worker 						     jps->b64, jps->pos) < 0)
381*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
382*1c60b9acSAndroid Build Coastguard Worker 
383*1c60b9acSAndroid Build Coastguard Worker 			if (jwk->e[idx & 0x7f].len >
384*1c60b9acSAndroid Build Coastguard Worker 					LWS_JWE_LIMIT_KEY_ELEMENT_BYTES) {
385*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: oversize keydata\n", __func__);
386*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
387*1c60b9acSAndroid Build Coastguard Worker 			}
388*1c60b9acSAndroid Build Coastguard Worker 
389*1c60b9acSAndroid Build Coastguard Worker 			return 0;
390*1c60b9acSAndroid Build Coastguard Worker 		}
391*1c60b9acSAndroid Build Coastguard Worker 
392*1c60b9acSAndroid Build Coastguard Worker 		if (idx & F_B64) {
393*1c60b9acSAndroid Build Coastguard Worker 
394*1c60b9acSAndroid Build Coastguard Worker 			/* cert data... do non-urlcoded base64 decode */
395*1c60b9acSAndroid Build Coastguard Worker 			if (_lws_jwk_set_el_jwk_b64(&jwk->e[idx & 0x7f],
396*1c60b9acSAndroid Build Coastguard Worker 						    jps->b64, jps->pos) < 0)
397*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
398*1c60b9acSAndroid Build Coastguard Worker 			return 0;
399*1c60b9acSAndroid Build Coastguard Worker 		}
400*1c60b9acSAndroid Build Coastguard Worker 
401*1c60b9acSAndroid Build Coastguard Worker 			if (_lws_jwk_set_el_jwk(&jwk->e[idx & 0x7f],
402*1c60b9acSAndroid Build Coastguard Worker 						jps->b64, (unsigned int)jps->pos) < 0)
403*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
404*1c60b9acSAndroid Build Coastguard Worker 		break;
405*1c60b9acSAndroid Build Coastguard Worker 	}
406*1c60b9acSAndroid Build Coastguard Worker 
407*1c60b9acSAndroid Build Coastguard Worker 	return 0;
408*1c60b9acSAndroid Build Coastguard Worker 
409*1c60b9acSAndroid Build Coastguard Worker elements_mismatch:
410*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err("%s: jwk elements mismatch\n", __func__);
411*1c60b9acSAndroid Build Coastguard Worker 
412*1c60b9acSAndroid Build Coastguard Worker bail:
413*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err("%s: element failed\n", __func__);
414*1c60b9acSAndroid Build Coastguard Worker 
415*1c60b9acSAndroid Build Coastguard Worker 	return -1;
416*1c60b9acSAndroid Build Coastguard Worker }
417*1c60b9acSAndroid Build Coastguard Worker 
418*1c60b9acSAndroid Build Coastguard Worker int
lws_jwk_import(struct lws_jwk * jwk,lws_jwk_key_import_callback cb,void * user,const char * in,size_t len)419*1c60b9acSAndroid Build Coastguard Worker lws_jwk_import(struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user,
420*1c60b9acSAndroid Build Coastguard Worker 	       const char *in, size_t len)
421*1c60b9acSAndroid Build Coastguard Worker {
422*1c60b9acSAndroid Build Coastguard Worker 	struct lejp_ctx jctx;
423*1c60b9acSAndroid Build Coastguard Worker 	struct lws_jwk_parse_state jps;
424*1c60b9acSAndroid Build Coastguard Worker 	int m;
425*1c60b9acSAndroid Build Coastguard Worker 
426*1c60b9acSAndroid Build Coastguard Worker 	lws_jwk_init_jps(&jps, jwk, cb, user);
427*1c60b9acSAndroid Build Coastguard Worker 
428*1c60b9acSAndroid Build Coastguard Worker 	lejp_construct(&jctx, cb_jwk, &jps, cb ? jwk_outer_tok: jwk_tok,
429*1c60b9acSAndroid Build Coastguard Worker 		       LWS_ARRAY_SIZE(jwk_tok));
430*1c60b9acSAndroid Build Coastguard Worker 
431*1c60b9acSAndroid Build Coastguard Worker 	m = lejp_parse(&jctx, (uint8_t *)in, (int)len);
432*1c60b9acSAndroid Build Coastguard Worker 	lejp_destruct(&jctx);
433*1c60b9acSAndroid Build Coastguard Worker 
434*1c60b9acSAndroid Build Coastguard Worker 	if (m < 0) {
435*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: parse got %d\n", __func__, m);
436*1c60b9acSAndroid Build Coastguard Worker 		lws_jwk_destroy(jwk);
437*1c60b9acSAndroid Build Coastguard Worker 		return -1;
438*1c60b9acSAndroid Build Coastguard Worker 	}
439*1c60b9acSAndroid Build Coastguard Worker 
440*1c60b9acSAndroid Build Coastguard Worker 	switch (jwk->kty) {
441*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_UNKNOWN:
442*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: missing or unknown kty\n", __func__);
443*1c60b9acSAndroid Build Coastguard Worker 		lws_jwk_destroy(jwk);
444*1c60b9acSAndroid Build Coastguard Worker 		return -1;
445*1c60b9acSAndroid Build Coastguard Worker 	default:
446*1c60b9acSAndroid Build Coastguard Worker 		break;
447*1c60b9acSAndroid Build Coastguard Worker 	}
448*1c60b9acSAndroid Build Coastguard Worker 
449*1c60b9acSAndroid Build Coastguard Worker 	return 0;
450*1c60b9acSAndroid Build Coastguard Worker }
451*1c60b9acSAndroid Build Coastguard Worker 
452*1c60b9acSAndroid Build Coastguard Worker 
453*1c60b9acSAndroid Build Coastguard Worker int
lws_jwk_export(struct lws_jwk * jwk,int flags,char * p,int * len)454*1c60b9acSAndroid Build Coastguard Worker lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len)
455*1c60b9acSAndroid Build Coastguard Worker {
456*1c60b9acSAndroid Build Coastguard Worker 	char *start = p, *end = &p[*len - 1];
457*1c60b9acSAndroid Build Coastguard Worker 	int n, m, limit, first = 1, asym = 0;
458*1c60b9acSAndroid Build Coastguard Worker 	struct lexico *l;
459*1c60b9acSAndroid Build Coastguard Worker 
460*1c60b9acSAndroid Build Coastguard Worker 	/* RFC7638 lexicographic order requires
461*1c60b9acSAndroid Build Coastguard Worker 	 *  RSA: e -> kty -> n
462*1c60b9acSAndroid Build Coastguard Worker 	 *  oct: k -> kty
463*1c60b9acSAndroid Build Coastguard Worker 	 *
464*1c60b9acSAndroid Build Coastguard Worker 	 * ie, meta and key data elements appear interleaved in name alpha order
465*1c60b9acSAndroid Build Coastguard Worker 	 */
466*1c60b9acSAndroid Build Coastguard Worker 
467*1c60b9acSAndroid Build Coastguard Worker 	p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{");
468*1c60b9acSAndroid Build Coastguard Worker 
469*1c60b9acSAndroid Build Coastguard Worker 	switch (jwk->kty) {
470*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_OCT:
471*1c60b9acSAndroid Build Coastguard Worker 		l = lexico_oct;
472*1c60b9acSAndroid Build Coastguard Worker 		limit = LWS_ARRAY_SIZE(lexico_oct);
473*1c60b9acSAndroid Build Coastguard Worker 		break;
474*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_RSA:
475*1c60b9acSAndroid Build Coastguard Worker 		l = lexico_rsa;
476*1c60b9acSAndroid Build Coastguard Worker 		limit = LWS_ARRAY_SIZE(lexico_rsa);
477*1c60b9acSAndroid Build Coastguard Worker 		asym = 1;
478*1c60b9acSAndroid Build Coastguard Worker 		break;
479*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_EC:
480*1c60b9acSAndroid Build Coastguard Worker 		l = lexico_ec;
481*1c60b9acSAndroid Build Coastguard Worker 		limit = LWS_ARRAY_SIZE(lexico_ec);
482*1c60b9acSAndroid Build Coastguard Worker 		asym = 1;
483*1c60b9acSAndroid Build Coastguard Worker 		break;
484*1c60b9acSAndroid Build Coastguard Worker 	default:
485*1c60b9acSAndroid Build Coastguard Worker 		return -1;
486*1c60b9acSAndroid Build Coastguard Worker 	}
487*1c60b9acSAndroid Build Coastguard Worker 
488*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < limit; n++) {
489*1c60b9acSAndroid Build Coastguard Worker 		const char *q, *q_end;
490*1c60b9acSAndroid Build Coastguard Worker 		char tok[12];
491*1c60b9acSAndroid Build Coastguard Worker 		int pos = 0, f = 1;
492*1c60b9acSAndroid Build Coastguard Worker 
493*1c60b9acSAndroid Build Coastguard Worker 		if ((l->meta & 1) && (jwk->meta[l->idx].buf ||
494*1c60b9acSAndroid Build Coastguard Worker 				      l->idx == (int)JWK_META_KTY)) {
495*1c60b9acSAndroid Build Coastguard Worker 
496*1c60b9acSAndroid Build Coastguard Worker 			switch (l->idx) {
497*1c60b9acSAndroid Build Coastguard Worker 			case JWK_META_KTY:
498*1c60b9acSAndroid Build Coastguard Worker 				if (!first)
499*1c60b9acSAndroid Build Coastguard Worker 					*p++ = ',';
500*1c60b9acSAndroid Build Coastguard Worker 				first = 0;
501*1c60b9acSAndroid Build Coastguard Worker 				p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"%s\"",
502*1c60b9acSAndroid Build Coastguard Worker 						  l->name, kty_names[jwk->kty]);
503*1c60b9acSAndroid Build Coastguard Worker 				break;
504*1c60b9acSAndroid Build Coastguard Worker 			case JWK_META_KEY_OPS:
505*1c60b9acSAndroid Build Coastguard Worker 				if (!first)
506*1c60b9acSAndroid Build Coastguard Worker 					*p++ = ',';
507*1c60b9acSAndroid Build Coastguard Worker 				first = 0;
508*1c60b9acSAndroid Build Coastguard Worker 				q = (const char *)jwk->meta[l->idx].buf;
509*1c60b9acSAndroid Build Coastguard Worker 				q_end = q + jwk->meta[l->idx].len;
510*1c60b9acSAndroid Build Coastguard Worker 
511*1c60b9acSAndroid Build Coastguard Worker 				p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
512*1c60b9acSAndroid Build Coastguard Worker 						  "\"%s\":[", l->name);
513*1c60b9acSAndroid Build Coastguard Worker 				/*
514*1c60b9acSAndroid Build Coastguard Worker 				 * For the public version, usages that
515*1c60b9acSAndroid Build Coastguard Worker 				 * require the private part must be
516*1c60b9acSAndroid Build Coastguard Worker 				 * snipped
517*1c60b9acSAndroid Build Coastguard Worker 				 */
518*1c60b9acSAndroid Build Coastguard Worker 
519*1c60b9acSAndroid Build Coastguard Worker 				while (q < q_end) {
520*1c60b9acSAndroid Build Coastguard Worker 					if (*q != ' ' && pos < (int)sizeof(tok) - 1) {
521*1c60b9acSAndroid Build Coastguard Worker 						tok[pos++] = *q++;
522*1c60b9acSAndroid Build Coastguard Worker 						if (q != q_end)
523*1c60b9acSAndroid Build Coastguard Worker 							continue;
524*1c60b9acSAndroid Build Coastguard Worker 					}
525*1c60b9acSAndroid Build Coastguard Worker 					tok[pos] = '\0';
526*1c60b9acSAndroid Build Coastguard Worker 					pos = 0;
527*1c60b9acSAndroid Build Coastguard Worker 					if ((flags & LWSJWKF_EXPORT_PRIVATE) ||
528*1c60b9acSAndroid Build Coastguard Worker 					    !asym || (strcmp(tok, "sign") &&
529*1c60b9acSAndroid Build Coastguard Worker 						      strcmp(tok, "encrypt"))) {
530*1c60b9acSAndroid Build Coastguard Worker 						if (!f)
531*1c60b9acSAndroid Build Coastguard Worker 							*p++ = ',';
532*1c60b9acSAndroid Build Coastguard Worker 						f = 0;
533*1c60b9acSAndroid Build Coastguard Worker 						p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
534*1c60b9acSAndroid Build Coastguard Worker 							"\"%s\"", tok);
535*1c60b9acSAndroid Build Coastguard Worker 					}
536*1c60b9acSAndroid Build Coastguard Worker 					q++;
537*1c60b9acSAndroid Build Coastguard Worker 				}
538*1c60b9acSAndroid Build Coastguard Worker 
539*1c60b9acSAndroid Build Coastguard Worker 				*p++ = ']';
540*1c60b9acSAndroid Build Coastguard Worker 
541*1c60b9acSAndroid Build Coastguard Worker 				break;
542*1c60b9acSAndroid Build Coastguard Worker 
543*1c60b9acSAndroid Build Coastguard Worker 			default:
544*1c60b9acSAndroid Build Coastguard Worker 				/* both sig and enc require asym private key */
545*1c60b9acSAndroid Build Coastguard Worker 				if (!(flags & LWSJWKF_EXPORT_PRIVATE) &&
546*1c60b9acSAndroid Build Coastguard Worker 				    asym && l->idx == (int)JWK_META_USE)
547*1c60b9acSAndroid Build Coastguard Worker 					break;
548*1c60b9acSAndroid Build Coastguard Worker 				if (!first)
549*1c60b9acSAndroid Build Coastguard Worker 					*p++ = ',';
550*1c60b9acSAndroid Build Coastguard Worker 				first = 0;
551*1c60b9acSAndroid Build Coastguard Worker 				p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"",
552*1c60b9acSAndroid Build Coastguard Worker 						  l->name);
553*1c60b9acSAndroid Build Coastguard Worker 				lws_strnncpy(p, (const char *)jwk->meta[l->idx].buf,
554*1c60b9acSAndroid Build Coastguard Worker 					     jwk->meta[l->idx].len, end - p);
555*1c60b9acSAndroid Build Coastguard Worker 				p += strlen(p);
556*1c60b9acSAndroid Build Coastguard Worker 				p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"");
557*1c60b9acSAndroid Build Coastguard Worker 				break;
558*1c60b9acSAndroid Build Coastguard Worker 			}
559*1c60b9acSAndroid Build Coastguard Worker 		}
560*1c60b9acSAndroid Build Coastguard Worker 
561*1c60b9acSAndroid Build Coastguard Worker 		if ((!(l->meta & 1)) && jwk->e[l->idx].buf &&
562*1c60b9acSAndroid Build Coastguard Worker 		    ((flags & LWSJWKF_EXPORT_PRIVATE) || !(l->meta & 2))) {
563*1c60b9acSAndroid Build Coastguard Worker 			if (!first)
564*1c60b9acSAndroid Build Coastguard Worker 				*p++ = ',';
565*1c60b9acSAndroid Build Coastguard Worker 			first = 0;
566*1c60b9acSAndroid Build Coastguard Worker 
567*1c60b9acSAndroid Build Coastguard Worker 			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"%s\":\"", l->name);
568*1c60b9acSAndroid Build Coastguard Worker 
569*1c60b9acSAndroid Build Coastguard Worker 			if (jwk->kty == LWS_GENCRYPTO_KTY_EC &&
570*1c60b9acSAndroid Build Coastguard Worker 			    l->idx == (int)LWS_GENCRYPTO_EC_KEYEL_CRV) {
571*1c60b9acSAndroid Build Coastguard Worker 				lws_strnncpy(p,
572*1c60b9acSAndroid Build Coastguard Worker 					     (const char *)jwk->e[l->idx].buf,
573*1c60b9acSAndroid Build Coastguard Worker 					     jwk->e[l->idx].len, end - p);
574*1c60b9acSAndroid Build Coastguard Worker 				m = (int)strlen(p);
575*1c60b9acSAndroid Build Coastguard Worker 			} else
576*1c60b9acSAndroid Build Coastguard Worker 				m = lws_jws_base64_enc(
577*1c60b9acSAndroid Build Coastguard Worker 					(const char *)jwk->e[l->idx].buf,
578*1c60b9acSAndroid Build Coastguard Worker 					jwk->e[l->idx].len, p, lws_ptr_diff_size_t(end, p) - 4);
579*1c60b9acSAndroid Build Coastguard Worker 			if (m < 0) {
580*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: enc failed\n", __func__);
581*1c60b9acSAndroid Build Coastguard Worker 				return -1;
582*1c60b9acSAndroid Build Coastguard Worker 			}
583*1c60b9acSAndroid Build Coastguard Worker 			p += m;
584*1c60b9acSAndroid Build Coastguard Worker 			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"");
585*1c60b9acSAndroid Build Coastguard Worker 		}
586*1c60b9acSAndroid Build Coastguard Worker 
587*1c60b9acSAndroid Build Coastguard Worker 		l++;
588*1c60b9acSAndroid Build Coastguard Worker 	}
589*1c60b9acSAndroid Build Coastguard Worker 
590*1c60b9acSAndroid Build Coastguard Worker 	p += lws_snprintf(p, lws_ptr_diff_size_t(end, p),
591*1c60b9acSAndroid Build Coastguard Worker 			  (flags & LWSJWKF_EXPORT_NOCRLF) ? "}" : "}\n");
592*1c60b9acSAndroid Build Coastguard Worker 
593*1c60b9acSAndroid Build Coastguard Worker 	*len -= lws_ptr_diff(p, start);
594*1c60b9acSAndroid Build Coastguard Worker 
595*1c60b9acSAndroid Build Coastguard Worker 	return lws_ptr_diff(p, start);
596*1c60b9acSAndroid Build Coastguard Worker }
597*1c60b9acSAndroid Build Coastguard Worker 
598*1c60b9acSAndroid Build Coastguard Worker int
lws_jwk_load(struct lws_jwk * jwk,const char * filename,lws_jwk_key_import_callback cb,void * user)599*1c60b9acSAndroid Build Coastguard Worker lws_jwk_load(struct lws_jwk *jwk, const char *filename,
600*1c60b9acSAndroid Build Coastguard Worker 	     lws_jwk_key_import_callback cb, void *user)
601*1c60b9acSAndroid Build Coastguard Worker {
602*1c60b9acSAndroid Build Coastguard Worker 	unsigned int buflen = 4096;
603*1c60b9acSAndroid Build Coastguard Worker 	char *buf = lws_malloc(buflen, "jwk-load");
604*1c60b9acSAndroid Build Coastguard Worker 	int n;
605*1c60b9acSAndroid Build Coastguard Worker 
606*1c60b9acSAndroid Build Coastguard Worker 	if (!buf)
607*1c60b9acSAndroid Build Coastguard Worker 		return -1;
608*1c60b9acSAndroid Build Coastguard Worker 
609*1c60b9acSAndroid Build Coastguard Worker 	n = lws_plat_read_file(filename, buf, buflen);
610*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
611*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
612*1c60b9acSAndroid Build Coastguard Worker 
613*1c60b9acSAndroid Build Coastguard Worker 	n = lws_jwk_import(jwk, cb, user, buf, (unsigned int)n);
614*1c60b9acSAndroid Build Coastguard Worker 	lws_free(buf);
615*1c60b9acSAndroid Build Coastguard Worker 
616*1c60b9acSAndroid Build Coastguard Worker 	return n;
617*1c60b9acSAndroid Build Coastguard Worker bail:
618*1c60b9acSAndroid Build Coastguard Worker 	lws_free(buf);
619*1c60b9acSAndroid Build Coastguard Worker 
620*1c60b9acSAndroid Build Coastguard Worker 	return -1;
621*1c60b9acSAndroid Build Coastguard Worker }
622*1c60b9acSAndroid Build Coastguard Worker 
623*1c60b9acSAndroid Build Coastguard Worker int
lws_jwk_save(struct lws_jwk * jwk,const char * filename)624*1c60b9acSAndroid Build Coastguard Worker lws_jwk_save(struct lws_jwk *jwk, const char *filename)
625*1c60b9acSAndroid Build Coastguard Worker {
626*1c60b9acSAndroid Build Coastguard Worker 	int buflen = 4096;
627*1c60b9acSAndroid Build Coastguard Worker 	char *buf = lws_malloc((unsigned int)buflen, "jwk-save");
628*1c60b9acSAndroid Build Coastguard Worker 	int n, m;
629*1c60b9acSAndroid Build Coastguard Worker 
630*1c60b9acSAndroid Build Coastguard Worker 	if (!buf)
631*1c60b9acSAndroid Build Coastguard Worker 		return -1;
632*1c60b9acSAndroid Build Coastguard Worker 
633*1c60b9acSAndroid Build Coastguard Worker 	n = lws_jwk_export(jwk, LWSJWKF_EXPORT_PRIVATE, buf, &buflen);
634*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
635*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
636*1c60b9acSAndroid Build Coastguard Worker 
637*1c60b9acSAndroid Build Coastguard Worker 	m = lws_plat_write_file(filename, buf, (size_t)n);
638*1c60b9acSAndroid Build Coastguard Worker 
639*1c60b9acSAndroid Build Coastguard Worker 	lws_free(buf);
640*1c60b9acSAndroid Build Coastguard Worker 	if (m)
641*1c60b9acSAndroid Build Coastguard Worker 		return -1;
642*1c60b9acSAndroid Build Coastguard Worker 
643*1c60b9acSAndroid Build Coastguard Worker 	return 0;
644*1c60b9acSAndroid Build Coastguard Worker 
645*1c60b9acSAndroid Build Coastguard Worker bail:
646*1c60b9acSAndroid Build Coastguard Worker 	lws_free(buf);
647*1c60b9acSAndroid Build Coastguard Worker 
648*1c60b9acSAndroid Build Coastguard Worker 	return -1;
649*1c60b9acSAndroid Build Coastguard Worker }
650