Botan  1.11.15
src/lib/hash/tiger/tiger.cpp
Go to the documentation of this file.
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 }