Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finish sha1 nist cavs testing #22

Merged
merged 8 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions include/boost/crypt/hash/sha1.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,6 @@ namespace crypt {

class sha1_hasher
{
private:

boost::crypt::array<boost::crypt::uint32_t, 5> intermediate_hash_ {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};
boost::crypt::array<boost::crypt::uint8_t, 64> buffer_ {};

boost::crypt::size_t buffer_index_ {};
boost::crypt::size_t low_ {};
boost::crypt::size_t high_ {};

bool computed {};
bool corrupted {};

BOOST_CRYPT_GPU_ENABLED constexpr auto sha1_process_message_block() -> void;

template <typename ForwardIter>
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1_update(ForwardIter data, boost::crypt::size_t size) noexcept -> hasher_state;

BOOST_CRYPT_GPU_ENABLED constexpr auto pad_message() noexcept -> void;

public:

using return_type = boost::crypt::array<boost::crypt::uint8_t, 20>;
Expand All @@ -71,6 +52,25 @@ class sha1_hasher


BOOST_CRYPT_GPU_ENABLED constexpr auto get_digest() noexcept -> return_type ;

private:

boost::crypt::array<boost::crypt::uint32_t, 5> intermediate_hash_ { UINT32_C(0x67452301), UINT32_C(0xEFCDAB89), UINT32_C(0x98BADCFE), UINT32_C(0x10325476), UINT32_C(0xC3D2E1F0) };
ckormanyos marked this conversation as resolved.
Show resolved Hide resolved
boost::crypt::array<boost::crypt::uint8_t, 64> buffer_ {};

boost::crypt::size_t buffer_index_ {};
boost::crypt::size_t low_ {};
boost::crypt::size_t high_ {};

bool computed {};
bool corrupted {};

BOOST_CRYPT_GPU_ENABLED constexpr auto sha1_process_message_block() -> void;

template <typename ForwardIter>
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1_update(ForwardIter data, boost::crypt::size_t size) noexcept -> hasher_state;

BOOST_CRYPT_GPU_ENABLED constexpr auto pad_message() noexcept -> void;
};

namespace detail {
Expand Down
1 change: 1 addition & 0 deletions test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ project : requirements

run quick.cpp ;
run test_md5.cpp ;
run test_nist_cavs_sha1_monte.cpp ;
run test_nist_cavs_sha1_short_long.cpp ;
run test_sha1.cpp ;
Binary file added test/nist_cavs/vectors/shavs.pdf
Binary file not shown.
191 changes: 188 additions & 3 deletions test/test_nist_cavs_detail.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ struct test_object_hash

test_object_hash() = delete;

// Construct hash test object with result only (no message and no length).
explicit test_object_hash(const std::string& str_result)
: my_result
{
[&str_result]()
{
const auto byte_data { detail::convert_hex_string_to_byte_container(str_result) };
return message_type(byte_data.cbegin(), byte_data.cend());
}()
}
{ }

// Construct hash test object with all of message, length and result.
explicit test_object_hash(const std::string& str_data, const std::string& str_result)
: my_length { str_data.size() / static_cast<size_type>(UINT8_C(2)) },
my_msg
Expand All @@ -61,7 +74,7 @@ struct test_object_hash
[&str_result]()
{
const auto byte_data { detail::convert_hex_string_to_byte_container(str_result) };
return message_type(byte_data.cbegin(), byte_data.cend());
return message_type(byte_data.cbegin(), byte_data.cend());
}()
}
{ }
Expand All @@ -73,7 +86,7 @@ struct test_object_hash

using test_vector_container_type = std::deque<test_object_hash>;

auto where_file(const std::string& test_vectors_filename) -> std::string
auto where_file_shabytesvectors(const std::string& test_vectors_filename) -> std::string
{
// Try to open the file in each of the known relative paths
// in order to find out where it is located.
Expand Down Expand Up @@ -159,10 +172,12 @@ auto parse_file_vectors(const std::string& test_vectors_filename, test_vector_co
{
bool result_parse_is_ok { false };

const std::string test_vectors_filename_relative { where_file(test_vectors_filename) };
const std::string test_vectors_filename_relative { where_file_shabytesvectors(test_vectors_filename) };

const bool result_filename_plausible_is_ok { (!test_vectors_filename_relative.empty()) };

BOOST_TEST(result_filename_plausible_is_ok);

if(result_filename_plausible_is_ok)
{
std::string str_message { };
Expand Down Expand Up @@ -232,6 +247,77 @@ auto parse_file_vectors(const std::string& test_vectors_filename, test_vector_co
}
}

BOOST_TEST(result_parse_is_ok);

return result_parse_is_ok;
}

auto parse_file_monte(const std::string& test_monte_filename, test_vector_container_type& test_vectors_to_get) -> bool
{
bool result_parse_is_ok { false };

const std::string test_vectors_filename_relative { where_file_shabytesvectors(test_monte_filename) };

const bool result_filename_plausible_is_ok { (!test_vectors_filename_relative.empty()) };

BOOST_TEST(result_filename_plausible_is_ok);

if(result_filename_plausible_is_ok)
{
std::string str_result { };

// Read the file for creating the test cases.
std::ifstream in(test_vectors_filename_relative.c_str());

const bool file_is_open = in.is_open();

unsigned count { };

if(file_is_open)
{
result_parse_is_ok = true;

std::string line { };
std::string result { };

while(getline(in, line))
{
const std::string::size_type pos_cnt = line.find("COUNT =", 0U);
const std::string::size_type pos_md = line.find("MD =", 0U);

const bool line_is_representation_is_cnt = (pos_cnt != std::string::npos);
const bool line_is_representation_is_md = (pos_md != std::string::npos);

// Get the next count.
if(line_is_representation_is_cnt)
{
const std::string str_cnt = line.substr(8U, line.length() - 8U);

const unsigned long count_from_file = std::strtoul(str_cnt.c_str(), nullptr, 10U);

count = static_cast<unsigned>(count_from_file);
}

// Get the next (expected) result.
if(line_is_representation_is_md)
{
result = line.substr(5U, line.length() - 5U);

// Add the new test object to v.
const test_object_hash test_obj(result);

test_vectors_to_get.push_back(test_obj);
}
}

in.close();

result_parse_is_ok = ((!test_vectors_to_get.empty()) && (count == 99U) && result_parse_is_ok);
}
}

BOOST_TEST(result_parse_is_ok);

return result_parse_is_ok;
}

Expand All @@ -246,6 +332,8 @@ auto test_vectors_oneshot(const test_vector_container_type& test_vectors) -> boo
using local_hasher_type = HasherType;
using local_result_type = typename local_hasher_type::return_type;

BOOST_TEST((!test_vectors.empty()));

bool result_is_ok { true };

for(const auto& test_vector : test_vectors)
Expand All @@ -267,6 +355,9 @@ auto test_vectors_oneshot(const test_vector_container_type& test_vectors) -> boo

// Make pass 2 through the messages.
// Use the triple-combination of init/process/get-result functions.
// Even though this is not required in CAVS testing, it is
// done in order to ensure that the init() function properly
// puts the hasher-object into its initialized state.

this_hash.init();

Expand All @@ -287,6 +378,100 @@ auto test_vectors_oneshot(const test_vector_container_type& test_vectors) -> boo
return result_is_ok;
}

template<typename HasherType>
auto test_vectors_monte(const nist::cavs::test_vector_container_type& test_vectors_monte) -> bool
{
using local_hasher_type = HasherType;
using local_result_type = typename local_hasher_type::return_type;

using local_array_type = local_result_type;

// TODO: ckormanyos this is for sha1 only. Use generic programming for the Seed.
local_array_type
Seed
(
{
0xDDU, 0x4DU, 0xF6U, 0x44U, 0xEAU, 0xF3U, 0xD8U, 0x5BU,
0xACU, 0xE2U, 0xB2U, 0x1AU, 0xCCU, 0xAAU, 0x22U, 0xB2U,
0x88U, 0x21U, 0xF5U, 0xCDU
}
);

constexpr local_array_type dummy_array { };

local_array_type MD[3U] { { }, { }, { } };

local_array_type MDi { };
local_array_type MDj { };

bool result_is_ok { (!test_vectors_monte.empty()) };

if(result_is_ok)
{
// See pseudocode on page 9 of "The Secure Hash Algorithm Validation System (SHAVS)".

for(std::size_t j { }; j < 100U; ++j)
{
MD[0U] = MD[1U] = MD[2U] = Seed;

for(std::size_t i { 3U } ; i < 1003U; ++i)
{
using local_wide_array_type = boost::crypt::array<std::uint8_t, dummy_array.size() * 3U>;

const local_wide_array_type Mi =
[&MD]()
{
std::vector<std::uint8_t> result_vector { };

result_vector.reserve(dummy_array.size() * 3U);

result_vector.insert(result_vector.end(), MD[0U].cbegin(), MD[0U].cend());
result_vector.insert(result_vector.end(), MD[1U].cbegin(), MD[1U].cend());
result_vector.insert(result_vector.end(), MD[2U].cbegin(), MD[2U].cend());

local_wide_array_type result { };

std::copy(result_vector.cbegin(), result_vector.cend(), result.begin());

return result;
}();

MDi =
[&Mi]()
{
local_hasher_type this_hash { };

this_hash.init();

this_hash.process_bytes(Mi.data(), Mi.size());

return this_hash.get_digest();
}();

MD[0U] = MD[1U];
MD[1U] = MD[2U];
MD[2U] = MDi;
}

MDj = Seed = MDi;

const bool result_this_monte_step_is_ok =
std::equal
(
MDj.cbegin(),
MDj.cend(),
test_vectors_monte[j].my_result.cbegin()
);

result_is_ok = (result_this_monte_step_is_ok && result_is_ok);

BOOST_TEST(result_this_monte_step_is_ok);
}
}

return result_is_ok;
}

} // namespace cavs
} // namespace nist

Expand Down
25 changes: 25 additions & 0 deletions test/test_nist_cavs_sha1_monte.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2024 Matt Borland
// Copyright 2024 Christopher Kormanyos
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/crypt/hash/sha1.hpp>

#include "test_nist_cavs_detail.hpp"

auto main() -> int
{
bool result_is_ok { true };

{
nist::cavs::test_vector_container_type my_test_vectors_monte { };

static_cast<void>(nist::cavs::detail::parse_file_monte("SHA1Monte.rsp", my_test_vectors_monte));

result_is_ok = (nist::cavs::test_vectors_monte<boost::crypt::sha1_hasher>(my_test_vectors_monte) && result_is_ok);

BOOST_TEST(result_is_ok);
}

return boost::report_errors();
}
4 changes: 2 additions & 2 deletions test/test_nist_cavs_sha1_short_long.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include "test_nist_cavs_detail.hpp"

#include <boost/crypt/hash/sha1.hpp>

#include "test_nist_cavs_detail.hpp"

auto main() -> int
{
bool result_is_ok { true };
Expand Down
Loading