Cut a release.
This commit is contained in:
parent
ad07da5a39
commit
4a2c18751a
|
@ -1,7 +1,8 @@
|
||||||
|
HeaderFilterRegex: \./.+
|
||||||
|
|
||||||
Checks: >-
|
Checks: >-
|
||||||
bugprone-*,
|
bugprone-*,
|
||||||
cppcoreguidelines-*,
|
cppcoreguidelines-*,
|
||||||
google-*,
|
|
||||||
misc-*,
|
misc-*,
|
||||||
modernize-*,
|
modernize-*,
|
||||||
performance-*,
|
performance-*,
|
||||||
|
@ -15,6 +16,7 @@ Checks: >-
|
||||||
-cppcoreguidelines-pro-type-vararg,
|
-cppcoreguidelines-pro-type-vararg,
|
||||||
-google-readability-braces-around-statements,
|
-google-readability-braces-around-statements,
|
||||||
-google-readability-function-size,
|
-google-readability-function-size,
|
||||||
|
-google-readability-namespace-comments,
|
||||||
-misc-no-recursion,
|
-misc-no-recursion,
|
||||||
-modernize-return-braced-init-list,
|
-modernize-return-braced-init-list,
|
||||||
-modernize-use-nodiscard,
|
-modernize-use-nodiscard,
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
<inspection_tool class="ClangTidy" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="ClangTidy" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="Misra" enabled="false" level="WARNING" enabled_by_default="false">
|
<inspection_tool class="Misra" enabled="true" level="WARNING" enabled_by_default="false">
|
||||||
<scope name="ProjectSources" level="WARNING" enabled="false" />
|
<scope name="ProjectSources" level="WARNING" enabled="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.22)
|
cmake_minimum_required(VERSION 3.22)
|
||||||
project(emsha
|
project(emsha
|
||||||
VERSION 1.0.3
|
VERSION 1.1.0
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
DESCRIPTION "A compact HMAC-SHA-256 C++11 library.")
|
DESCRIPTION "A compact HMAC-SHA-256 C++11 library.")
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
@ -9,8 +9,14 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
set(EMSHA_NO_HEXSTRING OFF CACHE BOOL
|
set(EMSHA_NO_HEXSTRING OFF CACHE BOOL
|
||||||
"Don't include support for hex strings.")
|
"Don't include support for hex strings.")
|
||||||
set(EMSHA_NO_HEXLUT OFF CACHE BOOL
|
if (EMSHA_NO_HEXSTRING)
|
||||||
|
add_definitions(EMSHA_NO_HEXSTRING)
|
||||||
|
endif ()
|
||||||
|
set(SET_EMSHA_NO_HEXLUT OFF CACHE BOOL
|
||||||
"Don't use a LUT for hex strings (saves ~256B of memory).")
|
"Don't use a LUT for hex strings (saves ~256B of memory).")
|
||||||
|
if (SET_EMSHA_NO_HEXLUT)
|
||||||
|
add_definitions("-DEMSHA_NO_HEXLUT")
|
||||||
|
endif ()
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
|
@ -24,13 +24,13 @@ if (${DOXYGEN_FOUND})
|
||||||
set(DOXYGEN_GENERATE_LATEX YES)
|
set(DOXYGEN_GENERATE_LATEX YES)
|
||||||
set(DOXYGEN_EXTRACT_ALL YES)
|
set(DOXYGEN_EXTRACT_ALL YES)
|
||||||
set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "${CMAKE_CURRENT_SOURCE_DIR}/docs/mainpage.md")
|
set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "${CMAKE_CURRENT_SOURCE_DIR}/docs/mainpage.md")
|
||||||
|
set(DOXYGEN_EXCLUDE_PATTERNS "test_*" "*.cc" )
|
||||||
message(STATUS "Doxygen found, building docs.")
|
message(STATUS "Doxygen found, building docs.")
|
||||||
|
|
||||||
doxygen_add_docs(${PROJECT_NAME}_docs
|
doxygen_add_docs(${PROJECT_NAME}_docs
|
||||||
${HEADER_FILES}
|
${HEADER_FILES}
|
||||||
${SOURCE_FILES}
|
ALL
|
||||||
USE_STAMP_FILE)
|
USE_STAMP_FILE)
|
||||||
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_docs)
|
|
||||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
|
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/latex
|
${CMAKE_CURRENT_BINARY_DIR}/latex
|
||||||
DESTINATION share/doc/${PROJECT_NAME}/doxygen)
|
DESTINATION share/doc/${PROJECT_NAME}/doxygen)
|
||||||
|
|
|
@ -77,50 +77,50 @@ satisfy a common interface :cpp`Hash`{.interpreted-text role="class"}.
|
||||||
All functionality provided by this library is found under the `emsha`
|
All functionality provided by this library is found under the `emsha`
|
||||||
namespace.
|
namespace.
|
||||||
|
|
||||||
### `EMSHA_RESULT`
|
### `EMSHAResult`
|
||||||
|
|
||||||
The `EMSHA_RESULT` enum is used to convey the result of an operation.
|
The `EMSHAResult` enum is used to convey the result of an operation.
|
||||||
The possible values are:
|
The possible values are:
|
||||||
|
|
||||||
// All operations have completed successfully so far.
|
// All operations have completed successfully so far.
|
||||||
EMSHA_ROK = 0,
|
EMSHAResult::OK = 0,
|
||||||
|
|
||||||
// A self test or unit test failed.
|
// A self test or unit test failed.
|
||||||
EMSHA_TEST_FAILURE = 1,
|
EMSHAResult::TestFailure = 1,
|
||||||
|
|
||||||
// A null pointer was passed in as a buffer where it
|
// A null pointer was passed in as a buffer where it
|
||||||
// shouldn't have been.
|
// shouldn't have been.
|
||||||
EMSHA_NULLPTR = 2,
|
EMSHAResult::NullPointer = 2,
|
||||||
|
|
||||||
// The Hash is in an invalid state.
|
// The Hash is in an invalid state.
|
||||||
EMSHA_INVALID_STATE = 3,
|
EMSHAResult::InvalidState = 3,
|
||||||
|
|
||||||
// The input to SHA256::update is too large.
|
// The input to SHA256::update is too large.
|
||||||
SHA256_INPUT_TOO_LONG = 4,
|
EMSHAResult::InputTooLong = 4,
|
||||||
|
|
||||||
// The self tests have been disabled, but a self test
|
// The self tests have been disabled, but a self test
|
||||||
// function was called.
|
// function was called.
|
||||||
EMSHA_SELFTEST_DISABLED = 5
|
EMSHAResult::SelfTestDisabled = 5
|
||||||
|
|
||||||
As a convenience, the following `typedef` is also provided.
|
As a convenience, the following `typedef` is also provided.
|
||||||
|
|
||||||
> `typedef enum _EMSHA_RESULT_` :cpp`EMSHA_RESULT`{.interpreted-text
|
> `typedef enum _EMSHA_RESULT_` :cpp`EMSHAResult`{.interpreted-text
|
||||||
> role="type"}
|
> role="type"}
|
||||||
|
|
||||||
## The Hash interface
|
## The Hash interface
|
||||||
|
|
||||||
In general, a [Hash]{.title-ref} is used along the lines of: :
|
In general, a [Hash]{.title-ref} is used along the lines of: :
|
||||||
|
|
||||||
emsha::EMSHA_RESULT
|
emsha::EMSHAResult
|
||||||
hash_single_pass(uint8_t *m, uint32_t ml, uint8_t *digest)
|
hash_single_pass(uint8_t *m, uint32_t ml, uint8_t *digest)
|
||||||
{
|
{
|
||||||
// Depending on the implementation, the constructor may need
|
// Depending on the implementation, the constructor may need
|
||||||
// arguments.
|
// arguments.
|
||||||
emsha::Hash h;
|
emsha::Hash h;
|
||||||
emsha::EMSHA_RESULT res;
|
emsha::EMSHAResult res;
|
||||||
|
|
||||||
res = h.write(m, ml);
|
res = h.write(m, ml);
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
emsha.cc
8
emsha.cc
|
@ -55,10 +55,13 @@ HashEqual(const uint8_t *a, const uint8_t *b)
|
||||||
|
|
||||||
|
|
||||||
#ifndef EMSHA_NO_HEXSTRING
|
#ifndef EMSHA_NO_HEXSTRING
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
#ifndef EMSHA_NO_HEXLUT
|
#ifndef EMSHA_NO_HEXLUT
|
||||||
// If using a lookup table is permitted, then the faster way to do this
|
// If using a lookup table is permitted, then the faster way to do this
|
||||||
// is to use one.
|
// is to use one.
|
||||||
static void
|
void
|
||||||
writeHexChar(uint8_t *dest, uint8_t src)
|
writeHexChar(uint8_t *dest, uint8_t src)
|
||||||
{
|
{
|
||||||
static constexpr uint8_t lut[256][3] = {
|
static constexpr uint8_t lut[256][3] = {
|
||||||
|
@ -106,7 +109,7 @@ writeHexChar(uint8_t *dest, uint8_t src)
|
||||||
// memory constraints, we'll work around this using a small (16-byte)
|
// memory constraints, we'll work around this using a small (16-byte)
|
||||||
// lookup table and some bit shifting. On platforms where even this is
|
// lookup table and some bit shifting. On platforms where even this is
|
||||||
// too much, the HexString functionality will just be disabled.
|
// too much, the HexString functionality will just be disabled.
|
||||||
static void
|
void
|
||||||
writeHexChar(uint8_t *dest, uint8_t src)
|
writeHexChar(uint8_t *dest, uint8_t src)
|
||||||
{
|
{
|
||||||
static constexpr uint8_t lut[] = {
|
static constexpr uint8_t lut[] = {
|
||||||
|
@ -118,6 +121,7 @@ writeHexChar(uint8_t *dest, uint8_t src)
|
||||||
*(dest + 1) = lut[(src & 0xF)];
|
*(dest + 1) = lut[(src & 0xF)];
|
||||||
}
|
}
|
||||||
#endif // #ifndef EMSHA_NO_HEXLUT
|
#endif // #ifndef EMSHA_NO_HEXLUT
|
||||||
|
} // anonymous namespace for writeHexChar
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
126
emsha/emsha.h
126
emsha/emsha.h
|
@ -35,11 +35,10 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
// Emsha is an EMbedded Secure HAshing interface.
|
// emsha is an EMbedded Secure HAshing interface.
|
||||||
namespace emsha {
|
namespace emsha {
|
||||||
|
|
||||||
|
|
||||||
/// EMSHA_CHECK is used for sanity checks in certain parts of the code.
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
/// EMSHA_CHECK is used for sanity checks in certain parts of
|
/// EMSHA_CHECK is used for sanity checks in certain parts of
|
||||||
/// the code. If asserts are turned off, expand the check to an
|
/// the code. If asserts are turned off, expand the check to an
|
||||||
|
@ -58,43 +57,52 @@ namespace emsha {
|
||||||
const std::uint32_t SHA256_HASH_SIZE = 32;
|
const std::uint32_t SHA256_HASH_SIZE = 32;
|
||||||
|
|
||||||
|
|
||||||
/// The EMSHA_RESULT type is used to indicate whether an
|
/// \brief Describe the result of an EMSHA operation.
|
||||||
/// operation succeeded, and if not, what the general fault type
|
///
|
||||||
/// was.
|
/// The EMSHAResult type is used to indicate whether an operation
|
||||||
typedef enum _EMSHA_RESULT_ : std::uint8_t {
|
/// succeeded, and if not, what the general fault type was.
|
||||||
/// All operations have completed successfully so far.
|
typedef enum class EMSHAResult : std::uint8_t {
|
||||||
EMSHA_ROK = 0,
|
/// An unknown fault occurred. This is a serious bug in the
|
||||||
|
/// program.
|
||||||
|
Unknown = 0,
|
||||||
|
|
||||||
/// A self test or unit test failed.
|
/// All operations have completed successfully so far.
|
||||||
EMSHA_TEST_FAILURE = 1,
|
OK = 1,
|
||||||
|
|
||||||
|
/// The self-test failed.
|
||||||
|
TestFailure = 2,
|
||||||
|
|
||||||
/// A null pointer was passed in as a buffer where it shouldn't
|
/// A null pointer was passed in as a buffer where it shouldn't
|
||||||
/// have been.
|
/// have been.
|
||||||
EMSHA_NULLPTR = 2,
|
NullPointer = 3,
|
||||||
|
|
||||||
/// The Hash is in an invalid state.
|
/// The Hash is in an invalid state.
|
||||||
EMSHA_INVALID_STATE = 3,
|
InvalidState = 4,
|
||||||
|
|
||||||
/// The input to SHA256::update is too large.
|
/// The input to SHA256::update is too large.
|
||||||
SHA256_INPUT_TOO_LONG = 4,
|
InputTooLong = 5,
|
||||||
|
|
||||||
/// The self tests have been disabled, but a self-test function
|
/// The self tests have been disabled, but a self-test function
|
||||||
/// was called.
|
/// was called.
|
||||||
EMSHA_SELFTEST_DISABLED = 5
|
SelfTestDisabled = 6
|
||||||
} EMSHA_RESULT;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
// A Hash is generalised superclass supporting concrete classes
|
/// A Hash is an abstract base class supporting concrete classes
|
||||||
// that produce digests of data.
|
/// that produce digests of data.
|
||||||
class Hash {
|
class Hash {
|
||||||
public:
|
public:
|
||||||
virtual ~Hash() = default;
|
virtual ~Hash() = default;
|
||||||
|
|
||||||
/// Reset should bring the Hash back into its
|
/// \brief Bring the Hash back to its initial state.
|
||||||
/// initial state. That is, the idea is that
|
|
||||||
///
|
///
|
||||||
/// hash->reset(); hash->update(...)... ;
|
/// That is, the idea is that
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// hash->reset();
|
||||||
|
/// hash->update(...);
|
||||||
/// hash->result(...);
|
/// hash->result(...);
|
||||||
|
/// ```
|
||||||
///
|
///
|
||||||
/// is idempotent, assuming the inputs to update
|
/// is idempotent, assuming the inputs to update
|
||||||
/// and result are constant. The implications of
|
/// and result are constant. The implications of
|
||||||
|
@ -103,34 +111,54 @@ public:
|
||||||
/// in general, it has the effect of preserving
|
/// in general, it has the effect of preserving
|
||||||
/// any initial state while removing any data
|
/// any initial state while removing any data
|
||||||
/// written to the Hash via the update method.
|
/// written to the Hash via the update method.
|
||||||
virtual EMSHA_RESULT Reset() = 0;
|
///
|
||||||
|
/// \return An ::EMSHAResult describing the status of the
|
||||||
|
/// operation.
|
||||||
|
virtual EMSHAResult Reset() = 0;
|
||||||
|
|
||||||
// Update is writes message data into the Hash.
|
/// \brief Write message data into the Hash.
|
||||||
virtual EMSHA_RESULT Update(const std::uint8_t *m,
|
///
|
||||||
std::uint32_t ml) = 0;
|
/// \param message The message data to write into the Hash.
|
||||||
|
/// \param messageLength The length of the message data.
|
||||||
|
/// \return An ::EMSHAResult describing the status of the
|
||||||
|
/// operation.
|
||||||
|
virtual EMSHAResult Update(const std::uint8_t *message,
|
||||||
|
std::uint32_t messageLength) = 0;
|
||||||
|
|
||||||
/// Finalise carries out any final operations
|
/// \brief Carry out any final operations on the Hash.
|
||||||
/// on the Hash; after a call to finalize, no
|
///
|
||||||
/// more data can be written. Additionally, it
|
/// After a call to finalize, no more data can be written.
|
||||||
/// transfers out the resulting hash into its
|
/// Additionally, it transfers out the resulting hash into its
|
||||||
/// argument.
|
/// argument.
|
||||||
virtual EMSHA_RESULT Finalise(std::uint8_t *d) = 0;
|
///
|
||||||
|
/// \param digest The buffer to store the hash in.
|
||||||
|
/// \return An ::EMSHAResult describing the status of the
|
||||||
|
/// operation.
|
||||||
|
virtual EMSHAResult Finalise(std::uint8_t *digest) = 0;
|
||||||
|
|
||||||
/// Result transfers out the hash to the
|
/// \brief Result transfers out the hash to the argument.
|
||||||
/// argument. The Hash must keep enough state
|
///
|
||||||
/// for repeated calls to result to work.
|
/// The Hash must keep enough state for repeated calls to
|
||||||
virtual EMSHA_RESULT Result(std::uint8_t *d) = 0;
|
/// result to work.
|
||||||
|
///
|
||||||
|
/// \param digest The buffer to store the hash in.
|
||||||
|
/// \return An ::EMSHAResult describing the status of the
|
||||||
|
/// operation.
|
||||||
|
virtual EMSHAResult Result(std::uint8_t *digest) = 0;
|
||||||
|
|
||||||
/// Size should return the output size of the
|
/// \brief Return the output size of the Hash.
|
||||||
/// Hash; this is, how large the buffers written
|
///
|
||||||
/// to by result should be.
|
/// This is how large the buffers written to by result should
|
||||||
|
/// be.
|
||||||
virtual std::uint32_t Size() = 0;
|
virtual std::uint32_t Size() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// HashEqual provides a constant time function for comparing
|
/// \brief Constant-time function for comparing two digests.
|
||||||
/// two hashes. The caller *must* ensure that both a and b are
|
///
|
||||||
/// the same size. The recommended approach is to use fixed-size
|
/// HashEqual provides a constant time function for comparing two
|
||||||
/// buffers of emsha::SHA256_HASH_SIZE length:
|
/// digests. The caller *must* ensure that both a and b are the same
|
||||||
|
/// size. The recommended approach is to use fixed-size buffers of
|
||||||
|
/// emsha::SHA256_HASH_SIZE length:
|
||||||
///
|
///
|
||||||
/// ```c++
|
/// ```c++
|
||||||
/// uint8_t expected[emsha::SHA256_HASH_SIZE];
|
/// uint8_t expected[emsha::SHA256_HASH_SIZE];
|
||||||
|
@ -146,21 +174,21 @@ public:
|
||||||
/// \param a A byte buffer of size Hash::Size().
|
/// \param a A byte buffer of size Hash::Size().
|
||||||
/// \param b A byte buffer of size Hash::Size().
|
/// \param b A byte buffer of size Hash::Size().
|
||||||
/// \return True if both byte arrays match.
|
/// \return True if both byte arrays match.
|
||||||
bool
|
bool HashEqual(const std::uint8_t *a, const std::uint8_t *b);
|
||||||
HashEqual(const std::uint8_t *a, const std::uint8_t *b);
|
|
||||||
|
|
||||||
#ifndef EMSHA_NO_HEXSTRING
|
#ifndef EMSHA_NO_HEXSTRING
|
||||||
/// HexString writes a hex-encoded version of the src byte
|
/// \brief Write a hex-encoded version of a byte string.
|
||||||
/// array into dest. The caller *must* ensure that dest is
|
|
||||||
/// srclen * 2 bytes or longer.
|
|
||||||
///
|
///
|
||||||
|
/// HexString writes a hex-encoded version of the src byte array into
|
||||||
|
/// dest. The caller **must** ensure that dest is `srclen * 2` bytes
|
||||||
|
/// or longer.
|
||||||
///
|
///
|
||||||
/// \param dest The destination byte array at least (2*srclen)
|
/// \param dest The destination byte array at least (`2*srclen`)
|
||||||
/// bytes in length.
|
/// bytes in length.
|
||||||
/// \param src A byte array containing the data to hexify..
|
/// \param src A byte array containing the data to hexify.
|
||||||
/// \param srclen The size in bytes of src.
|
/// \param srclen The size in bytes of src.
|
||||||
void
|
void HexString(std::uint8_t *dest, std::uint8_t *src, std::uint32_t srclen);
|
||||||
HexString(std::uint8_t *dest, std::uint8_t *src, std::uint32_t srclen);
|
|
||||||
#endif // EMSHA_NO_HEXSTRING
|
#endif // EMSHA_NO_HEXSTRING
|
||||||
|
|
||||||
|
|
||||||
|
|
216
emsha/hmac.h
216
emsha/hmac.h
|
@ -43,151 +43,137 @@ const uint32_t HMAC_KEY_LENGTH = SHA256_MB_SIZE;
|
||||||
|
|
||||||
/// HMAC is a keyed hash that can be used to produce an
|
/// HMAC is a keyed hash that can be used to produce an
|
||||||
/// authenticated hash of some data. The HMAC is built on
|
/// authenticated hash of some data. The HMAC is built on
|
||||||
/// (and uses internally) the SHA-256 class; it's helpful to
|
/// (and uses internally) the SHA256 class; it's helpful to
|
||||||
/// note that faults that occur in the SHA-256 code will be
|
/// note that faults that occur in the SHA-256 code will be
|
||||||
/// propagated up as the return value from many of the HMAC
|
/// propagated up as the return value from many of the HMAC
|
||||||
/// functions.
|
/// functions.
|
||||||
class HMAC : Hash {
|
class HMAC : Hash {
|
||||||
public:
|
public:
|
||||||
/// An HMAC is constructed with a key and the
|
/// \brief Construct an HMAC with its initial key.
|
||||||
/// length of the key. This key is stored in
|
///
|
||||||
/// the HMAC context, and is wiped by the HMAC
|
/// An HMAC is constructed with a key and the length of the
|
||||||
/// destructor.
|
/// key. This key is stored in the HMAC context, and is wiped
|
||||||
|
/// by the HMAC destructor.
|
||||||
///
|
///
|
||||||
/// \param k The HMAC key.
|
/// \param k The HMAC key.
|
||||||
/// \param kl THe length of the HMAC key.
|
/// \param kl THe length of the HMAC key.
|
||||||
HMAC(const uint8_t *k, uint32_t kl);
|
HMAC(const uint8_t *k, uint32_t kl);
|
||||||
|
|
||||||
/// Reset clears any data written to the HMAC;
|
/// \brief Clear any data written to the HMAC.
|
||||||
/// this is equivalent to constructing a new HMAC,
|
|
||||||
/// but it preserves the keys.
|
|
||||||
///
|
///
|
||||||
/// \return EMSHA_ROK is returned if the reset
|
/// This is equivalent to constructing a new HMAC, but it
|
||||||
/// occurred without (detected) fault.
|
/// preserves the keys.
|
||||||
/// If a fault occurs with the under-
|
///
|
||||||
/// lying SHA-256 context, the error
|
/// \return EMSHAResult::OK is returned if the reset occurred
|
||||||
/// code is returned.
|
/// without (detected) fault. If a fault occurs with
|
||||||
EMSHA_RESULT Reset() override;
|
/// the underlying SHA256 context, the error code is
|
||||||
|
/// returned.
|
||||||
|
EMSHAResult Reset() override;
|
||||||
|
|
||||||
/// Update writes data into the context. While
|
/// \brief Write data into the context.
|
||||||
/// there is an upper limit on the size of data
|
|
||||||
/// that the underlying hash can operate on,
|
|
||||||
/// this package is designed for small systems
|
|
||||||
/// that will not approach that level of data
|
|
||||||
/// (which is on the order of 2 exabytes), so it
|
|
||||||
/// is not thought to be a concern.
|
|
||||||
///
|
///
|
||||||
/// \param m A byte array containing the message
|
/// While there is an upper limit on the size of data that the
|
||||||
|
/// underlying hash can operate on, this package is designed
|
||||||
|
/// for small systems that will not approach that level of data
|
||||||
|
/// (which is on the order of 2 exabytes), so it is not a
|
||||||
|
/// concern for this library.
|
||||||
|
///
|
||||||
|
/// \param message A byte array containing the message
|
||||||
/// to be written.
|
/// to be written.
|
||||||
/// \param ml The message length, in bytes.
|
/// \param messageLength The message length, in bytes.
|
||||||
/// \return
|
/// \return An ::EMSHAResult describing the result of the
|
||||||
/// - EMSHA_NULLPTR is returned if m is NULL and ml is
|
/// operation.
|
||||||
/// nonzero.
|
|
||||||
/// - EMSHA_INVALID_STATE is returned if the update
|
|
||||||
/// is called after a call to finalize.
|
|
||||||
/// - SHA256_INPUT_TOO_LONG is returned if too much
|
|
||||||
/// data has been written to the context.
|
|
||||||
/// - EMSHA_ROK is returned if the data was
|
|
||||||
/// successfully written into the HMAC context.
|
|
||||||
///
|
///
|
||||||
EMSHA_RESULT Update(const uint8_t *, uint32_t) override;
|
/// - EMSHAResult::NullPointer is returned if m is NULL
|
||||||
|
/// and ml is nonzero.
|
||||||
|
/// - EMSHAResult::InvalidState is returned if the
|
||||||
|
/// update is called after a call to finalize.
|
||||||
|
/// - EMSHAResult::InputTooLong is returned if too much
|
||||||
|
/// data has been written to the context.
|
||||||
|
/// - EMSHAResult::OK is returned if the data was
|
||||||
|
/// successfully written into the HMAC context.
|
||||||
|
EMSHAResult Update(const std::uint8_t *message, std::uint32_t messageLength) override;
|
||||||
|
|
||||||
// Finalise completes the HMAC computation. Once this
|
/// \brief Complete the HMAC computation.
|
||||||
// method is called, the context cannot be updated
|
///
|
||||||
// unless the context is reset.
|
/// \note Once #Finalise is called, the context cannot be
|
||||||
//
|
/// updated unless the context is reset.
|
||||||
// Inputs:
|
///
|
||||||
// d: a byte buffer that must be at least
|
/// \param digest A byte buffer that must be at least #HMAC.Size()
|
||||||
// HMAC.size() in length.
|
/// in length.
|
||||||
//
|
/// \return An EMSHAResult describing the result of this
|
||||||
// Outputs:
|
/// method:
|
||||||
// EMSHA_NULLPTR is returned if d is the null
|
///
|
||||||
// pointer.
|
/// - EMSHAResult::NullPointer is returned if d is a
|
||||||
//
|
/// null pointer.
|
||||||
// EMSHA_INVALID_STATE is returned if the HMAC
|
/// - EMSHAResult::InvalidState is returned if the HMAC
|
||||||
// context is in an invalid state, such as if there
|
/// context is in an invalid state, such as if there
|
||||||
// were errors in previous updates.
|
/// were errors in previous updates.
|
||||||
//
|
/// - EMSHAResult::OK is returned if the context was
|
||||||
// EMSHA_ROK is returned if the context was
|
/// successfully finalised and the digest copied to d.
|
||||||
// successfully finalised and the digest copied to
|
///
|
||||||
// d.
|
EMSHAResult Finalise(std::uint8_t *digest) override;
|
||||||
//
|
|
||||||
EMSHA_RESULT Finalise(uint8_t *) override;
|
|
||||||
|
|
||||||
// Result copies the result from the HMAC context into
|
/// \brief Copy the current digest into a destination buffer.
|
||||||
// the buffer pointed to by d, running finalize if
|
///
|
||||||
// needed. Once called, the context cannot be updated
|
/// Copy the current digest from the HMAC context into
|
||||||
// until the context is reset.
|
/// `digest`, running #Finalise if needed. Once called, the
|
||||||
//
|
/// context cannot be updated until the context is reset.
|
||||||
// Inputs:
|
///
|
||||||
// d: a byte buffer that must be at least
|
/// \param digest A byte buffer that must be at least #HMAC.size()
|
||||||
// HMAC.size() in length.
|
/// in length.
|
||||||
//
|
/// \return An ::EMSHAResult describing the result of this
|
||||||
// Outputs:
|
/// method:
|
||||||
// EMSHA_NULLPTR is returned if d is the null
|
///
|
||||||
// pointer.
|
/// - EMSHAResult::NullPointer is returned if d is a
|
||||||
//
|
/// null pointer.
|
||||||
// EMSHA_INVALID_STATE is returned if the HMAC
|
/// - EMSHAResult::InvalidState is returned if the HMAC
|
||||||
// context is in an invalid state, such as if there
|
/// context is in an invalid state, such as if there
|
||||||
// were errors in previous updates.
|
/// were errors in previous updates.
|
||||||
//
|
/// - EMSHAResult::OK is returned if the context was
|
||||||
// EMSHA_ROK is returned if the context was
|
/// successfully finalised and the digest copied to d.
|
||||||
// successfully finalised and the digest copied to
|
EMSHAResult Result(std::uint8_t *digest) override;
|
||||||
// d.
|
|
||||||
//
|
|
||||||
EMSHA_RESULT Result(uint8_t *) override;
|
|
||||||
|
|
||||||
|
|
||||||
// size returns the output size of HMAC-SHA-256, e.g.
|
/// \brief Returns the output size of HMAC-SHA-256.
|
||||||
// the size that the buffers passed to finalize and
|
///
|
||||||
// result should be.
|
/// The buffers passed to #Update and #Finalise should be at
|
||||||
//
|
/// least this size.
|
||||||
// Outputs:
|
///
|
||||||
// A uint32_t representing the expected size
|
/// \return The expected size of buffers passed to result and
|
||||||
// of buffers passed to result and finalize.
|
/// finalize.
|
||||||
std::uint32_t Size() override;
|
std::uint32_t Size() override;
|
||||||
|
|
||||||
// When an HMAC context is destroyed, it is reset and
|
/// When an HMAC context is destroyed, it is reset and
|
||||||
// the key material is zeroised using the STL fill
|
/// the key material is zeroised using the STL `fill`
|
||||||
// function.
|
/// function.
|
||||||
~HMAC(void);
|
~HMAC();
|
||||||
private:
|
private:
|
||||||
uint8_t hstate;
|
uint8_t hstate;
|
||||||
SHA256 ctx;
|
SHA256 ctx;
|
||||||
uint8_t k[HMAC_KEY_LENGTH];
|
uint8_t k[HMAC_KEY_LENGTH];
|
||||||
uint8_t buf[SHA256_HASH_SIZE];
|
uint8_t buf[SHA256_HASH_SIZE];
|
||||||
|
|
||||||
EMSHA_RESULT reset();
|
EMSHAResult reset();
|
||||||
inline EMSHA_RESULT
|
inline EMSHAResult finalResult(uint8_t *d);
|
||||||
finalResult(uint8_t *d);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// compute_hmac performs a single-pass HMAC computation over
|
|
||||||
// a message.
|
/// \brief Perform a single-pass HMAC computation over a message.
|
||||||
//
|
///
|
||||||
// Inputs:
|
/// \param k A byte buffer containing the HMAC key.
|
||||||
// k: a byte buffer containing the HMAC key.
|
/// \param kl The length of the HMAC key.
|
||||||
//
|
/// \param m The message data over which the HMAC is to be computed.
|
||||||
// kl: the length of the HMAC key.
|
/// \param ml The length of the message.
|
||||||
//
|
/// \param d Byte buffer that will be used to store the resulting
|
||||||
// m: the message data over which the HMAC is to be computed.
|
/// HMAC. It should be emsha::SHA256_HASH_SIZE bytes in size.
|
||||||
//
|
/// \return An ::EMSHAResult describing the result of the HMAC operation.
|
||||||
// ml: the length of the message.
|
EMSHAResult
|
||||||
//
|
ComputeHMAC(const uint8_t *k, const uint32_t kl,
|
||||||
// d: a byte buffer that will be used to store the resulting
|
const uint8_t *m, const uint32_t ml,
|
||||||
// HMAC. It should be SHA256_HASH_SIZE bytes in size.
|
|
||||||
//
|
|
||||||
// Outputs:
|
|
||||||
// This function handles setting up the HMAC context with
|
|
||||||
// the given key, calling update with the message data, and
|
|
||||||
// then calling finalize to place the result in the output
|
|
||||||
// buffer. Any of the faults that can occur in these functions
|
|
||||||
// can be returned here, or EMSHA_ROK if the HMAC was
|
|
||||||
// successfully computed.
|
|
||||||
EMSHA_RESULT
|
|
||||||
ComputeHMAC(const uint8_t *k, uint32_t kl,
|
|
||||||
const uint8_t *m, uint32_t ml,
|
|
||||||
uint8_t *d);
|
uint8_t *d);
|
||||||
|
|
||||||
|
|
||||||
} // end of namespace emsha
|
} // end of namespace emsha
|
||||||
|
|
||||||
|
|
||||||
|
|
264
emsha/sha256.h
264
emsha/sha256.h
|
@ -34,184 +34,160 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <emsha/emsha.h>
|
#include <emsha/emsha.h>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
|
||||||
namespace emsha {
|
namespace emsha {
|
||||||
|
|
||||||
|
|
||||||
// SHA256_MB_SIZE is the size of a message block.
|
/// SHA256_MB_SIZE is the size of a message block.
|
||||||
const uint32_t SHA256_MB_SIZE = 64;
|
const uint32_t SHA256_MB_SIZE = 64;
|
||||||
|
|
||||||
class SHA256 : Hash {
|
class SHA256 : Hash {
|
||||||
public:
|
public:
|
||||||
// A SHA256 context does not need any special
|
/// \brief A SHA256 context does not need any special
|
||||||
// construction. It can be declared and
|
/// construction.
|
||||||
// immediately start being used.
|
///
|
||||||
|
/// It can be declared and immediately start being used.
|
||||||
SHA256();
|
SHA256();
|
||||||
|
|
||||||
// The SHA256 destructor will clear out its internal
|
/// The SHA256 destructor will clear out its internal
|
||||||
// message buffer; all the members are local and
|
/// message buffer; all the members are local and
|
||||||
// not resource handles, so cleanup is minimal.
|
/// not resource handles, so cleanup is minimal.
|
||||||
~SHA256();
|
~SHA256();
|
||||||
|
|
||||||
// reset clears the internal state of the SHA256
|
/// \brief Clear the internal state of the SHA256 context,
|
||||||
// context and returns it to its initial state.
|
/// returning it to its initial state.
|
||||||
// It should always return EMSHA_ROK.
|
///
|
||||||
EMSHA_RESULT Reset() override;
|
/// \return This should always return EMSHAResult::OK.
|
||||||
|
EMSHAResult Reset() override;
|
||||||
|
|
||||||
// update writes data into the context. While
|
/// \brief Writes data into the SHA256.
|
||||||
// there is an upper limit on the size of data
|
///
|
||||||
// that SHA-256 can operate on, this package is
|
/// While there is an upper limit on the size of data that
|
||||||
// designed for small systems that will not
|
/// SHA-256 can operate on, this package is designed for small
|
||||||
// approach that level of data (which is on the
|
/// systems that will not approach that level of data (which is
|
||||||
// order of 2 exabytes), so it is not thought
|
/// on the order of 2 exabytes), so it is not thought to be a
|
||||||
// to be a concern.
|
/// concern.
|
||||||
//
|
///
|
||||||
// Inputs:
|
/// \param message A byte array containing the message to be
|
||||||
// m: a byte array containing the message to
|
/// written. It must not be NULL (unless the
|
||||||
// be written. It must not be NULL (unless
|
/// message length is zero).
|
||||||
// the message length is zero).
|
/// \param messageLength The message length, in bytes.
|
||||||
//
|
/// \return An ::EMSHAResult describing the result of the
|
||||||
// ml: the message length, in bytes.
|
/// operation.
|
||||||
//
|
///
|
||||||
// Outputs:
|
/// - EMSHAResult::NullPointer is returned if m is a
|
||||||
// EMSHA_NULLPTR is returned if m is NULL
|
/// nullptr and ml is nonzero.
|
||||||
// and ml is nonzero.
|
/// - EMSHAResult::InvalidState is returned if the
|
||||||
//
|
/// update is called after a call to finalize.
|
||||||
// EMSHA_INVALID_STATE is returned if the
|
/// - EMSHAResult::InputTooLong is returned if too much
|
||||||
// update is called after a call to
|
/// data has been written to the context.
|
||||||
// finalize.
|
/// - EMSHAResult::OK is returned if the data was
|
||||||
//
|
/// successfully added to the SHA-256 context.
|
||||||
// SHA256_INPUT_TOO_LONG is returned if too
|
EMSHAResult Update(const std::uint8_t *message, std::uint32_t messageLength) override;
|
||||||
// much data has been written to the
|
|
||||||
// context.
|
|
||||||
//
|
|
||||||
// EMSHA_ROK is returned if the data was
|
|
||||||
// successfully added to the SHA-256
|
|
||||||
// context.
|
|
||||||
//
|
|
||||||
EMSHA_RESULT Update(const uint8_t *m, uint32_t ml) override;
|
|
||||||
|
|
||||||
// Finalise completes the digest. Once this
|
/// \brief Complete the digest.
|
||||||
// method is called, the context cannot be
|
///
|
||||||
// updated unless the context is reset.
|
/// Once this method is called, the context cannot be updated
|
||||||
//
|
/// unless the context is reset.
|
||||||
// Inputs:
|
///
|
||||||
// d: a byte buffer that must be at least
|
/// \param digest byte buffer that must be at least
|
||||||
// SHA256.size() in length.
|
/// SHA256.size() in length.
|
||||||
//
|
/// \return An ::EMSHAResult describing the result of the
|
||||||
// Outputs:
|
/// operation.
|
||||||
// EMSHA_NULLPTR is returned if d is the
|
///
|
||||||
// null pointer.
|
/// - EMSHAResult::NullPointer is returned if a nullptr
|
||||||
//
|
/// is passed in.
|
||||||
// EMSHA_INVALID_STATE is returned if the
|
/// - EMSHAResult::InvalidState is returned if the
|
||||||
// SHA-256 context is in an invalid state,
|
/// SHA-256 context is in an invalid state, such as
|
||||||
// such as if there were errors in previous
|
/// if there were errors in previous updates.
|
||||||
// updates.
|
/// - EMSHAResult::OK is returned if the context was
|
||||||
//
|
/// successfully finalised and the digest copied to
|
||||||
// EMSHA_ROK is returned if the context was
|
/// digest.
|
||||||
// successfully finalised and the digest
|
EMSHAResult Finalise(std::uint8_t *digest) override;
|
||||||
// copied to d.
|
|
||||||
//
|
|
||||||
EMSHA_RESULT Finalise(uint8_t *d) override;
|
|
||||||
|
|
||||||
// result copies the result from the SHA-256
|
/// \brief Copy the result from the SHA-256
|
||||||
// context into the buffer pointed to by d,
|
/// context into the buffer pointed to by d,
|
||||||
// running Finalise if needed. Once called,
|
/// running #Finalise if needed. Once called,
|
||||||
// the context cannot be updated until the
|
/// the context cannot be updated until the
|
||||||
// context is reset.
|
/// context is reset.
|
||||||
//
|
///
|
||||||
// Inputs:
|
/// \param digest A byte buffer that must be at least
|
||||||
// d: a byte buffer that must be at least
|
/// SHA256.size() in length.
|
||||||
// SHA256.size() in length.
|
/// \return An ::EMSHAResult describing the result of the
|
||||||
//
|
/// operation.
|
||||||
// Outputs:
|
///
|
||||||
// EMSHA_NULLPTR is returned if d is the
|
/// - EMSHAResult::NullPointer is returned if a nullptr
|
||||||
// null pointer.
|
/// is passed in.
|
||||||
//
|
/// - EMSHAResult::InvalidState is returned if the
|
||||||
// EMSHA_INVALID_STATE is returned if the
|
/// SHA-256 context is in an invalid state, such as
|
||||||
// SHA-256 context is in an invalid state,
|
/// if there were errors in previous updates.
|
||||||
// such as if there were errors in previous
|
/// - EMSHAResult::OK is returned if the context was
|
||||||
// updates.
|
/// successfully finalised and the digest copied to
|
||||||
//
|
/// digest.
|
||||||
// EMSHA_ROK is returned if the context was
|
EMSHAResult Result(std::uint8_t *digest) override;
|
||||||
// successfully finalised and the digest
|
|
||||||
// copied to d.
|
|
||||||
//
|
|
||||||
EMSHA_RESULT Result(uint8_t *d) override;
|
|
||||||
|
|
||||||
// size returns the output size of SHA256, e.g.
|
/// \brief Returns the output size of SHA-256.
|
||||||
// the size that the buffers passed to finalize
|
///
|
||||||
// and result should be.
|
/// The buffers passed to #Update and #Finalise should be at
|
||||||
//
|
/// least this size.
|
||||||
// Outputs:
|
///
|
||||||
// a uint32_t representing the expected size
|
/// \return The expected size of buffers passed to result and
|
||||||
// of buffers passed to result and finalize.
|
/// finalize.
|
||||||
std::uint32_t Size() override;
|
std::uint32_t Size() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// mlen stores the current message length.
|
uint64_t mlen; // Current message length.
|
||||||
uint64_t mlen;
|
uint32_t i_hash[8]; // The intermediate hash is 8x 32-bit blocks.
|
||||||
|
|
||||||
// The intermediate hash is 8x 32-bit blocks.
|
|
||||||
uint32_t i_hash[8];
|
|
||||||
|
|
||||||
// hStatus is the hash status, and hComplete indicates
|
// hStatus is the hash status, and hComplete indicates
|
||||||
// whether the hash has been finalised.
|
// whether the hash has been finalised.
|
||||||
EMSHA_RESULT hStatus;
|
EMSHAResult hStatus;
|
||||||
uint8_t hComplete;
|
uint8_t hComplete;
|
||||||
|
|
||||||
// mb is the message block, and mbi is the message
|
// mb is the message block, and mbi is the message
|
||||||
// block index.
|
// block index.
|
||||||
uint8_t mbi;
|
uint8_t mbi;
|
||||||
uint8_t mb[SHA256_MB_SIZE];
|
std::array<uint8_t, SHA256_MB_SIZE> mb;
|
||||||
|
|
||||||
inline EMSHA_RESULT addLength(const uint32_t);
|
inline EMSHAResult addLength(const uint32_t);
|
||||||
inline void updateMessageBlock(void);
|
inline void updateMessageBlock(void);
|
||||||
inline void padMessage(uint8_t pc);
|
inline void padMessage(uint8_t pc);
|
||||||
EMSHA_RESULT reset();
|
uint32_t chunkToUint32(uint32_t offset);
|
||||||
|
uint32_t uint32ToChunk(uint32_t offset);
|
||||||
|
EMSHAResult reset();
|
||||||
}; // end class SHA256
|
}; // end class SHA256
|
||||||
|
|
||||||
// sha256Digest performs a single pass hashing of the message
|
|
||||||
// passed in.
|
|
||||||
//
|
|
||||||
// Inputs:
|
|
||||||
// m: byte buffer containing the message to hash.
|
|
||||||
//
|
|
||||||
// ml: the length of m.
|
|
||||||
//
|
|
||||||
// d: byte buffer that will be used to store the resulting
|
|
||||||
// hash; it should have at least emsha::SHA256_HASH_SIZE
|
|
||||||
// bytes available.
|
|
||||||
//
|
|
||||||
// Outputs:
|
|
||||||
// This function handles setting up a SHA256 context, calling
|
|
||||||
// update using the message data, and then calling finalize. Any
|
|
||||||
// of the errors that can occur in those functions can be
|
|
||||||
// returned here, or EMSHA_ROK if the digest was computed
|
|
||||||
// successfully.
|
|
||||||
//
|
|
||||||
EMSHA_RESULT
|
|
||||||
sha256Digest(const uint8_t *m, uint32_t ml, uint8_t *d);
|
|
||||||
|
|
||||||
// sha256SelfTest runs through two test cases to ensure that the
|
/// \brief SHA256Digest performs a single pass hashing of the message
|
||||||
// SHA-256 functions are working correctly.
|
/// passed in.
|
||||||
//
|
///
|
||||||
// Outputs:
|
/// \param m Byte buffer containing the message to hash.
|
||||||
// EMSHA_ROK is returned if the self tests pass.
|
/// \param ml The length of m.
|
||||||
//
|
/// \param d Byte buffer that will be used to store the resulting hash;
|
||||||
// EMSHA_SELFTEST_DISABLED is returned if the self tests
|
/// it should have at least emsha::SHA256_HASH_SIZE bytes
|
||||||
// have been disabled (e.g., libemsha was compiled with the
|
/// available.
|
||||||
// EMSHA_NO_SELFTEST #define).
|
/// \return An ::EMSHAResult describing the result of the operation.
|
||||||
//
|
EMSHAResult SHA256Digest(const uint8_t *m, uint32_t ml, uint8_t *d);
|
||||||
// If a fault occurred inside the SHA-256 code, the error
|
|
||||||
// code from one of the update, finalize, result, or reset
|
/// \brief SHA256SelfTest runs through two test cases to ensure that the
|
||||||
// methods is returned.
|
/// SHA-256 functions are working correctly.
|
||||||
//
|
///
|
||||||
// If the fault is that the output does not match the test
|
/// \return The result of the self-test.
|
||||||
// vector, EMSHA_TEST_FAILURE is returned.
|
///
|
||||||
EMSHA_RESULT
|
/// - EMSHAResult::OK is returned if the self tests pass.
|
||||||
sha256SelfTest(void);
|
/// - EMSHAResult::SelfTestDisabled is returned if the self
|
||||||
|
/// tests have been disabled (e.g., libemsha was compiled
|
||||||
|
/// with the EMSHA_NO_SELFTEST #define).
|
||||||
|
/// - If a fault occurred inside the SHA-256 code, the error
|
||||||
|
/// code from one of the update, finalize, result, or reset
|
||||||
|
/// methods is returned.
|
||||||
|
/// - If the fault is that the output does not match the test
|
||||||
|
/// vector, EMSHAResult::TestFailure is returned.
|
||||||
|
EMSHAResult SHA256SelfTest();
|
||||||
|
|
||||||
|
|
||||||
} // end of namespace emsha
|
} // end of namespace emsha
|
||||||
|
|
||||||
|
|
||||||
|
|
88
hmac.cc
88
hmac.cc
|
@ -63,11 +63,12 @@ static constexpr uint8_t opad = 0x5c;
|
||||||
HMAC::HMAC(const uint8_t *ik, uint32_t ikl)
|
HMAC::HMAC(const uint8_t *ik, uint32_t ikl)
|
||||||
: hstate(HMAC_INIT), k{0}, buf{0}
|
: hstate(HMAC_INIT), k{0}, buf{0}
|
||||||
{
|
{
|
||||||
|
std::fill(this->k, this->k+HMAC_KEY_LENGTH, 0);
|
||||||
std::fill(this->k, this->k + emsha::HMAC_KEY_LENGTH, 0);
|
|
||||||
|
|
||||||
if (ikl < HMAC_KEY_LENGTH) {
|
if (ikl < HMAC_KEY_LENGTH) {
|
||||||
std::copy(ik, ik + ikl, this->k);
|
for (uint32_t i = 0; i < ikl; i++) {
|
||||||
|
this->k[i] = ik[i];
|
||||||
|
}
|
||||||
while (ikl < HMAC_KEY_LENGTH) {
|
while (ikl < HMAC_KEY_LENGTH) {
|
||||||
this->k[ikl++] = 0;
|
this->k[ikl++] = 0;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +77,9 @@ HMAC::HMAC(const uint8_t *ik, uint32_t ikl)
|
||||||
this->ctx.Result(this->k);
|
this->ctx.Result(this->k);
|
||||||
this->ctx.Reset();
|
this->ctx.Reset();
|
||||||
} else {
|
} else {
|
||||||
std::copy(ik, ik + ikl, this->k);
|
for (uint32_t i = 0; i < ikl; i++) {
|
||||||
|
this->k[i] = ik[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->reset();
|
this->reset();
|
||||||
|
@ -93,17 +96,17 @@ HMAC::~HMAC()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
HMAC::Reset()
|
HMAC::Reset()
|
||||||
{
|
{
|
||||||
return this->reset();
|
return this->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
HMAC::reset()
|
HMAC::reset()
|
||||||
{
|
{
|
||||||
EMSHA_RESULT res;
|
EMSHAResult res;
|
||||||
|
|
||||||
// Following a reset, both SHA-256 contexts and result buffer should be
|
// Following a reset, both SHA-256 contexts and result buffer should be
|
||||||
// zero'd out for a clean slate. The HMAC state should be reset
|
// zero'd out for a clean slate. The HMAC state should be reset
|
||||||
|
@ -119,7 +122,7 @@ HMAC::reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
res = this->ctx.Update(key, HMAC_KEY_LENGTH);
|
res = this->ctx.Update(key, HMAC_KEY_LENGTH);
|
||||||
if (EMSHA_ROK != res) {
|
if (EMSHAResult::OK != res) {
|
||||||
this->hstate = HMAC_INVALID;
|
this->hstate = HMAC_INVALID;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -128,55 +131,56 @@ HMAC::reset()
|
||||||
std::fill(key, key + HMAC_KEY_LENGTH, 0);
|
std::fill(key, key + HMAC_KEY_LENGTH, 0);
|
||||||
|
|
||||||
this->hstate = HMAC_IPAD;
|
this->hstate = HMAC_IPAD;
|
||||||
return EMSHA_ROK;
|
return EMSHAResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
HMAC::Update(const uint8_t *m, uint32_t ml)
|
HMAC::Update(const std::uint8_t *message, std::uint32_t messageLength)
|
||||||
{
|
{
|
||||||
EMSHA_RESULT res;
|
EMSHAResult res;
|
||||||
SHA256 &hctx = this->ctx;
|
SHA256 &hctx = this->ctx;
|
||||||
|
|
||||||
EMSHA_CHECK(m != nullptr, EMSHA_NULLPTR);
|
EMSHA_CHECK(message != nullptr, EMSHAResult::NullPointer);
|
||||||
EMSHA_CHECK(HMAC_IPAD == this->hstate, EMSHA_INVALID_STATE);
|
EMSHA_CHECK(HMAC_IPAD == this->hstate, EMSHAResult::InvalidState);
|
||||||
|
|
||||||
// Write the message to the SHA-256 context.
|
// Write the message to the SHA-256 context.
|
||||||
res = hctx.Update(m, ml);
|
res = hctx.Update(message, messageLength);
|
||||||
if (EMSHA_ROK != res) {
|
if (EMSHAResult::OK != res) {
|
||||||
this->hstate = HMAC_INVALID;
|
this->hstate = HMAC_INVALID;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
assert(HMAC_IPAD == this->hstate);
|
assert(HMAC_IPAD == this->hstate);
|
||||||
|
|
||||||
return EMSHA_ROK;
|
return EMSHAResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline EMSHA_RESULT
|
inline EMSHAResult
|
||||||
HMAC::finalResult(uint8_t *d)
|
HMAC::finalResult(uint8_t *d)
|
||||||
{
|
{
|
||||||
if (nullptr == d) {
|
if (nullptr == d) {
|
||||||
return EMSHA_NULLPTR;
|
return EMSHAResult::NullPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the HMAC has already been finalised, skip straight to
|
// If the HMAC has already been finalised, skip straight to
|
||||||
// copying the result.
|
// copying the result.
|
||||||
if (HMAC_FIN == this->hstate) {
|
if (this->hstate == HMAC_FIN) {
|
||||||
std::copy(this->buf, this->buf+SHA256_HASH_SIZE, d);
|
std::copy(this->buf, this->buf+SHA256_HASH_SIZE, d);
|
||||||
return EMSHA_ROK;
|
|
||||||
|
return EMSHAResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSHA_CHECK(HMAC_IPAD == this->hstate, EMSHA_INVALID_STATE);
|
EMSHA_CHECK(HMAC_IPAD == this->hstate, EMSHAResult::InvalidState);
|
||||||
|
|
||||||
EMSHA_RESULT res;
|
EMSHAResult res;
|
||||||
|
|
||||||
// Use the result buffer as an intermediate buffer to store the result
|
// Use the result buffer as an intermediate buffer to store the result
|
||||||
// of the inner hash.
|
// of the inner hash.
|
||||||
res = this->ctx.Result(this->buf);
|
res = this->ctx.Result(this->buf);
|
||||||
if (EMSHA_ROK != res) {
|
if (EMSHAResult::OK != res) {
|
||||||
this->hstate = HMAC_INVALID;
|
this->hstate = HMAC_INVALID;
|
||||||
return EMSHA_INVALID_STATE;
|
return EMSHAResult::InvalidState;
|
||||||
}
|
}
|
||||||
assert(HMAC_IPAD == this->hstate);
|
assert(HMAC_IPAD == this->hstate);
|
||||||
|
|
||||||
|
@ -192,7 +196,7 @@ HMAC::finalResult(uint8_t *d)
|
||||||
}
|
}
|
||||||
|
|
||||||
res = this->ctx.Update(key, HMAC_KEY_LENGTH);
|
res = this->ctx.Update(key, HMAC_KEY_LENGTH);
|
||||||
if (EMSHA_ROK != res) {
|
if (EMSHAResult::OK != res) {
|
||||||
this->hstate = HMAC_INVALID;
|
this->hstate = HMAC_INVALID;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -203,14 +207,14 @@ HMAC::finalResult(uint8_t *d)
|
||||||
|
|
||||||
// Write the inner hash result into the outer hash.
|
// Write the inner hash result into the outer hash.
|
||||||
res = this->ctx.Update(this->buf, SHA256_HASH_SIZE);
|
res = this->ctx.Update(this->buf, SHA256_HASH_SIZE);
|
||||||
if (EMSHA_ROK != res) {
|
if (EMSHAResult::OK != res) {
|
||||||
this->hstate = HMAC_INVALID;
|
this->hstate = HMAC_INVALID;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the outer hash result into the working buffer.
|
// Write the outer hash result into the working buffer.
|
||||||
res = this->ctx.Finalise(this->buf);
|
res = this->ctx.Finalise(this->buf);
|
||||||
if (EMSHA_ROK != res) {
|
if (EMSHAResult::OK != res) {
|
||||||
this->hstate = HMAC_INVALID;
|
this->hstate = HMAC_INVALID;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -218,21 +222,21 @@ HMAC::finalResult(uint8_t *d)
|
||||||
|
|
||||||
std::copy(this->buf, this->buf + SHA256_HASH_SIZE, d);
|
std::copy(this->buf, this->buf + SHA256_HASH_SIZE, d);
|
||||||
this->hstate = HMAC_FIN;
|
this->hstate = HMAC_FIN;
|
||||||
return EMSHA_ROK;
|
return EMSHAResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
HMAC::Finalise(uint8_t *d)
|
HMAC::Finalise(std::uint8_t *digest)
|
||||||
{
|
{
|
||||||
return this->finalResult(d);
|
return this->finalResult(digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
HMAC::Result(uint8_t *d)
|
HMAC::Result(std::uint8_t *digest)
|
||||||
{
|
{
|
||||||
return this->finalResult(d);
|
return this->finalResult(digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -243,21 +247,17 @@ HMAC::Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
ComputeHMAC(const uint8_t *k, uint32_t kl, const uint8_t *m, uint32_t ml,
|
ComputeHMAC(const uint8_t *k, const uint32_t kl,
|
||||||
|
const uint8_t *m, const uint32_t ml,
|
||||||
uint8_t *d)
|
uint8_t *d)
|
||||||
{
|
{
|
||||||
EMSHA_RESULT res;
|
EMSHAResult res;
|
||||||
HMAC h(k, kl);
|
HMAC h(k, kl);
|
||||||
|
|
||||||
res = h.Update(m, ml);
|
res = h.Update(m, ml);
|
||||||
if (EMSHA_ROK != res) {
|
if (res == EMSHAResult::OK) {
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = h.Result(d);
|
res = h.Result(d);
|
||||||
if (EMSHA_ROK != res) {
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
184
sha256.cc
184
sha256.cc
|
@ -69,13 +69,13 @@ static constexpr uint32_t emsha256H0[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
sha256Digest(const uint8_t *m, uint32_t ml, uint8_t *d)
|
SHA256Digest(const uint8_t *m, uint32_t ml, uint8_t *d)
|
||||||
{
|
{
|
||||||
SHA256 h;
|
SHA256 h;
|
||||||
EMSHA_RESULT ret;
|
EMSHAResult ret = EMSHAResult::Unknown;
|
||||||
|
|
||||||
if (EMSHA_ROK != (ret = h.Update(m, ml))) {
|
if (EMSHAResult::OK != (ret = h.Update(m, ml))) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,33 +92,35 @@ SHA256::SHA256()
|
||||||
|
|
||||||
SHA256::~SHA256()
|
SHA256::~SHA256()
|
||||||
{
|
{
|
||||||
memset(this->mb, 0, SHA256_MB_SIZE);
|
for (auto i = static_cast<uint32_t>(0); i < SHA256_MB_SIZE; i++) {
|
||||||
|
this->mb[i] = static_cast<uint8_t>(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
SHA256::addLength(const uint32_t l)
|
SHA256::addLength(const uint32_t l)
|
||||||
{
|
{
|
||||||
uint32_t tmp = this->mlen + l;
|
EMSHAResult res = EMSHAResult::InputTooLong;;
|
||||||
|
|
||||||
if (tmp < this->mlen) {
|
|
||||||
return SHA256_INPUT_TOO_LONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
uint32_t const tmp = static_cast<uint32_t>(this->mlen) + l;
|
||||||
|
if (tmp >= this->mlen) {
|
||||||
this->mlen = tmp;
|
this->mlen = tmp;
|
||||||
assert(this->mlen > 0);
|
assert(this->mlen > 0);
|
||||||
|
res = EMSHAResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
return EMSHA_ROK;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
SHA256::Reset()
|
SHA256::Reset()
|
||||||
{
|
{
|
||||||
return this->reset();
|
return this->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
SHA256::reset()
|
SHA256::reset()
|
||||||
{
|
{
|
||||||
// The message block is set to the initial hash vector.
|
// The message block is set to the initial hash vector.
|
||||||
|
@ -132,29 +134,47 @@ SHA256::reset()
|
||||||
this->i_hash[7] = emsha256H0[7];
|
this->i_hash[7] = emsha256H0[7];
|
||||||
|
|
||||||
this->mbi = 0;
|
this->mbi = 0;
|
||||||
this->hStatus = EMSHA_ROK;
|
this->hStatus = EMSHAResult::OK;
|
||||||
this->hComplete = 0;
|
this->hComplete = 0;
|
||||||
this->mlen = 0;
|
this->mlen = 0;
|
||||||
memset(this->mb, 0, SHA256_MB_SIZE);
|
|
||||||
|
std::fill(this->mb.begin(), this->mb.end(), 0);
|
||||||
|
|
||||||
return this->hStatus;
|
return this->hStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Read 32 bits from the byte buffer chunk as an unsigned 32-bit integer.
|
uint32_t
|
||||||
static uint32_t
|
SHA256::chunkToUint32(uint32_t offset)
|
||||||
chunkToUint32(const uint8_t *chunk)
|
|
||||||
{
|
{
|
||||||
return ((*chunk) << 24) |
|
uint32_t chunk = 0;
|
||||||
((*(chunk + 1)) << 16) |
|
|
||||||
((*(chunk + 2)) << 8) |
|
for (uint32_t i = offset; i < offset+4; i++) {
|
||||||
(*(chunk + 3));
|
chunk <<= 8;
|
||||||
|
chunk += static_cast<uint32_t>(this->mb[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
SHA256::uint32ToChunk(uint32_t offset)
|
||||||
|
{
|
||||||
|
uint32_t chunk = 0;
|
||||||
|
|
||||||
|
for (uint32_t i = offset; i < offset+4; i++) {
|
||||||
|
chunk <<= 8;
|
||||||
|
chunk += static_cast<uint32_t>(this->mb[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Copy an unsigned 32-bit integer into the start of the byte buffer chunk.
|
|
||||||
static void
|
static void
|
||||||
uint32ToChunk(uint32_t x, uint8_t *chunk)
|
uint32ToChunkInPlace(uint32_t x, uint8_t *chunk)
|
||||||
{
|
{
|
||||||
chunk[0] = (x & 0xff000000) >> 24;
|
chunk[0] = (x & 0xff000000) >> 24;
|
||||||
chunk[1] = (x & 0x00ff0000) >> 16;
|
chunk[1] = (x & 0x00ff0000) >> 16;
|
||||||
|
@ -180,7 +200,7 @@ SHA256::updateMessageBlock()
|
||||||
uint32_t h = 0;
|
uint32_t h = 0;
|
||||||
|
|
||||||
while (i < 16) {
|
while (i < 16) {
|
||||||
w[i++] = chunkToUint32(this->mb + chunk);
|
w[i++] = this->chunkToUint32(chunk);
|
||||||
chunk += 4;
|
chunk += 4;
|
||||||
}
|
}
|
||||||
this->mbi = 0;
|
this->mbi = 0;
|
||||||
|
@ -225,36 +245,36 @@ SHA256::updateMessageBlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
SHA256::Update(const uint8_t *m, uint32_t ml)
|
SHA256::Update(const std::uint8_t *message, std::uint32_t messageLength)
|
||||||
{
|
{
|
||||||
// Checking invariants:
|
// Checking invariants:
|
||||||
// If the message length is zero, there's nothing to be done.
|
// If the message length is zero, there's nothing to be done.
|
||||||
if (0 == ml) { return EMSHA_ROK; }
|
if (0 == messageLength) { return EMSHAResult::OK; }
|
||||||
|
|
||||||
// The message passed in cannot be the null pointer if the
|
// The message passed in cannot be the null pointer if the
|
||||||
// message length is greater than 0.
|
// message length is greater than 0.
|
||||||
if (nullptr == m) { return EMSHA_NULLPTR; }
|
if (message == nullptr) { return EMSHAResult::NullPointer; }
|
||||||
|
|
||||||
// If the SHA256 object is in a bad state, don't proceed.
|
// If the SHA256 object is in a bad state, don't proceed.
|
||||||
if (EMSHA_ROK != this->hStatus) { return this->hStatus; }
|
if (this->hStatus != EMSHAResult::OK) { return this->hStatus; }
|
||||||
|
|
||||||
// If the hash has been finalised, don't proceed.
|
// If the hash has been finalised, don't proceed.
|
||||||
if (0 != this->hComplete) { return EMSHA_INVALID_STATE; }
|
if (this->hComplete != static_cast<uint8_t>(0)) { return EMSHAResult::InvalidState; }
|
||||||
// Invariants satisfied by here.
|
// Invariants satisfied by here.
|
||||||
|
|
||||||
for (uint32_t i = 0; i < ml; i++) {
|
for (uint32_t i = 0; i < messageLength; i++) {
|
||||||
this->mb[this->mbi] = *(m + i);
|
this->mb[this->mbi] = *(message + i);
|
||||||
mbi++;
|
mbi++;
|
||||||
|
|
||||||
if (EMSHA_ROK == this->addLength(8)) {
|
if (EMSHAResult::OK == this->addLength(8)) {
|
||||||
if (SHA256_MB_SIZE == this->mbi) {
|
if (SHA256_MB_SIZE == this->mbi) {
|
||||||
this->updateMessageBlock();
|
this->updateMessageBlock();
|
||||||
|
|
||||||
// Assumption: following the message block
|
// Assumption: following the message block
|
||||||
// write, the context should still be in a good
|
// write, the context should still be in a good
|
||||||
// state.
|
// state.
|
||||||
assert(EMSHA_ROK == this->hStatus);
|
assert(EMSHAResult::OK == this->hStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,7 +287,7 @@ inline void
|
||||||
SHA256::padMessage(uint8_t pc)
|
SHA256::padMessage(uint8_t pc)
|
||||||
{
|
{
|
||||||
// Assumption: the context is not in a corrupted state.
|
// Assumption: the context is not in a corrupted state.
|
||||||
assert(EMSHA_ROK == this->hStatus);
|
assert(EMSHAResult::OK == this->hStatus);
|
||||||
|
|
||||||
if (this->mbi < (SHA256_MB_SIZE - 8)) {
|
if (this->mbi < (SHA256_MB_SIZE - 8)) {
|
||||||
this->mb[this->mbi++] = pc;
|
this->mb[this->mbi++] = pc;
|
||||||
|
@ -290,7 +310,7 @@ SHA256::padMessage(uint8_t pc)
|
||||||
|
|
||||||
// Assumption: updating the message block has not left the
|
// Assumption: updating the message block has not left the
|
||||||
// context in a corrupted state.
|
// context in a corrupted state.
|
||||||
assert(EMSHA_ROK == this->hStatus);
|
assert(EMSHAResult::OK == this->hStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (this->mbi < (SHA256_MB_SIZE - 8)) {
|
while (this->mbi < (SHA256_MB_SIZE - 8)) {
|
||||||
|
@ -320,76 +340,76 @@ SHA256::padMessage(uint8_t pc)
|
||||||
|
|
||||||
// Assumption: updating the message block has not left the context in a
|
// Assumption: updating the message block has not left the context in a
|
||||||
// corrupted state.
|
// corrupted state.
|
||||||
assert(EMSHA_ROK == this->hStatus);
|
assert(EMSHAResult::OK == this->hStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
SHA256::Finalise(uint8_t *d)
|
SHA256::Finalise(std::uint8_t *digest)
|
||||||
{
|
{
|
||||||
// Check invariants.
|
// Check invariants.
|
||||||
// The digest cannot be a null pointer; this library allocates
|
// The digest cannot be a null pointer; this library allocates
|
||||||
// no memory of its own.
|
// no memory of its own.
|
||||||
if (nullptr == d) { return EMSHA_NULLPTR; }
|
if (nullptr == digest) { return EMSHAResult::NullPointer; }
|
||||||
|
|
||||||
// If the SHA256 object is in a bad state, don't proceed.
|
// If the SHA256 object is in a bad state, don't proceed.
|
||||||
if (EMSHA_ROK != this->hStatus) { return this->hStatus; }
|
if (EMSHAResult::OK != this->hStatus) { return this->hStatus; }
|
||||||
|
|
||||||
// If the hash has been finalised, don't proceed.
|
// If the hash has been finalised, don't proceed.
|
||||||
if (0 != this->hComplete) { return EMSHA_INVALID_STATE; }
|
if (0 != this->hComplete) { return EMSHAResult::InvalidState; }
|
||||||
// Invariants satisfied by here.
|
// Invariants satisfied by here.
|
||||||
|
|
||||||
this->padMessage(0x80);
|
this->padMessage(0x80);
|
||||||
|
|
||||||
// Assumption: padding the message block has not left the context in a
|
// Assumption: padding the message block has not left the context in a
|
||||||
// corrupted state.
|
// corrupted state.
|
||||||
assert(EMSHA_ROK == this->hStatus);
|
assert(EMSHAResult::OK == this->hStatus);
|
||||||
std::fill(this->mb, this->mb + SHA256_MB_SIZE, 0);
|
std::fill(this->mb.begin(), this->mb.end(), 0);
|
||||||
|
|
||||||
this->hComplete = 1;
|
this->hComplete = 1;
|
||||||
this->mlen = 0;
|
this->mlen = 0;
|
||||||
|
|
||||||
uint32ToChunk(this->i_hash[0], d);
|
uint32ToChunkInPlace(this->i_hash[0], digest);
|
||||||
uint32ToChunk(this->i_hash[1], d + 4);
|
uint32ToChunkInPlace(this->i_hash[1], digest + 4);
|
||||||
uint32ToChunk(this->i_hash[2], d + 8);
|
uint32ToChunkInPlace(this->i_hash[2], digest + 8);
|
||||||
uint32ToChunk(this->i_hash[3], d + 12);
|
uint32ToChunkInPlace(this->i_hash[3], digest + 12);
|
||||||
uint32ToChunk(this->i_hash[4], d + 16);
|
uint32ToChunkInPlace(this->i_hash[4], digest + 16);
|
||||||
uint32ToChunk(this->i_hash[5], d + 20);
|
uint32ToChunkInPlace(this->i_hash[5], digest + 20);
|
||||||
uint32ToChunk(this->i_hash[6], d + 24);
|
uint32ToChunkInPlace(this->i_hash[6], digest + 24);
|
||||||
uint32ToChunk(this->i_hash[7], d + 28);
|
uint32ToChunkInPlace(this->i_hash[7], digest + 28);
|
||||||
|
|
||||||
return EMSHA_ROK;
|
return EMSHAResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
SHA256::Result(uint8_t *d)
|
SHA256::Result(std::uint8_t *digest)
|
||||||
{
|
{
|
||||||
// Check invariants.
|
// Check invariants.
|
||||||
|
|
||||||
// The digest cannot be a null pointer; this library allocates
|
// The digest cannot be a null pointer; this library allocates
|
||||||
// no memory of its own.
|
// no memory of its own.
|
||||||
if (nullptr == d) { return EMSHA_NULLPTR; }
|
if (nullptr == digest) { return EMSHAResult::NullPointer; }
|
||||||
|
|
||||||
// If the SHA256 object is in a bad state, don't proceed.
|
// If the SHA256 object is in a bad state, don't proceed.
|
||||||
if (EMSHA_ROK != this->hStatus) { return this->hStatus; }
|
if (EMSHAResult::OK != this->hStatus) { return this->hStatus; }
|
||||||
|
|
||||||
// Invariants satisfied by here.
|
// Invariants satisfied by here.
|
||||||
|
|
||||||
if (this->hComplete == 0U) {
|
if (this->hComplete == 0U) {
|
||||||
return this->Finalise(d);
|
return this->Finalise(digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32ToChunk(this->i_hash[0], d);
|
uint32ToChunkInPlace(this->i_hash[0], digest);
|
||||||
uint32ToChunk(this->i_hash[1], d + 4);
|
uint32ToChunkInPlace(this->i_hash[1], digest + 4);
|
||||||
uint32ToChunk(this->i_hash[2], d + 8);
|
uint32ToChunkInPlace(this->i_hash[2], digest + 8);
|
||||||
uint32ToChunk(this->i_hash[3], d + 12);
|
uint32ToChunkInPlace(this->i_hash[3], digest + 12);
|
||||||
uint32ToChunk(this->i_hash[4], d + 16);
|
uint32ToChunkInPlace(this->i_hash[4], digest + 16);
|
||||||
uint32ToChunk(this->i_hash[5], d + 20);
|
uint32ToChunkInPlace(this->i_hash[5], digest + 20);
|
||||||
uint32ToChunk(this->i_hash[6], d + 24);
|
uint32ToChunkInPlace(this->i_hash[6], digest + 24);
|
||||||
uint32ToChunk(this->i_hash[7], d + 28);
|
uint32ToChunkInPlace(this->i_hash[7], digest + 28);
|
||||||
|
|
||||||
return EMSHA_ROK;
|
return EMSHAResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -426,22 +446,22 @@ static const uint8_t helloWorld[] = {
|
||||||
|
|
||||||
constexpr uint32_t EMSHA_SELF_TEST_ITERS = 4;
|
constexpr uint32_t EMSHA_SELF_TEST_ITERS = 4;
|
||||||
|
|
||||||
static EMSHA_RESULT
|
static EMSHAResult
|
||||||
runTest(const uint8_t *input, uint32_t input_len, const uint8_t *expected)
|
runTest(const uint8_t *input, uint32_t input_len, const uint8_t *expected)
|
||||||
{
|
{
|
||||||
uint8_t hexString[65]{0};
|
uint8_t hexString[65]{0};
|
||||||
uint8_t d[SHA256_HASH_SIZE]{0};
|
uint8_t d[SHA256_HASH_SIZE]{0};
|
||||||
emsha::SHA256 ctx;
|
emsha::SHA256 ctx;
|
||||||
emsha::EMSHA_RESULT res;
|
emsha::EMSHAResult res;
|
||||||
|
|
||||||
res = ctx.Update(input, input_len);
|
res = ctx.Update(input, input_len);
|
||||||
if (EMSHA_ROK != res) {
|
if (EMSHAResult::OK != res) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t n = 0; n < EMSHA_SELF_TEST_ITERS; n++) {
|
for (uint32_t n = 0; n < EMSHA_SELF_TEST_ITERS; n++) {
|
||||||
res = ctx.Result(d);
|
res = ctx.Result(d);
|
||||||
if (EMSHA_ROK != res) {
|
if (EMSHAResult::OK != res) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,24 +471,24 @@ runTest(const uint8_t *input, uint32_t input_len, const uint8_t *expected)
|
||||||
std::cerr << "[!] have: " << hexString << "\n";
|
std::cerr << "[!] have: " << hexString << "\n";
|
||||||
HexString(hexString, const_cast<uint8_t *>(helloWorld), 32);
|
HexString(hexString, const_cast<uint8_t *>(helloWorld), 32);
|
||||||
std::cerr << "[!] want: " << hexString << "\n";
|
std::cerr << "[!] want: " << hexString << "\n";
|
||||||
return EMSHA_TEST_FAILURE;
|
return EMSHAResult::TestFailure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EMSHA_ROK;
|
return EMSHAResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
sha256SelfTest()
|
SHA256SelfTest()
|
||||||
{
|
{
|
||||||
EMSHA_RESULT res;
|
EMSHAResult res;
|
||||||
|
|
||||||
res = runTest(reinterpret_cast<const uint8_t *>(""), 0, emptyVector);
|
res = runTest(reinterpret_cast<const uint8_t *>(""), 0, emptyVector);
|
||||||
if (EMSHA_ROK == res) {
|
if (EMSHAResult::OK == res) {
|
||||||
res = runTest(reinterpret_cast<const uint8_t *>("hello, world"), 12, helloWorld);
|
res = runTest(reinterpret_cast<const uint8_t *>("hello, world"), 12, helloWorld);
|
||||||
if (res != EMSHA_ROK) {
|
if (res != EMSHAResult::OK) {
|
||||||
std::cerr << "[!] failed on hello, world.\n";
|
std::cerr << "[!] failed on hello, world.\n";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -480,10 +500,10 @@ sha256SelfTest()
|
||||||
|
|
||||||
|
|
||||||
#else // #ifdef EMSHA_NO_SELFTEST
|
#else // #ifdef EMSHA_NO_SELFTEST
|
||||||
EMSHA_RESULT
|
EMSHAResult
|
||||||
sha256_self_test()
|
sha256_self_test()
|
||||||
{
|
{
|
||||||
return EMSHA_SELFTEST_DISABLED;
|
return EMSHAResult::SelfTestDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <emsha/emsha.h>
|
#include <emsha/emsha.h>
|
||||||
|
|
||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
|
@ -33,6 +33,10 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
// how many test runs to benchmark hex strings?
|
||||||
|
static constexpr auto testIterations = 32768;
|
||||||
|
|
||||||
|
|
||||||
#ifndef EMSHA_NO_HEXSTRING
|
#ifndef EMSHA_NO_HEXSTRING
|
||||||
static void
|
static void
|
||||||
hexStringTest()
|
hexStringTest()
|
||||||
|
@ -49,19 +53,11 @@ hexStringTest()
|
||||||
emsha::HexString(out, buf, emsha::SHA256_HASH_SIZE);
|
emsha::HexString(out, buf, emsha::SHA256_HASH_SIZE);
|
||||||
string const outs(reinterpret_cast<const char *>(out));
|
string const outs(reinterpret_cast<const char *>(out));
|
||||||
if (outs != expected) {
|
if (outs != expected) {
|
||||||
cerr << "FAILED: HexString" << endl;
|
cerr << "FAILED: HexString\n";
|
||||||
cerr << "\twanted: " << expected << endl;
|
cerr << "\twanted: " << expected << "\n";
|
||||||
cerr << "\thave: " << out << endl;
|
cerr << "\thave: " << out << "\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "PASSED: HexString ";
|
|
||||||
#ifdef EMSHA_NO_HEXLUT
|
|
||||||
cout << "(small LUT)";
|
|
||||||
#else // #ifdef EMSHA_NO_HEXLUT
|
|
||||||
cout << "(large LUT)";
|
|
||||||
#endif // #ifdef EMSHA_NO_HEXLUT
|
|
||||||
cout << endl;
|
|
||||||
}
|
}
|
||||||
#endif // #ifndef EMSHA_NO_HEXSTRING
|
#endif // #ifndef EMSHA_NO_HEXSTRING
|
||||||
|
|
||||||
|
@ -84,9 +80,9 @@ hashEqualTest()
|
||||||
cerr << "FAILED: HashEqual\n";
|
cerr << "FAILED: HashEqual\n";
|
||||||
cerr << "\tHashEqual should have succeeded comparing a and b.\n";
|
cerr << "\tHashEqual should have succeeded comparing a and b.\n";
|
||||||
DumpHexString(s, a, emsha::SHA256_HASH_SIZE);
|
DumpHexString(s, a, emsha::SHA256_HASH_SIZE);
|
||||||
cerr << "\ta <- " << s << std::endl;
|
cerr << "\ta <- " << s << "\n";
|
||||||
DumpHexString(s, b, emsha::SHA256_HASH_SIZE);
|
DumpHexString(s, b, emsha::SHA256_HASH_SIZE);
|
||||||
cerr << "\tb <- " << s << std::endl;
|
cerr << "\tb <- " << s << "\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,9 +96,9 @@ hashEqualTest()
|
||||||
cerr << "FAILED: HashEqual\n";
|
cerr << "FAILED: HashEqual\n";
|
||||||
cerr << "\tHashEqual should not have succeeded comparing a and b.\n";
|
cerr << "\tHashEqual should not have succeeded comparing a and b.\n";
|
||||||
DumpHexString(s, a, emsha::SHA256_HASH_SIZE);
|
DumpHexString(s, a, emsha::SHA256_HASH_SIZE);
|
||||||
cerr << "\ta <- " << s << std::endl;
|
cerr << "\ta <- " << s << "\n";
|
||||||
DumpHexString(s, b, emsha::SHA256_HASH_SIZE);
|
DumpHexString(s, b, emsha::SHA256_HASH_SIZE);
|
||||||
cerr << "\tb <- " << s << std::endl;
|
cerr << "\tb <- " << s << "\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,17 +122,33 @@ hashEqualTest()
|
||||||
cerr << "\tb <- " << s << std::endl;
|
cerr << "\tb <- " << s << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cout << "PASSED: HashEqual\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
auto start = std::chrono::steady_clock::now();
|
||||||
|
std::string testLabel;
|
||||||
|
|
||||||
|
for (auto i = 0; i < testIterations; i++) {
|
||||||
#ifndef EMSHA_NO_HEXSTRING
|
#ifndef EMSHA_NO_HEXSTRING
|
||||||
|
#ifndef EMSHA_NO_HEXLUT
|
||||||
|
testLabel = "(large LUT) ";
|
||||||
|
#endif
|
||||||
hexStringTest();
|
hexStringTest();
|
||||||
#endif
|
#endif
|
||||||
hashEqualTest();
|
hashEqualTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto end = std::chrono::steady_clock::now();
|
||||||
|
auto delta = (end - start);
|
||||||
|
|
||||||
|
std::cout << "Passed HexString " << testLabel << "tests.\n";
|
||||||
|
std::cout << "Total time: "
|
||||||
|
<< std::chrono::duration<double, std::milli>(delta).count()
|
||||||
|
<< " ms\n";
|
||||||
|
std::cout << "Average over " << testIterations << " tests: "
|
||||||
|
<< std::chrono::duration<double, std::nano>(delta).count() / testIterations
|
||||||
|
<< " ns\n";
|
||||||
|
}
|
||||||
|
|
20
test_mem.cc
20
test_mem.cc
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
|
|
||||||
// Number of test iterations.
|
// Number of test iterations.
|
||||||
static constexpr std::uint32_t ITERS = 8192;
|
static constexpr std::uint32_t ITERS = 32768;
|
||||||
|
|
||||||
// The key used for HMAC.
|
// The key used for HMAC.
|
||||||
static constexpr std::uint8_t k[] = {
|
static constexpr std::uint8_t k[] = {
|
||||||
|
@ -112,12 +112,12 @@ iterateSHA()
|
||||||
{
|
{
|
||||||
emsha::SHA256 ctx;
|
emsha::SHA256 ctx;
|
||||||
int cmp = 0;
|
int cmp = 0;
|
||||||
emsha::EMSHA_RESULT res;
|
emsha::EMSHAResult res;
|
||||||
|
|
||||||
res = ctx.Update(m, sizeof(m));
|
res = ctx.Update(m, sizeof(m));
|
||||||
assert(emsha::EMSHA_ROK == res);
|
assert(emsha::EMSHAResult::OK == res);
|
||||||
res = ctx.Result(dig);
|
res = ctx.Result(dig);
|
||||||
assert(emsha::EMSHA_ROK == res);
|
assert(emsha::EMSHAResult::OK == res);
|
||||||
|
|
||||||
cmp = std::memcmp(dig, d, emsha::SHA256_HASH_SIZE);
|
cmp = std::memcmp(dig, d, emsha::SHA256_HASH_SIZE);
|
||||||
assert(0 == cmp);
|
assert(0 == cmp);
|
||||||
|
@ -129,12 +129,12 @@ iterateHMAC()
|
||||||
{
|
{
|
||||||
emsha::HMAC ctx(k, kl);
|
emsha::HMAC ctx(k, kl);
|
||||||
int cmp = 0;
|
int cmp = 0;
|
||||||
emsha::EMSHA_RESULT res;
|
emsha::EMSHAResult res;
|
||||||
|
|
||||||
res = ctx.Update(m, sizeof(m));
|
res = ctx.Update(m, sizeof(m));
|
||||||
assert(emsha::EMSHA_ROK == res);
|
assert(emsha::EMSHAResult::OK == res);
|
||||||
res = ctx.Result(dig);
|
res = ctx.Result(dig);
|
||||||
assert(emsha::EMSHA_ROK == res);
|
assert(emsha::EMSHAResult::OK == res);
|
||||||
|
|
||||||
cmp = std::memcmp(dig, t, emsha::SHA256_HASH_SIZE);
|
cmp = std::memcmp(dig, t, emsha::SHA256_HASH_SIZE);
|
||||||
assert(0 == cmp);
|
assert(0 == cmp);
|
||||||
|
@ -146,7 +146,7 @@ iterateSHASP()
|
||||||
{
|
{
|
||||||
int cmp = 0;
|
int cmp = 0;
|
||||||
|
|
||||||
assert(emsha::EMSHA_ROK == emsha::sha256Digest(m, sizeof(m), dig));
|
assert(emsha::EMSHAResult::OK == emsha::SHA256Digest(m, sizeof(m), dig));
|
||||||
cmp = std::memcmp(dig, d, emsha::SHA256_HASH_SIZE);
|
cmp = std::memcmp(dig, d, emsha::SHA256_HASH_SIZE);
|
||||||
assert(0 == cmp);
|
assert(0 == cmp);
|
||||||
}
|
}
|
||||||
|
@ -156,10 +156,10 @@ static void
|
||||||
iterateHMACSP()
|
iterateHMACSP()
|
||||||
{
|
{
|
||||||
int cmp = 0;
|
int cmp = 0;
|
||||||
emsha::EMSHA_RESULT res;
|
emsha::EMSHAResult res;
|
||||||
|
|
||||||
res = emsha::ComputeHMAC(k, kl, m, sizeof(m), dig);
|
res = emsha::ComputeHMAC(k, kl, m, sizeof(m), dig);
|
||||||
assert(emsha::EMSHA_ROK == res);
|
assert(emsha::EMSHAResult::OK == res);
|
||||||
|
|
||||||
cmp = std::memcmp(dig, t, emsha::SHA256_HASH_SIZE);
|
cmp = std::memcmp(dig, t, emsha::SHA256_HASH_SIZE);
|
||||||
assert(0 == cmp);
|
assert(0 == cmp);
|
||||||
|
|
|
@ -76,18 +76,34 @@ main()
|
||||||
#ifdef EMSHA_NO_SELFTEST
|
#ifdef EMSHA_NO_SELFTEST
|
||||||
cout << "[NOTICE] internal self-tests have been disabled.\n";
|
cout << "[NOTICE] internal self-tests have been disabled.\n";
|
||||||
#else
|
#else
|
||||||
auto selfTestStatus = emsha::sha256SelfTest();
|
auto selfTestStatus = emsha::SHA256SelfTest();
|
||||||
switch (selfTestStatus) {
|
switch (selfTestStatus) {
|
||||||
case emsha::EMSHA_ROK:
|
case emsha::EMSHAResult::OK:
|
||||||
cout << "PASSED: SHA-256 self test\n";
|
cout << "PASSED: SHA-256 self test\n";
|
||||||
break;
|
break;
|
||||||
case emsha::EMSHA_TEST_FAILURE:
|
case emsha::EMSHAResult::TestFailure:
|
||||||
cout << "FAILED: SHA-256 self test (test failure)\n";
|
cout << "FAILED: SHA-256 self-test\n";
|
||||||
|
break;
|
||||||
|
case emsha::EMSHAResult::Unknown:
|
||||||
|
cout << "FAILED: SHA-256 self test (fault: Unknown)\n";
|
||||||
|
break;
|
||||||
|
case emsha::EMSHAResult::NullPointer:
|
||||||
|
cout << "FAILED: SHA-256 self test (fault: NullPointer)\n";
|
||||||
|
break;
|
||||||
|
case emsha::EMSHAResult::InvalidState:
|
||||||
|
cout << "FAILED: SHA-256 self test (fault: InvalidState)\n";
|
||||||
|
break;
|
||||||
|
case emsha::EMSHAResult::InputTooLong:
|
||||||
|
cout << "FAILED: SHA-256 self test (fault: InputTooLong)\n";
|
||||||
|
break;
|
||||||
|
case emsha::EMSHAResult::SelfTestDisabled:
|
||||||
|
cout << "FAILED: SHA-256 self test (fault: SelfTestDisabled)\n";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cout << "FAILED: SHA-256 self test (fault " << selfTestStatus << ")\n";
|
cout << "FAILED: SHA-256 self test (fault: internal system failure)\n";
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
assert(selfTestStatus == emsha::EMSHA_ROK);
|
assert(selfTestStatus == emsha::EMSHAResult::OK);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -53,28 +53,28 @@ DumpHexString(std::string& hs, uint8_t *s, uint32_t sl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
emsha::EMSHA_RESULT
|
emsha::EMSHAResult
|
||||||
runHMACTest(const struct hmacTest test, const string& label)
|
runHMACTest(const struct hmacTest& test, const string& label)
|
||||||
{
|
{
|
||||||
emsha::HMAC h(test.key, test.keylen);
|
emsha::HMAC h(test.key, test.keylen);
|
||||||
emsha::EMSHA_RESULT res;
|
emsha::EMSHAResult res;
|
||||||
uint8_t dig[emsha::SHA256_HASH_SIZE];
|
uint8_t dig[emsha::SHA256_HASH_SIZE];
|
||||||
string hs;
|
string hs;
|
||||||
|
|
||||||
res = h.Update((uint8_t *)test.input.c_str(), test.input.size());
|
res = h.Update((uint8_t *)test.input.c_str(), test.input.size());
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
|
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
|
||||||
res = h.Result(dig);
|
res = h.Result(dig);
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
||||||
if (hs != test.output) {
|
if (hs != test.output) {
|
||||||
res = emsha::EMSHA_TEST_FAILURE;
|
res = emsha::EMSHAResult::TestFailure;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
||||||
|
@ -84,19 +84,19 @@ runHMACTest(const struct hmacTest test, const string& label)
|
||||||
h.Reset();
|
h.Reset();
|
||||||
|
|
||||||
res = h.Update((uint8_t *)test.input.c_str(), test.input.size());
|
res = h.Update((uint8_t *)test.input.c_str(), test.input.size());
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
|
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
|
||||||
res = h.Result(dig);
|
res = h.Result(dig);
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
||||||
if (hs != test.output) {
|
if (hs != test.output) {
|
||||||
res = emsha::EMSHA_TEST_FAILURE;
|
res = emsha::EMSHAResult::TestFailure;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
||||||
|
@ -106,7 +106,7 @@ runHMACTest(const struct hmacTest test, const string& label)
|
||||||
res = emsha::ComputeHMAC(test.key, test.keylen,
|
res = emsha::ComputeHMAC(test.key, test.keylen,
|
||||||
(uint8_t *)test.input.c_str(), test.input.size(),
|
(uint8_t *)test.input.c_str(), test.input.size(),
|
||||||
dig);
|
dig);
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
cerr << "(running single pass function test)\n";
|
cerr << "(running single pass function test)\n";
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -114,15 +114,15 @@ runHMACTest(const struct hmacTest test, const string& label)
|
||||||
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
||||||
if (hs != test.output) {
|
if (hs != test.output) {
|
||||||
cerr << "(comparing single pass function output)\n";
|
cerr << "(comparing single pass function output)\n";
|
||||||
res = emsha::EMSHA_TEST_FAILURE;
|
res = emsha::EMSHAResult::TestFailure;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
||||||
|
|
||||||
res = emsha::EMSHA_ROK;
|
res = emsha::EMSHAResult::OK;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
cerr << "FAILED: " << label << endl;
|
cerr << "FAILED: " << label << endl;
|
||||||
cerr << "\tinput: " << test.input << endl;
|
cerr << "\tinput: " << test.input << endl;
|
||||||
cerr << "\twanted: " << test.output << endl;
|
cerr << "\twanted: " << test.output << endl;
|
||||||
|
@ -137,7 +137,7 @@ int
|
||||||
runHMACTests(const struct hmacTest *tests, size_t nTests, const string& label)
|
runHMACTests(const struct hmacTest *tests, size_t nTests, const string& label)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < nTests; i++) {
|
for (uint32_t i = 0; i < nTests; i++) {
|
||||||
if (emsha::EMSHA_ROK != runHMACTest(*(tests + i), label)) {
|
if (emsha::EMSHAResult::OK != runHMACTest(*(tests + i), label)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,28 +146,28 @@ runHMACTests(const struct hmacTest *tests, size_t nTests, const string& label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
emsha::EMSHA_RESULT
|
emsha::EMSHAResult
|
||||||
runHashTest(const struct hashTest& test, const string& label)
|
runHashTest(const struct hashTest& test, const string& label)
|
||||||
{
|
{
|
||||||
emsha::SHA256 ctx;
|
emsha::SHA256 ctx;
|
||||||
emsha::EMSHA_RESULT res;
|
emsha::EMSHAResult res;
|
||||||
uint8_t dig[emsha::SHA256_HASH_SIZE];
|
uint8_t dig[emsha::SHA256_HASH_SIZE];
|
||||||
string hs;
|
string hs;
|
||||||
|
|
||||||
res = ctx.Update((uint8_t *)test.input.c_str(), test.input.size());
|
res = ctx.Update((uint8_t *)test.input.c_str(), test.input.size());
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
|
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
|
||||||
res = ctx.Result(dig);
|
res = ctx.Result(dig);
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
||||||
if (hs != test.output) {
|
if (hs != test.output) {
|
||||||
res = emsha::EMSHA_TEST_FAILURE;
|
res = emsha::EMSHAResult::TestFailure;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
||||||
|
@ -177,28 +177,28 @@ runHashTest(const struct hashTest& test, const string& label)
|
||||||
ctx.Reset();
|
ctx.Reset();
|
||||||
|
|
||||||
res = ctx.Update((uint8_t *)test.input.c_str(), test.input.size());
|
res = ctx.Update((uint8_t *)test.input.c_str(), test.input.size());
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
|
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
|
||||||
res = ctx.Result(dig);
|
res = ctx.Result(dig);
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
||||||
if (hs != test.output) {
|
if (hs != test.output) {
|
||||||
res = emsha::EMSHA_TEST_FAILURE;
|
res = emsha::EMSHAResult::TestFailure;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the single-pass function works.
|
// Test that the single-pass function works.
|
||||||
res = emsha::sha256Digest((uint8_t *) test.input.c_str(),
|
res = emsha::SHA256Digest((uint8_t *) test.input.c_str(),
|
||||||
test.input.size(), dig);
|
test.input.size(), dig);
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
cerr << "(running single pass function test)\n";
|
cerr << "(running single pass function test)\n";
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -206,14 +206,14 @@ runHashTest(const struct hashTest& test, const string& label)
|
||||||
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
|
||||||
if (hs != test.output) {
|
if (hs != test.output) {
|
||||||
cerr << "(comparing single pass function output)\n";
|
cerr << "(comparing single pass function output)\n";
|
||||||
res = emsha::EMSHA_TEST_FAILURE;
|
res = emsha::EMSHAResult::TestFailure;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
memset(dig, 0, emsha::SHA256_HASH_SIZE);
|
||||||
res = emsha::EMSHA_ROK;
|
res = emsha::EMSHAResult::OK;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (emsha::EMSHA_ROK != res) {
|
if (emsha::EMSHAResult::OK != res) {
|
||||||
cerr << "FAILED: " << label << endl;
|
cerr << "FAILED: " << label << endl;
|
||||||
cerr << "\tinput: '" << test.input << "'" << endl;
|
cerr << "\tinput: '" << test.input << "'" << endl;
|
||||||
cerr << "\twanted: " << test.output << endl;
|
cerr << "\twanted: " << test.output << endl;
|
||||||
|
@ -227,7 +227,7 @@ int
|
||||||
runHashTests(const struct hashTest *tests, const size_t ntests, const string& label)
|
runHashTests(const struct hashTest *tests, const size_t ntests, const string& label)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < ntests; i++) {
|
for (uint32_t i = 0; i < ntests; i++) {
|
||||||
if (emsha::EMSHA_ROK != runHashTest(*(tests + i), label)) {
|
if (emsha::EMSHAResult::OK != runHashTest(*(tests + i), label)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,13 +64,13 @@ void dump_pair(std::uint8_t *, std::uint8_t *);
|
||||||
|
|
||||||
|
|
||||||
// SHA-256 testing functions.
|
// SHA-256 testing functions.
|
||||||
emsha::EMSHA_RESULT runHashTest(const struct hashTest& test, const std::string& label);
|
emsha::EMSHAResult runHashTest(const struct hashTest& test, const std::string& label);
|
||||||
int runHashTests(const struct hashTest *tests, const std::size_t nTests,
|
int runHashTests(const struct hashTest *tests, const std::size_t nTests,
|
||||||
const std::string& label);
|
const std::string& label);
|
||||||
|
|
||||||
|
|
||||||
// HMAC-SHA-256 testery.
|
// HMAC-SHA-256 testery.
|
||||||
emsha::EMSHA_RESULT runHMACTest(struct hmacTest test, const std::string& label);
|
emsha::EMSHAResult runHMACTest(struct hmacTest& test, const std::string& label);
|
||||||
int runHMACTests(const struct hmacTest *tests, std::size_t nTests,
|
int runHMACTests(const struct hmacTest *tests, std::size_t nTests,
|
||||||
const std::string& label);
|
const std::string& label);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue