3 * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
5 * This file is part of CyaSSL.
7 * CyaSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * CyaSSL 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
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
28 #include <cyassl/ctaocrypt/des3.h>
31 #include <cyassl/ctaocrypt/misc.h>
33 #include <ctaocrypt/src/misc.c>
37 /* permuted choice table (key) */
38 static const byte pc1[] = {
39 57, 49, 41, 33, 25, 17, 9,
40 1, 58, 50, 42, 34, 26, 18,
41 10, 2, 59, 51, 43, 35, 27,
42 19, 11, 3, 60, 52, 44, 36,
44 63, 55, 47, 39, 31, 23, 15,
45 7, 62, 54, 46, 38, 30, 22,
46 14, 6, 61, 53, 45, 37, 29,
47 21, 13, 5, 28, 20, 12, 4
50 /* number left rotations of pc1 */
51 static const byte totrot[] = {
52 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
55 /* permuted choice key (table) */
56 static const byte pc2[] = {
61 41, 52, 31, 37, 47, 55,
62 30, 40, 51, 45, 33, 48,
63 44, 49, 39, 56, 34, 53,
64 46, 42, 50, 36, 29, 32
67 /* End of DES-defined tables */
69 /* bit 0 is left-most in byte */
70 static const int bytebit[] = {
71 0200,0100,040,020,010,04,02,01
74 const word32 Spbox[8][64] = {
76 0x01010400,0x00000000,0x00010000,0x01010404,
77 0x01010004,0x00010404,0x00000004,0x00010000,
78 0x00000400,0x01010400,0x01010404,0x00000400,
79 0x01000404,0x01010004,0x01000000,0x00000004,
80 0x00000404,0x01000400,0x01000400,0x00010400,
81 0x00010400,0x01010000,0x01010000,0x01000404,
82 0x00010004,0x01000004,0x01000004,0x00010004,
83 0x00000000,0x00000404,0x00010404,0x01000000,
84 0x00010000,0x01010404,0x00000004,0x01010000,
85 0x01010400,0x01000000,0x01000000,0x00000400,
86 0x01010004,0x00010000,0x00010400,0x01000004,
87 0x00000400,0x00000004,0x01000404,0x00010404,
88 0x01010404,0x00010004,0x01010000,0x01000404,
89 0x01000004,0x00000404,0x00010404,0x01010400,
90 0x00000404,0x01000400,0x01000400,0x00000000,
91 0x00010004,0x00010400,0x00000000,0x01010004},
93 0x80108020,0x80008000,0x00008000,0x00108020,
94 0x00100000,0x00000020,0x80100020,0x80008020,
95 0x80000020,0x80108020,0x80108000,0x80000000,
96 0x80008000,0x00100000,0x00000020,0x80100020,
97 0x00108000,0x00100020,0x80008020,0x00000000,
98 0x80000000,0x00008000,0x00108020,0x80100000,
99 0x00100020,0x80000020,0x00000000,0x00108000,
100 0x00008020,0x80108000,0x80100000,0x00008020,
101 0x00000000,0x00108020,0x80100020,0x00100000,
102 0x80008020,0x80100000,0x80108000,0x00008000,
103 0x80100000,0x80008000,0x00000020,0x80108020,
104 0x00108020,0x00000020,0x00008000,0x80000000,
105 0x00008020,0x80108000,0x00100000,0x80000020,
106 0x00100020,0x80008020,0x80000020,0x00100020,
107 0x00108000,0x00000000,0x80008000,0x00008020,
108 0x80000000,0x80100020,0x80108020,0x00108000},
110 0x00000208,0x08020200,0x00000000,0x08020008,
111 0x08000200,0x00000000,0x00020208,0x08000200,
112 0x00020008,0x08000008,0x08000008,0x00020000,
113 0x08020208,0x00020008,0x08020000,0x00000208,
114 0x08000000,0x00000008,0x08020200,0x00000200,
115 0x00020200,0x08020000,0x08020008,0x00020208,
116 0x08000208,0x00020200,0x00020000,0x08000208,
117 0x00000008,0x08020208,0x00000200,0x08000000,
118 0x08020200,0x08000000,0x00020008,0x00000208,
119 0x00020000,0x08020200,0x08000200,0x00000000,
120 0x00000200,0x00020008,0x08020208,0x08000200,
121 0x08000008,0x00000200,0x00000000,0x08020008,
122 0x08000208,0x00020000,0x08000000,0x08020208,
123 0x00000008,0x00020208,0x00020200,0x08000008,
124 0x08020000,0x08000208,0x00000208,0x08020000,
125 0x00020208,0x00000008,0x08020008,0x00020200},
127 0x00802001,0x00002081,0x00002081,0x00000080,
128 0x00802080,0x00800081,0x00800001,0x00002001,
129 0x00000000,0x00802000,0x00802000,0x00802081,
130 0x00000081,0x00000000,0x00800080,0x00800001,
131 0x00000001,0x00002000,0x00800000,0x00802001,
132 0x00000080,0x00800000,0x00002001,0x00002080,
133 0x00800081,0x00000001,0x00002080,0x00800080,
134 0x00002000,0x00802080,0x00802081,0x00000081,
135 0x00800080,0x00800001,0x00802000,0x00802081,
136 0x00000081,0x00000000,0x00000000,0x00802000,
137 0x00002080,0x00800080,0x00800081,0x00000001,
138 0x00802001,0x00002081,0x00002081,0x00000080,
139 0x00802081,0x00000081,0x00000001,0x00002000,
140 0x00800001,0x00002001,0x00802080,0x00800081,
141 0x00002001,0x00002080,0x00800000,0x00802001,
142 0x00000080,0x00800000,0x00002000,0x00802080},
144 0x00000100,0x02080100,0x02080000,0x42000100,
145 0x00080000,0x00000100,0x40000000,0x02080000,
146 0x40080100,0x00080000,0x02000100,0x40080100,
147 0x42000100,0x42080000,0x00080100,0x40000000,
148 0x02000000,0x40080000,0x40080000,0x00000000,
149 0x40000100,0x42080100,0x42080100,0x02000100,
150 0x42080000,0x40000100,0x00000000,0x42000000,
151 0x02080100,0x02000000,0x42000000,0x00080100,
152 0x00080000,0x42000100,0x00000100,0x02000000,
153 0x40000000,0x02080000,0x42000100,0x40080100,
154 0x02000100,0x40000000,0x42080000,0x02080100,
155 0x40080100,0x00000100,0x02000000,0x42080000,
156 0x42080100,0x00080100,0x42000000,0x42080100,
157 0x02080000,0x00000000,0x40080000,0x42000000,
158 0x00080100,0x02000100,0x40000100,0x00080000,
159 0x00000000,0x40080000,0x02080100,0x40000100},
161 0x20000010,0x20400000,0x00004000,0x20404010,
162 0x20400000,0x00000010,0x20404010,0x00400000,
163 0x20004000,0x00404010,0x00400000,0x20000010,
164 0x00400010,0x20004000,0x20000000,0x00004010,
165 0x00000000,0x00400010,0x20004010,0x00004000,
166 0x00404000,0x20004010,0x00000010,0x20400010,
167 0x20400010,0x00000000,0x00404010,0x20404000,
168 0x00004010,0x00404000,0x20404000,0x20000000,
169 0x20004000,0x00000010,0x20400010,0x00404000,
170 0x20404010,0x00400000,0x00004010,0x20000010,
171 0x00400000,0x20004000,0x20000000,0x00004010,
172 0x20000010,0x20404010,0x00404000,0x20400000,
173 0x00404010,0x20404000,0x00000000,0x20400010,
174 0x00000010,0x00004000,0x20400000,0x00404010,
175 0x00004000,0x00400010,0x20004010,0x00000000,
176 0x20404000,0x20000000,0x00400010,0x20004010},
178 0x00200000,0x04200002,0x04000802,0x00000000,
179 0x00000800,0x04000802,0x00200802,0x04200800,
180 0x04200802,0x00200000,0x00000000,0x04000002,
181 0x00000002,0x04000000,0x04200002,0x00000802,
182 0x04000800,0x00200802,0x00200002,0x04000800,
183 0x04000002,0x04200000,0x04200800,0x00200002,
184 0x04200000,0x00000800,0x00000802,0x04200802,
185 0x00200800,0x00000002,0x04000000,0x00200800,
186 0x04000000,0x00200800,0x00200000,0x04000802,
187 0x04000802,0x04200002,0x04200002,0x00000002,
188 0x00200002,0x04000000,0x04000800,0x00200000,
189 0x04200800,0x00000802,0x00200802,0x04200800,
190 0x00000802,0x04000002,0x04200802,0x04200000,
191 0x00200800,0x00000000,0x00000002,0x04200802,
192 0x00000000,0x00200802,0x04200000,0x00000800,
193 0x04000002,0x04000800,0x00000800,0x00200002},
195 0x10001040,0x00001000,0x00040000,0x10041040,
196 0x10000000,0x10001040,0x00000040,0x10000000,
197 0x00040040,0x10040000,0x10041040,0x00041000,
198 0x10041000,0x00041040,0x00001000,0x00000040,
199 0x10040000,0x10000040,0x10001000,0x00001040,
200 0x00041000,0x00040040,0x10040040,0x10041000,
201 0x00001040,0x00000000,0x00000000,0x10040040,
202 0x10000040,0x10001000,0x00041040,0x00040000,
203 0x00041040,0x00040000,0x10041000,0x00001000,
204 0x00000040,0x10040040,0x00001000,0x00041040,
205 0x10001000,0x00000040,0x10000040,0x10040000,
206 0x10040040,0x10000000,0x00040000,0x10001040,
207 0x00000000,0x10041040,0x00040040,0x10000040,
208 0x10040000,0x10001000,0x10001040,0x00000000,
209 0x10041040,0x00041000,0x00041000,0x00001040,
210 0x00001040,0x00040040,0x10000000,0x10041000}
214 static INLINE void IPERM(word32* left, word32* right)
218 *right = rotlFixed(*right, 4U);
219 work = (*left ^ *right) & 0xf0f0f0f0;
222 *right = rotrFixed(*right^work, 20U);
223 work = (*left ^ *right) & 0xffff0000;
226 *right = rotrFixed(*right^work, 18U);
227 work = (*left ^ *right) & 0x33333333;
230 *right = rotrFixed(*right^work, 6U);
231 work = (*left ^ *right) & 0x00ff00ff;
234 *right = rotlFixed(*right^work, 9U);
235 work = (*left ^ *right) & 0xaaaaaaaa;
236 *left = rotlFixed(*left^work, 1U);
241 static INLINE void FPERM(word32* left, word32* right)
245 *right = rotrFixed(*right, 1U);
246 work = (*left ^ *right) & 0xaaaaaaaa;
249 *left = rotrFixed(*left^work, 9U);
250 work = (*left ^ *right) & 0x00ff00ff;
253 *left = rotlFixed(*left^work, 6U);
254 work = (*left ^ *right) & 0x33333333;
257 *left = rotlFixed(*left^work, 18U);
258 work = (*left ^ *right) & 0xffff0000;
261 *left = rotlFixed(*left^work, 20U);
262 work = (*left ^ *right) & 0xf0f0f0f0;
265 *left = rotrFixed(*left^work, 4U);
269 static void DesSetKey(const byte* key, int dir, word32* out)
271 byte buffer[56+56+8];
272 byte *const pc1m = buffer; /* place to modify pc1 into */
273 byte *const pcr = pc1m + 56; /* place to rotate pc1 into */
274 byte *const ks = pcr + 56;
278 for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */
279 l = pc1[j] - 1; /* integer bit location */
280 m = l & 07; /* find bit */
281 pc1m[j] = (key[l >> 3] & /* find which key byte l is in */
282 bytebit[m]) /* and which bit of that byte */
283 ? 1 : 0; /* and store 1-bit result */
285 for (i = 0; i < 16; i++) { /* key chunk for each iteration */
286 XMEMSET(ks, 0, 8); /* Clear key schedule */
287 for (j = 0; j < 56; j++) /* rotate pc1 the right amount */
288 pcr[j] = pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l: l-28];
289 /* rotate left and right halves independently */
290 for (j = 0; j < 48; j++){ /* select bits individually */
291 /* check bit that goes to ks[j] */
292 if (pcr[pc2[j] - 1]){
293 /* mask it in if it's there */
295 ks[j/6] |= bytebit[l] >> 2;
298 /* Now convert to odd/even interleaved form for use in F */
299 out[2*i] = ((word32)ks[0] << 24)
300 | ((word32)ks[2] << 16)
301 | ((word32)ks[4] << 8)
303 out[2*i + 1] = ((word32)ks[1] << 24)
304 | ((word32)ks[3] << 16)
305 | ((word32)ks[5] << 8)
309 /* reverse key schedule order */
310 if (dir == DES_DECRYPTION)
311 for (i = 0; i < 16; i += 2) {
312 word32 swap = out[i];
313 out[i] = out[DES_KS_SIZE - 2 - i];
314 out[DES_KS_SIZE - 2 - i] = swap;
317 out[i + 1] = out[DES_KS_SIZE - 1 - i];
318 out[DES_KS_SIZE - 1 - i] = swap;
324 static INLINE int Reverse(int dir)
330 void Des_SetIV(Des* des, const byte* iv)
333 XMEMCPY(des->reg, iv, DES_BLOCK_SIZE);
337 void Des3_SetIV(Des3* des, const byte* iv)
340 XMEMCPY(des->reg, iv, DES_BLOCK_SIZE);
344 void Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
346 DesSetKey(key, dir, des->key);
352 void Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
354 DesSetKey(key + (dir == DES_ENCRYPTION ? 0 : 16), dir, des->key[0]);
355 DesSetKey(key + 8, Reverse(dir), des->key[1]);
356 DesSetKey(key + (dir == DES_DECRYPTION ? 0 : 16), dir, des->key[2]);
362 static void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr)
364 word32 l = *lIn, r = *rIn, i;
368 word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
369 l ^= Spbox[6][(work) & 0x3f]
370 ^ Spbox[4][(work >> 8) & 0x3f]
371 ^ Spbox[2][(work >> 16) & 0x3f]
372 ^ Spbox[0][(work >> 24) & 0x3f];
373 work = r ^ kptr[4*i+1];
374 l ^= Spbox[7][(work) & 0x3f]
375 ^ Spbox[5][(work >> 8) & 0x3f]
376 ^ Spbox[3][(work >> 16) & 0x3f]
377 ^ Spbox[1][(work >> 24) & 0x3f];
379 work = rotrFixed(l, 4U) ^ kptr[4*i+2];
380 r ^= Spbox[6][(work) & 0x3f]
381 ^ Spbox[4][(work >> 8) & 0x3f]
382 ^ Spbox[2][(work >> 16) & 0x3f]
383 ^ Spbox[0][(work >> 24) & 0x3f];
384 work = l ^ kptr[4*i+3];
385 r ^= Spbox[7][(work) & 0x3f]
386 ^ Spbox[5][(work >> 8) & 0x3f]
387 ^ Spbox[3][(work >> 16) & 0x3f]
388 ^ Spbox[1][(work >> 24) & 0x3f];
395 static void DesProcessBlock(Des* des, const byte* in, byte* out)
399 XMEMCPY(&l, in, sizeof(l));
400 XMEMCPY(&r, in + sizeof(l), sizeof(r));
401 #ifdef LITTLE_ENDIAN_ORDER
402 l = ByteReverseWord32(l);
403 r = ByteReverseWord32(r);
407 DesRawProcessBlock(&l, &r, des->key);
410 #ifdef LITTLE_ENDIAN_ORDER
411 l = ByteReverseWord32(l);
412 r = ByteReverseWord32(r);
414 XMEMCPY(out, &r, sizeof(r));
415 XMEMCPY(out + sizeof(r), &l, sizeof(l));
419 static void Des3ProcessBlock(Des3* des, const byte* in, byte* out)
423 XMEMCPY(&l, in, sizeof(l));
424 XMEMCPY(&r, in + sizeof(l), sizeof(r));
425 #ifdef LITTLE_ENDIAN_ORDER
426 l = ByteReverseWord32(l);
427 r = ByteReverseWord32(r);
431 DesRawProcessBlock(&l, &r, des->key[0]);
432 DesRawProcessBlock(&r, &l, des->key[1]);
433 DesRawProcessBlock(&l, &r, des->key[2]);
436 #ifdef LITTLE_ENDIAN_ORDER
437 l = ByteReverseWord32(l);
438 r = ByteReverseWord32(r);
440 XMEMCPY(out, &r, sizeof(r));
441 XMEMCPY(out + sizeof(r), &l, sizeof(l));
445 void Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
447 word32 blocks = sz / DES_BLOCK_SIZE;
450 xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE);
451 DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg);
452 XMEMCPY(out, des->reg, DES_BLOCK_SIZE);
454 out += DES_BLOCK_SIZE;
455 in += DES_BLOCK_SIZE;
460 void Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
462 word32 blocks = sz / DES_BLOCK_SIZE;
466 XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
467 DesProcessBlock(des, (byte*)des->tmp, out);
468 xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE);
470 XMEMCPY(hold, des->reg, DES_BLOCK_SIZE);
471 XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
472 XMEMCPY(des->tmp, hold, DES_BLOCK_SIZE);
474 out += DES_BLOCK_SIZE;
475 in += DES_BLOCK_SIZE;
480 void Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
482 word32 blocks = sz / DES_BLOCK_SIZE;
485 xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE);
486 Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg);
487 XMEMCPY(out, des->reg, DES_BLOCK_SIZE);
489 out += DES_BLOCK_SIZE;
490 in += DES_BLOCK_SIZE;
495 void Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
497 word32 blocks = sz / DES_BLOCK_SIZE;
500 XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
501 Des3ProcessBlock(des, (byte*)des->tmp, out);
502 xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE);
503 XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
505 out += DES_BLOCK_SIZE;
506 in += DES_BLOCK_SIZE;
510 #ifdef CYASSL_DES_ECB
512 /* One block, compatibility only */
513 void Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz)
515 word32 blocks = sz / DES_BLOCK_SIZE;
518 DesProcessBlock(des, in, out);
520 out += DES_BLOCK_SIZE;
521 in += DES_BLOCK_SIZE;
525 #endif /* CYASSL_DES_ECB */