+++ /dev/null
-/* Modified for SILC. -Pekka */\r
-\r
-/* This is an independent implementation of the encryption algorithm: */\r
-/* */\r
-/* DFC designed by a team at CNRS and France Telecom */\r
-/* */\r
-/* which is a candidate algorithm in the Advanced Encryption Standard */\r
-/* programme of the US National Institute of Standards and Technology. */\r
-/* */\r
-/* Copyright in this implementation is held by Dr B R Gladman but I */\r
-/* hereby give permission for its free direct or derivative use subject */\r
-/* to acknowledgment of its origin and compliance with any conditions */\r
-/* that the originators of the algorithm place on its exploitation. */\r
-/* */\r
-/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */\r
-/* */\r
-/* My thanks go to Serge Vaudenay of the Ecole Normale Superieure */\r
-/* for providing test vectors. This implementation has also been */\r
-/* tested with an independent implementation by Dr Russell Bradford */\r
-/* (Department of Mathematical Sciences, University of Bath, Bath, */\r
-/* UK) and checks out. My thanks go to Russell for his help in */\r
-/* comparing our implementations and finding bugs (and for help in */\r
-/* resolving 'endian' issues before test vectors became available). */\r
-\r
-/* Timing data for DFC (dfc.c)\r
-\r
-Core timing without I/O endian conversion:\r
-\r
-Algorithm: dfc (dfc.c)\r
-\r
-128 bit key:\r
-Key Setup: 5222 cycles\r
-Encrypt: 1203 cycles = 21.3 mbits/sec\r
-Decrypt: 1244 cycles = 20.6 mbits/sec\r
-Mean: 1224 cycles = 20.9 mbits/sec\r
-\r
-192 bit key:\r
-Key Setup: 5203 cycles\r
-Encrypt: 1288 cycles = 19.9 mbits/sec\r
-Decrypt: 1235 cycles = 20.7 mbits/sec\r
-Mean: 1262 cycles = 20.3 mbits/sec\r
-\r
-256 bit key:\r
-Key Setup: 5177 cycles\r
-Encrypt: 1178 cycles = 21.7 mbits/sec\r
-Decrypt: 1226 cycles = 20.9 mbits/sec\r
-Mean: 1202 cycles = 21.3 mbits/sec\r
-\r
-Full timing with I/O endian conversion:\r
-\r
-128 bit key:\r
-Key Setup: 5227 cycles\r
-Encrypt: 1247 cycles = 20.5 mbits/sec\r
-Decrypt: 1222 cycles = 20.9 mbits/sec\r
-Mean: 1235 cycles = 20.7 mbits/sec\r
-\r
-192 bit key:\r
-Key Setup: 5252 cycles\r
-Encrypt: 1215 cycles = 21.1 mbits/sec\r
-Decrypt: 1265 cycles = 20.2 mbits/sec\r
-Mean: 1240 cycles = 20.6 mbits/sec\r
-\r
-256 bit key:\r
-Key Setup: 5174 cycles\r
-Encrypt: 1247 cycles = 20.5 mbits/sec\r
-Decrypt: 1206 cycles = 21.2 mbits/sec\r
-Mean: 1227 cycles = 20.9 mbits/sec\r
-\r
-*/\r
-\r
-/* The EES string is as follows (the abstract contains an error in \r
- the last line of this sequence which changes KC and KD):\r
-\r
- 0xb7e15162, 0x8aed2a6a, 0xbf715880, 0x9cf4f3c7, \r
- 0x62e7160f, 0x38b4da56, 0xa784d904, 0x5190cfef, \r
- 0x324e7738, 0x926cfbe5, 0xf4bf8d8d, 0x8c31d763,\r
- 0xda06c80a, 0xbb1185eb, 0x4f7c7b57, 0x57f59584, \r
-\r
- 0x90cfd47d, 0x7c19bb42, 0x158d9554, 0xf7b46bce, \r
- 0xd55c4d79, 0xfd5f24d6, 0x613c31c3, 0x839a2ddf,\r
- 0x8a9a276b, 0xcfbfa1c8, 0x77c56284, 0xdab79cd4, \r
- 0xc2b3293d, 0x20e9e5ea, 0xf02ac60a, 0xcc93ed87, \r
-\r
- 0x4422a52e, 0xcb238fee, 0xe5ab6add, 0x835fd1a0,\r
- 0x753d0a8f, 0x78e537d2, 0xb95bb79d, 0x8dcaec64, \r
- 0x2c1e9f23, 0xb829b5c2, 0x780bf387, 0x37df8bb3, \r
- 0x00d01334, 0xa0d0bd86, 0x45cbfa73, 0xa6160ffe,\r
-\r
- 0x393c48cb, 0xbbca060f, 0x0ff8ec6d, 0x31beb5cc, \r
- 0xeed7f2f0, 0xbb088017, 0x163bc60d, 0xf45a0ecb, \r
- 0x1bcd289b, 0x06cbbfea, 0x21ad08e1, 0x847f3f73,\r
- 0x78d56ced, 0x94640d6e, 0xf0d3d37b, 0xe67008e1, \r
- \r
- 0x86d1bf27, 0x5b9b241d, 0xeb64749a, 0x47dfdfb9, \r
-\r
- Where:\r
-\r
- EES = RT(0) | RT(1) | ... | RT(63) | KD | KC\r
-\r
- Note that the abstract describing DFC is written \r
- in big endian notation with the most significant \r
- digits of a sequence of digits placed at the low\r
- index positions in arrays. This format is used\r
- here and is only converted to machine format at\r
- the point that maths is done on any numbers in \r
- the round function.\r
- \r
- The key input is thus treated as an array of 32 \r
- bit words numbered from 0..3, 0..5 or 0..7 \r
- depending on key length. The first (leftmost) \r
- bit of this key string as defined in the DFC \r
- abstract is the most significant bit of word 0 \r
- and the rightmost bit of this string is the least \r
- signicant bit of the highest numbered key word.\r
-\r
- The input and output blocks for the cipher are \r
- also treated as arrays of 32 bit words numbered\r
- from 0..3. The most significant bit of word 0 is\r
- the 1st (leftmost) bit of the 128 bit input string \r
- and the least significant bit of word 3 is the \r
- last (rightmost) bit.\r
- \r
- Note that the inputs, the output and the key are\r
- in Intel little endian format when BYTE_SWAP is \r
- defined\r
-*/\r
-\r
-#include <stdio.h>\r
-#include <sys/types.h>\r
-#include "dfc_internal.h"\r
-\r
-/* The following arrays are all stored in big endian */\r
-/* format with 32 bit words at lower array positions */\r
-/* being more significant in multi-word values */\r
-\r
-u4byte rt64[64] = \r
-{\r
- 0xb7e15162, 0x8aed2a6a, 0xbf715880, 0x9cf4f3c7, \r
- 0x62e7160f, 0x38b4da56, 0xa784d904, 0x5190cfef, \r
- 0x324e7738, 0x926cfbe5, 0xf4bf8d8d, 0x8c31d763,\r
- 0xda06c80a, 0xbb1185eb, 0x4f7c7b57, 0x57f59584, \r
-\r
- 0x90cfd47d, 0x7c19bb42, 0x158d9554, 0xf7b46bce, \r
- 0xd55c4d79, 0xfd5f24d6, 0x613c31c3, 0x839a2ddf,\r
- 0x8a9a276b, 0xcfbfa1c8, 0x77c56284, 0xdab79cd4, \r
- 0xc2b3293d, 0x20e9e5ea, 0xf02ac60a, 0xcc93ed87, \r
-\r
- 0x4422a52e, 0xcb238fee, 0xe5ab6add, 0x835fd1a0,\r
- 0x753d0a8f, 0x78e537d2, 0xb95bb79d, 0x8dcaec64, \r
- 0x2c1e9f23, 0xb829b5c2, 0x780bf387, 0x37df8bb3, \r
- 0x00d01334, 0xa0d0bd86, 0x45cbfa73, 0xa6160ffe,\r
-\r
- 0x393c48cb, 0xbbca060f, 0x0ff8ec6d, 0x31beb5cc, \r
- 0xeed7f2f0, 0xbb088017, 0x163bc60d, 0xf45a0ecb, \r
- 0x1bcd289b, 0x06cbbfea, 0x21ad08e1, 0x847f3f73,\r
- 0x78d56ced, 0x94640d6e, 0xf0d3d37b, 0xe67008e1, \r
-};\r
-\r
-u4byte kc = 0xeb64749a;\r
-\r
-u4byte kd2[2] = \r
-{\r
- 0x86d1bf27, 0x5b9b241d \r
-};\r
-\r
-u4byte ka2[6] = \r
-{\r
- 0xb7e15162, 0x8aed2a6a, \r
- 0xbf715880, 0x9cf4f3c7, \r
- 0x62e7160f, 0x38b4da56, \r
-};\r
-\r
-u4byte kb2[6] =\r
-{\r
- 0xa784d904, 0x5190cfef, \r
- 0x324e7738, 0x926cfbe5, \r
- 0xf4bf8d8d, 0x8c31d763,\r
-};\r
-\r
-u4byte ks8[8] = \r
-{ 0xda06c80a, 0xbb1185eb, 0x4f7c7b57, 0x57f59584, \r
- 0x90cfd47d, 0x7c19bb42, 0x158d9554, 0xf7b46bce,\r
-};\r
-\r
-#define lo(x) ((x) & 0x0000ffff)\r
-#define hi(x) ((x) >> 16)\r
-\r
-#define mult_64(r,x,y) \\r
- x0 = lo(x[1]); x1 = hi(x[1]); x2 = lo(x[0]); x3 = hi(x[0]); \\r
- y0 = lo(y[1]); y1 = hi(y[1]); y2 = lo(y[0]); y3 = hi(y[0]); \\r
- t0 = x0 * y0; r[0] = lo(t0); c = hi(t0); \\r
- t0 = x0 * y1; t1 = x1 * y0; c += lo(t0) + lo(t1); \\r
- r[0] += (c << 16); c = hi(c) + hi(t0) + hi(t1); \\r
- t0 = x0 * y2; t1 = x1 * y1; t2 = x2 * y0; \\r
- c += lo(t0) + lo(t1) + lo(t2); r[1] = lo(c); \\r
- c = hi(c) + hi(t0) + hi(t1) + hi(t2); \\r
- t0 = x0 * y3; t1 = x1 * y2; t2 = x2 * y1; t3 = x3 * y0; \\r
- c += lo(t0) + lo(t1) + lo(t2) + lo(t3); r[1] += (c << 16); \\r
- c = hi(c) + hi(t0) + hi(t1) + hi(t2) + hi(t3); \\r
- t0 = x1 * y3; t1 = x2 * y2; t2 = x3 * y1; \\r
- c += lo(t0) + lo(t1) + lo(t2); r[2] = lo(c); \\r
- c = hi(c) + hi(t0) + hi(t1) + hi(t2); \\r
- t0 = x2 * y3; t1 = x3 * y2; c += lo(t0) + lo(t1); \\r
- r[2] += (c << 16); c = hi(c) + hi(t0) + hi(t1); \\r
- r[3] = c + x3 * y3\r
-\r
-#define add_64(r,hi,lo) \\r
- if((r[0] += lo) < lo) \\r
- if(!++r[1]) \\r
- if(!++r[2]) \\r
- ++r[3]; \\r
- if((r[1] += hi) < hi) \\r
- if(!++r[2]) \\r
- ++r[3]\r
- \r
-#define mult_13(r) \\r
- c = 13 * lo((r)[0]); \\r
- d = hi((r)[0]); \\r
- (r)[0] = lo(c); \\r
- c = hi(c) + 13 * d; \\r
- (r)[0] += (c << 16); \\r
- c = hi(c) + 13 * lo((r)[1]); \\r
- d = hi((r)[1]); \\r
- (r)[1] = lo(c); \\r
- c = hi(c) + 13 * d; \\r
- (r)[1] += (c << 16); \\r
- (r)[2] = hi(c)\r
-\r
-/* Where necessary this is where conversion from big endian to */\r
-/* little endian format is performed. Since all the maths is */\r
-/* little endian care is needed when 64 bit blocks are being */\r
-/* used to get them in the right order by reversing the order */\r
-/* in which these are stored. This applies to the key array */\r
-/* which gives the two values A and B and to the constant KD. */\r
-/* Since the input and output blocks are big endian we also */\r
-/* have to invert the order of the 32 bit words in the 64 bit */\r
-/* blocks being processed. */ \r
-\r
-void r_fun(u4byte outp[2], const u4byte inp[2], const u4byte key[4])\r
-{ u4byte acc[5], x0, x1, x2, x3, y0, y1, y2, y3, t0, t1, t2, t3, c, d;\r
-\r
- mult_64(acc, inp, key); add_64(acc, key[2], key[3]);\r
-\r
- /* we need the value in the accumulator mod 2^64 + 13 so if */\r
- /* the accumulator value is hi * 2^64 + lo we need to find */\r
- /* a k value such that r = hi * 2^64 + lo - k * (2^64 + 13) */\r
- /* is 0 <= r < 2^64 + 13. We can see that k will be close */\r
- /* to hi in value - it may equal hi but will not be greater */\r
- /* and we can let k = hi - e with e >= 0 so that r is given */\r
- /* by r = e * (2^64 + 13) + lo - 13 * hi. If we compute the */\r
- /* lo - 13 * hi value, the overflow into the top 64 bits of */\r
- /* the accumulator has to be 'zeroed' by the e * (2^64 + 13)*/\r
- /* term and this sets the e value (in fact such an overlow */\r
- /* is only removed when the lower word is higher than 12). */\r
-\r
- mult_13(acc + 2); /* multiply top of accumulator by 13 */\r
-\r
- /* calculate lo - 13 * hi in acc[0] and acc[1] with any */\r
- /* overflow into top 64 bits in c */\r
-\r
- d = acc[0]; acc[0] -= acc[2]; c = (acc[0] > d ? 1 : 0);\r
-\r
- d = acc[1]; acc[1] -= acc[3] + c;\r
- c = (acc[1] > d ? 1 : (acc[1] == d ? c : 0));\r
-\r
- c = 13 * (acc[4] + c); /* overflow into top 64 bits of acc */\r
-\r
- if(((acc[0] += c) < c) && !(++acc[1]))\r
- {\r
- if(acc[0] > 12)\r
-\r
- acc[0] -= 13;\r
- }\r
-\r
- /* do the confusion permutation */\r
-\r
- d = acc[1] ^ kc; c = acc[0] ^ rt64[acc[1] >> 26]; \r
- \r
- c += kd2[0] + ((d += kd2[1]) < kd2[1] ? 1 : 0);\r
-\r
- outp[0] ^= c; outp[1] ^= d; \r
-};\r
-\r
-u4byte *dfc_set_key(DfcContext *ctx,\r
- const u4byte in_key[], const u4byte key_len)\r
-{ \r
- u4byte i, lk[32], rk[4];\r
- u4byte *l_key = ctx->l_key;\r
-\r
- for(i = 0; i < key_len / 32; ++i)\r
-\r
- lk[i] = io_swap(in_key[i]);\r
-\r
- /* pad the key with the KS array */\r
-\r
- for(i = 0; i < 8 - key_len / 32; ++i) /* K|KS */\r
-\r
- lk[i + key_len / 32] = ks8[i];\r
-\r
- /* do the reordering of the key parameters */\r
- /* the OAP[1]|OBP[1]|OAP[2]... sequence is */\r
- /* at lk[0]... and the other at lk[16]... */\r
- \r
- lk[18] = lk[5]; lk[19] = lk[2]; /* EBP */ \r
- lk[16] = lk[1]; lk[17] = lk[6]; /* EAP */\r
- lk[ 2] = lk[4]; lk[ 3] = lk[3]; /* OBP */\r
- lk[ 0] = lk[0]; lk[ 1] = lk[7]; /* OAP */\r
-\r
- /* create other elements using KA and KB */\r
-\r
- for(i = 0; i < 6; i += 2)\r
- {\r
- lk[i + i + 4] = lk[ 0] ^ ka2[i]; /* OAP[i] ms */\r
- lk[i + i + 5] = lk[ 1] ^ ka2[i + 1]; /* OAP[i] ls */\r
- lk[i + i + 6] = lk[ 2] ^ kb2[i]; /* OBP[i] ms */\r
- lk[i + i + 7] = lk[ 3] ^ kb2[i + 1]; /* OBP[i] ls */\r
- lk[i + i + 20] = lk[16] ^ ka2[i]; /* EAP[i] ms */\r
- lk[i + i + 21] = lk[17] ^ ka2[i + 1]; /* EAP[i] ls */\r
- lk[i + i + 22] = lk[18] ^ kb2[i]; /* EBP[i] ms */\r
- lk[i + i + 23] = lk[19] ^ kb2[i + 1]; /* EBP[i] ls */\r
- }\r
-\r
- rk[0] = rk[1] = rk[2] = rk[3] = 0;\r
-\r
- /* do the 4 round key mixing encryption */\r
-\r
- for(i = 0; i < 32; i += 8)\r
- {\r
- r_fun(rk, rk + 2, lk); /* R2|R1 */\r
- r_fun(rk + 2, rk, lk + 4); /* R2|R3 */\r
- r_fun(rk, rk + 2, lk + 8); /* R4|R3 */\r
- r_fun(rk + 2, rk, lk + 12); /* R4|R5 */\r
-\r
- /* keep key in big endian format with */\r
- /* the most significant 32 bit words */\r
- /* first (lowest) in the key schedule */\r
- /* - note that the upper and lower 64 */\r
- /* bit blocks are in inverse order at */\r
- /* this point in the loop */\r
-\r
- l_key[i + 0] = rk[2]; l_key[i + 1] = rk[3]; \r
- l_key[i + 2] = rk[0]; l_key[i + 3] = rk[1]; \r
-\r
- r_fun(rk + 2, rk, lk + 16); /* R1|R2 */\r
- r_fun(rk, rk + 2, lk + 20); /* R3|R2 */\r
- r_fun(rk + 2, rk, lk + 24); /* R3|R4 */ \r
- r_fun(rk, rk + 2, lk + 28); /* R5|R4 */\r
-\r
- l_key[i + 4] = rk[0]; l_key[i + 5] = rk[1]; \r
- l_key[i + 6] = rk[2]; l_key[i + 7] = rk[3];\r
- }\r
- \r
- return l_key;\r
-};\r
-\r
-void dfc_encrypt(DfcContext *ctx,\r
- const u4byte in_blk[4], u4byte out_blk[4])\r
-{ \r
- u4byte blk[4];\r
- u4byte *l_key = ctx->l_key;\r
-\r
- /* the input/output format is big endian - */\r
- /* any reversals needed are performed when */\r
- /* maths is done in the round function */\r
-\r
- blk[0] = io_swap(in_blk[0]); blk[1] = io_swap(in_blk[1]);\r
- blk[2] = io_swap(in_blk[2]); blk[3] = io_swap(in_blk[3]);\r
-\r
- r_fun(blk, blk + 2, l_key + 0); /* R2|R1 */ \r
- r_fun(blk + 2, blk, l_key + 4); /* R2|R3 */\r
- r_fun(blk, blk + 2, l_key + 8); /* R4|R3 */\r
- r_fun(blk + 2, blk, l_key + 12); /* R4|R5 */\r
- r_fun(blk, blk + 2, l_key + 16); /* R6|R5 */\r
- r_fun(blk + 2, blk, l_key + 20); /* R6|R7 */\r
- r_fun(blk, blk + 2, l_key + 24); /* R8|R7 */\r
- r_fun(blk + 2, blk, l_key + 28); /* R8|R9 */\r
-\r
- /* swap order to obtain the result R9|R8 */\r
-\r
- out_blk[0] = io_swap(blk[2]); out_blk[1] = io_swap(blk[3]);\r
- out_blk[2] = io_swap(blk[0]); out_blk[3] = io_swap(blk[1]);\r
-};\r
-\r
-void dfc_decrypt(DfcContext *ctx,\r
- const u4byte in_blk[4], u4byte out_blk[4])\r
-{ \r
- u4byte blk[4];\r
- u4byte *l_key = ctx->l_key;\r
-\r
- /* the input/output format is big endian - */\r
- /* any reversals needed are performed when */\r
- /* maths is done in the round function */\r
-\r
- blk[0] = io_swap(in_blk[0]); blk[1] = io_swap(in_blk[1]);\r
- blk[2] = io_swap(in_blk[2]); blk[3] = io_swap(in_blk[3]);\r
-\r
- r_fun(blk, blk + 2, l_key + 28); /* R7|R8 */\r
- r_fun(blk + 2, blk, l_key + 24); /* R7|R6 */\r
- r_fun(blk, blk + 2, l_key + 20); /* R5|R6 */\r
- r_fun(blk + 2, blk, l_key + 16); /* R5|R4 */\r
- r_fun(blk, blk + 2, l_key + 12); /* R3|R4 */\r
- r_fun(blk + 2, blk, l_key + 8); /* R3|R2 */\r
- r_fun(blk, blk + 2, l_key + 4); /* R1|R2 */\r
- r_fun(blk + 2, blk, l_key ); /* R1|R0 */ \r
-\r
- /* swap order to obtain the result R1|R0 */\r
-\r
- out_blk[0] = io_swap(blk[2]); out_blk[1] = io_swap(blk[3]);\r
- out_blk[2] = io_swap(blk[0]); out_blk[3] = io_swap(blk[1]); \r
-};\r