Botan
1.11.15
|
00001 /* 00002 * Tiger 00003 * (C) 1999-2007 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/hash_utils.h> 00009 #include <botan/tiger.h> 00010 #include <botan/exceptn.h> 00011 #include <botan/parsing.h> 00012 00013 namespace Botan { 00014 00015 BOTAN_REGISTER_NAMED_T_2LEN(HashFunction, Tiger, "Tiger", "builtin", 24, 3); 00016 00017 namespace { 00018 00019 /* 00020 * Tiger Mixing Function 00021 */ 00022 inline void mix(secure_vector<u64bit>& X) 00023 { 00024 X[0] -= X[7] ^ 0xA5A5A5A5A5A5A5A5; 00025 X[1] ^= X[0]; 00026 X[2] += X[1]; 00027 X[3] -= X[2] ^ ((~X[1]) << 19); 00028 X[4] ^= X[3]; 00029 X[5] += X[4]; 00030 X[6] -= X[5] ^ ((~X[4]) >> 23); 00031 X[7] ^= X[6]; 00032 00033 X[0] += X[7]; 00034 X[1] -= X[0] ^ ((~X[7]) << 19); 00035 X[2] ^= X[1]; 00036 X[3] += X[2]; 00037 X[4] -= X[3] ^ ((~X[2]) >> 23); 00038 X[5] ^= X[4]; 00039 X[6] += X[5]; 00040 X[7] -= X[6] ^ 0x0123456789ABCDEF; 00041 } 00042 00043 } 00044 00045 /* 00046 * Tiger Compression Function 00047 */ 00048 void Tiger::compress_n(const byte input[], size_t blocks) 00049 { 00050 u64bit A = digest[0], B = digest[1], C = digest[2]; 00051 00052 for(size_t i = 0; i != blocks; ++i) 00053 { 00054 load_le(&X[0], input, X.size()); 00055 00056 pass(A, B, C, X, 5); mix(X); 00057 pass(C, A, B, X, 7); mix(X); 00058 pass(B, C, A, X, 9); 00059 00060 for(size_t j = 3; j != passes; ++j) 00061 { 00062 mix(X); 00063 pass(A, B, C, X, 9); 00064 u64bit T = A; A = C; C = B; B = T; 00065 } 00066 00067 A = (digest[0] ^= A); 00068 B = digest[1] = B - digest[1]; 00069 C = (digest[2] += C); 00070 00071 input += hash_block_size(); 00072 } 00073 } 00074 00075 /* 00076 * Copy out the digest 00077 */ 00078 void Tiger::copy_out(byte output[]) 00079 { 00080 copy_out_vec_le(output, output_length(), digest); 00081 } 00082 00083 /* 00084 * Tiger Pass 00085 */ 00086 void Tiger::pass(u64bit& A, u64bit& B, u64bit& C, 00087 const secure_vector<u64bit>& X, 00088 byte mul) 00089 { 00090 C ^= X[0]; 00091 A -= SBOX1[get_byte(7, C)] ^ SBOX2[get_byte(5, C)] ^ 00092 SBOX3[get_byte(3, C)] ^ SBOX4[get_byte(1, C)]; 00093 B += SBOX1[get_byte(0, C)] ^ SBOX2[get_byte(2, C)] ^ 00094 SBOX3[get_byte(4, C)] ^ SBOX4[get_byte(6, C)]; 00095 B *= mul; 00096 00097 A ^= X[1]; 00098 B -= SBOX1[get_byte(7, A)] ^ SBOX2[get_byte(5, A)] ^ 00099 SBOX3[get_byte(3, A)] ^ SBOX4[get_byte(1, A)]; 00100 C += SBOX1[get_byte(0, A)] ^ SBOX2[get_byte(2, A)] ^ 00101 SBOX3[get_byte(4, A)] ^ SBOX4[get_byte(6, A)]; 00102 C *= mul; 00103 00104 B ^= X[2]; 00105 C -= SBOX1[get_byte(7, B)] ^ SBOX2[get_byte(5, B)] ^ 00106 SBOX3[get_byte(3, B)] ^ SBOX4[get_byte(1, B)]; 00107 A += SBOX1[get_byte(0, B)] ^ SBOX2[get_byte(2, B)] ^ 00108 SBOX3[get_byte(4, B)] ^ SBOX4[get_byte(6, B)]; 00109 A *= mul; 00110 00111 C ^= X[3]; 00112 A -= SBOX1[get_byte(7, C)] ^ SBOX2[get_byte(5, C)] ^ 00113 SBOX3[get_byte(3, C)] ^ SBOX4[get_byte(1, C)]; 00114 B += SBOX1[get_byte(0, C)] ^ SBOX2[get_byte(2, C)] ^ 00115 SBOX3[get_byte(4, C)] ^ SBOX4[get_byte(6, C)]; 00116 B *= mul; 00117 00118 A ^= X[4]; 00119 B -= SBOX1[get_byte(7, A)] ^ SBOX2[get_byte(5, A)] ^ 00120 SBOX3[get_byte(3, A)] ^ SBOX4[get_byte(1, A)]; 00121 C += SBOX1[get_byte(0, A)] ^ SBOX2[get_byte(2, A)] ^ 00122 SBOX3[get_byte(4, A)] ^ SBOX4[get_byte(6, A)]; 00123 C *= mul; 00124 00125 B ^= X[5]; 00126 C -= SBOX1[get_byte(7, B)] ^ SBOX2[get_byte(5, B)] ^ 00127 SBOX3[get_byte(3, B)] ^ SBOX4[get_byte(1, B)]; 00128 A += SBOX1[get_byte(0, B)] ^ SBOX2[get_byte(2, B)] ^ 00129 SBOX3[get_byte(4, B)] ^ SBOX4[get_byte(6, B)]; 00130 A *= mul; 00131 00132 C ^= X[6]; 00133 A -= SBOX1[get_byte(7, C)] ^ SBOX2[get_byte(5, C)] ^ 00134 SBOX3[get_byte(3, C)] ^ SBOX4[get_byte(1, C)]; 00135 B += SBOX1[get_byte(0, C)] ^ SBOX2[get_byte(2, C)] ^ 00136 SBOX3[get_byte(4, C)] ^ SBOX4[get_byte(6, C)]; 00137 B *= mul; 00138 00139 A ^= X[7]; 00140 B -= SBOX1[get_byte(7, A)] ^ SBOX2[get_byte(5, A)] ^ 00141 SBOX3[get_byte(3, A)] ^ SBOX4[get_byte(1, A)]; 00142 C += SBOX1[get_byte(0, A)] ^ SBOX2[get_byte(2, A)] ^ 00143 SBOX3[get_byte(4, A)] ^ SBOX4[get_byte(6, A)]; 00144 C *= mul; 00145 } 00146 00147 /* 00148 * Clear memory of sensitive data 00149 */ 00150 void Tiger::clear() 00151 { 00152 MDx_HashFunction::clear(); 00153 zeroise(X); 00154 digest[0] = 0x0123456789ABCDEF; 00155 digest[1] = 0xFEDCBA9876543210; 00156 digest[2] = 0xF096A5B4C3B2E187; 00157 } 00158 00159 /* 00160 * Return the name of this type 00161 */ 00162 std::string Tiger::name() const 00163 { 00164 return "Tiger(" + std::to_string(output_length()) + "," + 00165 std::to_string(passes) + ")"; 00166 } 00167 00168 /* 00169 * Tiger Constructor 00170 */ 00171 Tiger::Tiger(size_t hash_len, size_t passes) : 00172 MDx_HashFunction(64, false, false), 00173 X(8), 00174 digest(3), 00175 hash_len(hash_len), 00176 passes(passes) 00177 { 00178 if(output_length() != 16 && output_length() != 20 && output_length() != 24) 00179 throw Invalid_Argument("Tiger: Illegal hash output size: " + 00180 std::to_string(output_length())); 00181 00182 if(passes < 3) 00183 throw Invalid_Argument("Tiger: Invalid number of passes: " 00184 + std::to_string(passes)); 00185 clear(); 00186 } 00187 00188 }