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