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