33
44#include " crypto/openssl/hash.h"
55
6- #include " ccf/crypto/openssl_init.h"
7-
86#include < limits>
97#include < openssl/evp.h>
108#include < openssl/sha.h>
119#include < stdexcept>
1210
11+ namespace
12+ {
13+ struct Sha256Context
14+ {
15+ Sha256Context ()
16+ {
17+ openssl_sha256_init ();
18+ }
19+
20+ Sha256Context (const Sha256Context&) = delete ;
21+ Sha256Context& operator =(const Sha256Context&) = delete ;
22+
23+ Sha256Context (Sha256Context&&) = delete ;
24+ Sha256Context& operator =(Sha256Context&&) = delete ;
25+
26+ ~Sha256Context ()
27+ {
28+ openssl_sha256_shutdown ();
29+ }
30+
31+ [[nodiscard]] EVP_MD_CTX * get_basectx () const
32+ {
33+ return basectx;
34+ }
35+
36+ [[nodiscard]] EVP_MD_CTX * get_mdctx () const
37+ {
38+ return mdctx;
39+ }
40+
41+ private:
42+ void openssl_sha256_init ()
43+ {
44+ if (mdctx != nullptr || basectx != nullptr )
45+ {
46+ throw std::logic_error (
47+ " openssl_sha256_init: double-init of the context" );
48+ }
49+
50+ mdctx = EVP_MD_CTX_new ();
51+ if (mdctx == nullptr )
52+ {
53+ throw std::logic_error (" openssl_sha256_init: failed to create mdctx" );
54+ }
55+
56+ basectx = EVP_MD_CTX_new ();
57+ if (basectx == nullptr )
58+ {
59+ mdctx = nullptr ;
60+ throw std::logic_error (" openssl_sha256_init: failed to create basectx" );
61+ }
62+
63+ if (EVP_DigestInit_ex (basectx, EVP_sha256 (), nullptr ) != 1 )
64+ {
65+ mdctx = nullptr ;
66+ basectx = nullptr ;
67+ throw std::logic_error (" EVP_DigestInit_ex failed" );
68+ }
69+
70+ EVP_MD_CTX * mdctx{nullptr };
71+ EVP_MD_CTX * basectx{nullptr };
72+ }
73+
74+ void openssl_sha256_shutdown ()
75+ {
76+ if (mdctx != nullptr )
77+ {
78+ EVP_MD_CTX_free (mdctx);
79+ mdctx = nullptr ;
80+ }
81+ if (basectx != nullptr )
82+ {
83+ EVP_MD_CTX_free (basectx);
84+ basectx = nullptr ;
85+ }
86+ }
87+
88+ EVP_MD_CTX * basectx{nullptr };
89+ EVP_MD_CTX * mdctx{nullptr };
90+ };
91+
92+ thread_local const Sha256Context sha256_context{};
93+ }
94+
1395namespace ccf ::crypto
1496{
1597 namespace OpenSSL
@@ -55,52 +137,6 @@ namespace ccf::crypto
55137
56138 using namespace OpenSSL ;
57139
58- namespace
59- {
60- thread_local EVP_MD_CTX * mdctx = nullptr ;
61- thread_local EVP_MD_CTX * basectx = nullptr ;
62- }
63-
64- void openssl_sha256_init ()
65- {
66- if (mdctx != nullptr || basectx != nullptr )
67- {
68- return ; // Already initialised
69- }
70-
71- mdctx = EVP_MD_CTX_new ();
72- if (mdctx == nullptr )
73- {
74- throw std::logic_error (" openssl_sha256_init: failed to create mdctx" );
75- }
76- basectx = EVP_MD_CTX_new ();
77- if (basectx == nullptr )
78- {
79- mdctx = nullptr ;
80- throw std::logic_error (" openssl_sha256_init: failed to create basectx" );
81- }
82- if (EVP_DigestInit_ex (basectx, EVP_sha256 (), nullptr ) != 1 )
83- {
84- mdctx = nullptr ;
85- basectx = nullptr ;
86- throw std::logic_error (" EVP_DigestInit_ex failed" );
87- }
88- }
89-
90- void openssl_sha256_shutdown ()
91- {
92- if (mdctx != nullptr )
93- {
94- EVP_MD_CTX_free (mdctx);
95- mdctx = nullptr ;
96- }
97- if (basectx != nullptr )
98- {
99- EVP_MD_CTX_free (basectx);
100- basectx = nullptr ;
101- }
102- }
103-
104140 void openssl_sha256 (const std::span<const uint8_t >& data, uint8_t * h)
105141 {
106142 // EVP_Digest calls are notoriously slow with OpenSSL 3.x (see
@@ -109,6 +145,9 @@ namespace ccf::crypto
109145 // and reusing them between calls. This is about 2x faster than EVP_Digest
110146 // for 128-byte buffers.
111147
148+ auto * const mdctx = sha256_context.get_mdctx ();
149+ auto * const basectx = sha256_context.get_basectx ();
150+
112151 if (mdctx == nullptr || basectx == nullptr )
113152 {
114153 throw std::logic_error (
@@ -120,11 +159,13 @@ namespace ccf::crypto
120159 {
121160 throw std::logic_error (fmt::format (" EVP_MD_CTX_copy_ex failed: {}" , rc));
122161 }
162+
123163 rc = EVP_DigestUpdate (mdctx, data.data (), data.size ());
124164 if (rc != 1 )
125165 {
126166 throw std::logic_error (fmt::format (" EVP_DigestUpdate failed: {}" , rc));
127167 }
168+
128169 rc = EVP_DigestFinal_ex (mdctx, h, nullptr );
129170 if (rc != 1 )
130171 {
0 commit comments