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 (MBEDTLS_VERSION_NUMBER >= 0x02070000)
31 #define MBA(fn) fn##_ret
32 #else
33 #define MBA(fn) fn
34 #endif
35
36 int
lws_genhash_init(struct lws_genhash_ctx * ctx,enum lws_genhash_types type)37 lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type)
38 {
39 ctx->type = type;
40
41 switch (ctx->type) {
42 case LWS_GENHASH_TYPE_MD5:
43 mbedtls_md5_init(&ctx->u.md5);
44 MBA(mbedtls_md5_starts)(&ctx->u.md5);
45 break;
46 case LWS_GENHASH_TYPE_SHA1:
47 mbedtls_sha1_init(&ctx->u.sha1);
48 MBA(mbedtls_sha1_starts)(&ctx->u.sha1);
49 break;
50 case LWS_GENHASH_TYPE_SHA256:
51 mbedtls_sha256_init(&ctx->u.sha256);
52 MBA(mbedtls_sha256_starts)(&ctx->u.sha256, 0);
53 break;
54 case LWS_GENHASH_TYPE_SHA384:
55 mbedtls_sha512_init(&ctx->u.sha512);
56 MBA(mbedtls_sha512_starts)(&ctx->u.sha512, 1 /* is384 */);
57 break;
58 case LWS_GENHASH_TYPE_SHA512:
59 mbedtls_sha512_init(&ctx->u.sha512);
60 MBA(mbedtls_sha512_starts)(&ctx->u.sha512, 0);
61 break;
62 default:
63 return 1;
64 }
65
66 return 0;
67 }
68
69 int
lws_genhash_update(struct lws_genhash_ctx * ctx,const void * in,size_t len)70 lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len)
71 {
72 if (!len)
73 return 0;
74
75 switch (ctx->type) {
76 case LWS_GENHASH_TYPE_MD5:
77 MBA(mbedtls_md5_update)(&ctx->u.md5, in, len);
78 break;
79 case LWS_GENHASH_TYPE_SHA1:
80 MBA(mbedtls_sha1_update)(&ctx->u.sha1, in, len);
81 break;
82 case LWS_GENHASH_TYPE_SHA256:
83 MBA(mbedtls_sha256_update)(&ctx->u.sha256, in, len);
84 break;
85 case LWS_GENHASH_TYPE_SHA384:
86 MBA(mbedtls_sha512_update)(&ctx->u.sha512, in, len);
87 break;
88 case LWS_GENHASH_TYPE_SHA512:
89 MBA(mbedtls_sha512_update)(&ctx->u.sha512, in, len);
90 break;
91 }
92
93 return 0;
94 }
95
96 int
lws_genhash_destroy(struct lws_genhash_ctx * ctx,void * result)97 lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result)
98 {
99 switch (ctx->type) {
100 case LWS_GENHASH_TYPE_MD5:
101 MBA(mbedtls_md5_finish)(&ctx->u.md5, result);
102 mbedtls_md5_free(&ctx->u.md5);
103 break;
104 case LWS_GENHASH_TYPE_SHA1:
105 MBA(mbedtls_sha1_finish)(&ctx->u.sha1, result);
106 mbedtls_sha1_free(&ctx->u.sha1);
107 break;
108 case LWS_GENHASH_TYPE_SHA256:
109 MBA(mbedtls_sha256_finish)(&ctx->u.sha256, result);
110 mbedtls_sha256_free(&ctx->u.sha256);
111 break;
112 case LWS_GENHASH_TYPE_SHA384:
113 MBA(mbedtls_sha512_finish)(&ctx->u.sha512, result);
114 mbedtls_sha512_free(&ctx->u.sha512);
115 break;
116 case LWS_GENHASH_TYPE_SHA512:
117 MBA(mbedtls_sha512_finish)(&ctx->u.sha512, result);
118 mbedtls_sha512_free(&ctx->u.sha512);
119 break;
120 }
121
122 return 0;
123 }
124
125 int
lws_genhmac_init(struct lws_genhmac_ctx * ctx,enum lws_genhmac_types type,const uint8_t * key,size_t key_len)126 lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
127 const uint8_t *key, size_t key_len)
128 {
129 int t;
130
131 ctx->type = type;
132
133 switch (type) {
134 case LWS_GENHMAC_TYPE_SHA256:
135 t = MBEDTLS_MD_SHA256;
136 break;
137 case LWS_GENHMAC_TYPE_SHA384:
138 t = MBEDTLS_MD_SHA384;
139 break;
140 case LWS_GENHMAC_TYPE_SHA512:
141 t = MBEDTLS_MD_SHA512;
142 break;
143 default:
144 return -1;
145 }
146
147 ctx->hmac = mbedtls_md_info_from_type(t);
148 if (!ctx->hmac)
149 return -1;
150
151 if (mbedtls_md_init_ctx(&ctx->ctx, ctx->hmac))
152 return -1;
153
154 if (mbedtls_md_hmac_starts(&ctx->ctx, key, key_len)) {
155 mbedtls_md_free(&ctx->ctx);
156 ctx->hmac = NULL;
157
158 return -1;
159 }
160
161 return 0;
162 }
163
164 int
lws_genhmac_update(struct lws_genhmac_ctx * ctx,const void * in,size_t len)165 lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len)
166 {
167 if (!len)
168 return 0;
169
170 if (mbedtls_md_hmac_update(&ctx->ctx, in, len))
171 return -1;
172
173 return 0;
174 }
175
176 int
lws_genhmac_destroy(struct lws_genhmac_ctx * ctx,void * result)177 lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result)
178 {
179 int n = 0;
180
181 if (result)
182 n = mbedtls_md_hmac_finish(&ctx->ctx, result);
183
184 mbedtls_md_free(&ctx->ctx);
185 ctx->hmac = NULL;
186 if (n)
187 return -1;
188
189 return 0;
190 }
191