emsha/include/emsha/sha256.h

195 lines
7.1 KiB
C++

///
/// \file emsha/sha256.h
/// \author K. Isom <kyle@imap.cc>
/// \date 2015-12-17
/// \brief Declares an interface for producing SHA-256 hashes.
///
/// The MIT License (MIT)
///
/// Copyright (c) 2015 K. Isom <coder@kyleisom.net>
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// copy of this software and associated documentation files (the "Software"),
/// to deal in the Software without restriction, including without limitation
/// the rights to use, copy, modify, merge, publish, distribute, sublicense,
/// and/or sell copies of the Software, and to permit persons to whom the
/// Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
/// IN THE SOFTWARE.
///
#ifndef EMSHA_SHA256_H
#define EMSHA_SHA256_H
#include <cstdint>
#include <array>
#include <emsha/emsha.h>
namespace emsha {
/// SHA256_MB_SIZE is the size of a message block.
const uint32_t SHA256_MB_SIZE = 64;
class SHA256 : Hash {
public:
/// \brief A SHA256 context does not need any special
/// construction.
///
/// It can be declared and immediately start being used.
SHA256();
/// The SHA256 destructor will clear out its internal
/// message buffer; all the members are local and
/// not resource handles, so cleanup is minimal.
~SHA256();
/// \brief Clear the internal state of the SHA256 context,
/// returning it to its initial state.
///
/// \return This should always return EMSHAResult::OK.
EMSHAResult Reset() override;
/// \brief Writes data into the SHA256.
///
/// While there is an upper limit on the size of data that
/// SHA-256 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 message A byte array containing the message to be
/// written. It must not be NULL (unless the
/// message length is zero).
/// \param messageLength The message length, in bytes.
/// \return An ::EMSHAResult describing the result of the
/// operation.
///
/// - EMSHAResult::NullPointer is returned if m is a
/// nullptr 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 added to the SHA-256 context.
EMSHAResult Update(const std::uint8_t *message, std::uint32_t messageLength) override;
/// \brief Complete the digest.
///
/// Once this method is called, the context cannot be updated
/// unless the context is reset.
///
/// \param digest byte buffer that must be at least
/// SHA256.size() in length.
/// \return An ::EMSHAResult describing the result of the
/// operation.
///
/// - EMSHAResult::NullPointer is returned if a nullptr
/// is passed in.
/// - EMSHAResult::InvalidState is returned if the
/// SHA-256 context is in an invalid state, such as
/// if there were errors in previous updates.
/// - EMSHAResult::OK is returned if the context was
/// successfully finalised and the digest copied to
/// digest.
EMSHAResult Finalise(std::uint8_t *digest) override;
/// \brief Copy the result from the SHA-256
/// context into the buffer pointed to by d,
/// running #Finalise if needed. Once called,
/// the context cannot be updated until the
/// context is reset.
///
/// \param digest A byte buffer that must be at least
/// SHA256.size() in length.
/// \return An ::EMSHAResult describing the result of the
/// operation.
///
/// - EMSHAResult::NullPointer is returned if a nullptr
/// is passed in.
/// - EMSHAResult::InvalidState is returned if the
/// SHA-256 context is in an invalid state, such as
/// if there were errors in previous updates.
/// - EMSHAResult::OK is returned if the context was
/// successfully finalised and the digest copied to
/// digest.
EMSHAResult Result(std::uint8_t *digest) override;
/// \brief Returns the output size of SHA-256.
///
/// The buffers passed to #Update and #Finalise should be at
/// least this size.
///
/// \return The expected size of buffers passed to result and
/// finalize.
std::uint32_t Size() override;
private:
uint64_t mlen; // Current message length.
uint32_t i_hash[8]; // The intermediate hash is 8x 32-bit blocks.
// hStatus is the hash status, and hComplete indicates
// whether the hash has been finalised.
EMSHAResult hStatus;
uint8_t hComplete;
// mb is the message block, and mbi is the message
// block index.
uint8_t mbi;
std::array<uint8_t, SHA256_MB_SIZE> mb;
inline EMSHAResult addLength(const uint32_t);
inline void updateMessageBlock(void);
inline void padMessage(uint8_t pc);
uint32_t chunkToUint32(uint32_t offset);
uint32_t uint32ToChunk(uint32_t offset);
EMSHAResult reset();
}; // end class SHA256
/// \brief SHA256Digest performs a single pass hashing of the message
/// passed in.
///
/// \param m Byte buffer containing the message to hash.
/// \param ml The length of m.
/// \param d Byte buffer that will be used to store the resulting hash;
/// it should have at least emsha::SHA256_HASH_SIZE bytes
/// available.
/// \return An ::EMSHAResult describing the result of the operation.
EMSHAResult SHA256Digest(const uint8_t *m, uint32_t ml, uint8_t *d);
/// \brief SHA256SelfTest runs through two test cases to ensure that the
/// SHA-256 functions are working correctly.
///
/// \return The result of the self-test.
///
/// - EMSHAResult::OK is returned if the self tests pass.
/// - 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
#endif // EMSHA_SHA256_H