Skip to content

Commit dd59858

Browse files
authored
Merge pull request #41 from cppalliance/sha224
Add implementation for SHA224
2 parents d21132f + b9a0d1c commit dd59858

File tree

17 files changed

+2174
-181
lines changed

17 files changed

+2174
-181
lines changed

fuzzing/fuzz_sha224.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2024 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#include <boost/crypt/hash/sha224.hpp>
6+
#include <iostream>
7+
#include <exception>
8+
#include <string>
9+
10+
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size)
11+
{
12+
try
13+
{
14+
auto c_data = reinterpret_cast<const char*>(data);
15+
std::string c_data_str {c_data, size}; // Guarantee null termination since we can't pass the size argument
16+
17+
boost::crypt::sha224(c_data_str);
18+
boost::crypt::sha224(c_data, size);
19+
boost::crypt::sha224(data, size);
20+
21+
#ifdef BOOST_CRYPT_HAS_STRING_VIEW
22+
std::string_view view {c_data_str};
23+
boost::crypt::sha224(view);
24+
#endif
25+
26+
#ifdef BOOST_CRYPT_HAS_SPAN
27+
std::span data_span {c_data, size};
28+
boost::crypt::sha224(data_span);
29+
#endif
30+
31+
// Fuzz the hasher object
32+
boost::crypt::sha224_hasher hasher;
33+
hasher.process_bytes(data, size);
34+
hasher.process_bytes(data, size);
35+
hasher.process_bytes(data, size);
36+
hasher.get_digest();
37+
hasher.process_bytes(data, size); // State is invalid but should not crash
38+
}
39+
catch(...)
40+
{
41+
std::cerr << "Error with: " << data << std::endl;
42+
std::terminate();
43+
}
44+
45+
return 0;
46+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"The quick brown fox jumps over the lazy dog"
2+
"The quick brown fox jumps over the lazy dog."
3+
""
4+
"aB3$x9Yz"
5+
"12345"
6+
"!@#$%^&*()"
7+
"FuzzTest123"
8+
" "
9+
"Lorem ipsum dolor sit amet"
10+
"a"
11+
"9876543210"
12+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
13+
"ñÑáéíóúÁÉÍÓÚ"
14+
"\n\r\t"
15+
"0"
16+
"ThisIsAVeryLongStringWithNoSpacesOrPunctuationToTestEdgeCases"
17+
"<?php echo 'test'; ?>"
18+
"SELECT * FROM users;"
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// Copyright 2024 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
//
5+
// See: https://datatracker.ietf.org/doc/html/rfc4634
6+
// See: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
7+
8+
#ifndef BOOST_CRYPT_HASH_DETAIL_SHA224_256_HASHER_HPP
9+
#define BOOST_CRYPT_HASH_DETAIL_SHA224_256_HASHER_HPP
10+
11+
#include <boost/crypt/hash/detail/hasher_base_512.hpp>
12+
#include <boost/crypt/hash/hasher_state.hpp>
13+
#include <boost/crypt/utility/config.hpp>
14+
#include <boost/crypt/utility/bit.hpp>
15+
#include <boost/crypt/utility/byte.hpp>
16+
#include <boost/crypt/utility/array.hpp>
17+
#include <boost/crypt/utility/cstdint.hpp>
18+
#include <boost/crypt/utility/type_traits.hpp>
19+
#include <boost/crypt/utility/strlen.hpp>
20+
#include <boost/crypt/utility/cstddef.hpp>
21+
#include <boost/crypt/utility/iterator.hpp>
22+
#include <boost/crypt/utility/file.hpp>
23+
#include <boost/crypt/utility/null.hpp>
24+
25+
#if !defined(BOOST_CRYPT_BUILD_MODULE) && !defined(BOOST_CRYPT_HAS_CUDA)
26+
#include <memory>
27+
#include <string>
28+
#include <cstdint>
29+
#include <cstring>
30+
#endif
31+
32+
namespace boost {
33+
namespace crypt {
34+
namespace hash_detail {
35+
36+
template <boost::crypt::size_t digest_size>
37+
class sha_224_256_hasher : public hasher_base_512<digest_size, 8U>
38+
{
39+
private:
40+
static_assert(digest_size == 28U || digest_size == 32U, "Digest size must be 28 (SHA224) or 32 (SHA256)");
41+
42+
using base_class = hasher_base_512<digest_size, 8U>;
43+
using base_class::intermediate_hash_;
44+
using base_class::buffer_;
45+
using base_class::buffer_index_;
46+
47+
using is_sha224 = boost::crypt::integral_constant<bool, digest_size == 28U>;
48+
49+
BOOST_CRYPT_GPU_ENABLED inline auto process_message_block() noexcept -> void override;
50+
51+
BOOST_CRYPT_GPU_ENABLED inline auto init(const boost::crypt::true_type&) noexcept -> void;
52+
53+
BOOST_CRYPT_GPU_ENABLED inline auto init(const boost::crypt::false_type&) noexcept -> void;
54+
55+
public:
56+
57+
BOOST_CRYPT_GPU_ENABLED sha_224_256_hasher() noexcept { init(); }
58+
59+
BOOST_CRYPT_GPU_ENABLED inline auto init() noexcept -> void { init(is_sha224()); }
60+
};
61+
62+
// Initial values for SHA224
63+
template <boost::crypt::size_t digest_size>
64+
auto sha_224_256_hasher<digest_size>::init(const boost::crypt::true_type&) noexcept -> void
65+
{
66+
hasher_base_512<digest_size, 8U>::base_init();
67+
68+
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
69+
intermediate_hash_[0] = 0xC1059ED8;
70+
intermediate_hash_[1] = 0x367CD507;
71+
intermediate_hash_[2] = 0x3070DD17;
72+
intermediate_hash_[3] = 0xF70E5939;
73+
intermediate_hash_[4] = 0xFFC00B31;
74+
intermediate_hash_[5] = 0x68581511;
75+
intermediate_hash_[6] = 0x64F98FA7;
76+
intermediate_hash_[7] = 0xBEFA4FA4;
77+
}
78+
79+
// Initial values for SHA256
80+
template <boost::crypt::size_t digest_size>
81+
auto sha_224_256_hasher<digest_size>::init(const boost::crypt::false_type&) noexcept -> void
82+
{
83+
hasher_base_512<digest_size, 8U>::base_init();
84+
85+
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
86+
intermediate_hash_[0] = 0x6A09E667;
87+
intermediate_hash_[1] = 0xBB67AE85;
88+
intermediate_hash_[2] = 0x3C6EF372;
89+
intermediate_hash_[3] = 0xA54FF53A;
90+
intermediate_hash_[4] = 0x510E527F;
91+
intermediate_hash_[5] = 0x9B05688C;
92+
intermediate_hash_[6] = 0x1F83D9AB;
93+
intermediate_hash_[7] = 0x5BE0CD19;
94+
}
95+
96+
namespace sha256_detail {
97+
98+
#ifndef BOOST_CRYPT_HAS_CUDA
99+
BOOST_CRYPT_INLINE_CONSTEXPR boost::crypt::array<boost::crypt::uint32_t, 64> sha256_k = {
100+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
101+
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
102+
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
103+
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
104+
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
105+
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
106+
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
107+
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
108+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
109+
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
110+
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
111+
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
112+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
113+
};
114+
#endif
115+
116+
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
117+
// See section 4.1.2
118+
BOOST_CRYPT_GPU_ENABLED inline auto big_sigma0(const boost::crypt::uint32_t value) noexcept -> boost::crypt::uint32_t
119+
{
120+
return detail::rotr(value, 2U) ^ detail::rotr(value, 13U) ^ detail::rotr(value, 22U);
121+
}
122+
123+
BOOST_CRYPT_GPU_ENABLED inline auto big_sigma1(const boost::crypt::uint32_t value) noexcept -> boost::crypt::uint32_t
124+
{
125+
return detail::rotr(value, 6U) ^ detail::rotr(value, 11U) ^ detail::rotr(value, 25U);
126+
}
127+
128+
BOOST_CRYPT_GPU_ENABLED inline auto little_sigma0(const boost::crypt::uint32_t value) noexcept -> boost::crypt::uint32_t
129+
{
130+
return detail::rotr(value, 7U) ^ detail::rotr(value, 18U) ^ (value >> 3U);
131+
}
132+
133+
BOOST_CRYPT_GPU_ENABLED inline auto little_sigma1(const boost::crypt::uint32_t value) noexcept -> boost::crypt::uint32_t
134+
{
135+
return detail::rotr(value, 17U) ^ detail::rotr(value, 19U) ^ (value >> 10U);
136+
}
137+
138+
BOOST_CRYPT_GPU_ENABLED inline auto sha_ch(const boost::crypt::uint32_t x, const boost::crypt::uint32_t y, const boost::crypt::uint32_t z) noexcept -> boost::crypt::uint32_t
139+
{
140+
return (x & y) ^ ((~x) & z);
141+
}
142+
143+
BOOST_CRYPT_GPU_ENABLED inline auto sha_maj(const boost::crypt::uint32_t x, const boost::crypt::uint32_t y, const boost::crypt::uint32_t z) noexcept -> boost::crypt::uint32_t
144+
{
145+
return (x & y) ^ (x & z) ^ (y & z);
146+
}
147+
148+
} // Namespace sha256_detail
149+
150+
// See definitions from the RFC on the rounds
151+
template <boost::crypt::size_t digest_size>
152+
auto sha_224_256_hasher<digest_size>::process_message_block() noexcept -> void
153+
{
154+
// On the host we prefer this array to be static but,
155+
// in a CUDA environment it solves linking problems to move into the function
156+
157+
#ifdef BOOST_CRYPT_HAS_CUDA
158+
constexpr boost::crypt::uint32_t sha256_k[64] = {
159+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
160+
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
161+
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
162+
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
163+
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
164+
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
165+
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
166+
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
167+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
168+
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
169+
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
170+
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
171+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
172+
};
173+
#endif
174+
175+
using namespace sha256_detail;
176+
boost::crypt::array<boost::crypt::uint32_t, 64> W {};
177+
178+
// Init the first 16 words of W
179+
for (boost::crypt::size_t i {}; i < 16UL; ++i)
180+
{
181+
W[i] = (static_cast<boost::crypt::uint32_t>(buffer_[i * 4U]) << 24U) |
182+
(static_cast<boost::crypt::uint32_t>(buffer_[i * 4U + 1U]) << 16U) |
183+
(static_cast<boost::crypt::uint32_t>(buffer_[i * 4U + 2U]) << 8U) |
184+
(static_cast<boost::crypt::uint32_t>(buffer_[i * 4U + 3U]));
185+
186+
}
187+
188+
for (boost::crypt::size_t i {16U}; i < W.size(); ++i)
189+
{
190+
W[i] = little_sigma1(W[i - 2U]) + W[i - 7U] +
191+
little_sigma0(W[i - 15U]) + W[i - 16U];
192+
}
193+
194+
auto A {intermediate_hash_[0]};
195+
auto B {intermediate_hash_[1]};
196+
auto C {intermediate_hash_[2]};
197+
auto D {intermediate_hash_[3]};
198+
auto E {intermediate_hash_[4]};
199+
auto F {intermediate_hash_[5]};
200+
auto G {intermediate_hash_[6]};
201+
auto H {intermediate_hash_[7]};
202+
203+
for (boost::crypt::size_t i {}; i < W.size(); ++i)
204+
{
205+
const auto temp1 {H + big_sigma1(E) + sha_ch(E, F, G) + sha256_k[i] + W[i]};
206+
const auto temp2 {big_sigma0(A) + sha_maj(A, B, C)};
207+
208+
H = G;
209+
G = F;
210+
F = E;
211+
E = D + temp1;
212+
D = C;
213+
C = B;
214+
B = A;
215+
A = temp1 + temp2;
216+
}
217+
218+
intermediate_hash_[0] += A;
219+
intermediate_hash_[1] += B;
220+
intermediate_hash_[2] += C;
221+
intermediate_hash_[3] += D;
222+
intermediate_hash_[4] += E;
223+
intermediate_hash_[5] += F;
224+
intermediate_hash_[6] += G;
225+
intermediate_hash_[7] += H;
226+
227+
buffer_index_ = 0U;
228+
}
229+
230+
} // namespace hash_detail
231+
} // namespace crypt
232+
} // namespace boost
233+
234+
#endif // BOOST_CRYPT_HASH_DETAIL_SHA224_256_HASHER_HPP

0 commit comments

Comments
 (0)