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