public:
Digest() : ctx_(EVP_MD_CTX_new()) {}
+ Digest(const Digest& other) {
+ ctx_ = EvpMdCtxUniquePtr(EVP_MD_CTX_new());
+ if (other.md_ != nullptr) {
+ hash_init(other.md_);
+ check_libssl_result(
+ 1, EVP_MD_CTX_copy_ex(ctx_.get(), other.ctx_.get()));
+ }
+ }
+
+ Digest& operator=(const Digest& other) {
+ this->~Digest();
+ return *new (this) Digest(other);
+ }
+
void hash_init(const EVP_MD* md) {
md_ = md;
check_libssl_result(1, EVP_DigestInit_ex(ctx_.get(), md, nullptr));
check_libssl_result(size, int(len));
md_ = nullptr;
}
+
private:
const EVP_MD* md_ = nullptr;
EvpMdCtxUniquePtr ctx_{nullptr};
EXPECT_EQ(expected, out);
}
+TEST_F(OpenSSLHashTest, sha256_hashcopy) {
+ std::array<uint8_t, 32> expected, actual;
+
+ OpenSSLHash::Digest digest;
+ digest.hash_init(EVP_sha256());
+ digest.hash_update(ByteRange(StringPiece("foobar")));
+
+ OpenSSLHash::Digest copy(digest);
+
+ digest.hash_final(range(expected));
+ copy.hash_final(range(actual));
+
+ EXPECT_EQ(expected, actual);
+}
+
+TEST_F(OpenSSLHashTest, sha256_hashcopy_intermediate) {
+ std::array<uint8_t, 32> expected, actual;
+
+ OpenSSLHash::Digest digest;
+ digest.hash_init(EVP_sha256());
+ digest.hash_update(ByteRange(StringPiece("foo")));
+
+ OpenSSLHash::Digest copy(digest);
+
+ digest.hash_update(ByteRange(StringPiece("bar")));
+ copy.hash_update(ByteRange(StringPiece("bar")));
+
+ digest.hash_final(range(expected));
+ copy.hash_final(range(actual));
+
+ EXPECT_EQ(expected, actual);
+}
+
TEST_F(OpenSSLHashTest, hmac_sha256) {
auto key = ByteRange(StringPiece("qwerty"));