|  | // 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/crypto.h> | 
|  | #include <openssl/sha.h> | 
|  |  | 
|  | #include "base/basictypes.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 |