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
5#include "crypto/hmac.h"
6
7#include <stddef.h>
8
9#include <algorithm>
10
11#include "base/logging.h"
12#include "crypto/secure_util.h"
13#include "crypto/symmetric_key.h"
14
15namespace crypto {
16
17bool HMAC::Init(SymmetricKey* key) {
18  std::string raw_key;
19  bool result = key->GetRawKey(&raw_key) && Init(raw_key);
20  // Zero out key copy.  This might get optimized away, but one can hope.
21  // Using std::string to store key info at all is a larger problem.
22  std::fill(raw_key.begin(), raw_key.end(), 0);
23  return result;
24}
25
26size_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
38bool HMAC::Verify(const base::StringPiece& data,
39                  const base::StringPiece& digest) const {
40  if (digest.size() != DigestLength())
41    return false;
42  return VerifyTruncated(data, digest);
43}
44
45bool HMAC::VerifyTruncated(const base::StringPiece& data,
46                           const base::StringPiece& digest) const {
47  if (digest.empty())
48    return false;
49  size_t digest_length = DigestLength();
50  std::unique_ptr<unsigned char[]> computed_digest(
51      new unsigned char[digest_length]);
52  if (!Sign(data, computed_digest.get(), digest_length))
53    return false;
54
55  return SecureMemEqual(digest.data(), computed_digest.get(),
56                        std::min(digest.size(), digest_length));
57}
58
59}  // namespace crypto
60