blob: f7892af9fb30aea429ba7dafc78633803350d138
1 | /* |
2 | * A 32-bit implementation of the XTEA algorithm |
3 | * Copyright (c) 2012 Samuel Pitoiset |
4 | * |
5 | * loosely based on the implementation of David Wheeler and Roger Needham |
6 | * |
7 | * This file is part of FFmpeg. |
8 | * |
9 | * FFmpeg is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU Lesser General Public |
11 | * License as published by the Free Software Foundation; either |
12 | * version 2.1 of the License, or (at your option) any later version. |
13 | * |
14 | * FFmpeg is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | * Lesser General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU Lesser General Public |
20 | * License along with FFmpeg; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | */ |
23 | |
24 | /** |
25 | * @file |
26 | * @brief XTEA 32-bit implementation |
27 | * @author Samuel Pitoiset |
28 | * @ingroup lavu_xtea |
29 | */ |
30 | |
31 | #include "avutil.h" |
32 | #include "common.h" |
33 | #include "intreadwrite.h" |
34 | #include "mem.h" |
35 | #include "xtea.h" |
36 | |
37 | AVXTEA *av_xtea_alloc(void) |
38 | { |
39 | return av_mallocz(sizeof(struct AVXTEA)); |
40 | } |
41 | |
42 | void av_xtea_init(AVXTEA *ctx, const uint8_t key[16]) |
43 | { |
44 | int i; |
45 | |
46 | for (i = 0; i < 4; i++) |
47 | ctx->key[i] = AV_RB32(key + (i << 2)); |
48 | } |
49 | |
50 | void av_xtea_le_init(AVXTEA *ctx, const uint8_t key[16]) |
51 | { |
52 | int i; |
53 | |
54 | for (i = 0; i < 4; i++) |
55 | ctx->key[i] = AV_RL32(key + (i << 2)); |
56 | } |
57 | |
58 | static void xtea_crypt_ecb(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, |
59 | int decrypt, uint8_t *iv) |
60 | { |
61 | uint32_t v0, v1; |
62 | #if !CONFIG_SMALL |
63 | uint32_t k0 = ctx->key[0]; |
64 | uint32_t k1 = ctx->key[1]; |
65 | uint32_t k2 = ctx->key[2]; |
66 | uint32_t k3 = ctx->key[3]; |
67 | #endif |
68 | |
69 | v0 = AV_RB32(src); |
70 | v1 = AV_RB32(src + 4); |
71 | |
72 | if (decrypt) { |
73 | #if CONFIG_SMALL |
74 | int i; |
75 | uint32_t delta = 0x9E3779B9U, sum = delta * 32; |
76 | |
77 | for (i = 0; i < 32; i++) { |
78 | v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + ctx->key[(sum >> 11) & 3]); |
79 | sum -= delta; |
80 | v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + ctx->key[sum & 3]); |
81 | } |
82 | #else |
83 | #define DSTEP(SUM, K0, K1) \ |
84 | v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (SUM + K0); \ |
85 | v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (SUM - 0x9E3779B9U + K1) |
86 | |
87 | DSTEP(0xC6EF3720U, k2, k3); |
88 | DSTEP(0x28B7BD67U, k3, k2); |
89 | DSTEP(0x8A8043AEU, k0, k1); |
90 | DSTEP(0xEC48C9F5U, k1, k0); |
91 | DSTEP(0x4E11503CU, k2, k3); |
92 | DSTEP(0xAFD9D683U, k2, k2); |
93 | DSTEP(0x11A25CCAU, k3, k1); |
94 | DSTEP(0x736AE311U, k0, k0); |
95 | DSTEP(0xD5336958U, k1, k3); |
96 | DSTEP(0x36FBEF9FU, k1, k2); |
97 | DSTEP(0x98C475E6U, k2, k1); |
98 | DSTEP(0xFA8CFC2DU, k3, k0); |
99 | DSTEP(0x5C558274U, k0, k3); |
100 | DSTEP(0xBE1E08BBU, k1, k2); |
101 | DSTEP(0x1FE68F02U, k1, k1); |
102 | DSTEP(0x81AF1549U, k2, k0); |
103 | DSTEP(0xE3779B90U, k3, k3); |
104 | DSTEP(0x454021D7U, k0, k2); |
105 | DSTEP(0xA708A81EU, k1, k1); |
106 | DSTEP(0x08D12E65U, k1, k0); |
107 | DSTEP(0x6A99B4ACU, k2, k3); |
108 | DSTEP(0xCC623AF3U, k3, k2); |
109 | DSTEP(0x2E2AC13AU, k0, k1); |
110 | DSTEP(0x8FF34781U, k0, k0); |
111 | DSTEP(0xF1BBCDC8U, k1, k3); |
112 | DSTEP(0x5384540FU, k2, k2); |
113 | DSTEP(0xB54CDA56U, k3, k1); |
114 | DSTEP(0x1715609DU, k0, k0); |
115 | DSTEP(0x78DDE6E4U, k0, k3); |
116 | DSTEP(0xDAA66D2BU, k1, k2); |
117 | DSTEP(0x3C6EF372U, k2, k1); |
118 | DSTEP(0x9E3779B9U, k3, k0); |
119 | #endif |
120 | if (iv) { |
121 | v0 ^= AV_RB32(iv); |
122 | v1 ^= AV_RB32(iv + 4); |
123 | memcpy(iv, src, 8); |
124 | } |
125 | } else { |
126 | #if CONFIG_SMALL |
127 | int i; |
128 | uint32_t sum = 0, delta = 0x9E3779B9U; |
129 | |
130 | for (i = 0; i < 32; i++) { |
131 | v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + ctx->key[sum & 3]); |
132 | sum += delta; |
133 | v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + ctx->key[(sum >> 11) & 3]); |
134 | } |
135 | #else |
136 | #define ESTEP(SUM, K0, K1) \ |
137 | v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (SUM + K0);\ |
138 | v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (SUM + 0x9E3779B9U + K1) |
139 | ESTEP(0x00000000U, k0, k3); |
140 | ESTEP(0x9E3779B9U, k1, k2); |
141 | ESTEP(0x3C6EF372U, k2, k1); |
142 | ESTEP(0xDAA66D2BU, k3, k0); |
143 | ESTEP(0x78DDE6E4U, k0, k0); |
144 | ESTEP(0x1715609DU, k1, k3); |
145 | ESTEP(0xB54CDA56U, k2, k2); |
146 | ESTEP(0x5384540FU, k3, k1); |
147 | ESTEP(0xF1BBCDC8U, k0, k0); |
148 | ESTEP(0x8FF34781U, k1, k0); |
149 | ESTEP(0x2E2AC13AU, k2, k3); |
150 | ESTEP(0xCC623AF3U, k3, k2); |
151 | ESTEP(0x6A99B4ACU, k0, k1); |
152 | ESTEP(0x08D12E65U, k1, k1); |
153 | ESTEP(0xA708A81EU, k2, k0); |
154 | ESTEP(0x454021D7U, k3, k3); |
155 | ESTEP(0xE3779B90U, k0, k2); |
156 | ESTEP(0x81AF1549U, k1, k1); |
157 | ESTEP(0x1FE68F02U, k2, k1); |
158 | ESTEP(0xBE1E08BBU, k3, k0); |
159 | ESTEP(0x5C558274U, k0, k3); |
160 | ESTEP(0xFA8CFC2DU, k1, k2); |
161 | ESTEP(0x98C475E6U, k2, k1); |
162 | ESTEP(0x36FBEF9FU, k3, k1); |
163 | ESTEP(0xD5336958U, k0, k0); |
164 | ESTEP(0x736AE311U, k1, k3); |
165 | ESTEP(0x11A25CCAU, k2, k2); |
166 | ESTEP(0xAFD9D683U, k3, k2); |
167 | ESTEP(0x4E11503CU, k0, k1); |
168 | ESTEP(0xEC48C9F5U, k1, k0); |
169 | ESTEP(0x8A8043AEU, k2, k3); |
170 | ESTEP(0x28B7BD67U, k3, k2); |
171 | #endif |
172 | } |
173 | |
174 | AV_WB32(dst, v0); |
175 | AV_WB32(dst + 4, v1); |
176 | } |
177 | |
178 | static void xtea_le_crypt_ecb(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, |
179 | int decrypt, uint8_t *iv) |
180 | { |
181 | uint32_t v0, v1; |
182 | int i; |
183 | |
184 | v0 = AV_RL32(src); |
185 | v1 = AV_RL32(src + 4); |
186 | |
187 | if (decrypt) { |
188 | uint32_t delta = 0x9E3779B9, sum = delta * 32; |
189 | |
190 | for (i = 0; i < 32; i++) { |
191 | v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + ctx->key[(sum >> 11) & 3]); |
192 | sum -= delta; |
193 | v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + ctx->key[sum & 3]); |
194 | } |
195 | if (iv) { |
196 | v0 ^= AV_RL32(iv); |
197 | v1 ^= AV_RL32(iv + 4); |
198 | memcpy(iv, src, 8); |
199 | } |
200 | } else { |
201 | uint32_t sum = 0, delta = 0x9E3779B9; |
202 | |
203 | for (i = 0; i < 32; i++) { |
204 | v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + ctx->key[sum & 3]); |
205 | sum += delta; |
206 | v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + ctx->key[(sum >> 11) & 3]); |
207 | } |
208 | } |
209 | |
210 | AV_WL32(dst, v0); |
211 | AV_WL32(dst + 4, v1); |
212 | } |
213 | |
214 | static void xtea_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, |
215 | uint8_t *iv, int decrypt, |
216 | void (*crypt)(AVXTEA *, uint8_t *, const uint8_t *, int, uint8_t *)) |
217 | { |
218 | int i; |
219 | |
220 | if (decrypt) { |
221 | while (count--) { |
222 | crypt(ctx, dst, src, decrypt, iv); |
223 | |
224 | src += 8; |
225 | dst += 8; |
226 | } |
227 | } else { |
228 | while (count--) { |
229 | if (iv) { |
230 | for (i = 0; i < 8; i++) |
231 | dst[i] = src[i] ^ iv[i]; |
232 | crypt(ctx, dst, dst, decrypt, NULL); |
233 | memcpy(iv, dst, 8); |
234 | } else { |
235 | crypt(ctx, dst, src, decrypt, NULL); |
236 | } |
237 | src += 8; |
238 | dst += 8; |
239 | } |
240 | } |
241 | } |
242 | |
243 | void av_xtea_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, |
244 | uint8_t *iv, int decrypt) |
245 | { |
246 | xtea_crypt(ctx, dst, src, count, iv, decrypt, xtea_crypt_ecb); |
247 | } |
248 | |
249 | void av_xtea_le_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, |
250 | uint8_t *iv, int decrypt) |
251 | { |
252 | xtea_crypt(ctx, dst, src, count, iv, decrypt, xtea_le_crypt_ecb); |
253 | } |
254 |