Line | Branch | Exec | Source |
---|---|---|---|
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 <string.h> | ||
32 | #include "config.h" | ||
33 | #include "intreadwrite.h" | ||
34 | #include "mem.h" | ||
35 | #include "xtea.h" | ||
36 | |||
37 | 1 | AVXTEA *av_xtea_alloc(void) | |
38 | { | ||
39 | 1 | return av_mallocz(sizeof(struct AVXTEA)); | |
40 | } | ||
41 | |||
42 | 6 | void av_xtea_init(AVXTEA *ctx, const uint8_t key[16]) | |
43 | { | ||
44 | int i; | ||
45 | |||
46 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6 times.
|
30 | for (i = 0; i < 4; i++) |
47 | 24 | ctx->key[i] = AV_RB32(key + (i << 2)); | |
48 | 6 | } | |
49 | |||
50 | 6 | void av_xtea_le_init(AVXTEA *ctx, const uint8_t key[16]) | |
51 | { | ||
52 | int i; | ||
53 | |||
54 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6 times.
|
30 | for (i = 0; i < 4; i++) |
55 | 24 | ctx->key[i] = AV_RL32(key + (i << 2)); | |
56 | 6 | } | |
57 | |||
58 | 84 | 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 | 84 | uint32_t k0 = ctx->key[0]; | |
64 | 84 | uint32_t k1 = ctx->key[1]; | |
65 | 84 | uint32_t k2 = ctx->key[2]; | |
66 | 84 | uint32_t k3 = ctx->key[3]; | |
67 | #endif | ||
68 | |||
69 | 84 | v0 = AV_RB32(src); | |
70 | 84 | v1 = AV_RB32(src + 4); | |
71 | |||
72 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 30 times.
|
84 | 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 | 54 | DSTEP(0xC6EF3720U, k2, k3); | |
88 | 54 | DSTEP(0x28B7BD67U, k3, k2); | |
89 | 54 | DSTEP(0x8A8043AEU, k0, k1); | |
90 | 54 | DSTEP(0xEC48C9F5U, k1, k0); | |
91 | 54 | DSTEP(0x4E11503CU, k2, k3); | |
92 | 54 | DSTEP(0xAFD9D683U, k2, k2); | |
93 | 54 | DSTEP(0x11A25CCAU, k3, k1); | |
94 | 54 | DSTEP(0x736AE311U, k0, k0); | |
95 | 54 | DSTEP(0xD5336958U, k1, k3); | |
96 | 54 | DSTEP(0x36FBEF9FU, k1, k2); | |
97 | 54 | DSTEP(0x98C475E6U, k2, k1); | |
98 | 54 | DSTEP(0xFA8CFC2DU, k3, k0); | |
99 | 54 | DSTEP(0x5C558274U, k0, k3); | |
100 | 54 | DSTEP(0xBE1E08BBU, k1, k2); | |
101 | 54 | DSTEP(0x1FE68F02U, k1, k1); | |
102 | 54 | DSTEP(0x81AF1549U, k2, k0); | |
103 | 54 | DSTEP(0xE3779B90U, k3, k3); | |
104 | 54 | DSTEP(0x454021D7U, k0, k2); | |
105 | 54 | DSTEP(0xA708A81EU, k1, k1); | |
106 | 54 | DSTEP(0x08D12E65U, k1, k0); | |
107 | 54 | DSTEP(0x6A99B4ACU, k2, k3); | |
108 | 54 | DSTEP(0xCC623AF3U, k3, k2); | |
109 | 54 | DSTEP(0x2E2AC13AU, k0, k1); | |
110 | 54 | DSTEP(0x8FF34781U, k0, k0); | |
111 | 54 | DSTEP(0xF1BBCDC8U, k1, k3); | |
112 | 54 | DSTEP(0x5384540FU, k2, k2); | |
113 | 54 | DSTEP(0xB54CDA56U, k3, k1); | |
114 | 54 | DSTEP(0x1715609DU, k0, k0); | |
115 | 54 | DSTEP(0x78DDE6E4U, k0, k3); | |
116 | 54 | DSTEP(0xDAA66D2BU, k1, k2); | |
117 | 54 | DSTEP(0x3C6EF372U, k2, k1); | |
118 | 54 | DSTEP(0x9E3779B9U, k3, k0); | |
119 | #endif | ||
120 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 6 times.
|
54 | if (iv) { |
121 | 48 | v0 ^= AV_RB32(iv); | |
122 | 48 | v1 ^= AV_RB32(iv + 4); | |
123 | 48 | 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 | 30 | ESTEP(0x00000000U, k0, k3); | |
140 | 30 | ESTEP(0x9E3779B9U, k1, k2); | |
141 | 30 | ESTEP(0x3C6EF372U, k2, k1); | |
142 | 30 | ESTEP(0xDAA66D2BU, k3, k0); | |
143 | 30 | ESTEP(0x78DDE6E4U, k0, k0); | |
144 | 30 | ESTEP(0x1715609DU, k1, k3); | |
145 | 30 | ESTEP(0xB54CDA56U, k2, k2); | |
146 | 30 | ESTEP(0x5384540FU, k3, k1); | |
147 | 30 | ESTEP(0xF1BBCDC8U, k0, k0); | |
148 | 30 | ESTEP(0x8FF34781U, k1, k0); | |
149 | 30 | ESTEP(0x2E2AC13AU, k2, k3); | |
150 | 30 | ESTEP(0xCC623AF3U, k3, k2); | |
151 | 30 | ESTEP(0x6A99B4ACU, k0, k1); | |
152 | 30 | ESTEP(0x08D12E65U, k1, k1); | |
153 | 30 | ESTEP(0xA708A81EU, k2, k0); | |
154 | 30 | ESTEP(0x454021D7U, k3, k3); | |
155 | 30 | ESTEP(0xE3779B90U, k0, k2); | |
156 | 30 | ESTEP(0x81AF1549U, k1, k1); | |
157 | 30 | ESTEP(0x1FE68F02U, k2, k1); | |
158 | 30 | ESTEP(0xBE1E08BBU, k3, k0); | |
159 | 30 | ESTEP(0x5C558274U, k0, k3); | |
160 | 30 | ESTEP(0xFA8CFC2DU, k1, k2); | |
161 | 30 | ESTEP(0x98C475E6U, k2, k1); | |
162 | 30 | ESTEP(0x36FBEF9FU, k3, k1); | |
163 | 30 | ESTEP(0xD5336958U, k0, k0); | |
164 | 30 | ESTEP(0x736AE311U, k1, k3); | |
165 | 30 | ESTEP(0x11A25CCAU, k2, k2); | |
166 | 30 | ESTEP(0xAFD9D683U, k3, k2); | |
167 | 30 | ESTEP(0x4E11503CU, k0, k1); | |
168 | 30 | ESTEP(0xEC48C9F5U, k1, k0); | |
169 | 30 | ESTEP(0x8A8043AEU, k2, k3); | |
170 | 30 | ESTEP(0x28B7BD67U, k3, k2); | |
171 | #endif | ||
172 | } | ||
173 | |||
174 | 84 | AV_WB32(dst, v0); | |
175 | 84 | AV_WB32(dst + 4, v1); | |
176 | 84 | } | |
177 | |||
178 | 12 | 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 | 12 | v0 = AV_RL32(src); | |
185 | 12 | v1 = AV_RL32(src + 4); | |
186 | |||
187 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | if (decrypt) { |
188 | 6 | uint32_t delta = 0x9E3779B9, sum = delta * 32; | |
189 | |||
190 |
2/2✓ Branch 0 taken 192 times.
✓ Branch 1 taken 6 times.
|
198 | for (i = 0; i < 32; i++) { |
191 | 192 | v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + ctx->key[(sum >> 11) & 3]); | |
192 | 192 | sum -= delta; | |
193 | 192 | v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + ctx->key[sum & 3]); | |
194 | } | ||
195 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (iv) { |
196 | ✗ | v0 ^= AV_RL32(iv); | |
197 | ✗ | v1 ^= AV_RL32(iv + 4); | |
198 | ✗ | memcpy(iv, src, 8); | |
199 | } | ||
200 | } else { | ||
201 | 6 | uint32_t sum = 0, delta = 0x9E3779B9; | |
202 | |||
203 |
2/2✓ Branch 0 taken 192 times.
✓ Branch 1 taken 6 times.
|
198 | for (i = 0; i < 32; i++) { |
204 | 192 | v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + ctx->key[sum & 3]); | |
205 | 192 | sum += delta; | |
206 | 192 | v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + ctx->key[(sum >> 11) & 3]); | |
207 | } | ||
208 | } | ||
209 | |||
210 | 12 | AV_WL32(dst, v0); | |
211 | 12 | AV_WL32(dst + 4, v1); | |
212 | 12 | } | |
213 | |||
214 | 42 | 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 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 18 times.
|
42 | if (decrypt) { |
221 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 24 times.
|
84 | while (count--) { |
222 | 60 | crypt(ctx, dst, src, decrypt, iv); | |
223 | |||
224 | 60 | src += 8; | |
225 | 60 | dst += 8; | |
226 | } | ||
227 | } else { | ||
228 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18 times.
|
54 | while (count--) { |
229 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
|
36 | if (iv) { |
230 |
2/2✓ Branch 0 taken 192 times.
✓ Branch 1 taken 24 times.
|
216 | for (i = 0; i < 8; i++) |
231 | 192 | dst[i] = src[i] ^ iv[i]; | |
232 | 24 | crypt(ctx, dst, dst, decrypt, NULL); | |
233 | 24 | memcpy(iv, dst, 8); | |
234 | } else { | ||
235 | 12 | crypt(ctx, dst, src, decrypt, NULL); | |
236 | } | ||
237 | 36 | src += 8; | |
238 | 36 | dst += 8; | |
239 | } | ||
240 | } | ||
241 | 42 | } | |
242 | |||
243 | 30 | void av_xtea_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, | |
244 | uint8_t *iv, int decrypt) | ||
245 | { | ||
246 | 30 | xtea_crypt(ctx, dst, src, count, iv, decrypt, xtea_crypt_ecb); | |
247 | 30 | } | |
248 | |||
249 | 12 | void av_xtea_le_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count, | |
250 | uint8_t *iv, int decrypt) | ||
251 | { | ||
252 | 12 | xtea_crypt(ctx, dst, src, count, iv, decrypt, xtea_le_crypt_ecb); | |
253 | 12 | } | |
254 |