/* Optimized implementation of the Serpent AES candidate algorithm * Designed by Anderson, Biham and Knudsen and Implemented by * Gisle Sælensminde 2000. * * The implementation is based on the pentium optimised sboxes of * Dag Arne Osvik. Even these sboxes are designed to be optimal for x86 * processors they are efficient on other processors as well, but the speedup * isn't so impressive compared to other implementations. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. */ #ifdef __KERNEL__ #include #include #include #else #include #include #endif #include "serpent.h" #define rotl(reg, val) ((reg << val) | (reg >> (32 - val))) #define rotr(reg, val) ((reg >> val) | (reg << (32 - val))) #ifdef __cpu_to_be32 #define BLOCK_SWAP #define io_swap(x) __cpu_to_be32(x) #else #undef BLOCK_SWAP #endif /* The sbox functions. The first four parameters is the input bits, and * the last is a tempoary. These parameters are also used for output, but * the bit order is permuted. The output bit order from S0 is * (1 4 2 0 3), where 3 is the (now useless) tempoary. */ #define S0(r0,r1,r2,r3,r4) \ r3 = r3 ^ r0; \ r4 = r1; \ r1 = r1 & r3; \ r4 = r4 ^ r2; \ r1 = r1 ^ r0; \ r0 = r0 | r3; \ r0 = r0 ^ r4; \ r4 = r4 ^ r3; \ r3 = r3 ^ r2; \ r2 = r2 | r1; \ r2 = r2 ^ r4; \ r4 = -1 ^ r4; \ r4 = r4 | r1; \ r1 = r1 ^ r3; \ r1 = r1 ^ r4; \ r3 = r3 | r0; \ r1 = r1 ^ r3; \ r4 = r4 ^ r3; #define S1(r0,r1,r2,r3,r4) \ r1 = -1 ^ r1; \ r4 = r0; \ r0 = r0 ^ r1; \ r4 = r4 | r1; \ r4 = r4 ^ r3; \ r3 = r3 & r0; \ r2 = r2 ^ r4; \ r3 = r3 ^ r1; \ r3 = r3 | r2; \ r0 = r0 ^ r4; \ r3 = r3 ^ r0; \ r1 = r1 & r2; \ r0 = r0 | r1; \ r1 = r1 ^ r4; \ r0 = r0 ^ r2; \ r4 = r4 | r3; \ r0 = r0 ^ r4; \ r4 = -1 ^ r4; \ r1 = r1 ^ r3; \ r4 = r4 & r2; \ r1 = -1 ^ r1; \ r4 = r4 ^ r0; \ r1 = r1 ^ r4; #define S2(r0,r1,r2,r3,r4) \ r4 = r0; \ r0 = r0 & r2; \ r0 = r0 ^ r3; \ r2 = r2 ^ r1; \ r2 = r2 ^ r0; \ r3 = r3 | r4; \ r3 = r3 ^ r1; \ r4 = r4 ^ r2; \ r1 = r3; \ r3 = r3 | r4; \ r3 = r3 ^ r0; \ r0 = r0 & r1; \ r4 = r4 ^ r0; \ r1 = r1 ^ r3; \ r1 = r1 ^ r4; \ r4 = -1 ^ r4; #define S3(r0,r1,r2,r3,r4) \ r4 = r0 ; \ r0 = r0 | r3; \ r3 = r3 ^ r1; \ r1 = r1 & r4; \ r4 = r4 ^ r2; \ r2 = r2 ^ r3; \ r3 = r3 & r0; \ r4 = r4 | r1; \ r3 = r3 ^ r4; \ r0 = r0 ^ r1; \ r4 = r4 & r0; \ r1 = r1 ^ r3; \ r4 = r4 ^ r2; \ r1 = r1 | r0; \ r1 = r1 ^ r2; \ r0 = r0 ^ r3; \ r2 = r1; \ r1 = r1 | r3; \ r1 = r1 ^ r0; #define S4(r0,r1,r2,r3,r4) \ r1 = r1 ^ r3; \ r3 = -1 ^ r3; \ r2 = r2 ^ r3; \ r3 = r3 ^ r0; \ r4 = r1; \ r1 = r1 & r3; \ r1 = r1 ^ r2; \ r4 = r4 ^ r3; \ r0 = r0 ^ r4; \ r2 = r2 & r4; \ r2 = r2 ^ r0; \ r0 = r0 & r1; \ r3 = r3 ^ r0; \ r4 = r4 | r1; \ r4 = r4 ^ r0; \ r0 = r0 | r3; \ r0 = r0 ^ r2; \ r2 = r2 & r3; \ r0 = -1 ^ r0; \ r4 = r4 ^ r2; #define S5(r0,r1,r2,r3,r4) \ r0 = r0 ^ r1; \ r1 = r1 ^ r3; \ r3 = -1 ^ r3; \ r4 = r1; \ r1 = r1 & r0; \ r2 = r2 ^ r3; \ r1 = r1 ^ r2; \ r2 = r2 | r4; \ r4 = r4 ^ r3; \ r3 = r3 & r1; \ r3 = r3 ^ r0; \ r4 = r4 ^ r1; \ r4 = r4 ^ r2; \ r2 = r2 ^ r0; \ r0 = r0 & r3; \ r2 = -1 ^ r2; \ r0 = r0 ^ r4; \ r4 = r4 | r3; \ r2 = r2 ^ r4; #define S6(r0,r1,r2,r3,r4) \ r2 = -1 ^ r2; \ r4 = r3; \ r3 = r3 & r0; \ r0 = r0 ^ r4; \ r3 = r3 ^ r2; \ r2 = r2 | r4; \ r1 = r1 ^ r3; \ r2 = r2 ^ r0; \ r0 = r0 | r1; \ r2 = r2 ^ r1; \ r4 = r4 ^ r0; \ r0 = r0 | r3; \ r0 = r0 ^ r2; \ r4 = r4 ^ r3; \ r4 = r4 ^ r0; \ r3 = -1 ^ r3; \ r2 = r2 & r4; \ r2 = r2 ^ r3; #define S7(r0,r1,r2,r3,r4) \ r4 = r2; \ r2 = r2 & r1; \ r2 = r2 ^ r3; \ r3 = r3 & r1; \ r4 = r4 ^ r2; \ r2 = r2 ^ r1; \ r1 = r1 ^ r0; \ r0 = r0 | r4; \ r0 = r0 ^ r2; \ r3 = r3 ^ r1; \ r2 = r2 ^ r3; \ r3 = r3 & r0; \ r3 = r3 ^ r4; \ r4 = r4 ^ r2; \ r2 = r2 & r0; \ r4 = -1 ^ r4; \ r2 = r2 ^ r4; \ r4 = r4 & r0; \ r1 = r1 ^ r3; \ r4 = r4 ^ r1; /* The inverse sboxes */ #define I0(r0,r1,r2,r3,r4) \ r2 = r2 ^ -1; \ r4 = r1; \ r1 = r1 | r0; \ r4 = r4 ^ -1; \ r1 = r1 ^ r2; \ r2 = r2 | r4; \ r1 = r1 ^ r3; \ r0 = r0 ^ r4; \ r2 = r2 ^ r0; \ r0 = r0 & r3; \ r4 = r4 ^ r0; \ r0 = r0 | r1; \ r0 = r0 ^ r2; \ r3 = r3 ^ r4; \ r2 = r2 ^ r1; \ r3 = r3 ^ r0; \ r3 = r3 ^ r1; \ r2 = r2 & r3; \ r4 = r4 ^ r2; #define I1(r0,r1,r2,r3,r4) \ r4 = r1; \ r1 = r1 ^ r3; \ r3 = r3 & r1; \ r4 = r4 ^ r2; \ r3 = r3 ^ r0; \ r0 = r0 | r1; \ r2 = r2 ^ r3; \ r0 = r0 ^ r4; \ r0 = r0 | r2; \ r1 = r1 ^ r3; \ r0 = r0 ^ r1; \ r1 = r1 | r3; \ r1 = r1 ^ r0; \ r4 = r4 ^ -1; \ r4 = r4 ^ r1; \ r1 = r1 | r0; \ r1 = r1 ^ r0; \ r1 = r1 | r4; \ r3 = r3 ^ r1; #define I2(r0,r1,r2,r3,r4) \ r2 = r2 ^ r3; \ r3 = r3 ^ r0; \ r4 = r3; \ r3 = r3 & r2; \ r3 = r3 ^ r1; \ r1 = r1 | r2; \ r1 = r1 ^ r4; \ r4 = r4 & r3; \ r2 = r2 ^ r3; \ r4 = r4 & r0; \ r4 = r4 ^ r2; \ r2 = r2 & r1; \ r2 = r2 | r0; \ r3 = r3 ^ -1; \ r2 = r2 ^ r3; \ r0 = r0 ^ r3; \ r0 = r0 & r1; \ r3 = r3 ^ r4; \ r3 = r3 ^ r0; #define I3(r0,r1,r2,r3,r4) \ r4 = r2; \ r2 = r2 ^ r1; \ r0 = r0 ^ r2; \ r4 = r4 & r2; \ r4 = r4 ^ r0; \ r0 = r0 & r1; \ r1 = r1 ^ r3; \ r3 = r3 | r4; \ r2 = r2 ^ r3; \ r0 = r0 ^ r3; \ r1 = r1 ^ r4; \ r3 = r3 & r2; \ r3 = r3 ^ r1; \ r1 = r1 ^ r0; \ r1 = r1 | r2; \ r0 = r0 ^ r3; \ r1 = r1 ^ r4; \ r0 = r0 ^ r1; #define I4(r0,r1,r2,r3,r4) \ r4 = r2; \ r2 = r2 & r3; \ r2 = r2 ^ r1; \ r1 = r1 | r3; \ r1 = r1 & r0; \ r4 = r4 ^ r2; \ r4 = r4 ^ r1; \ r1 = r1 & r2; \ r0 = r0 ^ -1; \ r3 = r3 ^ r4; \ r1 = r1 ^ r3; \ r3 = r3 & r0; \ r3 = r3 ^ r2; \ r0 = r0 ^ r1; \ r2 = r2 & r0; \ r3 = r3 ^ r0; \ r2 = r2 ^ r4; \ r2 = r2 | r3; \ r3 = r3 ^ r0; \ r2 = r2 ^ r1; #define I5(r0,r1,r2,r3,r4) \ r1 = r1 ^ -1; \ r4 = r3; \ r2 = r2 ^ r1; \ r3 = r3 | r0; \ r3 = r3 ^ r2; \ r2 = r2 | r1; \ r2 = r2 & r0; \ r4 = r4 ^ r3; \ r2 = r2 ^ r4; \ r4 = r4 | r0; \ r4 = r4 ^ r1; \ r1 = r1 & r2; \ r1 = r1 ^ r3; \ r4 = r4 ^ r2; \ r3 = r3 & r4; \ r4 = r4 ^ r1; \ r3 = r3 ^ r0; \ r3 = r3 ^ r4; \ r4 = r4 ^ -1; #define I6(r0,r1,r2,r3,r4) \ r0 = r0 ^ r2; \ r4 = r2; \ r2 = r2 & r0; \ r4 = r4 ^ r3; \ r2 = r2 ^ -1; \ r3 = r3 ^ r1; \ r2 = r2 ^ r3; \ r4 = r4 | r0; \ r0 = r0 ^ r2; \ r3 = r3 ^ r4; \ r4 = r4 ^ r1; \ r1 = r1 & r3; \ r1 = r1 ^ r0; \ r0 = r0 ^ r3; \ r0 = r0 | r2; \ r3 = r3 ^ r1; \ r4 = r4 ^ r0; #define I7(r0,r1,r2,r3,r4) \ r4 = r2; \ r2 = r2 ^ r0; \ r0 = r0 & r3; \ r4 = r4 | r3; \ r2 = r2 ^ -1; \ r3 = r3 ^ r1; \ r1 = r1 | r0; \ r0 = r0 ^ r2; \ r2 = r2 & r4; \ r3 = r3 & r4; \ r1 = r1 ^ r2; \ r2 = r2 ^ r0; \ r0 = r0 | r2; \ r4 = r4 ^ r1; \ r0 = r0 ^ r3; \ r3 = r3 ^ r4; \ r4 = r4 | r0; \ r3 = r3 ^ r2; \ r4 = r4 ^ r2; /* forward and inverse linear transformations */ #define LINTRANS(r0,r1,r2,r3,r4) \ r0 = rotl(r0, 13); \ r2 = rotl(r2, 3); \ r3 = r3 ^ r2; \ r4 = r0 << 3; \ r1 = r1 ^ r0; \ r3 = r3 ^ r4; \ r1 = r1 ^ r2; \ r3 = rotl(r3, 7); \ r1 = rotl(r1, 1); \ r2 = r2 ^ r3; \ r4 = r1 << 7; \ r0 = r0 ^ r1; \ r2 = r2 ^ r4; \ r0 = r0 ^ r3; \ r2 = rotl(r2, 22); \ r0 = rotl(r0, 5); #define ILINTRANS(r0,r1,r2,r3,r4) \ r2 = rotr(r2, 22); \ r0 = rotr(r0, 5); \ r2 = r2 ^ r3; \ r4 = r1 << 7; \ r0 = r0 ^ r1; \ r2 = r2 ^ r4; \ r0 = r0 ^ r3; \ r3 = rotr(r3, 7); \ r1 = rotr(r1, 1); \ r3 = r3 ^ r2; \ r4 = r0 << 3; \ r1 = r1 ^ r0; \ r3 = r3 ^ r4; \ r1 = r1 ^ r2; \ r2 = rotr(r2, 3); \ r0 = rotr(r0, 13); #define KEYMIX(r0,r1,r2,r3,r4,IN) \ r0 = r0 ^ l_key[IN+8]; \ r1 = r1 ^ l_key[IN+9]; \ r2 = r2 ^ l_key[IN+10]; \ r3 = r3 ^ l_key[IN+11]; #define GETKEY(r0, r1, r2, r3, IN) \ r0 = l_key[IN+8]; \ r1 = l_key[IN+9]; \ r2 = l_key[IN+10]; \ r3 = l_key[IN+11]; #define SETKEY(r0, r1, r2, r3, IN) \ l_key[IN+8] = r0; \ l_key[IN+9] = r1; \ l_key[IN+10] = r2; \ l_key[IN+11] = r3; /* initialise the key schedule from the user supplied key */ int serpent_set_key(serpent_context *cx, const unsigned char *key, int key_len) { const u32 *in_key = (const u32 *)key; /* l_key - storage for the key schedule */ u32 *l_key = cx->keyinfo; u32 i,lk,r0,r1,r2,r3,r4; if (key_len != 16 && key_len != 24 && key_len != 32) return -1; /* unsupported key length */ key_len *= 8; i = 0; lk = (key_len + 31) / 32; while(i < lk) { #ifdef BLOCK_SWAP l_key[i] = io_swap(in_key[lk - i - 1]); #else l_key[i] = in_key[i]; #endif i++; } if (key_len < 256) { while(i < 8) l_key[i++] = 0; i = key_len / 32; lk = 1 << key_len % 32; l_key[i] &= lk - 1; l_key[i] |= lk; } for(i = 0; i < 132; ++i) { lk = l_key[i] ^ l_key[i + 3] ^ l_key[i + 5] ^ l_key[i + 7] ^ 0x9e3779b9 ^ i; l_key[i + 8] = (lk << 11) | (lk >> 21); } GETKEY(r0, r1, r2, r3, 0); S3(r0,r1,r2,r3,r4); SETKEY(r1, r2, r3, r4, 0) GETKEY(r0, r1, r2, r3, 4); S2(r0,r1,r2,r3,r4); SETKEY(r2, r3, r1, r4, 4) GETKEY(r0, r1, r2, r3, 8); S1(r0,r1,r2,r3,r4); SETKEY(r3, r1, r2, r0, 8) GETKEY(r0, r1, r2, r3, 12); S0(r0,r1,r2,r3,r4); SETKEY(r1, r4, r2, r0, 12) GETKEY(r0, r1, r2, r3, 16); S7(r0,r1,r2,r3,r4); SETKEY(r2, r4, r3, r0, 16) GETKEY(r0, r1, r2, r3, 20); S6(r0,r1,r2,r3,r4) SETKEY(r0, r1, r4, r2, 20) GETKEY(r0, r1, r2, r3, 24); S5(r0,r1,r2,r3,r4); SETKEY(r1, r3, r0, r2, 24) GETKEY(r0, r1, r2, r3, 28); S4(r0,r1,r2,r3,r4) SETKEY(r1, r4, r0, r3, 28) GETKEY(r0, r1, r2, r3, 32); S3(r0,r1,r2,r3,r4); SETKEY(r1, r2, r3, r4, 32) GETKEY(r0, r1, r2, r3, 36); S2(r0,r1,r2,r3,r4); SETKEY(r2, r3, r1, r4, 36) GETKEY(r0, r1, r2, r3, 40); S1(r0,r1,r2,r3,r4); SETKEY(r3, r1, r2, r0, 40) GETKEY(r0, r1, r2, r3, 44); S0(r0,r1,r2,r3,r4); SETKEY(r1, r4, r2, r0, 44) GETKEY(r0, r1, r2, r3, 48); S7(r0,r1,r2,r3,r4); SETKEY(r2, r4, r3, r0, 48) GETKEY(r0, r1, r2, r3, 52); S6(r0,r1,r2,r3,r4) SETKEY(r0, r1, r4, r2, 52) GETKEY(r0, r1, r2, r3, 56); S5(r0,r1,r2,r3,r4); SETKEY(r1, r3, r0, r2, 56) GETKEY(r0, r1, r2, r3, 60); S4(r0,r1,r2,r3,r4) SETKEY(r1, r4, r0, r3, 60) GETKEY(r0, r1, r2, r3, 64); S3(r0,r1,r2,r3,r4); SETKEY(r1, r2, r3, r4, 64) GETKEY(r0, r1, r2, r3, 68); S2(r0,r1,r2,r3,r4); SETKEY(r2, r3, r1, r4, 68) GETKEY(r0, r1, r2, r3, 72); S1(r0,r1,r2,r3,r4); SETKEY(r3, r1, r2, r0, 72) GETKEY(r0, r1, r2, r3, 76); S0(r0,r1,r2,r3,r4); SETKEY(r1, r4, r2, r0, 76) GETKEY(r0, r1, r2, r3, 80); S7(r0,r1,r2,r3,r4); SETKEY(r2, r4, r3, r0, 80) GETKEY(r0, r1, r2, r3, 84); S6(r0,r1,r2,r3,r4) SETKEY(r0, r1, r4, r2, 84) GETKEY(r0, r1, r2, r3, 88); S5(r0,r1,r2,r3,r4); SETKEY(r1, r3, r0, r2, 88) GETKEY(r0, r1, r2, r3, 92); S4(r0,r1,r2,r3,r4) SETKEY(r1, r4, r0, r3, 92) GETKEY(r0, r1, r2, r3, 96); S3(r0,r1,r2,r3,r4); SETKEY(r1, r2, r3, r4, 96) GETKEY(r0, r1, r2, r3, 100); S2(r0,r1,r2,r3,r4); SETKEY(r2, r3, r1, r4, 100) GETKEY(r0, r1, r2, r3, 104); S1(r0,r1,r2,r3,r4); SETKEY(r3, r1, r2, r0, 104) GETKEY(r0, r1, r2, r3, 108); S0(r0,r1,r2,r3,r4); SETKEY(r1, r4, r2, r0, 108) GETKEY(r0, r1, r2, r3, 112); S7(r0,r1,r2,r3,r4); SETKEY(r2, r4, r3, r0, 112) GETKEY(r0, r1, r2, r3, 116); S6(r0,r1,r2,r3,r4) SETKEY(r0, r1, r4, r2, 116) GETKEY(r0, r1, r2, r3, 120); S5(r0,r1,r2,r3,r4); SETKEY(r1, r3, r0, r2, 120) GETKEY(r0, r1, r2, r3, 124); S4(r0,r1,r2,r3,r4) SETKEY(r1, r4, r0, r3, 124) GETKEY(r0, r1, r2, r3, 128); S3(r0,r1,r2,r3,r4); SETKEY(r1, r2, r3, r4, 128) return 0; }; /* Encryption and decryption functions. The rounds are fully inlined. * The sboxes alters the bit order of the output, and the altered * bit ordrer is used progressivly. */ /* encrypt a block of text */ int serpent_encrypt(serpent_context *cx, const u8 *in, u8 *out) { u32 *l_key = cx->keyinfo; const u32 *in_blk = (const u32 *) in; u32 *out_blk = (u32 *) out; u32 r0,r1,r2,r3,r4; #ifdef BLOCK_SWAP r0 = io_swap(in_blk[3]); r1 = io_swap(in_blk[2]); r2 = io_swap(in_blk[1]); r3 = io_swap(in_blk[0]); #else r0 = in_blk[0]; r1 = in_blk[1]; r2 = in_blk[2]; r3 = in_blk[3]; #endif /* round 1 */ KEYMIX(r0,r1,r2,r3,r4,0); S0(r0,r1,r2,r3,r4); LINTRANS(r1,r4,r2,r0,r3); /* round 2 */ KEYMIX(r1,r4,r2,r0,r3,4); S1(r1,r4,r2,r0,r3); LINTRANS(r0,r4,r2,r1,r3); /* round 3 */ KEYMIX(r0,r4,r2,r1,r3,8); S2(r0,r4,r2,r1,r3); LINTRANS(r2,r1,r4,r3,r0); /* round 4 */ KEYMIX(r2,r1,r4,r3,r0,12); S3(r2,r1,r4,r3,r0); LINTRANS(r1,r4,r3,r0,r2); /* round 5 */ KEYMIX(r1,r4,r3,r0,r2,16); S4(r1,r4,r3,r0,r2) LINTRANS(r4,r2,r1,r0,r3); /* round 6 */ KEYMIX(r4,r2,r1,r0,r3,20); S5(r4,r2,r1,r0,r3); LINTRANS(r2,r0,r4,r1,r3); /* round 7 */ KEYMIX(r2,r0,r4,r1,r3,24); S6(r2,r0,r4,r1,r3) LINTRANS(r2,r0,r3,r4,r1); /* round 8 */ KEYMIX(r2,r0,r3,r4,r1,28); S7(r2,r0,r3,r4,r1); LINTRANS(r3,r1,r4,r2,r0); /* round 9 */ KEYMIX(r3,r1,r4,r2,r0,32); S0(r3,r1,r4,r2,r0); LINTRANS(r1,r0,r4,r3,r2); /* round 10 */ KEYMIX(r1,r0,r4,r3,r2,36); S1(r1,r0,r4,r3,r2); LINTRANS(r3,r0,r4,r1,r2); /* round 11 */ KEYMIX(r3,r0,r4,r1,r2,40); S2(r3,r0,r4,r1,r2); LINTRANS(r4,r1,r0,r2,r3); /* round 12 */ KEYMIX(r4,r1,r0,r2,r3,44); S3(r4,r1,r0,r2,r3); LINTRANS(r1,r0,r2,r3,r4); /* round 13 */ KEYMIX(r1,r0,r2,r3,r4,48); S4(r1,r0,r2,r3,r4) LINTRANS(r0,r4,r1,r3,r2); /* round 14 */ KEYMIX(r0,r4,r1,r3,r2,52); S5(r0,r4,r1,r3,r2); LINTRANS(r4,r3,r0,r1,r2); /* round 15 */ KEYMIX(r4,r3,r0,r1,r2,56); S6(r4,r3,r0,r1,r2) LINTRANS(r4,r3,r2,r0,r1); /* round 16 */ KEYMIX(r4,r3,r2,r0,r1,60); S7(r4,r3,r2,r0,r1); LINTRANS(r2,r1,r0,r4,r3); /* round 17 */ KEYMIX(r2,r1,r0,r4,r3,64); S0(r2,r1,r0,r4,r3); LINTRANS(r1,r3,r0,r2,r4); /* round 18 */ KEYMIX(r1,r3,r0,r2,r4,68); S1(r1,r3,r0,r2,r4); LINTRANS(r2,r3,r0,r1,r4); /* round 19 */ KEYMIX(r2,r3,r0,r1,r4,72); S2(r2,r3,r0,r1,r4); LINTRANS(r0,r1,r3,r4,r2); /* round 20 */ KEYMIX(r0,r1,r3,r4,r2,76); S3(r0,r1,r3,r4,r2); LINTRANS(r1,r3,r4,r2,r0); /* round 21 */ KEYMIX(r1,r3,r4,r2,r0,80); S4(r1,r3,r4,r2,r0) LINTRANS(r3,r0,r1,r2,r4); /* round 22 */ KEYMIX(r3,r0,r1,r2,r4,84); S5(r3,r0,r1,r2,r4); LINTRANS(r0,r2,r3,r1,r4); /* round 23 */ KEYMIX(r0,r2,r3,r1,r4,88); S6(r0,r2,r3,r1,r4) LINTRANS(r0,r2,r4,r3,r1); /* round 24 */ KEYMIX(r0,r2,r4,r3,r1,92); S7(r0,r2,r4,r3,r1); LINTRANS(r4,r1,r3,r0,r2); /* round 25 */ KEYMIX(r4,r1,r3,r0,r2,96); S0(r4,r1,r3,r0,r2); LINTRANS(r1,r2,r3,r4,r0); /* round 26 */ KEYMIX(r1,r2,r3,r4,r0,100); S1(r1,r2,r3,r4,r0); LINTRANS(r4,r2,r3,r1,r0); /* round 27 */ KEYMIX(r4,r2,r3,r1,r0,104); S2(r4,r2,r3,r1,r0); LINTRANS(r3,r1,r2,r0,r4); /* round 28 */ KEYMIX(r3,r1,r2,r0,r4,108); S3(r3,r1,r2,r0,r4); LINTRANS(r1,r2,r0,r4,r3); /* round 29 */ KEYMIX(r1,r2,r0,r4,r3,112); S4(r1,r2,r0,r4,r3) LINTRANS(r2,r3,r1,r4,r0); /* round 30 */ KEYMIX(r2,r3,r1,r4,r0,116); S5(r2,r3,r1,r4,r0); LINTRANS(r3,r4,r2,r1,r0); /* round 31 */ KEYMIX(r3,r4,r2,r1,r0,120); S6(r3,r4,r2,r1,r0) LINTRANS(r3,r4,r0,r2,r1); /* round 32 */ KEYMIX(r3,r4,r0,r2,r1,124); S7(r3,r4,r0,r2,r1); KEYMIX(r0,r1,r2,r3,r4,128); #ifdef BLOCK_SWAP out_blk[3] = io_swap(r0); out_blk[2] = io_swap(r1); out_blk[1] = io_swap(r2); out_blk[0] = io_swap(r3); #else out_blk[0] = r0; out_blk[1] = r1; out_blk[2] = r2; out_blk[3] = r3; #endif return 0; }; /* decrypt a block of text */ int serpent_decrypt(serpent_context *cx, const u8 *in, u8 *out) { u32 *l_key = cx->keyinfo; const u32 *in_blk = (const u32 *)in; u32 *out_blk = (u32 *)out; u32 r0,r1,r2,r3,r4; #ifdef BLOCK_SWAP r0 = io_swap(in_blk[3]); r1 = io_swap(in_blk[2]); r2 = io_swap(in_blk[1]); r3 = io_swap(in_blk[0]); #else r0 = in_blk[0]; r1 = in_blk[1]; r2 = in_blk[2]; r3 = in_blk[3]; #endif /* round 1 */ KEYMIX(r0,r1,r2,r3,r4,128); I7(r0,r1,r2,r3,r4); KEYMIX(r3,r0,r1,r4,r2,124); /* round 2 */ ILINTRANS(r3,r0,r1,r4,r2); I6(r3,r0,r1,r4,r2); KEYMIX(r0,r1,r2,r4,r3,120); /* round 3 */ ILINTRANS(r0,r1,r2,r4,r3); I5(r0,r1,r2,r4,r3); KEYMIX(r1,r3,r4,r2,r0,116); /* round 4 */ ILINTRANS(r1,r3,r4,r2,r0); I4(r1,r3,r4,r2,r0); KEYMIX(r1,r2,r4,r0,r3,112); /* round 5 */ ILINTRANS(r1,r2,r4,r0,r3); I3(r1,r2,r4,r0,r3); KEYMIX(r4,r2,r0,r1,r3,108); /* round 6 */ ILINTRANS(r4,r2,r0,r1,r3); I2(r4,r2,r0,r1,r3); KEYMIX(r2,r3,r0,r1,r4,104); /* round 7 */ ILINTRANS(r2,r3,r0,r1,r4); I1(r2,r3,r0,r1,r4); KEYMIX(r4,r2,r1,r0,r3,100); /* round 8 */ ILINTRANS(r4,r2,r1,r0,r3); I0(r4,r2,r1,r0,r3); KEYMIX(r4,r3,r2,r0,r1,96); /* round 9 */ ILINTRANS(r4,r3,r2,r0,r1); I7(r4,r3,r2,r0,r1); KEYMIX(r0,r4,r3,r1,r2,92); /* round 10 */ ILINTRANS(r0,r4,r3,r1,r2); I6(r0,r4,r3,r1,r2); KEYMIX(r4,r3,r2,r1,r0,88); /* round 11 */ ILINTRANS(r4,r3,r2,r1,r0); I5(r4,r3,r2,r1,r0); KEYMIX(r3,r0,r1,r2,r4,84); /* round 12 */ ILINTRANS(r3,r0,r1,r2,r4); I4(r3,r0,r1,r2,r4); KEYMIX(r3,r2,r1,r4,r0,80); /* round 13 */ ILINTRANS(r3,r2,r1,r4,r0); I3(r3,r2,r1,r4,r0); KEYMIX(r1,r2,r4,r3,r0,76); /* round 14 */ ILINTRANS(r1,r2,r4,r3,r0); I2(r1,r2,r4,r3,r0); KEYMIX(r2,r0,r4,r3,r1,72); /* round 15 */ ILINTRANS(r2,r0,r4,r3,r1); I1(r2,r0,r4,r3,r1); KEYMIX(r1,r2,r3,r4,r0,68); /* round 16 */ ILINTRANS(r1,r2,r3,r4,r0); I0(r1,r2,r3,r4,r0); KEYMIX(r1,r0,r2,r4,r3,64); /* round 17 */ ILINTRANS(r1,r0,r2,r4,r3); I7(r1,r0,r2,r4,r3); KEYMIX(r4,r1,r0,r3,r2,60); /* round 18 */ ILINTRANS(r4,r1,r0,r3,r2); I6(r4,r1,r0,r3,r2); KEYMIX(r1,r0,r2,r3,r4,56); /* round 19 */ ILINTRANS(r1,r0,r2,r3,r4); I5(r1,r0,r2,r3,r4); KEYMIX(r0,r4,r3,r2,r1,52); /* round 20 */ ILINTRANS(r0,r4,r3,r2,r1); I4(r0,r4,r3,r2,r1); KEYMIX(r0,r2,r3,r1,r4,48); /* round 21 */ ILINTRANS(r0,r2,r3,r1,r4); I3(r0,r2,r3,r1,r4); KEYMIX(r3,r2,r1,r0,r4,44); /* round 22 */ ILINTRANS(r3,r2,r1,r0,r4); I2(r3,r2,r1,r0,r4); KEYMIX(r2,r4,r1,r0,r3,40); /* round 23 */ ILINTRANS(r2,r4,r1,r0,r3); I1(r2,r4,r1,r0,r3); KEYMIX(r3,r2,r0,r1,r4,36); /* round 24 */ ILINTRANS(r3,r2,r0,r1,r4); I0(r3,r2,r0,r1,r4); KEYMIX(r3,r4,r2,r1,r0,32); /* round 25 */ ILINTRANS(r3,r4,r2,r1,r0); I7(r3,r4,r2,r1,r0); KEYMIX(r1,r3,r4,r0,r2,28); /* round 26 */ ILINTRANS(r1,r3,r4,r0,r2); I6(r1,r3,r4,r0,r2); KEYMIX(r3,r4,r2,r0,r1,24); /* round 27 */ ILINTRANS(r3,r4,r2,r0,r1); I5(r3,r4,r2,r0,r1); KEYMIX(r4,r1,r0,r2,r3,20); /* round 28 */ ILINTRANS(r4,r1,r0,r2,r3); I4(r4,r1,r0,r2,r3); KEYMIX(r4,r2,r0,r3,r1,16); /* round 29 */ ILINTRANS(r4,r2,r0,r3,r1); I3(r4,r2,r0,r3,r1); KEYMIX(r0,r2,r3,r4,r1,12); /* round 30 */ ILINTRANS(r0,r2,r3,r4,r1); I2(r0,r2,r3,r4,r1); KEYMIX(r2,r1,r3,r4,r0,8); /* round 31 */ ILINTRANS(r2,r1,r3,r4,r0); I1(r2,r1,r3,r4,r0); KEYMIX(r0,r2,r4,r3,r1,4); /* round 32 */ ILINTRANS(r0,r2,r4,r3,r1); I0(r0,r2,r4,r3,r1); KEYMIX(r0,r1,r2,r3,r4,0); #ifdef BLOCK_SWAP out_blk[3] = io_swap(r0); out_blk[2] = io_swap(r1); out_blk[1] = io_swap(r2); out_blk[0] = io_swap(r3); #else out_blk[0] = r0; out_blk[1] = r1; out_blk[2] = r2; out_blk[3] = r3; #endif return 0; };