-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41 from cppalliance/sha224
Add implementation for SHA224
- Loading branch information
Showing
17 changed files
with
2,174 additions
and
181 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright 2024 Matt Borland | ||
// Distributed under the Boost Software License, Version 1.0. | ||
// https://www.boost.org/LICENSE_1_0.txt | ||
|
||
#include <boost/crypt/hash/sha224.hpp> | ||
#include <iostream> | ||
#include <exception> | ||
#include <string> | ||
|
||
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size) | ||
{ | ||
try | ||
{ | ||
auto c_data = reinterpret_cast<const char*>(data); | ||
std::string c_data_str {c_data, size}; // Guarantee null termination since we can't pass the size argument | ||
|
||
boost::crypt::sha224(c_data_str); | ||
boost::crypt::sha224(c_data, size); | ||
boost::crypt::sha224(data, size); | ||
|
||
#ifdef BOOST_CRYPT_HAS_STRING_VIEW | ||
std::string_view view {c_data_str}; | ||
boost::crypt::sha224(view); | ||
#endif | ||
|
||
#ifdef BOOST_CRYPT_HAS_SPAN | ||
std::span data_span {c_data, size}; | ||
boost::crypt::sha224(data_span); | ||
#endif | ||
|
||
// Fuzz the hasher object | ||
boost::crypt::sha224_hasher hasher; | ||
hasher.process_bytes(data, size); | ||
hasher.process_bytes(data, size); | ||
hasher.process_bytes(data, size); | ||
hasher.get_digest(); | ||
hasher.process_bytes(data, size); // State is invalid but should not crash | ||
} | ||
catch(...) | ||
{ | ||
std::cerr << "Error with: " << data << std::endl; | ||
std::terminate(); | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
"The quick brown fox jumps over the lazy dog" | ||
"The quick brown fox jumps over the lazy dog." | ||
"" | ||
"aB3$x9Yz" | ||
"12345" | ||
"!@#$%^&*()" | ||
"FuzzTest123" | ||
" " | ||
"Lorem ipsum dolor sit amet" | ||
"a" | ||
"9876543210" | ||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
"ñÑáéíóúÁÉÍÓÚ" | ||
"\n\r\t" | ||
"0" | ||
"ThisIsAVeryLongStringWithNoSpacesOrPunctuationToTestEdgeCases" | ||
"<?php echo 'test'; ?>" | ||
"SELECT * FROM users;" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
// Copyright 2024 Matt Borland | ||
// Distributed under the Boost Software License, Version 1.0. | ||
// https://www.boost.org/LICENSE_1_0.txt | ||
// | ||
// See: https://datatracker.ietf.org/doc/html/rfc4634 | ||
// See: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf | ||
|
||
#ifndef BOOST_CRYPT_HASH_DETAIL_SHA224_256_HASHER_HPP | ||
#define BOOST_CRYPT_HASH_DETAIL_SHA224_256_HASHER_HPP | ||
|
||
#include <boost/crypt/hash/detail/hasher_base_512.hpp> | ||
#include <boost/crypt/hash/hasher_state.hpp> | ||
#include <boost/crypt/utility/config.hpp> | ||
#include <boost/crypt/utility/bit.hpp> | ||
#include <boost/crypt/utility/byte.hpp> | ||
#include <boost/crypt/utility/array.hpp> | ||
#include <boost/crypt/utility/cstdint.hpp> | ||
#include <boost/crypt/utility/type_traits.hpp> | ||
#include <boost/crypt/utility/strlen.hpp> | ||
#include <boost/crypt/utility/cstddef.hpp> | ||
#include <boost/crypt/utility/iterator.hpp> | ||
#include <boost/crypt/utility/file.hpp> | ||
#include <boost/crypt/utility/null.hpp> | ||
|
||
#if !defined(BOOST_CRYPT_BUILD_MODULE) && !defined(BOOST_CRYPT_HAS_CUDA) | ||
#include <memory> | ||
#include <string> | ||
#include <cstdint> | ||
#include <cstring> | ||
#endif | ||
|
||
namespace boost { | ||
namespace crypt { | ||
namespace hash_detail { | ||
|
||
template <boost::crypt::size_t digest_size> | ||
class sha_224_256_hasher : public hasher_base_512<digest_size, 8U> | ||
{ | ||
private: | ||
static_assert(digest_size == 28U || digest_size == 32U, "Digest size must be 28 (SHA224) or 32 (SHA256)"); | ||
|
||
using base_class = hasher_base_512<digest_size, 8U>; | ||
using base_class::intermediate_hash_; | ||
using base_class::buffer_; | ||
using base_class::buffer_index_; | ||
|
||
using is_sha224 = boost::crypt::integral_constant<bool, digest_size == 28U>; | ||
|
||
BOOST_CRYPT_GPU_ENABLED inline auto process_message_block() noexcept -> void override; | ||
|
||
BOOST_CRYPT_GPU_ENABLED inline auto init(const boost::crypt::true_type&) noexcept -> void; | ||
|
||
BOOST_CRYPT_GPU_ENABLED inline auto init(const boost::crypt::false_type&) noexcept -> void; | ||
|
||
public: | ||
|
||
BOOST_CRYPT_GPU_ENABLED sha_224_256_hasher() noexcept { init(); } | ||
|
||
BOOST_CRYPT_GPU_ENABLED inline auto init() noexcept -> void { init(is_sha224()); } | ||
}; | ||
|
||
// Initial values for SHA224 | ||
template <boost::crypt::size_t digest_size> | ||
auto sha_224_256_hasher<digest_size>::init(const boost::crypt::true_type&) noexcept -> void | ||
{ | ||
hasher_base_512<digest_size, 8U>::base_init(); | ||
|
||
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf | ||
intermediate_hash_[0] = 0xC1059ED8; | ||
intermediate_hash_[1] = 0x367CD507; | ||
intermediate_hash_[2] = 0x3070DD17; | ||
intermediate_hash_[3] = 0xF70E5939; | ||
intermediate_hash_[4] = 0xFFC00B31; | ||
intermediate_hash_[5] = 0x68581511; | ||
intermediate_hash_[6] = 0x64F98FA7; | ||
intermediate_hash_[7] = 0xBEFA4FA4; | ||
} | ||
|
||
// Initial values for SHA256 | ||
template <boost::crypt::size_t digest_size> | ||
auto sha_224_256_hasher<digest_size>::init(const boost::crypt::false_type&) noexcept -> void | ||
{ | ||
hasher_base_512<digest_size, 8U>::base_init(); | ||
|
||
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf | ||
intermediate_hash_[0] = 0x6A09E667; | ||
intermediate_hash_[1] = 0xBB67AE85; | ||
intermediate_hash_[2] = 0x3C6EF372; | ||
intermediate_hash_[3] = 0xA54FF53A; | ||
intermediate_hash_[4] = 0x510E527F; | ||
intermediate_hash_[5] = 0x9B05688C; | ||
intermediate_hash_[6] = 0x1F83D9AB; | ||
intermediate_hash_[7] = 0x5BE0CD19; | ||
} | ||
|
||
namespace sha256_detail { | ||
|
||
#ifndef BOOST_CRYPT_HAS_CUDA | ||
BOOST_CRYPT_INLINE_CONSTEXPR boost::crypt::array<boost::crypt::uint32_t, 64> sha256_k = { | ||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, | ||
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, | ||
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, | ||
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, | ||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, | ||
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, | ||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, | ||
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, | ||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, | ||
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, | ||
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, | ||
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, | ||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 | ||
}; | ||
#endif | ||
|
||
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf | ||
// See section 4.1.2 | ||
BOOST_CRYPT_GPU_ENABLED inline auto big_sigma0(const boost::crypt::uint32_t value) noexcept -> boost::crypt::uint32_t | ||
{ | ||
return detail::rotr(value, 2U) ^ detail::rotr(value, 13U) ^ detail::rotr(value, 22U); | ||
} | ||
|
||
BOOST_CRYPT_GPU_ENABLED inline auto big_sigma1(const boost::crypt::uint32_t value) noexcept -> boost::crypt::uint32_t | ||
{ | ||
return detail::rotr(value, 6U) ^ detail::rotr(value, 11U) ^ detail::rotr(value, 25U); | ||
} | ||
|
||
BOOST_CRYPT_GPU_ENABLED inline auto little_sigma0(const boost::crypt::uint32_t value) noexcept -> boost::crypt::uint32_t | ||
{ | ||
return detail::rotr(value, 7U) ^ detail::rotr(value, 18U) ^ (value >> 3U); | ||
} | ||
|
||
BOOST_CRYPT_GPU_ENABLED inline auto little_sigma1(const boost::crypt::uint32_t value) noexcept -> boost::crypt::uint32_t | ||
{ | ||
return detail::rotr(value, 17U) ^ detail::rotr(value, 19U) ^ (value >> 10U); | ||
} | ||
|
||
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 | ||
{ | ||
return (x & y) ^ ((~x) & z); | ||
} | ||
|
||
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 | ||
{ | ||
return (x & y) ^ (x & z) ^ (y & z); | ||
} | ||
|
||
} // Namespace sha256_detail | ||
|
||
// See definitions from the RFC on the rounds | ||
template <boost::crypt::size_t digest_size> | ||
auto sha_224_256_hasher<digest_size>::process_message_block() noexcept -> void | ||
{ | ||
// On the host we prefer this array to be static but, | ||
// in a CUDA environment it solves linking problems to move into the function | ||
|
||
#ifdef BOOST_CRYPT_HAS_CUDA | ||
constexpr boost::crypt::uint32_t sha256_k[64] = { | ||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, | ||
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, | ||
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, | ||
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, | ||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, | ||
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, | ||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, | ||
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, | ||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, | ||
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, | ||
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, | ||
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, | ||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 | ||
}; | ||
#endif | ||
|
||
using namespace sha256_detail; | ||
boost::crypt::array<boost::crypt::uint32_t, 64> W {}; | ||
|
||
// Init the first 16 words of W | ||
for (boost::crypt::size_t i {}; i < 16UL; ++i) | ||
{ | ||
W[i] = (static_cast<boost::crypt::uint32_t>(buffer_[i * 4U]) << 24U) | | ||
(static_cast<boost::crypt::uint32_t>(buffer_[i * 4U + 1U]) << 16U) | | ||
(static_cast<boost::crypt::uint32_t>(buffer_[i * 4U + 2U]) << 8U) | | ||
(static_cast<boost::crypt::uint32_t>(buffer_[i * 4U + 3U])); | ||
|
||
} | ||
|
||
for (boost::crypt::size_t i {16U}; i < W.size(); ++i) | ||
{ | ||
W[i] = little_sigma1(W[i - 2U]) + W[i - 7U] + | ||
little_sigma0(W[i - 15U]) + W[i - 16U]; | ||
} | ||
|
||
auto A {intermediate_hash_[0]}; | ||
auto B {intermediate_hash_[1]}; | ||
auto C {intermediate_hash_[2]}; | ||
auto D {intermediate_hash_[3]}; | ||
auto E {intermediate_hash_[4]}; | ||
auto F {intermediate_hash_[5]}; | ||
auto G {intermediate_hash_[6]}; | ||
auto H {intermediate_hash_[7]}; | ||
|
||
for (boost::crypt::size_t i {}; i < W.size(); ++i) | ||
{ | ||
const auto temp1 {H + big_sigma1(E) + sha_ch(E, F, G) + sha256_k[i] + W[i]}; | ||
const auto temp2 {big_sigma0(A) + sha_maj(A, B, C)}; | ||
|
||
H = G; | ||
G = F; | ||
F = E; | ||
E = D + temp1; | ||
D = C; | ||
C = B; | ||
B = A; | ||
A = temp1 + temp2; | ||
} | ||
|
||
intermediate_hash_[0] += A; | ||
intermediate_hash_[1] += B; | ||
intermediate_hash_[2] += C; | ||
intermediate_hash_[3] += D; | ||
intermediate_hash_[4] += E; | ||
intermediate_hash_[5] += F; | ||
intermediate_hash_[6] += G; | ||
intermediate_hash_[7] += H; | ||
|
||
buffer_index_ = 0U; | ||
} | ||
|
||
} // namespace hash_detail | ||
} // namespace crypt | ||
} // namespace boost | ||
|
||
#endif // BOOST_CRYPT_HASH_DETAIL_SHA224_256_HASHER_HPP |
Oops, something went wrong.