xref: /aosp_15_r20/external/libwebsockets/lib/tls/mbedtls/lws-genaes.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker  /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  *
24*1c60b9acSAndroid Build Coastguard Worker  *  lws_genaes provides an abstraction api for AES in lws that works the
25*1c60b9acSAndroid Build Coastguard Worker  *  same whether you are using openssl or mbedtls hash functions underneath.
26*1c60b9acSAndroid Build Coastguard Worker  */
27*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
28*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_JOSE)
29*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-jose.h"
30*1c60b9acSAndroid Build Coastguard Worker #endif
31*1c60b9acSAndroid Build Coastguard Worker 
32*1c60b9acSAndroid Build Coastguard Worker static int operation_map[] = { MBEDTLS_AES_ENCRYPT, MBEDTLS_AES_DECRYPT };
33*1c60b9acSAndroid Build Coastguard Worker 
34*1c60b9acSAndroid Build Coastguard Worker static unsigned int
_write_pkcs7_pad(uint8_t * p,int len)35*1c60b9acSAndroid Build Coastguard Worker _write_pkcs7_pad(uint8_t *p, int len)
36*1c60b9acSAndroid Build Coastguard Worker {
37*1c60b9acSAndroid Build Coastguard Worker 	unsigned int n = 0, padlen = LWS_AES_CBC_BLOCKLEN * ((unsigned int)len /
38*1c60b9acSAndroid Build Coastguard Worker 					LWS_AES_CBC_BLOCKLEN + 1) - (unsigned int)len;
39*1c60b9acSAndroid Build Coastguard Worker 
40*1c60b9acSAndroid Build Coastguard Worker 	p += len;
41*1c60b9acSAndroid Build Coastguard Worker 
42*1c60b9acSAndroid Build Coastguard Worker 	while (n++ < padlen)
43*1c60b9acSAndroid Build Coastguard Worker 		*p++ = (uint8_t)padlen;
44*1c60b9acSAndroid Build Coastguard Worker 
45*1c60b9acSAndroid Build Coastguard Worker 	return padlen;
46*1c60b9acSAndroid Build Coastguard Worker }
47*1c60b9acSAndroid Build Coastguard Worker 
48*1c60b9acSAndroid Build Coastguard Worker 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)49*1c60b9acSAndroid Build Coastguard Worker lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op,
50*1c60b9acSAndroid Build Coastguard Worker 		  enum enum_aes_modes mode, struct lws_gencrypto_keyelem *el,
51*1c60b9acSAndroid Build Coastguard Worker 		  enum enum_aes_padding padding, void *engine)
52*1c60b9acSAndroid Build Coastguard Worker {
53*1c60b9acSAndroid Build Coastguard Worker 	int n = 0;
54*1c60b9acSAndroid Build Coastguard Worker 
55*1c60b9acSAndroid Build Coastguard Worker 	ctx->mode = mode;
56*1c60b9acSAndroid Build Coastguard Worker 	ctx->k = el;
57*1c60b9acSAndroid Build Coastguard Worker 	ctx->op = (enum enum_aes_operation)operation_map[op];
58*1c60b9acSAndroid Build Coastguard Worker 	ctx->underway = 0;
59*1c60b9acSAndroid Build Coastguard Worker 	ctx->padding = padding == LWS_GAESP_WITH_PADDING;
60*1c60b9acSAndroid Build Coastguard Worker 
61*1c60b9acSAndroid Build Coastguard Worker 	switch (ctx->mode) {
62*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_XTS:
63*1c60b9acSAndroid Build Coastguard Worker #if defined(MBEDTLS_CIPHER_MODE_XTS)
64*1c60b9acSAndroid Build Coastguard Worker 		mbedtls_aes_xts_init(&ctx->u.ctx_xts);
65*1c60b9acSAndroid Build Coastguard Worker 		break;
66*1c60b9acSAndroid Build Coastguard Worker #else
67*1c60b9acSAndroid Build Coastguard Worker 		return -1;
68*1c60b9acSAndroid Build Coastguard Worker #endif
69*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_GCM:
70*1c60b9acSAndroid Build Coastguard Worker 		mbedtls_gcm_init(&ctx->u.ctx_gcm);
71*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_gcm_setkey(&ctx->u.ctx_gcm, MBEDTLS_CIPHER_ID_AES,
72*1c60b9acSAndroid Build Coastguard Worker 				       ctx->k->buf, ctx->k->len * 8);
73*1c60b9acSAndroid Build Coastguard Worker 		if (n) {
74*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: mbedtls_gcm_setkey: -0x%x\n",
75*1c60b9acSAndroid Build Coastguard Worker 				    __func__, -n);
76*1c60b9acSAndroid Build Coastguard Worker 			return n;
77*1c60b9acSAndroid Build Coastguard Worker 		}
78*1c60b9acSAndroid Build Coastguard Worker 		return n;
79*1c60b9acSAndroid Build Coastguard Worker 	default:
80*1c60b9acSAndroid Build Coastguard Worker 		mbedtls_aes_init(&ctx->u.ctx);
81*1c60b9acSAndroid Build Coastguard Worker 		break;
82*1c60b9acSAndroid Build Coastguard Worker 	}
83*1c60b9acSAndroid Build Coastguard Worker 
84*1c60b9acSAndroid Build Coastguard Worker 	switch (op) {
85*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESO_ENC:
86*1c60b9acSAndroid Build Coastguard Worker 		if (ctx->mode == LWS_GAESM_XTS)
87*1c60b9acSAndroid Build Coastguard Worker #if defined(MBEDTLS_CIPHER_MODE_XTS)
88*1c60b9acSAndroid Build Coastguard Worker 			n = mbedtls_aes_xts_setkey_enc(&ctx->u.ctx_xts,
89*1c60b9acSAndroid Build Coastguard Worker 						       ctx->k->buf,
90*1c60b9acSAndroid Build Coastguard Worker 						       ctx->k->len * 8);
91*1c60b9acSAndroid Build Coastguard Worker #else
92*1c60b9acSAndroid Build Coastguard Worker 			return -1;
93*1c60b9acSAndroid Build Coastguard Worker #endif
94*1c60b9acSAndroid Build Coastguard Worker 		else
95*1c60b9acSAndroid Build Coastguard Worker 			n = mbedtls_aes_setkey_enc(&ctx->u.ctx, ctx->k->buf,
96*1c60b9acSAndroid Build Coastguard Worker 						   ctx->k->len * 8);
97*1c60b9acSAndroid Build Coastguard Worker 		break;
98*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESO_DEC:
99*1c60b9acSAndroid Build Coastguard Worker 		switch (ctx->mode) {
100*1c60b9acSAndroid Build Coastguard Worker 		case LWS_GAESM_XTS:
101*1c60b9acSAndroid Build Coastguard Worker #if defined(MBEDTLS_CIPHER_MODE_XTS)
102*1c60b9acSAndroid Build Coastguard Worker 			n = mbedtls_aes_xts_setkey_dec(&ctx->u.ctx_xts,
103*1c60b9acSAndroid Build Coastguard Worker 						       ctx->k->buf,
104*1c60b9acSAndroid Build Coastguard Worker 						       ctx->k->len * 8);
105*1c60b9acSAndroid Build Coastguard Worker 			break;
106*1c60b9acSAndroid Build Coastguard Worker #else
107*1c60b9acSAndroid Build Coastguard Worker 			return -1;
108*1c60b9acSAndroid Build Coastguard Worker #endif
109*1c60b9acSAndroid Build Coastguard Worker 
110*1c60b9acSAndroid Build Coastguard Worker 		case LWS_GAESM_CFB128:
111*1c60b9acSAndroid Build Coastguard Worker 		case LWS_GAESM_CFB8:
112*1c60b9acSAndroid Build Coastguard Worker 		case LWS_GAESM_CTR:
113*1c60b9acSAndroid Build Coastguard Worker 		case LWS_GAESM_OFB:
114*1c60b9acSAndroid Build Coastguard Worker 			n = mbedtls_aes_setkey_enc(&ctx->u.ctx, ctx->k->buf,
115*1c60b9acSAndroid Build Coastguard Worker 						   ctx->k->len * 8);
116*1c60b9acSAndroid Build Coastguard Worker 			break;
117*1c60b9acSAndroid Build Coastguard Worker 		default:
118*1c60b9acSAndroid Build Coastguard Worker 			n = mbedtls_aes_setkey_dec(&ctx->u.ctx, ctx->k->buf,
119*1c60b9acSAndroid Build Coastguard Worker 						   ctx->k->len * 8);
120*1c60b9acSAndroid Build Coastguard Worker 			break;
121*1c60b9acSAndroid Build Coastguard Worker 		}
122*1c60b9acSAndroid Build Coastguard Worker 		break;
123*1c60b9acSAndroid Build Coastguard Worker 	}
124*1c60b9acSAndroid Build Coastguard Worker 
125*1c60b9acSAndroid Build Coastguard Worker 	if (n)
126*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: setting key: -0x%x\n", __func__, -n);
127*1c60b9acSAndroid Build Coastguard Worker 
128*1c60b9acSAndroid Build Coastguard Worker 	return n;
129*1c60b9acSAndroid Build Coastguard Worker }
130*1c60b9acSAndroid Build Coastguard Worker 
131*1c60b9acSAndroid Build Coastguard Worker int
lws_genaes_destroy(struct lws_genaes_ctx * ctx,unsigned char * tag,size_t tlen)132*1c60b9acSAndroid Build Coastguard Worker lws_genaes_destroy(struct lws_genaes_ctx *ctx, unsigned char *tag, size_t tlen)
133*1c60b9acSAndroid Build Coastguard Worker {
134*1c60b9acSAndroid Build Coastguard Worker #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
135*1c60b9acSAndroid Build Coastguard Worker 	size_t last_len = 0;
136*1c60b9acSAndroid Build Coastguard Worker 	uint8_t last[16];
137*1c60b9acSAndroid Build Coastguard Worker #endif
138*1c60b9acSAndroid Build Coastguard Worker 	int n;
139*1c60b9acSAndroid Build Coastguard Worker 
140*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->mode == LWS_GAESM_GCM) {
141*1c60b9acSAndroid Build Coastguard Worker #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
142*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_gcm_finish(&ctx->u.ctx_gcm, last, sizeof(last),
143*1c60b9acSAndroid Build Coastguard Worker 					&last_len, tag, tlen);
144*1c60b9acSAndroid Build Coastguard Worker #else
145*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_gcm_finish(&ctx->u.ctx_gcm, tag, tlen);
146*1c60b9acSAndroid Build Coastguard Worker #endif
147*1c60b9acSAndroid Build Coastguard Worker 
148*1c60b9acSAndroid Build Coastguard Worker 		if (n)
149*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: mbedtls_gcm_finish: -0x%x\n",
150*1c60b9acSAndroid Build Coastguard Worker 				    __func__, -n);
151*1c60b9acSAndroid Build Coastguard Worker 		if (tag && ctx->op == MBEDTLS_AES_DECRYPT && !n) {
152*1c60b9acSAndroid Build Coastguard Worker 			if (lws_timingsafe_bcmp(ctx->tag, tag, (unsigned int)ctx->taglen)) {
153*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: lws_genaes_crypt tag "
154*1c60b9acSAndroid Build Coastguard Worker 					 "mismatch (bad first)\n",
155*1c60b9acSAndroid Build Coastguard Worker 						__func__);
156*1c60b9acSAndroid Build Coastguard Worker 				lwsl_hexdump_notice(tag, tlen);
157*1c60b9acSAndroid Build Coastguard Worker 				lwsl_hexdump_notice(ctx->tag, (unsigned int)ctx->taglen);
158*1c60b9acSAndroid Build Coastguard Worker 				n = -1;
159*1c60b9acSAndroid Build Coastguard Worker 			}
160*1c60b9acSAndroid Build Coastguard Worker 		}
161*1c60b9acSAndroid Build Coastguard Worker 		mbedtls_gcm_free(&ctx->u.ctx_gcm);
162*1c60b9acSAndroid Build Coastguard Worker 		return n;
163*1c60b9acSAndroid Build Coastguard Worker 	}
164*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->mode == LWS_GAESM_XTS)
165*1c60b9acSAndroid Build Coastguard Worker #if defined(MBEDTLS_CIPHER_MODE_XTS)
166*1c60b9acSAndroid Build Coastguard Worker 		mbedtls_aes_xts_free(&ctx->u.ctx_xts);
167*1c60b9acSAndroid Build Coastguard Worker #else
168*1c60b9acSAndroid Build Coastguard Worker 		return -1;
169*1c60b9acSAndroid Build Coastguard Worker #endif
170*1c60b9acSAndroid Build Coastguard Worker 	else
171*1c60b9acSAndroid Build Coastguard Worker 		mbedtls_aes_free(&ctx->u.ctx);
172*1c60b9acSAndroid Build Coastguard Worker 
173*1c60b9acSAndroid Build Coastguard Worker 	return 0;
174*1c60b9acSAndroid Build Coastguard Worker }
175*1c60b9acSAndroid Build Coastguard Worker 
176*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_mbedtls_internal_aes_encrypt)
177*1c60b9acSAndroid Build Coastguard Worker 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)178*1c60b9acSAndroid Build Coastguard Worker lws_genaes_rfc3394_wrap(int wrap, int cek_bits, const uint8_t *kek,
179*1c60b9acSAndroid Build Coastguard Worker 			int kek_bits, const uint8_t *in, uint8_t *out)
180*1c60b9acSAndroid Build Coastguard Worker {
181*1c60b9acSAndroid Build Coastguard Worker 	int n, m, ret = -1, c64 = cek_bits / 64;
182*1c60b9acSAndroid Build Coastguard Worker 	mbedtls_aes_context ctx;
183*1c60b9acSAndroid Build Coastguard Worker 	uint8_t a[8], b[16];
184*1c60b9acSAndroid Build Coastguard Worker 
185*1c60b9acSAndroid Build Coastguard Worker 	/*
186*1c60b9acSAndroid Build Coastguard Worker 	 * notice the KEK key used to perform the wrapping or unwrapping is
187*1c60b9acSAndroid Build Coastguard Worker 	 * always the size of the AES key used, eg, A128KW == 128 bits.  The
188*1c60b9acSAndroid Build Coastguard Worker 	 * key being wrapped or unwrapped may be larger and is set by the
189*1c60b9acSAndroid Build Coastguard Worker 	 * 'bits' parameter.
190*1c60b9acSAndroid Build Coastguard Worker 	 *
191*1c60b9acSAndroid Build Coastguard Worker 	 * If it's larger than the KEK key size bits, we iterate over it
192*1c60b9acSAndroid Build Coastguard Worker 	 */
193*1c60b9acSAndroid Build Coastguard Worker 
194*1c60b9acSAndroid Build Coastguard Worker 	mbedtls_aes_init(&ctx);
195*1c60b9acSAndroid Build Coastguard Worker 
196*1c60b9acSAndroid Build Coastguard Worker 	if (wrap) {
197*1c60b9acSAndroid Build Coastguard Worker 		/*
198*1c60b9acSAndroid Build Coastguard Worker 		 * The inputs to the key wrapping process are the KEK and the
199*1c60b9acSAndroid Build Coastguard Worker 		 * plaintext to be wrapped.  The plaintext consists of n 64-bit
200*1c60b9acSAndroid Build Coastguard Worker 		 * blocks, containing the key data being wrapped.
201*1c60b9acSAndroid Build Coastguard Worker 		 *
202*1c60b9acSAndroid Build Coastguard Worker 		 * Inputs:      Plaintext, n 64-bit values {P1, P2, ..., Pn},
203*1c60b9acSAndroid Build Coastguard Worker 		 *		and Key, K (the KEK).
204*1c60b9acSAndroid Build Coastguard Worker 		 * Outputs:     Ciphertext, (n+1) 64-bit values
205*1c60b9acSAndroid Build Coastguard Worker 		 *		{C0, C1, ..., Cn}.
206*1c60b9acSAndroid Build Coastguard Worker 		 *
207*1c60b9acSAndroid Build Coastguard Worker 		 * The default initial value (IV) is defined to be the
208*1c60b9acSAndroid Build Coastguard Worker 		 * hexadecimal constant:
209*1c60b9acSAndroid Build Coastguard Worker 		 *
210*1c60b9acSAndroid Build Coastguard Worker 		 * A[0] = IV = A6A6A6A6A6A6A6A6
211*1c60b9acSAndroid Build Coastguard Worker 		 */
212*1c60b9acSAndroid Build Coastguard Worker 		memset(out, 0xa6, 8);
213*1c60b9acSAndroid Build Coastguard Worker 		memcpy(out + 8, in, 8 * (unsigned int)c64);
214*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_aes_setkey_enc(&ctx, kek, (unsigned int)kek_bits);
215*1c60b9acSAndroid Build Coastguard Worker 	} else {
216*1c60b9acSAndroid Build Coastguard Worker 		/*
217*1c60b9acSAndroid Build Coastguard Worker 		 * 2.2.2 Key Unwrap
218*1c60b9acSAndroid Build Coastguard Worker 		 *
219*1c60b9acSAndroid Build Coastguard Worker 		 * The inputs to the unwrap process are the KEK and (n+1)
220*1c60b9acSAndroid Build Coastguard Worker 		 * 64-bit blocks of ciphertext consisting of previously
221*1c60b9acSAndroid Build Coastguard Worker 		 * wrapped key.  It returns n blocks of plaintext consisting
222*1c60b9acSAndroid Build Coastguard Worker 		 * of the n 64-bit blocks of the decrypted key data.
223*1c60b9acSAndroid Build Coastguard Worker 		 *
224*1c60b9acSAndroid Build Coastguard Worker 		 * Inputs:  Ciphertext, (n+1) 64-bit values {C0, C1, ..., Cn},
225*1c60b9acSAndroid Build Coastguard Worker 		 * and Key, K (the KEK).
226*1c60b9acSAndroid Build Coastguard Worker 		 *
227*1c60b9acSAndroid Build Coastguard Worker 		 * Outputs: Plaintext, n 64-bit values {P1, P2, ..., Pn}.
228*1c60b9acSAndroid Build Coastguard Worker 		 */
229*1c60b9acSAndroid Build Coastguard Worker 		memcpy(a, in, 8);
230*1c60b9acSAndroid Build Coastguard Worker 		memcpy(out, in + 8, 8 * (unsigned int)c64);
231*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_aes_setkey_dec(&ctx, kek, (unsigned int)kek_bits);
232*1c60b9acSAndroid Build Coastguard Worker 	}
233*1c60b9acSAndroid Build Coastguard Worker 
234*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
235*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: setkey failed\n", __func__);
236*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
237*1c60b9acSAndroid Build Coastguard Worker 	}
238*1c60b9acSAndroid Build Coastguard Worker 
239*1c60b9acSAndroid Build Coastguard Worker 	if (wrap) {
240*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n <= 5; n++) {
241*1c60b9acSAndroid Build Coastguard Worker 			uint8_t *r = out + 8;
242*1c60b9acSAndroid Build Coastguard Worker 			for (m = 1; m <= c64; m++) {
243*1c60b9acSAndroid Build Coastguard Worker 				memcpy(b, out, 8);
244*1c60b9acSAndroid Build Coastguard Worker 				memcpy(b + 8, r, 8);
245*1c60b9acSAndroid Build Coastguard Worker 				if (mbedtls_internal_aes_encrypt(&ctx, b, b))
246*1c60b9acSAndroid Build Coastguard Worker 					goto bail;
247*1c60b9acSAndroid Build Coastguard Worker 
248*1c60b9acSAndroid Build Coastguard Worker 				memcpy(out, b, 8);
249*1c60b9acSAndroid Build Coastguard Worker 				out[7] ^= (uint8_t)(c64 * n + m);
250*1c60b9acSAndroid Build Coastguard Worker 				memcpy(r, b + 8, 8);
251*1c60b9acSAndroid Build Coastguard Worker 				r += 8;
252*1c60b9acSAndroid Build Coastguard Worker 			}
253*1c60b9acSAndroid Build Coastguard Worker 		}
254*1c60b9acSAndroid Build Coastguard Worker 		ret = 0;
255*1c60b9acSAndroid Build Coastguard Worker 	} else {
256*1c60b9acSAndroid Build Coastguard Worker 		/*
257*1c60b9acSAndroid Build Coastguard Worker 		 *
258*1c60b9acSAndroid Build Coastguard Worker 		 */
259*1c60b9acSAndroid Build Coastguard Worker 		for (n = 5; n >= 0; n--) {
260*1c60b9acSAndroid Build Coastguard Worker 			uint8_t *r = out + (c64 - 1) * 8;
261*1c60b9acSAndroid Build Coastguard Worker 			for (m = c64; m >= 1; m--) {
262*1c60b9acSAndroid Build Coastguard Worker 				memcpy(b, a, 8);
263*1c60b9acSAndroid Build Coastguard Worker 				b[7] ^= (uint8_t)(c64 * n + m);
264*1c60b9acSAndroid Build Coastguard Worker 				memcpy(b + 8, r, 8);
265*1c60b9acSAndroid Build Coastguard Worker 				if (mbedtls_internal_aes_decrypt(&ctx, b, b))
266*1c60b9acSAndroid Build Coastguard Worker 					goto bail;
267*1c60b9acSAndroid Build Coastguard Worker 
268*1c60b9acSAndroid Build Coastguard Worker 				memcpy(a, b, 8);
269*1c60b9acSAndroid Build Coastguard Worker 				memcpy(r, b + 8, 8);
270*1c60b9acSAndroid Build Coastguard Worker 				r -= 8;
271*1c60b9acSAndroid Build Coastguard Worker 			}
272*1c60b9acSAndroid Build Coastguard Worker 		}
273*1c60b9acSAndroid Build Coastguard Worker 
274*1c60b9acSAndroid Build Coastguard Worker 		ret = 0;
275*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n < 8; n++)
276*1c60b9acSAndroid Build Coastguard Worker 			if (a[n] != 0xa6)
277*1c60b9acSAndroid Build Coastguard Worker 				ret = -1;
278*1c60b9acSAndroid Build Coastguard Worker 	}
279*1c60b9acSAndroid Build Coastguard Worker 
280*1c60b9acSAndroid Build Coastguard Worker bail:
281*1c60b9acSAndroid Build Coastguard Worker 	if (ret)
282*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: failed\n", __func__);
283*1c60b9acSAndroid Build Coastguard Worker 	mbedtls_aes_free(&ctx);
284*1c60b9acSAndroid Build Coastguard Worker 
285*1c60b9acSAndroid Build Coastguard Worker 	return ret;
286*1c60b9acSAndroid Build Coastguard Worker }
287*1c60b9acSAndroid Build Coastguard Worker #endif
288*1c60b9acSAndroid Build Coastguard Worker 
289*1c60b9acSAndroid Build Coastguard Worker 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*1c60b9acSAndroid Build Coastguard Worker lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len,
291*1c60b9acSAndroid Build Coastguard Worker 		 uint8_t *out, uint8_t *iv_or_nonce_ctr_or_data_unit_16,
292*1c60b9acSAndroid Build Coastguard Worker 		 uint8_t *stream_block_16, size_t *nc_or_iv_off, int taglen)
293*1c60b9acSAndroid Build Coastguard Worker {
294*1c60b9acSAndroid Build Coastguard Worker 	uint8_t iv[LWS_JWE_AES_IV_BYTES], sb[16];
295*1c60b9acSAndroid Build Coastguard Worker 	int n = 0;
296*1c60b9acSAndroid Build Coastguard Worker 
297*1c60b9acSAndroid Build Coastguard Worker 	switch (ctx->mode) {
298*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_KW:
299*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_mbedtls_internal_aes_encrypt)
300*1c60b9acSAndroid Build Coastguard Worker 		/* a key of length ctx->k->len is wrapped by a 128-bit KEK */
301*1c60b9acSAndroid Build Coastguard Worker 		n = lws_genaes_rfc3394_wrap(ctx->op == MBEDTLS_AES_ENCRYPT,
302*1c60b9acSAndroid Build Coastguard Worker 				(ctx->op == MBEDTLS_AES_ENCRYPT ? (int)len * 8 :
303*1c60b9acSAndroid Build Coastguard Worker 						((int)len - 8) * 8), ctx->k->buf,
304*1c60b9acSAndroid Build Coastguard Worker 						(int)ctx->k->len * 8,
305*1c60b9acSAndroid Build Coastguard Worker 				in, out);
306*1c60b9acSAndroid Build Coastguard Worker 		break;
307*1c60b9acSAndroid Build Coastguard Worker #else
308*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: your mbedtls is too old\n", __func__);
309*1c60b9acSAndroid Build Coastguard Worker 		return -1;
310*1c60b9acSAndroid Build Coastguard Worker #endif
311*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_CBC:
312*1c60b9acSAndroid Build Coastguard Worker 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
313*1c60b9acSAndroid Build Coastguard Worker 
314*1c60b9acSAndroid Build Coastguard Worker 		/*
315*1c60b9acSAndroid Build Coastguard Worker 		 * If encrypting, we do the PKCS#7 padding.
316*1c60b9acSAndroid Build Coastguard Worker 		 * During decryption, the caller will need to unpad.
317*1c60b9acSAndroid Build Coastguard Worker 		 */
318*1c60b9acSAndroid Build Coastguard Worker 		if (ctx->padding && ctx->op == MBEDTLS_AES_ENCRYPT) {
319*1c60b9acSAndroid Build Coastguard Worker 			/*
320*1c60b9acSAndroid Build Coastguard Worker 			 * Since we don't want to burden the caller with
321*1c60b9acSAndroid Build Coastguard Worker 			 * the over-allocation at the end of the input,
322*1c60b9acSAndroid Build Coastguard Worker 			 * we have to allocate a temp with space for it
323*1c60b9acSAndroid Build Coastguard Worker 			 */
324*1c60b9acSAndroid Build Coastguard Worker 			uint8_t *padin = (uint8_t *)lws_malloc(
325*1c60b9acSAndroid Build Coastguard Worker 				lws_gencrypto_padded_length(LWS_AES_CBC_BLOCKLEN, len),
326*1c60b9acSAndroid Build Coastguard Worker 								__func__);
327*1c60b9acSAndroid Build Coastguard Worker 
328*1c60b9acSAndroid Build Coastguard Worker 			if (!padin)
329*1c60b9acSAndroid Build Coastguard Worker 				return -1;
330*1c60b9acSAndroid Build Coastguard Worker 
331*1c60b9acSAndroid Build Coastguard Worker 			memcpy(padin, in, len);
332*1c60b9acSAndroid Build Coastguard Worker 			len += _write_pkcs7_pad((uint8_t *)padin, (int)len);
333*1c60b9acSAndroid Build Coastguard Worker 			n = mbedtls_aes_crypt_cbc(&ctx->u.ctx, (int)ctx->op, len, iv,
334*1c60b9acSAndroid Build Coastguard Worker 						  padin, out);
335*1c60b9acSAndroid Build Coastguard Worker 			lws_free(padin);
336*1c60b9acSAndroid Build Coastguard Worker 		} else
337*1c60b9acSAndroid Build Coastguard Worker 			n = mbedtls_aes_crypt_cbc(&ctx->u.ctx, (int)ctx->op, len, iv,
338*1c60b9acSAndroid Build Coastguard Worker                                       in, out);
339*1c60b9acSAndroid Build Coastguard Worker 
340*1c60b9acSAndroid Build Coastguard Worker 		break;
341*1c60b9acSAndroid Build Coastguard Worker 
342*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_CFB128:
343*1c60b9acSAndroid Build Coastguard Worker 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
344*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_aes_crypt_cfb128(&ctx->u.ctx, (int)ctx->op, len,
345*1c60b9acSAndroid Build Coastguard Worker 					     nc_or_iv_off, iv, in, out);
346*1c60b9acSAndroid Build Coastguard Worker 		break;
347*1c60b9acSAndroid Build Coastguard Worker 
348*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_CFB8:
349*1c60b9acSAndroid Build Coastguard Worker 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
350*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_aes_crypt_cfb8(&ctx->u.ctx, (int)ctx->op, len, iv,
351*1c60b9acSAndroid Build Coastguard Worker 					   in, out);
352*1c60b9acSAndroid Build Coastguard Worker 		break;
353*1c60b9acSAndroid Build Coastguard Worker 
354*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_CTR:
355*1c60b9acSAndroid Build Coastguard Worker 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
356*1c60b9acSAndroid Build Coastguard Worker 		memcpy(sb, stream_block_16, 16);
357*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_aes_crypt_ctr(&ctx->u.ctx, len, nc_or_iv_off,
358*1c60b9acSAndroid Build Coastguard Worker 					  iv, sb, in, out);
359*1c60b9acSAndroid Build Coastguard Worker 		memcpy(iv_or_nonce_ctr_or_data_unit_16, iv, 16);
360*1c60b9acSAndroid Build Coastguard Worker 		memcpy(stream_block_16, sb, 16);
361*1c60b9acSAndroid Build Coastguard Worker 		break;
362*1c60b9acSAndroid Build Coastguard Worker 
363*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_ECB:
364*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_aes_crypt_ecb(&ctx->u.ctx, (int)ctx->op, in, out);
365*1c60b9acSAndroid Build Coastguard Worker 		break;
366*1c60b9acSAndroid Build Coastguard Worker 
367*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_OFB:
368*1c60b9acSAndroid Build Coastguard Worker #if defined(MBEDTLS_CIPHER_MODE_OFB)
369*1c60b9acSAndroid Build Coastguard Worker 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
370*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_aes_crypt_ofb(&ctx->u.ctx, len, nc_or_iv_off, iv,
371*1c60b9acSAndroid Build Coastguard Worker 					  in, out);
372*1c60b9acSAndroid Build Coastguard Worker 		break;
373*1c60b9acSAndroid Build Coastguard Worker #else
374*1c60b9acSAndroid Build Coastguard Worker 		return -1;
375*1c60b9acSAndroid Build Coastguard Worker #endif
376*1c60b9acSAndroid Build Coastguard Worker 
377*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_XTS:
378*1c60b9acSAndroid Build Coastguard Worker #if defined(MBEDTLS_CIPHER_MODE_XTS)
379*1c60b9acSAndroid Build Coastguard Worker 		memcpy(iv, iv_or_nonce_ctr_or_data_unit_16, 16);
380*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_aes_crypt_xts(&ctx->u.ctx_xts, (int)ctx->op, len, iv,
381*1c60b9acSAndroid Build Coastguard Worker 					  in, out);
382*1c60b9acSAndroid Build Coastguard Worker 		break;
383*1c60b9acSAndroid Build Coastguard Worker #else
384*1c60b9acSAndroid Build Coastguard Worker 		return -1;
385*1c60b9acSAndroid Build Coastguard Worker #endif
386*1c60b9acSAndroid Build Coastguard Worker 	case LWS_GAESM_GCM:
387*1c60b9acSAndroid Build Coastguard Worker 		if (!ctx->underway) {
388*1c60b9acSAndroid Build Coastguard Worker 			ctx->underway = 1;
389*1c60b9acSAndroid Build Coastguard Worker 
390*1c60b9acSAndroid Build Coastguard Worker 			memcpy(ctx->tag, stream_block_16, (unsigned int)taglen);
391*1c60b9acSAndroid Build Coastguard Worker 			ctx->taglen = taglen;
392*1c60b9acSAndroid Build Coastguard Worker 
393*1c60b9acSAndroid Build Coastguard Worker 			/*
394*1c60b9acSAndroid Build Coastguard Worker 			 * iv:                   iv_or_nonce_ctr_or_data_unit_16
395*1c60b9acSAndroid Build Coastguard Worker 			 * iv_len:               *nc_or_iv_off
396*1c60b9acSAndroid Build Coastguard Worker 			 * stream_block_16:      pointer to tag
397*1c60b9acSAndroid Build Coastguard Worker 			 * additional data:      in
398*1c60b9acSAndroid Build Coastguard Worker 			 * additional data len:  len
399*1c60b9acSAndroid Build Coastguard Worker 			 */
400*1c60b9acSAndroid Build Coastguard Worker 
401*1c60b9acSAndroid Build Coastguard Worker #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
402*1c60b9acSAndroid Build Coastguard Worker 			n = mbedtls_gcm_starts(&ctx->u.ctx_gcm, (int)ctx->op,
403*1c60b9acSAndroid Build Coastguard Worker 					       iv_or_nonce_ctr_or_data_unit_16,
404*1c60b9acSAndroid Build Coastguard Worker 					       *nc_or_iv_off);
405*1c60b9acSAndroid Build Coastguard Worker 			if (!n)
406*1c60b9acSAndroid Build Coastguard Worker 				n = mbedtls_gcm_update_ad(&ctx->u.ctx_gcm,
407*1c60b9acSAndroid Build Coastguard Worker 							  in, len);
408*1c60b9acSAndroid Build Coastguard Worker #else
409*1c60b9acSAndroid Build Coastguard Worker 			n = mbedtls_gcm_starts(&ctx->u.ctx_gcm, (int)ctx->op,
410*1c60b9acSAndroid Build Coastguard Worker 					       iv_or_nonce_ctr_or_data_unit_16,
411*1c60b9acSAndroid Build Coastguard Worker 					       *nc_or_iv_off, in, len);
412*1c60b9acSAndroid Build Coastguard Worker #endif
413*1c60b9acSAndroid Build Coastguard Worker 			if (n) {
414*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: mbedtls_gcm_starts: -0x%x\n",
415*1c60b9acSAndroid Build Coastguard Worker 					    __func__, -n);
416*1c60b9acSAndroid Build Coastguard Worker 
417*1c60b9acSAndroid Build Coastguard Worker 				return -1;
418*1c60b9acSAndroid Build Coastguard Worker 			}
419*1c60b9acSAndroid Build Coastguard Worker 			break;
420*1c60b9acSAndroid Build Coastguard Worker 		}
421*1c60b9acSAndroid Build Coastguard Worker 
422*1c60b9acSAndroid Build Coastguard Worker #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
423*1c60b9acSAndroid Build Coastguard Worker 		{
424*1c60b9acSAndroid Build Coastguard Worker 			size_t al;
425*1c60b9acSAndroid Build Coastguard Worker 
426*1c60b9acSAndroid Build Coastguard Worker 			n = mbedtls_gcm_update(&ctx->u.ctx_gcm, in, len, out, len, &al);
427*1c60b9acSAndroid Build Coastguard Worker 		}
428*1c60b9acSAndroid Build Coastguard Worker #else
429*1c60b9acSAndroid Build Coastguard Worker 		n = mbedtls_gcm_update(&ctx->u.ctx_gcm, len, in, out);
430*1c60b9acSAndroid Build Coastguard Worker #endif
431*1c60b9acSAndroid Build Coastguard Worker 		if (n) {
432*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: mbedtls_gcm_update: -0x%x\n",
433*1c60b9acSAndroid Build Coastguard Worker 				    __func__, -n);
434*1c60b9acSAndroid Build Coastguard Worker 
435*1c60b9acSAndroid Build Coastguard Worker 			return -1;
436*1c60b9acSAndroid Build Coastguard Worker 		}
437*1c60b9acSAndroid Build Coastguard Worker 		break;
438*1c60b9acSAndroid Build Coastguard Worker 	}
439*1c60b9acSAndroid Build Coastguard Worker 
440*1c60b9acSAndroid Build Coastguard Worker 	if (n) {
441*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: failed: -0x%x, len %d\n", __func__, -n, (int)len);
442*1c60b9acSAndroid Build Coastguard Worker 
443*1c60b9acSAndroid Build Coastguard Worker 		return -1;
444*1c60b9acSAndroid Build Coastguard Worker 	}
445*1c60b9acSAndroid Build Coastguard Worker 
446*1c60b9acSAndroid Build Coastguard Worker 	return 0;
447*1c60b9acSAndroid Build Coastguard Worker }
448