Index: crypto/hmac.cc |
diff --git a/crypto/hmac.cc b/crypto/hmac.cc |
index a38f5144cdd032738cfca0f0a84088659dc6482c..36ed3fc49e1f99d7723b23cd4e277e38c20643bf 100644 |
--- a/crypto/hmac.cc |
+++ b/crypto/hmac.cc |
@@ -20,4 +20,29 @@ size_t HMAC::DigestLength() const { |
} |
} |
+bool HMAC::Verify(const base::StringPiece& data, |
+ const base::StringPiece& digest) const { |
+ if (digest.size() != DigestLength()) |
+ return false; |
+ scoped_array<unsigned char> computed_digest( |
+ new unsigned char[digest.size()]); |
+ if (!Sign(data, computed_digest.get(), static_cast<int>(digest.size()))) |
+ return false; |
+ |
+ // In order to avoid any timing attacks, this comparison must be constant |
+ // time with respect to the input. Using a comparison such as memcmp() can |
+ // cause a short-circuit once a differing byte is found, which can reveal |
+ // to an attacker which byte (and possibly which bit) of the digest was |
+ // invalid. See also: |
+ // http://groups.google.com/group/keyczar-discuss/browse_thread/thread/5571eca0948b2a13 |
wtc
2011/07/14 00:49:42
This URL doesn't work for me.
|
+ const unsigned char* digest_ptr = |
+ reinterpret_cast<const unsigned char*>(digest.data()); |
+ const unsigned char* computed_ptr = computed_digest.get(); |
+ unsigned char tmp = 0; |
+ for (size_t i = 0; i < digest.size(); ++i) |
+ tmp |= *digest_ptr++ ^ *computed_ptr++; |
wtc
2011/07/14 00:00:22
We should add a SecureMemcmp function.
Ryan Sleevi
2011/07/14 00:18:19
Was this remark for a high-level, crypto/ API, or
wtc
2011/07/14 00:49:42
Sorry I wasn't clear. I meant a function that can
|
+ |
+ return tmp == 0; |
+} |
+ |
} // namespace crypto |