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
27typedef 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
30static 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
43static 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
56static 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
69static 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
82static 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 */
114static 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
198static 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
206static 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
217static 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 */
248static 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
256static 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
269static 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
288uint64_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
295int 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
307void 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>
343static uint64_t rand64(void) {
344    uint64_t r = rand();
345    r = (r << 32) | rand();
346    return r;
347}
348
349static const uint8_t test_key[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
350static const DECLARE_ALIGNED(8, uint8_t, plain[]) = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
351static const DECLARE_ALIGNED(8, uint8_t, crypt[]) = {0x4a, 0xb6, 0x5b, 0x3d, 0x4b, 0x06, 0x15, 0x18};
352static DECLARE_ALIGNED(8, uint8_t, tmp[8]);
353static DECLARE_ALIGNED(8, uint8_t, large_buffer[10002][8]);
354static 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
360int 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
383int 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
444