3 This file is part of the ARM-Crypto-Lib.
4 Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de)
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 * \email daniel.otte@rub.de
24 * \brief DES and EDE-DES implementation
25 * \license GPLv3 or later
30 #include <avr/pgmspace.h>
32 const uint8_t sbox[256] PROGMEM = {
34 0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07,
35 0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38,
36 0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50,
37 0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D,
39 0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A,
40 0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5,
41 0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F,
42 0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9,
44 0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28,
45 0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1,
46 0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7,
47 0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C,
49 0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F,
50 0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9,
51 0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84,
52 0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E,
54 0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9,
55 0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86,
56 0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E,
57 0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53,
59 0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B,
60 0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38,
61 0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6,
62 0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D,
64 0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61,
65 0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86,
66 0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92,
67 0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C,
69 0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7,
70 0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92,
71 0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58,
72 0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B
75 const uint8_t e_permtab[] PROGMEM = {
76 4, 6, /* 4 bytes in 6 bytes out*/
80 12, 13, 14, 15, 16, 17,
81 16, 17, 18, 19, 20, 21,
82 20, 21, 22, 23, 24, 25,
83 24, 25, 26, 27, 28, 29,
87 const uint8_t p_permtab[] PROGMEM = {
88 4, 4, /* 32 bit -> 32 bit */
99 const uint8_t ip_permtab[] PROGMEM = {
100 8, 8, /* 64 bit -> 64 bit */
101 58, 50, 42, 34, 26, 18, 10, 2,
102 60, 52, 44, 36, 28, 20, 12, 4,
103 62, 54, 46, 38, 30, 22, 14, 6,
104 64, 56, 48, 40, 32, 24, 16, 8,
105 57, 49, 41, 33, 25, 17, 9, 1,
106 59, 51, 43, 35, 27, 19, 11, 3,
107 61, 53, 45, 37, 29, 21, 13, 5,
108 63, 55, 47, 39, 31, 23, 15, 7
111 const uint8_t inv_ip_permtab[] PROGMEM = {
112 8, 8, /* 64 bit -> 64 bit */
113 40, 8, 48, 16, 56, 24, 64, 32,
114 39, 7, 47, 15, 55, 23, 63, 31,
115 38, 6, 46, 14, 54, 22, 62, 30,
116 37, 5, 45, 13, 53, 21, 61, 29,
117 36, 4, 44, 12, 52, 20, 60, 28,
118 35, 3, 43, 11, 51, 19, 59, 27,
119 34, 2, 42, 10, 50, 18, 58, 26,
120 33, 1, 41, 9, 49, 17, 57, 25
123 const uint8_t pc1_permtab[] PROGMEM = {
124 8, 7, /* 64 bit -> 56 bit*/
125 57, 49, 41, 33, 25, 17, 9,
126 1, 58, 50, 42, 34, 26, 18,
127 10, 2, 59, 51, 43, 35, 27,
128 19, 11, 3, 60, 52, 44, 36,
129 63, 55, 47, 39, 31, 23, 15,
130 7, 62, 54, 46, 38, 30, 22,
131 14, 6, 61, 53, 45, 37, 29,
132 21, 13, 5, 28, 20, 12, 4
135 const uint8_t pc2_permtab[] PROGMEM = {
136 7, 6, /* 56 bit -> 48 bit */
137 14, 17, 11, 24, 1, 5,
138 3, 28, 15, 6, 21, 10,
139 23, 19, 12, 4, 26, 8,
140 16, 7, 27, 20, 13, 2,
141 41, 52, 31, 37, 47, 55,
142 30, 40, 51, 45, 33, 48,
143 44, 49, 39, 56, 34, 53,
144 46, 42, 50, 36, 29, 32
147 const uint8_t splitin6bitword_permtab[] PROGMEM = {
148 8, 8, /* 64 bit -> 64 bit */
149 64, 64, 1, 6, 2, 3, 4, 5,
150 64, 64, 7, 12, 8, 9, 10, 11,
151 64, 64, 13, 18, 14, 15, 16, 17,
152 64, 64, 19, 24, 20, 21, 22, 23,
153 64, 64, 25, 30, 26, 27, 28, 29,
154 64, 64, 31, 36, 32, 33, 34, 35,
155 64, 64, 37, 42, 38, 39, 40, 41,
156 64, 64, 43, 48, 44, 45, 46, 47
159 const uint8_t shiftkey_permtab[] PROGMEM = {
160 7, 7, /* 56 bit -> 56 bit */
161 2, 3, 4, 5, 6, 7, 8, 9,
162 10, 11, 12, 13, 14, 15, 16, 17,
163 18, 19, 20, 21, 22, 23, 24, 25,
165 30, 31, 32, 33, 34, 35, 36, 37,
166 38, 39, 40, 41, 42, 43, 44, 45,
167 46, 47, 48, 49, 50, 51, 52, 53,
171 const uint8_t shiftkeyinv_permtab[] PROGMEM = {
173 28, 1, 2, 3, 4, 5, 6, 7,
174 8, 9, 10, 11, 12, 13, 14, 15,
175 16, 17, 18, 19, 20, 21, 22, 23,
177 56, 29, 30, 31, 32, 33, 34, 35,
178 36, 37, 38, 39, 40, 41, 42, 43,
179 44, 45, 46, 47, 48, 49, 50, 51,
202 #define ROTTABLE 0x7EFC
203 #define ROTTABLE_INV 0x3F7E
204 /******************************************************************************/
206 void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){
207 uint8_t ob; /* in-bytes and out-bytes */
208 uint8_t byte, bit; /* counter for bit and byte */
209 ob = pgm_read_byte(&ptable[1]);
210 ptable = &(ptable[2]);
211 for(byte=0; byte<ob; ++byte){
213 for(bit=0; bit<8; ++bit){
214 x = pgm_read_byte(ptable++) -1 ;
216 if((in[x/8]) & (0x80>>(x%8)) ){
224 /******************************************************************************/
226 void changeendian32(uint32_t * a){
227 *a = (*a & 0x000000FF) << 24 |
228 (*a & 0x0000FF00) << 8 |
229 (*a & 0x00FF0000) >> 8 |
230 (*a & 0xFF000000) >> 24;
233 /******************************************************************************/
235 void shiftkey(uint8_t *key){
238 permute((uint8_t*)shiftkey_permtab, k, key);
241 /******************************************************************************/
243 void shiftkey_inv(uint8_t *key){
246 permute((uint8_t*)shiftkeyinv_permtab, k, key);
250 /******************************************************************************/
252 uint64_t splitin6bitwords(uint64_t a){
254 a &= 0x0000ffffffffffffLL;
255 permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret);
259 /******************************************************************************/
262 uint8_t substitute(uint8_t a, uint8_t * sbp){
264 x = pgm_read_byte(&sbp[a>>1]);
265 x = (a&1)?x&0x0F:x>>4;
270 /******************************************************************************/
272 uint32_t des_f(uint32_t r, uint8_t *kr){
276 uint8_t *sbp; /* sboxpointer */
277 permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data);
279 ((uint8_t*)&data)[i] ^= kr[i];
281 /* Sbox substitution */
282 data = splitin6bitwords(data);
286 x = substitute(((uint8_t*)&data)[i], sbp);
293 permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret);
298 /******************************************************************************/
300 void des_enc(void *out, const void *in, const void *key){
301 #define R (data.v32[1])
302 #define L (data.v32[0])
311 permute((uint8_t*)ip_permtab, (uint8_t*)in, data.v8);
312 permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
315 if(ROTTABLE&((1<<((i<<1)+0))) )
317 permute((uint8_t*)pc2_permtab, k, kr);
321 if(ROTTABLE&((1<<((i<<1)+1))) )
323 permute((uint8_t*)pc2_permtab, k, kr);
331 permute((uint8_t*)inv_ip_permtab, data.v8, (uint8_t*)out);
334 /******************************************************************************/
336 void des_dec(void *out, const void *in, const uint8_t *key){
343 permute((uint8_t*)ip_permtab, (uint8_t*)in, data.v8);
344 permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
347 permute((uint8_t*)pc2_permtab, k, kr);
350 if(ROTTABLE&((1<<((i<<1)+1))) ){
354 permute((uint8_t*)pc2_permtab, k, kr);
357 if(ROTTABLE&((1<<((i<<1)+0))) ){
366 permute((uint8_t*)inv_ip_permtab, data.v8, (uint8_t*)out);
369 /******************************************************************************/
371 void tdes_enc(void *out, void *in, const void *key){
372 des_enc(out, in, (uint8_t*)key + 0);
373 des_dec(out, out, (uint8_t*)key + 8);
374 des_enc(out, out, (uint8_t*)key +16);
377 /******************************************************************************/
379 void tdes_dec(void *out, void *in, const uint8_t *key){
380 des_dec(out, in, (uint8_t*)key +16);
381 des_enc(out, out, (uint8_t*)key + 8);
382 des_dec(out, out, (uint8_t*)key + 0);
385 /******************************************************************************/