Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 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 
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
#if CONFIG_SMALL || defined(GENTABLES)
43
#define T(a, b, c, d) 32-a,32-b,32-c,32-d
44
static 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
58
static 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
71
static 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
84
static 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
 */
116
static 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
 
200
static 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
 
208
static 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
 
219
static 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
 */
250
static 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
 
258
static 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
 
271
static 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
 
289
int av_des_init(AVDES *d, const uint8_t *key, int key_bits, av_unused 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
 
301
static 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
 
331
void 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
 
335
void 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
#include 
341
#include 
342
 
343
#include "time.h"
344
 
345
static uint64_t rand64(void) {
346
    uint64_t r = rand();
347
    r = (r << 32) | rand();
348
    return r;
349
}
350
 
351
static const uint8_t test_key[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
352
static const DECLARE_ALIGNED(8, uint8_t, plain)[] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
353
static const DECLARE_ALIGNED(8, uint8_t, crypt)[] = {0x4a, 0xb6, 0x5b, 0x3d, 0x4b, 0x06, 0x15, 0x18};
354
static DECLARE_ALIGNED(8, uint8_t, tmp)[8];
355
static DECLARE_ALIGNED(8, uint8_t, large_buffer)[10002][8];
356
static const uint8_t cbc_key[] = {
357
    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
358
    0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
359
    0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
360
};
361
 
362
static int run_test(int cbc, int decrypt) {
363
    AVDES d;
364
    int delay = cbc && !decrypt ? 2 : 1;
365
    uint64_t res;
366
    AV_WB64(large_buffer[0], 0x4e6f772069732074ULL);
367
    AV_WB64(large_buffer[1], 0x1234567890abcdefULL);
368
    AV_WB64(tmp,             0x1234567890abcdefULL);
369
    av_des_init(&d, cbc_key, 192, decrypt);
370
    av_des_crypt(&d, large_buffer[delay], large_buffer[0], 10000, cbc ? tmp : NULL, decrypt);
371
    res = AV_RB64(large_buffer[9999 + delay]);
372
    if (cbc) {
373
        if (decrypt)
374
            return res == 0xc5cecf63ecec514cULL;
375
        else
376
            return res == 0xcb191f85d1ed8439ULL;
377
    } else {
378
        if (decrypt)
379
            return res == 0x8325397644091a0aULL;
380
        else
381
            return res == 0xdd17e8b8b437d232ULL;
382
    }
383
}
384
 
385
int main(void) {
386
    AVDES d;
387
    int i;
388
#ifdef GENTABLES
389
    int j;
390
#endif
391
    uint64_t key[3];
392
    uint64_t data;
393
    uint64_t ct;
394
    uint64_t roundkeys[16];
395
    srand(av_gettime());
396
    key[0] = AV_RB64(test_key);
397
    data = AV_RB64(plain);
398
    gen_roundkeys(roundkeys, key[0]);
399
    if (des_encdec(data, roundkeys, 0) != AV_RB64(crypt)) {
400
        printf("Test 1 failed\n");
401
        return 1;
402
    }
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 < 1000; i++) {
414
        key[0] = rand64(); key[1] = rand64(); key[2] = rand64();
415
        data = rand64();
416
        av_des_init(&d, (uint8_t*)key, 192, 0);
417
        av_des_crypt(&d, (uint8_t*)&ct, (uint8_t*)&data, 1, NULL, 0);
418
        av_des_init(&d, (uint8_t*)key, 192, 1);
419
        av_des_crypt(&d, (uint8_t*)&ct, (uint8_t*)&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