diff options
author | Jack Lloyd <[email protected]> | 2017-05-22 13:31:37 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-05-22 13:31:37 -0400 |
commit | f2f2fe7610f196cd4c5f51b5e588558762448d3c (patch) | |
tree | 70f0f84ea8c0659387e6726493a3065d05adcfe1 | |
parent | 89e6af6b94de14a4325d6f761b1bf597b6eb450f (diff) |
Add HashFunction::copy_state
See GH #1037
42 files changed, 186 insertions, 1 deletions
diff --git a/src/lib/hash/blake2/blake2b.cpp b/src/lib/hash/blake2/blake2b.cpp index b478af106..85171b16b 100644 --- a/src/lib/hash/blake2/blake2b.cpp +++ b/src/lib/hash/blake2/blake2b.cpp @@ -208,6 +208,11 @@ HashFunction* Blake2b::clone() const return new Blake2b(m_output_bits); } +std::unique_ptr<HashFunction> Blake2b::copy_state() const + { + return std::unique_ptr<HashFunction>(new Blake2b(*this)); + } + void Blake2b::clear() { zeroise(m_H); diff --git a/src/lib/hash/blake2/blake2b.h b/src/lib/hash/blake2/blake2b.h index 473352174..c7ceac01e 100644 --- a/src/lib/hash/blake2/blake2b.h +++ b/src/lib/hash/blake2/blake2b.h @@ -38,6 +38,8 @@ class BOTAN_DLL Blake2b final : public HashFunction std::string name() const override; void clear() override; + std::unique_ptr<HashFunction> copy_state() const override; + private: void add_data(const uint8_t input[], size_t length) override; void final_result(uint8_t out[]) override; diff --git a/src/lib/hash/checksum/adler32/adler32.cpp b/src/lib/hash/checksum/adler32/adler32.cpp index b7f6356c4..329ba99a8 100644 --- a/src/lib/hash/checksum/adler32/adler32.cpp +++ b/src/lib/hash/checksum/adler32/adler32.cpp @@ -78,4 +78,9 @@ void Adler32::final_result(uint8_t output[]) clear(); } +std::unique_ptr<HashFunction> Adler32::copy_state() const + { + return std::unique_ptr<HashFunction>(new Adler32(*this)); + } + } diff --git a/src/lib/hash/checksum/adler32/adler32.h b/src/lib/hash/checksum/adler32/adler32.h index eaf57c656..98ba4f91a 100644 --- a/src/lib/hash/checksum/adler32/adler32.h +++ b/src/lib/hash/checksum/adler32/adler32.h @@ -21,6 +21,7 @@ class BOTAN_DLL Adler32 final : public HashFunction std::string name() const override { return "Adler32"; } size_t output_length() const override { return 4; } HashFunction* clone() const override { return new Adler32; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override { m_S1 = 1; m_S2 = 0; } diff --git a/src/lib/hash/checksum/crc24/crc24.cpp b/src/lib/hash/checksum/crc24/crc24.cpp index 923433d7e..bed456177 100644 --- a/src/lib/hash/checksum/crc24/crc24.cpp +++ b/src/lib/hash/checksum/crc24/crc24.cpp @@ -10,6 +10,11 @@ namespace Botan { +std::unique_ptr<HashFunction> CRC24::copy_state() const + { + return std::unique_ptr<HashFunction>(new CRC24(*this)); + } + /* * Update a CRC24 Checksum */ diff --git a/src/lib/hash/checksum/crc24/crc24.h b/src/lib/hash/checksum/crc24/crc24.h index 95977bc48..203611b8f 100644 --- a/src/lib/hash/checksum/crc24/crc24.h +++ b/src/lib/hash/checksum/crc24/crc24.h @@ -21,6 +21,7 @@ class BOTAN_DLL CRC24 final : public HashFunction std::string name() const override { return "CRC24"; } size_t output_length() const override { return 3; } HashFunction* clone() const override { return new CRC24; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override { m_crc = 0xB704CE; } diff --git a/src/lib/hash/checksum/crc32/crc32.cpp b/src/lib/hash/checksum/crc32/crc32.cpp index 1bbc35ac8..c69c8f80b 100644 --- a/src/lib/hash/checksum/crc32/crc32.cpp +++ b/src/lib/hash/checksum/crc32/crc32.cpp @@ -10,6 +10,11 @@ namespace Botan { +std::unique_ptr<HashFunction> CRC32::copy_state() const + { + return std::unique_ptr<HashFunction>(new CRC32(*this)); + } + /* * Update a CRC32 Checksum */ diff --git a/src/lib/hash/checksum/crc32/crc32.h b/src/lib/hash/checksum/crc32/crc32.h index fd9db1b3e..e1e266de3 100644 --- a/src/lib/hash/checksum/crc32/crc32.h +++ b/src/lib/hash/checksum/crc32/crc32.h @@ -21,6 +21,7 @@ class BOTAN_DLL CRC32 final : public HashFunction std::string name() const override { return "CRC32"; } size_t output_length() const override { return 4; } HashFunction* clone() const override { return new CRC32; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override { m_crc = 0xFFFFFFFF; } diff --git a/src/lib/hash/comb4p/comb4p.cpp b/src/lib/hash/comb4p/comb4p.cpp index ece8c9051..a6c40b801 100644 --- a/src/lib/hash/comb4p/comb4p.cpp +++ b/src/lib/hash/comb4p/comb4p.cpp @@ -69,6 +69,14 @@ void Comb4P::clear() m_hash2->update(0); } +std::unique_ptr<HashFunction> Comb4P::copy_state() const + { + std::unique_ptr<Comb4P> copy(new Comb4P); + copy->m_hash1 = m_hash1->copy_state(); + copy->m_hash2 = m_hash2->copy_state(); + return copy; + } + void Comb4P::add_data(const uint8_t input[], size_t length) { m_hash1->update(input, length); diff --git a/src/lib/hash/comb4p/comb4p.h b/src/lib/hash/comb4p/comb4p.h index a578b56c8..9579db0ab 100644 --- a/src/lib/hash/comb4p/comb4p.h +++ b/src/lib/hash/comb4p/comb4p.h @@ -37,6 +37,8 @@ class BOTAN_DLL Comb4P final : public HashFunction return new Comb4P(m_hash1->clone(), m_hash2->clone()); } + std::unique_ptr<HashFunction> copy_state() const override; + std::string name() const override { return "Comb4P(" + m_hash1->name() + "," + m_hash2->name() + ")"; @@ -44,6 +46,8 @@ class BOTAN_DLL Comb4P final : public HashFunction void clear() override; private: + Comb4P() {} + void add_data(const uint8_t input[], size_t length) override; void final_result(uint8_t out[]) override; diff --git a/src/lib/hash/gost_3411/gost_3411.cpp b/src/lib/hash/gost_3411/gost_3411.cpp index 62028e496..2e2ed962d 100644 --- a/src/lib/hash/gost_3411/gost_3411.cpp +++ b/src/lib/hash/gost_3411/gost_3411.cpp @@ -31,6 +31,11 @@ void GOST_34_11::clear() m_position = 0; } +std::unique_ptr<HashFunction> GOST_34_11::copy_state() const + { + return std::unique_ptr<HashFunction>(new GOST_34_11(*this)); + } + /** * Hash additional inputs */ diff --git a/src/lib/hash/gost_3411/gost_3411.h b/src/lib/hash/gost_3411/gost_3411.h index e18ab56fa..51f010afb 100644 --- a/src/lib/hash/gost_3411/gost_3411.h +++ b/src/lib/hash/gost_3411/gost_3411.h @@ -23,6 +23,7 @@ class BOTAN_DLL GOST_34_11 final : public HashFunction size_t output_length() const override { return 32; } size_t hash_block_size() const override { return 32; } HashFunction* clone() const override { return new GOST_34_11; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; diff --git a/src/lib/hash/hash.h b/src/lib/hash/hash.h index 5cb290499..db049989a 100644 --- a/src/lib/hash/hash.h +++ b/src/lib/hash/hash.h @@ -72,6 +72,17 @@ class BOTAN_DLL HashFunction : public Buffered_Computation * @return hash block size as defined for this algorithm */ virtual size_t hash_block_size() const { return 0; } + + /** + * Return a new hash object with the same state as *this. This + * allows computing the hash of several messages with a common + * prefix more efficiently than would otherwise be possible. + * + * This function should be called `clone` but that was already + * used for the case of returning an uninitialized object. + * @return new hash object + */ + virtual std::unique_ptr<HashFunction> copy_state() const = 0; }; } diff --git a/src/lib/hash/keccak/keccak.cpp b/src/lib/hash/keccak/keccak.cpp index 1d2747ff2..f51b53e06 100644 --- a/src/lib/hash/keccak/keccak.cpp +++ b/src/lib/hash/keccak/keccak.cpp @@ -12,6 +12,11 @@ namespace Botan { +std::unique_ptr<HashFunction> Keccak_1600::copy_state() const + { + return std::unique_ptr<HashFunction>(new Keccak_1600(*this)); + } + Keccak_1600::Keccak_1600(size_t output_bits) : m_output_bits(output_bits), m_bitrate(1600 - 2*output_bits), diff --git a/src/lib/hash/keccak/keccak.h b/src/lib/hash/keccak/keccak.h index a2c14c65a..36e1ad9fe 100644 --- a/src/lib/hash/keccak/keccak.h +++ b/src/lib/hash/keccak/keccak.h @@ -31,6 +31,7 @@ class BOTAN_DLL Keccak_1600 final : public HashFunction size_t output_length() const override { return m_output_bits / 8; } HashFunction* clone() const override; + std::unique_ptr<HashFunction> copy_state() const override; std::string name() const override; void clear() override; diff --git a/src/lib/hash/md4/md4.cpp b/src/lib/hash/md4/md4.cpp index 014ba8c2c..79f3a2d13 100644 --- a/src/lib/hash/md4/md4.cpp +++ b/src/lib/hash/md4/md4.cpp @@ -9,6 +9,11 @@ namespace Botan { +std::unique_ptr<HashFunction> MD4::copy_state() const + { + return std::unique_ptr<HashFunction>(new MD4(*this)); + } + namespace { /* diff --git a/src/lib/hash/md4/md4.h b/src/lib/hash/md4/md4.h index ebd0bdedd..c84cb0058 100644 --- a/src/lib/hash/md4/md4.h +++ b/src/lib/hash/md4/md4.h @@ -21,6 +21,7 @@ class BOTAN_DLL MD4 final : public MDx_HashFunction std::string name() const override { return "MD4"; } size_t output_length() const override { return 16; } HashFunction* clone() const override { return new MD4; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; diff --git a/src/lib/hash/md5/md5.cpp b/src/lib/hash/md5/md5.cpp index 0612ba956..174443a67 100644 --- a/src/lib/hash/md5/md5.cpp +++ b/src/lib/hash/md5/md5.cpp @@ -9,6 +9,11 @@ namespace Botan { +std::unique_ptr<HashFunction> MD5::copy_state() const + { + return std::unique_ptr<HashFunction>(new MD5(*this)); + } + namespace { /* diff --git a/src/lib/hash/md5/md5.h b/src/lib/hash/md5/md5.h index 13a423594..ee8d70e3f 100644 --- a/src/lib/hash/md5/md5.h +++ b/src/lib/hash/md5/md5.h @@ -21,6 +21,7 @@ class BOTAN_DLL MD5 final : public MDx_HashFunction std::string name() const override { return "MD5"; } size_t output_length() const override { return 16; } HashFunction* clone() const override { return new MD5; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; diff --git a/src/lib/hash/par_hash/par_hash.cpp b/src/lib/hash/par_hash/par_hash.cpp index 2a1ef7c9c..af43d6d97 100644 --- a/src/lib/hash/par_hash/par_hash.cpp +++ b/src/lib/hash/par_hash/par_hash.cpp @@ -56,6 +56,18 @@ HashFunction* Parallel::clone() const return new Parallel(hash_copies); } +std::unique_ptr<HashFunction> Parallel::copy_state() const + { + std::vector<std::unique_ptr<HashFunction>> hash_clones; + + for(const std::unique_ptr<HashFunction>& hash : m_hashes) + { + hash_clones.push_back(hash->copy_state()); + } + + return std::unique_ptr<HashFunction>(new Parallel(hash_clones)); + } + void Parallel::clear() { for(auto&& hash : m_hashes) diff --git a/src/lib/hash/par_hash/par_hash.h b/src/lib/hash/par_hash/par_hash.h index cf6f49af4..85bf49208 100644 --- a/src/lib/hash/par_hash/par_hash.h +++ b/src/lib/hash/par_hash/par_hash.h @@ -22,6 +22,7 @@ class BOTAN_DLL Parallel final : public HashFunction void clear() override; std::string name() const override; HashFunction* clone() const override; + std::unique_ptr<HashFunction> copy_state() const override; size_t output_length() const override; diff --git a/src/lib/hash/rmd160/rmd160.cpp b/src/lib/hash/rmd160/rmd160.cpp index 8d190a74f..95f96c281 100644 --- a/src/lib/hash/rmd160/rmd160.cpp +++ b/src/lib/hash/rmd160/rmd160.cpp @@ -9,6 +9,11 @@ namespace Botan { +std::unique_ptr<HashFunction> RIPEMD_160::copy_state() const + { + return std::unique_ptr<HashFunction>(new RIPEMD_160(*this)); + } + namespace { /* diff --git a/src/lib/hash/rmd160/rmd160.h b/src/lib/hash/rmd160/rmd160.h index 9e2d1de87..f2b57ef33 100644 --- a/src/lib/hash/rmd160/rmd160.h +++ b/src/lib/hash/rmd160/rmd160.h @@ -21,6 +21,7 @@ class BOTAN_DLL RIPEMD_160 final : public MDx_HashFunction std::string name() const override { return "RIPEMD-160"; } size_t output_length() const override { return 20; } HashFunction* clone() const override { return new RIPEMD_160; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; diff --git a/src/lib/hash/sha1/sha160.cpp b/src/lib/hash/sha1/sha160.cpp index 13f9c24d7..e3b84bf1d 100644 --- a/src/lib/hash/sha1/sha160.cpp +++ b/src/lib/hash/sha1/sha160.cpp @@ -10,6 +10,11 @@ namespace Botan { +std::unique_ptr<HashFunction> SHA_160::copy_state() const + { + return std::unique_ptr<HashFunction>(new SHA_160(*this)); + } + namespace SHA1_F { namespace { diff --git a/src/lib/hash/sha1/sha160.h b/src/lib/hash/sha1/sha160.h index 7333ca827..caf3a0d25 100644 --- a/src/lib/hash/sha1/sha160.h +++ b/src/lib/hash/sha1/sha160.h @@ -21,6 +21,7 @@ class BOTAN_DLL SHA_160 final : public MDx_HashFunction std::string name() const override { return "SHA-160"; } size_t output_length() const override { return 20; } HashFunction* clone() const override { return new SHA_160; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; diff --git a/src/lib/hash/sha2_32/sha2_32.cpp b/src/lib/hash/sha2_32/sha2_32.cpp index c4d76b0f6..bdb45273e 100644 --- a/src/lib/hash/sha2_32/sha2_32.cpp +++ b/src/lib/hash/sha2_32/sha2_32.cpp @@ -11,6 +11,16 @@ namespace Botan { +std::unique_ptr<HashFunction> SHA_224::copy_state() const + { + return std::unique_ptr<HashFunction>(new SHA_224(*this)); + } + +std::unique_ptr<HashFunction> SHA_256::copy_state() const + { + return std::unique_ptr<HashFunction>(new SHA_256(*this)); + } + namespace { namespace SHA2_32 { diff --git a/src/lib/hash/sha2_32/sha2_32.h b/src/lib/hash/sha2_32/sha2_32.h index 5a687efbe..d9b70c8da 100644 --- a/src/lib/hash/sha2_32/sha2_32.h +++ b/src/lib/hash/sha2_32/sha2_32.h @@ -22,6 +22,7 @@ class BOTAN_DLL SHA_224 final : public MDx_HashFunction std::string name() const override { return "SHA-224"; } size_t output_length() const override { return 28; } HashFunction* clone() const override { return new SHA_224; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; @@ -43,6 +44,7 @@ class BOTAN_DLL SHA_256 final : public MDx_HashFunction std::string name() const override { return "SHA-256"; } size_t output_length() const override { return 32; } HashFunction* clone() const override { return new SHA_256; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; diff --git a/src/lib/hash/sha2_64/sha2_64.cpp b/src/lib/hash/sha2_64/sha2_64.cpp index 59242ee9c..8e01b6b4d 100644 --- a/src/lib/hash/sha2_64/sha2_64.cpp +++ b/src/lib/hash/sha2_64/sha2_64.cpp @@ -9,6 +9,21 @@ namespace Botan { +std::unique_ptr<HashFunction> SHA_384::copy_state() const + { + return std::unique_ptr<HashFunction>(new SHA_384(*this)); + } + +std::unique_ptr<HashFunction> SHA_512::copy_state() const + { + return std::unique_ptr<HashFunction>(new SHA_512(*this)); + } + +std::unique_ptr<HashFunction> SHA_512_256::copy_state() const + { + return std::unique_ptr<HashFunction>(new SHA_512_256(*this)); + } + namespace { namespace SHA2_64 { diff --git a/src/lib/hash/sha2_64/sha2_64.h b/src/lib/hash/sha2_64/sha2_64.h index 51bdb2b77..b027c4d27 100644 --- a/src/lib/hash/sha2_64/sha2_64.h +++ b/src/lib/hash/sha2_64/sha2_64.h @@ -21,6 +21,7 @@ class BOTAN_DLL SHA_384 final : public MDx_HashFunction std::string name() const override { return "SHA-384"; } size_t output_length() const override { return 48; } HashFunction* clone() const override { return new SHA_384; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; @@ -42,6 +43,7 @@ class BOTAN_DLL SHA_512 final : public MDx_HashFunction std::string name() const override { return "SHA-512"; } size_t output_length() const override { return 64; } HashFunction* clone() const override { return new SHA_512; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; @@ -63,6 +65,7 @@ class BOTAN_DLL SHA_512_256 final : public MDx_HashFunction std::string name() const override { return "SHA-512-256"; } size_t output_length() const override { return 32; } HashFunction* clone() const override { return new SHA_512_256; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; diff --git a/src/lib/hash/sha3/sha3.cpp b/src/lib/hash/sha3/sha3.cpp index f1c769e6b..a31b3bd14 100644 --- a/src/lib/hash/sha3/sha3.cpp +++ b/src/lib/hash/sha3/sha3.cpp @@ -11,6 +11,11 @@ namespace Botan { +std::unique_ptr<HashFunction> SHA_3::copy_state() const + { + return std::unique_ptr<HashFunction>(new SHA_3(*this)); + } + //static void SHA_3::permute(uint64_t A[25]) { diff --git a/src/lib/hash/sha3/sha3.h b/src/lib/hash/sha3/sha3.h index e7905b5c4..fec25b806 100644 --- a/src/lib/hash/sha3/sha3.h +++ b/src/lib/hash/sha3/sha3.h @@ -31,6 +31,7 @@ class BOTAN_DLL SHA_3 : public HashFunction size_t output_length() const override { return m_output_bits / 8; } HashFunction* clone() const override; + std::unique_ptr<HashFunction> copy_state() const override; std::string name() const override; void clear() override; diff --git a/src/lib/hash/shake/shake.cpp b/src/lib/hash/shake/shake.cpp index 97ee0c4da..329aec080 100644 --- a/src/lib/hash/shake/shake.cpp +++ b/src/lib/hash/shake/shake.cpp @@ -30,6 +30,11 @@ HashFunction* SHAKE_128::clone() const return new SHAKE_128(m_output_bits); } +std::unique_ptr<HashFunction> SHAKE_128::copy_state() const + { + return std::unique_ptr<HashFunction>(new SHAKE_128(*this)); + } + void SHAKE_128::clear() { zeroise(m_S); @@ -73,6 +78,11 @@ HashFunction* SHAKE_256::clone() const return new SHAKE_256(m_output_bits); } +std::unique_ptr<HashFunction> SHAKE_256::copy_state() const + { + return std::unique_ptr<HashFunction>(new SHAKE_256(*this)); + } + void SHAKE_256::clear() { zeroise(m_S); diff --git a/src/lib/hash/shake/shake.h b/src/lib/hash/shake/shake.h index f24fda4fa..363e8be48 100644 --- a/src/lib/hash/shake/shake.h +++ b/src/lib/hash/shake/shake.h @@ -31,6 +31,7 @@ class BOTAN_DLL SHAKE_128 : public HashFunction size_t output_length() const override { return m_output_bits / 8; } HashFunction* clone() const override; + std::unique_ptr<HashFunction> copy_state() const override; std::string name() const override; void clear() override; @@ -62,6 +63,7 @@ class BOTAN_DLL SHAKE_256 : public HashFunction size_t output_length() const override { return m_output_bits / 8; } HashFunction* clone() const override; + std::unique_ptr<HashFunction> copy_state() const override; std::string name() const override; void clear() override; diff --git a/src/lib/hash/skein/skein_512.cpp b/src/lib/hash/skein/skein_512.cpp index ae059f085..a3bbde9a7 100644 --- a/src/lib/hash/skein/skein_512.cpp +++ b/src/lib/hash/skein/skein_512.cpp @@ -38,6 +38,18 @@ HashFunction* Skein_512::clone() const return new Skein_512(m_output_bits, m_personalization); } +std::unique_ptr<HashFunction> Skein_512::copy_state() const + { + std::unique_ptr<Skein_512> copy(new Skein_512(m_output_bits, m_personalization)); + + copy->m_threefish->m_K = this->m_threefish->m_K; + copy->m_T = this->m_T; + copy->m_buffer = this->m_buffer; + copy->m_buf_pos = this->m_buf_pos; + + return copy; + } + void Skein_512::clear() { zeroise(m_buffer); diff --git a/src/lib/hash/skein/skein_512.h b/src/lib/hash/skein/skein_512.h index 32323807e..ad47e4b1c 100644 --- a/src/lib/hash/skein/skein_512.h +++ b/src/lib/hash/skein/skein_512.h @@ -33,6 +33,7 @@ class BOTAN_DLL Skein_512 final : public HashFunction size_t output_length() const override { return m_output_bits / 8; } HashFunction* clone() const override; + std::unique_ptr<HashFunction> copy_state() const override; std::string name() const override; void clear() override; private: diff --git a/src/lib/hash/sm3/sm3.cpp b/src/lib/hash/sm3/sm3.cpp index a64a9a5e7..c2eeb4cdf 100644 --- a/src/lib/hash/sm3/sm3.cpp +++ b/src/lib/hash/sm3/sm3.cpp @@ -9,6 +9,11 @@ namespace Botan { +std::unique_ptr<HashFunction> SM3::copy_state() const + { + return std::unique_ptr<HashFunction>(new SM3(*this)); + } + namespace { const uint32_t SM3_IV[] = { diff --git a/src/lib/hash/sm3/sm3.h b/src/lib/hash/sm3/sm3.h index c5dacdf3a..dd76ab4d0 100644 --- a/src/lib/hash/sm3/sm3.h +++ b/src/lib/hash/sm3/sm3.h @@ -26,6 +26,7 @@ class BOTAN_DLL SM3 final : public MDx_HashFunction std::string name() const override { return "SM3"; } size_t output_length() const override { return SM3_DIGEST_BYTES; } HashFunction* clone() const override { return new SM3; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; diff --git a/src/lib/hash/tiger/tiger.cpp b/src/lib/hash/tiger/tiger.cpp index b09e03d2e..0851742c0 100644 --- a/src/lib/hash/tiger/tiger.cpp +++ b/src/lib/hash/tiger/tiger.cpp @@ -11,6 +11,11 @@ namespace Botan { +std::unique_ptr<HashFunction> Tiger::copy_state() const + { + return std::unique_ptr<HashFunction>(new Tiger(*this)); + } + namespace { /* diff --git a/src/lib/hash/tiger/tiger.h b/src/lib/hash/tiger/tiger.h index 32ae26258..73907b71f 100644 --- a/src/lib/hash/tiger/tiger.h +++ b/src/lib/hash/tiger/tiger.h @@ -26,6 +26,8 @@ class BOTAN_DLL Tiger final : public MDx_HashFunction return new Tiger(output_length(), m_passes); } + std::unique_ptr<HashFunction> copy_state() const override; + void clear() override; /** diff --git a/src/lib/hash/whirlpool/whirlpool.cpp b/src/lib/hash/whirlpool/whirlpool.cpp index 64350fd24..f78cc7572 100644 --- a/src/lib/hash/whirlpool/whirlpool.cpp +++ b/src/lib/hash/whirlpool/whirlpool.cpp @@ -9,6 +9,11 @@ namespace Botan { +std::unique_ptr<HashFunction> Whirlpool::copy_state() const + { + return std::unique_ptr<HashFunction>(new Whirlpool(*this)); + } + /* * Whirlpool Compression Function */ diff --git a/src/lib/hash/whirlpool/whrlpool.h b/src/lib/hash/whirlpool/whrlpool.h index 606fc3257..ed541e497 100644 --- a/src/lib/hash/whirlpool/whrlpool.h +++ b/src/lib/hash/whirlpool/whrlpool.h @@ -21,6 +21,7 @@ class BOTAN_DLL Whirlpool final : public MDx_HashFunction std::string name() const override { return "Whirlpool"; } size_t output_length() const override { return 64; } HashFunction* clone() const override { return new Whirlpool; } + std::unique_ptr<HashFunction> copy_state() const override; void clear() override; diff --git a/src/tests/test_hash.cpp b/src/tests/test_hash.cpp index 9c6051f49..9ac3e7d4e 100644 --- a/src/tests/test_hash.cpp +++ b/src/tests/test_hash.cpp @@ -69,11 +69,19 @@ class Hash_Function_Tests : public Text_Based_Test result.test_eq(provider, "hashing after clear", hash->final(), expected); // TODO: feed in random pieces to fully test buffering - if(input.size() > 1) + if(input.size() > 5) { hash->update(input[0]); + + std::unique_ptr<Botan::HashFunction> fork = hash->copy_state(); + // verify fork copy doesn't affect original computation + fork->update(&input[1], input.size() - 2); + hash->update(&input[1], input.size() - 1); result.test_eq(provider, "hashing split", hash->final(), expected); + + fork->update(&input[input.size() - 1], 1); + result.test_eq(provider, "hashing split", fork->final(), expected); } if(hash->hash_block_size() > 0) |