1/* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to 8 * deal in the Software without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25#include "private-lib-core.h" 26#include "private-lib-cose.h" 27 28lws_cose_sig_alg_t * 29lws_cose_sign_alg_create(struct lws_context *cx, const lws_cose_key_t *ck, 30 cose_param_t cose_alg, int op) 31{ 32 lws_cose_sig_alg_t *alg = lws_zalloc(sizeof(*alg), __func__); 33 const struct lws_gencrypto_keyelem *ke; 34 enum lws_genhmac_types ghm; 35 enum lws_genhash_types gh; 36 const char *crv; 37 38 if (!alg) 39 return NULL; 40 41 alg->cose_alg = cose_alg; 42 alg->cose_key = ck; 43 44 switch (cose_alg) { 45 46 /* ECDSA algs */ 47 48 case LWSCOSE_WKAECDSA_ALG_ES256: /* ECDSA w/ SHA-256 */ 49 crv = "P-256"; 50 gh = LWS_GENHASH_TYPE_SHA256; 51 alg->keybits = 256; 52 goto ecdsa; 53 case LWSCOSE_WKAECDSA_ALG_ES384: /* ECDSA w/ SHA-384 */ 54 crv = "P-384"; 55 gh = LWS_GENHASH_TYPE_SHA384; 56 alg->keybits = 384; 57 goto ecdsa; 58 case LWSCOSE_WKAECDSA_ALG_ES512: /* ECDSA w/ SHA-512 */ 59 crv = "P-521"; 60 gh = LWS_GENHASH_TYPE_SHA512; 61 alg->keybits = 521; 62ecdsa: 63 64 /* the key is good for this? */ 65 66 if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_EC2, cose_alg, 67 op, crv)) 68 goto bail_ecdsa; 69 70 if (lws_genhash_init(&alg->hash_ctx, gh)) 71 goto bail_ecdsa; 72 73 if (lws_genecdsa_create(&alg->u.ecdsactx, cx, lws_ec_curves)) { 74 lwsl_notice("%s: lws_genrsa_public_decrypt_create\n", 75 __func__); 76 goto bail_ecdsa1; 77 } 78 79 if (lws_genecdsa_set_key(&alg->u.ecdsactx, ck->e)) { 80 lwsl_notice("%s: ec key import fail\n", __func__); 81 goto bail_ecdsa2; 82 } 83 84 break; 85 86 /* HMAC algs */ 87 88 case LWSCOSE_WKAHMAC_256_64: 89 ghm = LWS_GENHMAC_TYPE_SHA256; 90 alg->keybits = 64; 91 goto hmac; 92 case LWSCOSE_WKAHMAC_256_256: 93 ghm = LWS_GENHMAC_TYPE_SHA256; 94 alg->keybits = 256; 95 goto hmac; 96 case LWSCOSE_WKAHMAC_384_384: 97 ghm = LWS_GENHMAC_TYPE_SHA384; 98 alg->keybits = 384; 99 goto hmac; 100 case LWSCOSE_WKAHMAC_512_512: 101 ghm = LWS_GENHMAC_TYPE_SHA512; 102 alg->keybits = 512; 103 104hmac: 105 if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_SYMMETRIC, 106 cose_alg, op, NULL)) 107 goto bail_hmac; 108 109 ke = &ck->e[LWS_GENCRYPTO_OCT_KEYEL_K]; 110 if (lws_genhmac_init(&alg->u.hmacctx, ghm, ke->buf, ke->len)) 111 goto bail_hmac; 112 113 break; 114 115 /* RSASSA algs */ 116 117 case LWSCOSE_WKARSA_ALG_RS256: 118 gh = LWS_GENHASH_TYPE_SHA256; 119 goto rsassa; 120 121 case LWSCOSE_WKARSA_ALG_RS384: 122 gh = LWS_GENHASH_TYPE_SHA384; 123 goto rsassa; 124 125 case LWSCOSE_WKARSA_ALG_RS512: 126 gh = LWS_GENHASH_TYPE_SHA512; 127 128rsassa: 129 if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_RSA, cose_alg, 130 op, NULL)) 131 goto bail_hmac; 132 133 alg->keybits = (int)ck->e[LWS_GENCRYPTO_RSA_KEYEL_N].len * 8; 134 135 if (lws_genhash_init(&alg->hash_ctx, gh)) 136 goto bail_hmac; 137 138 if (lws_genrsa_create(&alg->u.rsactx, ck->e, cx, 139 LGRSAM_PKCS1_1_5, gh)) { 140 lwsl_notice("%s: lws_genrsa_create fail\n", __func__); 141 goto bail_hmac; 142 } 143 break; 144 145 default: 146 lwsl_warn("%s: unsupported alg %lld\n", __func__, 147 (long long)cose_alg); 148 goto bail_hmac; 149 } 150 151 return alg; 152 153bail_ecdsa2: 154 lws_genec_destroy(&alg->u.ecdsactx); 155bail_ecdsa1: 156 lws_genhash_destroy(&alg->hash_ctx, NULL); 157bail_ecdsa: 158 lws_free(alg); 159 160 return NULL; 161 162bail_hmac: 163 lws_free(alg); 164 165 return NULL; 166} 167 168int 169lws_cose_sign_alg_hash(lws_cose_sig_alg_t *alg, const uint8_t *in, size_t in_len) 170{ 171#if defined(VERBOSE) 172 lwsl_hexdump_warn(in, in_len); 173#endif 174 175 switch (alg->cose_alg) { 176 177 case LWSCOSE_WKAHMAC_256_64: 178 case LWSCOSE_WKAHMAC_256_256: 179 case LWSCOSE_WKAHMAC_384_384: 180 case LWSCOSE_WKAHMAC_512_512: 181 return lws_genhmac_update(&alg->u.hmacctx, in, in_len); 182 } 183 184 /* EC, rsa are just making the hash before signing */ 185 186 return lws_genhash_update(&alg->hash_ctx, in, in_len); 187} 188 189/* 190 * We fill up alg-> rhash and rhash_len with the results, and destroy the 191 * crypto pieces cleanly. Call lws_cose_sign_alg_destroy() afterwards to 192 * clean up the alg itself. 193 */ 194 195void 196lws_cose_sign_alg_complete(lws_cose_sig_alg_t *alg) 197{ 198 uint8_t digest[LWS_GENHASH_LARGEST]; 199 unsigned int bytes; 200 uint8_t htype; 201 size_t hs; 202 203 if (alg->completed) 204 return; 205 206 switch (alg->cose_alg) { 207 case LWSCOSE_WKAECDSA_ALG_ES256: /* ECDSA w/ SHA-256 */ 208 case LWSCOSE_WKAECDSA_ALG_ES384: /* ECDSA w/ SHA-384 */ 209 case LWSCOSE_WKAECDSA_ALG_ES512: /* ECDSA w/ SHA-512 */ 210 hs = lws_genhash_size(alg->hash_ctx.type); 211 bytes = (unsigned int)lws_gencrypto_bits_to_bytes(alg->keybits); 212 lws_genhash_destroy(&alg->hash_ctx, digest); 213 alg->rhash_len = 0; 214 lwsl_notice("alg keybits %d hs %d\n", (int)alg->keybits, (int)hs); 215 if (!alg->failed && 216 lws_genecdsa_hash_sign_jws(&alg->u.ecdsactx, digest, 217 alg->hash_ctx.type, 218 (int)alg->keybits, alg->rhash, 219 2u * bytes) >= 0) 220 alg->rhash_len = (int)(2 * bytes); 221 else 222 alg->failed = 1; 223 224 lws_genec_destroy(&alg->u.ecdsactx); 225 break; 226 227 case LWSCOSE_WKAHMAC_256_64: 228 case LWSCOSE_WKAHMAC_256_256: 229 case LWSCOSE_WKAHMAC_384_384: 230 case LWSCOSE_WKAHMAC_512_512: 231 alg->rhash_len = (int)lws_genhmac_size(alg->u.hmacctx.type); 232 if (alg->cose_alg == LWSCOSE_WKAHMAC_256_64) 233 alg->rhash_len = 8; 234 235 if (lws_genhmac_destroy(&alg->u.hmacctx, alg->rhash)) { 236 lwsl_err("%s: destroy failed\n", __func__); 237 break; 238 } 239 break; 240 241 case LWSCOSE_WKARSA_ALG_RS256: 242 case LWSCOSE_WKARSA_ALG_RS384: 243 case LWSCOSE_WKARSA_ALG_RS512: 244 bytes = (unsigned int)lws_gencrypto_bits_to_bytes(alg->keybits); 245 htype = alg->hash_ctx.type; 246 247 if (!lws_genhash_destroy(&alg->hash_ctx, digest) && 248 !alg->failed && 249 lws_genrsa_hash_sign(&alg->u.rsactx, digest, htype, 250 alg->rhash, bytes) >= 0) 251 alg->rhash_len = (int)bytes; 252 else 253 lwsl_err("%s: lws_genrsa_hash_sign\n", __func__); 254 255 lws_genrsa_destroy(&alg->u.rsactx); 256 break; 257 258 default: 259 break; 260 } 261 262 alg->completed = 1; 263} 264 265void 266lws_cose_sign_alg_destroy(lws_cose_sig_alg_t **_alg) 267{ 268 lws_dll2_remove(&(*_alg)->list); 269 lws_cose_sign_alg_complete(*_alg); 270 lws_free_set_NULL(*_alg); 271} 272