blob: b4dd6cf106cbd01f67661320c097426062eed57a [file] [log] [blame]
[email protected]2c9f0def2012-01-11 23:17:141// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]a5aec2e2011-04-30 18:55:182// 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
svaldez9c641462016-05-02 20:49:057#include <openssl/hmac.h>
avidd373b8b2015-12-21 21:34:438#include <stddef.h>
9
[email protected]baff1d042011-07-29 23:28:5510#include <algorithm>
11
[email protected]a5aec2e2011-04-30 18:55:1812#include "base/logging.h"
svaldez9c641462016-05-02 20:49:0513#include "base/stl_util.h"
14#include "crypto/openssl_util.h"
[email protected]3cdf6d42011-10-07 17:02:4815#include "crypto/secure_util.h"
[email protected]2c9f0def2012-01-11 23:17:1416#include "crypto/symmetric_key.h"
[email protected]a5aec2e2011-04-30 18:55:1817
18namespace crypto {
19
svaldez9c641462016-05-02 20:49:0520HMAC::HMAC(HashAlgorithm hash_alg) : hash_alg_(hash_alg), initialized_(false) {
21 // Only SHA-1 and SHA-256 hash algorithms are supported now.
22 DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256);
23}
24
25HMAC::~HMAC() {
26 // Zero out key copy.
27 key_.assign(key_.size(), 0);
skyostil8ef165b2016-08-12 13:05:0028 base::STLClearObject(&key_);
[email protected]2c9f0def2012-01-11 23:17:1429}
30
[email protected]a5aec2e2011-04-30 18:55:1831size_t HMAC::DigestLength() const {
32 switch (hash_alg_) {
33 case SHA1:
34 return 20;
35 case SHA256:
36 return 32;
37 default:
38 NOTREACHED();
39 return 0;
40 }
41}
42
svaldez9c641462016-05-02 20:49:0543bool HMAC::Init(const unsigned char* key, size_t key_length) {
44 // Init must not be called more than once on the same HMAC object.
45 DCHECK(!initialized_);
46 initialized_ = true;
47 key_.assign(key, key + key_length);
48 return true;
49}
50
51bool HMAC::Init(SymmetricKey* key) {
52 std::string raw_key;
53 bool result = key->GetRawKey(&raw_key) && Init(raw_key);
54 // Zero out key copy. This might get optimized away, but one can hope.
55 // Using std::string to store key info at all is a larger problem.
56 std::fill(raw_key.begin(), raw_key.end(), 0);
57 return result;
58}
59
60bool HMAC::Sign(const base::StringPiece& data,
61 unsigned char* digest,
62 size_t digest_length) const {
63 DCHECK(initialized_);
64
65 ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> result(digest, digest_length);
rsleeviffe5a132016-06-28 01:51:5266 return !!::HMAC(hash_alg_ == SHA1 ? EVP_sha1() : EVP_sha256(), key_.data(),
67 key_.size(),
svaldez9c641462016-05-02 20:49:0568 reinterpret_cast<const unsigned char*>(data.data()),
rsleeviffe5a132016-06-28 01:51:5269 data.size(), result.safe_buffer(), nullptr);
svaldez9c641462016-05-02 20:49:0570}
71
[email protected]3292f532011-07-18 00:39:4472bool HMAC::Verify(const base::StringPiece& data,
73 const base::StringPiece& digest) const {
74 if (digest.size() != DigestLength())
75 return false;
[email protected]baff1d042011-07-29 23:28:5576 return VerifyTruncated(data, digest);
77}
78
79bool HMAC::VerifyTruncated(const base::StringPiece& data,
80 const base::StringPiece& digest) const {
81 if (digest.empty())
82 return false;
83 size_t digest_length = DigestLength();
thakisd1a18472016-04-08 22:30:4184 std::unique_ptr<unsigned char[]> computed_digest(
[email protected]baff1d042011-07-29 23:28:5585 new unsigned char[digest_length]);
[email protected]673266c42012-12-04 00:50:3586 if (!Sign(data, computed_digest.get(), digest_length))
[email protected]3292f532011-07-18 00:39:4487 return false;
88
[email protected]3cdf6d42011-10-07 17:02:4889 return SecureMemEqual(digest.data(), computed_digest.get(),
90 std::min(digest.size(), digest_length));
[email protected]3292f532011-07-18 00:39:4491}
92
[email protected]a5aec2e2011-04-30 18:55:1893} // namespace crypto