mirror of
https://github.com/taigrr/arduinolibs
synced 2025-01-18 04:33:12 -08:00
Split the OMAC code out of EAX so it can be used separately
This commit is contained in:
parent
21ac06136a
commit
e66f8fe6e0
@ -31,7 +31,7 @@
|
|||||||
\li Stream ciphers: ChaCha
|
\li Stream ciphers: ChaCha
|
||||||
\li Authenticated encryption with associated data (AEAD): ChaChaPoly, EAX, GCM
|
\li Authenticated encryption with associated data (AEAD): ChaChaPoly, EAX, GCM
|
||||||
\li Hash algorithms: SHA256, SHA512, SHA3_256, SHA3_512, BLAKE2s, BLAKE2b (regular and HMAC modes)
|
\li Hash algorithms: SHA256, SHA512, SHA3_256, SHA3_512, BLAKE2s, BLAKE2b (regular and HMAC modes)
|
||||||
\li Message authenticators: Poly1305, GHASH
|
\li Message authenticators: Poly1305, GHASH, OMAC
|
||||||
\li Public key algorithms: Curve25519, Ed25519
|
\li Public key algorithms: Curve25519, Ed25519
|
||||||
\li Random number generation: \link RNGClass RNG\endlink, TransistorNoiseSource, RingOscillatorNoiseSource
|
\li Random number generation: \link RNGClass RNG\endlink, TransistorNoiseSource, RingOscillatorNoiseSource
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ realtime clock and the LCD library to implement an alarm clock.
|
|||||||
\li Stream ciphers: ChaCha
|
\li Stream ciphers: ChaCha
|
||||||
\li Authenticated encryption with associated data (AEAD): ChaChaPoly, EAX, GCM
|
\li Authenticated encryption with associated data (AEAD): ChaChaPoly, EAX, GCM
|
||||||
\li Hash algorithms: SHA256, SHA512, SHA3_256, SHA3_512, BLAKE2s, BLAKE2b (regular and HMAC modes)
|
\li Hash algorithms: SHA256, SHA512, SHA3_256, SHA3_512, BLAKE2s, BLAKE2b (regular and HMAC modes)
|
||||||
\li Message authenticators: Poly1305, GHASH
|
\li Message authenticators: Poly1305, GHASH, OMAC
|
||||||
\li Public key algorithms: Curve25519, Ed25519
|
\li Public key algorithms: Curve25519, Ed25519
|
||||||
\li Random number generation: \link RNGClass RNG\endlink, TransistorNoiseSource, RingOscillatorNoiseSource
|
\li Random number generation: \link RNGClass RNG\endlink, TransistorNoiseSource, RingOscillatorNoiseSource
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "EAX.h"
|
#include "EAX.h"
|
||||||
#include "GF128.h"
|
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -42,10 +41,8 @@
|
|||||||
* This constructor must be followed by a call to setBlockCipher().
|
* This constructor must be followed by a call to setBlockCipher().
|
||||||
*/
|
*/
|
||||||
EAXCommon::EAXCommon()
|
EAXCommon::EAXCommon()
|
||||||
: blockCipher(0)
|
|
||||||
{
|
{
|
||||||
state.encPosn = 0;
|
state.encPosn = 0;
|
||||||
state.authPosn = 0;
|
|
||||||
state.authMode = 0;
|
state.authMode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +53,7 @@ EAXCommon::~EAXCommon()
|
|||||||
|
|
||||||
size_t EAXCommon::keySize() const
|
size_t EAXCommon::keySize() const
|
||||||
{
|
{
|
||||||
return blockCipher->keySize();
|
return omac.blockCipher()->keySize();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t EAXCommon::ivSize() const
|
size_t EAXCommon::ivSize() const
|
||||||
@ -73,7 +70,7 @@ size_t EAXCommon::tagSize() const
|
|||||||
|
|
||||||
bool EAXCommon::setKey(const uint8_t *key, size_t len)
|
bool EAXCommon::setKey(const uint8_t *key, size_t len)
|
||||||
{
|
{
|
||||||
return blockCipher->setKey(key, len);
|
return omac.blockCipher()->setKey(key, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EAXCommon::setIV(const uint8_t *iv, size_t len)
|
bool EAXCommon::setIV(const uint8_t *iv, size_t len)
|
||||||
@ -83,16 +80,16 @@ bool EAXCommon::setIV(const uint8_t *iv, size_t len)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Hash the IV to create the initial nonce for CTR mode. Also creates B.
|
// Hash the IV to create the initial nonce for CTR mode. Also creates B.
|
||||||
omacInitFirst(state.counter);
|
omac.initFirst(state.counter);
|
||||||
omacUpdate(state.counter, iv, len);
|
omac.update(state.counter, iv, len);
|
||||||
omacFinal(state.counter);
|
omac.finalize(state.counter);
|
||||||
|
|
||||||
// The tag is initially the nonce value. Will be XOR'ed with
|
// The tag is initially the nonce value. Will be XOR'ed with
|
||||||
// the hash of the authenticated and encrypted data later.
|
// the hash of the authenticated and encrypted data later.
|
||||||
memcpy(state.tag, state.counter, 16);
|
memcpy(state.tag, state.counter, 16);
|
||||||
|
|
||||||
// Start the hashing context for the authenticated data.
|
// Start the hashing context for the authenticated data.
|
||||||
omacInit(state.hash, 1);
|
omac.initNext(state.hash, 1);
|
||||||
state.encPosn = 16;
|
state.encPosn = 16;
|
||||||
state.authMode = 1;
|
state.authMode = 1;
|
||||||
|
|
||||||
@ -105,21 +102,21 @@ void EAXCommon::encrypt(uint8_t *output, const uint8_t *input, size_t len)
|
|||||||
if (state.authMode)
|
if (state.authMode)
|
||||||
closeAuthData();
|
closeAuthData();
|
||||||
encryptCTR(output, input, len);
|
encryptCTR(output, input, len);
|
||||||
omacUpdate(state.hash, output, len);
|
omac.update(state.hash, output, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EAXCommon::decrypt(uint8_t *output, const uint8_t *input, size_t len)
|
void EAXCommon::decrypt(uint8_t *output, const uint8_t *input, size_t len)
|
||||||
{
|
{
|
||||||
if (state.authMode)
|
if (state.authMode)
|
||||||
closeAuthData();
|
closeAuthData();
|
||||||
omacUpdate(state.hash, input, len);
|
omac.update(state.hash, input, len);
|
||||||
encryptCTR(output, input, len);
|
encryptCTR(output, input, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EAXCommon::addAuthData(const void *data, size_t len)
|
void EAXCommon::addAuthData(const void *data, size_t len)
|
||||||
{
|
{
|
||||||
if (state.authMode)
|
if (state.authMode)
|
||||||
omacUpdate(state.hash, (const uint8_t *)data, len);
|
omac.update(state.hash, (const uint8_t *)data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EAXCommon::computeTag(void *tag, size_t len)
|
void EAXCommon::computeTag(void *tag, size_t len)
|
||||||
@ -146,95 +143,6 @@ void EAXCommon::clear()
|
|||||||
clean(state);
|
clean(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Initialises the first OMAC hashing context and creates the B value.
|
|
||||||
*
|
|
||||||
* \param omac The OMAC hashing context.
|
|
||||||
*/
|
|
||||||
void EAXCommon::omacInitFirst(uint8_t omac[16])
|
|
||||||
{
|
|
||||||
// Start the OMAC context for the nonce. 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);
|
|
||||||
state.authPosn = 0;
|
|
||||||
|
|
||||||
// Generate the B value from the encrypted block of zeroes.
|
|
||||||
// We will need this later when finalising the OMAC hashes.
|
|
||||||
memcpy(state.b, omac, 16);
|
|
||||||
GF128::dblEAX(state.b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Initialises an OMAC hashing context.
|
|
||||||
*
|
|
||||||
* \param omac The OMAC hashing context.
|
|
||||||
* \param t The tag value indicating which OMAC calculation we are doing.
|
|
||||||
*/
|
|
||||||
void EAXCommon::omacInit(uint8_t omac[16], uint8_t t)
|
|
||||||
{
|
|
||||||
memset(omac, 0, 15);
|
|
||||||
omac[15] = t;
|
|
||||||
state.authPosn = 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.
|
|
||||||
* \parm len The number of bytes to be hashed.
|
|
||||||
*/
|
|
||||||
void EAXCommon::omacUpdate(uint8_t omac[16], const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
while (len > 0) {
|
|
||||||
// Encrypt the current block if it is already full.
|
|
||||||
if (state.authPosn == 16) {
|
|
||||||
blockCipher->encryptBlock(omac, omac);
|
|
||||||
state.authPosn = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XOR the incoming data with the current block.
|
|
||||||
uint8_t size = 16 - state.authPosn;
|
|
||||||
if (size > len)
|
|
||||||
size = (uint8_t)len;
|
|
||||||
for (uint8_t index = 0; index < size; ++index)
|
|
||||||
omac[(state.authPosn)++] ^= data[index];
|
|
||||||
|
|
||||||
// Move onto the next block.
|
|
||||||
len -= size;
|
|
||||||
data += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Finalises an OMAC hashing context.
|
|
||||||
*
|
|
||||||
* \param omac The OMAC hashing context on entry, the final OMAC value on exit.
|
|
||||||
*/
|
|
||||||
void EAXCommon::omacFinal(uint8_t omac[16])
|
|
||||||
{
|
|
||||||
// Apply padding if necessary.
|
|
||||||
if (state.authPosn != 16) {
|
|
||||||
// Need padding: XOR with P = 2 * B.
|
|
||||||
uint32_t p[4];
|
|
||||||
memcpy(p, state.b, 16);
|
|
||||||
GF128::dblEAX(p);
|
|
||||||
omac[state.authPosn] ^= 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 *)(state.b))[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt the hash to get the final OMAC value.
|
|
||||||
blockCipher->encryptBlock(omac, omac);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Closes the authenticated data portion of the session and
|
* \brief Closes the authenticated data portion of the session and
|
||||||
* starts encryption or decryption.
|
* starts encryption or decryption.
|
||||||
@ -242,13 +150,13 @@ void EAXCommon::omacFinal(uint8_t omac[16])
|
|||||||
void EAXCommon::closeAuthData()
|
void EAXCommon::closeAuthData()
|
||||||
{
|
{
|
||||||
// Finalise the OMAC hash and XOR it with the final tag.
|
// Finalise the OMAC hash and XOR it with the final tag.
|
||||||
omacFinal(state.hash);
|
omac.finalize(state.hash);
|
||||||
for (uint8_t index = 0; index < 16; ++index)
|
for (uint8_t index = 0; index < 16; ++index)
|
||||||
state.tag[index] ^= state.hash[index];
|
state.tag[index] ^= state.hash[index];
|
||||||
state.authMode = 0;
|
state.authMode = 0;
|
||||||
|
|
||||||
// Initialise the hashing context for the ciphertext data.
|
// Initialise the hashing context for the ciphertext data.
|
||||||
omacInit(state.hash, 2);
|
omac.initNext(state.hash, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -266,7 +174,7 @@ void EAXCommon::encryptCTR(uint8_t *output, const uint8_t *input, size_t len)
|
|||||||
// Do we need to start a new block?
|
// Do we need to start a new block?
|
||||||
if (state.encPosn == 16) {
|
if (state.encPosn == 16) {
|
||||||
// Encrypt the counter to create the next keystream block.
|
// Encrypt the counter to create the next keystream block.
|
||||||
blockCipher->encryptBlock(state.stream, state.counter);
|
omac.blockCipher()->encryptBlock(state.stream, state.counter);
|
||||||
state.encPosn = 0;
|
state.encPosn = 0;
|
||||||
|
|
||||||
// Increment the counter, taking care not to reveal
|
// Increment the counter, taking care not to reveal
|
||||||
@ -304,7 +212,7 @@ void EAXCommon::closeTag()
|
|||||||
closeAuthData();
|
closeAuthData();
|
||||||
|
|
||||||
// Finalise the hash over the ciphertext and XOR with the final tag.
|
// Finalise the hash over the ciphertext and XOR with the final tag.
|
||||||
omacFinal(state.hash);
|
omac.finalize(state.hash);
|
||||||
for (uint8_t index = 0; index < 16; ++index)
|
for (uint8_t index = 0; index < 16; ++index)
|
||||||
state.tag[index] ^= state.hash[index];
|
state.tag[index] ^= state.hash[index];
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "AuthenticatedCipher.h"
|
#include "AuthenticatedCipher.h"
|
||||||
#include "BlockCipher.h"
|
#include "BlockCipher.h"
|
||||||
|
#include "OMAC.h"
|
||||||
|
|
||||||
class EAXCommon : public AuthenticatedCipher
|
class EAXCommon : public AuthenticatedCipher
|
||||||
{
|
{
|
||||||
@ -50,25 +51,21 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
EAXCommon();
|
EAXCommon();
|
||||||
void setBlockCipher(BlockCipher *cipher) { blockCipher = cipher; }
|
void setBlockCipher(BlockCipher *cipher)
|
||||||
|
{
|
||||||
|
omac.setBlockCipher(cipher);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BlockCipher *blockCipher;
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t counter[16];
|
uint8_t counter[16];
|
||||||
uint8_t stream[16];
|
uint8_t stream[16];
|
||||||
uint8_t tag[16];
|
uint8_t tag[16];
|
||||||
uint8_t hash[16];
|
uint8_t hash[16];
|
||||||
uint32_t b[4];
|
|
||||||
uint8_t encPosn;
|
uint8_t encPosn;
|
||||||
uint8_t authPosn;
|
|
||||||
uint8_t authMode;
|
uint8_t authMode;
|
||||||
} state;
|
} state;
|
||||||
|
OMAC omac;
|
||||||
void omacInitFirst(uint8_t omac[16]);
|
|
||||||
void omacInit(uint8_t omac[16], uint8_t t);
|
|
||||||
void omacUpdate(uint8_t omac[16], const uint8_t *data, size_t len);
|
|
||||||
void omacFinal(uint8_t omac[16]);
|
|
||||||
|
|
||||||
void closeAuthData();
|
void closeAuthData();
|
||||||
void encryptCTR(uint8_t *output, const uint8_t *input, size_t len);
|
void encryptCTR(uint8_t *output, const uint8_t *input, size_t len);
|
||||||
|
200
libraries/Crypto/OMAC.cpp
Normal file
200
libraries/Crypto/OMAC.cpp
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
50
libraries/Crypto/OMAC.h
Normal file
50
libraries/Crypto/OMAC.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CRYPTO_OMAC_H
|
||||||
|
#define CRYPTO_OMAC_H
|
||||||
|
|
||||||
|
#include "BlockCipher.h"
|
||||||
|
|
||||||
|
class OMAC
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OMAC();
|
||||||
|
~OMAC();
|
||||||
|
|
||||||
|
BlockCipher *blockCipher() const { return _blockCipher; }
|
||||||
|
void setBlockCipher(BlockCipher *cipher) { _blockCipher = cipher; }
|
||||||
|
|
||||||
|
void initFirst(uint8_t omac[16]);
|
||||||
|
void initNext(uint8_t omac[16], uint8_t tag);
|
||||||
|
void update(uint8_t omac[16], const uint8_t *data, size_t size);
|
||||||
|
void finalize(uint8_t omac[16]);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BlockCipher *_blockCipher;
|
||||||
|
uint32_t b[4];
|
||||||
|
uint8_t posn;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user