Botan
1.11.15
|
00001 /* 00002 * Threefish-512 00003 * (C) 2013,2014 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/threefish.h> 00010 00011 namespace Botan { 00012 00013 BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(Threefish_512, "Threefish-512"); 00014 00015 #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \ 00016 do { \ 00017 X0 += X4; \ 00018 X1 += X5; \ 00019 X2 += X6; \ 00020 X3 += X7; \ 00021 X4 = rotate_left(X4, ROT1); \ 00022 X5 = rotate_left(X5, ROT2); \ 00023 X6 = rotate_left(X6, ROT3); \ 00024 X7 = rotate_left(X7, ROT4); \ 00025 X4 ^= X0; \ 00026 X5 ^= X1; \ 00027 X6 ^= X2; \ 00028 X7 ^= X3; \ 00029 } while(0) 00030 00031 #define THREEFISH_INJECT_KEY(r) \ 00032 do { \ 00033 X0 += m_K[(r ) % 9]; \ 00034 X1 += m_K[(r+1) % 9]; \ 00035 X2 += m_K[(r+2) % 9]; \ 00036 X3 += m_K[(r+3) % 9]; \ 00037 X4 += m_K[(r+4) % 9]; \ 00038 X5 += m_K[(r+5) % 9] + m_T[(r ) % 3]; \ 00039 X6 += m_K[(r+6) % 9] + m_T[(r+1) % 3]; \ 00040 X7 += m_K[(r+7) % 9] + (r); \ 00041 } while(0) 00042 00043 #define THREEFISH_ENC_8_ROUNDS(R1,R2) \ 00044 do { \ 00045 THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \ 00046 THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \ 00047 THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \ 00048 THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \ 00049 THREEFISH_INJECT_KEY(R1); \ 00050 \ 00051 THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \ 00052 THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \ 00053 THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \ 00054 THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 8,35,56,22); \ 00055 THREEFISH_INJECT_KEY(R2); \ 00056 } while(0) 00057 00058 void Threefish_512::skein_feedfwd(const secure_vector<u64bit>& M, 00059 const secure_vector<u64bit>& T) 00060 { 00061 BOTAN_ASSERT(m_K.size() == 9, "Key was set"); 00062 BOTAN_ASSERT(M.size() == 8, "Single block"); 00063 00064 m_T[0] = T[0]; 00065 m_T[1] = T[1]; 00066 m_T[2] = T[0] ^ T[1]; 00067 00068 u64bit X0 = M[0]; 00069 u64bit X1 = M[1]; 00070 u64bit X2 = M[2]; 00071 u64bit X3 = M[3]; 00072 u64bit X4 = M[4]; 00073 u64bit X5 = M[5]; 00074 u64bit X6 = M[6]; 00075 u64bit X7 = M[7]; 00076 00077 THREEFISH_INJECT_KEY(0); 00078 00079 THREEFISH_ENC_8_ROUNDS(1,2); 00080 THREEFISH_ENC_8_ROUNDS(3,4); 00081 THREEFISH_ENC_8_ROUNDS(5,6); 00082 THREEFISH_ENC_8_ROUNDS(7,8); 00083 THREEFISH_ENC_8_ROUNDS(9,10); 00084 THREEFISH_ENC_8_ROUNDS(11,12); 00085 THREEFISH_ENC_8_ROUNDS(13,14); 00086 THREEFISH_ENC_8_ROUNDS(15,16); 00087 THREEFISH_ENC_8_ROUNDS(17,18); 00088 00089 m_K[0] = M[0] ^ X0; 00090 m_K[1] = M[1] ^ X1; 00091 m_K[2] = M[2] ^ X2; 00092 m_K[3] = M[3] ^ X3; 00093 m_K[4] = M[4] ^ X4; 00094 m_K[5] = M[5] ^ X5; 00095 m_K[6] = M[6] ^ X6; 00096 m_K[7] = M[7] ^ X7; 00097 00098 m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^ 00099 m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22; 00100 } 00101 00102 void Threefish_512::encrypt_n(const byte in[], byte out[], size_t blocks) const 00103 { 00104 BOTAN_ASSERT(m_K.size() == 9, "Key was set"); 00105 BOTAN_ASSERT(m_T.size() == 3, "Tweak was set"); 00106 00107 for(size_t i = 0; i != blocks; ++i) 00108 { 00109 u64bit X0 = load_le<u64bit>(in, 0); 00110 u64bit X1 = load_le<u64bit>(in, 1); 00111 u64bit X2 = load_le<u64bit>(in, 2); 00112 u64bit X3 = load_le<u64bit>(in, 3); 00113 u64bit X4 = load_le<u64bit>(in, 4); 00114 u64bit X5 = load_le<u64bit>(in, 5); 00115 u64bit X6 = load_le<u64bit>(in, 6); 00116 u64bit X7 = load_le<u64bit>(in, 7); 00117 00118 THREEFISH_INJECT_KEY(0); 00119 00120 THREEFISH_ENC_8_ROUNDS(1,2); 00121 THREEFISH_ENC_8_ROUNDS(3,4); 00122 THREEFISH_ENC_8_ROUNDS(5,6); 00123 THREEFISH_ENC_8_ROUNDS(7,8); 00124 THREEFISH_ENC_8_ROUNDS(9,10); 00125 THREEFISH_ENC_8_ROUNDS(11,12); 00126 THREEFISH_ENC_8_ROUNDS(13,14); 00127 THREEFISH_ENC_8_ROUNDS(15,16); 00128 THREEFISH_ENC_8_ROUNDS(17,18); 00129 00130 store_le(out, X0, X1, X2, X3, X4, X5, X6, X7); 00131 00132 in += 64; 00133 out += 64; 00134 } 00135 } 00136 00137 #undef THREEFISH_ENC_8_ROUNDS 00138 #undef THREEFISH_INJECT_KEY 00139 #undef THREEFISH_ROUND 00140 00141 void Threefish_512::decrypt_n(const byte in[], byte out[], size_t blocks) const 00142 { 00143 BOTAN_ASSERT(m_K.size() == 9, "Key was set"); 00144 BOTAN_ASSERT(m_T.size() == 3, "Tweak was set"); 00145 00146 #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \ 00147 do { \ 00148 X4 ^= X0; \ 00149 X5 ^= X1; \ 00150 X6 ^= X2; \ 00151 X7 ^= X3; \ 00152 X4 = rotate_right(X4, ROT1); \ 00153 X5 = rotate_right(X5, ROT2); \ 00154 X6 = rotate_right(X6, ROT3); \ 00155 X7 = rotate_right(X7, ROT4); \ 00156 X0 -= X4; \ 00157 X1 -= X5; \ 00158 X2 -= X6; \ 00159 X3 -= X7; \ 00160 } while(0) 00161 00162 #define THREEFISH_INJECT_KEY(r) \ 00163 do { \ 00164 X0 -= m_K[(r ) % 9]; \ 00165 X1 -= m_K[(r+1) % 9]; \ 00166 X2 -= m_K[(r+2) % 9]; \ 00167 X3 -= m_K[(r+3) % 9]; \ 00168 X4 -= m_K[(r+4) % 9]; \ 00169 X5 -= m_K[(r+5) % 9] + m_T[(r ) % 3]; \ 00170 X6 -= m_K[(r+6) % 9] + m_T[(r+1) % 3]; \ 00171 X7 -= m_K[(r+7) % 9] + (r); \ 00172 } while(0) 00173 00174 #define THREEFISH_DEC_8_ROUNDS(R1,R2) \ 00175 do { \ 00176 THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 8,35,56,22); \ 00177 THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \ 00178 THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \ 00179 THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \ 00180 THREEFISH_INJECT_KEY(R1); \ 00181 \ 00182 THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \ 00183 THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \ 00184 THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \ 00185 THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \ 00186 THREEFISH_INJECT_KEY(R2); \ 00187 } while(0) 00188 00189 for(size_t i = 0; i != blocks; ++i) 00190 { 00191 u64bit X0 = load_le<u64bit>(in, 0); 00192 u64bit X1 = load_le<u64bit>(in, 1); 00193 u64bit X2 = load_le<u64bit>(in, 2); 00194 u64bit X3 = load_le<u64bit>(in, 3); 00195 u64bit X4 = load_le<u64bit>(in, 4); 00196 u64bit X5 = load_le<u64bit>(in, 5); 00197 u64bit X6 = load_le<u64bit>(in, 6); 00198 u64bit X7 = load_le<u64bit>(in, 7); 00199 00200 THREEFISH_INJECT_KEY(18); 00201 00202 THREEFISH_DEC_8_ROUNDS(17,16); 00203 THREEFISH_DEC_8_ROUNDS(15,14); 00204 THREEFISH_DEC_8_ROUNDS(13,12); 00205 THREEFISH_DEC_8_ROUNDS(11,10); 00206 THREEFISH_DEC_8_ROUNDS(9,8); 00207 THREEFISH_DEC_8_ROUNDS(7,6); 00208 THREEFISH_DEC_8_ROUNDS(5,4); 00209 THREEFISH_DEC_8_ROUNDS(3,2); 00210 THREEFISH_DEC_8_ROUNDS(1,0); 00211 00212 store_le(out, X0, X1, X2, X3, X4, X5, X6, X7); 00213 00214 in += 64; 00215 out += 64; 00216 } 00217 00218 #undef THREEFISH_DEC_8_ROUNDS 00219 #undef THREEFISH_INJECT_KEY 00220 #undef THREEFISH_ROUND 00221 } 00222 00223 void Threefish_512::set_tweak(const byte tweak[], size_t len) 00224 { 00225 if(len != 16) 00226 throw std::runtime_error("Unsupported twofish tweak length"); 00227 m_T.resize(3); 00228 m_T[0] = load_le<u64bit>(tweak, 0); 00229 m_T[1] = load_le<u64bit>(tweak, 1); 00230 m_T[2] = m_T[0] ^ m_T[1]; 00231 } 00232 00233 void Threefish_512::key_schedule(const byte key[], size_t) 00234 { 00235 // todo: define key schedule for smaller keys 00236 m_K.resize(9); 00237 00238 for(size_t i = 0; i != 8; ++i) 00239 m_K[i] = load_le<u64bit>(key, i); 00240 00241 m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^ 00242 m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22; 00243 00244 // Reset tweak to all zeros on key reset 00245 m_T.resize(3); 00246 zeroise(m_T); 00247 } 00248 00249 void Threefish_512::clear() 00250 { 00251 zeroise(m_K); 00252 zeroise(m_T); 00253 } 00254 00255 }