testprogs: K&R formatting cosmetics
[libav.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