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