1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 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 *  lws_genhash provides a hash / hmac abstraction api in lws that works the
25 *  same whether you are using openssl or mbedtls hash functions underneath.
26 */
27#include "libwebsockets.h"
28#include <mbedtls/version.h>
29
30#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x03000000)
31#define mbedtls_md5_starts_ret mbedtls_md5_starts
32#define mbedtls_md5_update_ret mbedtls_md5_update
33#define mbedtls_md5_finish_ret mbedtls_md5_finish
34#define mbedtls_sha1_finish_ret mbedtls_sha1_finish
35#define mbedtls_sha1_update_ret mbedtls_sha1_update
36#define mbedtls_sha1_starts_ret mbedtls_sha1_starts
37#define mbedtls_sha256_starts_ret mbedtls_sha256_starts
38#define mbedtls_sha256_update_ret mbedtls_sha256_update
39#define mbedtls_sha256_finish_ret mbedtls_sha256_finish
40#define mbedtls_sha512_starts_ret mbedtls_sha512_starts
41#define mbedtls_sha512_update_ret mbedtls_sha512_update
42#define mbedtls_sha512_finish_ret mbedtls_sha512_finish
43#endif
44
45#if defined(MBEDTLS_VERSION_NUMBER) && (MBEDTLS_VERSION_NUMBER >= 0x02070000)
46
47/*
48 * We have the _ret variants available, check the return codes on everything
49 */
50
51int
52lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type)
53{
54	ctx->type = (uint8_t)type;
55
56	switch (ctx->type) {
57	case LWS_GENHASH_TYPE_MD5:
58		mbedtls_md5_init(&ctx->u.md5);
59		if (mbedtls_md5_starts_ret(&ctx->u.md5))
60			return 1;
61		break;
62	case LWS_GENHASH_TYPE_SHA1:
63		mbedtls_sha1_init(&ctx->u.sha1);
64		if (mbedtls_sha1_starts_ret(&ctx->u.sha1))
65			return 1;
66		break;
67	case LWS_GENHASH_TYPE_SHA256:
68		mbedtls_sha256_init(&ctx->u.sha256);
69		if (mbedtls_sha256_starts_ret(&ctx->u.sha256, 0))
70			return 1;
71		break;
72	case LWS_GENHASH_TYPE_SHA384:
73		mbedtls_sha512_init(&ctx->u.sha512);
74		if (mbedtls_sha512_starts_ret(&ctx->u.sha512, 1 /* is384 */))
75			return 1;
76		break;
77	case LWS_GENHASH_TYPE_SHA512:
78		mbedtls_sha512_init(&ctx->u.sha512);
79		if (mbedtls_sha512_starts_ret(&ctx->u.sha512, 0))
80			return 1;
81		break;
82	default:
83		return 1;
84	}
85
86	return 0;
87}
88
89int
90lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len)
91{
92	if (!len)
93		return 0;
94
95	switch (ctx->type) {
96	case LWS_GENHASH_TYPE_MD5:
97		if (mbedtls_md5_update_ret(&ctx->u.md5, in, len))
98			return 1;
99		break;
100	case LWS_GENHASH_TYPE_SHA1:
101		if (mbedtls_sha1_update_ret(&ctx->u.sha1, in, len))
102			return 1;
103		break;
104	case LWS_GENHASH_TYPE_SHA256:
105		if (mbedtls_sha256_update_ret(&ctx->u.sha256, in, len))
106			return 1;
107		break;
108	case LWS_GENHASH_TYPE_SHA384:
109		if (mbedtls_sha512_update_ret(&ctx->u.sha512, in, len))
110			return 1;
111		break;
112	case LWS_GENHASH_TYPE_SHA512:
113		if (mbedtls_sha512_update_ret(&ctx->u.sha512, in, len))
114			return 1;
115		break;
116	}
117
118	return 0;
119}
120
121int
122lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result)
123{
124	switch (ctx->type) {
125	case LWS_GENHASH_TYPE_MD5:
126		if (mbedtls_md5_finish_ret(&ctx->u.md5, result))
127			return 1;
128		mbedtls_md5_free(&ctx->u.md5);
129		break;
130	case LWS_GENHASH_TYPE_SHA1:
131		if (mbedtls_sha1_finish_ret(&ctx->u.sha1, result))
132			return 1;
133		mbedtls_sha1_free(&ctx->u.sha1);
134		break;
135	case LWS_GENHASH_TYPE_SHA256:
136		if (mbedtls_sha256_finish_ret(&ctx->u.sha256, result))
137			return 1;
138		mbedtls_sha256_free(&ctx->u.sha256);
139		break;
140	case LWS_GENHASH_TYPE_SHA384:
141		if (mbedtls_sha512_finish_ret(&ctx->u.sha512, result))
142			return 1;
143		mbedtls_sha512_free(&ctx->u.sha512);
144		break;
145	case LWS_GENHASH_TYPE_SHA512:
146		if (mbedtls_sha512_finish_ret(&ctx->u.sha512, result))
147			return 1;
148		mbedtls_sha512_free(&ctx->u.sha512);
149		break;
150	}
151
152	return 0;
153}
154
155#else
156
157/*
158 * mbedtls is too old to have the _ret variants
159 */
160
161int
162lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type)
163{
164	ctx->type = type;
165
166	switch (ctx->type) {
167	case LWS_GENHASH_TYPE_MD5:
168		mbedtls_md5_init(&ctx->u.md5);
169		mbedtls_md5_starts(&ctx->u.md5);
170		break;
171	case LWS_GENHASH_TYPE_SHA1:
172		mbedtls_sha1_init(&ctx->u.sha1);
173		mbedtls_sha1_starts(&ctx->u.sha1);
174		break;
175	case LWS_GENHASH_TYPE_SHA256:
176		mbedtls_sha256_init(&ctx->u.sha256);
177		mbedtls_sha256_starts(&ctx->u.sha256, 0);
178		break;
179	case LWS_GENHASH_TYPE_SHA384:
180		mbedtls_sha512_init(&ctx->u.sha512);
181		mbedtls_sha512_starts(&ctx->u.sha512, 1 /* is384 */);
182		break;
183	case LWS_GENHASH_TYPE_SHA512:
184		mbedtls_sha512_init(&ctx->u.sha512);
185		mbedtls_sha512_starts(&ctx->u.sha512, 0);
186		break;
187	default:
188		return 1;
189	}
190
191	return 0;
192}
193
194int
195lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len)
196{
197	if (!len)
198		return 0;
199
200	switch (ctx->type) {
201	case LWS_GENHASH_TYPE_MD5:
202		mbedtls_md5_update(&ctx->u.md5, in, len);
203		break;
204	case LWS_GENHASH_TYPE_SHA1:
205		mbedtls_sha1_update(&ctx->u.sha1, in, len);
206		break;
207	case LWS_GENHASH_TYPE_SHA256:
208		mbedtls_sha256_update(&ctx->u.sha256, in, len);
209		break;
210	case LWS_GENHASH_TYPE_SHA384:
211		mbedtls_sha512_update(&ctx->u.sha512, in, len);
212		break;
213	case LWS_GENHASH_TYPE_SHA512:
214		mbedtls_sha512_update(&ctx->u.sha512, in, len);
215		break;
216	}
217
218	return 0;
219}
220
221int
222lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result)
223{
224	switch (ctx->type) {
225	case LWS_GENHASH_TYPE_MD5:
226		mbedtls_md5_finish(&ctx->u.md5, result);
227		mbedtls_md5_free(&ctx->u.md5);
228		break;
229	case LWS_GENHASH_TYPE_SHA1:
230		mbedtls_sha1_finish(&ctx->u.sha1, result);
231		mbedtls_sha1_free(&ctx->u.sha1);
232		break;
233	case LWS_GENHASH_TYPE_SHA256:
234		mbedtls_sha256_finish(&ctx->u.sha256, result);
235		mbedtls_sha256_free(&ctx->u.sha256);
236		break;
237	case LWS_GENHASH_TYPE_SHA384:
238		mbedtls_sha512_finish(&ctx->u.sha512, result);
239		mbedtls_sha512_free(&ctx->u.sha512);
240		break;
241	case LWS_GENHASH_TYPE_SHA512:
242		mbedtls_sha512_finish(&ctx->u.sha512, result);
243		mbedtls_sha512_free(&ctx->u.sha512);
244		break;
245	}
246
247	return 0;
248}
249
250#endif
251
252int
253lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
254		 const uint8_t *key, size_t key_len)
255{
256	int t;
257
258	ctx->type = (uint8_t)type;
259
260	switch (type) {
261	case LWS_GENHMAC_TYPE_SHA256:
262		t = MBEDTLS_MD_SHA256;
263		break;
264	case LWS_GENHMAC_TYPE_SHA384:
265		t = MBEDTLS_MD_SHA384;
266		break;
267	case LWS_GENHMAC_TYPE_SHA512:
268		t = MBEDTLS_MD_SHA512;
269		break;
270	default:
271		return -1;
272	}
273
274	ctx->hmac = mbedtls_md_info_from_type((mbedtls_md_type_t)t);
275	if (!ctx->hmac)
276		return -1;
277
278#if !defined(LWS_HAVE_mbedtls_md_setup)
279	if (mbedtls_md_init_ctx(&ctx->ctx, ctx->hmac))
280		return -1;
281#else
282	if (mbedtls_md_setup(&ctx->ctx, ctx->hmac, 1))
283		return -1;
284#endif
285
286	if (mbedtls_md_hmac_starts(&ctx->ctx, key, key_len)) {
287		mbedtls_md_free(&ctx->ctx);
288		ctx->hmac = NULL;
289
290		return -1;
291	}
292
293	return 0;
294}
295
296int
297lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len)
298{
299	if (!len)
300		return 0;
301
302	if (mbedtls_md_hmac_update(&ctx->ctx, in, len))
303		return -1;
304
305	return 0;
306}
307
308int
309lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result)
310{
311	int n = 0;
312
313	if (result)
314		n = mbedtls_md_hmac_finish(&ctx->ctx, result);
315
316	mbedtls_md_free(&ctx->ctx);
317	ctx->hmac = NULL;
318	if (n)
319		return -1;
320
321	return 0;
322}
323