xref: /freebsd/crypto/openssl/crypto/aes/aes_ige.c (revision b077aed3)
1e71b7053SJung-uk Kim /*
258f35182SJung-uk Kim  * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
3ed5d4f9aSSimon L. B. Nielsen  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
8ed5d4f9aSSimon L. B. Nielsen  */
9ed5d4f9aSSimon L. B. Nielsen 
10b077aed3SPierre Pronchery /*
11b077aed3SPierre Pronchery  * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement
12b077aed3SPierre Pronchery  * these functions
13b077aed3SPierre Pronchery  */
14b077aed3SPierre Pronchery #include "internal/deprecated.h"
15b077aed3SPierre Pronchery 
16e71b7053SJung-uk Kim #include "internal/cryptlib.h"
17ed5d4f9aSSimon L. B. Nielsen 
18ed5d4f9aSSimon L. B. Nielsen #include <openssl/aes.h>
1917f01e99SJung-uk Kim #include "aes_local.h"
20ed5d4f9aSSimon L. B. Nielsen 
21db522d3aSSimon L. B. Nielsen /* XXX: probably some better way to do this */
22db522d3aSSimon L. B. Nielsen #if defined(__i386__) || defined(__x86_64__)
23db522d3aSSimon L. B. Nielsen # define UNALIGNED_MEMOPS_ARE_FAST 1
24db522d3aSSimon L. B. Nielsen #else
25db522d3aSSimon L. B. Nielsen # define UNALIGNED_MEMOPS_ARE_FAST 0
26db522d3aSSimon L. B. Nielsen #endif
27db522d3aSSimon L. B. Nielsen 
2858f35182SJung-uk Kim #define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long))
2958f35182SJung-uk Kim typedef struct {
3058f35182SJung-uk Kim     unsigned long data[N_WORDS];
3158f35182SJung-uk Kim #if defined(__GNUC__) && UNALIGNED_MEMOPS_ARE_FAST
3258f35182SJung-uk Kim } aes_block_t __attribute((__aligned__(1)));
3358f35182SJung-uk Kim #else
3458f35182SJung-uk Kim } aes_block_t;
3558f35182SJung-uk Kim #endif
3658f35182SJung-uk Kim 
37db522d3aSSimon L. B. Nielsen #if UNALIGNED_MEMOPS_ARE_FAST
38db522d3aSSimon L. B. Nielsen # define load_block(d, s)        (d) = *(const aes_block_t *)(s)
39db522d3aSSimon L. B. Nielsen # define store_block(d, s)       *(aes_block_t *)(d) = (s)
40db522d3aSSimon L. B. Nielsen #else
41db522d3aSSimon L. B. Nielsen # define load_block(d, s)        memcpy((d).data, (s), AES_BLOCK_SIZE)
42db522d3aSSimon L. B. Nielsen # define store_block(d, s)       memcpy((d), (s).data, AES_BLOCK_SIZE)
43db522d3aSSimon L. B. Nielsen #endif
44ed5d4f9aSSimon L. B. Nielsen 
45ed5d4f9aSSimon L. B. Nielsen /* N.B. The IV for this mode is _twice_ the block size */
46ed5d4f9aSSimon L. B. Nielsen 
47b077aed3SPierre Pronchery /*  Use of this function is deprecated. */
AES_ige_encrypt(const unsigned char * in,unsigned char * out,size_t length,const AES_KEY * key,unsigned char * ivec,const int enc)48ed5d4f9aSSimon L. B. Nielsen void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
491f13597dSJung-uk Kim                      size_t length, const AES_KEY *key,
50ed5d4f9aSSimon L. B. Nielsen                      unsigned char *ivec, const int enc)
51ed5d4f9aSSimon L. B. Nielsen {
521f13597dSJung-uk Kim     size_t n;
53b077aed3SPierre Pronchery     size_t len = length / AES_BLOCK_SIZE;
54ed5d4f9aSSimon L. B. Nielsen 
55e71b7053SJung-uk Kim     if (length == 0)
56e71b7053SJung-uk Kim         return;
57e71b7053SJung-uk Kim 
58ed5d4f9aSSimon L. B. Nielsen     OPENSSL_assert(in && out && key && ivec);
59ed5d4f9aSSimon L. B. Nielsen     OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
60ed5d4f9aSSimon L. B. Nielsen     OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
61ed5d4f9aSSimon L. B. Nielsen 
626f9291ceSJung-uk Kim     if (AES_ENCRYPT == enc) {
63db522d3aSSimon L. B. Nielsen         if (in != out &&
646f9291ceSJung-uk Kim             (UNALIGNED_MEMOPS_ARE_FAST
656f9291ceSJung-uk Kim              || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
666f9291ceSJung-uk Kim              0)) {
67db522d3aSSimon L. B. Nielsen             aes_block_t *ivp = (aes_block_t *) ivec;
68db522d3aSSimon L. B. Nielsen             aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
69db522d3aSSimon L. B. Nielsen 
706f9291ceSJung-uk Kim             while (len) {
71db522d3aSSimon L. B. Nielsen                 aes_block_t *inp = (aes_block_t *) in;
72db522d3aSSimon L. B. Nielsen                 aes_block_t *outp = (aes_block_t *) out;
73db522d3aSSimon L. B. Nielsen 
74db522d3aSSimon L. B. Nielsen                 for (n = 0; n < N_WORDS; ++n)
75db522d3aSSimon L. B. Nielsen                     outp->data[n] = inp->data[n] ^ ivp->data[n];
766f9291ceSJung-uk Kim                 AES_encrypt((unsigned char *)outp->data,
776f9291ceSJung-uk Kim                             (unsigned char *)outp->data, key);
78db522d3aSSimon L. B. Nielsen                 for (n = 0; n < N_WORDS; ++n)
79db522d3aSSimon L. B. Nielsen                     outp->data[n] ^= iv2p->data[n];
80db522d3aSSimon L. B. Nielsen                 ivp = outp;
81db522d3aSSimon L. B. Nielsen                 iv2p = inp;
82db522d3aSSimon L. B. Nielsen                 --len;
83ed5d4f9aSSimon L. B. Nielsen                 in += AES_BLOCK_SIZE;
84ed5d4f9aSSimon L. B. Nielsen                 out += AES_BLOCK_SIZE;
85ed5d4f9aSSimon L. B. Nielsen             }
86db522d3aSSimon L. B. Nielsen             memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
87db522d3aSSimon L. B. Nielsen             memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
886f9291ceSJung-uk Kim         } else {
89db522d3aSSimon L. B. Nielsen             aes_block_t tmp, tmp2;
90db522d3aSSimon L. B. Nielsen             aes_block_t iv;
91db522d3aSSimon L. B. Nielsen             aes_block_t iv2;
92db522d3aSSimon L. B. Nielsen 
93db522d3aSSimon L. B. Nielsen             load_block(iv, ivec);
94db522d3aSSimon L. B. Nielsen             load_block(iv2, ivec + AES_BLOCK_SIZE);
95db522d3aSSimon L. B. Nielsen 
966f9291ceSJung-uk Kim             while (len) {
97db522d3aSSimon L. B. Nielsen                 load_block(tmp, in);
98db522d3aSSimon L. B. Nielsen                 for (n = 0; n < N_WORDS; ++n)
99db522d3aSSimon L. B. Nielsen                     tmp2.data[n] = tmp.data[n] ^ iv.data[n];
1006f9291ceSJung-uk Kim                 AES_encrypt((unsigned char *)tmp2.data,
1016f9291ceSJung-uk Kim                             (unsigned char *)tmp2.data, key);
102db522d3aSSimon L. B. Nielsen                 for (n = 0; n < N_WORDS; ++n)
103db522d3aSSimon L. B. Nielsen                     tmp2.data[n] ^= iv2.data[n];
104db522d3aSSimon L. B. Nielsen                 store_block(out, tmp2);
105db522d3aSSimon L. B. Nielsen                 iv = tmp2;
106db522d3aSSimon L. B. Nielsen                 iv2 = tmp;
107db522d3aSSimon L. B. Nielsen                 --len;
108ed5d4f9aSSimon L. B. Nielsen                 in += AES_BLOCK_SIZE;
109ed5d4f9aSSimon L. B. Nielsen                 out += AES_BLOCK_SIZE;
110ed5d4f9aSSimon L. B. Nielsen             }
111db522d3aSSimon L. B. Nielsen             memcpy(ivec, iv.data, AES_BLOCK_SIZE);
112db522d3aSSimon L. B. Nielsen             memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
113db522d3aSSimon L. B. Nielsen         }
1146f9291ceSJung-uk Kim     } else {
115db522d3aSSimon L. B. Nielsen         if (in != out &&
1166f9291ceSJung-uk Kim             (UNALIGNED_MEMOPS_ARE_FAST
1176f9291ceSJung-uk Kim              || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
1186f9291ceSJung-uk Kim              0)) {
119db522d3aSSimon L. B. Nielsen             aes_block_t *ivp = (aes_block_t *) ivec;
120db522d3aSSimon L. B. Nielsen             aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
121db522d3aSSimon L. B. Nielsen 
1226f9291ceSJung-uk Kim             while (len) {
123db522d3aSSimon L. B. Nielsen                 aes_block_t tmp;
124db522d3aSSimon L. B. Nielsen                 aes_block_t *inp = (aes_block_t *) in;
125db522d3aSSimon L. B. Nielsen                 aes_block_t *outp = (aes_block_t *) out;
126db522d3aSSimon L. B. Nielsen 
127db522d3aSSimon L. B. Nielsen                 for (n = 0; n < N_WORDS; ++n)
128db522d3aSSimon L. B. Nielsen                     tmp.data[n] = inp->data[n] ^ iv2p->data[n];
1296f9291ceSJung-uk Kim                 AES_decrypt((unsigned char *)tmp.data,
1306f9291ceSJung-uk Kim                             (unsigned char *)outp->data, key);
131db522d3aSSimon L. B. Nielsen                 for (n = 0; n < N_WORDS; ++n)
132db522d3aSSimon L. B. Nielsen                     outp->data[n] ^= ivp->data[n];
133db522d3aSSimon L. B. Nielsen                 ivp = inp;
134db522d3aSSimon L. B. Nielsen                 iv2p = outp;
135db522d3aSSimon L. B. Nielsen                 --len;
136db522d3aSSimon L. B. Nielsen                 in += AES_BLOCK_SIZE;
137db522d3aSSimon L. B. Nielsen                 out += AES_BLOCK_SIZE;
138db522d3aSSimon L. B. Nielsen             }
139db522d3aSSimon L. B. Nielsen             memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
140db522d3aSSimon L. B. Nielsen             memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
1416f9291ceSJung-uk Kim         } else {
142db522d3aSSimon L. B. Nielsen             aes_block_t tmp, tmp2;
143db522d3aSSimon L. B. Nielsen             aes_block_t iv;
144db522d3aSSimon L. B. Nielsen             aes_block_t iv2;
145db522d3aSSimon L. B. Nielsen 
146db522d3aSSimon L. B. Nielsen             load_block(iv, ivec);
147db522d3aSSimon L. B. Nielsen             load_block(iv2, ivec + AES_BLOCK_SIZE);
148db522d3aSSimon L. B. Nielsen 
1496f9291ceSJung-uk Kim             while (len) {
150db522d3aSSimon L. B. Nielsen                 load_block(tmp, in);
151db522d3aSSimon L. B. Nielsen                 tmp2 = tmp;
152db522d3aSSimon L. B. Nielsen                 for (n = 0; n < N_WORDS; ++n)
153db522d3aSSimon L. B. Nielsen                     tmp.data[n] ^= iv2.data[n];
1546f9291ceSJung-uk Kim                 AES_decrypt((unsigned char *)tmp.data,
1556f9291ceSJung-uk Kim                             (unsigned char *)tmp.data, key);
156db522d3aSSimon L. B. Nielsen                 for (n = 0; n < N_WORDS; ++n)
157db522d3aSSimon L. B. Nielsen                     tmp.data[n] ^= iv.data[n];
158db522d3aSSimon L. B. Nielsen                 store_block(out, tmp);
159db522d3aSSimon L. B. Nielsen                 iv = tmp2;
160db522d3aSSimon L. B. Nielsen                 iv2 = tmp;
161db522d3aSSimon L. B. Nielsen                 --len;
162db522d3aSSimon L. B. Nielsen                 in += AES_BLOCK_SIZE;
163db522d3aSSimon L. B. Nielsen                 out += AES_BLOCK_SIZE;
164db522d3aSSimon L. B. Nielsen             }
165db522d3aSSimon L. B. Nielsen             memcpy(ivec, iv.data, AES_BLOCK_SIZE);
166db522d3aSSimon L. B. Nielsen             memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
167db522d3aSSimon L. B. Nielsen         }
168ed5d4f9aSSimon L. B. Nielsen     }
169ed5d4f9aSSimon L. B. Nielsen }
170ed5d4f9aSSimon L. B. Nielsen 
171ed5d4f9aSSimon L. B. Nielsen /*
172ed5d4f9aSSimon L. B. Nielsen  * Note that its effectively impossible to do biIGE in anything other
173ed5d4f9aSSimon L. B. Nielsen  * than a single pass, so no provision is made for chaining.
174b077aed3SPierre Pronchery  *
175b077aed3SPierre Pronchery  * NB: The implementation of AES_bi_ige_encrypt has a bug. It is supposed to use
176b077aed3SPierre Pronchery  * 2 AES keys, but in fact only one is ever used. This bug has been present
177b077aed3SPierre Pronchery  * since this code was first implemented. It is believed to have minimal
178b077aed3SPierre Pronchery  * security impact in practice and has therefore not been fixed for backwards
179b077aed3SPierre Pronchery  * compatibility reasons.
180b077aed3SPierre Pronchery  *
181b077aed3SPierre Pronchery  * Use of this function is deprecated.
182ed5d4f9aSSimon L. B. Nielsen  */
183ed5d4f9aSSimon L. B. Nielsen 
184ed5d4f9aSSimon L. B. Nielsen /* N.B. The IV for this mode is _four times_ the block size */
185ed5d4f9aSSimon L. B. Nielsen 
AES_bi_ige_encrypt(const unsigned char * in,unsigned char * out,size_t length,const AES_KEY * key,const AES_KEY * key2,const unsigned char * ivec,const int enc)186ed5d4f9aSSimon L. B. Nielsen void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
1871f13597dSJung-uk Kim                         size_t length, const AES_KEY *key,
188ed5d4f9aSSimon L. B. Nielsen                         const AES_KEY *key2, const unsigned char *ivec,
189ed5d4f9aSSimon L. B. Nielsen                         const int enc)
190ed5d4f9aSSimon L. B. Nielsen {
1911f13597dSJung-uk Kim     size_t n;
1921f13597dSJung-uk Kim     size_t len = length;
193ed5d4f9aSSimon L. B. Nielsen     unsigned char tmp[AES_BLOCK_SIZE];
194ed5d4f9aSSimon L. B. Nielsen     unsigned char tmp2[AES_BLOCK_SIZE];
195ed5d4f9aSSimon L. B. Nielsen     unsigned char tmp3[AES_BLOCK_SIZE];
196ed5d4f9aSSimon L. B. Nielsen     unsigned char prev[AES_BLOCK_SIZE];
197ed5d4f9aSSimon L. B. Nielsen     const unsigned char *iv;
198ed5d4f9aSSimon L. B. Nielsen     const unsigned char *iv2;
199ed5d4f9aSSimon L. B. Nielsen 
200ed5d4f9aSSimon L. B. Nielsen     OPENSSL_assert(in && out && key && ivec);
201ed5d4f9aSSimon L. B. Nielsen     OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
202ed5d4f9aSSimon L. B. Nielsen     OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
203ed5d4f9aSSimon L. B. Nielsen 
2046f9291ceSJung-uk Kim     if (AES_ENCRYPT == enc) {
2056f9291ceSJung-uk Kim         /*
2066f9291ceSJung-uk Kim          * XXX: Do a separate case for when in != out (strictly should check
2076f9291ceSJung-uk Kim          * for overlap, too)
2086f9291ceSJung-uk Kim          */
209ed5d4f9aSSimon L. B. Nielsen 
210ed5d4f9aSSimon L. B. Nielsen         /* First the forward pass */
211ed5d4f9aSSimon L. B. Nielsen         iv = ivec;
212ed5d4f9aSSimon L. B. Nielsen         iv2 = ivec + AES_BLOCK_SIZE;
2136f9291ceSJung-uk Kim         while (len >= AES_BLOCK_SIZE) {
214ed5d4f9aSSimon L. B. Nielsen             for (n = 0; n < AES_BLOCK_SIZE; ++n)
215ed5d4f9aSSimon L. B. Nielsen                 out[n] = in[n] ^ iv[n];
216ed5d4f9aSSimon L. B. Nielsen             AES_encrypt(out, out, key);
217ed5d4f9aSSimon L. B. Nielsen             for (n = 0; n < AES_BLOCK_SIZE; ++n)
218ed5d4f9aSSimon L. B. Nielsen                 out[n] ^= iv2[n];
219ed5d4f9aSSimon L. B. Nielsen             iv = out;
220ed5d4f9aSSimon L. B. Nielsen             memcpy(prev, in, AES_BLOCK_SIZE);
221ed5d4f9aSSimon L. B. Nielsen             iv2 = prev;
222ed5d4f9aSSimon L. B. Nielsen             len -= AES_BLOCK_SIZE;
223ed5d4f9aSSimon L. B. Nielsen             in += AES_BLOCK_SIZE;
224ed5d4f9aSSimon L. B. Nielsen             out += AES_BLOCK_SIZE;
225ed5d4f9aSSimon L. B. Nielsen         }
226ed5d4f9aSSimon L. B. Nielsen 
227ed5d4f9aSSimon L. B. Nielsen         /* And now backwards */
228ed5d4f9aSSimon L. B. Nielsen         iv = ivec + AES_BLOCK_SIZE * 2;
229ed5d4f9aSSimon L. B. Nielsen         iv2 = ivec + AES_BLOCK_SIZE * 3;
230ed5d4f9aSSimon L. B. Nielsen         len = length;
2316f9291ceSJung-uk Kim         while (len >= AES_BLOCK_SIZE) {
232ed5d4f9aSSimon L. B. Nielsen             out -= AES_BLOCK_SIZE;
2336f9291ceSJung-uk Kim             /*
2346f9291ceSJung-uk Kim              * XXX: reduce copies by alternating between buffers
2356f9291ceSJung-uk Kim              */
236ed5d4f9aSSimon L. B. Nielsen             memcpy(tmp, out, AES_BLOCK_SIZE);
237ed5d4f9aSSimon L. B. Nielsen             for (n = 0; n < AES_BLOCK_SIZE; ++n)
238ed5d4f9aSSimon L. B. Nielsen                 out[n] ^= iv[n];
2396f9291ceSJung-uk Kim             /*
2406f9291ceSJung-uk Kim              * hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE);
2416f9291ceSJung-uk Kim              */
242ed5d4f9aSSimon L. B. Nielsen             AES_encrypt(out, out, key);
2436f9291ceSJung-uk Kim             /*
2446f9291ceSJung-uk Kim              * hexdump(stdout,"enc", out, AES_BLOCK_SIZE);
2456f9291ceSJung-uk Kim              */
2466f9291ceSJung-uk Kim             /*
2476f9291ceSJung-uk Kim              * hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE);
2486f9291ceSJung-uk Kim              */
249ed5d4f9aSSimon L. B. Nielsen             for (n = 0; n < AES_BLOCK_SIZE; ++n)
250ed5d4f9aSSimon L. B. Nielsen                 out[n] ^= iv2[n];
2516f9291ceSJung-uk Kim             /*
2526f9291ceSJung-uk Kim              * hexdump(stdout,"out", out, AES_BLOCK_SIZE);
2536f9291ceSJung-uk Kim              */
254ed5d4f9aSSimon L. B. Nielsen             iv = out;
255ed5d4f9aSSimon L. B. Nielsen             memcpy(prev, tmp, AES_BLOCK_SIZE);
256ed5d4f9aSSimon L. B. Nielsen             iv2 = prev;
257ed5d4f9aSSimon L. B. Nielsen             len -= AES_BLOCK_SIZE;
258ed5d4f9aSSimon L. B. Nielsen         }
2596f9291ceSJung-uk Kim     } else {
260ed5d4f9aSSimon L. B. Nielsen         /* First backwards */
261ed5d4f9aSSimon L. B. Nielsen         iv = ivec + AES_BLOCK_SIZE * 2;
262ed5d4f9aSSimon L. B. Nielsen         iv2 = ivec + AES_BLOCK_SIZE * 3;
263ed5d4f9aSSimon L. B. Nielsen         in += length;
264ed5d4f9aSSimon L. B. Nielsen         out += length;
2656f9291ceSJung-uk Kim         while (len >= AES_BLOCK_SIZE) {
266ed5d4f9aSSimon L. B. Nielsen             in -= AES_BLOCK_SIZE;
267ed5d4f9aSSimon L. B. Nielsen             out -= AES_BLOCK_SIZE;
268ed5d4f9aSSimon L. B. Nielsen             memcpy(tmp, in, AES_BLOCK_SIZE);
269ed5d4f9aSSimon L. B. Nielsen             memcpy(tmp2, in, AES_BLOCK_SIZE);
270ed5d4f9aSSimon L. B. Nielsen             for (n = 0; n < AES_BLOCK_SIZE; ++n)
271ed5d4f9aSSimon L. B. Nielsen                 tmp[n] ^= iv2[n];
272ed5d4f9aSSimon L. B. Nielsen             AES_decrypt(tmp, out, key);
273ed5d4f9aSSimon L. B. Nielsen             for (n = 0; n < AES_BLOCK_SIZE; ++n)
274ed5d4f9aSSimon L. B. Nielsen                 out[n] ^= iv[n];
275ed5d4f9aSSimon L. B. Nielsen             memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
276ed5d4f9aSSimon L. B. Nielsen             iv = tmp3;
277ed5d4f9aSSimon L. B. Nielsen             iv2 = out;
278ed5d4f9aSSimon L. B. Nielsen             len -= AES_BLOCK_SIZE;
279ed5d4f9aSSimon L. B. Nielsen         }
280ed5d4f9aSSimon L. B. Nielsen 
281ed5d4f9aSSimon L. B. Nielsen         /* And now forwards */
282ed5d4f9aSSimon L. B. Nielsen         iv = ivec;
283ed5d4f9aSSimon L. B. Nielsen         iv2 = ivec + AES_BLOCK_SIZE;
284ed5d4f9aSSimon L. B. Nielsen         len = length;
2856f9291ceSJung-uk Kim         while (len >= AES_BLOCK_SIZE) {
286ed5d4f9aSSimon L. B. Nielsen             memcpy(tmp, out, AES_BLOCK_SIZE);
287ed5d4f9aSSimon L. B. Nielsen             memcpy(tmp2, out, AES_BLOCK_SIZE);
288ed5d4f9aSSimon L. B. Nielsen             for (n = 0; n < AES_BLOCK_SIZE; ++n)
289ed5d4f9aSSimon L. B. Nielsen                 tmp[n] ^= iv2[n];
290ed5d4f9aSSimon L. B. Nielsen             AES_decrypt(tmp, out, key);
291ed5d4f9aSSimon L. B. Nielsen             for (n = 0; n < AES_BLOCK_SIZE; ++n)
292ed5d4f9aSSimon L. B. Nielsen                 out[n] ^= iv[n];
293ed5d4f9aSSimon L. B. Nielsen             memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
294ed5d4f9aSSimon L. B. Nielsen             iv = tmp3;
295ed5d4f9aSSimon L. B. Nielsen             iv2 = out;
296ed5d4f9aSSimon L. B. Nielsen             len -= AES_BLOCK_SIZE;
297ed5d4f9aSSimon L. B. Nielsen             in += AES_BLOCK_SIZE;
298ed5d4f9aSSimon L. B. Nielsen             out += AES_BLOCK_SIZE;
299ed5d4f9aSSimon L. B. Nielsen         }
300ed5d4f9aSSimon L. B. Nielsen     }
301ed5d4f9aSSimon L. B. Nielsen }
302