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