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_sign_alg_create(struct lws_context * cx,const lws_cose_key_t * ck,cose_param_t cose_alg,int op)29 lws_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;
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
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
153 bail_ecdsa2:
154 lws_genec_destroy(&alg->u.ecdsactx);
155 bail_ecdsa1:
156 lws_genhash_destroy(&alg->hash_ctx, NULL);
157 bail_ecdsa:
158 lws_free(alg);
159
160 return NULL;
161
162 bail_hmac:
163 lws_free(alg);
164
165 return NULL;
166 }
167
168 int
lws_cose_sign_alg_hash(lws_cose_sig_alg_t * alg,const uint8_t * in,size_t in_len)169 lws_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
195 void
lws_cose_sign_alg_complete(lws_cose_sig_alg_t * alg)196 lws_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
265 void
lws_cose_sign_alg_destroy(lws_cose_sig_alg_t ** _alg)266 lws_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