Warning, file /include/cryptopp/siphash.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #ifndef CRYPTOPP_SIPHASH_H
0027 #define CRYPTOPP_SIPHASH_H
0028
0029 #include "cryptlib.h"
0030 #include "secblock.h"
0031 #include "seckey.h"
0032 #include "misc.h"
0033
0034 NAMESPACE_BEGIN(CryptoPP)
0035
0036
0037
0038 template <bool T_128bit>
0039 class SipHash_Info : public FixedKeyLength<16>
0040 {
0041 public:
0042 CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "SipHash";}
0043 CRYPTOPP_CONSTANT(DIGESTSIZE = (T_128bit ? 16 : 8));
0044 };
0045
0046
0047
0048
0049
0050 template <unsigned int C, unsigned int D, bool T_128bit>
0051 class SipHash_Base : public MessageAuthenticationCode, public SipHash_Info<T_128bit>
0052 {
0053 public:
0054 static std::string StaticAlgorithmName() {
0055 return std::string(SipHash_Info<T_128bit>::StaticAlgorithmName())+"-"+IntToString(C)+"-"+IntToString(D);
0056 }
0057
0058 virtual ~SipHash_Base() {}
0059
0060 SipHash_Base() : m_idx(0) {}
0061
0062 virtual unsigned int DigestSize() const
0063 {return SipHash_Info<T_128bit>::DIGESTSIZE;}
0064 virtual size_t MinKeyLength() const
0065 {return SipHash_Info<T_128bit>::MIN_KEYLENGTH;}
0066 virtual size_t MaxKeyLength() const
0067 {return SipHash_Info<T_128bit>::MAX_KEYLENGTH;}
0068 virtual size_t DefaultKeyLength() const
0069 {return SipHash_Info<T_128bit>::DEFAULT_KEYLENGTH;}
0070 virtual size_t GetValidKeyLength(size_t keylength) const
0071 {CRYPTOPP_UNUSED(keylength); return SipHash_Info<T_128bit>::DEFAULT_KEYLENGTH;}
0072 virtual IV_Requirement IVRequirement() const
0073 {return SimpleKeyingInterface::NOT_RESYNCHRONIZABLE;}
0074 virtual unsigned int IVSize() const
0075 {return 0;}
0076 virtual unsigned int OptimalBlockSize() const
0077 {return sizeof(word64);}
0078 virtual unsigned int OptimalDataAlignment () const
0079 {return GetAlignmentOf<word64>();}
0080
0081 virtual void Update(const byte *input, size_t length);
0082 virtual void TruncatedFinal(byte *digest, size_t digestSize);
0083
0084 protected:
0085
0086 virtual void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms);
0087 virtual void Restart();
0088
0089 inline void SIPROUND()
0090 {
0091 m_v[0] += m_v[1];
0092 m_v[1] = rotlConstant<13>(m_v[1]);
0093 m_v[1] ^= m_v[0];
0094 m_v[0] = rotlConstant<32>(m_v[0]);
0095 m_v[2] += m_v[3];
0096 m_v[3] = rotlConstant<16>(m_v[3]);
0097 m_v[3] ^= m_v[2];
0098 m_v[0] += m_v[3];
0099 m_v[3] = rotlConstant<21>(m_v[3]);
0100 m_v[3] ^= m_v[0];
0101 m_v[2] += m_v[1];
0102 m_v[1] = rotlConstant<17>(m_v[1]);
0103 m_v[1] ^= m_v[2];
0104 m_v[2] = rotlConstant<32>(m_v[2]);
0105 }
0106
0107 private:
0108 FixedSizeSecBlock<word64, 4> m_v;
0109 FixedSizeSecBlock<word64, 2> m_k;
0110 FixedSizeSecBlock<word64, 2> m_b;
0111
0112
0113 FixedSizeSecBlock<byte, 8> m_acc;
0114 size_t m_idx;
0115 };
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 template <unsigned int C=2, unsigned int D=4, bool T_128bit=false>
0142 class SipHash : public SipHash_Base<C, D, T_128bit>
0143 {
0144 public:
0145
0146 SipHash()
0147 {this->UncheckedSetKey(NULLPTR, 0, g_nullNameValuePairs);}
0148
0149
0150
0151 SipHash(const byte *key, unsigned int length)
0152 {this->ThrowIfInvalidKeyLength(length);
0153 this->UncheckedSetKey(key, length, g_nullNameValuePairs);}
0154 };
0155
0156 template <unsigned int C, unsigned int D, bool T_128bit>
0157 void SipHash_Base<C,D,T_128bit>::Update(const byte *input, size_t length)
0158 {
0159 CRYPTOPP_ASSERT((input && length) || !length);
0160 if (!length) return;
0161
0162 if (m_idx)
0163 {
0164 size_t head = STDMIN(size_t(8U-m_idx), length);
0165 std::memcpy(m_acc+m_idx, input, head);
0166 m_idx += head; input += head; length -= head;
0167
0168 if (m_idx == 8)
0169 {
0170 word64 m = GetWord<word64>(true, LITTLE_ENDIAN_ORDER, m_acc);
0171 m_v[3] ^= m;
0172 for (unsigned int i = 0; i < C; ++i)
0173 SIPROUND();
0174
0175 m_v[0] ^= m;
0176 m_b[0] += 8;
0177
0178 m_idx = 0;
0179 }
0180 }
0181
0182 while (length >= 8)
0183 {
0184 word64 m = GetWord<word64>(false, LITTLE_ENDIAN_ORDER, input);
0185 m_v[3] ^= m;
0186 for (unsigned int i = 0; i < C; ++i)
0187 SIPROUND();
0188
0189 m_v[0] ^= m;
0190 m_b[0] += 8;
0191
0192 input += 8;
0193 length -= 8;
0194 }
0195
0196 CRYPTOPP_ASSERT(length < 8);
0197 size_t tail = length % 8;
0198 if (tail)
0199 {
0200 std::memcpy(m_acc+m_idx, input, tail);
0201 m_idx += tail;
0202 }
0203 }
0204
0205 template <unsigned int C, unsigned int D, bool T_128bit>
0206 void SipHash_Base<C,D,T_128bit>::TruncatedFinal(byte *digest, size_t digestSize)
0207 {
0208 CRYPTOPP_ASSERT(digest);
0209
0210 ThrowIfInvalidTruncatedSize(digestSize);
0211
0212
0213 m_b[0] += m_idx; m_b[0] <<= 56U;
0214 switch (m_idx)
0215 {
0216 case 7:
0217 m_b[0] |= ((word64)m_acc[6]) << 48;
0218
0219 case 6:
0220 m_b[0] |= ((word64)m_acc[5]) << 40;
0221
0222 case 5:
0223 m_b[0] |= ((word64)m_acc[4]) << 32;
0224
0225 case 4:
0226 m_b[0] |= ((word64)m_acc[3]) << 24;
0227
0228 case 3:
0229 m_b[0] |= ((word64)m_acc[2]) << 16;
0230
0231 case 2:
0232 m_b[0] |= ((word64)m_acc[1]) << 8;
0233
0234 case 1:
0235 m_b[0] |= ((word64)m_acc[0]);
0236
0237 case 0:
0238 break;
0239 }
0240
0241 m_v[3] ^= m_b[0];
0242
0243 for (unsigned int i=0; i<C; i++)
0244 SIPROUND();
0245
0246 m_v[0] ^= m_b[0];
0247
0248 if (T_128bit)
0249 m_v[2] ^= 0xee;
0250 else
0251 m_v[2] ^= 0xff;
0252
0253 for (unsigned int i=0; i<D; i++)
0254 SIPROUND();
0255
0256 m_b[0] = m_v[0] ^ m_v[1] ^ m_v[2] ^ m_v[3];
0257 m_b[0] = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, m_b[0]);
0258
0259 if (T_128bit)
0260 {
0261 m_v[1] ^= 0xdd;
0262 for (unsigned int i = 0; i<D; ++i)
0263 SIPROUND();
0264
0265 m_b[1] = m_v[0] ^ m_v[1] ^ m_v[2] ^ m_v[3];
0266 m_b[1] = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, m_b[1]);
0267 }
0268
0269 memcpy_s(digest, digestSize, m_b.begin(), STDMIN(digestSize, (size_t)SipHash_Info<T_128bit>::DIGESTSIZE));
0270 Restart();
0271 }
0272
0273 template <unsigned int C, unsigned int D, bool T_128bit>
0274 void SipHash_Base<C,D,T_128bit>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
0275 {
0276 CRYPTOPP_UNUSED(params);
0277 if (key && length)
0278 {
0279 m_k[0] = GetWord<word64>(false, LITTLE_ENDIAN_ORDER, key);
0280 m_k[1] = GetWord<word64>(false, LITTLE_ENDIAN_ORDER, key+8);
0281 }
0282 else
0283 {
0284
0285 m_k[0] = m_k[1] = 0;
0286 }
0287 Restart();
0288 }
0289
0290 template <unsigned int C, unsigned int D, bool T_128bit>
0291 void SipHash_Base<C,D,T_128bit>::Restart ()
0292 {
0293 m_v[0] = W64LIT(0x736f6d6570736575);
0294 m_v[1] = W64LIT(0x646f72616e646f6d);
0295 m_v[2] = W64LIT(0x6c7967656e657261);
0296 m_v[3] = W64LIT(0x7465646279746573);
0297
0298 m_v[3] ^= m_k[1];
0299 m_v[2] ^= m_k[0];
0300 m_v[1] ^= m_k[1];
0301 m_v[0] ^= m_k[0];
0302
0303 if (T_128bit)
0304 {
0305 m_v[1] ^= 0xee;
0306 }
0307
0308 m_idx = 0;
0309 m_b[0] = 0;
0310 }
0311
0312 NAMESPACE_END
0313
0314 #endif