• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
28 lws_cose_sig_alg_t *
lws_cose_val_alg_create(struct lws_context * cx,lws_cose_key_t * ck,cose_param_t cose_alg,int op)29 lws_cose_val_alg_create(struct lws_context *cx, 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 	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;
62 ecdsa:
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 
104 hmac:
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 
128 rsassa:
129 		if (lws_cose_key_checks(ck, LWSCOSE_WKKTV_RSA, cose_alg,
130 					op, NULL))
131 			goto bail_hmac;
132 		alg->keybits = (int)ck->e[LWS_GENCRYPTO_RSA_KEYEL_N].len * 8;
133 
134 		if (lws_genhash_init(&alg->hash_ctx, gh))
135 			goto bail_ecdsa;
136 
137 		if (lws_genrsa_create(&alg->u.rsactx, ck->e, cx,
138 				      LGRSAM_PKCS1_1_5, gh)) {
139 			lwsl_notice("%s: lws_genrsa_create fail\n", __func__);
140 			goto bail_ecdsa1;
141 		}
142 		break;
143 
144 	default:
145 		lwsl_warn("%s: unsupported alg %lld\n", __func__,
146 				(long long)cose_alg);
147 		goto bail_hmac;
148 	}
149 
150 	return alg;
151 
152 bail_ecdsa2:
153 	lws_genec_destroy(&alg->u.ecdsactx);
154 bail_ecdsa1:
155 	lws_genhash_destroy(&alg->hash_ctx, NULL);
156 bail_ecdsa:
157 	lws_free(alg);
158 
159 	lwsl_notice("%s: failed\n", __func__);
160 
161 	return NULL;
162 
163 bail_hmac:
164 	lws_free(alg);
165 
166 	return NULL;
167 }
168 
169 int
lws_cose_val_alg_hash(lws_cose_sig_alg_t * alg,const uint8_t * in,size_t in_len)170 lws_cose_val_alg_hash(lws_cose_sig_alg_t *alg, const uint8_t *in, size_t in_len)
171 {
172 #if defined(VERBOSE)
173 	lwsl_hexdump_warn(in, in_len);
174 #endif
175 
176 	switch (alg->cose_alg) {
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 	return lws_genhash_update(&alg->hash_ctx, in, in_len);
185 }
186 
187 void
lws_cose_val_alg_destroy(struct lws_cose_validate_context * cps,lws_cose_sig_alg_t ** _alg,const uint8_t * against,size_t against_len)188 lws_cose_val_alg_destroy(struct lws_cose_validate_context *cps,
189 			 lws_cose_sig_alg_t **_alg, const uint8_t *against,
190 			 size_t against_len)
191 {
192 	uint8_t digest[LWS_GENHASH_LARGEST];
193 	lws_cose_sig_alg_t *alg = *_alg;
194 	lws_cose_validate_res_t *res;
195 	size_t hs, shs;
196 	int keybits;
197 	uint8_t ht;
198 
199 	lws_dll2_remove(&alg->list);
200 	ht = alg->hash_ctx.type;
201 	keybits = alg->keybits;
202 
203 	res = lws_zalloc(sizeof(*res), __func__);
204 	if (res) {
205 
206 		res->cose_key = alg->cose_key;
207 		res->cose_alg = alg->cose_alg;
208 		res->result = -999;
209 
210 		lws_dll2_add_tail(&res->list, &cps->results);
211 	}
212 
213 	switch (alg->cose_alg) {
214 	case LWSCOSE_WKAECDSA_ALG_ES256: /* ECDSA w/ SHA-256 */
215 	case LWSCOSE_WKAECDSA_ALG_ES384: /* ECDSA w/ SHA-384 */
216 	case LWSCOSE_WKAECDSA_ALG_ES512: /* ECDSA w/ SHA-512 */
217 		hs = lws_genhash_size(alg->hash_ctx.type);
218 		lws_genhash_destroy(&alg->hash_ctx, digest);
219 
220 		lwsl_notice("%d %d %d\n", (int)hs, (int)keybits, (int)against_len);
221 
222 		if (res && against)
223 			res->result = lws_genecdsa_hash_sig_verify_jws(
224 						&alg->u.ecdsactx, digest, ht,
225 						keybits, against, against_len);
226 		lws_genec_destroy(&alg->u.ecdsactx);
227 		break;
228 
229 	case LWSCOSE_WKAHMAC_256_64:
230 	case LWSCOSE_WKAHMAC_256_256:
231 	case LWSCOSE_WKAHMAC_384_384:
232 	case LWSCOSE_WKAHMAC_512_512:
233 		shs = hs = lws_genhmac_size(alg->u.hmacctx.type);
234 		if (alg->cose_alg == LWSCOSE_WKAHMAC_256_64)
235 			shs = 8;
236 
237 		if (lws_genhmac_destroy(&alg->u.hmacctx, digest)) {
238 			lwsl_err("%s: destroy failed\n", __func__);
239 			break;
240 		}
241 
242 		if (cps->mac_pos != shs) {
243 			lwsl_warn("%s: mac wrong size\n", __func__);
244 			/* we can't compare it, leave it at fail */
245 			break;
246 		}
247 		if (res && against) {
248 			res->result = lws_timingsafe_bcmp(digest, cps->mac,
249 								(uint32_t)shs);
250 			if (res->result)
251 				lwsl_warn("%s: hash mismatch\n", __func__);
252 		}
253 		break;
254 
255 	case LWSCOSE_WKARSA_ALG_RS256:
256 	case LWSCOSE_WKARSA_ALG_RS384:
257 	case LWSCOSE_WKARSA_ALG_RS512:
258 
259 		if (!lws_genhash_destroy(&alg->hash_ctx, digest) &&
260 		    !alg->failed &&
261 		    lws_genrsa_hash_sig_verify(&alg->u.rsactx, digest,
262 					 alg->hash_ctx.type,
263 					 against, against_len) >= 0) {
264 			if (res)
265 				res->result = 0;
266 		} else
267 			lwsl_err("%s: lws_genrsa_hash_verify\n", __func__);
268 
269 		lws_genrsa_destroy(&alg->u.rsactx);
270 		break;
271 	}
272 
273 	lws_free_set_NULL(*_alg);
274 }
275