libavutil/des.c
Go to the documentation of this file.
00001 /*
00002  * DES encryption/decryption
00003  * Copyright (c) 2007 Reimar Doeffinger
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 #include <inttypes.h>
00022 #include "avutil.h"
00023 #include "common.h"
00024 #include "intreadwrite.h"
00025 #include "des.h"
00026 
00027 typedef struct AVDES AVDES;
00028 
00029 #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
00030 static const uint8_t IP_shuffle[] = {
00031     T(58, 50, 42, 34, 26, 18, 10, 2),
00032     T(60, 52, 44, 36, 28, 20, 12, 4),
00033     T(62, 54, 46, 38, 30, 22, 14, 6),
00034     T(64, 56, 48, 40, 32, 24, 16, 8),
00035     T(57, 49, 41, 33, 25, 17,  9, 1),
00036     T(59, 51, 43, 35, 27, 19, 11, 3),
00037     T(61, 53, 45, 37, 29, 21, 13, 5),
00038     T(63, 55, 47, 39, 31, 23, 15, 7)
00039 };
00040 #undef T
00041 
00042 #if CONFIG_SMALL || defined(GENTABLES)
00043 #define T(a, b, c, d) 32-a,32-b,32-c,32-d
00044 static const uint8_t P_shuffle[] = {
00045     T(16,  7, 20, 21),
00046     T(29, 12, 28, 17),
00047     T( 1, 15, 23, 26),
00048     T( 5, 18, 31, 10),
00049     T( 2,  8, 24, 14),
00050     T(32, 27,  3,  9),
00051     T(19, 13, 30,  6),
00052     T(22, 11,  4, 25)
00053 };
00054 #undef T
00055 #endif
00056 
00057 #define T(a, b, c, d, e, f, g) 64-a,64-b,64-c,64-d,64-e,64-f,64-g
00058 static const uint8_t PC1_shuffle[] = {
00059     T(57, 49, 41, 33, 25, 17,  9),
00060     T( 1, 58, 50, 42, 34, 26, 18),
00061     T(10,  2, 59, 51, 43, 35, 27),
00062     T(19, 11,  3, 60, 52, 44, 36),
00063     T(63, 55, 47, 39, 31, 23, 15),
00064     T( 7, 62, 54, 46, 38, 30, 22),
00065     T(14,  6, 61, 53, 45, 37, 29),
00066     T(21, 13,  5, 28, 20, 12,  4)
00067 };
00068 #undef T
00069 
00070 #define T(a, b, c, d, e, f) 56-a,56-b,56-c,56-d,56-e,56-f
00071 static const uint8_t PC2_shuffle[] = {
00072     T(14, 17, 11, 24,  1,  5),
00073     T( 3, 28, 15,  6, 21, 10),
00074     T(23, 19, 12,  4, 26,  8),
00075     T(16,  7, 27, 20, 13,  2),
00076     T(41, 52, 31, 37, 47, 55),
00077     T(30, 40, 51, 45, 33, 48),
00078     T(44, 49, 39, 56, 34, 53),
00079     T(46, 42, 50, 36, 29, 32)
00080 };
00081 #undef T
00082 
00083 #if CONFIG_SMALL
00084 static const uint8_t S_boxes[8][32] = {
00085     {
00086     0x0e, 0xf4, 0x7d, 0x41, 0xe2, 0x2f, 0xdb, 0x18, 0xa3, 0x6a, 0xc6, 0xbc, 0x95, 0x59, 0x30, 0x87,
00087     0xf4, 0xc1, 0x8e, 0x28, 0x4d, 0x96, 0x12, 0x7b, 0x5f, 0xbc, 0x39, 0xe7, 0xa3, 0x0a, 0x65, 0xd0,
00088     }, {
00089     0x3f, 0xd1, 0x48, 0x7e, 0xf6, 0x2b, 0x83, 0xe4, 0xc9, 0x07, 0x12, 0xad, 0x6c, 0x90, 0xb5, 0x5a,
00090     0xd0, 0x8e, 0xa7, 0x1b, 0x3a, 0xf4, 0x4d, 0x21, 0xb5, 0x68, 0x7c, 0xc6, 0x09, 0x53, 0xe2, 0x9f,
00091     }, {
00092     0xda, 0x70, 0x09, 0x9e, 0x36, 0x43, 0x6f, 0xa5, 0x21, 0x8d, 0x5c, 0xe7, 0xcb, 0xb4, 0xf2, 0x18,
00093     0x1d, 0xa6, 0xd4, 0x09, 0x68, 0x9f, 0x83, 0x70, 0x4b, 0xf1, 0xe2, 0x3c, 0xb5, 0x5a, 0x2e, 0xc7,
00094     }, {
00095     0xd7, 0x8d, 0xbe, 0x53, 0x60, 0xf6, 0x09, 0x3a, 0x41, 0x72, 0x28, 0xc5, 0x1b, 0xac, 0xe4, 0x9f,
00096     0x3a, 0xf6, 0x09, 0x60, 0xac, 0x1b, 0xd7, 0x8d, 0x9f, 0x41, 0x53, 0xbe, 0xc5, 0x72, 0x28, 0xe4,
00097     }, {
00098     0xe2, 0xbc, 0x24, 0xc1, 0x47, 0x7a, 0xdb, 0x16, 0x58, 0x05, 0xf3, 0xaf, 0x3d, 0x90, 0x8e, 0x69,
00099     0xb4, 0x82, 0xc1, 0x7b, 0x1a, 0xed, 0x27, 0xd8, 0x6f, 0xf9, 0x0c, 0x95, 0xa6, 0x43, 0x50, 0x3e,
00100     }, {
00101     0xac, 0xf1, 0x4a, 0x2f, 0x79, 0xc2, 0x96, 0x58, 0x60, 0x1d, 0xd3, 0xe4, 0x0e, 0xb7, 0x35, 0x8b,
00102     0x49, 0x3e, 0x2f, 0xc5, 0x92, 0x58, 0xfc, 0xa3, 0xb7, 0xe0, 0x14, 0x7a, 0x61, 0x0d, 0x8b, 0xd6,
00103     }, {
00104     0xd4, 0x0b, 0xb2, 0x7e, 0x4f, 0x90, 0x18, 0xad, 0xe3, 0x3c, 0x59, 0xc7, 0x25, 0xfa, 0x86, 0x61,
00105     0x61, 0xb4, 0xdb, 0x8d, 0x1c, 0x43, 0xa7, 0x7e, 0x9a, 0x5f, 0x06, 0xf8, 0xe0, 0x25, 0x39, 0xc2,
00106     }, {
00107     0x1d, 0xf2, 0xd8, 0x84, 0xa6, 0x3f, 0x7b, 0x41, 0xca, 0x59, 0x63, 0xbe, 0x05, 0xe0, 0x9c, 0x27,
00108     0x27, 0x1b, 0xe4, 0x71, 0x49, 0xac, 0x8e, 0xd2, 0xf0, 0xc6, 0x9a, 0x0d, 0x3f, 0x53, 0x65, 0xb8,
00109     }
00110 };
00111 #else
00112 
00116 static const uint32_t S_boxes_P_shuffle[8][64] = {
00117     {
00118     0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000,
00119     0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002,
00120     0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202,
00121     0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000,
00122     0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200,
00123     0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202,
00124     0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200,
00125     0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002,
00126     },
00127     {
00128     0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010,
00129     0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010,
00130     0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000,
00131     0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010,
00132     0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000,
00133     0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000,
00134     0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010,
00135     0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000,
00136     },
00137     {
00138     0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100,
00139     0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104,
00140     0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104,
00141     0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000,
00142     0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000,
00143     0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004,
00144     0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004,
00145     0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100,
00146     },
00147     {
00148     0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000,
00149     0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000,
00150     0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040,
00151     0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040,
00152     0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000,
00153     0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040,
00154     0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040,
00155     0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040,
00156     },
00157     {
00158     0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000,
00159     0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000,
00160     0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080,
00161     0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080,
00162     0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080,
00163     0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000,
00164     0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000,
00165     0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080,
00166     },
00167     {
00168     0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000,
00169     0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008,
00170     0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008,
00171     0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000,
00172     0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008,
00173     0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000,
00174     0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008,
00175     0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008,
00176     },
00177     {
00178     0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400,
00179     0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401,
00180     0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001,
00181     0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400,
00182     0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001,
00183     0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400,
00184     0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401,
00185     0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001,
00186     },
00187     {
00188     0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000,
00189     0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020,
00190     0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800,
00191     0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000,
00192     0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820,
00193     0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820,
00194     0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000,
00195     0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800,
00196     },
00197 };
00198 #endif
00199 
00200 static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len) {
00201     int i;
00202     uint64_t res = 0;
00203     for (i = 0; i < shuffle_len; i++)
00204         res += res + ((in >> *shuffle++) & 1);
00205     return res;
00206 }
00207 
00208 static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len) {
00209     int i;
00210     uint64_t res = 0;
00211     shuffle += shuffle_len - 1;
00212     for (i = 0; i < shuffle_len; i++) {
00213         res |= (in & 1) << *shuffle--;
00214         in >>= 1;
00215     }
00216     return res;
00217 }
00218 
00219 static uint32_t f_func(uint32_t r, uint64_t k) {
00220     int i;
00221     uint32_t out = 0;
00222     // rotate to get first part of E-shuffle in the lowest 6 bits
00223     r = (r << 1) | (r >> 31);
00224     // apply S-boxes, those compress the data again from 8 * 6 to 8 * 4 bits
00225     for (i = 7; i >= 0; i--) {
00226         uint8_t tmp = (r ^ k) & 0x3f;
00227 #if CONFIG_SMALL
00228         uint8_t v = S_boxes[i][tmp >> 1];
00229         if (tmp & 1) v >>= 4;
00230         out = (out >> 4) | (v << 28);
00231 #else
00232         out |= S_boxes_P_shuffle[i][tmp];
00233 #endif
00234         // get next 6 bits of E-shuffle and round key k into the lowest bits
00235         r = (r >> 4) | (r << 28);
00236         k >>= 6;
00237     }
00238 #if CONFIG_SMALL
00239     out = shuffle(out, P_shuffle, sizeof(P_shuffle));
00240 #endif
00241     return out;
00242 }
00243 
00250 static uint64_t key_shift_left(uint64_t CDn) {
00251     uint64_t carries = (CDn >> 27) & 0x10000001;
00252     CDn <<= 1;
00253     CDn &= ~0x10000001;
00254     CDn |= carries;
00255     return CDn;
00256 }
00257 
00258 static void gen_roundkeys(uint64_t K[16], uint64_t key) {
00259     int i;
00260     // discard parity bits from key and shuffle it into C and D parts
00261     uint64_t CDn = shuffle(key, PC1_shuffle, sizeof(PC1_shuffle));
00262     // generate round keys
00263     for (i = 0; i < 16; i++) {
00264         CDn = key_shift_left(CDn);
00265         if (i > 1 && i != 8 && i != 15)
00266             CDn = key_shift_left(CDn);
00267         K[i] = shuffle(CDn, PC2_shuffle, sizeof(PC2_shuffle));
00268     }
00269 }
00270 
00271 static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt) {
00272     int i;
00273     // used to apply round keys in reverse order for decryption
00274     decrypt = decrypt ? 15 : 0;
00275     // shuffle irrelevant to security but to ease hardware implementations
00276     in = shuffle(in, IP_shuffle, sizeof(IP_shuffle));
00277     for (i = 0; i < 16; i++) {
00278         uint32_t f_res;
00279         f_res = f_func(in, K[decrypt ^ i]);
00280         in = (in << 32) | (in >> 32);
00281         in ^= f_res;
00282     }
00283     in = (in << 32) | (in >> 32);
00284     // reverse shuffle used to ease hardware implementations
00285     in = shuffle_inv(in, IP_shuffle, sizeof(IP_shuffle));
00286     return in;
00287 }
00288 
00289 int av_des_init(AVDES *d, const uint8_t *key, int key_bits, int decrypt) {
00290     if (key_bits != 64 && key_bits != 192)
00291         return -1;
00292     d->triple_des = key_bits > 64;
00293     gen_roundkeys(d->round_keys[0], AV_RB64(key));
00294     if (d->triple_des) {
00295         gen_roundkeys(d->round_keys[1], AV_RB64(key +  8));
00296         gen_roundkeys(d->round_keys[2], AV_RB64(key + 16));
00297     }
00298     return 0;
00299 }
00300 
00301 static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt, int mac) {
00302     uint64_t iv_val = iv ? AV_RB64(iv) : 0;
00303     while (count-- > 0) {
00304         uint64_t dst_val;
00305         uint64_t src_val = src ? AV_RB64(src) : 0;
00306         if (decrypt) {
00307             uint64_t tmp = src_val;
00308             if (d->triple_des) {
00309                 src_val = des_encdec(src_val, d->round_keys[2], 1);
00310                 src_val = des_encdec(src_val, d->round_keys[1], 0);
00311             }
00312             dst_val = des_encdec(src_val, d->round_keys[0], 1) ^ iv_val;
00313             iv_val = iv ? tmp : 0;
00314         } else {
00315             dst_val = des_encdec(src_val ^ iv_val, d->round_keys[0], 0);
00316             if (d->triple_des) {
00317                 dst_val = des_encdec(dst_val, d->round_keys[1], 1);
00318                 dst_val = des_encdec(dst_val, d->round_keys[2], 0);
00319             }
00320             iv_val = iv ? dst_val : 0;
00321         }
00322         AV_WB64(dst, dst_val);
00323         src += 8;
00324         if (!mac)
00325             dst += 8;
00326     }
00327     if (iv)
00328         AV_WB64(iv, iv_val);
00329 }
00330 
00331 void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt) {
00332     av_des_crypt_mac(d, dst, src, count, iv, decrypt, 0);
00333 }
00334 
00335 void av_des_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count) {
00336     av_des_crypt_mac(d, dst, src, count, (uint8_t[8]){0}, 0, 1);
00337 }
00338 
00339 #ifdef TEST
00340 // LCOV_EXCL_START
00341 #undef printf
00342 #undef rand
00343 #undef srand
00344 #include <stdlib.h>
00345 #include <stdio.h>
00346 #include <sys/time.h>
00347 static uint64_t rand64(void) {
00348     uint64_t r = rand();
00349     r = (r << 32) | rand();
00350     return r;
00351 }
00352 
00353 static const uint8_t test_key[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
00354 static const DECLARE_ALIGNED(8, uint8_t, plain)[] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
00355 static const DECLARE_ALIGNED(8, uint8_t, crypt)[] = {0x4a, 0xb6, 0x5b, 0x3d, 0x4b, 0x06, 0x15, 0x18};
00356 static DECLARE_ALIGNED(8, uint8_t, tmp)[8];
00357 static DECLARE_ALIGNED(8, uint8_t, large_buffer)[10002][8];
00358 static const uint8_t cbc_key[] = {
00359     0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
00360     0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
00361     0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
00362 };
00363 
00364 static int run_test(int cbc, int decrypt) {
00365     AVDES d;
00366     int delay = cbc && !decrypt ? 2 : 1;
00367     uint64_t res;
00368     AV_WB64(large_buffer[0], 0x4e6f772069732074ULL);
00369     AV_WB64(large_buffer[1], 0x1234567890abcdefULL);
00370     AV_WB64(tmp,             0x1234567890abcdefULL);
00371     av_des_init(&d, cbc_key, 192, decrypt);
00372     av_des_crypt(&d, large_buffer[delay], large_buffer[0], 10000, cbc ? tmp : NULL, decrypt);
00373     res = AV_RB64(large_buffer[9999 + delay]);
00374     if (cbc) {
00375         if (decrypt)
00376             return res == 0xc5cecf63ecec514cULL;
00377         else
00378             return res == 0xcb191f85d1ed8439ULL;
00379     } else {
00380         if (decrypt)
00381             return res == 0x8325397644091a0aULL;
00382         else
00383             return res == 0xdd17e8b8b437d232ULL;
00384     }
00385 }
00386 
00387 int main(void) {
00388     AVDES d;
00389     int i;
00390 #ifdef GENTABLES
00391     int j;
00392 #endif
00393     struct timeval tv;
00394     uint64_t key[3];
00395     uint64_t data;
00396     uint64_t ct;
00397     uint64_t roundkeys[16];
00398     gettimeofday(&tv, NULL);
00399     srand(tv.tv_sec * 1000 * 1000 + tv.tv_usec);
00400     key[0] = AV_RB64(test_key);
00401     data = AV_RB64(plain);
00402     gen_roundkeys(roundkeys, key[0]);
00403     if (des_encdec(data, roundkeys, 0) != AV_RB64(crypt)) {
00404         printf("Test 1 failed\n");
00405         return 1;
00406     }
00407     av_des_init(&d, test_key, 64, 0);
00408     av_des_crypt(&d, tmp, plain, 1, NULL, 0);
00409     if (memcmp(tmp, crypt, sizeof(crypt))) {
00410         printf("Public API decryption failed\n");
00411         return 1;
00412     }
00413     if (!run_test(0, 0) || !run_test(0, 1) || !run_test(1, 0) || !run_test(1, 1)) {
00414         printf("Partial Monte-Carlo test failed\n");
00415         return 1;
00416     }
00417     for (i = 0; i < 1000; i++) {
00418         key[0] = rand64(); key[1] = rand64(); key[2] = rand64();
00419         data = rand64();
00420         av_des_init(&d, key, 192, 0);
00421         av_des_crypt(&d, &ct, &data, 1, NULL, 0);
00422         av_des_init(&d, key, 192, 1);
00423         av_des_crypt(&d, &ct, &ct, 1, NULL, 1);
00424         if (ct != data) {
00425             printf("Test 2 failed\n");
00426             return 1;
00427         }
00428     }
00429 #ifdef GENTABLES
00430     printf("static const uint32_t S_boxes_P_shuffle[8][64] = {\n");
00431     for (i = 0; i < 8; i++) {
00432         printf("    {");
00433         for (j = 0; j < 64; j++) {
00434             uint32_t v = S_boxes[i][j >> 1];
00435             v = j & 1 ? v >> 4 : v & 0xf;
00436             v <<= 28 - 4 * i;
00437             v = shuffle(v, P_shuffle, sizeof(P_shuffle));
00438             printf((j & 7) == 0 ? "\n    " : " ");
00439             printf("0x%08X,", v);
00440         }
00441         printf("\n    },\n");
00442     }
00443     printf("};\n");
00444 #endif
00445     return 0;
00446 }
00447 // LCOV_EXCL_STOP
00448 #endif