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