PageRenderTime 63ms CodeModel.GetById 11ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 0ms

/libavutil/des.c

http://github.com/FFmpeg/FFmpeg
C | 331 lines | 275 code | 18 blank | 38 comment | 24 complexity | 44976855ba5356f39636fd0a13ad7e1b MD5 | raw file
  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
 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#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
 31static const uint8_t IP_shuffle[] = {
 32    T(58, 50, 42, 34, 26, 18, 10, 2),
 33    T(60, 52, 44, 36, 28, 20, 12, 4),
 34    T(62, 54, 46, 38, 30, 22, 14, 6),
 35    T(64, 56, 48, 40, 32, 24, 16, 8),
 36    T(57, 49, 41, 33, 25, 17,  9, 1),
 37    T(59, 51, 43, 35, 27, 19, 11, 3),
 38    T(61, 53, 45, 37, 29, 21, 13, 5),
 39    T(63, 55, 47, 39, 31, 23, 15, 7)
 40};
 41#undef T
 42
 43#if CONFIG_SMALL || defined(GENTABLES)
 44#define T(a, b, c, d) 32 - a, 32 - b, 32 - c, 32 - d
 45static const uint8_t P_shuffle[] = {
 46    T(16,  7, 20, 21),
 47    T(29, 12, 28, 17),
 48    T( 1, 15, 23, 26),
 49    T( 5, 18, 31, 10),
 50    T( 2,  8, 24, 14),
 51    T(32, 27,  3,  9),
 52    T(19, 13, 30,  6),
 53    T(22, 11,  4, 25)
 54};
 55#undef T
 56#endif
 57
 58#define T(a, b, c, d, e, f, g) 64 - a, 64 - b, 64 - c, 64 - d, 64 - e, 64 - f, 64 - g
 59static const uint8_t PC1_shuffle[] = {
 60    T(57, 49, 41, 33, 25, 17,  9),
 61    T( 1, 58, 50, 42, 34, 26, 18),
 62    T(10,  2, 59, 51, 43, 35, 27),
 63    T(19, 11,  3, 60, 52, 44, 36),
 64    T(63, 55, 47, 39, 31, 23, 15),
 65    T( 7, 62, 54, 46, 38, 30, 22),
 66    T(14,  6, 61, 53, 45, 37, 29),
 67    T(21, 13,  5, 28, 20, 12,  4)
 68};
 69#undef T
 70
 71#define T(a, b, c, d, e, f) 56 - a, 56 - b, 56 - c, 56 - d, 56 - e, 56 - f
 72static const uint8_t PC2_shuffle[] = {
 73    T(14, 17, 11, 24,  1,  5),
 74    T( 3, 28, 15,  6, 21, 10),
 75    T(23, 19, 12,  4, 26,  8),
 76    T(16,  7, 27, 20, 13,  2),
 77    T(41, 52, 31, 37, 47, 55),
 78    T(30, 40, 51, 45, 33, 48),
 79    T(44, 49, 39, 56, 34, 53),
 80    T(46, 42, 50, 36, 29, 32)
 81};
 82#undef T
 83
 84#if CONFIG_SMALL
 85static const uint8_t S_boxes[8][32] = {
 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    { 0x3f, 0xd1, 0x48, 0x7e, 0xf6, 0x2b, 0x83, 0xe4, 0xc9, 0x07, 0x12, 0xad, 0x6c, 0x90, 0xb5, 0x5a,
 89      0xd0, 0x8e, 0xa7, 0x1b, 0x3a, 0xf4, 0x4d, 0x21, 0xb5, 0x68, 0x7c, 0xc6, 0x09, 0x53, 0xe2, 0x9f, },
 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    { 0xd7, 0x8d, 0xbe, 0x53, 0x60, 0xf6, 0x09, 0x3a, 0x41, 0x72, 0x28, 0xc5, 0x1b, 0xac, 0xe4, 0x9f,
 93      0x3a, 0xf6, 0x09, 0x60, 0xac, 0x1b, 0xd7, 0x8d, 0x9f, 0x41, 0x53, 0xbe, 0xc5, 0x72, 0x28, 0xe4, },
 94    { 0xe2, 0xbc, 0x24, 0xc1, 0x47, 0x7a, 0xdb, 0x16, 0x58, 0x05, 0xf3, 0xaf, 0x3d, 0x90, 0x8e, 0x69,
 95      0xb4, 0x82, 0xc1, 0x7b, 0x1a, 0xed, 0x27, 0xd8, 0x6f, 0xf9, 0x0c, 0x95, 0xa6, 0x43, 0x50, 0x3e, },
 96    { 0xac, 0xf1, 0x4a, 0x2f, 0x79, 0xc2, 0x96, 0x58, 0x60, 0x1d, 0xd3, 0xe4, 0x0e, 0xb7, 0x35, 0x8b,
 97      0x49, 0x3e, 0x2f, 0xc5, 0x92, 0x58, 0xfc, 0xa3, 0xb7, 0xe0, 0x14, 0x7a, 0x61, 0x0d, 0x8b, 0xd6, },
 98    { 0xd4, 0x0b, 0xb2, 0x7e, 0x4f, 0x90, 0x18, 0xad, 0xe3, 0x3c, 0x59, 0xc7, 0x25, 0xfa, 0x86, 0x61,
 99      0x61, 0xb4, 0xdb, 0x8d, 0x1c, 0x43, 0xa7, 0x7e, 0x9a, 0x5f, 0x06, 0xf8, 0xe0, 0x25, 0x39, 0xc2, },
100    { 0x1d, 0xf2, 0xd8, 0x84, 0xa6, 0x3f, 0x7b, 0x41, 0xca, 0x59, 0x63, 0xbe, 0x05, 0xe0, 0x9c, 0x27,
101      0x27, 0x1b, 0xe4, 0x71, 0x49, 0xac, 0x8e, 0xd2, 0xf0, 0xc6, 0x9a, 0x0d, 0x3f, 0x53, 0x65, 0xb8,
102    }
103};
104#else
105/**
106 * This table contains the results of applying both the S-box and P-shuffle.
107 * It can be regenerated by compiling tests/des.c with "-DCONFIG_SMALL -DGENTABLES".
108 */
109static const uint32_t S_boxes_P_shuffle[8][64] = {
110    { 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000,
111      0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002,
112      0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202,
113      0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000,
114      0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200,
115      0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202,
116      0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200,
117      0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002, },
118    { 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010,
119      0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010,
120      0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000,
121      0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010,
122      0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000,
123      0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000,
124      0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010,
125      0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000, },
126    { 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100,
127      0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104,
128      0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104,
129      0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000,
130      0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000,
131      0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004,
132      0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004,
133      0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100, },
134    { 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000,
135      0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000,
136      0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040,
137      0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040,
138      0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000,
139      0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040,
140      0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040,
141      0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040, },
142    { 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000,
143      0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000,
144      0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080,
145      0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080,
146      0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080,
147      0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000,
148      0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000,
149      0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080, },
150    { 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000,
151      0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008,
152      0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008,
153      0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000,
154      0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008,
155      0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000,
156      0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008,
157      0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008, },
158    { 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400,
159      0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401,
160      0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001,
161      0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400,
162      0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001,
163      0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400,
164      0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401,
165      0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001, },
166    { 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000,
167      0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020,
168      0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800,
169      0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000,
170      0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820,
171      0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820,
172      0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000,
173      0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800, },
174};
175#endif
176
177static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len)
178{
179    int i;
180    uint64_t res = 0;
181    for (i = 0; i < shuffle_len; i++)
182        res += res + ((in >> *shuffle++) & 1);
183    return res;
184}
185
186static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len)
187{
188    int i;
189    uint64_t res = 0;
190    shuffle += shuffle_len - 1;
191    for (i = 0; i < shuffle_len; i++) {
192        res |= (in & 1) << *shuffle--;
193        in >>= 1;
194    }
195    return res;
196}
197
198static uint32_t f_func(uint32_t r, uint64_t k)
199{
200    int i;
201    uint32_t out = 0;
202    // rotate to get first part of E-shuffle in the lowest 6 bits
203    r = (r << 1) | (r >> 31);
204    // apply S-boxes, those compress the data again from 8 * 6 to 8 * 4 bits
205    for (i = 7; i >= 0; i--) {
206        uint8_t tmp = (r ^ k) & 0x3f;
207#if CONFIG_SMALL
208        uint8_t v = S_boxes[i][tmp >> 1];
209        if (tmp & 1)
210            v >>= 4;
211        out = (out >> 4) | (v << 28);
212#else
213        out |= S_boxes_P_shuffle[i][tmp];
214#endif
215        // get next 6 bits of E-shuffle and round key k into the lowest bits
216        r   = (r >> 4) | (r << 28);
217        k >>= 6;
218    }
219#if CONFIG_SMALL
220    out = shuffle(out, P_shuffle, sizeof(P_shuffle));
221#endif
222    return out;
223}
224
225/**
226 * @brief rotate the two halves of the expanded 56 bit key each 1 bit left
227 *
228 * Note: the specification calls this "shift", so I kept it although
229 * it is confusing.
230 */
231static uint64_t key_shift_left(uint64_t CDn)
232{
233    uint64_t carries = (CDn >> 27) & 0x10000001;
234    CDn <<= 1;
235    CDn  &= ~0x10000001;
236    CDn  |= carries;
237    return CDn;
238}
239
240static void gen_roundkeys(uint64_t K[16], uint64_t key)
241{
242    int i;
243    // discard parity bits from key and shuffle it into C and D parts
244    uint64_t CDn = shuffle(key, PC1_shuffle, sizeof(PC1_shuffle));
245    // generate round keys
246    for (i = 0; i < 16; i++) {
247        CDn = key_shift_left(CDn);
248        if (i > 1 && i != 8 && i != 15)
249            CDn = key_shift_left(CDn);
250        K[i] = shuffle(CDn, PC2_shuffle, sizeof(PC2_shuffle));
251    }
252}
253
254static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt)
255{
256    int i;
257    // used to apply round keys in reverse order for decryption
258    decrypt = decrypt ? 15 : 0;
259    // shuffle irrelevant to security but to ease hardware implementations
260    in = shuffle(in, IP_shuffle, sizeof(IP_shuffle));
261    for (i = 0; i < 16; i++) {
262        uint32_t f_res;
263        f_res = f_func(in, K[decrypt ^ i]);
264        in    = (in << 32) | (in >> 32);
265        in   ^= f_res;
266    }
267    in = (in << 32) | (in >> 32);
268    // reverse shuffle used to ease hardware implementations
269    in = shuffle_inv(in, IP_shuffle, sizeof(IP_shuffle));
270    return in;
271}
272
273AVDES *av_des_alloc(void)
274{
275    return av_mallocz(sizeof(struct AVDES));
276}
277
278int av_des_init(AVDES *d, const uint8_t *key, int key_bits, av_unused int decrypt) {
279    if (key_bits != 64 && key_bits != 192)
280        return AVERROR(EINVAL);
281    d->triple_des = key_bits > 64;
282    gen_roundkeys(d->round_keys[0], AV_RB64(key));
283    if (d->triple_des) {
284        gen_roundkeys(d->round_keys[1], AV_RB64(key +  8));
285        gen_roundkeys(d->round_keys[2], AV_RB64(key + 16));
286    }
287    return 0;
288}
289
290static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src,
291                             int count, uint8_t *iv, int decrypt, int mac)
292{
293    uint64_t iv_val = iv ? AV_RB64(iv) : 0;
294    while (count-- > 0) {
295        uint64_t dst_val;
296        uint64_t src_val = src ? AV_RB64(src) : 0;
297        if (decrypt) {
298            uint64_t tmp = src_val;
299            if (d->triple_des) {
300                src_val = des_encdec(src_val, d->round_keys[2], 1);
301                src_val = des_encdec(src_val, d->round_keys[1], 0);
302            }
303            dst_val = des_encdec(src_val, d->round_keys[0], 1) ^ iv_val;
304            iv_val  = iv ? tmp : 0;
305        } else {
306            dst_val = des_encdec(src_val ^ iv_val, d->round_keys[0], 0);
307            if (d->triple_des) {
308                dst_val = des_encdec(dst_val, d->round_keys[1], 1);
309                dst_val = des_encdec(dst_val, d->round_keys[2], 0);
310            }
311            iv_val = iv ? dst_val : 0;
312        }
313        AV_WB64(dst, dst_val);
314        src += 8;
315        if (!mac)
316            dst += 8;
317    }
318    if (iv)
319        AV_WB64(iv, iv_val);
320}
321
322void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src,
323                  int count, uint8_t *iv, int decrypt)
324{
325    av_des_crypt_mac(d, dst, src, count, iv, decrypt, 0);
326}
327
328void av_des_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count)
329{
330    av_des_crypt_mac(d, dst, src, count, (uint8_t[8]) { 0 }, 0, 1);
331}