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_cilws_cose_sig_alg_t * 29d4afb5ceSopenharmony_cilws_cose_val_alg_create(struct lws_context *cx, lws_cose_key_t *ck, 30d4afb5ceSopenharmony_ci cose_param_t cose_alg, int op) 31d4afb5ceSopenharmony_ci{ 32d4afb5ceSopenharmony_ci lws_cose_sig_alg_t *alg = lws_zalloc(sizeof(*alg), __func__); 33d4afb5ceSopenharmony_ci struct lws_gencrypto_keyelem *ke; 34d4afb5ceSopenharmony_ci enum lws_genhmac_types ghm; 35d4afb5ceSopenharmony_ci enum lws_genhash_types gh; 36d4afb5ceSopenharmony_ci const char *crv; 37d4afb5ceSopenharmony_ci 38d4afb5ceSopenharmony_ci if (!alg) 39d4afb5ceSopenharmony_ci return NULL; 40d4afb5ceSopenharmony_ci 41d4afb5ceSopenharmony_ci alg->cose_alg = cose_alg; 42d4afb5ceSopenharmony_ci alg->cose_key = ck; 43d4afb5ceSopenharmony_ci 44d4afb5ceSopenharmony_ci switch (cose_alg) { 45d4afb5ceSopenharmony_ci 46d4afb5ceSopenharmony_ci /* ECDSA algs */ 47d4afb5ceSopenharmony_ci 48d4afb5ceSopenharmony_ci case LWSCOSE_WKAECDSA_ALG_ES256: /* ECDSA w/ SHA-256 */ 49d4afb5ceSopenharmony_ci crv = "P-256"; 50d4afb5ceSopenharmony_ci gh = LWS_GENHASH_TYPE_SHA256; 51d4afb5ceSopenharmony_ci alg->keybits = 256; 52d4afb5ceSopenharmony_ci goto ecdsa; 53d4afb5ceSopenharmony_ci case LWSCOSE_WKAECDSA_ALG_ES384: /* ECDSA w/ SHA-384 */ 54d4afb5ceSopenharmony_ci crv = "P-384"; 55d4afb5ceSopenharmony_ci gh = LWS_GENHASH_TYPE_SHA384; 56d4afb5ceSopenharmony_ci alg->keybits = 384; 57d4afb5ceSopenharmony_ci goto ecdsa; 58d4afb5ceSopenharmony_ci case LWSCOSE_WKAECDSA_ALG_ES512: /* ECDSA w/ SHA-512 */ 59d4afb5ceSopenharmony_ci crv = "P-521"; 60d4afb5ceSopenharmony_ci gh = LWS_GENHASH_TYPE_SHA512; 61d4afb5ceSopenharmony_ci alg->keybits = 521; 62d4afb5ceSopenharmony_ciecdsa: 63d4afb5ceSopenharmony_ci 64d4afb5ceSopenharmony_ci /* the key is good for this? */ 65d4afb5ceSopenharmony_ci 66d4afb5ceSopenharmony_ci if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_EC2, cose_alg, 67d4afb5ceSopenharmony_ci op, crv)) 68d4afb5ceSopenharmony_ci goto bail_ecdsa; 69d4afb5ceSopenharmony_ci 70d4afb5ceSopenharmony_ci if (lws_genhash_init(&alg->hash_ctx, gh)) 71d4afb5ceSopenharmony_ci goto bail_ecdsa; 72d4afb5ceSopenharmony_ci 73d4afb5ceSopenharmony_ci if (lws_genecdsa_create(&alg->u.ecdsactx, cx, lws_ec_curves)) { 74d4afb5ceSopenharmony_ci lwsl_notice("%s: lws_genrsa_public_decrypt_create\n", 75d4afb5ceSopenharmony_ci __func__); 76d4afb5ceSopenharmony_ci goto bail_ecdsa1; 77d4afb5ceSopenharmony_ci } 78d4afb5ceSopenharmony_ci 79d4afb5ceSopenharmony_ci if (lws_genecdsa_set_key(&alg->u.ecdsactx, ck->e)) { 80d4afb5ceSopenharmony_ci lwsl_notice("%s: ec key import fail\n", __func__); 81d4afb5ceSopenharmony_ci goto bail_ecdsa2; 82d4afb5ceSopenharmony_ci } 83d4afb5ceSopenharmony_ci 84d4afb5ceSopenharmony_ci break; 85d4afb5ceSopenharmony_ci 86d4afb5ceSopenharmony_ci /* HMAC algs */ 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_256_64: 89d4afb5ceSopenharmony_ci ghm = LWS_GENHMAC_TYPE_SHA256; 90d4afb5ceSopenharmony_ci alg->keybits = 64; 91d4afb5ceSopenharmony_ci goto hmac; 92d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_256_256: 93d4afb5ceSopenharmony_ci ghm = LWS_GENHMAC_TYPE_SHA256; 94d4afb5ceSopenharmony_ci alg->keybits = 256; 95d4afb5ceSopenharmony_ci goto hmac; 96d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_384_384: 97d4afb5ceSopenharmony_ci ghm = LWS_GENHMAC_TYPE_SHA384; 98d4afb5ceSopenharmony_ci alg->keybits = 384; 99d4afb5ceSopenharmony_ci goto hmac; 100d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_512_512: 101d4afb5ceSopenharmony_ci ghm = LWS_GENHMAC_TYPE_SHA512; 102d4afb5ceSopenharmony_ci alg->keybits = 512; 103d4afb5ceSopenharmony_ci 104d4afb5ceSopenharmony_cihmac: 105d4afb5ceSopenharmony_ci if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_SYMMETRIC, 106d4afb5ceSopenharmony_ci cose_alg, op, NULL)) 107d4afb5ceSopenharmony_ci goto bail_hmac; 108d4afb5ceSopenharmony_ci 109d4afb5ceSopenharmony_ci ke = &ck->e[LWS_GENCRYPTO_OCT_KEYEL_K]; 110d4afb5ceSopenharmony_ci if (lws_genhmac_init(&alg->u.hmacctx, ghm, ke->buf, ke->len)) 111d4afb5ceSopenharmony_ci goto bail_hmac; 112d4afb5ceSopenharmony_ci 113d4afb5ceSopenharmony_ci break; 114d4afb5ceSopenharmony_ci 115d4afb5ceSopenharmony_ci /* RSASSA algs */ 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_ci case LWSCOSE_WKARSA_ALG_RS256: 118d4afb5ceSopenharmony_ci gh = LWS_GENHASH_TYPE_SHA256; 119d4afb5ceSopenharmony_ci goto rsassa; 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ci case LWSCOSE_WKARSA_ALG_RS384: 122d4afb5ceSopenharmony_ci gh = LWS_GENHASH_TYPE_SHA384; 123d4afb5ceSopenharmony_ci goto rsassa; 124d4afb5ceSopenharmony_ci 125d4afb5ceSopenharmony_ci case LWSCOSE_WKARSA_ALG_RS512: 126d4afb5ceSopenharmony_ci gh = LWS_GENHASH_TYPE_SHA512; 127d4afb5ceSopenharmony_ci 128d4afb5ceSopenharmony_cirsassa: 129d4afb5ceSopenharmony_ci if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_RSA, cose_alg, 130d4afb5ceSopenharmony_ci op, NULL)) 131d4afb5ceSopenharmony_ci goto bail_hmac; 132d4afb5ceSopenharmony_ci alg->keybits = (int)ck->e[LWS_GENCRYPTO_RSA_KEYEL_N].len * 8; 133d4afb5ceSopenharmony_ci 134d4afb5ceSopenharmony_ci if (lws_genhash_init(&alg->hash_ctx, gh)) 135d4afb5ceSopenharmony_ci goto bail_ecdsa; 136d4afb5ceSopenharmony_ci 137d4afb5ceSopenharmony_ci if (lws_genrsa_create(&alg->u.rsactx, ck->e, cx, 138d4afb5ceSopenharmony_ci LGRSAM_PKCS1_1_5, gh)) { 139d4afb5ceSopenharmony_ci lwsl_notice("%s: lws_genrsa_create fail\n", __func__); 140d4afb5ceSopenharmony_ci goto bail_ecdsa1; 141d4afb5ceSopenharmony_ci } 142d4afb5ceSopenharmony_ci break; 143d4afb5ceSopenharmony_ci 144d4afb5ceSopenharmony_ci default: 145d4afb5ceSopenharmony_ci lwsl_warn("%s: unsupported alg %lld\n", __func__, 146d4afb5ceSopenharmony_ci (long long)cose_alg); 147d4afb5ceSopenharmony_ci goto bail_hmac; 148d4afb5ceSopenharmony_ci } 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci return alg; 151d4afb5ceSopenharmony_ci 152d4afb5ceSopenharmony_cibail_ecdsa2: 153d4afb5ceSopenharmony_ci lws_genec_destroy(&alg->u.ecdsactx); 154d4afb5ceSopenharmony_cibail_ecdsa1: 155d4afb5ceSopenharmony_ci lws_genhash_destroy(&alg->hash_ctx, NULL); 156d4afb5ceSopenharmony_cibail_ecdsa: 157d4afb5ceSopenharmony_ci lws_free(alg); 158d4afb5ceSopenharmony_ci 159d4afb5ceSopenharmony_ci lwsl_notice("%s: failed\n", __func__); 160d4afb5ceSopenharmony_ci 161d4afb5ceSopenharmony_ci return NULL; 162d4afb5ceSopenharmony_ci 163d4afb5ceSopenharmony_cibail_hmac: 164d4afb5ceSopenharmony_ci lws_free(alg); 165d4afb5ceSopenharmony_ci 166d4afb5ceSopenharmony_ci return NULL; 167d4afb5ceSopenharmony_ci} 168d4afb5ceSopenharmony_ci 169d4afb5ceSopenharmony_ciint 170d4afb5ceSopenharmony_cilws_cose_val_alg_hash(lws_cose_sig_alg_t *alg, const uint8_t *in, size_t in_len) 171d4afb5ceSopenharmony_ci{ 172d4afb5ceSopenharmony_ci#if defined(VERBOSE) 173d4afb5ceSopenharmony_ci lwsl_hexdump_warn(in, in_len); 174d4afb5ceSopenharmony_ci#endif 175d4afb5ceSopenharmony_ci 176d4afb5ceSopenharmony_ci switch (alg->cose_alg) { 177d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_256_64: 178d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_256_256: 179d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_384_384: 180d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_512_512: 181d4afb5ceSopenharmony_ci return lws_genhmac_update(&alg->u.hmacctx, in, in_len); 182d4afb5ceSopenharmony_ci } 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci return lws_genhash_update(&alg->hash_ctx, in, in_len); 185d4afb5ceSopenharmony_ci} 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_civoid 188d4afb5ceSopenharmony_cilws_cose_val_alg_destroy(struct lws_cose_validate_context *cps, 189d4afb5ceSopenharmony_ci lws_cose_sig_alg_t **_alg, const uint8_t *against, 190d4afb5ceSopenharmony_ci size_t against_len) 191d4afb5ceSopenharmony_ci{ 192d4afb5ceSopenharmony_ci uint8_t digest[LWS_GENHASH_LARGEST]; 193d4afb5ceSopenharmony_ci lws_cose_sig_alg_t *alg = *_alg; 194d4afb5ceSopenharmony_ci lws_cose_validate_res_t *res; 195d4afb5ceSopenharmony_ci size_t hs, shs; 196d4afb5ceSopenharmony_ci int keybits; 197d4afb5ceSopenharmony_ci uint8_t ht; 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci lws_dll2_remove(&alg->list); 200d4afb5ceSopenharmony_ci ht = alg->hash_ctx.type; 201d4afb5ceSopenharmony_ci keybits = alg->keybits; 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ci res = lws_zalloc(sizeof(*res), __func__); 204d4afb5ceSopenharmony_ci if (res) { 205d4afb5ceSopenharmony_ci 206d4afb5ceSopenharmony_ci res->cose_key = alg->cose_key; 207d4afb5ceSopenharmony_ci res->cose_alg = alg->cose_alg; 208d4afb5ceSopenharmony_ci res->result = -999; 209d4afb5ceSopenharmony_ci 210d4afb5ceSopenharmony_ci lws_dll2_add_tail(&res->list, &cps->results); 211d4afb5ceSopenharmony_ci } 212d4afb5ceSopenharmony_ci 213d4afb5ceSopenharmony_ci switch (alg->cose_alg) { 214d4afb5ceSopenharmony_ci case LWSCOSE_WKAECDSA_ALG_ES256: /* ECDSA w/ SHA-256 */ 215d4afb5ceSopenharmony_ci case LWSCOSE_WKAECDSA_ALG_ES384: /* ECDSA w/ SHA-384 */ 216d4afb5ceSopenharmony_ci case LWSCOSE_WKAECDSA_ALG_ES512: /* ECDSA w/ SHA-512 */ 217d4afb5ceSopenharmony_ci hs = lws_genhash_size(alg->hash_ctx.type); 218d4afb5ceSopenharmony_ci lws_genhash_destroy(&alg->hash_ctx, digest); 219d4afb5ceSopenharmony_ci 220d4afb5ceSopenharmony_ci lwsl_notice("%d %d %d\n", (int)hs, (int)keybits, (int)against_len); 221d4afb5ceSopenharmony_ci 222d4afb5ceSopenharmony_ci if (res && against) 223d4afb5ceSopenharmony_ci res->result = lws_genecdsa_hash_sig_verify_jws( 224d4afb5ceSopenharmony_ci &alg->u.ecdsactx, digest, ht, 225d4afb5ceSopenharmony_ci keybits, against, against_len); 226d4afb5ceSopenharmony_ci lws_genec_destroy(&alg->u.ecdsactx); 227d4afb5ceSopenharmony_ci break; 228d4afb5ceSopenharmony_ci 229d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_256_64: 230d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_256_256: 231d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_384_384: 232d4afb5ceSopenharmony_ci case LWSCOSE_WKAHMAC_512_512: 233d4afb5ceSopenharmony_ci shs = hs = lws_genhmac_size(alg->u.hmacctx.type); 234d4afb5ceSopenharmony_ci if (alg->cose_alg == LWSCOSE_WKAHMAC_256_64) 235d4afb5ceSopenharmony_ci shs = 8; 236d4afb5ceSopenharmony_ci 237d4afb5ceSopenharmony_ci if (lws_genhmac_destroy(&alg->u.hmacctx, digest)) { 238d4afb5ceSopenharmony_ci lwsl_err("%s: destroy failed\n", __func__); 239d4afb5ceSopenharmony_ci break; 240d4afb5ceSopenharmony_ci } 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_ci if (cps->mac_pos != shs) { 243d4afb5ceSopenharmony_ci lwsl_warn("%s: mac wrong size\n", __func__); 244d4afb5ceSopenharmony_ci /* we can't compare it, leave it at fail */ 245d4afb5ceSopenharmony_ci break; 246d4afb5ceSopenharmony_ci } 247d4afb5ceSopenharmony_ci if (res && against) { 248d4afb5ceSopenharmony_ci res->result = lws_timingsafe_bcmp(digest, cps->mac, 249d4afb5ceSopenharmony_ci (uint32_t)shs); 250d4afb5ceSopenharmony_ci if (res->result) 251d4afb5ceSopenharmony_ci lwsl_warn("%s: hash mismatch\n", __func__); 252d4afb5ceSopenharmony_ci } 253d4afb5ceSopenharmony_ci break; 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci case LWSCOSE_WKARSA_ALG_RS256: 256d4afb5ceSopenharmony_ci case LWSCOSE_WKARSA_ALG_RS384: 257d4afb5ceSopenharmony_ci case LWSCOSE_WKARSA_ALG_RS512: 258d4afb5ceSopenharmony_ci 259d4afb5ceSopenharmony_ci if (!lws_genhash_destroy(&alg->hash_ctx, digest) && 260d4afb5ceSopenharmony_ci !alg->failed && 261d4afb5ceSopenharmony_ci lws_genrsa_hash_sig_verify(&alg->u.rsactx, digest, 262d4afb5ceSopenharmony_ci alg->hash_ctx.type, 263d4afb5ceSopenharmony_ci against, against_len) >= 0) { 264d4afb5ceSopenharmony_ci if (res) 265d4afb5ceSopenharmony_ci res->result = 0; 266d4afb5ceSopenharmony_ci } else 267d4afb5ceSopenharmony_ci lwsl_err("%s: lws_genrsa_hash_verify\n", __func__); 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_ci lws_genrsa_destroy(&alg->u.rsactx); 270d4afb5ceSopenharmony_ci break; 271d4afb5ceSopenharmony_ci } 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ci lws_free_set_NULL(*_alg); 274d4afb5ceSopenharmony_ci} 275