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