]>
Commit | Line | Data |
---|---|---|
aa6bb135 | 1 | /* |
33388b44 | 2 | * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. |
aa6d1a0c | 3 | * |
c918d8e2 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
aa6bb135 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
aa6d1a0c BL |
8 | */ |
9 | ||
c72fa255 MC |
10 | /* |
11 | * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement | |
12 | * these functions | |
13 | */ | |
14 | #include "internal/deprecated.h" | |
15 | ||
b39fc560 | 16 | #include "internal/cryptlib.h" |
aa6d1a0c BL |
17 | |
18 | #include <openssl/aes.h> | |
706457b7 | 19 | #include "aes_local.h" |
aa6d1a0c | 20 | |
9660cbcd | 21 | /* XXX: probably some better way to do this */ |
5f09d0ec | 22 | #if defined(__i386__) || defined(__x86_64__) |
0f113f3e | 23 | # define UNALIGNED_MEMOPS_ARE_FAST 1 |
d8803d5a | 24 | #else |
0f113f3e | 25 | # define UNALIGNED_MEMOPS_ARE_FAST 0 |
5f09d0ec BL |
26 | #endif |
27 | ||
77286fe3 BE |
28 | #define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long)) |
29 | typedef struct { | |
30 | unsigned long data[N_WORDS]; | |
31 | #if defined(__GNUC__) && UNALIGNED_MEMOPS_ARE_FAST | |
32 | } aes_block_t __attribute((__aligned__(1))); | |
33 | #else | |
34 | } aes_block_t; | |
35 | #endif | |
36 | ||
d8803d5a | 37 | #if UNALIGNED_MEMOPS_ARE_FAST |
0f113f3e MC |
38 | # define load_block(d, s) (d) = *(const aes_block_t *)(s) |
39 | # define store_block(d, s) *(aes_block_t *)(d) = (s) | |
5f09d0ec | 40 | #else |
0f113f3e MC |
41 | # define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE) |
42 | # define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE) | |
5f09d0ec BL |
43 | #endif |
44 | ||
aa6d1a0c BL |
45 | /* N.B. The IV for this mode is _twice_ the block size */ |
46 | ||
fd367b4c | 47 | /* Use of this function is deprecated. */ |
aa6d1a0c | 48 | void AES_ige_encrypt(const unsigned char *in, unsigned char *out, |
0f113f3e MC |
49 | size_t length, const AES_KEY *key, |
50 | unsigned char *ivec, const int enc) | |
51 | { | |
52 | size_t n; | |
e442cdae | 53 | size_t len = length / AES_BLOCK_SIZE; |
aa6d1a0c | 54 | |
b1498c98 RS |
55 | if (length == 0) |
56 | return; | |
57 | ||
0f113f3e MC |
58 | OPENSSL_assert(in && out && key && ivec); |
59 | OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); | |
60 | OPENSSL_assert((length % AES_BLOCK_SIZE) == 0); | |
aa6d1a0c | 61 | |
0f113f3e MC |
62 | if (AES_ENCRYPT == enc) { |
63 | if (in != out && | |
64 | (UNALIGNED_MEMOPS_ARE_FAST | |
65 | || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) == | |
66 | 0)) { | |
67 | aes_block_t *ivp = (aes_block_t *) ivec; | |
68 | aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE); | |
69ab0852 | 69 | |
0f113f3e MC |
70 | while (len) { |
71 | aes_block_t *inp = (aes_block_t *) in; | |
72 | aes_block_t *outp = (aes_block_t *) out; | |
69ab0852 | 73 | |
0f113f3e MC |
74 | for (n = 0; n < N_WORDS; ++n) |
75 | outp->data[n] = inp->data[n] ^ ivp->data[n]; | |
76 | AES_encrypt((unsigned char *)outp->data, | |
77 | (unsigned char *)outp->data, key); | |
78 | for (n = 0; n < N_WORDS; ++n) | |
79 | outp->data[n] ^= iv2p->data[n]; | |
80 | ivp = outp; | |
81 | iv2p = inp; | |
82 | --len; | |
83 | in += AES_BLOCK_SIZE; | |
84 | out += AES_BLOCK_SIZE; | |
85 | } | |
86 | memcpy(ivec, ivp->data, AES_BLOCK_SIZE); | |
87 | memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); | |
88 | } else { | |
89 | aes_block_t tmp, tmp2; | |
90 | aes_block_t iv; | |
91 | aes_block_t iv2; | |
69ab0852 | 92 | |
0f113f3e MC |
93 | load_block(iv, ivec); |
94 | load_block(iv2, ivec + AES_BLOCK_SIZE); | |
69ab0852 | 95 | |
0f113f3e MC |
96 | while (len) { |
97 | load_block(tmp, in); | |
98 | for (n = 0; n < N_WORDS; ++n) | |
99 | tmp2.data[n] = tmp.data[n] ^ iv.data[n]; | |
100 | AES_encrypt((unsigned char *)tmp2.data, | |
101 | (unsigned char *)tmp2.data, key); | |
102 | for (n = 0; n < N_WORDS; ++n) | |
103 | tmp2.data[n] ^= iv2.data[n]; | |
104 | store_block(out, tmp2); | |
105 | iv = tmp2; | |
106 | iv2 = tmp; | |
107 | --len; | |
108 | in += AES_BLOCK_SIZE; | |
109 | out += AES_BLOCK_SIZE; | |
110 | } | |
111 | memcpy(ivec, iv.data, AES_BLOCK_SIZE); | |
112 | memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); | |
113 | } | |
114 | } else { | |
115 | if (in != out && | |
116 | (UNALIGNED_MEMOPS_ARE_FAST | |
117 | || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) == | |
118 | 0)) { | |
119 | aes_block_t *ivp = (aes_block_t *) ivec; | |
120 | aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE); | |
69ab0852 | 121 | |
0f113f3e MC |
122 | while (len) { |
123 | aes_block_t tmp; | |
124 | aes_block_t *inp = (aes_block_t *) in; | |
125 | aes_block_t *outp = (aes_block_t *) out; | |
69ab0852 | 126 | |
0f113f3e MC |
127 | for (n = 0; n < N_WORDS; ++n) |
128 | tmp.data[n] = inp->data[n] ^ iv2p->data[n]; | |
129 | AES_decrypt((unsigned char *)tmp.data, | |
130 | (unsigned char *)outp->data, key); | |
131 | for (n = 0; n < N_WORDS; ++n) | |
132 | outp->data[n] ^= ivp->data[n]; | |
133 | ivp = inp; | |
134 | iv2p = outp; | |
135 | --len; | |
136 | in += AES_BLOCK_SIZE; | |
137 | out += AES_BLOCK_SIZE; | |
138 | } | |
139 | memcpy(ivec, ivp->data, AES_BLOCK_SIZE); | |
140 | memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); | |
141 | } else { | |
142 | aes_block_t tmp, tmp2; | |
143 | aes_block_t iv; | |
144 | aes_block_t iv2; | |
69ab0852 | 145 | |
0f113f3e MC |
146 | load_block(iv, ivec); |
147 | load_block(iv2, ivec + AES_BLOCK_SIZE); | |
69ab0852 | 148 | |
0f113f3e MC |
149 | while (len) { |
150 | load_block(tmp, in); | |
151 | tmp2 = tmp; | |
152 | for (n = 0; n < N_WORDS; ++n) | |
153 | tmp.data[n] ^= iv2.data[n]; | |
154 | AES_decrypt((unsigned char *)tmp.data, | |
155 | (unsigned char *)tmp.data, key); | |
156 | for (n = 0; n < N_WORDS; ++n) | |
157 | tmp.data[n] ^= iv.data[n]; | |
158 | store_block(out, tmp); | |
159 | iv = tmp2; | |
160 | iv2 = tmp; | |
161 | --len; | |
162 | in += AES_BLOCK_SIZE; | |
163 | out += AES_BLOCK_SIZE; | |
164 | } | |
165 | memcpy(ivec, iv.data, AES_BLOCK_SIZE); | |
166 | memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); | |
167 | } | |
168 | } | |
169 | } | |
aa6d1a0c BL |
170 | |
171 | /* | |
172 | * Note that its effectively impossible to do biIGE in anything other | |
173 | * than a single pass, so no provision is made for chaining. | |
fd367b4c MC |
174 | * |
175 | * NB: The implementation of AES_bi_ige_encrypt has a bug. It is supposed to use | |
176 | * 2 AES keys, but in fact only one is ever used. This bug has been present | |
177 | * since this code was first implemented. It is believed to have minimal | |
178 | * security impact in practice and has therefore not been fixed for backwards | |
179 | * compatibility reasons. | |
180 | * | |
181 | * Use of this function is deprecated. | |
aa6d1a0c BL |
182 | */ |
183 | ||
184 | /* N.B. The IV for this mode is _four times_ the block size */ | |
185 | ||
186 | void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, | |
0f113f3e MC |
187 | size_t length, const AES_KEY *key, |
188 | const AES_KEY *key2, const unsigned char *ivec, | |
189 | const int enc) | |
190 | { | |
191 | size_t n; | |
192 | size_t len = length; | |
193 | unsigned char tmp[AES_BLOCK_SIZE]; | |
194 | unsigned char tmp2[AES_BLOCK_SIZE]; | |
195 | unsigned char tmp3[AES_BLOCK_SIZE]; | |
196 | unsigned char prev[AES_BLOCK_SIZE]; | |
197 | const unsigned char *iv; | |
198 | const unsigned char *iv2; | |
aa6d1a0c | 199 | |
0f113f3e MC |
200 | OPENSSL_assert(in && out && key && ivec); |
201 | OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); | |
202 | OPENSSL_assert((length % AES_BLOCK_SIZE) == 0); | |
aa6d1a0c | 203 | |
0f113f3e MC |
204 | if (AES_ENCRYPT == enc) { |
205 | /* | |
206 | * XXX: Do a separate case for when in != out (strictly should check | |
207 | * for overlap, too) | |
208 | */ | |
aa6d1a0c | 209 | |
0f113f3e MC |
210 | /* First the forward pass */ |
211 | iv = ivec; | |
212 | iv2 = ivec + AES_BLOCK_SIZE; | |
213 | while (len >= AES_BLOCK_SIZE) { | |
214 | for (n = 0; n < AES_BLOCK_SIZE; ++n) | |
215 | out[n] = in[n] ^ iv[n]; | |
216 | AES_encrypt(out, out, key); | |
217 | for (n = 0; n < AES_BLOCK_SIZE; ++n) | |
218 | out[n] ^= iv2[n]; | |
219 | iv = out; | |
220 | memcpy(prev, in, AES_BLOCK_SIZE); | |
221 | iv2 = prev; | |
222 | len -= AES_BLOCK_SIZE; | |
223 | in += AES_BLOCK_SIZE; | |
224 | out += AES_BLOCK_SIZE; | |
225 | } | |
aa6d1a0c | 226 | |
0f113f3e MC |
227 | /* And now backwards */ |
228 | iv = ivec + AES_BLOCK_SIZE * 2; | |
229 | iv2 = ivec + AES_BLOCK_SIZE * 3; | |
230 | len = length; | |
231 | while (len >= AES_BLOCK_SIZE) { | |
232 | out -= AES_BLOCK_SIZE; | |
233 | /* | |
234 | * XXX: reduce copies by alternating between buffers | |
235 | */ | |
236 | memcpy(tmp, out, AES_BLOCK_SIZE); | |
237 | for (n = 0; n < AES_BLOCK_SIZE; ++n) | |
238 | out[n] ^= iv[n]; | |
239 | /* | |
240 | * hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE); | |
241 | */ | |
242 | AES_encrypt(out, out, key); | |
243 | /* | |
244 | * hexdump(stdout,"enc", out, AES_BLOCK_SIZE); | |
245 | */ | |
246 | /* | |
247 | * hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); | |
248 | */ | |
249 | for (n = 0; n < AES_BLOCK_SIZE; ++n) | |
250 | out[n] ^= iv2[n]; | |
251 | /* | |
252 | * hexdump(stdout,"out", out, AES_BLOCK_SIZE); | |
253 | */ | |
254 | iv = out; | |
255 | memcpy(prev, tmp, AES_BLOCK_SIZE); | |
256 | iv2 = prev; | |
257 | len -= AES_BLOCK_SIZE; | |
258 | } | |
259 | } else { | |
260 | /* First backwards */ | |
261 | iv = ivec + AES_BLOCK_SIZE * 2; | |
262 | iv2 = ivec + AES_BLOCK_SIZE * 3; | |
263 | in += length; | |
264 | out += length; | |
265 | while (len >= AES_BLOCK_SIZE) { | |
266 | in -= AES_BLOCK_SIZE; | |
267 | out -= AES_BLOCK_SIZE; | |
268 | memcpy(tmp, in, AES_BLOCK_SIZE); | |
269 | memcpy(tmp2, in, AES_BLOCK_SIZE); | |
270 | for (n = 0; n < AES_BLOCK_SIZE; ++n) | |
271 | tmp[n] ^= iv2[n]; | |
272 | AES_decrypt(tmp, out, key); | |
273 | for (n = 0; n < AES_BLOCK_SIZE; ++n) | |
274 | out[n] ^= iv[n]; | |
275 | memcpy(tmp3, tmp2, AES_BLOCK_SIZE); | |
276 | iv = tmp3; | |
277 | iv2 = out; | |
278 | len -= AES_BLOCK_SIZE; | |
279 | } | |
aa6d1a0c | 280 | |
0f113f3e MC |
281 | /* And now forwards */ |
282 | iv = ivec; | |
283 | iv2 = ivec + AES_BLOCK_SIZE; | |
284 | len = length; | |
285 | while (len >= AES_BLOCK_SIZE) { | |
286 | memcpy(tmp, out, AES_BLOCK_SIZE); | |
287 | memcpy(tmp2, out, AES_BLOCK_SIZE); | |
288 | for (n = 0; n < AES_BLOCK_SIZE; ++n) | |
289 | tmp[n] ^= iv2[n]; | |
290 | AES_decrypt(tmp, out, key); | |
291 | for (n = 0; n < AES_BLOCK_SIZE; ++n) | |
292 | out[n] ^= iv[n]; | |
293 | memcpy(tmp3, tmp2, AES_BLOCK_SIZE); | |
294 | iv = tmp3; | |
295 | iv2 = out; | |
296 | len -= AES_BLOCK_SIZE; | |
297 | in += AES_BLOCK_SIZE; | |
298 | out += AES_BLOCK_SIZE; | |
299 | } | |
300 | } | |
301 | } |