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 25d4afb5ceSopenharmony_ci#include "private-lib-core.h" 26d4afb5ceSopenharmony_ci#include "private-lib-cose.h" 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_cistruct lws_cose_sign_context * 29d4afb5ceSopenharmony_cilws_cose_sign_create(const lws_cose_sign_create_info_t *info) 30d4afb5ceSopenharmony_ci{ 31d4afb5ceSopenharmony_ci struct lws_cose_sign_context *csc; 32d4afb5ceSopenharmony_ci 33d4afb5ceSopenharmony_ci /* you have to have prepared a cbor output context for us to use */ 34d4afb5ceSopenharmony_ci assert(info->lec); 35d4afb5ceSopenharmony_ci /* you have to provide at least one key in a cose_keyset */ 36d4afb5ceSopenharmony_ci assert(info->keyset); 37d4afb5ceSopenharmony_ci /* you have to provide an lws_context (for crypto random) */ 38d4afb5ceSopenharmony_ci assert(info->cx); 39d4afb5ceSopenharmony_ci 40d4afb5ceSopenharmony_ci if (info->sigtype == SIGTYPE_MAC) { 41d4afb5ceSopenharmony_ci lwsl_err("%s: only mac0 supported for signing\n", __func__); 42d4afb5ceSopenharmony_ci return NULL; 43d4afb5ceSopenharmony_ci } 44d4afb5ceSopenharmony_ci 45d4afb5ceSopenharmony_ci csc = lws_zalloc(sizeof(*csc), __func__); 46d4afb5ceSopenharmony_ci if (!csc) 47d4afb5ceSopenharmony_ci return NULL; 48d4afb5ceSopenharmony_ci 49d4afb5ceSopenharmony_ci csc->info = *info; 50d4afb5ceSopenharmony_ci 51d4afb5ceSopenharmony_ci return csc; 52d4afb5ceSopenharmony_ci} 53d4afb5ceSopenharmony_ci 54d4afb5ceSopenharmony_ciint 55d4afb5ceSopenharmony_cilws_cose_sign_add(struct lws_cose_sign_context *csc, cose_param_t alg, 56d4afb5ceSopenharmony_ci const lws_cose_key_t *ck) 57d4afb5ceSopenharmony_ci{ 58d4afb5ceSopenharmony_ci lws_cose_sig_alg_t *si = lws_cose_sign_alg_create(csc->info.cx, ck, alg, 59d4afb5ceSopenharmony_ci LWSCOSE_WKKO_SIGN); 60d4afb5ceSopenharmony_ci 61d4afb5ceSopenharmony_ci if (!si) 62d4afb5ceSopenharmony_ci return 1; 63d4afb5ceSopenharmony_ci 64d4afb5ceSopenharmony_ci lws_dll2_add_tail(&si->list, &csc->algs); 65d4afb5ceSopenharmony_ci 66d4afb5ceSopenharmony_ci return 0; 67d4afb5ceSopenharmony_ci} 68d4afb5ceSopenharmony_ci 69d4afb5ceSopenharmony_cistatic signed char cose_tags[] = { 70d4afb5ceSopenharmony_ci 0, 71d4afb5ceSopenharmony_ci LWSCOAP_CONTENTFORMAT_COSE_SIGN, 72d4afb5ceSopenharmony_ci LWSCOAP_CONTENTFORMAT_COSE_SIGN1, 73d4afb5ceSopenharmony_ci LWSCOAP_CONTENTFORMAT_COSE_SIGN, 74d4afb5ceSopenharmony_ci LWSCOAP_CONTENTFORMAT_COSE_MAC, 75d4afb5ceSopenharmony_ci LWSCOAP_CONTENTFORMAT_COSE_MAC0 76d4afb5ceSopenharmony_ci}; 77d4afb5ceSopenharmony_ci 78d4afb5ceSopenharmony_cistatic void 79d4afb5ceSopenharmony_cilws_cose_sign_hashing(struct lws_cose_sign_context *csc, 80d4afb5ceSopenharmony_ci const uint8_t *in, size_t in_len) 81d4afb5ceSopenharmony_ci{ 82d4afb5ceSopenharmony_ci //lwsl_hexdump_warn(in, in_len); 83d4afb5ceSopenharmony_ci 84d4afb5ceSopenharmony_ci assert(in_len); 85d4afb5ceSopenharmony_ci 86d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, 87d4afb5ceSopenharmony_ci lws_dll2_get_head(&csc->algs)) { 88d4afb5ceSopenharmony_ci lws_cose_sig_alg_t *alg = lws_container_of(p, 89d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_ci if (lws_cose_sign_alg_hash(alg, in, in_len)) 92d4afb5ceSopenharmony_ci alg->failed = 1; 93d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(p, tp); 94d4afb5ceSopenharmony_ci} 95d4afb5ceSopenharmony_ci 96d4afb5ceSopenharmony_ci/* 97d4afb5ceSopenharmony_ci * These chunks may be payload or application AAD being emitted into the 98d4afb5ceSopenharmony_ci * signed object somewhere else. But we do not emit them ourselves here 99d4afb5ceSopenharmony_ci * (since other non-emitted things are also hashed by us) and so can always 100d4afb5ceSopenharmony_ci * deal with the whole in_len in one step. 101d4afb5ceSopenharmony_ci */ 102d4afb5ceSopenharmony_ci 103d4afb5ceSopenharmony_cienum lws_lec_pctx_ret 104d4afb5ceSopenharmony_cilws_cose_sign_payload_chunk(struct lws_cose_sign_context *csc, 105d4afb5ceSopenharmony_ci const uint8_t *in, size_t in_len) 106d4afb5ceSopenharmony_ci{ 107d4afb5ceSopenharmony_ci uint8_t lbuf[MAX_BLOBBED_PARAMS], lb[9]; 108d4afb5ceSopenharmony_ci const struct lws_gencrypto_keyelem *ke; 109d4afb5ceSopenharmony_ci enum lws_lec_pctx_ret ret; 110d4afb5ceSopenharmony_ci lws_lec_pctx_t lec, lec1; 111d4afb5ceSopenharmony_ci lws_cose_sig_alg_t *alg; 112d4afb5ceSopenharmony_ci uint8_t c; 113d4afb5ceSopenharmony_ci size_t s; 114d4afb5ceSopenharmony_ci 115d4afb5ceSopenharmony_ci switch (csc->tli) { 116d4afb5ceSopenharmony_ci case ST_UNKNOWN: 117d4afb5ceSopenharmony_ci /* 118d4afb5ceSopenharmony_ci * We need to figure out what signing structure we need to use, 119d4afb5ceSopenharmony_ci * given the algorithms that are in it. So let's have a look 120d4afb5ceSopenharmony_ci * and decide. 121d4afb5ceSopenharmony_ci */ 122d4afb5ceSopenharmony_ci 123d4afb5ceSopenharmony_ci if (!csc->algs.count) { 124d4afb5ceSopenharmony_ci lwsl_err("%s: must add at least one signature\n", __func__); 125d4afb5ceSopenharmony_ci return 1; 126d4afb5ceSopenharmony_ci } 127d4afb5ceSopenharmony_ci 128d4afb5ceSopenharmony_ci csc->type = SIGTYPE_MULTI; 129d4afb5ceSopenharmony_ci alg = lws_container_of(csc->algs.head, lws_cose_sig_alg_t, list); 130d4afb5ceSopenharmony_ci 131d4afb5ceSopenharmony_ci switch (alg->cose_alg) { 132d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_256_64: 133d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_256_256: 134d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_384_384: 135d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_512_512: 136d4afb5ceSopenharmony_ci// if (csc->info.sigtype == SIGTYPE_MAC0) 137d4afb5ceSopenharmony_ci csc->type = SIGTYPE_MAC0; 138d4afb5ceSopenharmony_ci// else 139d4afb5ceSopenharmony_ci// csc->type = SIGTYPE_MAC; 140d4afb5ceSopenharmony_ci break; 141d4afb5ceSopenharmony_ci } 142d4afb5ceSopenharmony_ci 143d4afb5ceSopenharmony_ci if (csc->algs.count == 1) { 144d4afb5ceSopenharmony_ci if (!csc->info.sigtype && csc->type == SIGTYPE_MAC) { 145d4afb5ceSopenharmony_ci if (csc->info.flags & LCSC_FL_ADD_CBOR_PREFER_MAC0) 146d4afb5ceSopenharmony_ci csc->type = SIGTYPE_MAC0; 147d4afb5ceSopenharmony_ci } else 148d4afb5ceSopenharmony_ci if (!csc->info.sigtype || 149d4afb5ceSopenharmony_ci csc->info.sigtype == SIGTYPE_SINGLE) /* ie, if no hint */ 150d4afb5ceSopenharmony_ci csc->type = SIGTYPE_SINGLE; 151d4afb5ceSopenharmony_ci } 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci lwsl_notice("%s: decided on type %d\n", __func__, csc->type); 154d4afb5ceSopenharmony_ci 155d4afb5ceSopenharmony_ci /* 156d4afb5ceSopenharmony_ci * Start emitting the appropriate tag if that's requested 157d4afb5ceSopenharmony_ci */ 158d4afb5ceSopenharmony_ci 159d4afb5ceSopenharmony_ci if (csc->info.flags & LCSC_FL_ADD_CBOR_TAG) { 160d4afb5ceSopenharmony_ci ret = lws_lec_printf(csc->info.lec, "%t(", 161d4afb5ceSopenharmony_ci cose_tags[csc->type]); 162d4afb5ceSopenharmony_ci 163d4afb5ceSopenharmony_ci if (ret != LWS_LECPCTX_RET_FINISHED) 164d4afb5ceSopenharmony_ci return ret; 165d4afb5ceSopenharmony_ci } 166d4afb5ceSopenharmony_ci 167d4afb5ceSopenharmony_ci /* The */ 168d4afb5ceSopenharmony_ci c = 0; 169d4afb5ceSopenharmony_ci switch (csc->type) { 170d4afb5ceSopenharmony_ci case SIGTYPE_MAC0: 171d4afb5ceSopenharmony_ci case SIGTYPE_MULTI: 172d4afb5ceSopenharmony_ci case SIGTYPE_SINGLE: 173d4afb5ceSopenharmony_ci c = 0x84; 174d4afb5ceSopenharmony_ci break; 175d4afb5ceSopenharmony_ci case SIGTYPE_MAC: 176d4afb5ceSopenharmony_ci c = 0x85; 177d4afb5ceSopenharmony_ci break; 178d4afb5ceSopenharmony_ci default: 179d4afb5ceSopenharmony_ci break; 180d4afb5ceSopenharmony_ci } 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ci /* The outer array */ 183d4afb5ceSopenharmony_ci csc->info.lec->scratch[csc->info.lec->scratch_len++] = c; 184d4afb5ceSopenharmony_ci 185d4afb5ceSopenharmony_ci /* 186d4afb5ceSopenharmony_ci * Then, let's start hashing with the sigtype constant part 187d4afb5ceSopenharmony_ci */ 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci lws_cose_sign_hashing(csc, sig_mctx[csc->type], 190d4afb5ceSopenharmony_ci sig_mctx_len[csc->type]); 191d4afb5ceSopenharmony_ci 192d4afb5ceSopenharmony_ci csc->tli = ST_OUTER_PROTECTED; 193d4afb5ceSopenharmony_ci csc->subsequent = 0; 194d4afb5ceSopenharmony_ci 195d4afb5ceSopenharmony_ci /* fallthru */ 196d4afb5ceSopenharmony_ci 197d4afb5ceSopenharmony_ci case ST_OUTER_PROTECTED: 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci /* 200d4afb5ceSopenharmony_ci * We need to list and emit any outer protected data as a map 201d4afb5ceSopenharmony_ci * into its own buffer, then emit that into the output as a bstr 202d4afb5ceSopenharmony_ci */ 203d4afb5ceSopenharmony_ci 204d4afb5ceSopenharmony_ci switch (csc->type) { 205d4afb5ceSopenharmony_ci case SIGTYPE_SINGLE: 206d4afb5ceSopenharmony_ci case SIGTYPE_MAC0: 207d4afb5ceSopenharmony_ci alg = lws_container_of(csc->algs.head, 208d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 209d4afb5ceSopenharmony_ci 210d4afb5ceSopenharmony_ci lws_lec_init(&lec, lbuf, sizeof(lbuf)); 211d4afb5ceSopenharmony_ci 212d4afb5ceSopenharmony_ci /* we know it will fit... but coverity doesn't */ 213d4afb5ceSopenharmony_ci ret = lws_lec_printf(&lec, "{1:%lld}", 214d4afb5ceSopenharmony_ci (long long)alg->cose_alg); 215d4afb5ceSopenharmony_ci if (ret != LWS_LECPCTX_RET_FINISHED) 216d4afb5ceSopenharmony_ci return ret; 217d4afb5ceSopenharmony_ci 218d4afb5ceSopenharmony_ci lws_lec_scratch(&lec); 219d4afb5ceSopenharmony_ci 220d4afb5ceSopenharmony_ci if (!csc->subsequent) { 221d4afb5ceSopenharmony_ci lws_lec_init(&lec1, lb, sizeof(lb)); 222d4afb5ceSopenharmony_ci lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, 223d4afb5ceSopenharmony_ci lec.used); 224d4afb5ceSopenharmony_ci lws_cose_sign_hashing(csc, lec1.scratch, 225d4afb5ceSopenharmony_ci lec1.scratch_len); 226d4afb5ceSopenharmony_ci lws_cose_sign_hashing(csc, lec.start, lec.used); 227d4afb5ceSopenharmony_ci ret = lws_lec_printf(csc->info.lec, "%.*b", 228d4afb5ceSopenharmony_ci (int)lec.used, lec.start); 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_ci if (ret != LWS_LECPCTX_RET_FINISHED) 231d4afb5ceSopenharmony_ci return ret; 232d4afb5ceSopenharmony_ci csc->subsequent = 1; 233d4afb5ceSopenharmony_ci } 234d4afb5ceSopenharmony_ci break; 235d4afb5ceSopenharmony_ci case SIGTYPE_MAC: 236d4afb5ceSopenharmony_ci case SIGTYPE_MULTI: 237d4afb5ceSopenharmony_ci lws_lec_init(&lec, lbuf, sizeof(lbuf)); 238d4afb5ceSopenharmony_ci lws_lec_int(&lec, LWS_CBOR_MAJTYP_BSTR, 0, 0); 239d4afb5ceSopenharmony_ci lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_BSTR, 0, 0); 240d4afb5ceSopenharmony_ci lws_lec_scratch(&lec); 241d4afb5ceSopenharmony_ci lec.used = lws_ptr_diff_size_t(lec.buf, lec.start); 242d4afb5ceSopenharmony_ci lws_cose_sign_hashing(csc, lec.start, 243d4afb5ceSopenharmony_ci lec.used); 244d4afb5ceSopenharmony_ci break; 245d4afb5ceSopenharmony_ci default: 246d4afb5ceSopenharmony_ci lec.used = 0; 247d4afb5ceSopenharmony_ci break; 248d4afb5ceSopenharmony_ci } 249d4afb5ceSopenharmony_ci 250d4afb5ceSopenharmony_ci csc->tli = ST_OUTER_UNPROTECTED; 251d4afb5ceSopenharmony_ci 252d4afb5ceSopenharmony_ci /* fallthru */ 253d4afb5ceSopenharmony_ci 254d4afb5ceSopenharmony_ci case ST_OUTER_UNPROTECTED: 255d4afb5ceSopenharmony_ci 256d4afb5ceSopenharmony_ci /* 257d4afb5ceSopenharmony_ci * We need to list and emit any outer unprotected data, as 258d4afb5ceSopenharmony_ci * an inline cbor map 259d4afb5ceSopenharmony_ci */ 260d4afb5ceSopenharmony_ci 261d4afb5ceSopenharmony_ci switch (csc->type) { 262d4afb5ceSopenharmony_ci case SIGTYPE_SINGLE: 263d4afb5ceSopenharmony_ci case SIGTYPE_MAC0: 264d4afb5ceSopenharmony_ci alg = lws_container_of(csc->algs.head, 265d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 266d4afb5ceSopenharmony_ci ke = &alg->cose_key->meta[COSEKEY_META_KID]; 267d4afb5ceSopenharmony_ci if (ke->len) { 268d4afb5ceSopenharmony_ci ret = lws_lec_printf(csc->info.lec, "{%d:%.*b}", 269d4afb5ceSopenharmony_ci LWSCOSE_WKL_KID, 270d4afb5ceSopenharmony_ci (int)ke->len, ke->buf); 271d4afb5ceSopenharmony_ci 272d4afb5ceSopenharmony_ci if (ret != LWS_LECPCTX_RET_FINISHED) 273d4afb5ceSopenharmony_ci return ret; 274d4afb5ceSopenharmony_ci } 275d4afb5ceSopenharmony_ci /* hack for no extra data */ 276d4afb5ceSopenharmony_ci 277d4afb5ceSopenharmony_ci lws_lec_init(&lec1, lb, sizeof(lb)); 278d4afb5ceSopenharmony_ci lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, 0); 279d4afb5ceSopenharmony_ci lws_cose_sign_hashing(csc, lec1.scratch, 280d4afb5ceSopenharmony_ci lec1.scratch_len); 281d4afb5ceSopenharmony_ci break; 282d4afb5ceSopenharmony_ci case SIGTYPE_MAC: 283d4afb5ceSopenharmony_ci case SIGTYPE_MULTI: 284d4afb5ceSopenharmony_ci 285d4afb5ceSopenharmony_ci lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_BSTR, 0, 0); 286d4afb5ceSopenharmony_ci 287d4afb5ceSopenharmony_ci /* 288d4afb5ceSopenharmony_ci * For cose-sign, we need to feed each sig alg its alg- 289d4afb5ceSopenharmony_ci * specific protected data into the hash before letting 290d4afb5ceSopenharmony_ci * all the hashes see the payload 291d4afb5ceSopenharmony_ci */ 292d4afb5ceSopenharmony_ci 293d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, 294d4afb5ceSopenharmony_ci lws_dll2_get_head(&csc->algs)) { 295d4afb5ceSopenharmony_ci alg = lws_container_of(p, lws_cose_sig_alg_t, list); 296d4afb5ceSopenharmony_ci 297d4afb5ceSopenharmony_ci lws_lec_init(&lec, lbuf, sizeof(lbuf)); 298d4afb5ceSopenharmony_ci 299d4afb5ceSopenharmony_ci /* we know it will fit... but coverity doesn't... */ 300d4afb5ceSopenharmony_ci ret = lws_lec_printf(&lec, "{1:%lld}", 301d4afb5ceSopenharmony_ci (long long)alg->cose_alg); 302d4afb5ceSopenharmony_ci if (ret != LWS_LECPCTX_RET_FINISHED) 303d4afb5ceSopenharmony_ci return ret; 304d4afb5ceSopenharmony_ci 305d4afb5ceSopenharmony_ci lws_lec_init(&lec1, lb, sizeof(lb)); 306d4afb5ceSopenharmony_ci lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, 307d4afb5ceSopenharmony_ci lec.used); 308d4afb5ceSopenharmony_ci 309d4afb5ceSopenharmony_ci // lwsl_hexdump_warn(lec1.scratch, lec1.scratch_len); 310d4afb5ceSopenharmony_ci // lwsl_hexdump_warn(lec.start, lec.used); 311d4afb5ceSopenharmony_ci if (lws_cose_sign_alg_hash(alg, lec1.scratch, 312d4afb5ceSopenharmony_ci lec1.scratch_len)) 313d4afb5ceSopenharmony_ci alg->failed = 1; 314d4afb5ceSopenharmony_ci if (lws_cose_sign_alg_hash(alg, lec.start, 315d4afb5ceSopenharmony_ci lec.used)) 316d4afb5ceSopenharmony_ci alg->failed = 1; 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(p, tp); 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_ci lws_lec_init(&lec1, lb, sizeof(lb)); 321d4afb5ceSopenharmony_ci lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, 0); 322d4afb5ceSopenharmony_ci lws_cose_sign_hashing(csc, lec1.scratch, 323d4afb5ceSopenharmony_ci lec1.scratch_len); 324d4afb5ceSopenharmony_ci 325d4afb5ceSopenharmony_ci break; 326d4afb5ceSopenharmony_ci default: 327d4afb5ceSopenharmony_ci ret = lws_lec_printf(csc->info.lec, "{}"); 328d4afb5ceSopenharmony_ci if (ret != LWS_LECPCTX_RET_FINISHED) 329d4afb5ceSopenharmony_ci return ret; 330d4afb5ceSopenharmony_ci break; 331d4afb5ceSopenharmony_ci } 332d4afb5ceSopenharmony_ci 333d4afb5ceSopenharmony_ci csc->tli = ST_OUTER_PAYLOAD; 334d4afb5ceSopenharmony_ci csc->subsequent = 0; 335d4afb5ceSopenharmony_ci 336d4afb5ceSopenharmony_ci /* Prepare the payload BSTR */ 337d4afb5ceSopenharmony_ci 338d4afb5ceSopenharmony_ci lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_BSTR, 0, 339d4afb5ceSopenharmony_ci csc->info.inline_payload_len); 340d4afb5ceSopenharmony_ci 341d4afb5ceSopenharmony_ci lws_lec_init(&lec1, lb, sizeof(lb)); 342d4afb5ceSopenharmony_ci lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, 343d4afb5ceSopenharmony_ci csc->info.inline_payload_len); 344d4afb5ceSopenharmony_ci lws_cose_sign_hashing(csc, lec1.scratch, 345d4afb5ceSopenharmony_ci lec1.scratch_len); 346d4afb5ceSopenharmony_ci 347d4afb5ceSopenharmony_ci lws_lec_scratch(csc->info.lec); 348d4afb5ceSopenharmony_ci 349d4afb5ceSopenharmony_ci csc->rem_pay = csc->info.inline_payload_len; 350d4afb5ceSopenharmony_ci 351d4afb5ceSopenharmony_ci /* fallthru */ 352d4afb5ceSopenharmony_ci 353d4afb5ceSopenharmony_ci case ST_OUTER_PAYLOAD: 354d4afb5ceSopenharmony_ci 355d4afb5ceSopenharmony_ci if (csc->along) { 356d4afb5ceSopenharmony_ci in += csc->along; 357d4afb5ceSopenharmony_ci in_len -= csc->along; 358d4afb5ceSopenharmony_ci } 359d4afb5ceSopenharmony_ci 360d4afb5ceSopenharmony_ci lws_lec_scratch(csc->info.lec); 361d4afb5ceSopenharmony_ci 362d4afb5ceSopenharmony_ci if (csc->rem_pay) { 363d4afb5ceSopenharmony_ci 364d4afb5ceSopenharmony_ci lws_cose_sign_hashing(csc, in, in_len); 365d4afb5ceSopenharmony_ci 366d4afb5ceSopenharmony_ci /* 367d4afb5ceSopenharmony_ci * in / in_len is the payload chunk 368d4afb5ceSopenharmony_ci */ 369d4afb5ceSopenharmony_ci 370d4afb5ceSopenharmony_ci s = lws_ptr_diff_size_t(csc->info.lec->end, 371d4afb5ceSopenharmony_ci csc->info.lec->buf); 372d4afb5ceSopenharmony_ci if (s > (size_t)csc->rem_pay) 373d4afb5ceSopenharmony_ci s = (size_t)csc->rem_pay; 374d4afb5ceSopenharmony_ci if (s > in_len) 375d4afb5ceSopenharmony_ci s = in_len; 376d4afb5ceSopenharmony_ci 377d4afb5ceSopenharmony_ci memcpy(csc->info.lec->buf, in, s); 378d4afb5ceSopenharmony_ci csc->info.lec->buf += s; 379d4afb5ceSopenharmony_ci csc->info.lec->used = lws_ptr_diff_size_t( 380d4afb5ceSopenharmony_ci csc->info.lec->buf, 381d4afb5ceSopenharmony_ci csc->info.lec->start); 382d4afb5ceSopenharmony_ci csc->rem_pay -= s; 383d4afb5ceSopenharmony_ci 384d4afb5ceSopenharmony_ci csc->along = s; 385d4afb5ceSopenharmony_ci 386d4afb5ceSopenharmony_ci return LWS_LECPCTX_RET_AGAIN; 387d4afb5ceSopenharmony_ci } 388d4afb5ceSopenharmony_ci 389d4afb5ceSopenharmony_ci /* finished with rem_pay */ 390d4afb5ceSopenharmony_ci 391d4afb5ceSopenharmony_ci if (csc->type == SIGTYPE_MULTI) { 392d4afb5ceSopenharmony_ci 393d4afb5ceSopenharmony_ci csc->alg = lws_container_of(csc->algs.head, 394d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 395d4afb5ceSopenharmony_ci lws_lec_init(&lec1, lb, sizeof(lb)); 396d4afb5ceSopenharmony_ci lws_lec_int(&lec1, LWS_CBOR_MAJTYP_ARRAY, 0, 397d4afb5ceSopenharmony_ci csc->algs.count); 398d4afb5ceSopenharmony_ci lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_ARRAY, 0, 399d4afb5ceSopenharmony_ci csc->algs.count); 400d4afb5ceSopenharmony_ci csc->tli = ST_INNER_PROTECTED; 401d4afb5ceSopenharmony_ci goto inner_protected; 402d4afb5ceSopenharmony_ci } 403d4afb5ceSopenharmony_ci csc->tli = ST_OUTER_SIGN1_SIGNATURE; 404d4afb5ceSopenharmony_ci csc->along = 0; 405d4afb5ceSopenharmony_ci 406d4afb5ceSopenharmony_ci /* fallthru */ 407d4afb5ceSopenharmony_ci 408d4afb5ceSopenharmony_ci case ST_OUTER_SIGN1_SIGNATURE: 409d4afb5ceSopenharmony_ci 410d4afb5ceSopenharmony_ci alg = lws_container_of(lws_dll2_get_head(&csc->algs), 411d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 412d4afb5ceSopenharmony_ci 413d4afb5ceSopenharmony_ci if (!alg->completed) 414d4afb5ceSopenharmony_ci lws_cose_sign_alg_complete(alg); 415d4afb5ceSopenharmony_ci if (alg->failed) 416d4afb5ceSopenharmony_ci return LWS_LECPCTX_RET_FAIL; 417d4afb5ceSopenharmony_ci 418d4afb5ceSopenharmony_ci ret = lws_lec_printf(csc->info.lec, "%.*b", 419d4afb5ceSopenharmony_ci (int)alg->rhash_len, alg->rhash); 420d4afb5ceSopenharmony_ci if (ret != LWS_LECPCTX_RET_FINISHED) 421d4afb5ceSopenharmony_ci return ret; 422d4afb5ceSopenharmony_ci 423d4afb5ceSopenharmony_ci if (csc->type == SIGTYPE_MAC) { 424d4afb5ceSopenharmony_ci csc->alg = lws_container_of(csc->algs.head, 425d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 426d4afb5ceSopenharmony_ci lws_lec_init(&lec1, lb, sizeof(lb)); 427d4afb5ceSopenharmony_ci lws_lec_int(&lec1, LWS_CBOR_MAJTYP_ARRAY, 0, 428d4afb5ceSopenharmony_ci csc->algs.count); 429d4afb5ceSopenharmony_ci lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_ARRAY, 0, 430d4afb5ceSopenharmony_ci csc->algs.count); 431d4afb5ceSopenharmony_ci csc->tli = ST_INNER_PROTECTED; 432d4afb5ceSopenharmony_ci goto inner_protected; 433d4afb5ceSopenharmony_ci } 434d4afb5ceSopenharmony_ci 435d4afb5ceSopenharmony_ci break; 436d4afb5ceSopenharmony_ci 437d4afb5ceSopenharmony_ci case ST_INNER_PROTECTED: 438d4afb5ceSopenharmony_ciinner_protected: 439d4afb5ceSopenharmony_ci 440d4afb5ceSopenharmony_ci /* 441d4afb5ceSopenharmony_ci * We need to list and emit any outer protected data as a map 442d4afb5ceSopenharmony_ci * into its own buffer, then emit that into the output as a bstr 443d4afb5ceSopenharmony_ci */ 444d4afb5ceSopenharmony_ci 445d4afb5ceSopenharmony_ci switch (csc->type) { 446d4afb5ceSopenharmony_ci case SIGTYPE_MAC: 447d4afb5ceSopenharmony_ci case SIGTYPE_MULTI: 448d4afb5ceSopenharmony_ci lws_lec_init(&lec1, lb, sizeof(lb)); 449d4afb5ceSopenharmony_ci lws_lec_int(&lec1, LWS_CBOR_MAJTYP_ARRAY, 0, 3); 450d4afb5ceSopenharmony_ci 451d4afb5ceSopenharmony_ci lws_lec_int(csc->info.lec, LWS_CBOR_MAJTYP_ARRAY, 0, 3); 452d4afb5ceSopenharmony_ci 453d4afb5ceSopenharmony_ci lws_lec_init(&lec, lbuf, sizeof(lbuf)); 454d4afb5ceSopenharmony_ci 455d4afb5ceSopenharmony_ci /* we know it will fit */ 456d4afb5ceSopenharmony_ci lws_lec_printf(&lec, "{1:%lld}", 457d4afb5ceSopenharmony_ci (long long)csc->alg->cose_alg); 458d4afb5ceSopenharmony_ci 459d4afb5ceSopenharmony_ci lws_lec_init(&lec1, lb, sizeof(lb)); 460d4afb5ceSopenharmony_ci lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, 461d4afb5ceSopenharmony_ci lec.used); 462d4afb5ceSopenharmony_ci if (lws_lec_printf(csc->info.lec, "{1:%lld}", 463d4afb5ceSopenharmony_ci (long long)csc->alg->cose_alg) != LWS_LECPCTX_RET_FINISHED) 464d4afb5ceSopenharmony_ci /* coverity */ 465d4afb5ceSopenharmony_ci return 0; 466d4afb5ceSopenharmony_ci break; 467d4afb5ceSopenharmony_ci default: 468d4afb5ceSopenharmony_ci lec.used = 0; 469d4afb5ceSopenharmony_ci break; 470d4afb5ceSopenharmony_ci } 471d4afb5ceSopenharmony_ci 472d4afb5ceSopenharmony_ci 473d4afb5ceSopenharmony_ci csc->tli = ST_INNER_UNPROTECTED; 474d4afb5ceSopenharmony_ci 475d4afb5ceSopenharmony_ci /* fallthru */ 476d4afb5ceSopenharmony_ci 477d4afb5ceSopenharmony_ci case ST_INNER_UNPROTECTED: 478d4afb5ceSopenharmony_ci 479d4afb5ceSopenharmony_ci switch (csc->type) { 480d4afb5ceSopenharmony_ci case SIGTYPE_MULTI: 481d4afb5ceSopenharmony_ci alg = lws_container_of(csc->algs.head, 482d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 483d4afb5ceSopenharmony_ci ke = &alg->cose_key->meta[COSEKEY_META_KID]; 484d4afb5ceSopenharmony_ci if (ke->len) { 485d4afb5ceSopenharmony_ci ret = lws_lec_printf(csc->info.lec, "{%d:%.*b}", 486d4afb5ceSopenharmony_ci LWSCOSE_WKL_KID, 487d4afb5ceSopenharmony_ci (int)ke->len, ke->buf); 488d4afb5ceSopenharmony_ci 489d4afb5ceSopenharmony_ci if (ret != LWS_LECPCTX_RET_FINISHED) 490d4afb5ceSopenharmony_ci return ret; 491d4afb5ceSopenharmony_ci } 492d4afb5ceSopenharmony_ci break; 493d4afb5ceSopenharmony_ci default: 494d4afb5ceSopenharmony_ci ret = lws_lec_printf(csc->info.lec, "{}"); 495d4afb5ceSopenharmony_ci if (ret != LWS_LECPCTX_RET_FINISHED) 496d4afb5ceSopenharmony_ci return ret; 497d4afb5ceSopenharmony_ci break; 498d4afb5ceSopenharmony_ci } 499d4afb5ceSopenharmony_ci 500d4afb5ceSopenharmony_ci lws_cose_sign_alg_complete(csc->alg); 501d4afb5ceSopenharmony_ci if (csc->alg->failed) 502d4afb5ceSopenharmony_ci return LWS_LECPCTX_RET_FAIL; 503d4afb5ceSopenharmony_ci csc->tli = ST_INNER_SIGNATURE; 504d4afb5ceSopenharmony_ci 505d4afb5ceSopenharmony_ci /* fallthru */ 506d4afb5ceSopenharmony_ci 507d4afb5ceSopenharmony_ci case ST_INNER_SIGNATURE: 508d4afb5ceSopenharmony_ci 509d4afb5ceSopenharmony_ci ret = lws_lec_printf(csc->info.lec, "%.*b", 510d4afb5ceSopenharmony_ci (int)csc->alg->rhash_len, csc->alg->rhash); 511d4afb5ceSopenharmony_ci if (ret != LWS_LECPCTX_RET_FINISHED) 512d4afb5ceSopenharmony_ci return ret; 513d4afb5ceSopenharmony_ci 514d4afb5ceSopenharmony_ci if (csc->alg->list.next) { 515d4afb5ceSopenharmony_ci csc->alg = (lws_cose_sig_alg_t *)csc->alg->list.next; 516d4afb5ceSopenharmony_ci csc->tli = ST_INNER_PROTECTED; 517d4afb5ceSopenharmony_ci } 518d4afb5ceSopenharmony_ci break; 519d4afb5ceSopenharmony_ci 520d4afb5ceSopenharmony_ci } 521d4afb5ceSopenharmony_ci 522d4afb5ceSopenharmony_ci return 0; 523d4afb5ceSopenharmony_ci} 524d4afb5ceSopenharmony_ci 525d4afb5ceSopenharmony_civoid 526d4afb5ceSopenharmony_cilws_cose_sign_destroy(struct lws_cose_sign_context **_csc) 527d4afb5ceSopenharmony_ci{ 528d4afb5ceSopenharmony_ci struct lws_cose_sign_context *csc = *_csc; 529d4afb5ceSopenharmony_ci 530d4afb5ceSopenharmony_ci if (!csc) 531d4afb5ceSopenharmony_ci return; 532d4afb5ceSopenharmony_ci 533d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, 534d4afb5ceSopenharmony_ci lws_dll2_get_head(&csc->algs)) { 535d4afb5ceSopenharmony_ci lws_cose_sig_alg_t *alg = lws_container_of(p, 536d4afb5ceSopenharmony_ci lws_cose_sig_alg_t, list); 537d4afb5ceSopenharmony_ci 538d4afb5ceSopenharmony_ci lws_dll2_remove(p); 539d4afb5ceSopenharmony_ci lws_cose_sign_alg_destroy(&alg); 540d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(p, tp); 541d4afb5ceSopenharmony_ci 542d4afb5ceSopenharmony_ci lws_free_set_NULL(*_csc); 543d4afb5ceSopenharmony_ci} 544