Botan
1.11.15
|
00001 /* 00002 * SipHash 00003 * (C) 2014,2015 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/mac_utils.h> 00009 #include <botan/siphash.h> 00010 00011 namespace Botan { 00012 00013 BOTAN_REGISTER_NAMED_T_2LEN(MessageAuthenticationCode, SipHash, "SipHash", "builtin", 2, 4); 00014 00015 namespace { 00016 00017 void SipRounds(u64bit M, secure_vector<u64bit>& V, size_t r) 00018 { 00019 u64bit V0 = V[0], V1 = V[1], V2 = V[2], V3 = V[3]; 00020 00021 V3 ^= M; 00022 for(size_t i = 0; i != r; ++i) 00023 { 00024 V0 += V1; V2 += V3; 00025 V1 = rotate_left(V1, 13); 00026 V3 = rotate_left(V3, 16); 00027 V1 ^= V0; V3 ^= V2; 00028 V0 = rotate_left(V0, 32); 00029 00030 V2 += V1; V0 += V3; 00031 V1 = rotate_left(V1, 17); 00032 V3 = rotate_left(V3, 21); 00033 V1 ^= V2; V3 ^= V0; 00034 V2 = rotate_left(V2, 32); 00035 } 00036 V0 ^= M; 00037 00038 V[0] = V0; V[1] = V1; V[2] = V2; V[3] = V3; 00039 } 00040 00041 } 00042 00043 void SipHash::add_data(const byte input[], size_t length) 00044 { 00045 m_words += length; 00046 00047 if(m_mbuf_pos) 00048 { 00049 while(length && m_mbuf_pos != 8) 00050 { 00051 m_mbuf = (m_mbuf >> 8) | (static_cast<u64bit>(input[0]) << 56); 00052 ++m_mbuf_pos; 00053 ++input; 00054 length--; 00055 } 00056 00057 if(m_mbuf_pos == 8) 00058 { 00059 SipRounds(m_mbuf, m_V, m_C); 00060 m_mbuf_pos = 0; 00061 m_mbuf = 0; 00062 } 00063 } 00064 00065 while(length >= 8) 00066 { 00067 SipRounds(load_le<u64bit>(input, 0), m_V, m_C); 00068 input += 8; 00069 length -= 8; 00070 } 00071 00072 for(size_t i = 0; i != length; ++i) 00073 { 00074 m_mbuf = (m_mbuf >> 8) | (static_cast<u64bit>(input[i]) << 56); 00075 m_mbuf_pos++; 00076 } 00077 } 00078 00079 void SipHash::final_result(byte mac[]) 00080 { 00081 m_mbuf = (m_mbuf >> (64-m_mbuf_pos*8)) | (static_cast<u64bit>(m_words) << 56); 00082 SipRounds(m_mbuf, m_V, m_C); 00083 00084 m_V[2] ^= 0xFF; 00085 SipRounds(0, m_V, m_D); 00086 00087 const u64bit X = m_V[0] ^ m_V[1] ^ m_V[2] ^ m_V[3]; 00088 00089 store_le(X, mac); 00090 00091 m_mbuf = 0; 00092 m_mbuf_pos = 0; 00093 m_words = 0; 00094 } 00095 00096 void SipHash::key_schedule(const byte key[], size_t) 00097 { 00098 const u64bit K0 = load_le<u64bit>(key, 0); 00099 const u64bit K1 = load_le<u64bit>(key, 1); 00100 00101 m_V.resize(4); 00102 m_V[0] = K0 ^ 0x736F6D6570736575; 00103 m_V[1] = K1 ^ 0x646F72616E646F6D; 00104 m_V[2] = K0 ^ 0x6C7967656E657261; 00105 m_V[3] = K1 ^ 0x7465646279746573; 00106 } 00107 00108 void SipHash::clear() 00109 { 00110 m_V.clear(); 00111 } 00112 00113 std::string SipHash::name() const 00114 { 00115 return "SipHash(" + std::to_string(m_C) + "," + std::to_string(m_D) + ")"; 00116 } 00117 00118 MessageAuthenticationCode* SipHash::clone() const 00119 { 00120 return new SipHash(m_C, m_D); 00121 } 00122 00123 }