VerifyBufsEqual
| Documentation |
#include <cryptopp/misc.h>
|
VerifyBufsEqual is a constant time memory comparison function. The code is written in a way that makes it difficult for the optimizer to short-circuit if the buffers are not equal. The function serves the same purpose as OpenSSL's CRYPTO_memcmp.
Crypto++ classes like SignatureVerificationFilter and HashVerificationFilter indirectly use the function. For example, SignatureVerificationFilter will call Verify on the PK_Verifier, and the PK_Verifier will use VerifyBufsEqual.
VerifyBufsEqual requires two equally sized buffers to compare. You should ensure you have valid, non-null buffers to compare before calling this function. A related question is on the Information Security Stack Exchange at Constant time compares when array sizes are not equal?.
If your code is using the C++ runtime's memcmp or std::compare on non-public data, then it should probably be using VerifyBufsEqual.
Source Code
The source code for VerifyBufsEqual is shown below. The asserts are present in debug builds to alert the developer a buffer is not valid.
// VerifyBufsEqual simplified at https://github.com/weidai11/cryptopp/issues/1020
bool VerifyBufsEqual(const byte *buf, const byte *mask, size_t count)
{
CRYPTOPP_ASSERT(buf != NULLPTR);
CRYPTOPP_ASSERT(mask != NULLPTR);
// CRYPTOPP_ASSERT(count > 0);
#if CRYPTOPP_BOOL_64BIT
word64 acc64 = 0;
while (count >= 8)
{
word64 b, m;
memcpy(&b, buf, 8); memcpy(&m, mask, 8);
acc64 |= b ^ m;
buf += 8; mask += 8; count -= 8;
}
word32 acc8 = (acc64 >> 32) | (acc64 & 0xffffffff);
acc8 = static_cast<byte>(acc8) | static_cast<byte>(acc8 >> 8) |
static_cast<byte>(acc8 >> 16) | static_cast<byte>(acc8 >> 24);
#else
word32 acc32 = 0;
while (count >= 4)
{
word32 b, m;
memcpy(&b, buf, 4); memcpy(&m, mask, 4);
acc32 |= b ^ m;
buf += 4; mask += 4; count -= 4;
}
word32 acc8 = acc32;
acc8 = static_cast<byte>(acc8) | static_cast<byte>(acc8 >> 8) |
static_cast<byte>(acc8 >> 16) | static_cast<byte>(acc8 >> 24);
#endif
for (size_t i=0; i<count; i++)
acc8 |= buf[i] ^ mask[i];
return acc8 == 0;
}