mirror of
https://github.com/taigrr/arduinolibs
synced 2025-01-18 04:33:12 -08:00
201 lines
5.7 KiB
C++
201 lines
5.7 KiB
C++
/*
|
|
* Copyright (C) 2016 Southern Storm Software, Pty Ltd.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* 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.
|
|
*/
|
|
|
|
#include "OMAC.h"
|
|
#include "GF128.h"
|
|
#include "Crypto.h"
|
|
#include <string.h>
|
|
|
|
/**
|
|
* \class OMAC OMAC.h <OMAC.h>
|
|
* \brief Implementation of the OMAC message authenticator.
|
|
*
|
|
* OMAC is the message authentication part of EAX mode. It is provided
|
|
* as a separate class for the convenience of applications that need
|
|
* message authentication separate from encryption.
|
|
*
|
|
* References: https://en.wikipedia.org/wiki/EAX_mode,
|
|
* http://web.cs.ucdavis.edu/~rogaway/papers/eax.html
|
|
*
|
|
* \sa EAX
|
|
*/
|
|
|
|
/**
|
|
* \brief Constructs a new OMAC object.
|
|
*
|
|
* This constructor must be followed by a call to setBlockCipher()
|
|
* to specify the block cipher to use.
|
|
*/
|
|
OMAC::OMAC()
|
|
: _blockCipher(0)
|
|
, posn(0)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* \brief Destroys this OMAC object.
|
|
*
|
|
* \sa clear()
|
|
*/
|
|
OMAC::~OMAC()
|
|
{
|
|
clean(b);
|
|
}
|
|
|
|
/**
|
|
* \fn BlockCipher *OMAC::blockCipher() const
|
|
* \brief Gets the block cipher that is in use for this OMAC object.
|
|
*
|
|
* \sa setBlockCipher()
|
|
*/
|
|
|
|
/**
|
|
* \fn void OMAC::setBlockCipher(BlockCipher *cipher)
|
|
* \brief Sets the block cipher to use for this OMAC object.
|
|
*
|
|
* \param cipher The block cipher to use to implement OMAC.
|
|
* This object must have a block size of 128 bits (16 bytes).
|
|
*
|
|
* \sa blockCipher()
|
|
*/
|
|
|
|
/**
|
|
* \brief Initialises the first OMAC hashing context and creates the B value.
|
|
*
|
|
* \param omac The OMAC hashing context.
|
|
*
|
|
* This function must be called first before initNext(), update(), or
|
|
* finalize() to create the B value from the OMAC algorithm which is
|
|
* used to finalize later hashes. It is assumed that setBlockCipher()
|
|
* has already been called.
|
|
*
|
|
* The tag value for the context is implicitly set to zero, which means
|
|
* that the context can be used for ordinary hashing as long as the
|
|
* data that follows is non-zero in length. Alternatively, initNext()
|
|
* can be called to restart the context with a specific tag.
|
|
*
|
|
* This function must be called again whenever the block cipher or the
|
|
* key changes.
|
|
*
|
|
* \sa initNext(), update(), finalize()
|
|
*/
|
|
void OMAC::initFirst(uint8_t omac[16])
|
|
{
|
|
// Start the OMAC context. We assume that the data that follows
|
|
// will be at least 1 byte in length so that we can encrypt the
|
|
// zeroes now to derive the B value.
|
|
memset(omac, 0, 16);
|
|
_blockCipher->encryptBlock(omac, omac);
|
|
posn = 0;
|
|
|
|
// Generate the B value from the encrypted block of zeroes.
|
|
// We will need this later when finalising the OMAC hashes.
|
|
memcpy(b, omac, 16);
|
|
GF128::dblEAX(b);
|
|
}
|
|
|
|
/**
|
|
* \brief Initialises or restarts an OMAC hashing context.
|
|
*
|
|
* \param omac The OMAC hashing context.
|
|
* \param tag The tag value indicating which OMAC calculation we are doing.
|
|
*
|
|
* It is assumed that initFirst() was called previously to create the B
|
|
* value for the context.
|
|
*
|
|
* \sa initFirst(), update(), finalize()
|
|
*/
|
|
void OMAC::initNext(uint8_t omac[16], uint8_t tag)
|
|
{
|
|
memset(omac, 0, 15);
|
|
omac[15] = tag;
|
|
posn = 16;
|
|
}
|
|
|
|
/**
|
|
* \brief Updates an OMAC hashing context with more data.
|
|
*
|
|
* \param omac The OMAC hashing context.
|
|
* \param data Points to the data to be hashed.
|
|
* \param size The number of bytes to be hashed.
|
|
*
|
|
* \sa initFirst(), initNext(), finalize()
|
|
*/
|
|
void OMAC::update(uint8_t omac[16], const uint8_t *data, size_t size)
|
|
{
|
|
while (size > 0) {
|
|
// Encrypt the current block if it is already full.
|
|
if (posn == 16) {
|
|
_blockCipher->encryptBlock(omac, omac);
|
|
posn = 0;
|
|
}
|
|
|
|
// XOR the incoming data with the current block.
|
|
uint8_t len = 16 - posn;
|
|
if (len > size)
|
|
len = (uint8_t)size;
|
|
for (uint8_t index = 0; index < len; ++index)
|
|
omac[posn++] ^= data[index];
|
|
|
|
// Move onto the next block.
|
|
size -= len;
|
|
data += len;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Finalises an OMAC hashing context.
|
|
*
|
|
* \param omac The OMAC hashing context on entry, the final OMAC value on exit.
|
|
*
|
|
* \sa initFirst(), initNext(), update()
|
|
*/
|
|
void OMAC::finalize(uint8_t omac[16])
|
|
{
|
|
// Apply padding if necessary.
|
|
if (posn != 16) {
|
|
// Need padding: XOR with P = 2 * B.
|
|
uint32_t p[4];
|
|
memcpy(p, b, 16);
|
|
GF128::dblEAX(p);
|
|
omac[posn] ^= 0x80;
|
|
for (uint8_t index = 0; index < 16; ++index)
|
|
omac[index] ^= ((const uint8_t *)p)[index];
|
|
clean(p);
|
|
} else {
|
|
// No padding necessary: XOR with B.
|
|
for (uint8_t index = 0; index < 16; ++index)
|
|
omac[index] ^= ((const uint8_t *)b)[index];
|
|
}
|
|
|
|
// Encrypt the hash to get the final OMAC value.
|
|
_blockCipher->encryptBlock(omac, omac);
|
|
}
|
|
|
|
/**
|
|
* \brief Clears all security-sensitive state from this object.
|
|
*/
|
|
void OMAC::clear()
|
|
{
|
|
clean(b);
|
|
}
|