Skip to content

Commit

Permalink
[release/4.x] Cherry pick: Update OpenSSL SHA digest API (#5336) (#5343)
Browse files Browse the repository at this point in the history
  • Loading branch information
CCF [bot] authored Jun 15, 2023
1 parent f8b027a commit 8b5e85e
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 15 deletions.
2 changes: 1 addition & 1 deletion include/ccf/crypto/hash_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace crypto
}

template <>
void update<std::vector<uint8_t>>(const std::vector<uint8_t>& d)
void update(const std::vector<uint8_t>& d)
{
update_hash(d);
}
Expand Down
2 changes: 0 additions & 2 deletions src/crypto/hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
#include "ccf/crypto/hkdf.h"
#include "ccf/crypto/sha256.h"

#include <openssl/sha.h>

namespace crypto
{
void default_sha256(const std::span<const uint8_t>& data, uint8_t* h)
Expand Down
40 changes: 30 additions & 10 deletions src/crypto/openssl/hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "crypto/openssl/hash.h"

#include <openssl/evp.h>
#include <openssl/sha.h>
#include <stdexcept>

Expand Down Expand Up @@ -38,21 +39,31 @@ namespace crypto

void openssl_sha256(const std::span<const uint8_t>& data, uint8_t* h)
{
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, data.data(), data.size());
SHA256_Final(h, &ctx);
const EVP_MD* md = EVP_sha256();
int rc = EVP_Digest(data.data(), data.size(), h, nullptr, md, nullptr);
if (rc != 1)
{
throw std::logic_error(fmt::format("EVP_Digest failed: {}", rc));
}
}

ISha256OpenSSL::ISha256OpenSSL()
{
ctx = new SHA256_CTX;
SHA256_Init((SHA256_CTX*)ctx);
const EVP_MD* md = EVP_sha256();
ctx = EVP_MD_CTX_new();
int rc = EVP_DigestInit(ctx, md);
if (rc != 1)
{
throw std::logic_error(fmt::format("EVP_DigestInit failed: {}", rc));
}
}

ISha256OpenSSL::~ISha256OpenSSL()
{
delete (SHA256_CTX*)ctx;
if (ctx)
{
EVP_MD_CTX_free(ctx);
}
}

void ISha256OpenSSL::update_hash(std::span<const uint8_t> data)
Expand All @@ -62,7 +73,11 @@ namespace crypto
throw std::logic_error("Attempting to use hash after it was finalised");
}

SHA256_Update((SHA256_CTX*)ctx, data.data(), data.size());
int rc = EVP_DigestUpdate(ctx, data.data(), data.size());
if (rc != 1)
{
throw std::logic_error(fmt::format("EVP_DigestUpdate failed: {}", rc));
}
}

Sha256Hash ISha256OpenSSL::finalise()
Expand All @@ -73,8 +88,13 @@ namespace crypto
}

Sha256Hash r;
SHA256_Final(r.h.data(), (SHA256_CTX*)ctx);
delete (SHA256_CTX*)ctx;
int rc = EVP_DigestFinal(ctx, r.h.data(), nullptr);
if (rc != 1)
{
EVP_MD_CTX_free(ctx);
throw std::logic_error(fmt::format("EVP_DigestFinal failed: {}", rc));
}
EVP_MD_CTX_free(ctx);
ctx = nullptr;
return r;
}
Expand Down
3 changes: 1 addition & 2 deletions src/crypto/openssl/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <openssl/sha.h>

#define FMT_HEADER_ONLY
#include <fmt/format.h>
Expand Down Expand Up @@ -75,7 +74,7 @@ namespace crypto
virtual Sha256Hash finalise();

protected:
void* ctx;
EVP_MD_CTX* ctx = nullptr;
};

void openssl_sha256(const std::span<const uint8_t>& data, uint8_t* h);
Expand Down
44 changes: 44 additions & 0 deletions src/crypto/test/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -877,4 +877,48 @@ TEST_CASE("PEM to JWK and back")
REQUIRE(jwk == jwk2);
}
}
}

TEST_CASE("Incremental hash")
{
auto simple_hash = crypto::Sha256Hash(contents);

INFO("Incremental hash");
{
INFO("Finalise before any update");
{
auto ihash = make_incremental_sha256();
auto final_hash = ihash->finalise();
REQUIRE(final_hash != simple_hash);
}

INFO("Update one by one");
{
auto ihash = make_incremental_sha256();
for (auto const& c : contents)
{
ihash->update(c);
}
auto final_hash = ihash->finalise();
REQUIRE(final_hash == simple_hash);

REQUIRE_THROWS_AS(ihash->finalise(), std::logic_error);
}

INFO("Update in large chunks");
{
constexpr size_t chunk_size = 10;
auto ihash = make_incremental_sha256();
for (auto it = contents.begin(); it < contents.end(); it += chunk_size)
{
auto end =
it + chunk_size > contents.end() ? contents.end() : it + chunk_size;
ihash->update(std::vector<uint8_t>{it, end});
}
auto final_hash = ihash->finalise();
REQUIRE(final_hash == simple_hash);

REQUIRE_THROWS_AS(ihash->finalise(), std::logic_error);
}
}
}

0 comments on commit 8b5e85e

Please sign in to comment.