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