diff options
author | ahendrickson@chromium.org <ahendrickson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-19 16:54:13 +0000 |
---|---|---|
committer | ahendrickson@chromium.org <ahendrickson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-19 16:54:13 +0000 |
commit | 02c28d22e674ead77e50520c350b1da082f0ca63 (patch) | |
tree | e5a6829766c9fe908ace1a82261475eb03314440 | |
parent | af00649ce4a4e34be81b489e7d14e08473d75988 (diff) | |
download | chromium_src-02c28d22e674ead77e50520c350b1da082f0ca63.zip chromium_src-02c28d22e674ead77e50520c350b1da082f0ca63.tar.gz chromium_src-02c28d22e674ead77e50520c350b1da082f0ca63.tar.bz2 |
Added serialization to SecureHash.
These will be used to resume hash generation when a download is interrupted and later resumed.
BUG=None.
TEST=SecureHashTest.TestSerialization
Review URL: http://codereview.chromium.org/8588057
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110842 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | crypto/secure_hash.h | 13 | ||||
-rw-r--r-- | crypto/secure_hash_default.cc | 48 | ||||
-rw-r--r-- | crypto/secure_hash_openssl.cc | 49 | ||||
-rw-r--r-- | crypto/secure_hash_unittest.cc | 39 |
4 files changed, 149 insertions, 0 deletions
diff --git a/crypto/secure_hash.h b/crypto/secure_hash.h index 8a0f6ae..4a49380 100644 --- a/crypto/secure_hash.h +++ b/crypto/secure_hash.h @@ -9,6 +9,8 @@ #include "base/basictypes.h" #include "crypto/crypto_export.h" +class Pickle; + namespace crypto { // A wrapper to calculate secure hashes incrementally, allowing to @@ -25,6 +27,17 @@ class CRYPTO_EXPORT SecureHash { virtual void Update(const void* input, size_t len) = 0; virtual void Finish(void* output, size_t len) = 0; + // Serialize the context, so it can be restored at a later time. + // |pickle| will contain the serialized data. + // Returns whether or not |pickle| was filled. + virtual bool Serialize(Pickle* pickle) = 0; + + // Restore the context that was saved earlier. + // |data_iterator| allows this to be used as part of a larger pickle. + // |pickle| holds the saved data. + // Returns success or failure. + virtual bool Deserialize(void** data_iterator, Pickle* pickle) = 0; + protected: SecureHash() {} diff --git a/crypto/secure_hash_default.cc b/crypto/secure_hash_default.cc index d85754a..6607dfe 100644 --- a/crypto/secure_hash_default.cc +++ b/crypto/secure_hash_default.cc @@ -5,6 +5,7 @@ #include "crypto/secure_hash.h" #include "base/logging.h" +#include "base/pickle.h" #include "crypto/third_party/nss/chromium-blapi.h" #include "crypto/third_party/nss/chromium-sha256.h" @@ -12,8 +13,12 @@ namespace crypto { namespace { +const char kSHA256Descriptor[] = "NSS"; + class SecureHashSHA256NSS : public SecureHash { public: + static const int kSecureHashVersion = 1; + SecureHashSHA256NSS() { SHA256_Begin(&ctx_); } @@ -30,10 +35,53 @@ class SecureHashSHA256NSS : public SecureHash { static_cast<unsigned int>(len)); } + virtual bool Serialize(Pickle* pickle); + virtual bool Deserialize(void** data_iterator, Pickle* pickle); + private: SHA256Context ctx_; }; +bool SecureHashSHA256NSS::Serialize(Pickle* pickle) { + if (!pickle) + return false; + + if (!pickle->WriteInt(kSecureHashVersion) || + !pickle->WriteString(kSHA256Descriptor) || + !pickle->WriteBytes(&ctx_, sizeof(ctx_))) { + return false; + } + + return true; +} + +bool SecureHashSHA256NSS::Deserialize(void** data_iterator, Pickle* pickle) { + if (!pickle) + return false; + + int version; + if (!pickle->ReadInt(data_iterator, &version)) + return false; + + if (version > kSecureHashVersion) + return false; // We don't know how to deal with this. + + std::string type; + if (!pickle->ReadString(data_iterator, &type)) + return false; + + if (type != kSHA256Descriptor) + return false; // It's the wrong kind. + + const char* data = NULL; + if (!pickle->ReadBytes(data_iterator, &data, sizeof(ctx_))) + return false; + + memcpy(&ctx_, data, sizeof(ctx_)); + + return true; +} + } // namespace SecureHash* SecureHash::Create(Algorithm algorithm) { diff --git a/crypto/secure_hash_openssl.cc b/crypto/secure_hash_openssl.cc index 8e2f128..098bf27 100644 --- a/crypto/secure_hash_openssl.cc +++ b/crypto/secure_hash_openssl.cc @@ -8,14 +8,19 @@ #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_); } @@ -34,10 +39,54 @@ class SecureHashSHA256OpenSSL : public SecureHash { SHA256_Final(result.safe_buffer(), &ctx_); } + virtual bool Serialize(Pickle* pickle); + virtual bool Deserialize(void** data_iterator, Pickle* pickle); + private: SHA256_CTX ctx_; }; +bool SecureHashSHA256OpenSSL::Serialize(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(void** data_iterator, + Pickle* pickle) { + if (!pickle) + return false; + + int version; + if (!pickle->ReadInt(data_iterator, &version)) + return false; + + if (version > kSecureHashVersion) + return false; // We don't know how to deal with this. + + std::string type; + if (!pickle->ReadString(data_iterator, &type)) + return false; + + if (type != kSHA256Descriptor) + return false; // It's the wrong kind. + + const char* data = NULL; + if (!pickle->ReadBytes(data_iterator, &data, sizeof(ctx_))) + return false; + + memcpy(&ctx_, data, sizeof(ctx_)); + + return true; +} + } // namespace SecureHash* SecureHash::Create(Algorithm algorithm) { diff --git a/crypto/secure_hash_unittest.cc b/crypto/secure_hash_unittest.cc index 6ac9285..2adddfb 100644 --- a/crypto/secure_hash_unittest.cc +++ b/crypto/secure_hash_unittest.cc @@ -6,6 +6,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" +#include "base/pickle.h" #include "crypto/sha2.h" #include "testing/gtest/include/gtest/gtest.h" @@ -32,3 +33,41 @@ TEST(SecureHashTest, TestUpdate) { for (size_t i = 0; i < crypto::kSHA256Length; i++) EXPECT_EQ(expected3[i], static_cast<int>(output3[i])); } + +// Save the crypto state mid-stream, and create another instance with the +// saved state. Then feed the same data afterwards to both. +// When done, both should have the same hash value. +TEST(SecureHashTest, TestSerialization) { + std::string input1(10001, 'a'); // 'a' repeated 10001 times + std::string input2(10001, 'b'); // 'b' repeated 10001 times + std::string input3(10001, 'c'); // 'c' repeated 10001 times + std::string input4(10001, 'd'); // 'd' repeated 10001 times + std::string input5(10001, 'e'); // 'e' repeated 10001 times + + uint8 output1[crypto::kSHA256Length]; + uint8 output2[crypto::kSHA256Length]; + + scoped_ptr<crypto::SecureHash> ctx1(crypto::SecureHash::Create( + crypto::SecureHash::SHA256)); + scoped_ptr<crypto::SecureHash> ctx2(crypto::SecureHash::Create( + crypto::SecureHash::SHA256)); + Pickle pickle; + ctx1->Update(input1.data(), input1.size()); + ctx1->Update(input2.data(), input2.size()); + ctx1->Update(input3.data(), input3.size()); + + EXPECT_TRUE(ctx1->Serialize(&pickle)); + ctx1->Update(input4.data(), input4.size()); + ctx1->Update(input5.data(), input5.size()); + + ctx1->Finish(output1, sizeof(output1)); + + void* data_iterator = NULL; + EXPECT_TRUE(ctx2->Deserialize(&data_iterator, &pickle)); + ctx2->Update(input4.data(), input4.size()); + ctx2->Update(input5.data(), input5.size()); + + ctx2->Finish(output2, sizeof(output2)); + + EXPECT_EQ(0, memcmp(output1, output2, crypto::kSHA256Length)); +} |