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