VerifyBufsEqual

From Crypto++ Wiki
Jump to navigation Jump to search
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;
}