// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "crypto/hmac.h" #include #include "base/logging.h" namespace crypto { struct HMACPlatformData { std::string key_; }; HMAC::HMAC(HashAlgorithm hash_alg) : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { // Only SHA-1 and SHA-256 hash algorithms are supported now. DCHECK(hash_alg_ == SHA1 || hash_alg_ == SHA256); } bool HMAC::Init(const unsigned char *key, int key_length) { if (!plat_->key_.empty()) { // Init must not be called more than once on the same HMAC object. NOTREACHED(); return false; } plat_->key_.assign(reinterpret_cast(key), key_length); return true; } HMAC::~HMAC() { // Zero out key copy. plat_->key_.assign(plat_->key_.length(), std::string::value_type()); plat_->key_.clear(); plat_->key_.reserve(0); } bool HMAC::Sign(const base::StringPiece& data, unsigned char* digest, int digest_length) const { if (plat_->key_.empty()) { // Init has not been called or has failed. NOTREACHED(); return false; } CCHmacAlgorithm algorithm; int algorithm_digest_length; switch (hash_alg_) { case SHA1: algorithm = kCCHmacAlgSHA1; algorithm_digest_length = CC_SHA1_DIGEST_LENGTH; break; case SHA256: algorithm = kCCHmacAlgSHA256; algorithm_digest_length = CC_SHA256_DIGEST_LENGTH; break; default: NOTREACHED(); return false; } if (digest_length < algorithm_digest_length) { NOTREACHED(); return false; } CCHmac(algorithm, plat_->key_.data(), plat_->key_.length(), data.data(), data.length(), digest); return true; } } // namespace crypto