• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <private-lib-core.h>
28 #include <openssl/obj_mac.h>
29 #include <openssl/opensslv.h>
30 /*
31  * Care: many openssl apis return 1 for success.  These are translated to the
32  * lws convention of 0 for success.
33  */
34 
35 int
lws_genhash_init(struct lws_genhash_ctx * ctx,enum lws_genhash_types type)36 lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type)
37 {
38 	ctx->type = (uint8_t)type;
39 	ctx->mdctx = EVP_MD_CTX_create();
40 	if (!ctx->mdctx)
41 		return 1;
42 
43 	switch (ctx->type) {
44 	case LWS_GENHASH_TYPE_MD5:
45 		ctx->evp_type = EVP_md5();
46 		break;
47 	case LWS_GENHASH_TYPE_SHA1:
48 		ctx->evp_type = EVP_sha1();
49 		break;
50 	case LWS_GENHASH_TYPE_SHA256:
51 		ctx->evp_type = EVP_sha256();
52 		break;
53 	case LWS_GENHASH_TYPE_SHA384:
54 		ctx->evp_type = EVP_sha384();
55 		break;
56 	case LWS_GENHASH_TYPE_SHA512:
57 		ctx->evp_type = EVP_sha512();
58 		break;
59 	default:
60 		return 1;
61 	}
62 
63 	if (EVP_DigestInit_ex(ctx->mdctx, ctx->evp_type, NULL) != 1) {
64 		EVP_MD_CTX_destroy(ctx->mdctx);
65 
66 		return 1;
67 	}
68 
69 	return 0;
70 }
71 
72 int
lws_genhash_update(struct lws_genhash_ctx * ctx,const void * in,size_t len)73 lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len)
74 {
75 	if (!len)
76 		return 0;
77 
78 	return EVP_DigestUpdate(ctx->mdctx, in, len) != 1;
79 }
80 
81 int
lws_genhash_destroy(struct lws_genhash_ctx * ctx,void * result)82 lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result)
83 {
84 	unsigned int len;
85 	int ret = 0;
86 
87 	if (!ctx->mdctx)
88 		return 0;
89 
90 	if (result)
91 		ret = EVP_DigestFinal_ex(ctx->mdctx, result, &len) != 1;
92 
93 	(void)len;
94 
95 	EVP_MD_CTX_destroy(ctx->mdctx);
96 	ctx->mdctx = NULL;
97 
98 	return ret;
99 }
100 
101 #if defined(LWS_HAVE_EVP_PKEY_new_raw_private_key)
102 
103 int
lws_genhmac_init(struct lws_genhmac_ctx * ctx,enum lws_genhmac_types type,const uint8_t * key,size_t key_len)104 lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
105 		 const uint8_t *key, size_t key_len)
106 {
107 	ctx->ctx = EVP_MD_CTX_create();
108 	if (!ctx->ctx)
109 		return -1;
110 
111 	ctx->evp_type = 0;
112 	ctx->type = (uint8_t)type;
113 
114 	switch (type) {
115 	case LWS_GENHMAC_TYPE_SHA256:
116 		ctx->evp_type = EVP_sha256();
117 		break;
118 	case LWS_GENHMAC_TYPE_SHA384:
119 		ctx->evp_type = EVP_sha384();
120 		break;
121 	case LWS_GENHMAC_TYPE_SHA512:
122 		ctx->evp_type = EVP_sha512();
123 		break;
124 	default:
125 		lwsl_err("%s: unknown HMAC type %d\n", __func__, type);
126 		goto bail;
127 	}
128 
129 	ctx->key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, key, key_len);
130 	if (!ctx->key)
131 		goto bail;
132 
133 	if (EVP_DigestSignInit(ctx->ctx, NULL, ctx->evp_type, NULL, ctx->key) != 1)
134 		goto bail1;
135 
136 	return 0;
137 
138 bail1:
139 	EVP_PKEY_free(ctx->key);
140 bail:
141 	EVP_MD_CTX_free(ctx->ctx);
142 
143 	return -1;
144 }
145 
146 int
lws_genhmac_update(struct lws_genhmac_ctx * ctx,const void * in,size_t len)147 lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len)
148 {
149 
150 	if (EVP_DigestSignUpdate(ctx->ctx, in, len) != 1)
151 		return -1;
152 
153 	return 0;
154 }
155 
156 int
lws_genhmac_destroy(struct lws_genhmac_ctx * ctx,void * result)157 lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result)
158 {
159 	size_t size = (size_t)lws_genhmac_size(ctx->type);
160 	int n;
161 
162 	n = EVP_DigestSignFinal(ctx->ctx, result, &size);
163 	EVP_MD_CTX_free(ctx->ctx);
164 	EVP_PKEY_free(ctx->key);
165 
166 	if (n != 1)
167 		return -1;
168 
169 	return 0;
170 }
171 
172 #else
173 
174 int
lws_genhmac_init(struct lws_genhmac_ctx * ctx,enum lws_genhmac_types type,const uint8_t * key,size_t key_len)175 lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
176 		 const uint8_t *key, size_t key_len)
177 {
178 #if defined(LWS_HAVE_HMAC_CTX_new)
179 	ctx->ctx = HMAC_CTX_new();
180 	if (!ctx->ctx)
181 		return -1;
182 #else
183 	HMAC_CTX_init(&ctx->ctx);
184 #endif
185 
186 	ctx->evp_type = 0;
187 	ctx->type = (uint8_t)type;
188 
189 	switch (type) {
190 	case LWS_GENHMAC_TYPE_SHA256:
191 		ctx->evp_type = EVP_sha256();
192 		break;
193 	case LWS_GENHMAC_TYPE_SHA384:
194 		ctx->evp_type = EVP_sha384();
195 		break;
196 	case LWS_GENHMAC_TYPE_SHA512:
197 		ctx->evp_type = EVP_sha512();
198 		break;
199 	default:
200 		lwsl_err("%s: unknown HMAC type %d\n", __func__, type);
201 		goto bail;
202 	}
203 
204 #if defined(LWS_HAVE_HMAC_CTX_new)
205         if (HMAC_Init_ex(ctx->ctx, key, (int)key_len, ctx->evp_type, NULL) != 1)
206 #else
207         if (HMAC_Init_ex(&ctx->ctx, key, (int)key_len, ctx->evp_type, NULL) != 1)
208 #endif
209         	goto bail;
210 
211 	return 0;
212 
213 bail:
214 #if defined(LWS_HAVE_HMAC_CTX_new)
215 	HMAC_CTX_free(ctx->ctx);
216 #endif
217 
218 	return -1;
219 }
220 
221 int
lws_genhmac_update(struct lws_genhmac_ctx * ctx,const void * in,size_t len)222 lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len)
223 {
224 #if defined(LWS_HAVE_HMAC_CTX_new)
225 #if defined(LIBRESSL_VERSION_NUMBER)
226 	if (HMAC_Update(ctx->ctx, in, len) != 1)
227 #else
228 	if (HMAC_Update(ctx->ctx, in, (int)len) != 1)
229 #endif
230 #else /* HMAC_CTX_new */
231 	if (HMAC_Update(&ctx->ctx, in, len) != 1)
232 #endif
233 		return -1;
234 
235 	return 0;
236 }
237 
238 int
lws_genhmac_destroy(struct lws_genhmac_ctx * ctx,void * result)239 lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result)
240 {
241 	unsigned int size = (unsigned int)lws_genhmac_size(ctx->type);
242 #if defined(LWS_HAVE_HMAC_CTX_new)
243 	int n = HMAC_Final(ctx->ctx, result, &size);
244 
245 	HMAC_CTX_free(ctx->ctx);
246 #else
247 	int n = HMAC_Final(&ctx->ctx, result, &size);
248 #endif
249 
250 	if (n != 1)
251 		return -1;
252 
253 	return 0;
254 }
255 
256 
257 #endif
258