diff --git a/drbg.h b/drbg.h index b219b861..e7262138 100644 --- a/drbg.h +++ b/drbg.h @@ -518,12 +518,33 @@ void Hash_DRBG::Hash_Generate(const byte* additional word128 r = static_cast(w1) + w2 + w3 + w4; PutWord(false, BIG_ENDIAN_ORDER, p1, static_cast(r)); i -= 8; j -= 8; k=0; carry = static_cast(r >> 64); + + // The default implementation and a couple of others cause a crash in + // VS2005, VS2008 and VS2105. This seems to work with all MS compilers. +#elif defined(CRYPTOPP_MSC_VERSION) + byte* p1 = m_v.begin()+SEEDLENGTH-8; + byte* p2 = m_c.begin()+SEEDLENGTH-8; + byte* p3 = h.begin()+HASH::DIGESTSIZE-8; + + const word64 w1 = GetWord(false, BIG_ENDIAN_ORDER, p1); + const word64 w2 = GetWord(false, BIG_ENDIAN_ORDER, p2); + const word64 w3 = GetWord(false, BIG_ENDIAN_ORDER, p3); + const word64 w4 = m_reseed; + + const word64 r1 = (w1 & 0xffffffff) + (w2 & 0xffffffff) + (w3 & 0xffffffff) + (w4 & 0xffffffff); + carry = static_cast(r1 >> 32); + const word64 r2 = (w1 >> 32) + (w2 >> 32) + (w3 >> 32) + (w4 >> 32) + carry; + carry = static_cast(r2 >> 32); + + const word64 r = (r2 << 32) + (r1 & 0xffffffff); + PutWord(false, BIG_ENDIAN_ORDER, p1, r); + i -= 8; j -= 8; k=0; + + // Default implementation, but slower on some machines. #else - byte t[8]; - PutWord(false, BIG_ENDIAN_ORDER, t, m_reseed); while (k>=0) { - carry = m_v[i] + m_c[i] + h[j] + t[k] + carry; + carry = m_v[i] + m_c[i] + h[j] + GetByte(BIG_ENDIAN_ORDER, m_reseed, k) + carry; m_v[i] = static_cast(carry); i--; j--; k--; carry >>= 8; }