diff --git a/crypto/hmac.cc b/crypto/hmac.cc index 588cb9e77bbf2..74d1f916ffd4e 100644 --- a/crypto/hmac.cc +++ b/crypto/hmac.cc @@ -4,6 +4,8 @@ #include "crypto/hmac.h" +#include <algorithm> + #include "base/logging.h" namespace crypto { @@ -43,12 +45,21 @@ bool HMAC::Verify(const base::StringPiece& data, const base::StringPiece& digest) const { if (digest.size() != DigestLength()) return false; + return VerifyTruncated(data, digest); +} + +bool HMAC::VerifyTruncated(const base::StringPiece& data, + const base::StringPiece& digest) const { + if (digest.empty()) + return false; + size_t digest_length = DigestLength(); scoped_array<unsigned char> computed_digest( - new unsigned char[digest.size()]); - if (!Sign(data, computed_digest.get(), static_cast<int>(digest.size()))) + new unsigned char[digest_length]); + if (!Sign(data, computed_digest.get(), static_cast<int>(digest_length))) return false; - return SecureMemcmp(digest.data(), computed_digest.get(), digest.size()); + return SecureMemcmp(digest.data(), computed_digest.get(), + std::min(digest.size(), digest_length)); } } // namespace crypto diff --git a/crypto/hmac.h b/crypto/hmac.h index a8956ff52b959..73d6dc3ddb215 100644 --- a/crypto/hmac.h +++ b/crypto/hmac.h @@ -59,11 +59,16 @@ class CRYPTO_API HMAC { // supplied to the Init method. Use of this method is strongly recommended // over using Sign() with a manual comparison (such as memcmp), as such // comparisons may result in side-channel disclosures, such as timing, that - // undermine the cryptographic integrity. This method does not support - // comparing truncated HMACs. + // undermine the cryptographic integrity. |digest| must be exactly + // |DigestLength()| bytes long. bool Verify(const base::StringPiece& data, const base::StringPiece& digest) const; + // Verifies a truncated HMAC, behaving identical to Verify(), except + // that |digest| is allowed to be smaller than |DigestLength()|. + bool VerifyTruncated(const base::StringPiece& data, + const base::StringPiece& digest) const; + private: HashAlgorithm hash_alg_; scoped_ptr<HMACPlatformData> plat_; diff --git a/crypto/hmac_unittest.cc b/crypto/hmac_unittest.cc index 1978705934daa..f5d99067ed7d3 100644 --- a/crypto/hmac_unittest.cc +++ b/crypto/hmac_unittest.cc @@ -221,6 +221,10 @@ TEST(HMACTest, NSSFIPSPowerUpSelfTest) { message_data, base::StringPiece(reinterpret_cast<const char*>(kKnownHMACSHA1), kSHA1DigestSize))); + EXPECT_TRUE(hmac.VerifyTruncated( + message_data, + base::StringPiece(reinterpret_cast<const char*>(kKnownHMACSHA1), + kSHA1DigestSize / 2))); crypto::HMAC hmac2(crypto::HMAC::SHA256); ASSERT_TRUE(hmac2.Init(kKnownSecretKey, kKnownSecretKeySize));