xref: /aosp_15_r20/external/libwebsockets/lib/cose/cose_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  * cose_key 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 #define lwsl_cose lwsl_notice
31*1c60b9acSAndroid Build Coastguard Worker #define lwsl_hexdump_cose lwsl_hexdump_notice
32*1c60b9acSAndroid Build Coastguard Worker 
33*1c60b9acSAndroid Build Coastguard Worker // #define VERBOSE 1
34*1c60b9acSAndroid Build Coastguard Worker 
35*1c60b9acSAndroid Build Coastguard Worker struct lws_cose_key_parse_state {
36*1c60b9acSAndroid Build Coastguard Worker 	struct lws_cose_key		*ck;
37*1c60b9acSAndroid Build Coastguard Worker 	/**< single key created here if pkey_set is NULL */
38*1c60b9acSAndroid Build Coastguard Worker 	char				buf[(8192 / 8) + 1];
39*1c60b9acSAndroid Build Coastguard Worker 	/**< enough for 8Kb key, only needed during parse */
40*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_import_callback	per_key_cb;
41*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_owner_t		*pkey_set;
42*1c60b9acSAndroid Build Coastguard Worker 	/**< if non-NULL, expects a [ key set ], else single key */
43*1c60b9acSAndroid Build Coastguard Worker 	void				*user;
44*1c60b9acSAndroid Build Coastguard Worker 	size_t				pos;
45*1c60b9acSAndroid Build Coastguard Worker 	int				cose_state;
46*1c60b9acSAndroid Build Coastguard Worker 	cose_param_t			seen[16];
47*1c60b9acSAndroid Build Coastguard Worker 	int				seen_count;
48*1c60b9acSAndroid Build Coastguard Worker 	int				gencrypto_eidx;
49*1c60b9acSAndroid Build Coastguard Worker 	int				meta_idx;
50*1c60b9acSAndroid Build Coastguard Worker 	unsigned short			possible;
51*1c60b9acSAndroid Build Coastguard Worker };
52*1c60b9acSAndroid Build Coastguard Worker 
53*1c60b9acSAndroid Build Coastguard Worker /*
54*1c60b9acSAndroid Build Coastguard Worker  * A COSE key representation is a CBOR map with a specified structure.  The
55*1c60b9acSAndroid Build Coastguard Worker  * keys are
56*1c60b9acSAndroid Build Coastguard Worker  *
57*1c60b9acSAndroid Build Coastguard Worker  * 	LWSCOSE_WKK_KTY			MUST	  int / tstr
58*1c60b9acSAndroid Build Coastguard Worker  *	LWSCOSE_WKK_KID			OPT       bstr
59*1c60b9acSAndroid Build Coastguard Worker  *	LWSCOSE_WKK_ALG			OPT	  int / tstr
60*1c60b9acSAndroid Build Coastguard Worker  *	LWSCOSE_WKK_KEY_OPS		OPT	  [ + (int / tstr) ]
61*1c60b9acSAndroid Build Coastguard Worker  *	LWSCOSE_WKK_BASE_IV		OPT	  bstr
62*1c60b9acSAndroid Build Coastguard Worker  */
63*1c60b9acSAndroid Build Coastguard Worker 
64*1c60b9acSAndroid Build Coastguard Worker #if defined(_DEBUG)
65*1c60b9acSAndroid Build Coastguard Worker 
66*1c60b9acSAndroid Build Coastguard Worker static const char *meta_names[] = {
67*1c60b9acSAndroid Build Coastguard Worker 	"kty", "kid", "use", "key_ops", "base_iv", "alg"
68*1c60b9acSAndroid Build Coastguard Worker };
69*1c60b9acSAndroid Build Coastguard Worker 
70*1c60b9acSAndroid Build Coastguard Worker static const char *oct_names[] = {
71*1c60b9acSAndroid Build Coastguard Worker 	"k"
72*1c60b9acSAndroid Build Coastguard Worker };
73*1c60b9acSAndroid Build Coastguard Worker 
74*1c60b9acSAndroid Build Coastguard Worker static const char *rsa_names[] = {
75*1c60b9acSAndroid Build Coastguard Worker 	"e", "n", "d", "p", "q", "dp", "dq", "qi", "other", "ri", "di", "ti"
76*1c60b9acSAndroid Build Coastguard Worker };
77*1c60b9acSAndroid Build Coastguard Worker 
78*1c60b9acSAndroid Build Coastguard Worker static const char *ec_names[] = {
79*1c60b9acSAndroid Build Coastguard Worker 	"crv", "x", "d", "y",
80*1c60b9acSAndroid Build Coastguard Worker };
81*1c60b9acSAndroid Build Coastguard Worker 
82*1c60b9acSAndroid Build Coastguard Worker void
lws_cose_key_dump(const struct lws_cose_key * ck)83*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_dump(const struct lws_cose_key *ck)
84*1c60b9acSAndroid Build Coastguard Worker {
85*1c60b9acSAndroid Build Coastguard Worker 	const char **enames;
86*1c60b9acSAndroid Build Coastguard Worker 	char hex[2048];
87*1c60b9acSAndroid Build Coastguard Worker 	int elems;
88*1c60b9acSAndroid Build Coastguard Worker 	int n;
89*1c60b9acSAndroid Build Coastguard Worker 
90*1c60b9acSAndroid Build Coastguard Worker 	(void)enames;
91*1c60b9acSAndroid Build Coastguard Worker 	(void)meta_names;
92*1c60b9acSAndroid Build Coastguard Worker 
93*1c60b9acSAndroid Build Coastguard Worker 	switch (ck->gencrypto_kty) {
94*1c60b9acSAndroid Build Coastguard Worker 
95*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_OCT:
96*1c60b9acSAndroid Build Coastguard Worker 		elems = LWS_GENCRYPTO_OCT_KEYEL_COUNT;
97*1c60b9acSAndroid Build Coastguard Worker 		enames = oct_names;
98*1c60b9acSAndroid Build Coastguard Worker 		break;
99*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_RSA:
100*1c60b9acSAndroid Build Coastguard Worker 		elems = LWS_GENCRYPTO_RSA_KEYEL_COUNT;
101*1c60b9acSAndroid Build Coastguard Worker 		enames = rsa_names;
102*1c60b9acSAndroid Build Coastguard Worker 		break;
103*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_EC:
104*1c60b9acSAndroid Build Coastguard Worker 		elems = LWS_GENCRYPTO_EC_KEYEL_COUNT;
105*1c60b9acSAndroid Build Coastguard Worker 		enames = ec_names;
106*1c60b9acSAndroid Build Coastguard Worker 		break;
107*1c60b9acSAndroid Build Coastguard Worker 
108*1c60b9acSAndroid Build Coastguard Worker 	default:
109*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: jwk %p: unknown type\n", __func__, ck);
110*1c60b9acSAndroid Build Coastguard Worker 
111*1c60b9acSAndroid Build Coastguard Worker 		return;
112*1c60b9acSAndroid Build Coastguard Worker 	}
113*1c60b9acSAndroid Build Coastguard Worker 
114*1c60b9acSAndroid Build Coastguard Worker 	lwsl_cose("%s: cose_key %p, kty: %lld (gc %d)\n", __func__, ck,
115*1c60b9acSAndroid Build Coastguard Worker 			(long long)ck->kty, ck->gencrypto_kty);
116*1c60b9acSAndroid Build Coastguard Worker 
117*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < LWS_COUNT_COSE_KEY_ELEMENTS; n++) {
118*1c60b9acSAndroid Build Coastguard Worker 		if (ck->meta[n].buf) {
119*1c60b9acSAndroid Build Coastguard Worker 			lws_hex_from_byte_array(ck->meta[n].buf, ck->meta[n].len,
120*1c60b9acSAndroid Build Coastguard Worker 						hex, sizeof(hex));
121*1c60b9acSAndroid Build Coastguard Worker 			lwsl_cose("  meta: %s: %s\n", meta_names[n], hex);
122*1c60b9acSAndroid Build Coastguard Worker 		}
123*1c60b9acSAndroid Build Coastguard Worker 	}
124*1c60b9acSAndroid Build Coastguard Worker 
125*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < elems; n++) {
126*1c60b9acSAndroid Build Coastguard Worker 		if (ck->e[n].buf) {
127*1c60b9acSAndroid Build Coastguard Worker 			lws_hex_from_byte_array(ck->e[n].buf, ck->e[n].len,
128*1c60b9acSAndroid Build Coastguard Worker 						hex, sizeof(hex));
129*1c60b9acSAndroid Build Coastguard Worker 			lwsl_cose("  e: %s: %s\n", enames[n], hex);
130*1c60b9acSAndroid Build Coastguard Worker 		}
131*1c60b9acSAndroid Build Coastguard Worker 	}
132*1c60b9acSAndroid Build Coastguard Worker }
133*1c60b9acSAndroid Build Coastguard Worker #endif
134*1c60b9acSAndroid Build Coastguard Worker 
135*1c60b9acSAndroid Build Coastguard Worker static const char * const kty_strings[] = { NULL,
136*1c60b9acSAndroid Build Coastguard Worker 	"OKP", "EC2", "RSA", "SYMMETRIC", "HSS_LMS", "WALNUTDSA"
137*1c60b9acSAndroid Build Coastguard Worker };
138*1c60b9acSAndroid Build Coastguard Worker 
139*1c60b9acSAndroid Build Coastguard Worker int
lws_cose_key_checks(const lws_cose_key_t * key,int64_t kty,cose_param_t alg,int key_op,const char * crv)140*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_checks(const lws_cose_key_t *key, int64_t kty, cose_param_t alg,
141*1c60b9acSAndroid Build Coastguard Worker 		    int key_op, const char *crv)
142*1c60b9acSAndroid Build Coastguard Worker {
143*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_gencrypto_keyelem *ke;
144*1c60b9acSAndroid Build Coastguard Worker 
145*1c60b9acSAndroid Build Coastguard Worker 	/*
146*1c60b9acSAndroid Build Coastguard Worker 	 * we ourselves have to have a very clear idea what we need, even if
147*1c60b9acSAndroid Build Coastguard Worker 	 * matches are optional in the key itself
148*1c60b9acSAndroid Build Coastguard Worker 	 */
149*1c60b9acSAndroid Build Coastguard Worker 	assert(key);
150*1c60b9acSAndroid Build Coastguard Worker 	assert(kty);
151*1c60b9acSAndroid Build Coastguard Worker 	assert(alg);
152*1c60b9acSAndroid Build Coastguard Worker 	assert(key_op);
153*1c60b9acSAndroid Build Coastguard Worker 	assert((kty != LWSCOSE_WKKTV_OKP && kty != LWSCOSE_WKKTV_EC2) || crv);
154*1c60b9acSAndroid Build Coastguard Worker 
155*1c60b9acSAndroid Build Coastguard Worker 	/* RFC8152 8.1:
156*1c60b9acSAndroid Build Coastguard Worker 	 *
157*1c60b9acSAndroid Build Coastguard Worker 	 * The 'kty' field MUST be present, and it MUST be '...'.
158*1c60b9acSAndroid Build Coastguard Worker 	 *
159*1c60b9acSAndroid Build Coastguard Worker 	 * But kty can come as an int or a string, but we convert well-known
160*1c60b9acSAndroid Build Coastguard Worker 	 * kty ints to the corresponding string representation at key import
161*1c60b9acSAndroid Build Coastguard Worker 	 */
162*1c60b9acSAndroid Build Coastguard Worker 	if (!kty || kty >= (int)LWS_ARRAY_SIZE(kty_strings)) {
163*1c60b9acSAndroid Build Coastguard Worker 		/* we don't understand it */
164*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: unknown kty %d\n", __func__, (int)kty);
165*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
166*1c60b9acSAndroid Build Coastguard Worker 	}
167*1c60b9acSAndroid Build Coastguard Worker 
168*1c60b9acSAndroid Build Coastguard Worker 	ke = &key->meta[COSEKEY_META_KTY];
169*1c60b9acSAndroid Build Coastguard Worker 	if (ke->buf && (strlen(kty_strings[kty]) != ke->len ||
170*1c60b9acSAndroid Build Coastguard Worker 			memcmp(kty_strings[kty], ke->buf, ke->len))) {
171*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: key is of wrong kty\n", __func__);
172*1c60b9acSAndroid Build Coastguard Worker 		lwsl_hexdump_notice(ke->buf, ke->len);
173*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
174*1c60b9acSAndroid Build Coastguard Worker 	}
175*1c60b9acSAndroid Build Coastguard Worker 
176*1c60b9acSAndroid Build Coastguard Worker 	/* ...
177*1c60b9acSAndroid Build Coastguard Worker 	 * If the 'alg' field is present, it MUST match the ... signature
178*1c60b9acSAndroid Build Coastguard Worker 	 * algorithm being used.
179*1c60b9acSAndroid Build Coastguard Worker 	 *
180*1c60b9acSAndroid Build Coastguard Worker 	 * We attempt to convert key alg text representations to a well-known
181*1c60b9acSAndroid Build Coastguard Worker 	 * index, if we can't, then we don't know the alg anyway and should fail
182*1c60b9acSAndroid Build Coastguard Worker 	 * it
183*1c60b9acSAndroid Build Coastguard Worker 	 */
184*1c60b9acSAndroid Build Coastguard Worker 
185*1c60b9acSAndroid Build Coastguard Worker 	if (!key->cose_alg && key->meta[COSEKEY_META_ALG].buf) {
186*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: alg fail 1\n", __func__);
187*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
188*1c60b9acSAndroid Build Coastguard Worker 	}
189*1c60b9acSAndroid Build Coastguard Worker 
190*1c60b9acSAndroid Build Coastguard Worker 	if (key->cose_alg && /* accept it being absent altogether */
191*1c60b9acSAndroid Build Coastguard Worker 	    key->cose_alg != alg) {
192*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: alg fail 2\n", __func__);
193*1c60b9acSAndroid Build Coastguard Worker 
194*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
195*1c60b9acSAndroid Build Coastguard Worker 	}
196*1c60b9acSAndroid Build Coastguard Worker 
197*1c60b9acSAndroid Build Coastguard Worker 	/* ...
198*1c60b9acSAndroid Build Coastguard Worker 	 * If the 'key_ops' field is present, it MUST include 'sign' / 'verify'
199*1c60b9acSAndroid Build Coastguard Worker 	 * when creating /verifying an ... signature.
200*1c60b9acSAndroid Build Coastguard Worker 	 */
201*1c60b9acSAndroid Build Coastguard Worker 
202*1c60b9acSAndroid Build Coastguard Worker 	ke = &key->meta[COSEKEY_META_KEY_OPS];
203*1c60b9acSAndroid Build Coastguard Worker 	if (ke->buf && ke->len) {
204*1c60b9acSAndroid Build Coastguard Worker 		uint32_t n;
205*1c60b9acSAndroid Build Coastguard Worker 
206*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n < ke->len; n++)
207*1c60b9acSAndroid Build Coastguard Worker 			if (ke->buf[n] == key_op)
208*1c60b9acSAndroid Build Coastguard Worker 				break;
209*1c60b9acSAndroid Build Coastguard Worker 
210*1c60b9acSAndroid Build Coastguard Worker 		if (n == ke->len)
211*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
212*1c60b9acSAndroid Build Coastguard Worker 	}
213*1c60b9acSAndroid Build Coastguard Worker 
214*1c60b9acSAndroid Build Coastguard Worker 	/*
215*1c60b9acSAndroid Build Coastguard Worker 	 * If it's related to EC, check there is a curve associated with the
216*1c60b9acSAndroid Build Coastguard Worker 	 * key, and check it is what we expect
217*1c60b9acSAndroid Build Coastguard Worker 	 */
218*1c60b9acSAndroid Build Coastguard Worker 
219*1c60b9acSAndroid Build Coastguard Worker 	if (kty == LWSCOSE_WKKTV_OKP || kty == LWSCOSE_WKKTV_EC2) {
220*1c60b9acSAndroid Build Coastguard Worker 		ke = &key->e[LWS_GENCRYPTO_EC_KEYEL_CRV];
221*1c60b9acSAndroid Build Coastguard Worker 
222*1c60b9acSAndroid Build Coastguard Worker 		if (!ke->buf)
223*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
224*1c60b9acSAndroid Build Coastguard Worker 		if (ke->len != strlen(crv))
225*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
226*1c60b9acSAndroid Build Coastguard Worker 		if (memcmp(ke->buf, crv, ke->len))
227*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
228*1c60b9acSAndroid Build Coastguard Worker 	}
229*1c60b9acSAndroid Build Coastguard Worker 
230*1c60b9acSAndroid Build Coastguard Worker 	/* We're willing to use this key for this operation */
231*1c60b9acSAndroid Build Coastguard Worker 
232*1c60b9acSAndroid Build Coastguard Worker 	return 0;
233*1c60b9acSAndroid Build Coastguard Worker 
234*1c60b9acSAndroid Build Coastguard Worker bail:
235*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("%s: key rejected\n", __func__);
236*1c60b9acSAndroid Build Coastguard Worker 
237*1c60b9acSAndroid Build Coastguard Worker 	return 1;
238*1c60b9acSAndroid Build Coastguard Worker }
239*1c60b9acSAndroid Build Coastguard Worker 
240*1c60b9acSAndroid Build Coastguard Worker 
241*1c60b9acSAndroid Build Coastguard Worker static int
lws_ck_set_el(struct lws_gencrypto_keyelem * e,char * in,size_t len)242*1c60b9acSAndroid Build Coastguard Worker lws_ck_set_el(struct lws_gencrypto_keyelem *e, char *in, size_t len)
243*1c60b9acSAndroid Build Coastguard Worker {
244*1c60b9acSAndroid Build Coastguard Worker 	e->buf = lws_malloc(len + 1, "ck");
245*1c60b9acSAndroid Build Coastguard Worker 	if (!e->buf)
246*1c60b9acSAndroid Build Coastguard Worker 		return -1;
247*1c60b9acSAndroid Build Coastguard Worker 
248*1c60b9acSAndroid Build Coastguard Worker 	memcpy(e->buf, in, len);
249*1c60b9acSAndroid Build Coastguard Worker 	e->buf[len] = '\0';
250*1c60b9acSAndroid Build Coastguard Worker 	e->len = (uint32_t)len;
251*1c60b9acSAndroid Build Coastguard Worker 
252*1c60b9acSAndroid Build Coastguard Worker 	return 0;
253*1c60b9acSAndroid Build Coastguard Worker }
254*1c60b9acSAndroid Build Coastguard Worker 
255*1c60b9acSAndroid Build Coastguard Worker static struct {
256*1c60b9acSAndroid Build Coastguard Worker 	const char *curve;
257*1c60b9acSAndroid Build Coastguard Worker 	cose_param_t cose_id;
258*1c60b9acSAndroid Build Coastguard Worker } cose_curves[] = {
259*1c60b9acSAndroid Build Coastguard Worker 	{ "P-256",	LWSCOSE_WKEC_P256 },
260*1c60b9acSAndroid Build Coastguard Worker 	{ "P-384",	LWSCOSE_WKEC_P384 },
261*1c60b9acSAndroid Build Coastguard Worker 	{ "P-521",	LWSCOSE_WKEC_P521 },
262*1c60b9acSAndroid Build Coastguard Worker 	{ "X25519",	LWSCOSE_WKEC_X25519 },
263*1c60b9acSAndroid Build Coastguard Worker 	{ "X448",	LWSCOSE_WKEC_X448 },
264*1c60b9acSAndroid Build Coastguard Worker 	{ "ED25519",	LWSCOSE_WKEC_ED25519 },
265*1c60b9acSAndroid Build Coastguard Worker 	{ "ED448",	LWSCOSE_WKEC_ED448 },
266*1c60b9acSAndroid Build Coastguard Worker 	{ "SECP256K1",	LWSCOSE_WKEC_SECP256K1 },
267*1c60b9acSAndroid Build Coastguard Worker };
268*1c60b9acSAndroid Build Coastguard Worker 
269*1c60b9acSAndroid Build Coastguard Worker /* 0 means failed */
270*1c60b9acSAndroid Build Coastguard Worker 
271*1c60b9acSAndroid Build Coastguard Worker static cose_param_t
lws_cose_curve_name_to_id(const char * curve)272*1c60b9acSAndroid Build Coastguard Worker lws_cose_curve_name_to_id(const char *curve)
273*1c60b9acSAndroid Build Coastguard Worker {
274*1c60b9acSAndroid Build Coastguard Worker 	int n;
275*1c60b9acSAndroid Build Coastguard Worker 
276*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < (int)LWS_ARRAY_SIZE(cose_curves); n++)
277*1c60b9acSAndroid Build Coastguard Worker 		if (!strcmp(cose_curves[n].curve, curve))
278*1c60b9acSAndroid Build Coastguard Worker 			return cose_curves[n].cose_id;
279*1c60b9acSAndroid Build Coastguard Worker 
280*1c60b9acSAndroid Build Coastguard Worker 	return 0;
281*1c60b9acSAndroid Build Coastguard Worker }
282*1c60b9acSAndroid Build Coastguard Worker 
283*1c60b9acSAndroid Build Coastguard Worker static const char *
lws_cose_curve_id_to_name(cose_param_t id)284*1c60b9acSAndroid Build Coastguard Worker lws_cose_curve_id_to_name(cose_param_t id)
285*1c60b9acSAndroid Build Coastguard Worker {
286*1c60b9acSAndroid Build Coastguard Worker 	int n;
287*1c60b9acSAndroid Build Coastguard Worker 
288*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < (int)LWS_ARRAY_SIZE(cose_curves); n++)
289*1c60b9acSAndroid Build Coastguard Worker 		if (cose_curves[n].cose_id == id)
290*1c60b9acSAndroid Build Coastguard Worker 			return cose_curves[n].curve;
291*1c60b9acSAndroid Build Coastguard Worker 
292*1c60b9acSAndroid Build Coastguard Worker 	return 0;
293*1c60b9acSAndroid Build Coastguard Worker }
294*1c60b9acSAndroid Build Coastguard Worker 
295*1c60b9acSAndroid Build Coastguard Worker static const char * const wk_algs[] = {
296*1c60b9acSAndroid Build Coastguard Worker 	"ES256", "ES384", "ES512"
297*1c60b9acSAndroid Build Coastguard Worker };
298*1c60b9acSAndroid Build Coastguard Worker static signed char wk_alg_indexes[] = {
299*1c60b9acSAndroid Build Coastguard Worker 	LWSCOSE_WKAECDSA_ALG_ES256,
300*1c60b9acSAndroid Build Coastguard Worker 	LWSCOSE_WKAECDSA_ALG_ES384,
301*1c60b9acSAndroid Build Coastguard Worker 	LWSCOSE_WKAECDSA_ALG_ES512,
302*1c60b9acSAndroid Build Coastguard Worker };
303*1c60b9acSAndroid Build Coastguard Worker 
304*1c60b9acSAndroid Build Coastguard Worker static signed char
cb_cose_key(struct lecp_ctx * ctx,char reason)305*1c60b9acSAndroid Build Coastguard Worker cb_cose_key(struct lecp_ctx *ctx, char reason)
306*1c60b9acSAndroid Build Coastguard Worker {
307*1c60b9acSAndroid Build Coastguard Worker 	struct lws_cose_key_parse_state *cps =
308*1c60b9acSAndroid Build Coastguard Worker 			(struct lws_cose_key_parse_state *)ctx->user;
309*1c60b9acSAndroid Build Coastguard Worker 	struct lws_gencrypto_keyelem *ke = NULL;
310*1c60b9acSAndroid Build Coastguard Worker 	const char *p;
311*1c60b9acSAndroid Build Coastguard Worker 	int n;
312*1c60b9acSAndroid Build Coastguard Worker 
313*1c60b9acSAndroid Build Coastguard Worker #if defined(VERBOSE)
314*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("%s: reason %d, path %s, ord %u, ppos %d\n", __func__,
315*1c60b9acSAndroid Build Coastguard Worker 			reason & 0x3f,
316*1c60b9acSAndroid Build Coastguard Worker 			ctx->path, ctx->st[ctx->sp - 1].ordinal,
317*1c60b9acSAndroid Build Coastguard Worker 			ctx->pst[ctx->pst_sp].ppos);
318*1c60b9acSAndroid Build Coastguard Worker #endif
319*1c60b9acSAndroid Build Coastguard Worker 
320*1c60b9acSAndroid Build Coastguard Worker 	switch (reason) {
321*1c60b9acSAndroid Build Coastguard Worker 	case LECPCB_OBJECT_START:
322*1c60b9acSAndroid Build Coastguard Worker 		if (cps->ck)
323*1c60b9acSAndroid Build Coastguard Worker 			break;
324*1c60b9acSAndroid Build Coastguard Worker 		goto ak;
325*1c60b9acSAndroid Build Coastguard Worker 	case LECPCB_ARRAY_ITEM_START:
326*1c60b9acSAndroid Build Coastguard Worker 		if (cps->pkey_set && ctx->pst[ctx->pst_sp].ppos == 2) {
327*1c60b9acSAndroid Build Coastguard Worker 			ak:
328*1c60b9acSAndroid Build Coastguard Worker 			cps->ck = lws_zalloc(sizeof(*cps->ck), __func__);
329*1c60b9acSAndroid Build Coastguard Worker 			if (!cps->ck)
330*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
331*1c60b9acSAndroid Build Coastguard Worker 			cps->cose_state = 0;
332*1c60b9acSAndroid Build Coastguard Worker 			cps->meta_idx = -1;
333*1c60b9acSAndroid Build Coastguard Worker 			cps->gencrypto_eidx = -1;
334*1c60b9acSAndroid Build Coastguard Worker 			cps->seen_count = 0;
335*1c60b9acSAndroid Build Coastguard Worker 
336*1c60b9acSAndroid Build Coastguard Worker 			if (cps->pkey_set)
337*1c60b9acSAndroid Build Coastguard Worker 				lws_dll2_add_tail(&cps->ck->list, cps->pkey_set);
338*1c60b9acSAndroid Build Coastguard Worker 		}
339*1c60b9acSAndroid Build Coastguard Worker 		break;
340*1c60b9acSAndroid Build Coastguard Worker 	case LECPCB_ARRAY_ITEM_END:
341*1c60b9acSAndroid Build Coastguard Worker 		if (cps->pkey_set && ctx->pst[ctx->pst_sp].ppos == 2) {
342*1c60b9acSAndroid Build Coastguard Worker 			if (cps->per_key_cb)
343*1c60b9acSAndroid Build Coastguard Worker 				cps->per_key_cb(cps->ck, cps->user);
344*1c60b9acSAndroid Build Coastguard Worker 		}
345*1c60b9acSAndroid Build Coastguard Worker 		break;
346*1c60b9acSAndroid Build Coastguard Worker 	case LECPCB_TAG_START:
347*1c60b9acSAndroid Build Coastguard Worker 		if (ctx->item.u.u64 != LWSCOAP_CONTENTFORMAT_COSE_KEY) {
348*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("%s: unexpected tag\n", __func__);
349*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
350*1c60b9acSAndroid Build Coastguard Worker 		}
351*1c60b9acSAndroid Build Coastguard Worker 		break;
352*1c60b9acSAndroid Build Coastguard Worker 
353*1c60b9acSAndroid Build Coastguard Worker 	case LECPCB_VAL_NUM_INT:
354*1c60b9acSAndroid Build Coastguard Worker 	case LECPCB_VAL_NUM_UINT:
355*1c60b9acSAndroid Build Coastguard Worker 		if (!ctx->sp) {
356*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("%s: unexpected uint %d, ppos %d\n",
357*1c60b9acSAndroid Build Coastguard Worker 				  __func__, ctx->sp, ctx->pst[ctx->sp].ppos);
358*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
359*1c60b9acSAndroid Build Coastguard Worker 		}
360*1c60b9acSAndroid Build Coastguard Worker 
361*1c60b9acSAndroid Build Coastguard Worker 		if (!lecp_parse_map_is_key(ctx)) {
362*1c60b9acSAndroid Build Coastguard Worker 			const char *kty_str;
363*1c60b9acSAndroid Build Coastguard Worker 
364*1c60b9acSAndroid Build Coastguard Worker 			/* value part of map */
365*1c60b9acSAndroid Build Coastguard Worker 
366*1c60b9acSAndroid Build Coastguard Worker 			switch (cps->cose_state) {
367*1c60b9acSAndroid Build Coastguard Worker 			case LWSCOSE_WKK_KTY:
368*1c60b9acSAndroid Build Coastguard Worker 				assert(cps->ck);
369*1c60b9acSAndroid Build Coastguard Worker 				cps->ck->kty = (int)ctx->item.u.u64;
370*1c60b9acSAndroid Build Coastguard Worker 
371*1c60b9acSAndroid Build Coastguard Worker 				/* convert the cose key type to gencrypto one */
372*1c60b9acSAndroid Build Coastguard Worker 				switch (ctx->item.u.u64) {
373*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKTV_OKP:
374*1c60b9acSAndroid Build Coastguard Worker 					cps->ck->gencrypto_kty =
375*1c60b9acSAndroid Build Coastguard Worker 							LWS_GENCRYPTO_KTY_EC;
376*1c60b9acSAndroid Build Coastguard Worker 					kty_str = "OKP";
377*1c60b9acSAndroid Build Coastguard Worker 					break;
378*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKTV_EC2:
379*1c60b9acSAndroid Build Coastguard Worker 					kty_str = "EC2";
380*1c60b9acSAndroid Build Coastguard Worker 					cps->ck->gencrypto_kty =
381*1c60b9acSAndroid Build Coastguard Worker 							LWS_GENCRYPTO_KTY_EC;
382*1c60b9acSAndroid Build Coastguard Worker 					break;
383*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKTV_RSA:
384*1c60b9acSAndroid Build Coastguard Worker 					kty_str = "RSA";
385*1c60b9acSAndroid Build Coastguard Worker 					cps->ck->gencrypto_kty =
386*1c60b9acSAndroid Build Coastguard Worker 							LWS_GENCRYPTO_KTY_RSA;
387*1c60b9acSAndroid Build Coastguard Worker 					break;
388*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKTV_SYMMETRIC:
389*1c60b9acSAndroid Build Coastguard Worker 					kty_str = "SYMMETRIC";
390*1c60b9acSAndroid Build Coastguard Worker 					cps->ck->gencrypto_kty =
391*1c60b9acSAndroid Build Coastguard Worker 							LWS_GENCRYPTO_KTY_OCT;
392*1c60b9acSAndroid Build Coastguard Worker 					break;
393*1c60b9acSAndroid Build Coastguard Worker 				// case LWSCOSE_WKKTV_HSS_LMS:
394*1c60b9acSAndroid Build Coastguard Worker 				// case LWSCOSE_WKKTV_WALNUTDSA:
395*1c60b9acSAndroid Build Coastguard Worker 				default:
396*1c60b9acSAndroid Build Coastguard Worker 					lwsl_warn("%s: unknown kty\n", __func__);
397*1c60b9acSAndroid Build Coastguard Worker 					goto bail;
398*1c60b9acSAndroid Build Coastguard Worker 				}
399*1c60b9acSAndroid Build Coastguard Worker 
400*1c60b9acSAndroid Build Coastguard Worker 				/* store the string version of the key type */
401*1c60b9acSAndroid Build Coastguard Worker 
402*1c60b9acSAndroid Build Coastguard Worker 				ke = &cps->ck->meta[COSEKEY_META_KTY];
403*1c60b9acSAndroid Build Coastguard Worker 				ke->len = (uint32_t)strlen(kty_str);
404*1c60b9acSAndroid Build Coastguard Worker 				ke->buf = lws_malloc(ke->len + 1, __func__);
405*1c60b9acSAndroid Build Coastguard Worker 				if (!ke->buf)
406*1c60b9acSAndroid Build Coastguard Worker 					goto bail;
407*1c60b9acSAndroid Build Coastguard Worker 				memcpy(ke->buf, kty_str, ke->len + 1);
408*1c60b9acSAndroid Build Coastguard Worker 				break;
409*1c60b9acSAndroid Build Coastguard Worker 			case LWSCOSE_WKK_ALG:
410*1c60b9acSAndroid Build Coastguard Worker 				/*
411*1c60b9acSAndroid Build Coastguard Worker 				 * He can tie the key to a cose alg code
412*1c60b9acSAndroid Build Coastguard Worker 				 */
413*1c60b9acSAndroid Build Coastguard Worker 				cps->ck->cose_alg = (int)ctx->item.u.u64;
414*1c60b9acSAndroid Build Coastguard Worker 				break;
415*1c60b9acSAndroid Build Coastguard Worker 			case LWSCOSE_WKK_KEY_OPS:
416*1c60b9acSAndroid Build Coastguard Worker 				if (!cps->pkey_set &&
417*1c60b9acSAndroid Build Coastguard Worker 				    (ctx->pst[ctx->sp].ppos != 3 ||
418*1c60b9acSAndroid Build Coastguard Worker 				     strcmp(ctx->path, ".[]"))) {
419*1c60b9acSAndroid Build Coastguard Worker 					lwsl_warn("%s: unexpected kops\n",
420*1c60b9acSAndroid Build Coastguard Worker 								__func__);
421*1c60b9acSAndroid Build Coastguard Worker 					goto bail;
422*1c60b9acSAndroid Build Coastguard Worker 				}
423*1c60b9acSAndroid Build Coastguard Worker 				if (cps->pkey_set &&
424*1c60b9acSAndroid Build Coastguard Worker 				    (ctx->pst[ctx->sp].ppos != 5 ||
425*1c60b9acSAndroid Build Coastguard Worker 				     strcmp(ctx->path, "[].[]"))) {
426*1c60b9acSAndroid Build Coastguard Worker 					lwsl_warn("%s: unexpected kops\n",
427*1c60b9acSAndroid Build Coastguard Worker 								__func__);
428*1c60b9acSAndroid Build Coastguard Worker 					goto bail;
429*1c60b9acSAndroid Build Coastguard Worker 				}
430*1c60b9acSAndroid Build Coastguard Worker 				break;
431*1c60b9acSAndroid Build Coastguard Worker 			case LWSCOSE_WKOKP_CRV:
432*1c60b9acSAndroid Build Coastguard Worker 				cps->ck->cose_curve = (int)ctx->item.u.u64;
433*1c60b9acSAndroid Build Coastguard Worker 				p = lws_cose_curve_id_to_name(cps->ck->cose_curve);
434*1c60b9acSAndroid Build Coastguard Worker 				if (p) {
435*1c60b9acSAndroid Build Coastguard Worker 					ke = &cps->ck->e[LWS_GENCRYPTO_EC_KEYEL_CRV];
436*1c60b9acSAndroid Build Coastguard Worker 					ke->len = (uint32_t)strlen(p);
437*1c60b9acSAndroid Build Coastguard Worker 					ke->buf = lws_malloc(ke->len + 1, __func__);
438*1c60b9acSAndroid Build Coastguard Worker 					if (!ke->buf)
439*1c60b9acSAndroid Build Coastguard Worker 						goto bail;
440*1c60b9acSAndroid Build Coastguard Worker 					memcpy(ke->buf, p, ke->len);
441*1c60b9acSAndroid Build Coastguard Worker 					ke->buf[ke->len] = '\0';
442*1c60b9acSAndroid Build Coastguard Worker 				}
443*1c60b9acSAndroid Build Coastguard Worker 				break;
444*1c60b9acSAndroid Build Coastguard Worker 			default:
445*1c60b9acSAndroid Build Coastguard Worker 				lwsl_warn("%s: uint not allowed in state %d\n",
446*1c60b9acSAndroid Build Coastguard Worker 						__func__, cps->cose_state);
447*1c60b9acSAndroid Build Coastguard Worker 				/* int not allowed in this state */
448*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
449*1c60b9acSAndroid Build Coastguard Worker 			}
450*1c60b9acSAndroid Build Coastguard Worker 
451*1c60b9acSAndroid Build Coastguard Worker 			cps->cose_state = 0;
452*1c60b9acSAndroid Build Coastguard Worker 			break;
453*1c60b9acSAndroid Build Coastguard Worker 		}
454*1c60b9acSAndroid Build Coastguard Worker 
455*1c60b9acSAndroid Build Coastguard Worker 		/* key part of map pair */
456*1c60b9acSAndroid Build Coastguard Worker 
457*1c60b9acSAndroid Build Coastguard Worker 		/*
458*1c60b9acSAndroid Build Coastguard Worker 		 * Disallow any of these coming more than once
459*1c60b9acSAndroid Build Coastguard Worker 		 */
460*1c60b9acSAndroid Build Coastguard Worker 		cps->cose_state = (int)ctx->item.u.u64;
461*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0 ; n < cps->seen_count; n++)
462*1c60b9acSAndroid Build Coastguard Worker 			if (cps->seen[n] == cps->cose_state) {
463*1c60b9acSAndroid Build Coastguard Worker 				/* dupe */
464*1c60b9acSAndroid Build Coastguard Worker 				lwsl_warn("%s: duplicate map name %d\n",
465*1c60b9acSAndroid Build Coastguard Worker 						__func__, cps->cose_state);
466*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
467*1c60b9acSAndroid Build Coastguard Worker 			}
468*1c60b9acSAndroid Build Coastguard Worker 
469*1c60b9acSAndroid Build Coastguard Worker 		if (cps->seen_count >= (int)LWS_ARRAY_SIZE(cps->seen))
470*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
471*1c60b9acSAndroid Build Coastguard Worker 		cps->seen[cps->seen_count++] = cps->cose_state;
472*1c60b9acSAndroid Build Coastguard Worker 
473*1c60b9acSAndroid Build Coastguard Worker 		cps->meta_idx = -1;
474*1c60b9acSAndroid Build Coastguard Worker 		switch ((int)ctx->item.u.u64) {
475*1c60b9acSAndroid Build Coastguard Worker 		case LWSCOSE_WKK_KTY:
476*1c60b9acSAndroid Build Coastguard Worker 			cps->meta_idx = COSEKEY_META_KTY;
477*1c60b9acSAndroid Build Coastguard Worker 			break;
478*1c60b9acSAndroid Build Coastguard Worker 		case LWSCOSE_WKK_KID:
479*1c60b9acSAndroid Build Coastguard Worker 			cps->meta_idx = COSEKEY_META_KID;
480*1c60b9acSAndroid Build Coastguard Worker 			break;
481*1c60b9acSAndroid Build Coastguard Worker 		case LWSCOSE_WKK_ALG:
482*1c60b9acSAndroid Build Coastguard Worker 			cps->meta_idx = COSEKEY_META_ALG;
483*1c60b9acSAndroid Build Coastguard Worker 			break;
484*1c60b9acSAndroid Build Coastguard Worker 		case LWSCOSE_WKK_KEY_OPS:
485*1c60b9acSAndroid Build Coastguard Worker 			cps->meta_idx = COSEKEY_META_KEY_OPS;
486*1c60b9acSAndroid Build Coastguard Worker 			break;
487*1c60b9acSAndroid Build Coastguard Worker 		case LWSCOSE_WKK_BASE_IV:
488*1c60b9acSAndroid Build Coastguard Worker 			cps->meta_idx = COSEKEY_META_BASE_IV;
489*1c60b9acSAndroid Build Coastguard Worker 			break;
490*1c60b9acSAndroid Build Coastguard Worker 
491*1c60b9acSAndroid Build Coastguard Worker 		default:
492*1c60b9acSAndroid Build Coastguard Worker 			cps->gencrypto_eidx = -1;
493*1c60b9acSAndroid Build Coastguard Worker 
494*1c60b9acSAndroid Build Coastguard Worker 			switch (cps->ck->kty) {
495*1c60b9acSAndroid Build Coastguard Worker 			case LWSCOSE_WKKTV_OKP:
496*1c60b9acSAndroid Build Coastguard Worker 				switch ((int)ctx->item.u.u64) {
497*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKOKP_CRV:
498*1c60b9acSAndroid Build Coastguard Worker 					cps->cose_state = LWSCOSE_WKOKP_CRV;
499*1c60b9acSAndroid Build Coastguard Worker 					break;
500*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKOKP_X:
501*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
502*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_EC_KEYEL_X;
503*1c60b9acSAndroid Build Coastguard Worker 					break;
504*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKOKP_D:
505*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
506*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_EC_KEYEL_D;
507*1c60b9acSAndroid Build Coastguard Worker 					break;
508*1c60b9acSAndroid Build Coastguard Worker 				default:
509*1c60b9acSAndroid Build Coastguard Worker 					goto bail;
510*1c60b9acSAndroid Build Coastguard Worker 				}
511*1c60b9acSAndroid Build Coastguard Worker 				break;
512*1c60b9acSAndroid Build Coastguard Worker 			case LWSCOSE_WKKTV_EC2:
513*1c60b9acSAndroid Build Coastguard Worker 				switch ((int)ctx->item.u.u64) {
514*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKECKP_CRV:
515*1c60b9acSAndroid Build Coastguard Worker 					cps->cose_state = LWSCOSE_WKOKP_CRV;
516*1c60b9acSAndroid Build Coastguard Worker 					break;
517*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKECKP_X:
518*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
519*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_EC_KEYEL_X;
520*1c60b9acSAndroid Build Coastguard Worker 					break;
521*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKECKP_Y:
522*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
523*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_EC_KEYEL_Y;
524*1c60b9acSAndroid Build Coastguard Worker 					break;
525*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKECKP_D:
526*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
527*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_EC_KEYEL_D;
528*1c60b9acSAndroid Build Coastguard Worker 					break;
529*1c60b9acSAndroid Build Coastguard Worker 				default:
530*1c60b9acSAndroid Build Coastguard Worker 					goto bail;
531*1c60b9acSAndroid Build Coastguard Worker 				}
532*1c60b9acSAndroid Build Coastguard Worker 				break;
533*1c60b9acSAndroid Build Coastguard Worker 			case LWSCOSE_WKKTV_RSA:
534*1c60b9acSAndroid Build Coastguard Worker 				switch ((int)ctx->item.u.u64) {
535*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_N:
536*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
537*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_N;
538*1c60b9acSAndroid Build Coastguard Worker 					break;
539*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_E:
540*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
541*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_E;
542*1c60b9acSAndroid Build Coastguard Worker 					break;
543*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_D:
544*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
545*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_D;
546*1c60b9acSAndroid Build Coastguard Worker 					break;
547*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_P:
548*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
549*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_P;
550*1c60b9acSAndroid Build Coastguard Worker 					break;
551*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_Q:
552*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
553*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_Q;
554*1c60b9acSAndroid Build Coastguard Worker 					break;
555*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_DP:
556*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
557*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_DP;
558*1c60b9acSAndroid Build Coastguard Worker 					break;
559*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_DQ:
560*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
561*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_DQ;
562*1c60b9acSAndroid Build Coastguard Worker 					break;
563*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_QINV:
564*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
565*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_QI;
566*1c60b9acSAndroid Build Coastguard Worker 					break;
567*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_OTHER:
568*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
569*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_OTHER;
570*1c60b9acSAndroid Build Coastguard Worker 					break;
571*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_RI:
572*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
573*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_RI;
574*1c60b9acSAndroid Build Coastguard Worker 					break;
575*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_DI:
576*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
577*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_DI;
578*1c60b9acSAndroid Build Coastguard Worker 					break;
579*1c60b9acSAndroid Build Coastguard Worker 				case LWSCOSE_WKKPRSA_TI:
580*1c60b9acSAndroid Build Coastguard Worker 					cps->gencrypto_eidx =
581*1c60b9acSAndroid Build Coastguard Worker 						LWS_GENCRYPTO_RSA_KEYEL_TI;
582*1c60b9acSAndroid Build Coastguard Worker 					break;
583*1c60b9acSAndroid Build Coastguard Worker 				default:
584*1c60b9acSAndroid Build Coastguard Worker 					goto bail;
585*1c60b9acSAndroid Build Coastguard Worker 				}
586*1c60b9acSAndroid Build Coastguard Worker 				break;
587*1c60b9acSAndroid Build Coastguard Worker 			case LWSCOSE_WKKTV_SYMMETRIC:
588*1c60b9acSAndroid Build Coastguard Worker 				if (ctx->item.u.i64 != -1 &&
589*1c60b9acSAndroid Build Coastguard Worker 				    ctx->item.u.u64 != LWSCOSE_WKSYMKP_KEY_VALUE)
590*1c60b9acSAndroid Build Coastguard Worker 					goto bail;
591*1c60b9acSAndroid Build Coastguard Worker 
592*1c60b9acSAndroid Build Coastguard Worker 				cps->gencrypto_eidx = LWS_GENCRYPTO_OCT_KEYEL_K;
593*1c60b9acSAndroid Build Coastguard Worker 				break;
594*1c60b9acSAndroid Build Coastguard Worker 			default:
595*1c60b9acSAndroid Build Coastguard Worker 				lwsl_warn("%s: unknown kty\n", __func__);
596*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
597*1c60b9acSAndroid Build Coastguard Worker 			}
598*1c60b9acSAndroid Build Coastguard Worker 			break;
599*1c60b9acSAndroid Build Coastguard Worker 		}
600*1c60b9acSAndroid Build Coastguard Worker 		break;
601*1c60b9acSAndroid Build Coastguard Worker 
602*1c60b9acSAndroid Build Coastguard Worker 	case LECPCB_VAL_BLOB_START:
603*1c60b9acSAndroid Build Coastguard Worker 		if (!ctx->sp || !(ctx->st[ctx->sp - 1].ordinal & 1)) {
604*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("%s: unexpected blob\n", __func__);
605*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
606*1c60b9acSAndroid Build Coastguard Worker 		}
607*1c60b9acSAndroid Build Coastguard Worker 
608*1c60b9acSAndroid Build Coastguard Worker 		if (cps->cose_state == COSEKEY_META_KID)
609*1c60b9acSAndroid Build Coastguard Worker 			break;
610*1c60b9acSAndroid Build Coastguard Worker 
611*1c60b9acSAndroid Build Coastguard Worker 		/*
612*1c60b9acSAndroid Build Coastguard Worker 		 * Validate the association of the blob now, collect it into
613*1c60b9acSAndroid Build Coastguard Worker 		 * the temp buf in cps and then alloc and copy it into the
614*1c60b9acSAndroid Build Coastguard Worker 		 * related key element when it's at the end and the size known
615*1c60b9acSAndroid Build Coastguard Worker 		 */
616*1c60b9acSAndroid Build Coastguard Worker 
617*1c60b9acSAndroid Build Coastguard Worker 		cps->pos = 0;
618*1c60b9acSAndroid Build Coastguard Worker 		if (cps->gencrypto_eidx >= 0) {
619*1c60b9acSAndroid Build Coastguard Worker 			if (cps->ck->e[cps->gencrypto_eidx].buf) {
620*1c60b9acSAndroid Build Coastguard Worker 				lwsl_warn("%s: e[%d] set twice %d\n", __func__,
621*1c60b9acSAndroid Build Coastguard Worker 						cps->gencrypto_eidx,
622*1c60b9acSAndroid Build Coastguard Worker 						cps->ck->e[cps->gencrypto_eidx].len);
623*1c60b9acSAndroid Build Coastguard Worker 				/* key elements must only come at most once */
624*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
625*1c60b9acSAndroid Build Coastguard Worker 			}
626*1c60b9acSAndroid Build Coastguard Worker 			break;
627*1c60b9acSAndroid Build Coastguard Worker 		}
628*1c60b9acSAndroid Build Coastguard Worker 		if (cps->meta_idx >= 0)
629*1c60b9acSAndroid Build Coastguard Worker 			break;
630*1c60b9acSAndroid Build Coastguard Worker 
631*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
632*1c60b9acSAndroid Build Coastguard Worker 
633*1c60b9acSAndroid Build Coastguard Worker 	case LECPCB_VAL_BLOB_CHUNK:
634*1c60b9acSAndroid Build Coastguard Worker 	case LECPCB_VAL_BLOB_END:
635*1c60b9acSAndroid Build Coastguard Worker 		if (cps->pos + ctx->npos > sizeof(cps->buf)) {
636*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("%s: oversize blob\n", __func__);
637*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
638*1c60b9acSAndroid Build Coastguard Worker 		}
639*1c60b9acSAndroid Build Coastguard Worker 		memcpy(cps->buf + cps->pos, ctx->buf, ctx->npos);
640*1c60b9acSAndroid Build Coastguard Worker 		cps->pos += ctx->npos;
641*1c60b9acSAndroid Build Coastguard Worker 
642*1c60b9acSAndroid Build Coastguard Worker 		if (reason == LECPCB_VAL_BLOB_CHUNK)
643*1c60b9acSAndroid Build Coastguard Worker 			break;
644*1c60b9acSAndroid Build Coastguard Worker 
645*1c60b9acSAndroid Build Coastguard Worker 		/* we have the key element data, let's make the ck element */
646*1c60b9acSAndroid Build Coastguard Worker 		if (cps->gencrypto_eidx >= 0) {
647*1c60b9acSAndroid Build Coastguard Worker 
648*1c60b9acSAndroid Build Coastguard Worker 			if (cps->ck->e[cps->gencrypto_eidx].buf)
649*1c60b9acSAndroid Build Coastguard Worker 				break;
650*1c60b9acSAndroid Build Coastguard Worker 
651*1c60b9acSAndroid Build Coastguard Worker 			lws_ck_set_el(&cps->ck->e[cps->gencrypto_eidx],
652*1c60b9acSAndroid Build Coastguard Worker 					(char *)cps->buf, cps->pos);
653*1c60b9acSAndroid Build Coastguard Worker 			cps->gencrypto_eidx = -1;
654*1c60b9acSAndroid Build Coastguard Worker 			break;
655*1c60b9acSAndroid Build Coastguard Worker 		}
656*1c60b9acSAndroid Build Coastguard Worker 
657*1c60b9acSAndroid Build Coastguard Worker 
658*1c60b9acSAndroid Build Coastguard Worker 		if (cps->meta_idx >= 0) {
659*1c60b9acSAndroid Build Coastguard Worker 			lws_ck_set_el(&cps->ck->meta[cps->meta_idx],
660*1c60b9acSAndroid Build Coastguard Worker 					(char *)cps->buf, cps->pos);
661*1c60b9acSAndroid Build Coastguard Worker 			cps->meta_idx = -1;
662*1c60b9acSAndroid Build Coastguard Worker 		}
663*1c60b9acSAndroid Build Coastguard Worker 		cps->pos = 0;
664*1c60b9acSAndroid Build Coastguard Worker 		break;
665*1c60b9acSAndroid Build Coastguard Worker 	case LECPCB_VAL_STR_END:
666*1c60b9acSAndroid Build Coastguard Worker 		if (cps->cose_state == LWSCOSE_WKOKP_CRV) {
667*1c60b9acSAndroid Build Coastguard Worker 			cps->ck->cose_curve = lws_cose_curve_name_to_id(ctx->buf);
668*1c60b9acSAndroid Build Coastguard Worker 			ke = &cps->ck->e[LWS_GENCRYPTO_EC_KEYEL_CRV];
669*1c60b9acSAndroid Build Coastguard Worker 			ke->len = ctx->npos;
670*1c60b9acSAndroid Build Coastguard Worker 			ke->buf = lws_malloc(ctx->npos, __func__);
671*1c60b9acSAndroid Build Coastguard Worker 			if (!ke->buf)
672*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
673*1c60b9acSAndroid Build Coastguard Worker 			memcpy(ke->buf, ctx->buf, ctx->npos);
674*1c60b9acSAndroid Build Coastguard Worker 		}
675*1c60b9acSAndroid Build Coastguard Worker 
676*1c60b9acSAndroid Build Coastguard Worker 		if (!lecp_parse_map_is_key(ctx) &&
677*1c60b9acSAndroid Build Coastguard Worker 		    cps->cose_state == LWSCOSE_WKK_ALG) {
678*1c60b9acSAndroid Build Coastguard Worker 			size_t n;
679*1c60b9acSAndroid Build Coastguard Worker 
680*1c60b9acSAndroid Build Coastguard Worker 			for (n = 0; n < LWS_ARRAY_SIZE(wk_algs); n++)
681*1c60b9acSAndroid Build Coastguard Worker 				if (ctx->npos == strlen(wk_algs[n]) &&
682*1c60b9acSAndroid Build Coastguard Worker 				    !memcmp(ctx->buf, wk_algs[n], ctx->npos)) {
683*1c60b9acSAndroid Build Coastguard Worker 					cps->ck->cose_alg = wk_alg_indexes[n];
684*1c60b9acSAndroid Build Coastguard Worker 					break;
685*1c60b9acSAndroid Build Coastguard Worker 				}
686*1c60b9acSAndroid Build Coastguard Worker 
687*1c60b9acSAndroid Build Coastguard Worker 			if (n == LWS_ARRAY_SIZE(wk_algs))
688*1c60b9acSAndroid Build Coastguard Worker 				/* key is for an alg we don't understand */
689*1c60b9acSAndroid Build Coastguard Worker 				lwsl_warn("%s: key for unknown alg %.*s\n",
690*1c60b9acSAndroid Build Coastguard Worker 					  __func__, (int)ctx->npos, ctx->buf);
691*1c60b9acSAndroid Build Coastguard Worker 
692*1c60b9acSAndroid Build Coastguard Worker 			ke = &cps->ck->meta[COSEKEY_META_ALG];
693*1c60b9acSAndroid Build Coastguard Worker 			ke->len = ctx->npos;
694*1c60b9acSAndroid Build Coastguard Worker 			ke->buf = lws_malloc(ctx->npos, __func__);
695*1c60b9acSAndroid Build Coastguard Worker 			if (!ke->buf)
696*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
697*1c60b9acSAndroid Build Coastguard Worker 			memcpy(ke->buf, ctx->buf, ctx->npos);
698*1c60b9acSAndroid Build Coastguard Worker 		}
699*1c60b9acSAndroid Build Coastguard Worker 
700*1c60b9acSAndroid Build Coastguard Worker 		break;
701*1c60b9acSAndroid Build Coastguard Worker 	}
702*1c60b9acSAndroid Build Coastguard Worker 
703*1c60b9acSAndroid Build Coastguard Worker 	return 0;
704*1c60b9acSAndroid Build Coastguard Worker 
705*1c60b9acSAndroid Build Coastguard Worker bail:
706*1c60b9acSAndroid Build Coastguard Worker 	lwsl_warn("%s: bail\n", __func__);
707*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_destroy(&cps->ck);
708*1c60b9acSAndroid Build Coastguard Worker 
709*1c60b9acSAndroid Build Coastguard Worker 	if (cps->pkey_set) {
710*1c60b9acSAndroid Build Coastguard Worker 		lws_cose_key_set_destroy(cps->pkey_set);
711*1c60b9acSAndroid Build Coastguard Worker 		cps->pkey_set = NULL;
712*1c60b9acSAndroid Build Coastguard Worker 	}
713*1c60b9acSAndroid Build Coastguard Worker 
714*1c60b9acSAndroid Build Coastguard Worker 	return -1;
715*1c60b9acSAndroid Build Coastguard Worker }
716*1c60b9acSAndroid Build Coastguard Worker 
717*1c60b9acSAndroid Build Coastguard Worker void
lws_cose_key_destroy_elements(struct lws_gencrypto_keyelem * el,int m)718*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_destroy_elements(struct lws_gencrypto_keyelem *el, int m)
719*1c60b9acSAndroid Build Coastguard Worker {
720*1c60b9acSAndroid Build Coastguard Worker 	int n;
721*1c60b9acSAndroid Build Coastguard Worker 
722*1c60b9acSAndroid Build Coastguard Worker 	if (!el)
723*1c60b9acSAndroid Build Coastguard Worker 		return;
724*1c60b9acSAndroid Build Coastguard Worker 
725*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < m; n++)
726*1c60b9acSAndroid Build Coastguard Worker 		if (el[n].buf) {
727*1c60b9acSAndroid Build Coastguard Worker 			/* wipe all key material when it goes out of scope */
728*1c60b9acSAndroid Build Coastguard Worker 			lws_explicit_bzero(el[n].buf, el[n].len);
729*1c60b9acSAndroid Build Coastguard Worker 			lws_free_set_NULL(el[n].buf);
730*1c60b9acSAndroid Build Coastguard Worker 			el[n].len = 0;
731*1c60b9acSAndroid Build Coastguard Worker 		}
732*1c60b9acSAndroid Build Coastguard Worker }
733*1c60b9acSAndroid Build Coastguard Worker 
734*1c60b9acSAndroid Build Coastguard Worker void
lws_cose_key_destroy(struct lws_cose_key ** pck)735*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_destroy(struct lws_cose_key **pck)
736*1c60b9acSAndroid Build Coastguard Worker {
737*1c60b9acSAndroid Build Coastguard Worker 	struct lws_cose_key *ck = *pck;
738*1c60b9acSAndroid Build Coastguard Worker 
739*1c60b9acSAndroid Build Coastguard Worker 	if (!ck)
740*1c60b9acSAndroid Build Coastguard Worker 		return;
741*1c60b9acSAndroid Build Coastguard Worker 
742*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_remove(&ck->list);
743*1c60b9acSAndroid Build Coastguard Worker 
744*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_destroy_elements(ck->e, LWS_ARRAY_SIZE(ck->e));
745*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_destroy_elements(ck->meta, LWS_ARRAY_SIZE(ck->meta));
746*1c60b9acSAndroid Build Coastguard Worker 
747*1c60b9acSAndroid Build Coastguard Worker 	lws_free_set_NULL(*pck);
748*1c60b9acSAndroid Build Coastguard Worker }
749*1c60b9acSAndroid Build Coastguard Worker 
750*1c60b9acSAndroid Build Coastguard Worker static int
lws_cose_key_set_memb_remove(struct lws_dll2 * d,void * user)751*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_set_memb_remove(struct lws_dll2 *d, void *user)
752*1c60b9acSAndroid Build Coastguard Worker {
753*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_t *ck = lws_container_of(d, lws_cose_key_t, list);
754*1c60b9acSAndroid Build Coastguard Worker 
755*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_remove(d);
756*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_destroy(&ck);
757*1c60b9acSAndroid Build Coastguard Worker 
758*1c60b9acSAndroid Build Coastguard Worker 	return 0;
759*1c60b9acSAndroid Build Coastguard Worker }
760*1c60b9acSAndroid Build Coastguard Worker 
761*1c60b9acSAndroid Build Coastguard Worker void
lws_cose_key_set_destroy(lws_dll2_owner_t * o)762*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_set_destroy(lws_dll2_owner_t *o)
763*1c60b9acSAndroid Build Coastguard Worker {
764*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_foreach_safe(o, NULL, lws_cose_key_set_memb_remove);
765*1c60b9acSAndroid Build Coastguard Worker }
766*1c60b9acSAndroid Build Coastguard Worker 
767*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_t *
lws_cose_key_from_set(lws_dll2_owner_t * set,const uint8_t * kid,size_t kl)768*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_from_set(lws_dll2_owner_t *set, const uint8_t *kid, size_t kl)
769*1c60b9acSAndroid Build Coastguard Worker {
770*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head(set)) {
771*1c60b9acSAndroid Build Coastguard Worker 		lws_cose_key_t *ck = lws_container_of(p, lws_cose_key_t, list);
772*1c60b9acSAndroid Build Coastguard Worker 		struct lws_gencrypto_keyelem *ke = &ck->meta[COSEKEY_META_KID];
773*1c60b9acSAndroid Build Coastguard Worker 
774*1c60b9acSAndroid Build Coastguard Worker 		if (!kid) /* always the first then */
775*1c60b9acSAndroid Build Coastguard Worker 			return ck;
776*1c60b9acSAndroid Build Coastguard Worker 
777*1c60b9acSAndroid Build Coastguard Worker 		if (ke->buf && ke->len == (uint32_t)kl &&
778*1c60b9acSAndroid Build Coastguard Worker 		    !memcmp(ke->buf, kid, ke->len))
779*1c60b9acSAndroid Build Coastguard Worker 			return ck;
780*1c60b9acSAndroid Build Coastguard Worker 
781*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll(p);
782*1c60b9acSAndroid Build Coastguard Worker 
783*1c60b9acSAndroid Build Coastguard Worker 	return NULL;
784*1c60b9acSAndroid Build Coastguard Worker }
785*1c60b9acSAndroid Build Coastguard Worker 
786*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_t *
lws_cose_key_generate(struct lws_context * context,cose_param_t cose_kty,int use_mask,int bits,const char * curve,const uint8_t * kid,size_t kl)787*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_generate(struct lws_context *context, cose_param_t cose_kty,
788*1c60b9acSAndroid Build Coastguard Worker 		      int use_mask, int bits, const char *curve,
789*1c60b9acSAndroid Build Coastguard Worker 		      const uint8_t *kid, size_t kl)
790*1c60b9acSAndroid Build Coastguard Worker {
791*1c60b9acSAndroid Build Coastguard Worker 	struct lws_gencrypto_keyelem *ke;
792*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_t *ck;
793*1c60b9acSAndroid Build Coastguard Worker 	size_t sn;
794*1c60b9acSAndroid Build Coastguard Worker 	int n;
795*1c60b9acSAndroid Build Coastguard Worker 
796*1c60b9acSAndroid Build Coastguard Worker 	ck = lws_zalloc(sizeof(*ck), __func__);
797*1c60b9acSAndroid Build Coastguard Worker 	if (!ck)
798*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
799*1c60b9acSAndroid Build Coastguard Worker 
800*1c60b9acSAndroid Build Coastguard Worker 	ck->kty = cose_kty;
801*1c60b9acSAndroid Build Coastguard Worker 	ck->private_key = 1;
802*1c60b9acSAndroid Build Coastguard Worker 
803*1c60b9acSAndroid Build Coastguard Worker 	if (use_mask & 0xfffe) {
804*1c60b9acSAndroid Build Coastguard Worker 		int count = 0;
805*1c60b9acSAndroid Build Coastguard Worker 
806*1c60b9acSAndroid Build Coastguard Worker 		for (n = 1; n < 15; n++)
807*1c60b9acSAndroid Build Coastguard Worker 			if (use_mask & (1 << n))
808*1c60b9acSAndroid Build Coastguard Worker 				count++;
809*1c60b9acSAndroid Build Coastguard Worker 		ke = &ck->meta[COSEKEY_META_KEY_OPS];
810*1c60b9acSAndroid Build Coastguard Worker 		ke->buf = lws_malloc((size_t)count, __func__);
811*1c60b9acSAndroid Build Coastguard Worker 		if (!ke->buf)
812*1c60b9acSAndroid Build Coastguard Worker 			goto fail;
813*1c60b9acSAndroid Build Coastguard Worker 		ke->len = (uint32_t)count;
814*1c60b9acSAndroid Build Coastguard Worker 		count = 0;
815*1c60b9acSAndroid Build Coastguard Worker 		for (n = 1; n < 15; n++)
816*1c60b9acSAndroid Build Coastguard Worker 			if (use_mask & (1 << n))
817*1c60b9acSAndroid Build Coastguard Worker 				ke->buf[count++] = (uint8_t)n;
818*1c60b9acSAndroid Build Coastguard Worker 	}
819*1c60b9acSAndroid Build Coastguard Worker 
820*1c60b9acSAndroid Build Coastguard Worker 	if (kid) {
821*1c60b9acSAndroid Build Coastguard Worker 		ke = &ck->meta[COSEKEY_META_KID];
822*1c60b9acSAndroid Build Coastguard Worker 		ke->buf = lws_malloc(kl, __func__);
823*1c60b9acSAndroid Build Coastguard Worker 		ke->len = (uint32_t)kl;
824*1c60b9acSAndroid Build Coastguard Worker 		memcpy(ke->buf, kid, ke->len);
825*1c60b9acSAndroid Build Coastguard Worker 	}
826*1c60b9acSAndroid Build Coastguard Worker 
827*1c60b9acSAndroid Build Coastguard Worker 	switch (cose_kty) {
828*1c60b9acSAndroid Build Coastguard Worker 	case LWSCOSE_WKKTV_RSA:
829*1c60b9acSAndroid Build Coastguard Worker 		{
830*1c60b9acSAndroid Build Coastguard Worker 			struct lws_genrsa_ctx ctx;
831*1c60b9acSAndroid Build Coastguard Worker 
832*1c60b9acSAndroid Build Coastguard Worker 			memset(&ctx, 0, sizeof(ctx));
833*1c60b9acSAndroid Build Coastguard Worker 			ck->gencrypto_kty = LWS_GENCRYPTO_KTY_RSA;
834*1c60b9acSAndroid Build Coastguard Worker 
835*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: generating %d bit RSA key\n",
836*1c60b9acSAndroid Build Coastguard Worker 					__func__, bits);
837*1c60b9acSAndroid Build Coastguard Worker 			n = lws_genrsa_new_keypair(context, &ctx,
838*1c60b9acSAndroid Build Coastguard Worker 						   LGRSAM_PKCS1_1_5,
839*1c60b9acSAndroid Build Coastguard Worker 						   ck->e, bits);
840*1c60b9acSAndroid Build Coastguard Worker 			lws_genrsa_destroy(&ctx);
841*1c60b9acSAndroid Build Coastguard Worker 			if (n) {
842*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: problem generating RSA key\n",
843*1c60b9acSAndroid Build Coastguard Worker 						__func__);
844*1c60b9acSAndroid Build Coastguard Worker 				goto fail;
845*1c60b9acSAndroid Build Coastguard Worker 			}
846*1c60b9acSAndroid Build Coastguard Worker 		}
847*1c60b9acSAndroid Build Coastguard Worker 		break;
848*1c60b9acSAndroid Build Coastguard Worker 	case LWSCOSE_WKKTV_SYMMETRIC:
849*1c60b9acSAndroid Build Coastguard Worker 
850*1c60b9acSAndroid Build Coastguard Worker 		ck->gencrypto_kty = LWS_GENCRYPTO_KTY_OCT;
851*1c60b9acSAndroid Build Coastguard Worker 		sn = (unsigned int)lws_gencrypto_bits_to_bytes(bits);
852*1c60b9acSAndroid Build Coastguard Worker 		ke = &ck->e[LWS_GENCRYPTO_OCT_KEYEL_K];
853*1c60b9acSAndroid Build Coastguard Worker 		ke->buf = lws_malloc(sn, "oct");
854*1c60b9acSAndroid Build Coastguard Worker 		if (!ke->buf)
855*1c60b9acSAndroid Build Coastguard Worker 			goto fail;
856*1c60b9acSAndroid Build Coastguard Worker 		ke->len = (uint32_t)sn;
857*1c60b9acSAndroid Build Coastguard Worker 		if (lws_get_random(context, ke->buf, sn) != sn) {
858*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: problem getting random\n", __func__);
859*1c60b9acSAndroid Build Coastguard Worker 			goto fail;
860*1c60b9acSAndroid Build Coastguard Worker 		}
861*1c60b9acSAndroid Build Coastguard Worker 		break;
862*1c60b9acSAndroid Build Coastguard Worker 
863*1c60b9acSAndroid Build Coastguard Worker 	case LWSCOSE_WKKTV_OKP:
864*1c60b9acSAndroid Build Coastguard Worker 	case LWSCOSE_WKKTV_EC2:
865*1c60b9acSAndroid Build Coastguard Worker 	{
866*1c60b9acSAndroid Build Coastguard Worker 		struct lws_genec_ctx ctx;
867*1c60b9acSAndroid Build Coastguard Worker 
868*1c60b9acSAndroid Build Coastguard Worker 		ck->gencrypto_kty = LWS_GENCRYPTO_KTY_EC;
869*1c60b9acSAndroid Build Coastguard Worker 
870*1c60b9acSAndroid Build Coastguard Worker 		if (!curve) {
871*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: must have a named curve\n", __func__);
872*1c60b9acSAndroid Build Coastguard Worker 
873*1c60b9acSAndroid Build Coastguard Worker 			goto fail;
874*1c60b9acSAndroid Build Coastguard Worker 		}
875*1c60b9acSAndroid Build Coastguard Worker 
876*1c60b9acSAndroid Build Coastguard Worker 		if (lws_genecdsa_create(&ctx, context, NULL))
877*1c60b9acSAndroid Build Coastguard Worker 			goto fail;
878*1c60b9acSAndroid Build Coastguard Worker 
879*1c60b9acSAndroid Build Coastguard Worker 		ctx.genec_alg = LEGENEC_ECDSA;
880*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: generating ECDSA key on curve %s\n", __func__,
881*1c60b9acSAndroid Build Coastguard Worker 				curve);
882*1c60b9acSAndroid Build Coastguard Worker 
883*1c60b9acSAndroid Build Coastguard Worker 		n = lws_genecdsa_new_keypair(&ctx, curve, ck->e);
884*1c60b9acSAndroid Build Coastguard Worker 		lws_genec_destroy(&ctx);
885*1c60b9acSAndroid Build Coastguard Worker 		if (n) {
886*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: problem generating ECDSA key\n", __func__);
887*1c60b9acSAndroid Build Coastguard Worker 			goto fail;
888*1c60b9acSAndroid Build Coastguard Worker 		}
889*1c60b9acSAndroid Build Coastguard Worker 		/* trim the trailing NUL */
890*1c60b9acSAndroid Build Coastguard Worker 		ck->e[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve);
891*1c60b9acSAndroid Build Coastguard Worker 	}
892*1c60b9acSAndroid Build Coastguard Worker 		break;
893*1c60b9acSAndroid Build Coastguard Worker 
894*1c60b9acSAndroid Build Coastguard Worker 	default:
895*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: unknown kty\n", __func__);
896*1c60b9acSAndroid Build Coastguard Worker 		goto fail;
897*1c60b9acSAndroid Build Coastguard Worker 	}
898*1c60b9acSAndroid Build Coastguard Worker 
899*1c60b9acSAndroid Build Coastguard Worker 	return ck;
900*1c60b9acSAndroid Build Coastguard Worker 
901*1c60b9acSAndroid Build Coastguard Worker fail:
902*1c60b9acSAndroid Build Coastguard Worker 	lws_free_set_NULL(ck);
903*1c60b9acSAndroid Build Coastguard Worker 
904*1c60b9acSAndroid Build Coastguard Worker 	return NULL;
905*1c60b9acSAndroid Build Coastguard Worker }
906*1c60b9acSAndroid Build Coastguard Worker 
907*1c60b9acSAndroid Build Coastguard Worker struct lws_cose_key *
lws_cose_key_import(lws_dll2_owner_t * pkey_set,lws_cose_key_import_callback cb,void * user,const uint8_t * in,size_t len)908*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_import(lws_dll2_owner_t *pkey_set, lws_cose_key_import_callback cb,
909*1c60b9acSAndroid Build Coastguard Worker 		    void *user, const uint8_t *in, size_t len)
910*1c60b9acSAndroid Build Coastguard Worker {
911*1c60b9acSAndroid Build Coastguard Worker 	struct lws_cose_key_parse_state cps;
912*1c60b9acSAndroid Build Coastguard Worker 	struct lecp_ctx ctx;
913*1c60b9acSAndroid Build Coastguard Worker 	int m;
914*1c60b9acSAndroid Build Coastguard Worker 
915*1c60b9acSAndroid Build Coastguard Worker 	memset(&cps, 0, sizeof(cps));
916*1c60b9acSAndroid Build Coastguard Worker 
917*1c60b9acSAndroid Build Coastguard Worker 	cps.per_key_cb		= cb;
918*1c60b9acSAndroid Build Coastguard Worker 	cps.user		= user;
919*1c60b9acSAndroid Build Coastguard Worker 	cps.pkey_set		= pkey_set;
920*1c60b9acSAndroid Build Coastguard Worker 	cps.gencrypto_eidx	= -1;
921*1c60b9acSAndroid Build Coastguard Worker 
922*1c60b9acSAndroid Build Coastguard Worker 	lecp_construct(&ctx, cb_cose_key, &cps, NULL, 0);
923*1c60b9acSAndroid Build Coastguard Worker 	m = lecp_parse(&ctx, in, len);
924*1c60b9acSAndroid Build Coastguard Worker 	lecp_destruct(&ctx);
925*1c60b9acSAndroid Build Coastguard Worker 
926*1c60b9acSAndroid Build Coastguard Worker 	if (m < 0) {
927*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: parse got %d\n", __func__, m);
928*1c60b9acSAndroid Build Coastguard Worker 		if (cps.pkey_set)
929*1c60b9acSAndroid Build Coastguard Worker 			lws_cose_key_set_destroy(cps.pkey_set);
930*1c60b9acSAndroid Build Coastguard Worker 
931*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
932*1c60b9acSAndroid Build Coastguard Worker 	}
933*1c60b9acSAndroid Build Coastguard Worker 
934*1c60b9acSAndroid Build Coastguard Worker 	switch (cps.ck->gencrypto_kty) {
935*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GENCRYPTO_KTY_UNKNOWN:
936*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: missing or unknown ktys\n", __func__);
937*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
938*1c60b9acSAndroid Build Coastguard Worker 	default:
939*1c60b9acSAndroid Build Coastguard Worker 		break;
940*1c60b9acSAndroid Build Coastguard Worker 	}
941*1c60b9acSAndroid Build Coastguard Worker 
942*1c60b9acSAndroid Build Coastguard Worker 	return cps.ck;
943*1c60b9acSAndroid Build Coastguard Worker 
944*1c60b9acSAndroid Build Coastguard Worker bail:
945*1c60b9acSAndroid Build Coastguard Worker 	lws_cose_key_destroy(&cps.ck);
946*1c60b9acSAndroid Build Coastguard Worker 	return NULL;
947*1c60b9acSAndroid Build Coastguard Worker }
948*1c60b9acSAndroid Build Coastguard Worker 
949*1c60b9acSAndroid Build Coastguard Worker /* gencrypto element orering -> cose key parameters */
950*1c60b9acSAndroid Build Coastguard Worker 
951*1c60b9acSAndroid Build Coastguard Worker static const signed char ckp[3][12] = {
952*1c60b9acSAndroid Build Coastguard Worker 	{ /* LWS_GENCRYPTO_KTY_OCT (1) */
953*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_OCT_KEYEL_K */ LWSCOSE_WKSYMKP_KEY_VALUE,
954*1c60b9acSAndroid Build Coastguard Worker 	},
955*1c60b9acSAndroid Build Coastguard Worker 	{ /* LWS_GENCRYPTO_KTY_RSA (2) */
956*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_E */       LWSCOSE_WKKPRSA_E,
957*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_N */       LWSCOSE_WKKPRSA_N,
958*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_D */       LWSCOSE_WKKPRSA_D,
959*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_P */       LWSCOSE_WKKPRSA_P,
960*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_Q */       LWSCOSE_WKKPRSA_Q,
961*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_DP */      LWSCOSE_WKKPRSA_DP,
962*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_DQ */      LWSCOSE_WKKPRSA_DQ,
963*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_QT */      LWSCOSE_WKKPRSA_QINV,
964*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_OTHER */   LWSCOSE_WKKPRSA_OTHER,
965*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_RI */      LWSCOSE_WKKPRSA_RI,
966*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_DI */      LWSCOSE_WKKPRSA_DI,
967*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_RSA_KEYEL_TI */      LWSCOSE_WKKPRSA_TI,
968*1c60b9acSAndroid Build Coastguard Worker 	},
969*1c60b9acSAndroid Build Coastguard Worker 	{ /* LWS_GENCRYPTO_KTY_EC (3) */
970*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_EC_KEYEL_CRV */ LWSCOSE_WKECKP_CRV,
971*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_EC_KEYEL_X */   LWSCOSE_WKECKP_X,
972*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_EC_KEYEL_D */   LWSCOSE_WKECKP_D,
973*1c60b9acSAndroid Build Coastguard Worker 		/* LWS_GENCRYPTO_EC_KEYEL_Y */   LWSCOSE_WKECKP_Y,
974*1c60b9acSAndroid Build Coastguard Worker 	}
975*1c60b9acSAndroid Build Coastguard Worker };
976*1c60b9acSAndroid Build Coastguard Worker 
977*1c60b9acSAndroid Build Coastguard Worker enum lws_lec_pctx_ret
lws_cose_key_export(lws_cose_key_t * ck,lws_lec_pctx_t * ctx,int flags)978*1c60b9acSAndroid Build Coastguard Worker lws_cose_key_export(lws_cose_key_t *ck, lws_lec_pctx_t *ctx, int flags)
979*1c60b9acSAndroid Build Coastguard Worker {
980*1c60b9acSAndroid Build Coastguard Worker 	cose_param_t pa = 0;
981*1c60b9acSAndroid Build Coastguard Worker 	int n;
982*1c60b9acSAndroid Build Coastguard Worker 
983*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->opaque[0]) {
984*1c60b9acSAndroid Build Coastguard Worker 
985*1c60b9acSAndroid Build Coastguard Worker 		ctx->opaque[0] = 1; /* map pair count */
986*1c60b9acSAndroid Build Coastguard Worker 		ctx->opaque[1] = 1; /* element index */
987*1c60b9acSAndroid Build Coastguard Worker 		ctx->opaque[2] = 0; /* public mask */
988*1c60b9acSAndroid Build Coastguard Worker 		ctx->opaque[3] = 0; /* doing AGAIN */
989*1c60b9acSAndroid Build Coastguard Worker 
990*1c60b9acSAndroid Build Coastguard Worker 		switch (ck->gencrypto_kty) {
991*1c60b9acSAndroid Build Coastguard Worker 		case LWS_GENCRYPTO_KTY_OCT:
992*1c60b9acSAndroid Build Coastguard Worker 			/* nothing to differentiate */
993*1c60b9acSAndroid Build Coastguard Worker 			ctx->opaque[2] = 1 << LWS_GENCRYPTO_OCT_KEYEL_K;
994*1c60b9acSAndroid Build Coastguard Worker 			break;
995*1c60b9acSAndroid Build Coastguard Worker 		case LWS_GENCRYPTO_KTY_RSA:
996*1c60b9acSAndroid Build Coastguard Worker 			ctx->opaque[2] = 1 << LWS_GENCRYPTO_RSA_KEYEL_E;
997*1c60b9acSAndroid Build Coastguard Worker 			break;
998*1c60b9acSAndroid Build Coastguard Worker 		case LWS_GENCRYPTO_KTY_EC:
999*1c60b9acSAndroid Build Coastguard Worker 			ctx->opaque[2] = (1 << LWS_GENCRYPTO_EC_KEYEL_X) |
1000*1c60b9acSAndroid Build Coastguard Worker 					 (1 << LWS_GENCRYPTO_EC_KEYEL_Y);
1001*1c60b9acSAndroid Build Coastguard Worker 			break;
1002*1c60b9acSAndroid Build Coastguard Worker 		default:
1003*1c60b9acSAndroid Build Coastguard Worker 			goto fail;
1004*1c60b9acSAndroid Build Coastguard Worker 		}
1005*1c60b9acSAndroid Build Coastguard Worker 
1006*1c60b9acSAndroid Build Coastguard Worker 		if (flags & LWSJWKF_EXPORT_PRIVATE)
1007*1c60b9acSAndroid Build Coastguard Worker 			ctx->opaque[2] = 0xffff;
1008*1c60b9acSAndroid Build Coastguard Worker 
1009*1c60b9acSAndroid Build Coastguard Worker 		/*
1010*1c60b9acSAndroid Build Coastguard Worker 		 * We first need to find out how many CBOR map pairs we are
1011*1c60b9acSAndroid Build Coastguard Worker 		 * planning to create, so we can set a fixed length map of the
1012*1c60b9acSAndroid Build Coastguard Worker 		 * right size.
1013*1c60b9acSAndroid Build Coastguard Worker 		 */
1014*1c60b9acSAndroid Build Coastguard Worker 
1015*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n < (int)LWS_ARRAY_SIZE(ck->e); n++)
1016*1c60b9acSAndroid Build Coastguard Worker 			if ((ctx->opaque[2] & (1 << n)) && ck->e[n].buf)
1017*1c60b9acSAndroid Build Coastguard Worker 				ctx->opaque[0]++;
1018*1c60b9acSAndroid Build Coastguard Worker 
1019*1c60b9acSAndroid Build Coastguard Worker 		/*
1020*1c60b9acSAndroid Build Coastguard Worker 		 * We always issue kty, others may be
1021*1c60b9acSAndroid Build Coastguard Worker 		 *
1022*1c60b9acSAndroid Build Coastguard Worker 		 * KID / ALG / KEY_OPS / BASE_IV
1023*1c60b9acSAndroid Build Coastguard Worker 		 */
1024*1c60b9acSAndroid Build Coastguard Worker 
1025*1c60b9acSAndroid Build Coastguard Worker 		if (ck->meta[COSEKEY_META_KID].buf)
1026*1c60b9acSAndroid Build Coastguard Worker 			ctx->opaque[0]++;
1027*1c60b9acSAndroid Build Coastguard Worker 		if (ck->meta[COSEKEY_META_ALG].buf)
1028*1c60b9acSAndroid Build Coastguard Worker 			ctx->opaque[0]++;
1029*1c60b9acSAndroid Build Coastguard Worker 		if (ck->meta[COSEKEY_META_KEY_OPS].buf)
1030*1c60b9acSAndroid Build Coastguard Worker 			ctx->opaque[0]++;
1031*1c60b9acSAndroid Build Coastguard Worker 		if (ck->meta[COSEKEY_META_BASE_IV].buf)
1032*1c60b9acSAndroid Build Coastguard Worker 			ctx->opaque[0]++;
1033*1c60b9acSAndroid Build Coastguard Worker 
1034*1c60b9acSAndroid Build Coastguard Worker 		lws_lec_int(ctx, LWS_CBOR_MAJTYP_MAP, 0, (uint64_t)ctx->opaque[0]);
1035*1c60b9acSAndroid Build Coastguard Worker 		lws_lec_signed(ctx, LWSCOSE_WKK_KTY);
1036*1c60b9acSAndroid Build Coastguard Worker 		lws_lec_signed(ctx, (int64_t)ck->kty);
1037*1c60b9acSAndroid Build Coastguard Worker 
1038*1c60b9acSAndroid Build Coastguard Worker 		if (ck->gencrypto_kty == LWS_GENCRYPTO_KTY_EC) {
1039*1c60b9acSAndroid Build Coastguard Worker 			struct lws_gencrypto_keyelem *ke =
1040*1c60b9acSAndroid Build Coastguard Worker 					&ck->e[LWS_GENCRYPTO_EC_KEYEL_CRV];
1041*1c60b9acSAndroid Build Coastguard Worker 
1042*1c60b9acSAndroid Build Coastguard Worker 			if (!ke->buf ||
1043*1c60b9acSAndroid Build Coastguard Worker 			    ck->e[LWS_GENCRYPTO_EC_KEYEL_CRV].len > 10) {
1044*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: no curve type\n", __func__);
1045*1c60b9acSAndroid Build Coastguard Worker 				goto fail;
1046*1c60b9acSAndroid Build Coastguard Worker 			}
1047*1c60b9acSAndroid Build Coastguard Worker 
1048*1c60b9acSAndroid Build Coastguard Worker 			pa = lws_cose_curve_name_to_id((const char *)ke->buf);
1049*1c60b9acSAndroid Build Coastguard Worker 			lws_lec_signed(ctx, LWSCOSE_WKECKP_CRV);
1050*1c60b9acSAndroid Build Coastguard Worker 			if (pa)
1051*1c60b9acSAndroid Build Coastguard Worker 				lws_lec_signed(ctx, pa);
1052*1c60b9acSAndroid Build Coastguard Worker 			else
1053*1c60b9acSAndroid Build Coastguard Worker 				lws_lec_printf(ctx, "%.*s",
1054*1c60b9acSAndroid Build Coastguard Worker 						(int)ke->len, ke->buf);
1055*1c60b9acSAndroid Build Coastguard Worker 		}
1056*1c60b9acSAndroid Build Coastguard Worker 
1057*1c60b9acSAndroid Build Coastguard Worker 
1058*1c60b9acSAndroid Build Coastguard Worker 		ctx->opaque[1] = COSEKEY_META_KID;
1059*1c60b9acSAndroid Build Coastguard Worker 	}
1060*1c60b9acSAndroid Build Coastguard Worker 
1061*1c60b9acSAndroid Build Coastguard Worker 	/*
1062*1c60b9acSAndroid Build Coastguard Worker 	 * Start from the second key meta, then do any elements that are set
1063*1c60b9acSAndroid Build Coastguard Worker 	 */
1064*1c60b9acSAndroid Build Coastguard Worker 
1065*1c60b9acSAndroid Build Coastguard Worker 	while (ctx->buf != ctx->end) {
1066*1c60b9acSAndroid Build Coastguard Worker 		struct lws_gencrypto_keyelem *ke = NULL;
1067*1c60b9acSAndroid Build Coastguard Worker 		int cose_key_param = 0;
1068*1c60b9acSAndroid Build Coastguard Worker 
1069*1c60b9acSAndroid Build Coastguard Worker 		if (lws_lec_scratch(ctx))
1070*1c60b9acSAndroid Build Coastguard Worker 			break;
1071*1c60b9acSAndroid Build Coastguard Worker 
1072*1c60b9acSAndroid Build Coastguard Worker 		if (ctx->opaque[1] == LWS_ARRAY_SIZE(ck->e) +
1073*1c60b9acSAndroid Build Coastguard Worker 				      LWS_COUNT_COSE_KEY_ELEMENTS)
1074*1c60b9acSAndroid Build Coastguard Worker 			break;
1075*1c60b9acSAndroid Build Coastguard Worker 
1076*1c60b9acSAndroid Build Coastguard Worker 		if (ctx->opaque[1] >= LWS_COUNT_COSE_KEY_ELEMENTS) {
1077*1c60b9acSAndroid Build Coastguard Worker 			n = ctx->opaque[1] - LWS_COUNT_COSE_KEY_ELEMENTS;
1078*1c60b9acSAndroid Build Coastguard Worker 
1079*1c60b9acSAndroid Build Coastguard Worker 			if (ck->gencrypto_kty != LWS_GENCRYPTO_KTY_EC ||
1080*1c60b9acSAndroid Build Coastguard Worker 			    n != LWS_GENCRYPTO_EC_KEYEL_CRV) {
1081*1c60b9acSAndroid Build Coastguard Worker 				/* we didn't already encode his curve */
1082*1c60b9acSAndroid Build Coastguard Worker 
1083*1c60b9acSAndroid Build Coastguard Worker 				if ((ctx->opaque[2] & (1 << n)) &&
1084*1c60b9acSAndroid Build Coastguard Worker 				     ck->e[n].buf && ck->e[n].len) {
1085*1c60b9acSAndroid Build Coastguard Worker 					ke = &ck->e[n];
1086*1c60b9acSAndroid Build Coastguard Worker 					cose_key_param = ckp[ck->gencrypto_kty - 1][n];
1087*1c60b9acSAndroid Build Coastguard Worker 				}
1088*1c60b9acSAndroid Build Coastguard Worker 			}
1089*1c60b9acSAndroid Build Coastguard Worker 		} else
1090*1c60b9acSAndroid Build Coastguard Worker 
1091*1c60b9acSAndroid Build Coastguard Worker 			switch (ctx->opaque[1]) {
1092*1c60b9acSAndroid Build Coastguard Worker 
1093*1c60b9acSAndroid Build Coastguard Worker 			case COSEKEY_META_KID: /* bstr */
1094*1c60b9acSAndroid Build Coastguard Worker 				if (ck->meta[COSEKEY_META_KID].buf) {
1095*1c60b9acSAndroid Build Coastguard Worker 					ke = &ck->meta[COSEKEY_META_KID];
1096*1c60b9acSAndroid Build Coastguard Worker 					cose_key_param = LWSCOSE_WKK_KID;
1097*1c60b9acSAndroid Build Coastguard Worker 					// lwsl_hexdump_notice(ke->buf, ke->len);
1098*1c60b9acSAndroid Build Coastguard Worker 				}
1099*1c60b9acSAndroid Build Coastguard Worker 				break;
1100*1c60b9acSAndroid Build Coastguard Worker 
1101*1c60b9acSAndroid Build Coastguard Worker 			case COSEKEY_META_ALG: /* int, tstr */
1102*1c60b9acSAndroid Build Coastguard Worker 				if (ck->meta[COSEKEY_META_ALG].buf) {
1103*1c60b9acSAndroid Build Coastguard Worker 					ke = &ck->meta[COSEKEY_META_ALG];
1104*1c60b9acSAndroid Build Coastguard Worker 					cose_key_param = LWSCOSE_WKK_ALG;
1105*1c60b9acSAndroid Build Coastguard Worker 				}
1106*1c60b9acSAndroid Build Coastguard Worker 				break;
1107*1c60b9acSAndroid Build Coastguard Worker 
1108*1c60b9acSAndroid Build Coastguard Worker 			case COSEKEY_META_KEY_OPS: /* [ int ] */
1109*1c60b9acSAndroid Build Coastguard Worker 				if (!ck->meta[COSEKEY_META_KEY_OPS].buf)
1110*1c60b9acSAndroid Build Coastguard Worker 					break;
1111*1c60b9acSAndroid Build Coastguard Worker 				ke = &ck->meta[COSEKEY_META_KEY_OPS];
1112*1c60b9acSAndroid Build Coastguard Worker 
1113*1c60b9acSAndroid Build Coastguard Worker 				n = (int)ke->len;
1114*1c60b9acSAndroid Build Coastguard Worker 				if (n > 10)
1115*1c60b9acSAndroid Build Coastguard Worker 					n = 10;
1116*1c60b9acSAndroid Build Coastguard Worker 
1117*1c60b9acSAndroid Build Coastguard Worker 				/*
1118*1c60b9acSAndroid Build Coastguard Worker 				 * We copy this array into scratch by hand now we
1119*1c60b9acSAndroid Build Coastguard Worker 				 * made sure it will fit, we will never need AGAIN
1120*1c60b9acSAndroid Build Coastguard Worker 				 */
1121*1c60b9acSAndroid Build Coastguard Worker 
1122*1c60b9acSAndroid Build Coastguard Worker 				lws_lec_signed(ctx, LWSCOSE_WKK_KEY_OPS);
1123*1c60b9acSAndroid Build Coastguard Worker 				lws_lec_int(ctx, LWS_CBOR_MAJTYP_ARRAY, 0, (uint64_t)n);
1124*1c60b9acSAndroid Build Coastguard Worker 				memcpy(&ctx->scratch[ctx->scratch_len], ke->buf,
1125*1c60b9acSAndroid Build Coastguard Worker 						(size_t)n);
1126*1c60b9acSAndroid Build Coastguard Worker 				ctx->scratch_len = (uint8_t)(ctx->scratch_len + (uint8_t)n);
1127*1c60b9acSAndroid Build Coastguard Worker 				ke = NULL;
1128*1c60b9acSAndroid Build Coastguard Worker 				break;
1129*1c60b9acSAndroid Build Coastguard Worker 
1130*1c60b9acSAndroid Build Coastguard Worker 			case COSEKEY_META_BASE_IV: /* bstr */
1131*1c60b9acSAndroid Build Coastguard Worker 				if (ck->meta[COSEKEY_META_BASE_IV].buf) {
1132*1c60b9acSAndroid Build Coastguard Worker 					ke = &ck->meta[COSEKEY_META_BASE_IV];
1133*1c60b9acSAndroid Build Coastguard Worker 					cose_key_param = LWSCOSE_WKK_BASE_IV;
1134*1c60b9acSAndroid Build Coastguard Worker 				}
1135*1c60b9acSAndroid Build Coastguard Worker 				break;
1136*1c60b9acSAndroid Build Coastguard Worker 
1137*1c60b9acSAndroid Build Coastguard Worker 			default:
1138*1c60b9acSAndroid Build Coastguard Worker 				break;
1139*1c60b9acSAndroid Build Coastguard Worker 			}
1140*1c60b9acSAndroid Build Coastguard Worker 
1141*1c60b9acSAndroid Build Coastguard Worker 		if (ke && ke->buf && ke->len) {
1142*1c60b9acSAndroid Build Coastguard Worker 
1143*1c60b9acSAndroid Build Coastguard Worker 			if (!ctx->opaque[3])
1144*1c60b9acSAndroid Build Coastguard Worker 				lws_lec_signed(ctx, cose_key_param);
1145*1c60b9acSAndroid Build Coastguard Worker 
1146*1c60b9acSAndroid Build Coastguard Worker 			/* binary string or text string? */
1147*1c60b9acSAndroid Build Coastguard Worker 			if (ctx->opaque[1] == COSEKEY_META_KID ||
1148*1c60b9acSAndroid Build Coastguard Worker 			    ctx->opaque[1] == COSEKEY_META_BASE_IV ||
1149*1c60b9acSAndroid Build Coastguard Worker 			    ctx->opaque[1] >= LWS_COUNT_COSE_KEY_ELEMENTS)
1150*1c60b9acSAndroid Build Coastguard Worker 				n = (int)lws_lec_printf(ctx, "%.*b",
1151*1c60b9acSAndroid Build Coastguard Worker 							(int)ke->len, ke->buf);
1152*1c60b9acSAndroid Build Coastguard Worker 			else
1153*1c60b9acSAndroid Build Coastguard Worker 				n = (int)lws_lec_printf(ctx, "%.*s",
1154*1c60b9acSAndroid Build Coastguard Worker 							(int)ke->len, ke->buf);
1155*1c60b9acSAndroid Build Coastguard Worker 
1156*1c60b9acSAndroid Build Coastguard Worker 			switch (n) {
1157*1c60b9acSAndroid Build Coastguard Worker 			case LWS_LECPCTX_RET_AGAIN:
1158*1c60b9acSAndroid Build Coastguard Worker 				ctx->opaque[3] = 1;
1159*1c60b9acSAndroid Build Coastguard Worker 				/* dump what we have and come back */
1160*1c60b9acSAndroid Build Coastguard Worker 				continue;
1161*1c60b9acSAndroid Build Coastguard Worker 			case LWS_LECPCTX_RET_FAIL:
1162*1c60b9acSAndroid Build Coastguard Worker 				goto fail;
1163*1c60b9acSAndroid Build Coastguard Worker 			case LWS_LECPCTX_RET_FINISHED:
1164*1c60b9acSAndroid Build Coastguard Worker 				break;
1165*1c60b9acSAndroid Build Coastguard Worker 			}
1166*1c60b9acSAndroid Build Coastguard Worker 		}
1167*1c60b9acSAndroid Build Coastguard Worker 
1168*1c60b9acSAndroid Build Coastguard Worker 		/* move on if we finished that guy */
1169*1c60b9acSAndroid Build Coastguard Worker 		ctx->opaque[1]++;
1170*1c60b9acSAndroid Build Coastguard Worker 		ctx->opaque[3] = 0;
1171*1c60b9acSAndroid Build Coastguard Worker 	}
1172*1c60b9acSAndroid Build Coastguard Worker 
1173*1c60b9acSAndroid Build Coastguard Worker 	ctx->used = lws_ptr_diff_size_t(ctx->buf, ctx->start);
1174*1c60b9acSAndroid Build Coastguard Worker 
1175*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->buf == ctx->end || ctx->scratch_len)
1176*1c60b9acSAndroid Build Coastguard Worker 		return LWS_LECPCTX_RET_AGAIN;
1177*1c60b9acSAndroid Build Coastguard Worker 
1178*1c60b9acSAndroid Build Coastguard Worker 	ctx->opaque[0] = 0;
1179*1c60b9acSAndroid Build Coastguard Worker 
1180*1c60b9acSAndroid Build Coastguard Worker 	return LWS_LECPCTX_RET_FINISHED;
1181*1c60b9acSAndroid Build Coastguard Worker 
1182*1c60b9acSAndroid Build Coastguard Worker fail:
1183*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("%s: failed\n", __func__);
1184*1c60b9acSAndroid Build Coastguard Worker 
1185*1c60b9acSAndroid Build Coastguard Worker 	ctx->opaque[0] = 0;
1186*1c60b9acSAndroid Build Coastguard Worker 
1187*1c60b9acSAndroid Build Coastguard Worker 	return LWS_LECPCTX_RET_FAIL;
1188*1c60b9acSAndroid Build Coastguard Worker }
1189