Botan
1.11.15
|
00001 /* 00002 * Serpent (SIMD) 00003 * (C) 2009,2013 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/block_utils.h> 00009 #include <botan/serp_simd.h> 00010 #include <botan/internal/serpent_sbox.h> 00011 #include <botan/internal/simd_32.h> 00012 00013 namespace Botan { 00014 00015 BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(SIMD_32::enabled(), Serpent_SIMD, "Serpent", "simd32", 64); 00016 00017 namespace { 00018 00019 #define key_xor(round, B0, B1, B2, B3) \ 00020 do { \ 00021 B0 ^= SIMD_32(keys[4*round ]); \ 00022 B1 ^= SIMD_32(keys[4*round+1]); \ 00023 B2 ^= SIMD_32(keys[4*round+2]); \ 00024 B3 ^= SIMD_32(keys[4*round+3]); \ 00025 } while(0); 00026 00027 /* 00028 * Serpent's linear transformations 00029 */ 00030 #define transform(B0, B1, B2, B3) \ 00031 do { \ 00032 B0.rotate_left(13); \ 00033 B2.rotate_left(3); \ 00034 B1 ^= B0 ^ B2; \ 00035 B3 ^= B2 ^ (B0 << 3); \ 00036 B1.rotate_left(1); \ 00037 B3.rotate_left(7); \ 00038 B0 ^= B1 ^ B3; \ 00039 B2 ^= B3 ^ (B1 << 7); \ 00040 B0.rotate_left(5); \ 00041 B2.rotate_left(22); \ 00042 } while(0); 00043 00044 #define i_transform(B0, B1, B2, B3) \ 00045 do { \ 00046 B2.rotate_right(22); \ 00047 B0.rotate_right(5); \ 00048 B2 ^= B3 ^ (B1 << 7); \ 00049 B0 ^= B1 ^ B3; \ 00050 B3.rotate_right(7); \ 00051 B1.rotate_right(1); \ 00052 B3 ^= B2 ^ (B0 << 3); \ 00053 B1 ^= B0 ^ B2; \ 00054 B2.rotate_right(3); \ 00055 B0.rotate_right(13); \ 00056 } while(0); 00057 00058 /* 00059 * SIMD Serpent Encryption of 4 blocks in parallel 00060 */ 00061 void serpent_encrypt_4(const byte in[64], 00062 byte out[64], 00063 const u32bit keys[132]) 00064 { 00065 SIMD_32 B0 = SIMD_32::load_le(in); 00066 SIMD_32 B1 = SIMD_32::load_le(in + 16); 00067 SIMD_32 B2 = SIMD_32::load_le(in + 32); 00068 SIMD_32 B3 = SIMD_32::load_le(in + 48); 00069 00070 SIMD_32::transpose(B0, B1, B2, B3); 00071 00072 key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00073 key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00074 key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00075 key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00076 key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00077 key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00078 key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00079 key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00080 00081 key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00082 key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00083 key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00084 key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00085 key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00086 key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00087 key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00088 key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00089 00090 key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00091 key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00092 key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00093 key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00094 key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00095 key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00096 key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00097 key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00098 00099 key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00100 key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00101 key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00102 key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00103 key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00104 key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00105 key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); 00106 key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3); 00107 00108 SIMD_32::transpose(B0, B1, B2, B3); 00109 00110 B0.store_le(out); 00111 B1.store_le(out + 16); 00112 B2.store_le(out + 32); 00113 B3.store_le(out + 48); 00114 } 00115 00116 /* 00117 * SIMD Serpent Decryption of 4 blocks in parallel 00118 */ 00119 void serpent_decrypt_4(const byte in[64], 00120 byte out[64], 00121 const u32bit keys[132]) 00122 { 00123 SIMD_32 B0 = SIMD_32::load_le(in); 00124 SIMD_32 B1 = SIMD_32::load_le(in + 16); 00125 SIMD_32 B2 = SIMD_32::load_le(in + 32); 00126 SIMD_32 B3 = SIMD_32::load_le(in + 48); 00127 00128 SIMD_32::transpose(B0, B1, B2, B3); 00129 00130 key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3); 00131 i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3); 00132 i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3); 00133 i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3); 00134 i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3); 00135 i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3); 00136 i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3); 00137 i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3); 00138 00139 i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3); 00140 i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3); 00141 i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3); 00142 i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3); 00143 i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3); 00144 i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3); 00145 i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3); 00146 i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3); 00147 00148 i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3); 00149 i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3); 00150 i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3); 00151 i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3); 00152 i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3); 00153 i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3); 00154 i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3); 00155 i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3); 00156 00157 i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3); 00158 i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3); 00159 i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3); 00160 i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3); 00161 i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3); 00162 i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3); 00163 i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3); 00164 i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3); 00165 00166 SIMD_32::transpose(B0, B1, B2, B3); 00167 00168 B0.store_le(out); 00169 B1.store_le(out + 16); 00170 B2.store_le(out + 32); 00171 B3.store_le(out + 48); 00172 } 00173 00174 } 00175 00176 #undef key_xor 00177 #undef transform 00178 #undef i_transform 00179 00180 /* 00181 * Serpent Encryption 00182 */ 00183 void Serpent_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const 00184 { 00185 const u32bit* KS = &(this->get_round_keys()[0]); 00186 00187 while(blocks >= 4) 00188 { 00189 serpent_encrypt_4(in, out, KS); 00190 in += 4 * BLOCK_SIZE; 00191 out += 4 * BLOCK_SIZE; 00192 blocks -= 4; 00193 } 00194 00195 if(blocks) 00196 Serpent::encrypt_n(in, out, blocks); 00197 } 00198 00199 /* 00200 * Serpent Decryption 00201 */ 00202 void Serpent_SIMD::decrypt_n(const byte in[], byte out[], size_t blocks) const 00203 { 00204 const u32bit* KS = &(this->get_round_keys()[0]); 00205 00206 while(blocks >= 4) 00207 { 00208 serpent_decrypt_4(in, out, KS); 00209 in += 4 * BLOCK_SIZE; 00210 out += 4 * BLOCK_SIZE; 00211 blocks -= 4; 00212 } 00213 00214 if(blocks) 00215 Serpent::decrypt_n(in, out, blocks); 00216 } 00217 00218 }