/* * Copyright (C) 2015 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 "EAX.h" #include "Crypto.h" #include /** * \class EAXCommon EAX.h * \brief Concrete base class to assist with implementing EAX for * 128-bit block ciphers. * * References: https://en.wikipedia.org/wiki/EAX_mode, * http://web.cs.ucdavis.edu/~rogaway/papers/eax.html * * \sa EAX */ /** * \brief Constructs a new cipher in EAX mode. * * This constructor must be followed by a call to setBlockCipher(). */ EAXCommon::EAXCommon() { state.encPosn = 0; state.authMode = 0; } EAXCommon::~EAXCommon() { clean(state); } size_t EAXCommon::keySize() const { return omac.blockCipher()->keySize(); } size_t EAXCommon::ivSize() const { // Can use any size but 16 is recommended. return 16; } size_t EAXCommon::tagSize() const { // Tags can be up to 16 bytes in length. return 16; } bool EAXCommon::setKey(const uint8_t *key, size_t len) { return omac.blockCipher()->setKey(key, len); } bool EAXCommon::setIV(const uint8_t *iv, size_t len) { // Must have at least 1 byte for the IV. if (!len) return false; // Hash the IV to create the initial nonce for CTR mode. Also creates B. omac.initFirst(state.counter); omac.update(state.counter, iv, len); omac.finalize(state.counter); // The tag is initially the nonce value. Will be XOR'ed with // the hash of the authenticated and encrypted data later. memcpy(state.tag, state.counter, 16); // Start the hashing context for the authenticated data. omac.initNext(state.hash, 1); state.encPosn = 16; state.authMode = 1; // The EAX context is ready to go. return true; } void EAXCommon::encrypt(uint8_t *output, const uint8_t *input, size_t len) { if (state.authMode) closeAuthData(); encryptCTR(output, input, len); omac.update(state.hash, output, len); } void EAXCommon::decrypt(uint8_t *output, const uint8_t *input, size_t len) { if (state.authMode) closeAuthData(); omac.update(state.hash, input, len); encryptCTR(output, input, len); } void EAXCommon::addAuthData(const void *data, size_t len) { if (state.authMode) omac.update(state.hash, (const uint8_t *)data, len); } void EAXCommon::computeTag(void *tag, size_t len) { closeTag(); if (len > 16) len = 16; memcpy(tag, state.tag, len); } bool EAXCommon::checkTag(const void *tag, size_t len) { // Can never match if the expected tag length is too long. if (len > 16) return false; // Compute the final tag and check it. closeTag(); return secure_compare(state.tag, tag, len); } void EAXCommon::clear() { clean(state); } /** * \brief Closes the authenticated data portion of the session and * starts encryption or decryption. */ void EAXCommon::closeAuthData() { // Finalise the OMAC hash and XOR it with the final tag. omac.finalize(state.hash); for (uint8_t index = 0; index < 16; ++index) state.tag[index] ^= state.hash[index]; state.authMode = 0; // Initialise the hashing context for the ciphertext data. omac.initNext(state.hash, 2); } /** * \brief Encrypts or decrypts a region using the block cipher in CTR mode. * * \param output The output buffer to write to, which may be the same * buffer as \a input. The \a output buffer must have at least as many * bytes as the \a input buffer. * \param input The input buffer to read from. * \param len The number of bytes to process. */ void EAXCommon::encryptCTR(uint8_t *output, const uint8_t *input, size_t len) { while (len > 0) { // Do we need to start a new block? if (state.encPosn == 16) { // Encrypt the counter to create the next keystream block. omac.blockCipher()->encryptBlock(state.stream, state.counter); state.encPosn = 0; // Increment the counter, taking care not to reveal // any timing information about the starting value. // We iterate through the entire counter region even // if we could stop earlier because a byte is non-zero. uint16_t temp = 1; uint8_t index = 16; while (index > 0) { --index; temp += state.counter[index]; state.counter[index] = (uint8_t)temp; temp >>= 8; } } // Encrypt/decrypt the current input block. uint8_t size = 16 - state.encPosn; if (size > len) size = (uint8_t)len; for (uint8_t index = 0; index < size; ++index) output[index] = input[index] ^ state.stream[(state.encPosn)++]; // Move onto the next block. len -= size; input += size; output += size; } } void EAXCommon::closeTag() { // If we were only authenticating, then close off auth mode. if (state.authMode) closeAuthData(); // Finalise the hash over the ciphertext and XOR with the final tag. omac.finalize(state.hash); for (uint8_t index = 0; index < 16; ++index) state.tag[index] ^= state.hash[index]; } /** * \fn void EAXCommon::setBlockCipher(BlockCipher *cipher) * \brief Sets the block cipher to use for this EAX object. * * \param cipher The block cipher to use to implement EAX mode. * This object must have a block size of 128 bits (16 bytes). */ /** * \class EAX EAX.h * \brief Implementation of the EAX authenticated cipher. * * EAX mode converts a block cipher into an authenticated cipher * that uses the block cipher T to encrypt and authenticate. * * The size of the key is determined by the underlying block cipher T. * The IV is recommended to be 128 bits (16 bytes) in length, but other * lengths are supported as well. The default tagSize() is 128 bits * (16 bytes) but the EAX specification does allow smaller tag sizes. * * The template parameter T must be a concrete subclass of BlockCipher * indicating the specific block cipher to use. The block cipher must * have a block size of 128 bits. For example, the following creates a * EAX object using AES256 as the underlying cipher and then uses it * to encrypt and authenticate a \c plaintext block: * * \code * EAX eax; * eax.setKey(key, sizeof(key)); * eax.setIV(iv, sizeof(iv)); * eax.addAuthData(adata, sizeof(adata)); * eax.encrypt(ciphertext, plaintext, sizeof(plaintext)); * eax.computeTag(tag, sizeof(tag)); * \endcode * * The decryption process is almost identical to convert a \c ciphertext and * \a tag back into plaintext and then check the tag: * * \code * EAX eax; * eax.setKey(key, sizeof(key)); * eax.setIV(iv, sizeof(iv)); * eax.addAuthData(adata, sizeof(adata)); * eax.decrypt(ciphertext, plaintext, sizeof(plaintext)); * if (!eax.checkTag(tag, sizeof(tag))) { * // The data was invalid - do not use it. * ... * } * \endcode * * The EAX class can also be used to implement message authentication * by omitting the plaintext: * * \code * EAX eax; * eax.setKey(key, sizeof(key)); * eax.setIV(iv, sizeof(iv)); * eax.addAuthData(adata1, sizeof(adata1)); * eax.addAuthData(adata2, sizeof(adata1)); * ... * eax.addAuthData(adataN, sizeof(adataN)); * eax.computeTag(tag, sizeof(tag)); * \endcode * * References: https://en.wikipedia.org/wiki/EAX_mode, * http://web.cs.ucdavis.edu/~rogaway/papers/eax.html * * \sa EAXCommon, GCM */ /** * \fn EAX::EAX() * \brief Constructs a new EAX object for the block cipher T. */