1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/hmac.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <CommonCrypto/CommonHMAC.h>
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace crypto {
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct HMACPlatformData {
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string key_;
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHMAC::HMAC(HashAlgorithm hash_alg)
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : hash_alg_(hash_alg), plat_(new HMACPlatformData()) {
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Only SHA-1 and SHA-256 hash algorithms are supported now.
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256);
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HMAC::Init(const unsigned char *key, int key_length) {
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!plat_->key_.empty()) {
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Init must not be called more than once on the same HMAC object.
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  plat_->key_.assign(reinterpret_cast<const char*>(key), key_length);
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHMAC::~HMAC() {
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Zero out key copy.
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  plat_->key_.assign(plat_->key_.length(), std::string::value_type());
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  plat_->key_.clear();
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  plat_->key_.reserve(0);
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HMAC::Sign(const std::string& data,
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                unsigned char* digest,
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                int digest_length) {
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CCHmacAlgorithm algorithm;
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int algorithm_digest_length;
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (hash_alg_) {
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case SHA1:
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      algorithm = kCCHmacAlgSHA1;
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      algorithm_digest_length = CC_SHA1_DIGEST_LENGTH;
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SHA256:
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      algorithm = kCCHmacAlgSHA256;
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      algorithm_digest_length = CC_SHA256_DIGEST_LENGTH;
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NOTREACHED();
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (digest_length < algorithm_digest_length) {
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CCHmac(algorithm,
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         plat_->key_.data(), plat_->key_.length(), data.data(), data.length(),
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         digest);
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}  // namespace crypto
74