emsha/emsha/hmac.h

181 lines
6.4 KiB
C++

///
/// \file emsha/hmac.h
/// \author K. Isom <kyle@imap.cc>
/// \date 2015-12-17
/// \brief Declares an interface for HMAC tagging.
///
/// 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_HMAC_H
#define EMSHA_HMAC_H
#include <cstdint>
#include "emsha.h"
#include "sha256.h"
namespace emsha {
const uint32_t HMAC_KEY_LENGTH = SHA256_MB_SIZE;
/// HMAC is a keyed hash that can be used to produce an
/// authenticated hash of some data. The HMAC is built on
/// (and uses internally) the SHA256 class; it's helpful to
/// note that faults that occur in the SHA-256 code will be
/// propagated up as the return value from many of the HMAC
/// functions.
class HMAC : Hash {
public:
/// \brief Construct an HMAC with its initial key.
///
/// An HMAC is constructed with a key and the length of the
/// key. This key is stored in the HMAC context, and is wiped
/// by the HMAC destructor.
///
/// \param k The HMAC key.
/// \param kl THe length of the HMAC key.
HMAC(const uint8_t *k, uint32_t kl);
/// \brief Clear any data written to the HMAC.
///
/// This is equivalent to constructing a new HMAC, but it
/// preserves the keys.
///
/// \return EMSHAResult::OK is returned if the reset occurred
/// without (detected) fault. If a fault occurs with
/// the underlying SHA256 context, the error code is
/// returned.
EMSHAResult Reset() override;
/// \brief Write data into the context.
///
/// 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.
/// \param messageLength The message length, in bytes.
/// \return An ::EMSHAResult describing the result of the
/// operation.
///
/// - 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;
/// \brief Complete the HMAC computation.
///
/// \note Once #Finalise is called, the context cannot be
/// updated unless the context is reset.
///
/// \param digest A byte buffer that must be at least #HMAC.Size()
/// in length.
/// \return An EMSHAResult describing the result of this
/// method:
///
/// - EMSHAResult::NullPointer is returned if d is a
/// null pointer.
/// - EMSHAResult::InvalidState is returned if the HMAC
/// 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 d.
///
EMSHAResult Finalise(std::uint8_t *digest) override;
/// \brief Copy the current digest into a destination buffer.
///
/// Copy the current digest from the HMAC context into
/// `digest`, 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 #HMAC.size()
/// in length.
/// \return An ::EMSHAResult describing the result of this
/// method:
///
/// - EMSHAResult::NullPointer is returned if d is a
/// null pointer.
/// - EMSHAResult::InvalidState is returned if the HMAC
/// 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 d.
EMSHAResult Result(std::uint8_t *digest) override;
/// \brief Returns the output size of HMAC-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;
/// When an HMAC context is destroyed, it is reset and
/// the key material is zeroised using the STL `fill`
/// function.
~HMAC();
private:
uint8_t hstate;
SHA256 ctx;
uint8_t k[HMAC_KEY_LENGTH];
uint8_t buf[SHA256_HASH_SIZE];
EMSHAResult reset();
inline EMSHAResult finalResult(uint8_t *d);
};
/// \brief Perform a single-pass HMAC computation over a message.
///
/// \param 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.
/// \param ml The length of the message.
/// \param d Byte buffer that will be used to store the resulting
/// HMAC. It should be emsha::SHA256_HASH_SIZE bytes in size.
/// \return An ::EMSHAResult describing the result of the HMAC operation.
EMSHAResult
ComputeHMAC(const uint8_t *k, const uint32_t kl,
const uint8_t *m, const uint32_t ml,
uint8_t *d);
} // end of namespace emsha
#endif // EMSHA_HMAC_H