-/* Tables used for executing des. This used to be in spr.h. */
-/* Copyright (C) 1993 Eric Young - see README for more details */
-static const word32 des_SPtrans[8][64]={
-/* nibble 0 */
-{ 0x00820200, 0x00020000, 0x80800000, 0x80820200,
-0x00800000, 0x80020200, 0x80020000, 0x80800000,
-0x80020200, 0x00820200, 0x00820000, 0x80000200,
-0x80800200, 0x00800000, 0x00000000, 0x80020000,
-0x00020000, 0x80000000, 0x00800200, 0x00020200,
-0x80820200, 0x00820000, 0x80000200, 0x00800200,
-0x80000000, 0x00000200, 0x00020200, 0x80820000,
-0x00000200, 0x80800200, 0x80820000, 0x00000000,
-0x00000000, 0x80820200, 0x00800200, 0x80020000,
-0x00820200, 0x00020000, 0x80000200, 0x00800200,
-0x80820000, 0x00000200, 0x00020200, 0x80800000,
-0x80020200, 0x80000000, 0x80800000, 0x00820000,
-0x80820200, 0x00020200, 0x00820000, 0x80800200,
-0x00800000, 0x80000200, 0x80020000, 0x00000000,
-0x00020000, 0x00800000, 0x80800200, 0x00820200,
-0x80000000, 0x80820000, 0x00000200, 0x80020200 },
-
-/* nibble 1 */
-{ 0x10042004, 0x00000000, 0x00042000, 0x10040000,
-0x10000004, 0x00002004, 0x10002000, 0x00042000,
-0x00002000, 0x10040004, 0x00000004, 0x10002000,
-0x00040004, 0x10042000, 0x10040000, 0x00000004,
-0x00040000, 0x10002004, 0x10040004, 0x00002000,
-0x00042004, 0x10000000, 0x00000000, 0x00040004,
-0x10002004, 0x00042004, 0x10042000, 0x10000004,
-0x10000000, 0x00040000, 0x00002004, 0x10042004,
-0x00040004, 0x10042000, 0x10002000, 0x00042004,
-0x10042004, 0x00040004, 0x10000004, 0x00000000,
-0x10000000, 0x00002004, 0x00040000, 0x10040004,
-0x00002000, 0x10000000, 0x00042004, 0x10002004,
-0x10042000, 0x00002000, 0x00000000, 0x10000004,
-0x00000004, 0x10042004, 0x00042000, 0x10040000,
-0x10040004, 0x00040000, 0x00002004, 0x10002000,
-0x10002004, 0x00000004, 0x10040000, 0x00042000 },
-
-/* nibble 2 */
-{ 0x41000000, 0x01010040, 0x00000040, 0x41000040,
-0x40010000, 0x01000000, 0x41000040, 0x00010040,
-0x01000040, 0x00010000, 0x01010000, 0x40000000,
-0x41010040, 0x40000040, 0x40000000, 0x41010000,
-0x00000000, 0x40010000, 0x01010040, 0x00000040,
-0x40000040, 0x41010040, 0x00010000, 0x41000000,
-0x41010000, 0x01000040, 0x40010040, 0x01010000,
-0x00010040, 0x00000000, 0x01000000, 0x40010040,
-0x01010040, 0x00000040, 0x40000000, 0x00010000,
-0x40000040, 0x40010000, 0x01010000, 0x41000040,
-0x00000000, 0x01010040, 0x00010040, 0x41010000,
-0x40010000, 0x01000000, 0x41010040, 0x40000000,
-0x40010040, 0x41000000, 0x01000000, 0x41010040,
-0x00010000, 0x01000040, 0x41000040, 0x00010040,
-0x01000040, 0x00000000, 0x41010000, 0x40000040,
-0x41000000, 0x40010040, 0x00000040, 0x01010000 },
-
-/* nibble 3 */
-{ 0x00100402, 0x04000400, 0x00000002, 0x04100402,
-0x00000000, 0x04100000, 0x04000402, 0x00100002,
-0x04100400, 0x04000002, 0x04000000, 0x00000402,
-0x04000002, 0x00100402, 0x00100000, 0x04000000,
-0x04100002, 0x00100400, 0x00000400, 0x00000002,
-0x00100400, 0x04000402, 0x04100000, 0x00000400,
-0x00000402, 0x00000000, 0x00100002, 0x04100400,
-0x04000400, 0x04100002, 0x04100402, 0x00100000,
-0x04100002, 0x00000402, 0x00100000, 0x04000002,
-0x00100400, 0x04000400, 0x00000002, 0x04100000,
-0x04000402, 0x00000000, 0x00000400, 0x00100002,
-0x00000000, 0x04100002, 0x04100400, 0x00000400,
-0x04000000, 0x04100402, 0x00100402, 0x00100000,
-0x04100402, 0x00000002, 0x04000400, 0x00100402,
-0x00100002, 0x00100400, 0x04100000, 0x04000402,
-0x00000402, 0x04000000, 0x04000002, 0x04100400 },
-
-/* nibble 4 */
-{ 0x02000000, 0x00004000, 0x00000100, 0x02004108,
-0x02004008, 0x02000100, 0x00004108, 0x02004000,
-0x00004000, 0x00000008, 0x02000008, 0x00004100,
-0x02000108, 0x02004008, 0x02004100, 0x00000000,
-0x00004100, 0x02000000, 0x00004008, 0x00000108,
-0x02000100, 0x00004108, 0x00000000, 0x02000008,
-0x00000008, 0x02000108, 0x02004108, 0x00004008,
-0x02004000, 0x00000100, 0x00000108, 0x02004100,
-0x02004100, 0x02000108, 0x00004008, 0x02004000,
-0x00004000, 0x00000008, 0x02000008, 0x02000100,
-0x02000000, 0x00004100, 0x02004108, 0x00000000,
-0x00004108, 0x02000000, 0x00000100, 0x00004008,
-0x02000108, 0x00000100, 0x00000000, 0x02004108,
-0x02004008, 0x02004100, 0x00000108, 0x00004000,
-0x00004100, 0x02004008, 0x02000100, 0x00000108,
-0x00000008, 0x00004108, 0x02004000, 0x02000008 },
-
-/* nibble 5 */
-{ 0x20000010, 0x00080010, 0x00000000, 0x20080800,
-0x00080010, 0x00000800, 0x20000810, 0x00080000,
-0x00000810, 0x20080810, 0x00080800, 0x20000000,
-0x20000800, 0x20000010, 0x20080000, 0x00080810,
-0x00080000, 0x20000810, 0x20080010, 0x00000000,
-0x00000800, 0x00000010, 0x20080800, 0x20080010,
-0x20080810, 0x20080000, 0x20000000, 0x00000810,
-0x00000010, 0x00080800, 0x00080810, 0x20000800,
-0x00000810, 0x20000000, 0x20000800, 0x00080810,
-0x20080800, 0x00080010, 0x00000000, 0x20000800,
-0x20000000, 0x00000800, 0x20080010, 0x00080000,
-0x00080010, 0x20080810, 0x00080800, 0x00000010,
-0x20080810, 0x00080800, 0x00080000, 0x20000810,
-0x20000010, 0x20080000, 0x00080810, 0x00000000,
-0x00000800, 0x20000010, 0x20000810, 0x20080800,
-0x20080000, 0x00000810, 0x00000010, 0x20080010 },
-
-/* nibble 6 */
-{ 0x00001000, 0x00000080, 0x00400080, 0x00400001,
-0x00401081, 0x00001001, 0x00001080, 0x00000000,
-0x00400000, 0x00400081, 0x00000081, 0x00401000,
-0x00000001, 0x00401080, 0x00401000, 0x00000081,
-0x00400081, 0x00001000, 0x00001001, 0x00401081,
-0x00000000, 0x00400080, 0x00400001, 0x00001080,
-0x00401001, 0x00001081, 0x00401080, 0x00000001,
-0x00001081, 0x00401001, 0x00000080, 0x00400000,
-0x00001081, 0x00401000, 0x00401001, 0x00000081,
-0x00001000, 0x00000080, 0x00400000, 0x00401001,
-0x00400081, 0x00001081, 0x00001080, 0x00000000,
-0x00000080, 0x00400001, 0x00000001, 0x00400080,
-0x00000000, 0x00400081, 0x00400080, 0x00001080,
-0x00000081, 0x00001000, 0x00401081, 0x00400000,
-0x00401080, 0x00000001, 0x00001001, 0x00401081,
-0x00400001, 0x00401080, 0x00401000, 0x00001001 },
-
-/* nibble 7 */
-{ 0x08200020, 0x08208000, 0x00008020, 0x00000000,
-0x08008000, 0x00200020, 0x08200000, 0x08208020,
-0x00000020, 0x08000000, 0x00208000, 0x00008020,
-0x00208020, 0x08008020, 0x08000020, 0x08200000,
-0x00008000, 0x00208020, 0x00200020, 0x08008000,
-0x08208020, 0x08000020, 0x00000000, 0x00208000,
-0x08000000, 0x00200000, 0x08008020, 0x08200020,
-0x00200000, 0x00008000, 0x08208000, 0x00000020,
-0x00200000, 0x00008000, 0x08000020, 0x08208020,
-0x00008020, 0x08000000, 0x00000000, 0x00208000,
-0x08200020, 0x08008020, 0x08008000, 0x00200020,
-0x08208000, 0x00000020, 0x00200020, 0x08008000,
-0x08208020, 0x00200000, 0x08200000, 0x08000020,
-0x00208000, 0x00008020, 0x08008020, 0x08200000,
-0x00000020, 0x08208000, 0x00208020, 0x00000000,
-0x08000000, 0x08200020, 0x00008000, 0x00208020 }};
-
-/* Some stuff that used to be in des_locl.h. Heavily modified. */
- /* IP and FP
- * The problem is more of a geometric problem that random bit fiddling.
- 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6
- 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4
- 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2
- 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0
-
- 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7
- 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5
- 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3
- 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1
-
- The output has been subject to swaps of the form
- 0 1 -> 3 1 but the odd and even bits have been put into
- 2 3 2 0
- different words. The main trick is to remember that
- t=((l>>size)^r)&(mask);
- r^=t;
- l^=(t<<size);
- can be used to swap and move bits between words.
-
- So l = 0 1 2 3 r = 16 17 18 19
- 4 5 6 7 20 21 22 23
- 8 9 10 11 24 25 26 27
- 12 13 14 15 28 29 30 31
- becomes (for size == 2 and mask == 0x3333)
- t = 2^16 3^17 -- -- l = 0 1 16 17 r = 2 3 18 19
- 6^20 7^21 -- -- 4 5 20 21 6 7 22 23
- 10^24 11^25 -- -- 8 9 24 25 10 11 24 25
- 14^28 15^29 -- -- 12 13 28 29 14 15 28 29
-
- Thanks for hints from Richard Outerbridge - he told me IP&FP
- could be done in 15 xor, 10 shifts and 5 ands.
- When I finally started to think of the problem in 2D
- I first got ~42 operations without xors. When I remembered
- how to use xors :-) I got it to its final state.
- */
-#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
- (b)^=(t),\
- (a)^=((t)<<(n)))
-
-#define IP(l,r,t) \
- PERM_OP(r,l,t, 4,0x0f0f0f0f); \
- PERM_OP(l,r,t,16,0x0000ffff); \
- PERM_OP(r,l,t, 2,0x33333333); \
- PERM_OP(l,r,t, 8,0x00ff00ff); \
- PERM_OP(r,l,t, 1,0x55555555);
-
-#define FP(l,r,t) \
- PERM_OP(l,r,t, 1,0x55555555); \
- PERM_OP(r,l,t, 8,0x00ff00ff); \
- PERM_OP(l,r,t, 2,0x33333333); \
- PERM_OP(r,l,t,16,0x0000ffff); \
- PERM_OP(l,r,t, 4,0x0f0f0f0f);
-
-#define D_ENCRYPT(L,R,S) \
- u=(R^s[S ]); \
- t=R^s[S+1]; \
- t=((t>>4)+(t<<28)); \
- L^= des_SPtrans[1][(t )&0x3f]| \
- des_SPtrans[3][(t>> 8)&0x3f]| \
- des_SPtrans[5][(t>>16)&0x3f]| \
- des_SPtrans[7][(t>>24)&0x3f]| \
- des_SPtrans[0][(u )&0x3f]| \
- des_SPtrans[2][(u>> 8)&0x3f]| \
- des_SPtrans[4][(u>>16)&0x3f]| \
- des_SPtrans[6][(u>>24)&0x3f];
-
-/* This part is based on code that used to be in ecb_enc.c. */
-/* Copyright (C) 1993 Eric Young - see README for more details */
-
-static void des_encrypt(word32 l, word32 r, word32 *output, DESContext *ks,
- int encrypt)
-{
- register word32 t,u;
- register int i;
- register word32 *s;
-
- s = ks->key_schedule;
-
- IP(l,r,t);
- /* Things have been modified so that the initial rotate is
- * done outside the loop. This required the
- * des_SPtrans values in sp.h to be rotated 1 bit to the right.
- * One perl script later and things have a 5% speed up on a sparc2.
- * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
- * for pointing this out. */
- t=(r<<1)|(r>>31);
- r=(l<<1)|(l>>31);
- l=t;
-
- /* I don't know if it is worth the effort of loop unrolling the
- * inner loop */
- if (encrypt)
- {
- for (i=0; i<32; i+=4)
- {
- D_ENCRYPT(l,r,i+0); /* 1 */
- D_ENCRYPT(r,l,i+2); /* 2 */
- }
- }
- else
- {
- for (i=30; i>0; i-=4)
- {
- D_ENCRYPT(l,r,i-0); /* 16 */
- D_ENCRYPT(r,l,i-2); /* 15 */
- }
+#define f(R, K0246, K1357) (\
+ s0246 = R ^ K0246, \
+ s1357 = R ^ K1357, \
+ s0246 = rotl(s0246, 28), \
+ SPboxes[0] [(s0246 >> 24) & 0x3F] | \
+ SPboxes[1] [(s1357 >> 24) & 0x3F] | \
+ SPboxes[2] [(s0246 >> 16) & 0x3F] | \
+ SPboxes[3] [(s1357 >> 16) & 0x3F] | \
+ SPboxes[4] [(s0246 >> 8) & 0x3F] | \
+ SPboxes[5] [(s1357 >> 8) & 0x3F] | \
+ SPboxes[6] [(s0246 ) & 0x3F] | \
+ SPboxes[7] [(s1357 ) & 0x3F])
+
+#define bitswap(L, R, n, mask) (\
+ swap = mask & ( (R >> n) ^ L ), \
+ R ^= swap << n, \
+ L ^= swap)
+
+/* Initial permutation */
+#define IP(L, R) (\
+ bitswap(R, L, 4, 0x0F0F0F0F), \
+ bitswap(R, L, 16, 0x0000FFFF), \
+ bitswap(L, R, 2, 0x33333333), \
+ bitswap(L, R, 8, 0x00FF00FF), \
+ bitswap(R, L, 1, 0x55555555))
+
+/* Final permutation */
+#define FP(L, R) (\
+ bitswap(R, L, 1, 0x55555555), \
+ bitswap(L, R, 8, 0x00FF00FF), \
+ bitswap(L, R, 2, 0x33333333), \
+ bitswap(R, L, 16, 0x0000FFFF), \
+ bitswap(R, L, 4, 0x0F0F0F0F))
+
+void des_encipher(word32 *output, word32 L, word32 R, DESContext *sched) {
+ word32 swap, s0246, s1357;
+
+ IP(L, R);
+
+ L = rotl(L, 1);
+ R = rotl(R, 1);
+
+ L ^= f(R, sched->k0246[ 0], sched->k1357[ 0]);
+ R ^= f(L, sched->k0246[ 1], sched->k1357[ 1]);
+ L ^= f(R, sched->k0246[ 2], sched->k1357[ 2]);
+ R ^= f(L, sched->k0246[ 3], sched->k1357[ 3]);
+ L ^= f(R, sched->k0246[ 4], sched->k1357[ 4]);
+ R ^= f(L, sched->k0246[ 5], sched->k1357[ 5]);
+ L ^= f(R, sched->k0246[ 6], sched->k1357[ 6]);
+ R ^= f(L, sched->k0246[ 7], sched->k1357[ 7]);
+ L ^= f(R, sched->k0246[ 8], sched->k1357[ 8]);
+ R ^= f(L, sched->k0246[ 9], sched->k1357[ 9]);
+ L ^= f(R, sched->k0246[10], sched->k1357[10]);
+ R ^= f(L, sched->k0246[11], sched->k1357[11]);
+ L ^= f(R, sched->k0246[12], sched->k1357[12]);
+ R ^= f(L, sched->k0246[13], sched->k1357[13]);
+ L ^= f(R, sched->k0246[14], sched->k1357[14]);
+ R ^= f(L, sched->k0246[15], sched->k1357[15]);
+
+ L = rotl(L, 31);
+ R = rotl(R, 31);
+
+ swap = L; L = R; R = swap;
+
+ FP(L, R);
+
+ output[0] = L;
+ output[1] = R;
+}
+
+void des_decipher(word32 *output, word32 L, word32 R, DESContext *sched) {
+ word32 swap, s0246, s1357;
+
+ IP(L, R);
+
+ L = rotl(L, 1);
+ R = rotl(R, 1);
+
+ L ^= f(R, sched->k0246[15], sched->k1357[15]);
+ R ^= f(L, sched->k0246[14], sched->k1357[14]);
+ L ^= f(R, sched->k0246[13], sched->k1357[13]);
+ R ^= f(L, sched->k0246[12], sched->k1357[12]);
+ L ^= f(R, sched->k0246[11], sched->k1357[11]);
+ R ^= f(L, sched->k0246[10], sched->k1357[10]);
+ L ^= f(R, sched->k0246[ 9], sched->k1357[ 9]);
+ R ^= f(L, sched->k0246[ 8], sched->k1357[ 8]);
+ L ^= f(R, sched->k0246[ 7], sched->k1357[ 7]);
+ R ^= f(L, sched->k0246[ 6], sched->k1357[ 6]);
+ L ^= f(R, sched->k0246[ 5], sched->k1357[ 5]);
+ R ^= f(L, sched->k0246[ 4], sched->k1357[ 4]);
+ L ^= f(R, sched->k0246[ 3], sched->k1357[ 3]);
+ R ^= f(L, sched->k0246[ 2], sched->k1357[ 2]);
+ L ^= f(R, sched->k0246[ 1], sched->k1357[ 1]);
+ R ^= f(L, sched->k0246[ 0], sched->k1357[ 0]);
+
+ L = rotl(L, 31);
+ R = rotl(R, 31);
+
+ swap = L; L = R; R = swap;
+
+ FP(L, R);
+
+ output[0] = L;
+ output[1] = R;
+}
+
+#define GET_32BIT_MSB_FIRST(cp) \
+ (((unsigned long)(unsigned char)(cp)[3]) | \
+ ((unsigned long)(unsigned char)(cp)[2] << 8) | \
+ ((unsigned long)(unsigned char)(cp)[1] << 16) | \
+ ((unsigned long)(unsigned char)(cp)[0] << 24))
+
+#define PUT_32BIT_MSB_FIRST(cp, value) do { \
+ (cp)[3] = (value); \
+ (cp)[2] = (value) >> 8; \
+ (cp)[1] = (value) >> 16; \
+ (cp)[0] = (value) >> 24; } while (0)
+
+static void des_cbc_encrypt(unsigned char *dest, const unsigned char *src,
+ unsigned int len, DESContext *sched) {
+ word32 out[2], iv0, iv1;
+ unsigned int i;
+
+ assert((len & 7) == 0);
+
+ iv0 = sched->eiv0;
+ iv1 = sched->eiv1;
+ for (i = 0; i < len; i += 8) {
+ iv0 ^= GET_32BIT_MSB_FIRST(src); src += 4;
+ iv1 ^= GET_32BIT_MSB_FIRST(src); src += 4;
+ des_encipher(out, iv0, iv1, sched);
+ iv0 = out[0];
+ iv1 = out[1];
+ PUT_32BIT_MSB_FIRST(dest, iv0); dest += 4;
+ PUT_32BIT_MSB_FIRST(dest, iv1); dest += 4;