mirror of
https://github.com/taigrr/arduinolibs
synced 2025-01-18 04:33:12 -08:00
438 lines
14 KiB
C++
438 lines
14 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 "XTS.h"
|
|
#include "Crypto.h"
|
|
#include "GF128.h"
|
|
#include <string.h>
|
|
|
|
/**
|
|
* \class XTSCommon XTS.h <XTS.h>
|
|
* \brief Concrete base class to assist with implementing XTS mode for
|
|
* 128-bit block ciphers.
|
|
*
|
|
* References: <a href="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE Std. 1619-2007</a>, <a href="http://csrc.nist.gov/publications/nistpubs/800-38E/nist-sp-800-38E.pdf">NIST SP 800-38E</a>, a href="http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf">XEX</a>.
|
|
*
|
|
* \sa XTS, XTSSingleKey
|
|
*/
|
|
|
|
/**
|
|
* \brief Constructs an XTS object with a default sector size of 512 bytes.
|
|
*/
|
|
XTSCommon::XTSCommon()
|
|
: sectSize(512)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* \brief Clears all sensitive information and destroys this object.
|
|
*/
|
|
XTSCommon::~XTSCommon()
|
|
{
|
|
clean(twk);
|
|
}
|
|
|
|
/**
|
|
* \brief Gets the size of the key for XTS mode.
|
|
*
|
|
* The key size for XTS mode is twice the size of the underlying
|
|
* block cipher key size.
|
|
*
|
|
* \sa setKey(), tweakSize()
|
|
*/
|
|
size_t XTSCommon::keySize() const
|
|
{
|
|
return blockCipher1->keySize() * 2;
|
|
}
|
|
|
|
/**
|
|
* \brief Gets the maximum supported size for the tweak.
|
|
*
|
|
* This function returns 16, which indicates that any tweak up to 16 bytes
|
|
* in size can be specified via setTweak().
|
|
*/
|
|
size_t XTSCommon::tweakSize() const
|
|
{
|
|
return 16;
|
|
}
|
|
|
|
/**
|
|
* \fn size_t XTSCommon::sectorSize() const
|
|
* \brief Gets the size of sectors encrypted or decrypted by this class.
|
|
*
|
|
* The default value is 512 bytes.
|
|
*
|
|
* \sa setSectorSize()
|
|
*/
|
|
|
|
/**
|
|
* \brief Sets the size of sectors encrypted or decrypted by this class.
|
|
*
|
|
* \param size The sector size in bytes, which must be greater than or
|
|
* equal to 16.
|
|
*
|
|
* \return Returns false if \a size is less than 16.
|
|
*
|
|
* \sa sectorSize(), encryptSector()
|
|
*/
|
|
bool XTSCommon::setSectorSize(size_t size)
|
|
{
|
|
if (size < 16)
|
|
return false;
|
|
sectSize = size;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* \brief Sets the key to use for XTS mode.
|
|
*
|
|
* \param key Points to the key.
|
|
* \param len The size of the key in bytes which must be twice the
|
|
* size of the underlying block cipher's key size.
|
|
*
|
|
* \return Returns true if the key was set or false if \a len was incorrect.
|
|
*
|
|
* This function should be followed by a call to setTweak() to specify
|
|
* the sector-specific tweak.
|
|
*
|
|
* \sa keySize(), setTweak(), encryptSector()
|
|
*/
|
|
bool XTSCommon::setKey(const uint8_t *key, size_t len)
|
|
{
|
|
if (!blockCipher1->setKey(key, len / 2))
|
|
return false;
|
|
return blockCipher2->setKey(key + len / 2, len - (len / 2));
|
|
}
|
|
|
|
/**
|
|
* \brief Sets the tweak value for the current sector to encrypt or decrypt.
|
|
*
|
|
* \param tweak Points to the tweak.
|
|
* \param len The length of the tweak which must be less than or equal to 16.
|
|
*
|
|
* \return Returns true if the tweak was set or false if \a len was incorrect.
|
|
*
|
|
* If \a len is less than 16, then the \a tweak will be zero-padded to
|
|
* 16 bytes.
|
|
*
|
|
* The \a tweak is encrypted with the second half of the XTS key to generate
|
|
* the actual tweak value for the sector.
|
|
*
|
|
* \sa tweakSize(), setKey(), encryptSector()
|
|
*/
|
|
bool XTSCommon::setTweak(const uint8_t *tweak, size_t len)
|
|
{
|
|
if (len > 16)
|
|
return false;
|
|
memcpy(twk, tweak, len);
|
|
memset(((uint8_t *)twk) + len, 0, 16 - len);
|
|
blockCipher2->encryptBlock((uint8_t *)twk, (uint8_t *)twk);
|
|
return true;
|
|
}
|
|
|
|
#define xorTweak(output, input, tweak) \
|
|
do { \
|
|
for (uint8_t i = 0; i < 16; ++i) \
|
|
(output)[i] = (input)[i] ^ ((const uint8_t *)(tweak))[i]; \
|
|
} while (0)
|
|
|
|
/**
|
|
* \brief Encrypts an entire sector of data.
|
|
*
|
|
* \param output The output buffer to write the ciphertext to, which can
|
|
* be the same as \a input.
|
|
* \param input The input buffer to read the plaintext from.
|
|
*
|
|
* The \a input and \a output buffers must be at least sectorSize()
|
|
* bytes in length.
|
|
*
|
|
* \sa decryptSector(), setKey(), setTweak()
|
|
*/
|
|
void XTSCommon::encryptSector(uint8_t *output, const uint8_t *input)
|
|
{
|
|
size_t sectLast = sectSize & ~15;
|
|
size_t posn = 0;
|
|
uint32_t t[4];
|
|
memcpy(t, twk, sizeof(t));
|
|
while (posn < sectLast) {
|
|
// Process all complete 16-byte blocks.
|
|
xorTweak(output, input, t);
|
|
blockCipher1->encryptBlock(output, output);
|
|
xorTweak(output, output, t);
|
|
GF128::dblXTS(t);
|
|
input += 16;
|
|
output += 16;
|
|
posn += 16;
|
|
}
|
|
if (posn < sectSize) {
|
|
// Perform ciphertext stealing on the final partial block.
|
|
uint8_t leftOver = sectSize - posn;
|
|
output -= 16;
|
|
while (leftOver > 0) {
|
|
// Swap the left-over bytes in the last two blocks.
|
|
--leftOver;
|
|
uint8_t temp = input[leftOver];
|
|
output[leftOver + 16] = output[leftOver];
|
|
output[leftOver] = temp;
|
|
}
|
|
xorTweak(output, output, t);
|
|
blockCipher1->encryptBlock(output, output);
|
|
xorTweak(output, output, t);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Decrypts an entire sector of data.
|
|
*
|
|
* \param output The output buffer to write the plaintext to, which can
|
|
* be the same as \a input.
|
|
* \param input The input buffer to read the ciphertext from.
|
|
*
|
|
* The \a input and \a output buffers must be at least sectorSize()
|
|
* bytes in length.
|
|
*
|
|
* \sa encryptSector(), setKey(), setTweak()
|
|
*/
|
|
void XTSCommon::decryptSector(uint8_t *output, const uint8_t *input)
|
|
{
|
|
size_t sectLast = sectSize & ~15;
|
|
size_t posn = 0;
|
|
uint32_t t[4];
|
|
memcpy(t, twk, sizeof(t));
|
|
if (sectLast != sectSize)
|
|
sectLast -= 16;
|
|
while (posn < sectLast) {
|
|
// Process all complete 16-byte blocks.
|
|
xorTweak(output, input, t);
|
|
blockCipher1->decryptBlock(output, output);
|
|
xorTweak(output, output, t);
|
|
GF128::dblXTS(t);
|
|
input += 16;
|
|
output += 16;
|
|
posn += 16;
|
|
}
|
|
if (posn < sectSize) {
|
|
// Perform ciphertext stealing on the final two blocks.
|
|
uint8_t leftOver = sectSize - 16 - posn;
|
|
uint32_t u[4];
|
|
|
|
// Decrypt the second-last block of ciphertext to recover
|
|
// the last partial block of plaintext. We need to use
|
|
// dblXTS(t) as the tweak for this block. Save the current
|
|
// tweak in "u" for use later.
|
|
memcpy(u, t, sizeof(t));
|
|
GF128::dblXTS(t);
|
|
xorTweak(output, input, t);
|
|
blockCipher1->decryptBlock(output, output);
|
|
xorTweak(output, output, t);
|
|
|
|
// Swap the left-over bytes in the last two blocks.
|
|
while (leftOver > 0) {
|
|
--leftOver;
|
|
uint8_t temp = input[leftOver + 16];
|
|
output[leftOver + 16] = output[leftOver];
|
|
output[leftOver] = temp;
|
|
}
|
|
|
|
// Decrypt the second-last block using the second-last tweak.
|
|
xorTweak(output, output, u);
|
|
blockCipher1->decryptBlock(output, output);
|
|
xorTweak(output, output, u);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Clears all security-sensitive state from this XTS object.
|
|
*/
|
|
void XTSCommon::clear()
|
|
{
|
|
clean(twk);
|
|
blockCipher1->clear();
|
|
blockCipher2->clear();
|
|
}
|
|
|
|
/**
|
|
* \fn void XTSCommon::setBlockCiphers(BlockCipher *cipher1, BlockCipher *cipher2)
|
|
* \brief Sets the two block ciphers to use for XTS mode.
|
|
*
|
|
* \param cipher1 Points to the first block cipher object, which must be
|
|
* capable of both encryption and decryption.
|
|
* \param cipher2 Points to the second block cipher object, which must be
|
|
* capable of both encryption but does not need to be capable of decryption.
|
|
*
|
|
* Both block ciphers must have a 128-bit block size.
|
|
*/
|
|
|
|
/**
|
|
* \class XTSSingleKeyCommon XTS.h <XTS.h>
|
|
* \brief Concrete base class to assist with implementing single-key XTS
|
|
* mode for 128-bit block ciphers.
|
|
*
|
|
* References: <a href="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE Std. 1619-2007</a>, <a href="http://csrc.nist.gov/publications/nistpubs/800-38E/nist-sp-800-38E.pdf">NIST SP 800-38E</a>, a href="http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf">XEX</a>.
|
|
*
|
|
* \sa XTSSingleKey, XTSCommon
|
|
*/
|
|
|
|
/**
|
|
* \fn XTSSingleKeyCommon::XTSSingleKeyCommon()
|
|
* \brief Constructs an XTS object with a default sector size of 512 bytes.
|
|
*/
|
|
|
|
/**
|
|
* \brief Clears all sensitive information and destroys this object.
|
|
*/
|
|
XTSSingleKeyCommon::~XTSSingleKeyCommon()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* \brief Gets the size of the key for single-pkey XTS mode.
|
|
*
|
|
* The key size for single-key XTS mode is the same as the key size
|
|
* for the underlying block cipher.
|
|
*
|
|
* \sa setKey(), tweakSize()
|
|
*/
|
|
size_t XTSSingleKeyCommon::keySize() const
|
|
{
|
|
return blockCipher1->keySize();
|
|
}
|
|
|
|
/**
|
|
* \brief Sets the key to use for single-keyh XTS mode.
|
|
*
|
|
* \param key Points to the key.
|
|
* \param len The size of the key in bytes which must be same as the
|
|
* size of the underlying block cipher.
|
|
*
|
|
* \return Returns true if the key was set or false if \a len was incorrect.
|
|
*
|
|
* This function should be followed by a call to setTweak() to specify
|
|
* the sector-specific tweak.
|
|
*
|
|
* \sa keySize(), setTweak(), encryptSector()
|
|
*/
|
|
bool XTSSingleKeyCommon::setKey(const uint8_t *key, size_t len)
|
|
{
|
|
return blockCipher1->setKey(key, len);
|
|
}
|
|
|
|
/**
|
|
* \class XTS XTS.h <XTS.h>
|
|
* \brief Implementation of the XTS mode for 128-bit block ciphers.
|
|
*
|
|
* XTS mode implements the XEX tweakable block cipher mode with ciphertext
|
|
* stealing for data that isn't a multiple of the 128-bit block size.
|
|
*
|
|
* XTS was designed for use in disk encryption where a large number of
|
|
* equal-sized "sectors" need to be encrypted in a way that information
|
|
* from one sector cannot be used to decrypt the other sectors. The mode
|
|
* combines the key with a sector-specific "tweak" which is usually
|
|
* based on the sector number.
|
|
*
|
|
* Some Arduino systems have SD cards, but typically embedded systems
|
|
* do not have disk drives. However, XTS can still be useful on
|
|
* Arduino systems with lots of EEPROM or flash memory. If the application
|
|
* needs to store critical security parameters like private keys then
|
|
* XTS can be used to encrypt non-volatile memory to protect the parameters.
|
|
*
|
|
* The following example encrypts a sector using XTS mode:
|
|
*
|
|
* \code
|
|
* XTS<AES256> xts;
|
|
* xts.setSectorSize(520);
|
|
* xts.setKey(key, 64); // Twice the AES256 key size.
|
|
* xts.setTweak(sectorNumber, sizeof(sectorNumber));
|
|
* xts.encryptSector(output, input);
|
|
* \endcode
|
|
*
|
|
* XTS keys are twice the size of the underlying block cipher
|
|
* (AES256 in the above example). The XTS key is divided into two halves.
|
|
* The first half is used to encrypt the plaintext and the second half
|
|
* is used to encrypt the sector-specific tweak. The same key can be
|
|
* used for both, in which case XTS is equivalent to the original
|
|
* XEX design upon which XTS was based. The companion XTSSingleKey class
|
|
* can be used for single-key scenarios.
|
|
*
|
|
* The template parameter must be a concrete subclass of BlockCipher
|
|
* indicating the specific block cipher to use. The example above uses
|
|
* AES256 as the underlying cipher.
|
|
*
|
|
* It is also possible to specify two different block ciphers, as long as
|
|
* they have the same key size. Because the second half of the key is only
|
|
* used to encrypt tweaks and never decrypt, a reduced block cipher
|
|
* implementation like SpeckTiny that only supports encryption can be
|
|
* used for the second block cipher:
|
|
*
|
|
* \code
|
|
* XTS<SpeckSmall, SpeckTiny> xts;
|
|
* \endcode
|
|
*
|
|
* This might save some memory that would otherwise be needed for the
|
|
* decryption key schedule of the second block cipher. XTSSingleKey provides
|
|
* another method to save memory.
|
|
*
|
|
* References: <a href="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE Std. 1619-2007</a>, <a href="http://csrc.nist.gov/publications/nistpubs/800-38E/nist-sp-800-38E.pdf">NIST SP 800-38E</a>, a href="http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf">XEX</a>.
|
|
*
|
|
* \sa XTSSingleKey, XTSCommon
|
|
*/
|
|
|
|
/**
|
|
* \fn XTS::XTS()
|
|
* \brief Constructs an object for encrypting sectors in XTS mode.
|
|
*
|
|
* This constructor should be followed by a call to setSectorSize().
|
|
* The default sector size is 512 bytes.
|
|
*/
|
|
|
|
/**
|
|
* \fn XTS::~XTS()
|
|
* \brief Clears all sensitive information and destroys this object.
|
|
*/
|
|
|
|
/**
|
|
* \class XTSSingleKey XTS.h <XTS.h>
|
|
* \brief Implementation of the single-key XTS mode for 128-bit block ciphers.
|
|
*
|
|
* XTS mode normally uses two keys to encrypt plaintext and the
|
|
* sector-specific tweak values. This class uses the same key for
|
|
* both purposes, which can help save memory.
|
|
*
|
|
* References: <a href="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE Std. 1619-2007</a>, <a href="http://csrc.nist.gov/publications/nistpubs/800-38E/nist-sp-800-38E.pdf">NIST SP 800-38E</a>, a href="http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf">XEX</a>.
|
|
*
|
|
* \sa XTS, XTSSingleKeyCommon
|
|
*/
|
|
|
|
/**
|
|
* \fn XTSSingleKey::XTSSingleKey()
|
|
* \brief Constructs an object for encrypting sectors in XTS mode
|
|
* with a single key instead of two split keys.
|
|
*
|
|
* This constructor should be followed by a call to setSectorSize().
|
|
* The default sector size is 512 bytes.
|
|
*/
|
|
|
|
/**
|
|
* \fn XTSSingleKey::~XTSSingleKey()
|
|
* \brief Clears all sensitive information and destroys this object.
|
|
*/
|