aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-05-22 13:31:37 -0400
committerJack Lloyd <[email protected]>2017-05-22 13:31:37 -0400
commitf2f2fe7610f196cd4c5f51b5e588558762448d3c (patch)
tree70f0f84ea8c0659387e6726493a3065d05adcfe1
parent89e6af6b94de14a4325d6f761b1bf597b6eb450f (diff)
Add HashFunction::copy_state
See GH #1037
-rw-r--r--src/lib/hash/blake2/blake2b.cpp5
-rw-r--r--src/lib/hash/blake2/blake2b.h2
-rw-r--r--src/lib/hash/checksum/adler32/adler32.cpp5
-rw-r--r--src/lib/hash/checksum/adler32/adler32.h1
-rw-r--r--src/lib/hash/checksum/crc24/crc24.cpp5
-rw-r--r--src/lib/hash/checksum/crc24/crc24.h1
-rw-r--r--src/lib/hash/checksum/crc32/crc32.cpp5
-rw-r--r--src/lib/hash/checksum/crc32/crc32.h1
-rw-r--r--src/lib/hash/comb4p/comb4p.cpp8
-rw-r--r--src/lib/hash/comb4p/comb4p.h4
-rw-r--r--src/lib/hash/gost_3411/gost_3411.cpp5
-rw-r--r--src/lib/hash/gost_3411/gost_3411.h1
-rw-r--r--src/lib/hash/hash.h11
-rw-r--r--src/lib/hash/keccak/keccak.cpp5
-rw-r--r--src/lib/hash/keccak/keccak.h1
-rw-r--r--src/lib/hash/md4/md4.cpp5
-rw-r--r--src/lib/hash/md4/md4.h1
-rw-r--r--src/lib/hash/md5/md5.cpp5
-rw-r--r--src/lib/hash/md5/md5.h1
-rw-r--r--src/lib/hash/par_hash/par_hash.cpp12
-rw-r--r--src/lib/hash/par_hash/par_hash.h1
-rw-r--r--src/lib/hash/rmd160/rmd160.cpp5
-rw-r--r--src/lib/hash/rmd160/rmd160.h1
-rw-r--r--src/lib/hash/sha1/sha160.cpp5
-rw-r--r--src/lib/hash/sha1/sha160.h1
-rw-r--r--src/lib/hash/sha2_32/sha2_32.cpp10
-rw-r--r--src/lib/hash/sha2_32/sha2_32.h2
-rw-r--r--src/lib/hash/sha2_64/sha2_64.cpp15
-rw-r--r--src/lib/hash/sha2_64/sha2_64.h3
-rw-r--r--src/lib/hash/sha3/sha3.cpp5
-rw-r--r--src/lib/hash/sha3/sha3.h1
-rw-r--r--src/lib/hash/shake/shake.cpp10
-rw-r--r--src/lib/hash/shake/shake.h2
-rw-r--r--src/lib/hash/skein/skein_512.cpp12
-rw-r--r--src/lib/hash/skein/skein_512.h1
-rw-r--r--src/lib/hash/sm3/sm3.cpp5
-rw-r--r--src/lib/hash/sm3/sm3.h1
-rw-r--r--src/lib/hash/tiger/tiger.cpp5
-rw-r--r--src/lib/hash/tiger/tiger.h2
-rw-r--r--src/lib/hash/whirlpool/whirlpool.cpp5
-rw-r--r--src/lib/hash/whirlpool/whrlpool.h1
-rw-r--r--src/tests/test_hash.cpp10
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)