• 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_genaes provides an AES 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 "private-lib-jose.h"
29 
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_genaes_create(struct lws_genaes_ctx * ctx,enum enum_aes_operation op,enum enum_aes_modes mode,struct lws_gencrypto_keyelem * el,enum enum_aes_padding padding,void * engine)36 lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op,
37 		  enum enum_aes_modes mode, struct lws_gencrypto_keyelem *el,
38 		  enum enum_aes_padding padding, void *engine)
39 {
40 	int n = 0;
41 
42 	ctx->ctx = EVP_CIPHER_CTX_new();
43 	if (!ctx->ctx)
44 		return -1;
45 
46 	ctx->mode = mode;
47 	ctx->k = el;
48 	ctx->engine = engine;
49 	ctx->init = 0;
50 	ctx->op = op;
51 	ctx->padding = padding;
52 
53 	switch (ctx->k->len) {
54 	case 128 / 8:
55 		switch (mode) {
56 		case LWS_GAESM_KW:
57 #if defined(LWS_HAVE_EVP_aes_128_wrap)
58 			EVP_CIPHER_CTX_set_flags(ctx->ctx,
59 						EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
60 			ctx->cipher = EVP_aes_128_wrap();
61 			break;
62 #else
63 			lwsl_err("%s: your OpenSSL lacks AES wrap apis, update it\n",
64 				 __func__);
65 			return -1;
66 #endif
67 		case LWS_GAESM_CBC:
68 			ctx->cipher = EVP_aes_128_cbc();
69 			break;
70 #if defined(LWS_HAVE_EVP_aes_128_cfb128)
71 		case LWS_GAESM_CFB128:
72 			ctx->cipher = EVP_aes_128_cfb128();
73 			break;
74 #endif
75 #if defined(LWS_HAVE_EVP_aes_128_cfb8)
76 		case LWS_GAESM_CFB8:
77 			ctx->cipher = EVP_aes_128_cfb8();
78 			break;
79 #endif
80 		case LWS_GAESM_CTR:
81 			ctx->cipher = EVP_aes_128_ctr();
82 			break;
83 		case LWS_GAESM_ECB:
84 			ctx->cipher = EVP_aes_128_ecb();
85 			break;
86 		case LWS_GAESM_OFB:
87 			ctx->cipher = EVP_aes_128_ofb();
88 			break;
89 		case LWS_GAESM_XTS:
90 			lwsl_err("%s: AES XTS requires double-length key\n",
91 				 __func__);
92 			break;
93 		case LWS_GAESM_GCM:
94 			ctx->cipher = EVP_aes_128_gcm();
95 			break;
96 		default:
97 			goto bail;
98 		}
99 		break;
100 
101 	case 192 / 8:
102 		switch (mode) {
103 		case LWS_GAESM_KW:
104 #if defined(LWS_HAVE_EVP_aes_128_wrap)
105 			EVP_CIPHER_CTX_set_flags(ctx->ctx,
106 						EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
107 			ctx->cipher = EVP_aes_192_wrap();
108 			break;
109 #else
110                         lwsl_err("%s: your OpenSSL lacks AES wrap apis, update it\n",
111                                  __func__);
112                         return -1;
113 #endif
114 		case LWS_GAESM_CBC:
115 			ctx->cipher = EVP_aes_192_cbc();
116 			break;
117 #if defined(LWS_HAVE_EVP_aes_192_cfb128)
118 		case LWS_GAESM_CFB128:
119 			ctx->cipher = EVP_aes_192_cfb128();
120 			break;
121 #endif
122 #if defined(LWS_HAVE_EVP_aes_192_cfb8)
123 		case LWS_GAESM_CFB8:
124 			ctx->cipher = EVP_aes_192_cfb8();
125 			break;
126 #endif
127 		case LWS_GAESM_CTR:
128 			ctx->cipher = EVP_aes_192_ctr();
129 			break;
130 		case LWS_GAESM_ECB:
131 			ctx->cipher = EVP_aes_192_ecb();
132 			break;
133 		case LWS_GAESM_OFB:
134 			ctx->cipher = EVP_aes_192_ofb();
135 			break;
136 		case LWS_GAESM_XTS:
137 			lwsl_err("%s: AES XTS 192 invalid\n", __func__);
138 			goto bail;
139 		case LWS_GAESM_GCM:
140 			ctx->cipher = EVP_aes_192_gcm();
141 			break;
142 		default:
143 			goto bail;
144 		}
145 		break;
146 
147 	case 256 / 8:
148 		switch (mode) {
149 		case LWS_GAESM_KW:
150 #if defined(LWS_HAVE_EVP_aes_128_wrap)
151 			EVP_CIPHER_CTX_set_flags(ctx->ctx,
152 						EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
153 			ctx->cipher = EVP_aes_256_wrap();
154 			break;
155 #else
156                         lwsl_err("%s: your OpenSSL lacks AES wrap apis, update it\n",
157                                  __func__);
158                         return -1;
159 #endif
160 		case LWS_GAESM_CBC:
161 			ctx->cipher = EVP_aes_256_cbc();
162 			break;
163 #if defined(LWS_HAVE_EVP_aes_256_cfb128)
164 		case LWS_GAESM_CFB128:
165 			ctx->cipher = EVP_aes_256_cfb128();
166 			break;
167 #endif
168 #if defined(LWS_HAVE_EVP_aes_256_cfb8)
169 		case LWS_GAESM_CFB8:
170 			ctx->cipher = EVP_aes_256_cfb8();
171 			break;
172 #endif
173 		case LWS_GAESM_CTR:
174 			ctx->cipher = EVP_aes_256_ctr();
175 			break;
176 		case LWS_GAESM_ECB:
177 			ctx->cipher = EVP_aes_256_ecb();
178 			break;
179 		case LWS_GAESM_OFB:
180 			ctx->cipher = EVP_aes_256_ofb();
181 			break;
182 #if defined(LWS_HAVE_EVP_aes_128_xts)
183 		case LWS_GAESM_XTS:
184 			ctx->cipher = EVP_aes_128_xts();
185 			break;
186 #endif
187 		case LWS_GAESM_GCM:
188 			ctx->cipher = EVP_aes_256_gcm();
189 			break;
190 		default:
191 			goto bail;
192 		}
193 		break;
194 
195 	case 512 / 8:
196 		switch (mode) {
197 		case LWS_GAESM_XTS:
198 			ctx->cipher = EVP_aes_256_xts();
199 			break;
200 		default:
201 			goto bail;
202 		}
203 	break;
204 
205 	default:
206 		lwsl_err("%s: unsupported AES size %d bits\n", __func__,
207 			 ctx->k->len * 8);
208 		goto bail;
209 	}
210 
211 	switch (ctx->op) {
212 	case LWS_GAESO_ENC:
213 		n = EVP_EncryptInit_ex(ctx->ctx, ctx->cipher, ctx->engine,
214 				       NULL, NULL);
215 		EVP_CIPHER_CTX_set_padding(ctx->ctx, padding);
216 		break;
217 	case LWS_GAESO_DEC:
218 		n = EVP_DecryptInit_ex(ctx->ctx, ctx->cipher, ctx->engine,
219 				       NULL, NULL);
220 		EVP_CIPHER_CTX_set_padding(ctx->ctx, padding);
221 		break;
222 	}
223 	if (!n) {
224 		lwsl_err("%s: cipher init failed (cipher %p)\n", __func__,
225 			 ctx->cipher);
226 		lws_tls_err_describe_clear();
227 		goto bail;
228 	}
229 
230 	return 0;
231 bail:
232 	EVP_CIPHER_CTX_free(ctx->ctx);
233 	ctx->ctx = NULL;
234 	return -1;
235 }
236 
237 int
lws_genaes_destroy(struct lws_genaes_ctx * ctx,unsigned char * tag,size_t tlen)238 lws_genaes_destroy(struct lws_genaes_ctx *ctx, unsigned char *tag, size_t tlen)
239 {
240 	uint8_t buf[256];
241 	int outl = sizeof(buf), n = 0;
242 
243 	if (!ctx->ctx)
244 		return 0;
245 
246 	if (ctx->init) {
247 		switch (ctx->op) {
248 		case LWS_GAESO_ENC:
249 
250 			if (EVP_EncryptFinal_ex(ctx->ctx, buf, &outl) != 1) {
251 				lwsl_err("%s: enc final failed\n", __func__);
252 				n = -1;
253 			}
254 
255 			if (ctx->mode == LWS_GAESM_GCM) {
256 				if (EVP_CIPHER_CTX_ctrl(ctx->ctx,
257 						EVP_CTRL_GCM_GET_TAG,
258 						    ctx->taglen, tag) != 1) {
259 					lwsl_err("get tag ctrl failed\n");
260 					//lws_tls_err_describe_clear();
261 					n = 1;
262 				}
263 			}
264 			if (ctx->mode == LWS_GAESM_CBC)
265 				memcpy(tag, buf, outl);
266 
267 			break;
268 
269 		case LWS_GAESO_DEC:
270 			if (EVP_DecryptFinal_ex(ctx->ctx, buf, &outl) != 1) {
271 				lwsl_err("%s: dec final failed\n", __func__);
272 				lws_tls_err_describe_clear();
273 				n = -1;
274 			}
275 
276 			break;
277 		}
278 		if (outl)
279 			lwsl_debug("%s: final len %d\n", __func__, outl);
280 	}
281 
282 	ctx->k = NULL;
283 	EVP_CIPHER_CTX_free(ctx->ctx);
284 	ctx->ctx = NULL;
285 
286 	return n;
287 }
288 
289 int
lws_genaes_crypt(struct lws_genaes_ctx * ctx,const uint8_t * in,size_t len,uint8_t * out,uint8_t * iv_or_nonce_ctr_or_data_unit_16,uint8_t * stream_block_16,size_t * nc_or_iv_off,int taglen)290 lws_genaes_crypt(struct lws_genaes_ctx *ctx,
291 		 const uint8_t *in, size_t len, uint8_t *out,
292 		 uint8_t *iv_or_nonce_ctr_or_data_unit_16,
293 		 uint8_t *stream_block_16, size_t *nc_or_iv_off, int taglen)
294 {
295 	int n = 0, outl, olen;
296 
297 	if (!ctx->init) {
298 
299 		EVP_CIPHER_CTX_set_key_length(ctx->ctx, ctx->k->len);
300 
301 		if (ctx->mode == LWS_GAESM_GCM) {
302 			n = EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_SET_IVLEN,
303 					   (int)*nc_or_iv_off, NULL);
304 			if (n != 1) {
305 				lwsl_err("%s: SET_IVLEN failed\n", __func__);
306 				return -1;
307 			}
308 			memcpy(ctx->tag, stream_block_16, taglen);
309 			ctx->taglen = taglen;
310 		}
311 
312 		switch (ctx->op) {
313 		case LWS_GAESO_ENC:
314 			n = EVP_EncryptInit_ex(ctx->ctx, NULL, NULL,
315 					       ctx->k->buf,
316 					       iv_or_nonce_ctr_or_data_unit_16);
317 			break;
318 		case LWS_GAESO_DEC:
319 			if (ctx->mode == LWS_GAESM_GCM)
320 				EVP_CIPHER_CTX_ctrl(ctx->ctx,
321 						    EVP_CTRL_GCM_SET_TAG,
322 						    ctx->taglen, ctx->tag);
323 			n = EVP_DecryptInit_ex(ctx->ctx, NULL, NULL,
324 					       ctx->k->buf,
325 					       iv_or_nonce_ctr_or_data_unit_16);
326 			break;
327 		}
328 
329 		if (!n) {
330 			lws_tls_err_describe_clear();
331 			lwsl_err("%s: init failed (cipher %p)\n",
332 				 __func__, ctx->cipher);
333 
334 			return -1;
335 		}
336 		ctx->init = 1;
337 	}
338 
339 	if (ctx->mode == LWS_GAESM_GCM && !out) {
340 		/* AAD */
341 
342 		if (!len)
343 			return 0;
344 
345 		switch (ctx->op) {
346 		case LWS_GAESO_ENC:
347 			n = EVP_EncryptUpdate(ctx->ctx, NULL, &olen, in, (int)len);
348 			break;
349 		case LWS_GAESO_DEC:
350 			n = EVP_DecryptUpdate(ctx->ctx, NULL, &olen, in, (int)len);
351 			break;
352 		default:
353 			return -1;
354 		}
355 		if (n != 1) {
356 			lwsl_err("%s: set AAD failed\n",  __func__);
357 			lws_tls_err_describe_clear();
358 			lwsl_hexdump_err(in, len);
359 			return -1;
360 		}
361 
362 		return 0;
363 	}
364 
365 	switch (ctx->op) {
366 	case LWS_GAESO_ENC:
367 		n = EVP_EncryptUpdate(ctx->ctx, out, &outl, in, (int)len);
368 		break;
369 	case LWS_GAESO_DEC:
370 		n = EVP_DecryptUpdate(ctx->ctx, out, &outl, in, (int)len);
371 		break;
372 	default:
373 		return -1;
374 	}
375 
376 	// lwsl_notice("discarding outl %d\n", (int)outl);
377 
378 	if (!n) {
379 		lwsl_notice("%s: update failed\n", __func__);
380 		lws_tls_err_describe_clear();
381 
382 		return -1;
383 	}
384 
385 	return 0;
386 }
387