Add a routine for truncated HMAC verification
BUG=none TEST=crypto_unittests --gtest_filter=HMACTest.* Review URL: http://codereview.chromium.org/7532020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94794 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "crypto/hmac.h"
|
#include "crypto/hmac.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
|
|
||||||
namespace crypto {
|
namespace crypto {
|
||||||
@ -43,12 +45,21 @@ bool HMAC::Verify(const base::StringPiece& data,
|
|||||||
const base::StringPiece& digest) const {
|
const base::StringPiece& digest) const {
|
||||||
if (digest.size() != DigestLength())
|
if (digest.size() != DigestLength())
|
||||||
return false;
|
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(
|
scoped_array<unsigned char> computed_digest(
|
||||||
new unsigned char[digest.size()]);
|
new unsigned char[digest_length]);
|
||||||
if (!Sign(data, computed_digest.get(), static_cast<int>(digest.size())))
|
if (!Sign(data, computed_digest.get(), static_cast<int>(digest_length)))
|
||||||
return false;
|
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
|
} // namespace crypto
|
||||||
|
@ -59,11 +59,16 @@ class CRYPTO_API HMAC {
|
|||||||
// supplied to the Init method. Use of this method is strongly recommended
|
// supplied to the Init method. Use of this method is strongly recommended
|
||||||
// over using Sign() with a manual comparison (such as memcmp), as such
|
// over using Sign() with a manual comparison (such as memcmp), as such
|
||||||
// comparisons may result in side-channel disclosures, such as timing, that
|
// comparisons may result in side-channel disclosures, such as timing, that
|
||||||
// undermine the cryptographic integrity. This method does not support
|
// undermine the cryptographic integrity. |digest| must be exactly
|
||||||
// comparing truncated HMACs.
|
// |DigestLength()| bytes long.
|
||||||
bool Verify(const base::StringPiece& data,
|
bool Verify(const base::StringPiece& data,
|
||||||
const base::StringPiece& digest) const;
|
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:
|
private:
|
||||||
HashAlgorithm hash_alg_;
|
HashAlgorithm hash_alg_;
|
||||||
scoped_ptr<HMACPlatformData> plat_;
|
scoped_ptr<HMACPlatformData> plat_;
|
||||||
|
@ -221,6 +221,10 @@ TEST(HMACTest, NSSFIPSPowerUpSelfTest) {
|
|||||||
message_data,
|
message_data,
|
||||||
base::StringPiece(reinterpret_cast<const char*>(kKnownHMACSHA1),
|
base::StringPiece(reinterpret_cast<const char*>(kKnownHMACSHA1),
|
||||||
kSHA1DigestSize)));
|
kSHA1DigestSize)));
|
||||||
|
EXPECT_TRUE(hmac.VerifyTruncated(
|
||||||
|
message_data,
|
||||||
|
base::StringPiece(reinterpret_cast<const char*>(kKnownHMACSHA1),
|
||||||
|
kSHA1DigestSize / 2)));
|
||||||
|
|
||||||
crypto::HMAC hmac2(crypto::HMAC::SHA256);
|
crypto::HMAC hmac2(crypto::HMAC::SHA256);
|
||||||
ASSERT_TRUE(hmac2.Init(kKnownSecretKey, kKnownSecretKeySize));
|
ASSERT_TRUE(hmac2.Init(kKnownSecretKey, kKnownSecretKeySize));
|
||||||
|
Reference in New Issue
Block a user