hmac.cc 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "crypto/hmac.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include <string>
  8. #include "base/check.h"
  9. #include "base/check_op.h"
  10. #include "base/notreached.h"
  11. #include "base/stl_util.h"
  12. #include "crypto/openssl_util.h"
  13. #include "crypto/secure_util.h"
  14. #include "crypto/symmetric_key.h"
  15. #include "third_party/boringssl/src/include/openssl/hmac.h"
  16. namespace crypto {
  17. HMAC::HMAC(HashAlgorithm hash_alg) : hash_alg_(hash_alg), initialized_(false) {
  18. // Only SHA-1 and SHA-256 hash algorithms are supported now.
  19. DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256);
  20. }
  21. HMAC::~HMAC() {
  22. // Zero out key copy.
  23. key_.assign(key_.size(), 0);
  24. base::STLClearObject(&key_);
  25. }
  26. size_t HMAC::DigestLength() const {
  27. switch (hash_alg_) {
  28. case SHA1:
  29. return 20;
  30. case SHA256:
  31. return 32;
  32. default:
  33. NOTREACHED();
  34. return 0;
  35. }
  36. }
  37. bool HMAC::Init(const unsigned char* key, size_t key_length) {
  38. // Init must not be called more than once on the same HMAC object.
  39. DCHECK(!initialized_);
  40. initialized_ = true;
  41. key_.assign(key, key + key_length);
  42. return true;
  43. }
  44. bool HMAC::Init(const SymmetricKey* key) {
  45. return Init(key->key());
  46. }
  47. bool HMAC::Sign(base::StringPiece data,
  48. unsigned char* digest,
  49. size_t digest_length) const {
  50. return Sign(base::as_bytes(base::make_span(data)),
  51. base::make_span(digest, digest_length));
  52. }
  53. bool HMAC::Sign(base::span<const uint8_t> data,
  54. base::span<uint8_t> digest) const {
  55. DCHECK(initialized_);
  56. if (digest.size() > DigestLength())
  57. return false;
  58. ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> result(digest.data(),
  59. digest.size());
  60. return !!::HMAC(hash_alg_ == SHA1 ? EVP_sha1() : EVP_sha256(), key_.data(),
  61. key_.size(), data.data(), data.size(), result.safe_buffer(),
  62. nullptr);
  63. }
  64. bool HMAC::Verify(base::StringPiece data, base::StringPiece digest) const {
  65. return Verify(base::as_bytes(base::make_span(data)),
  66. base::as_bytes(base::make_span(digest)));
  67. }
  68. bool HMAC::Verify(base::span<const uint8_t> data,
  69. base::span<const uint8_t> digest) const {
  70. if (digest.size() != DigestLength())
  71. return false;
  72. return VerifyTruncated(data, digest);
  73. }
  74. bool HMAC::VerifyTruncated(base::StringPiece data,
  75. base::StringPiece digest) const {
  76. return VerifyTruncated(base::as_bytes(base::make_span(data)),
  77. base::as_bytes(base::make_span(digest)));
  78. }
  79. bool HMAC::VerifyTruncated(base::span<const uint8_t> data,
  80. base::span<const uint8_t> digest) const {
  81. if (digest.empty())
  82. return false;
  83. size_t digest_length = DigestLength();
  84. if (digest.size() > digest_length)
  85. return false;
  86. uint8_t computed_digest[EVP_MAX_MD_SIZE];
  87. CHECK_LE(digest.size(), size_t{EVP_MAX_MD_SIZE});
  88. if (!Sign(data, base::make_span(computed_digest, digest.size())))
  89. return false;
  90. return SecureMemEqual(digest.data(), computed_digest, digest.size());
  91. }
  92. } // namespace crypto