// Copyright (c) 2012 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/secure_hash.h" #include <openssl/mem.h> #include <openssl/sha.h> #include <stddef.h> #include "base/logging.h" #include "base/pickle.h" #include "crypto/openssl_util.h" namespace crypto { namespace { const char kSHA256Descriptor[] = "OpenSSL"; class SecureHashSHA256OpenSSL : public SecureHash { public: static const int kSecureHashVersion = 1; SecureHashSHA256OpenSSL() { SHA256_Init(&ctx_); } ~SecureHashSHA256OpenSSL() override { OPENSSL_cleanse(&ctx_, sizeof(ctx_)); } void Update(const void* input, size_t len) override { SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len); } void Finish(void* output, size_t len) override { ScopedOpenSSLSafeSizeBuffer<SHA256_DIGEST_LENGTH> result( static_cast<unsigned char*>(output), len); SHA256_Final(result.safe_buffer(), &ctx_); } bool Serialize(base::Pickle* pickle) override; bool Deserialize(base::PickleIterator* data_iterator) override; private: SHA256_CTX ctx_; }; bool SecureHashSHA256OpenSSL::Serialize(base::Pickle* pickle) { if (!pickle) return false; if (!pickle->WriteInt(kSecureHashVersion) || !pickle->WriteString(kSHA256Descriptor) || !pickle->WriteBytes(&ctx_, sizeof(ctx_))) { return false; } return true; } bool SecureHashSHA256OpenSSL::Deserialize(base::PickleIterator* data_iterator) { if (!data_iterator) return false; int version; if (!data_iterator->ReadInt(&version)) return false; if (version > kSecureHashVersion) return false; // We don't know how to deal with this. std::string type; if (!data_iterator->ReadString(&type)) return false; if (type != kSHA256Descriptor) return false; // It's the wrong kind. const char* data = NULL; if (!data_iterator->ReadBytes(&data, sizeof(ctx_))) return false; memcpy(&ctx_, data, sizeof(ctx_)); return true; } } // namespace SecureHash* SecureHash::Create(Algorithm algorithm) { switch (algorithm) { case SHA256: return new SecureHashSHA256OpenSSL(); default: NOTIMPLEMENTED(); return NULL; } } } // namespace crypto