• 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 abstraction api for AES 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 static int operation_map[] = { MBEDTLS_AES_ENCRYPT, MBEDTLS_AES_DECRYPT };
31 
32 static unsigned int
_write_pkcs7_pad(uint8_t * p,int len)33 _write_pkcs7_pad(uint8_t *p, int len)
34 {
35 	unsigned int n = 0, padlen = LWS_AES_CBC_BLOCKLEN * (len /
36 					LWS_AES_CBC_BLOCKLEN + 1) - len;
37 
38 	p += len;
39 
40 	while (n++ < padlen)
41 		*p++ = (uint8_t)padlen;
42 
43 	return padlen;
44 }
45 
46 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)47 lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op,
48 		  enum enum_aes_modes mode, struct lws_gencrypto_keyelem *el,
49 		  enum enum_aes_padding padding, void *engine)
50 {
51 	int n = 0;
52 
53 	ctx->mode = mode;
54 	ctx->k = el;
55 	ctx->op = operation_map[op];
56 	ctx->underway = 0;
57 	ctx->padding = padding == LWS_GAESP_WITH_PADDING;
58 
59 	switch (ctx->mode) {
60 	case LWS_GAESM_XTS:
61 #if defined(MBEDTLS_CIPHER_MODE_XTS)
62 		mbedtls_aes_xts_init(&ctx->u.ctx_xts);
63 		break;
64 #else
65 		return -1;
66 #endif
67 	case LWS_GAESM_GCM:
68 		mbedtls_gcm_init(&ctx->u.ctx_gcm);
69 		n = mbedtls_gcm_setkey(&ctx->u.ctx_gcm, MBEDTLS_CIPHER_ID_AES,
70 				       ctx->k->buf, ctx->k->len * 8);
71 		if (n) {
72 			lwsl_notice("%s: mbedtls_gcm_setkey: -0x%x\n",
73 				    __func__, -n);
74 			return n;
75 		}
76 		return n;
77 	default:
78 		mbedtls_aes_init(&ctx->u.ctx);
79 		break;
80 	}
81 
82 	switch (op) {
83 	case LWS_GAESO_ENC:
84 		if (ctx->mode == LWS_GAESM_XTS)
85 #if defined(MBEDTLS_CIPHER_MODE_XTS)
86 			n = mbedtls_aes_xts_setkey_enc(&ctx->u.ctx_xts,
87 						       ctx->k->buf,
88 						       ctx->k->len * 8);
89 #else
90 			return -1;
91 #endif
92 		else
93 			n = mbedtls_aes_setkey_enc(&ctx->u.ctx, ctx->k->buf,
94 						   ctx->k->len * 8);
95 		break;
96 	case LWS_GAESO_DEC:
97 		switch (ctx->mode) {
98 		case LWS_GAESM_XTS:
99 #if defined(MBEDTLS_CIPHER_MODE_XTS)
100 			n = mbedtls_aes_xts_setkey_dec(&ctx->u.ctx_xts,
101 						       ctx->k->buf,
102 						       ctx->k->len * 8);
103 			break;
104 #else
105 			return -1;
106 #endif
107 
108 		case LWS_GAESM_CFB128:
109 		case LWS_GAESM_CFB8:
110 		case LWS_GAESM_CTR:
111 		case LWS_GAESM_OFB:
112 			n = mbedtls_aes_setkey_enc(&ctx->u.ctx, ctx->k->buf,
113 						   ctx->k->len * 8);
114 			break;
115 		default:
116 			n = mbedtls_aes_setkey_dec(&ctx->u.ctx, ctx->k->buf,
117 						   ctx->k->len * 8);
118 			break;
119 		}
120 		break;
121 	}
122 
123 	if (n)
124 		lwsl_notice("%s: setting key: -0x%x\n", __func__, -n);
125 
126 	return n;
127 }
128 
129 int
lws_genaes_destroy(struct lws_genaes_ctx * ctx,unsigned char * tag,size_t tlen)130 lws_genaes_destroy(struct lws_genaes_ctx *ctx, unsigned char *tag, size_t tlen)
131 {
132 	int n;
133 
134 	if (ctx->mode == LWS_GAESM_GCM) {
135 		n = mbedtls_gcm_finish(&ctx->u.ctx_gcm, tag, tlen);
136 		if (n)
137 			lwsl_notice("%s: mbedtls_gcm_finish: -0x%x\n",
138 				    __func__, -n);
139 		if (tag && ctx->op == MBEDTLS_AES_DECRYPT && !n) {
140 			if (lws_timingsafe_bcmp(ctx->tag, tag, ctx->taglen)) {
141 				lwsl_err("%s: lws_genaes_crypt tag "
142 					 "mismatch (bad first)\n",
143 						__func__);
144 				lwsl_hexdump_notice(tag, tlen);
145 				lwsl_hexdump_notice(ctx->tag, ctx->taglen);
146 				n = -1;
147 			}
148 		}
149 		mbedtls_gcm_free(&ctx->u.ctx_gcm);
150 		return n;
151 	}
152 	if (ctx->mode == LWS_GAESM_XTS)
153 #if defined(MBEDTLS_CIPHER_MODE_XTS)
154 		mbedtls_aes_xts_free(&ctx->u.ctx_xts);
155 #else
156 		return -1;
157 #endif
158 	else
159 		mbedtls_aes_free(&ctx->u.ctx);
160 
161 	return 0;
162 }
163 
164 static int
lws_genaes_rfc3394_wrap(int wrap,int cek_bits,const uint8_t * kek,int kek_bits,const uint8_t * in,uint8_t * out)165 lws_genaes_rfc3394_wrap(int wrap, int cek_bits, const uint8_t *kek,
166 			int kek_bits, const uint8_t *in, uint8_t *out)
167 {
168 	int n, m, ret = -1, c64 = cek_bits / 64;
169 	mbedtls_aes_context ctx;
170 	uint8_t a[8], b[16];
171 
172 	/*
173 	 * notice the KEK key used to perform the wrapping or unwrapping is
174 	 * always the size of the AES key used, eg, A128KW == 128 bits.  The
175 	 * key being wrapped or unwrapped may be larger and is set by the
176 	 * 'bits' parameter.
177 	 *
178 	 * If it's larger than the KEK key size bits, we iterate over it
179 	 */
180 
181 	mbedtls_aes_init(&ctx);
182 
183 	if (wrap) {
184 		/*
185 		 * The inputs to the key wrapping process are the KEK and the
186 		 * plaintext to be wrapped.  The plaintext consists of n 64-bit
187 		 * blocks, containing the key data being wrapped.
188 		 *
189 		 * Inputs:      Plaintext, n 64-bit values {P1, P2, ..., Pn},
190 		 *		and Key, K (the KEK).
191 		 * Outputs:     Ciphertext, (n+1) 64-bit values
192 		 *		{C0, C1, ..., Cn}.
193 		 *
194 		 * The default initial value (IV) is defined to be the
195 		 * hexadecimal constant:
196 		 *
197 		 * A[0] = IV = A6A6A6A6A6A6A6A6
198 		 */
199 		memset(out, 0xa6, 8);
200 		memcpy(out + 8, in, 8 * c64);
201 		n = mbedtls_aes_setkey_enc(&ctx, kek, kek_bits);
202 	} else {
203 		/*
204 		 * 2.2.2 Key Unwrap
205 		 *
206 		 * The inputs to the unwrap process are the KEK and (n+1)
207 		 * 64-bit blocks of ciphertext consisting of previously
208 		 * wrapped key.  It returns n blocks of plaintext consisting
209 		 * of the n 64-bit blocks of the decrypted key data.
210 		 *
211 		 * Inputs:  Ciphertext, (n+1) 64-bit values {C0, C1, ..., Cn},
212 		 * and Key, K (the KEK).
213 		 *
214 		 * Outputs: Plaintext, n 64-bit values {P1, P2, ..., Pn}.
215 		 */
216 		memcpy(a, in, 8);
217 		memcpy(out, in + 8, 8 * c64);
218 		n = mbedtls_aes_setkey_dec(&ctx, kek, kek_bits);
219 	}
220 
221 	if (n < 0) {
222 		lwsl_err("%s: setkey failed\n", __func__);
223 		goto bail;
224 	}
225 
226 	if (wrap) {
227 		for (n = 0; n <= 5; n++) {
228 			uint8_t *r = out + 8;
229 			for (m = 1; m <= c64; m++) {
230 				memcpy(b, out, 8);
231 				memcpy(b + 8, r, 8);
232 				if (mbedtls_internal_aes_encrypt(&ctx, b, b))
233 					goto bail;
234 
235 				memcpy(out, b, 8);
236 				out[7] ^= c64 * n + m;
237 				memcpy(r, b + 8, 8);
238 				r += 8;
239 			}
240 		}
241 		ret = 0;
242 	} else {
243 		/*
244 		 *
245 		 */
246 		for (n = 5; n >= 0; n--) {
247 			uint8_t *r = out + (c64 - 1) * 8;
248 			for (m = c64; m >= 1; m--) {
249 				memcpy(b, a, 8);
250 				b[7] ^= c64 * n + m;
251 				memcpy(b + 8, r, 8);
252 				if (mbedtls_internal_aes_decrypt(&ctx, b, b))
253 					goto bail;
254 
255 				memcpy(a, b, 8);
256 				memcpy(r, b + 8, 8);
257 				r -= 8;
258 			}
259 		}
260 
261 		ret = 0;
262 		for (n = 0; n < 8; n++)
263 			if (a[n] != 0xa6)
264 				ret = -1;
265 	}
266 
267 bail:
268 	if (ret)
269 		lwsl_notice("%s: failed\n", __func__);
270 	mbedtls_aes_free(&ctx);
271 
272 	return ret;
273 }
274 
275 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)276 lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len,
277 		 uint8_t *out, uint8_t *iv_or_nonce_ctr_or_data_unit_16,
278 		 uint8_t *stream_block_16, size_t *nc_or_iv_off, int taglen)
279 {
280 	uint8_t iv[LWS_JWE_AES_IV_BYTES], sb[16];
281 	int n = 0;
282 
283 	switch (ctx->mode) {
284 	case LWS_GAESM_KW:
285 		/* a key of length ctx->k->len is wrapped by a 128-bit KEK */
286 		n = lws_genaes_rfc3394_wrap(ctx->op == MBEDTLS_AES_ENCRYPT,
287 				ctx->op == MBEDTLS_AES_ENCRYPT ? len * 8 :
288 						(len - 8) * 8, ctx->k->buf,
289 						ctx->k->len * 8,
290 				in, out);
291 		break;
292 	case LWS_GAESM_CBC:
293 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
294 
295 		/*
296 		 * If encrypting, we do the PKCS#7 padding.
297 		 * During decryption, the caller will need to unpad.
298 		 */
299 		if (ctx->padding && ctx->op == MBEDTLS_AES_ENCRYPT) {
300 			/*
301 			 * Since we don't want to burden the caller with
302 			 * the over-allocation at the end of the input,
303 			 * we have to allocate a temp with space for it
304 			 */
305 			uint8_t *padin = (uint8_t *)lws_malloc(
306 				lws_gencrypto_padded_length(LWS_AES_CBC_BLOCKLEN, len),
307 								__func__);
308 
309 			if (!padin)
310 				return -1;
311 
312 			memcpy(padin, in, len);
313 			len += _write_pkcs7_pad((uint8_t *)padin, len);
314 			n = mbedtls_aes_crypt_cbc(&ctx->u.ctx, ctx->op, len, iv,
315 						  padin, out);
316 			lws_free(padin);
317 		} else
318 			n = mbedtls_aes_crypt_cbc(&ctx->u.ctx, ctx->op, len, iv,
319                                       in, out);
320 
321 		break;
322 
323 	case LWS_GAESM_CFB128:
324 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
325 		n = mbedtls_aes_crypt_cfb128(&ctx->u.ctx, ctx->op, len,
326 					     nc_or_iv_off, iv, in, out);
327 		break;
328 
329 	case LWS_GAESM_CFB8:
330 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
331 		n = mbedtls_aes_crypt_cfb8(&ctx->u.ctx, ctx->op, len, iv,
332 					   in, out);
333 		break;
334 
335 	case LWS_GAESM_CTR:
336 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
337 		memcpy(sb, stream_block_16, 16);
338 		n = mbedtls_aes_crypt_ctr(&ctx->u.ctx, len, nc_or_iv_off,
339 					  iv, sb, in, out);
340 		memcpy(iv_or_nonce_ctr_or_data_unit_16, iv, 16);
341 		memcpy(stream_block_16, sb, 16);
342 		break;
343 
344 	case LWS_GAESM_ECB:
345 		n = mbedtls_aes_crypt_ecb(&ctx->u.ctx, ctx->op, in, out);
346 		break;
347 
348 	case LWS_GAESM_OFB:
349 #if defined(MBEDTLS_CIPHER_MODE_OFB)
350 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
351 		n = mbedtls_aes_crypt_ofb(&ctx->u.ctx, len, nc_or_iv_off, iv,
352 					  in, out);
353 		break;
354 #else
355 		return -1;
356 #endif
357 
358 	case LWS_GAESM_XTS:
359 #if defined(MBEDTLS_CIPHER_MODE_XTS)
360 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
361 		n = mbedtls_aes_crypt_xts(&ctx->u.ctx_xts, ctx->op, len, iv,
362 					  in, out);
363 		break;
364 #else
365 		return -1;
366 #endif
367 	case LWS_GAESM_GCM:
368 		if (!ctx->underway) {
369 			ctx->underway = 1;
370 
371 			memcpy(ctx->tag, stream_block_16, taglen);
372 			ctx->taglen = taglen;
373 
374 			/*
375 			 * iv:                   iv_or_nonce_ctr_or_data_unit_16
376 			 * iv_len:               *nc_or_iv_off
377 			 * stream_block_16:      pointer to tag
378 			 * additional data:      in
379 			 * additional data len:  len
380 			 */
381 
382 			n = mbedtls_gcm_starts(&ctx->u.ctx_gcm, ctx->op,
383 					       iv_or_nonce_ctr_or_data_unit_16,
384 					       *nc_or_iv_off, in, len);
385 			if (n) {
386 				lwsl_notice("%s: mbedtls_gcm_starts: -0x%x\n",
387 					    __func__, -n);
388 
389 				return -1;
390 			}
391 			break;
392 		}
393 
394 		n = mbedtls_gcm_update(&ctx->u.ctx_gcm, len, in, out);
395 		if (n) {
396 			lwsl_notice("%s: mbedtls_gcm_update: -0x%x\n",
397 				    __func__, -n);
398 
399 			return -1;
400 		}
401 		break;
402 	}
403 
404 	if (n) {
405 		lwsl_notice("%s: failed: -0x%x, len %d\n", __func__, -n, (int)len);
406 
407 		return -1;
408 	}
409 
410 	return 0;
411 }
412