Tomato 1.26
[tomato.git] / release / src / router / matrixssl / src / crypto / peersec / des3.c
blob53cb34727dbd758f95baf95a9508439eb4b64458
1 /*
2 * des3.c
3 * Release $Name: MATRIXSSL_1_8_8_OPEN $
5 * 3DES block cipher implementation for low memory usage
6 */
7 /*
8 * Copyright (c) PeerSec Networks, 2002-2009. All Rights Reserved.
9 * The latest version of this code is available at http://www.matrixssl.org
11 * This software is open source; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This General Public License does NOT permit incorporating this software
17 * into proprietary programs. If you are unable to comply with the GPL, a
18 * commercial license for this software may be purchased from PeerSec Networks
19 * at http://www.peersec.com
21 * This program is distributed in WITHOUT ANY WARRANTY; without even the
22 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 * See the GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * http://www.gnu.org/copyleft/gpl.html
30 /******************************************************************************/
32 #include "../cryptoLayer.h"
34 #ifdef USE_3DES
36 #define EN0 0
37 #define DE1 1
39 static const ulong32 bytebit[8] =
41 0200, 0100, 040, 020, 010, 04, 02, 01
44 static const ulong32 bigbyte[24] =
46 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL,
47 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL,
48 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL,
49 0x800UL, 0x400UL, 0x200UL, 0x100UL,
50 0x80UL, 0x40UL, 0x20UL, 0x10UL,
51 0x8UL, 0x4UL, 0x2UL, 0x1L
54 static const unsigned char pc1[56] = {
55 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
56 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
57 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
58 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
61 static const unsigned char pc2[48] = {
62 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
63 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
64 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
65 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
68 static const unsigned char totrot[16] = {
69 1, 2, 4, 6,
70 8, 10, 12, 14,
71 15, 17, 19, 21,
72 23, 25, 27, 28
75 static const ulong32 SP1[] =
77 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
78 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
79 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
80 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
81 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
82 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
83 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
84 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
85 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
86 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
87 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
88 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
89 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
90 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
91 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
92 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
95 static const ulong32 SP2[] =
97 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
98 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
99 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
100 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
101 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
102 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
103 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
104 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
105 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
106 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
107 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
108 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
109 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
110 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
111 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
112 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
115 static const ulong32 SP3[] =
117 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
118 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
119 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
120 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
121 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
122 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
123 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
124 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
125 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
126 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
127 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
128 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
129 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
130 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
131 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
132 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
135 static const ulong32 SP4[] =
137 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
138 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
139 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
140 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
141 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
142 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
143 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
144 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
145 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
146 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
147 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
148 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
149 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
150 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
151 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
152 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
155 static const ulong32 SP5[] =
157 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
158 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
159 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
160 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
161 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
162 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
163 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
164 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
165 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
166 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
167 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
168 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
169 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
170 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
171 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
172 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
175 static const ulong32 SP6[] =
177 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
178 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
179 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
180 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
181 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
182 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
183 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
184 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
185 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
186 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
187 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
188 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
189 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
190 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
191 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
192 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
195 static const ulong32 SP7[] =
197 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
198 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
199 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
200 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
201 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
202 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
203 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
204 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
205 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
206 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
207 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
208 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
209 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
210 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
211 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
212 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
215 static const ulong32 SP8[] =
217 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
218 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
219 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
220 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
221 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
222 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
223 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
224 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
225 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
226 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
227 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
228 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
229 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
230 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
231 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
232 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL,
233 0xe1f27f3aUL, 0xf5710fb0UL, 0xada0e5c4UL, 0x98e4c919UL
236 static void cookey(const ulong32 *raw1, ulong32 *keyout);
237 static void deskey(const unsigned char *key, short edf, ulong32 *keyout);
239 /******************************************************************************/
241 Init the 3DES block cipher context for CBC-EDE mode.
242 IV should point to 8 bytes of initialization vector
243 Key should point to 24 bytes of data
245 int32 matrix3desInit(sslCipherContext_t *ctx, unsigned char *IV,
246 unsigned char *key, int32 keylen)
248 int32 x, err;
250 if (IV == NULL || key == NULL || ctx == NULL || keylen != SSL_DES3_KEY_LEN){
251 return -1;
254 setup cipher
256 if ((err = des3_setup(key, keylen, 0, &ctx->des3)) != CRYPT_OK) {
257 return -1;
260 copy IV
262 ctx->des3.blocklen = SSL_DES3_IV_LEN;
263 for (x = 0; x < ctx->des3.blocklen; x++) {
264 ctx->des3.IV[x] = IV[x];
266 ctx->des3.explicitIV = 0;
267 return 0;
270 /******************************************************************************/
272 Encrypt a buffer using 3DES-EDE-CBC
273 (Encrypt Decrypt Encrypt and Cipher Block Chaining)
274 len must be a multiple of blockLen (8 bytes)
276 int32 matrix3desEncrypt(sslCipherContext_t *ctx, unsigned char *pt,
277 unsigned char *ct, int32 len)
279 int32 x, i;
280 unsigned char tmp[MAXBLOCKSIZE];
282 if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) {
283 return -1;
286 /* is blocklen valid? */
287 if (ctx->des3.blocklen < 0 || ctx->des3.blocklen >
288 (int32)sizeof(ctx->des3.IV)) {
289 return -1;
292 for (i = 0; i < len; i += ctx->des3.blocklen) {
293 /* xor IV against plaintext */
294 for (x = 0; x < ctx->des3.blocklen; x++) {
295 tmp[x] = pt[x] ^ ctx->des3.IV[x];
297 /* encrypt */
298 des3_ecb_encrypt(tmp, (unsigned char*)ct, &ctx->des3);
300 /* store IV [ciphertext] for a future block */
301 for (x = 0; x < ctx->des3.blocklen; x++) {
302 ctx->des3.IV[x] = ct[x];
304 ct += ctx->des3.blocklen;
305 pt += ctx->des3.blocklen;
308 #ifdef CLEAN_STACK
309 psZeromem(tmp, sizeof(tmp));
310 #endif /* CLEAN STACK */
311 return len;
314 /******************************************************************************/
316 Decrypt a buffer using 3DES-EDE-CBC
317 (Encrypt Decrypt Encrypt and Cipher Block Chaining)
318 len must be a multiple of blockLen (8 bytes)
320 int32 matrix3desDecrypt(sslCipherContext_t *ctx, unsigned char *ct,
321 unsigned char *pt, int32 len)
323 int32 x, i;
324 unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE];
326 if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) {
327 return -1;
330 /* is blocklen valid? */
331 if (ctx->des3.blocklen < 0 || ctx->des3.blocklen >
332 (int32)sizeof(ctx->des3.IV)) {
333 return -1;
335 for (i = 0; i < len; i += ctx->des3.blocklen) {
336 /* decrypt the block from ct into tmp */
337 des3_ecb_decrypt(ct, tmp, &ctx->des3);
338 /* xor IV against the plaintext of the previous step */
339 for (x = 0; x < ctx->des3.blocklen; x++) {
340 /* copy CT in case ct == pt */
341 tmp2[x] = ct[x];
342 /* actually decrypt the byte */
343 pt[x] = tmp[x] ^ ctx->des3.IV[x];
345 /* replace IV with this current ciphertext */
346 for (x = 0; x < ctx->des3.blocklen; x++) {
347 ctx->des3.IV[x] = tmp2[x];
349 ct += ctx->des3.blocklen;
350 if (ctx->des3.explicitIV) {
352 An explict IV mode has an additional block of random data that
353 we dismiss here. It is not part of the MAC. The TLS 1.1 spec
354 isn't explicit about this, but it only makes sense since the
355 extra block is used to derive the IV for the remainder of the
356 message. In theory (DTLS for example) the actual decrypted block
357 could have been received out of order and the first block would
358 not decrypt to the plaintext it originally was anyway.
360 It is easiest to simply remove the first block in this cipher
361 code here. If we wait until we get back into matrixSslDecode
362 we have to deal with a bunch of sslBuf_t manipulations which is
363 ugly.
365 if (i != 0) {
366 pt += ctx->des3.blocklen;
368 } else {
369 pt += ctx->des3.blocklen;
372 #ifdef CLEAN_STACK
373 psZeromem(tmp, sizeof(tmp));
374 psZeromem(tmp2, sizeof(tmp2));
375 #endif /* CLEAN_STACK */
376 return len;
379 /******************************************************************************/
381 3DES implementation below
383 static void cookey(const ulong32 *raw1, ulong32 *keyout)
385 ulong32 *cook;
386 const ulong32 *raw0;
387 ulong32 dough[32];
388 int32 i;
390 cook = dough;
391 for(i=0; i < 16; i++, raw1++) {
392 raw0 = raw1++;
393 *cook = (*raw0 & 0x00fc0000L) << 6;
394 *cook |= (*raw0 & 0x00000fc0L) << 10;
395 *cook |= (*raw1 & 0x00fc0000L) >> 10;
396 *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
397 *cook = (*raw0 & 0x0003f000L) << 12;
398 *cook |= (*raw0 & 0x0000003fL) << 16;
399 *cook |= (*raw1 & 0x0003f000L) >> 4;
400 *cook++ |= (*raw1 & 0x0000003fL);
403 psMemcpy(keyout, dough, sizeof dough);
404 psBurnStack(sizeof(ulong32 *) * 2 + sizeof(ulong32)*32 + sizeof(int32));
408 static void deskey(const unsigned char *key, short edf, ulong32 *keyout)
410 ulong32 i, j, l, m, n, kn[32];
411 unsigned char pc1m[56], pcr[56];
413 for (j=0; j < 56; j++) {
414 l = (ulong32)pc1[j];
415 m = l & 7;
416 pc1m[j] = (unsigned char)((key[l >> 3U] & bytebit[m]) ==
417 bytebit[m] ? 1 : 0);
420 for (i=0; i < 16; i++) {
421 if (edf == DE1) {
422 m = (15 - i) << 1;
423 } else {
424 m = i << 1;
426 n = m + 1;
427 kn[m] = kn[n] = 0L;
428 for (j=0; j < 28; j++) {
429 l = j + (ulong32)totrot[i];
430 if (l < 28) {
431 pcr[j] = pc1m[l];
432 } else {
433 pcr[j] = pc1m[l - 28];
436 for (/*j = 28*/; j < 56; j++) {
437 l = j + (ulong32)totrot[i];
438 if (l < 56) {
439 pcr[j] = pc1m[l];
440 } else {
441 pcr[j] = pc1m[l - 28];
444 for (j=0; j < 24; j++) {
445 if ((int32)pcr[(int32)pc2[j]] != 0) {
446 kn[m] |= bigbyte[j];
448 if ((int32)pcr[(int32)pc2[j+24]] != 0) {
449 kn[n] |= bigbyte[j];
453 cookey(kn, keyout);
454 psBurnStack(sizeof(int32)*5 + sizeof(ulong32)*32 +
455 sizeof(unsigned char)*112);
458 static void desfunc(ulong32 *block, const ulong32 *keys)
460 ulong32 work, right, leftt;
461 int32 cur_round;
463 leftt = block[0];
464 right = block[1];
466 #ifdef SMALL_CODE
467 work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
468 right ^= work;
469 leftt ^= (work << 4);
471 work = ((leftt >> 16) ^ right) & 0x0000ffffL;
472 right ^= work;
473 leftt ^= (work << 16);
475 work = ((right >> 2) ^ leftt) & 0x33333333L;
476 leftt ^= work;
477 right ^= (work << 2);
479 work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
480 leftt ^= work;
481 right ^= (work << 8);
483 right = ROLc(right, 1);
484 work = (leftt ^ right) & 0xaaaaaaaaL;
486 leftt ^= work;
487 right ^= work;
488 leftt = ROLc(leftt, 1);
489 #else /* SMALL_CODE */
491 ulong64 tmp;
492 tmp = des_ip[0][byte(leftt, 0)] ^
493 des_ip[1][byte(leftt, 1)] ^
494 des_ip[2][byte(leftt, 2)] ^
495 des_ip[3][byte(leftt, 3)] ^
496 des_ip[4][byte(right, 0)] ^
497 des_ip[5][byte(right, 1)] ^
498 des_ip[6][byte(right, 2)] ^
499 des_ip[7][byte(right, 3)];
500 leftt = (ulong32)(tmp >> 32);
501 right = (ulong32)(tmp & 0xFFFFFFFFUL);
503 #endif /* SMALL CODE */
505 for (cur_round = 0; cur_round < 8; cur_round++) {
506 work = RORc(right, 4) ^ *keys++;
507 leftt ^= SP7[work & 0x3fL]
508 ^ SP5[(work >> 8) & 0x3fL]
509 ^ SP3[(work >> 16) & 0x3fL]
510 ^ SP1[(work >> 24) & 0x3fL];
511 work = right ^ *keys++;
512 leftt ^= SP8[ work & 0x3fL]
513 ^ SP6[(work >> 8) & 0x3fL]
514 ^ SP4[(work >> 16) & 0x3fL]
515 ^ SP2[(work >> 24) & 0x3fL];
517 work = RORc(leftt, 4) ^ *keys++;
518 right ^= SP7[ work & 0x3fL]
519 ^ SP5[(work >> 8) & 0x3fL]
520 ^ SP3[(work >> 16) & 0x3fL]
521 ^ SP1[(work >> 24) & 0x3fL];
522 work = leftt ^ *keys++;
523 right ^= SP8[ work & 0x3fL]
524 ^ SP6[(work >> 8) & 0x3fL]
525 ^ SP4[(work >> 16) & 0x3fL]
526 ^ SP2[(work >> 24) & 0x3fL];
529 #ifdef SMALL_CODE
530 right = RORc(right, 1);
531 work = (leftt ^ right) & 0xaaaaaaaaL;
532 leftt ^= work;
533 right ^= work;
534 leftt = RORc(leftt, 1);
535 work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
536 right ^= work;
537 leftt ^= (work << 8);
539 work = ((leftt >> 2) ^ right) & 0x33333333L;
540 right ^= work;
541 leftt ^= (work << 2);
542 work = ((right >> 16) ^ leftt) & 0x0000ffffL;
543 leftt ^= work;
544 right ^= (work << 16);
545 work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
546 leftt ^= work;
547 right ^= (work << 4);
548 #else /* SMALL CODE */
550 ulong64 tmp;
551 tmp = des_fp[0][byte(leftt, 0)] ^
552 des_fp[1][byte(leftt, 1)] ^
553 des_fp[2][byte(leftt, 2)] ^
554 des_fp[3][byte(leftt, 3)] ^
555 des_fp[4][byte(right, 0)] ^
556 des_fp[5][byte(right, 1)] ^
557 des_fp[6][byte(right, 2)] ^
558 des_fp[7][byte(right, 3)];
559 leftt = (ulong32)(tmp >> 32);
560 right = (ulong32)(tmp & 0xFFFFFFFFUL);
562 #endif /* SMALL CODE */
564 block[0] = right;
565 block[1] = leftt;
566 psBurnStack(sizeof(ulong32) * 4 + sizeof(int32));
570 We don't validate DES keys against the following known weak keys.
571 Astronomically small chances of randomly getting a weak key
572 with 3DES. http://www.rsasecurity.com/rsalabs/faq/3-2-4.html
574 http://www.itl.nist.gov/fipspubs/fip74.htm
575 1. E001E00lFl0lFl0l 01E001E00lFl0lFl
576 2. FElFFElFFEOEFEOE 1FFElFFEOEFEOEFE
577 3. E01FE01FF10EF10E 1FE01FEOOEF10EF1
578 4. 01FE01FE01FE01FE FE01FE01FE01FE01
579 5. 011F011F0l0E010E 1F011F0l0E0l0E01
580 6. E0FEE0FEFlFEFlFE FEE0FEE0FEFlFEF1
581 7. 0101010101010101
582 8. FEFEFEFEFEFEFEFE
583 9. E0E0E0E0FlFlFlFl
584 10. lFlFlFlF0E0E0E0E
586 int32 des3_setup(const unsigned char *key, int32 keylen, int32 num_rounds,
587 des3_CBC *skey)
589 if (key == NULL || skey == NULL) {
590 return -1;
593 if( num_rounds != 0 && num_rounds != 16) {
594 return CRYPT_INVALID_ROUNDS;
597 if (keylen != 24) {
598 return CRYPT_INVALID_KEYSIZE;
601 deskey(key, EN0, skey->key.ek[0]);
602 deskey(key+8, DE1, skey->key.ek[1]);
603 deskey(key+16, EN0, skey->key.ek[2]);
605 deskey(key, DE1, skey->key.dk[2]);
606 deskey(key+8, EN0, skey->key.dk[1]);
607 deskey(key+16, DE1, skey->key.dk[0]);
609 return CRYPT_OK;
612 int des_setup(const unsigned char *key, int keylen, int num_rounds,
613 des3_CBC *skey)
616 if (num_rounds != 0 && num_rounds != 16) {
617 return CRYPT_INVALID_ROUNDS;
620 if (keylen != 8) {
621 return CRYPT_INVALID_KEYSIZE;
624 deskey(key, EN0, skey->key.ek[0]);
625 deskey(key, DE1, skey->key.dk[0]);
627 return CRYPT_OK;
630 void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
631 des3_CBC *key)
633 ulong32 work[2];
635 LOAD32H(work[0], pt+0);
636 LOAD32H(work[1], pt+4);
637 desfunc(work, key->key.ek[0]);
638 desfunc(work, key->key.ek[1]);
639 desfunc(work, key->key.ek[2]);
640 STORE32H(work[0],ct+0);
641 STORE32H(work[1],ct+4);
644 void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
645 des3_CBC *key)
647 ulong32 work[2];
649 LOAD32H(work[0], pt+0);
650 LOAD32H(work[1], pt+4);
651 desfunc(work, key->key.ek[0]);
652 STORE32H(work[0],ct+0);
653 STORE32H(work[1],ct+4);
656 void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
657 des3_CBC *key)
659 ulong32 work[2];
661 LOAD32H(work[0], ct+0);
662 LOAD32H(work[1], ct+4);
663 desfunc(work, key->key.dk[0]);
664 desfunc(work, key->key.dk[1]);
665 desfunc(work, key->key.dk[2]);
666 STORE32H(work[0],pt+0);
667 STORE32H(work[1],pt+4);
670 void des_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
671 des3_CBC *key)
673 ulong32 work[2];
674 LOAD32H(work[0], ct+0);
675 LOAD32H(work[1], ct+4);
676 desfunc(work, key->key.dk[0]);
677 STORE32H(work[0],pt+0);
678 STORE32H(work[1],pt+4);
681 int32 des3_keysize(int32 *desired_keysize)
683 if(*desired_keysize < 24) {
684 return CRYPT_INVALID_KEYSIZE;
686 *desired_keysize = 24;
687 return CRYPT_OK;
690 /******************************************************************************/
692 Generate a 3DES key given a password and salt value.
693 We use PKCS#5 2.0 PBKDF1 key derivation format with MD5 and count == 1 per:
694 http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html
696 This key is compatible with the algorithm used by OpenSSL to encrypt keys
697 generated with 'openssl genrsa'. If other encryption formats are used
698 (for example PBKDF2), or an iteration count > 0 is used, they are not
699 compatible with this simple implementation. OpenSSL provides many options
700 for converting key formats to the one used here.
702 A 3DES key is 24 bytes long, to generate it with this algorithm,
703 we md5 hash the password and salt for the first 16 bytes. We then
704 hash these first 16 bytes with the password and salt again, generating
705 another 16 bytes. We take the first 16 bytes and 8 of the second 16 to
706 form the 24 byte key.
708 salt is assumed to point to 8 bytes of data
709 key is assumed to point to 24 bytes of data
711 void generate3DESKey(unsigned char *pass, int32 passlen, unsigned char *salt,
712 unsigned char *key)
714 sslMd5Context_t state;
715 unsigned char md5[SSL_MD5_HASH_SIZE];
717 matrixMd5Init(&state);
718 matrixMd5Update(&state, pass, passlen);
719 matrixMd5Update(&state, salt, SSL_DES3_IV_LEN);
720 matrixMd5Final(&state, md5);
721 memcpy(key, md5, SSL_MD5_HASH_SIZE);
723 matrixMd5Init(&state);
724 matrixMd5Update(&state, md5, SSL_MD5_HASH_SIZE);
725 matrixMd5Update(&state, pass, passlen);
726 matrixMd5Update(&state, salt, SSL_DES3_IV_LEN);
727 matrixMd5Final(&state, md5);
728 memcpy(key + SSL_MD5_HASH_SIZE, md5, SSL_DES3_KEY_LEN - SSL_MD5_HASH_SIZE);
732 #ifdef PEERSEC_TEST
734 int32 matrixDes3Test()
736 unsigned char key[24], pt[8], ct[8], tmp[8];
737 des3_CBC skey;
738 int32 x, err;
740 for (x = 0; x < 8; x++) {
741 pt[x] = x;
744 for (x = 0; x < 24; x++) {
745 key[x] = x;
748 if ((err = des3_setup(key, 24, 0, &skey)) != CRYPT_OK) {
749 return err;
752 des3_ecb_encrypt(pt, ct, &skey);
753 des3_ecb_decrypt(ct, tmp, &skey);
755 if (memcmp(pt, tmp, 8) != 0) {
756 return CRYPT_FAIL_TESTVECTOR;
759 return CRYPT_OK;
762 int32 matrixDesTest()
764 unsigned char key[8], pt[8], ct[8], tmp[8];
765 des3_CBC skey;
766 int32 x, err;
768 for (x = 0; x < 8; x++) {
769 pt[x] = x;
772 for (x = 0; x < 8; x++) {
773 key[x] = x;
776 if ((err = des_setup(key, 8, 0, &skey)) != CRYPT_OK) {
777 return err;
780 des_ecb_encrypt(pt, ct, &skey);
781 des_ecb_decrypt(ct, tmp, &skey);
783 if (memcmp(pt, tmp, 8) != 0) {
784 return CRYPT_FAIL_TESTVECTOR;
787 return CRYPT_OK;
790 #endif /* PEERSEC_TEST */
792 #endif /* USE_3DES */
794 /******************************************************************************/