Merge commit '439929859ae0eb9542d3bb8a0c856bd5a1d1ec48'
[ffmpeg.git] / libavutil / des.c
1 /*
2  * DES encryption/decryption
3  * Copyright (c) 2007 Reimar Doeffinger
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include <stdint.h>
23
24 #include "avutil.h"
25 #include "common.h"
26 #include "intreadwrite.h"
27 #include "mem.h"
28 #include "des.h"
29
30 #define T(a, b, c, d, e, f, g, h) 64-a,64-b,64-c,64-d,64-e,64-f,64-g,64-h
31 static const uint8_t IP_shuffle[] = {
32     T(58, 50, 42, 34, 26, 18, 10, 2),
33     T(60, 52, 44, 36, 28, 20, 12, 4),
34     T(62, 54, 46, 38, 30, 22, 14, 6),
35     T(64, 56, 48, 40, 32, 24, 16, 8),
36     T(57, 49, 41, 33, 25, 17,  9, 1),
37     T(59, 51, 43, 35, 27, 19, 11, 3),
38     T(61, 53, 45, 37, 29, 21, 13, 5),
39     T(63, 55, 47, 39, 31, 23, 15, 7)
40 };
41 #undef T
42
43 #if CONFIG_SMALL || defined(GENTABLES)
44 #define T(a, b, c, d) 32-a,32-b,32-c,32-d
45 static const uint8_t P_shuffle[] = {
46     T(16,  7, 20, 21),
47     T(29, 12, 28, 17),
48     T( 1, 15, 23, 26),
49     T( 5, 18, 31, 10),
50     T( 2,  8, 24, 14),
51     T(32, 27,  3,  9),
52     T(19, 13, 30,  6),
53     T(22, 11,  4, 25)
54 };
55 #undef T
56 #endif
57
58 #define T(a, b, c, d, e, f, g) 64-a,64-b,64-c,64-d,64-e,64-f,64-g
59 static const uint8_t PC1_shuffle[] = {
60     T(57, 49, 41, 33, 25, 17,  9),
61     T( 1, 58, 50, 42, 34, 26, 18),
62     T(10,  2, 59, 51, 43, 35, 27),
63     T(19, 11,  3, 60, 52, 44, 36),
64     T(63, 55, 47, 39, 31, 23, 15),
65     T( 7, 62, 54, 46, 38, 30, 22),
66     T(14,  6, 61, 53, 45, 37, 29),
67     T(21, 13,  5, 28, 20, 12,  4)
68 };
69 #undef T
70
71 #define T(a, b, c, d, e, f) 56-a,56-b,56-c,56-d,56-e,56-f
72 static const uint8_t PC2_shuffle[] = {
73     T(14, 17, 11, 24,  1,  5),
74     T( 3, 28, 15,  6, 21, 10),
75     T(23, 19, 12,  4, 26,  8),
76     T(16,  7, 27, 20, 13,  2),
77     T(41, 52, 31, 37, 47, 55),
78     T(30, 40, 51, 45, 33, 48),
79     T(44, 49, 39, 56, 34, 53),
80     T(46, 42, 50, 36, 29, 32)
81 };
82 #undef T
83
84 #if CONFIG_SMALL
85 static const uint8_t S_boxes[8][32] = {
86     {
87     0x0e, 0xf4, 0x7d, 0x41, 0xe2, 0x2f, 0xdb, 0x18, 0xa3, 0x6a, 0xc6, 0xbc, 0x95, 0x59, 0x30, 0x87,
88     0xf4, 0xc1, 0x8e, 0x28, 0x4d, 0x96, 0x12, 0x7b, 0x5f, 0xbc, 0x39, 0xe7, 0xa3, 0x0a, 0x65, 0xd0,
89     }, {
90     0x3f, 0xd1, 0x48, 0x7e, 0xf6, 0x2b, 0x83, 0xe4, 0xc9, 0x07, 0x12, 0xad, 0x6c, 0x90, 0xb5, 0x5a,
91     0xd0, 0x8e, 0xa7, 0x1b, 0x3a, 0xf4, 0x4d, 0x21, 0xb5, 0x68, 0x7c, 0xc6, 0x09, 0x53, 0xe2, 0x9f,
92     }, {
93     0xda, 0x70, 0x09, 0x9e, 0x36, 0x43, 0x6f, 0xa5, 0x21, 0x8d, 0x5c, 0xe7, 0xcb, 0xb4, 0xf2, 0x18,
94     0x1d, 0xa6, 0xd4, 0x09, 0x68, 0x9f, 0x83, 0x70, 0x4b, 0xf1, 0xe2, 0x3c, 0xb5, 0x5a, 0x2e, 0xc7,
95     }, {
96     0xd7, 0x8d, 0xbe, 0x53, 0x60, 0xf6, 0x09, 0x3a, 0x41, 0x72, 0x28, 0xc5, 0x1b, 0xac, 0xe4, 0x9f,
97     0x3a, 0xf6, 0x09, 0x60, 0xac, 0x1b, 0xd7, 0x8d, 0x9f, 0x41, 0x53, 0xbe, 0xc5, 0x72, 0x28, 0xe4,
98     }, {
99     0xe2, 0xbc, 0x24, 0xc1, 0x47, 0x7a, 0xdb, 0x16, 0x58, 0x05, 0xf3, 0xaf, 0x3d, 0x90, 0x8e, 0x69,
100     0xb4, 0x82, 0xc1, 0x7b, 0x1a, 0xed, 0x27, 0xd8, 0x6f, 0xf9, 0x0c, 0x95, 0xa6, 0x43, 0x50, 0x3e,
101     }, {
102     0xac, 0xf1, 0x4a, 0x2f, 0x79, 0xc2, 0x96, 0x58, 0x60, 0x1d, 0xd3, 0xe4, 0x0e, 0xb7, 0x35, 0x8b,
103     0x49, 0x3e, 0x2f, 0xc5, 0x92, 0x58, 0xfc, 0xa3, 0xb7, 0xe0, 0x14, 0x7a, 0x61, 0x0d, 0x8b, 0xd6,
104     }, {
105     0xd4, 0x0b, 0xb2, 0x7e, 0x4f, 0x90, 0x18, 0xad, 0xe3, 0x3c, 0x59, 0xc7, 0x25, 0xfa, 0x86, 0x61,
106     0x61, 0xb4, 0xdb, 0x8d, 0x1c, 0x43, 0xa7, 0x7e, 0x9a, 0x5f, 0x06, 0xf8, 0xe0, 0x25, 0x39, 0xc2,
107     }, {
108     0x1d, 0xf2, 0xd8, 0x84, 0xa6, 0x3f, 0x7b, 0x41, 0xca, 0x59, 0x63, 0xbe, 0x05, 0xe0, 0x9c, 0x27,
109     0x27, 0x1b, 0xe4, 0x71, 0x49, 0xac, 0x8e, 0xd2, 0xf0, 0xc6, 0x9a, 0x0d, 0x3f, 0x53, 0x65, 0xb8,
110     }
111 };
112 #else
113 /**
114  * This table contains the results of applying both the S-box and P-shuffle.
115  * It can be regenerated by compiling this file with -DCONFIG_SMALL -DTEST -DGENTABLES
116  */
117 static const uint32_t S_boxes_P_shuffle[8][64] = {
118     {
119     0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000,
120     0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002,
121     0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202,
122     0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000,
123     0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200,
124     0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202,
125     0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200,
126     0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002,
127     },
128     {
129     0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010,
130     0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010,
131     0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000,
132     0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010,
133     0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000,
134     0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000,
135     0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010,
136     0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000,
137     },
138     {
139     0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100,
140     0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104,
141     0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104,
142     0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000,
143     0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000,
144     0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004,
145     0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004,
146     0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100,
147     },
148     {
149     0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000,
150     0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000,
151     0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040,
152     0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040,
153     0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000,
154     0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040,
155     0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040,
156     0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040,
157     },
158     {
159     0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000,
160     0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000,
161     0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080,
162     0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080,
163     0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080,
164     0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000,
165     0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000,
166     0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080,
167     },
168     {
169     0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000,
170     0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008,
171     0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008,
172     0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000,
173     0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008,
174     0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000,
175     0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008,
176     0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008,
177     },
178     {
179     0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400,
180     0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401,
181     0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001,
182     0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400,
183     0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001,
184     0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400,
185     0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401,
186     0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001,
187     },
188     {
189     0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000,
190     0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020,
191     0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800,
192     0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000,
193     0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820,
194     0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820,
195     0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000,
196     0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800,
197     },
198 };
199 #endif
200
201 static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len) {
202     int i;
203     uint64_t res = 0;
204     for (i = 0; i < shuffle_len; i++)
205         res += res + ((in >> *shuffle++) & 1);
206     return res;
207 }
208
209 static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len) {
210     int i;
211     uint64_t res = 0;
212     shuffle += shuffle_len - 1;
213     for (i = 0; i < shuffle_len; i++) {
214         res |= (in & 1) << *shuffle--;
215         in >>= 1;
216     }
217     return res;
218 }
219
220 static uint32_t f_func(uint32_t r, uint64_t k) {
221     int i;
222     uint32_t out = 0;
223     // rotate to get first part of E-shuffle in the lowest 6 bits
224     r = (r << 1) | (r >> 31);
225     // apply S-boxes, those compress the data again from 8 * 6 to 8 * 4 bits
226     for (i = 7; i >= 0; i--) {
227         uint8_t tmp = (r ^ k) & 0x3f;
228 #if CONFIG_SMALL
229         uint8_t v = S_boxes[i][tmp >> 1];
230         if (tmp & 1) v >>= 4;
231         out = (out >> 4) | (v << 28);
232 #else
233         out |= S_boxes_P_shuffle[i][tmp];
234 #endif
235         // get next 6 bits of E-shuffle and round key k into the lowest bits
236         r = (r >> 4) | (r << 28);
237         k >>= 6;
238     }
239 #if CONFIG_SMALL
240     out = shuffle(out, P_shuffle, sizeof(P_shuffle));
241 #endif
242     return out;
243 }
244
245 /**
246  * @brief rotate the two halves of the expanded 56 bit key each 1 bit left
247  *
248  * Note: the specification calls this "shift", so I kept it although
249  * it is confusing.
250  */
251 static uint64_t key_shift_left(uint64_t CDn) {
252     uint64_t carries = (CDn >> 27) & 0x10000001;
253     CDn <<= 1;
254     CDn &= ~0x10000001;
255     CDn |= carries;
256     return CDn;
257 }
258
259 static void gen_roundkeys(uint64_t K[16], uint64_t key) {
260     int i;
261     // discard parity bits from key and shuffle it into C and D parts
262     uint64_t CDn = shuffle(key, PC1_shuffle, sizeof(PC1_shuffle));
263     // generate round keys
264     for (i = 0; i < 16; i++) {
265         CDn = key_shift_left(CDn);
266         if (i > 1 && i != 8 && i != 15)
267             CDn = key_shift_left(CDn);
268         K[i] = shuffle(CDn, PC2_shuffle, sizeof(PC2_shuffle));
269     }
270 }
271
272 static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt) {
273     int i;
274     // used to apply round keys in reverse order for decryption
275     decrypt = decrypt ? 15 : 0;
276     // shuffle irrelevant to security but to ease hardware implementations
277     in = shuffle(in, IP_shuffle, sizeof(IP_shuffle));
278     for (i = 0; i < 16; i++) {
279         uint32_t f_res;
280         f_res = f_func(in, K[decrypt ^ i]);
281         in = (in << 32) | (in >> 32);
282         in ^= f_res;
283     }
284     in = (in << 32) | (in >> 32);
285     // reverse shuffle used to ease hardware implementations
286     in = shuffle_inv(in, IP_shuffle, sizeof(IP_shuffle));
287     return in;
288 }
289
290 AVDES *av_des_alloc(void)
291 {
292     return av_mallocz(sizeof(struct AVDES));
293 }
294
295 int av_des_init(AVDES *d, const uint8_t *key, int key_bits, av_unused int decrypt) {
296     if (key_bits != 64 && key_bits != 192)
297         return AVERROR(EINVAL);
298     d->triple_des = key_bits > 64;
299     gen_roundkeys(d->round_keys[0], AV_RB64(key));
300     if (d->triple_des) {
301         gen_roundkeys(d->round_keys[1], AV_RB64(key +  8));
302         gen_roundkeys(d->round_keys[2], AV_RB64(key + 16));
303     }
304     return 0;
305 }
306
307 static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt, int mac) {
308     uint64_t iv_val = iv ? AV_RB64(iv) : 0;
309     while (count-- > 0) {
310         uint64_t dst_val;
311         uint64_t src_val = src ? AV_RB64(src) : 0;
312         if (decrypt) {
313             uint64_t tmp = src_val;
314             if (d->triple_des) {
315                 src_val = des_encdec(src_val, d->round_keys[2], 1);
316                 src_val = des_encdec(src_val, d->round_keys[1], 0);
317             }
318             dst_val = des_encdec(src_val, d->round_keys[0], 1) ^ iv_val;
319             iv_val = iv ? tmp : 0;
320         } else {
321             dst_val = des_encdec(src_val ^ iv_val, d->round_keys[0], 0);
322             if (d->triple_des) {
323                 dst_val = des_encdec(dst_val, d->round_keys[1], 1);
324                 dst_val = des_encdec(dst_val, d->round_keys[2], 0);
325             }
326             iv_val = iv ? dst_val : 0;
327         }
328         AV_WB64(dst, dst_val);
329         src += 8;
330         if (!mac)
331             dst += 8;
332     }
333     if (iv)
334         AV_WB64(iv, iv_val);
335 }
336
337 void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt) {
338     av_des_crypt_mac(d, dst, src, count, iv, decrypt, 0);
339 }
340
341 void av_des_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count) {
342     av_des_crypt_mac(d, dst, src, count, (uint8_t[8]){0}, 0, 1);
343 }
344
345 #ifdef TEST
346 #include <stdlib.h>
347 #include <stdio.h>
348
349 #include "time.h"
350
351 static uint64_t rand64(void) {
352     uint64_t r = rand();
353     r = (r << 32) | rand();
354     return r;
355 }
356
357 static const uint8_t test_key[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
358 static const DECLARE_ALIGNED(8, uint8_t, plain)[] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
359 static const DECLARE_ALIGNED(8, uint8_t, crypt)[] = {0x4a, 0xb6, 0x5b, 0x3d, 0x4b, 0x06, 0x15, 0x18};
360 static DECLARE_ALIGNED(8, uint8_t, tmp)[8];
361 static DECLARE_ALIGNED(8, uint8_t, large_buffer)[10002][8];
362 static const uint8_t cbc_key[] = {
363     0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
364     0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
365     0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
366 };
367
368 static int run_test(int cbc, int decrypt) {
369     AVDES d;
370     int delay = cbc && !decrypt ? 2 : 1;
371     uint64_t res;
372     AV_WB64(large_buffer[0], 0x4e6f772069732074ULL);
373     AV_WB64(large_buffer[1], 0x1234567890abcdefULL);
374     AV_WB64(tmp,             0x1234567890abcdefULL);
375     av_des_init(&d, cbc_key, 192, decrypt);
376     av_des_crypt(&d, large_buffer[delay], large_buffer[0], 10000, cbc ? tmp : NULL, decrypt);
377     res = AV_RB64(large_buffer[9999 + delay]);
378     if (cbc) {
379         if (decrypt)
380             return res == 0xc5cecf63ecec514cULL;
381         else
382             return res == 0xcb191f85d1ed8439ULL;
383     } else {
384         if (decrypt)
385             return res == 0x8325397644091a0aULL;
386         else
387             return res == 0xdd17e8b8b437d232ULL;
388     }
389 }
390
391 int main(void) {
392     AVDES d;
393     int i;
394     uint64_t key[3];
395     uint64_t data;
396     uint64_t ct;
397     uint64_t roundkeys[16];
398     srand(av_gettime());
399     key[0] = AV_RB64(test_key);
400     data = AV_RB64(plain);
401     gen_roundkeys(roundkeys, key[0]);
402     if (des_encdec(data, roundkeys, 0) != AV_RB64(crypt)) {
403         printf("Test 1 failed\n");
404         return 1;
405     }
406     av_des_init(&d, test_key, 64, 0);
407     av_des_crypt(&d, tmp, plain, 1, NULL, 0);
408     if (memcmp(tmp, crypt, sizeof(crypt))) {
409         printf("Public API decryption failed\n");
410         return 1;
411     }
412     if (!run_test(0, 0) || !run_test(0, 1) || !run_test(1, 0) || !run_test(1, 1)) {
413         printf("Partial Monte-Carlo test failed\n");
414         return 1;
415     }
416     for (i = 0; i < 1000; i++) {
417         key[0] = rand64(); key[1] = rand64(); key[2] = rand64();
418         data = rand64();
419         av_des_init(&d, (uint8_t*)key, 192, 0);
420         av_des_crypt(&d, (uint8_t*)&ct, (uint8_t*)&data, 1, NULL, 0);
421         av_des_init(&d, (uint8_t*)key, 192, 1);
422         av_des_crypt(&d, (uint8_t*)&ct, (uint8_t*)&ct, 1, NULL, 1);
423         if (ct != data) {
424             printf("Test 2 failed\n");
425             return 1;
426         }
427     }
428 #ifdef GENTABLES
429     printf("static const uint32_t S_boxes_P_shuffle[8][64] = {\n");
430     for (i = 0; i < 8; i++) {
431         int j;
432         printf("    {");
433         for (j = 0; j < 64; j++) {
434             uint32_t v = S_boxes[i][j >> 1];
435             v = j & 1 ? v >> 4 : v & 0xf;
436             v <<= 28 - 4 * i;
437             v = shuffle(v, P_shuffle, sizeof(P_shuffle));
438             printf((j & 7) == 0 ? "\n    " : " ");
439             printf("0x%08X,", v);
440         }
441         printf("\n    },\n");
442     }
443     printf("};\n");
444 #endif
445     return 0;
446 }
447 #endif