mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-26 20:56:37 +00:00
feat(sim): add variants/sim/ — real companion_radio firmware on native + Emscripten
New board variant compiling the unmodified MyMesh/UITask/DataStore app logic against real mesh::Radio/MainBoard/RTCClock/RNG interfaces, for running the actual firmware outside embedded hardware: - Native (plain g++, platform = native): ASCII-art display over stdout, stdin-driven input, local-disk-backed DataStore/IdentityStore. - Emscripten/WASM (variants/sim/build_wasm.sh, since PlatformIO's native platform force-overrides any CC/CXX toolchain override back to system clang++): canvas-backed display, IDBFS-backed persistence across page reloads, JS-callable input via sim_enqueue_key(), emscripten_set_main_loop. Real rweather/Crypto (AES128/SHA256/Ed25519) vendored unmodified and proven working on both targets. variants/sim/web/index.html is a bare verification harness, not the polished website embed.
This commit is contained in:
Vendored
+269
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2018 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_AES_h
|
||||
#define CRYPTO_AES_h
|
||||
|
||||
#include "BlockCipher.h"
|
||||
|
||||
// Determine which AES implementation to export to applications.
|
||||
#if defined(ESP32)
|
||||
#define CRYPTO_AES_ESP32 1
|
||||
#else
|
||||
#define CRYPTO_AES_DEFAULT 1
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTO_AES_DEFAULT) || defined(CRYPTO_DOC)
|
||||
|
||||
class AESTiny128;
|
||||
class AESTiny256;
|
||||
class AESSmall128;
|
||||
class AESSmall256;
|
||||
|
||||
class AESCommon : public BlockCipher
|
||||
{
|
||||
public:
|
||||
virtual ~AESCommon();
|
||||
|
||||
size_t blockSize() const;
|
||||
|
||||
void encryptBlock(uint8_t *output, const uint8_t *input);
|
||||
void decryptBlock(uint8_t *output, const uint8_t *input);
|
||||
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
AESCommon();
|
||||
|
||||
/** @cond aes_internal */
|
||||
uint8_t rounds;
|
||||
uint8_t *schedule;
|
||||
|
||||
static void subBytesAndShiftRows(uint8_t *output, const uint8_t *input);
|
||||
static void inverseShiftRowsAndSubBytes(uint8_t *output, const uint8_t *input);
|
||||
static void mixColumn(uint8_t *output, uint8_t *input);
|
||||
static void inverseMixColumn(uint8_t *output, const uint8_t *input);
|
||||
static void keyScheduleCore(uint8_t *output, const uint8_t *input, uint8_t iteration);
|
||||
static void applySbox(uint8_t *output, const uint8_t *input);
|
||||
/** @endcond */
|
||||
|
||||
friend class AESTiny128;
|
||||
friend class AESTiny256;
|
||||
friend class AESSmall128;
|
||||
friend class AESSmall256;
|
||||
};
|
||||
|
||||
class AES128 : public AESCommon
|
||||
{
|
||||
public:
|
||||
AES128();
|
||||
virtual ~AES128();
|
||||
|
||||
size_t keySize() const;
|
||||
|
||||
bool setKey(const uint8_t *key, size_t len);
|
||||
|
||||
private:
|
||||
uint8_t sched[176];
|
||||
};
|
||||
|
||||
class AES192 : public AESCommon
|
||||
{
|
||||
public:
|
||||
AES192();
|
||||
virtual ~AES192();
|
||||
|
||||
size_t keySize() const;
|
||||
|
||||
bool setKey(const uint8_t *key, size_t len);
|
||||
|
||||
private:
|
||||
uint8_t sched[208];
|
||||
};
|
||||
|
||||
class AES256 : public AESCommon
|
||||
{
|
||||
public:
|
||||
AES256();
|
||||
virtual ~AES256();
|
||||
|
||||
size_t keySize() const;
|
||||
|
||||
bool setKey(const uint8_t *key, size_t len);
|
||||
|
||||
private:
|
||||
uint8_t sched[240];
|
||||
};
|
||||
|
||||
class AESTiny256 : public BlockCipher
|
||||
{
|
||||
public:
|
||||
AESTiny256();
|
||||
virtual ~AESTiny256();
|
||||
|
||||
size_t blockSize() const;
|
||||
size_t keySize() const;
|
||||
|
||||
bool setKey(const uint8_t *key, size_t len);
|
||||
|
||||
void encryptBlock(uint8_t *output, const uint8_t *input);
|
||||
void decryptBlock(uint8_t *output, const uint8_t *input);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
uint8_t schedule[32];
|
||||
};
|
||||
|
||||
class AESSmall256 : public AESTiny256
|
||||
{
|
||||
public:
|
||||
AESSmall256();
|
||||
virtual ~AESSmall256();
|
||||
|
||||
bool setKey(const uint8_t *key, size_t len);
|
||||
|
||||
void decryptBlock(uint8_t *output, const uint8_t *input);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
uint8_t reverse[32];
|
||||
};
|
||||
|
||||
class AESTiny128 : public BlockCipher
|
||||
{
|
||||
public:
|
||||
AESTiny128();
|
||||
virtual ~AESTiny128();
|
||||
|
||||
size_t blockSize() const;
|
||||
size_t keySize() const;
|
||||
|
||||
bool setKey(const uint8_t *key, size_t len);
|
||||
|
||||
void encryptBlock(uint8_t *output, const uint8_t *input);
|
||||
void decryptBlock(uint8_t *output, const uint8_t *input);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
uint8_t schedule[16];
|
||||
};
|
||||
|
||||
class AESSmall128 : public AESTiny128
|
||||
{
|
||||
public:
|
||||
AESSmall128();
|
||||
virtual ~AESSmall128();
|
||||
|
||||
bool setKey(const uint8_t *key, size_t len);
|
||||
|
||||
void decryptBlock(uint8_t *output, const uint8_t *input);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
uint8_t reverse[16];
|
||||
};
|
||||
|
||||
#endif // CRYPTO_AES_DEFAULT
|
||||
|
||||
#if defined(CRYPTO_AES_ESP32)
|
||||
|
||||
/** @cond aes_esp_rename */
|
||||
|
||||
// The esp32 SDK keeps moving where aes.h is located, so we have to
|
||||
// declare the API functions ourselves and make the context opaque.
|
||||
//
|
||||
// About the only thing the various SDK versions agree on is that the
|
||||
// first byte is the length of the key in bytes.
|
||||
//
|
||||
// Some versions of esp-idf have a 33 byte AES context, and others 34.
|
||||
// Allocate up to 40 to make space for future expansion.
|
||||
#define CRYPTO_ESP32_CONTEXT_SIZE 40
|
||||
|
||||
// Some of the esp-idf system headers define enumerations for AES128,
|
||||
// AES192, and AES256 to identify the hardware-accelerated algorithms.
|
||||
// These can cause conflicts with the names we use in our library.
|
||||
// Define our class names to something else to work around esp-idf.
|
||||
#undef AES128
|
||||
#undef AES192
|
||||
#undef AES256
|
||||
#define AES128 AES128_ESP
|
||||
#define AES192 AES192_ESP
|
||||
#define AES256 AES256_ESP
|
||||
|
||||
/** @endcond */
|
||||
|
||||
class AESCommon : public BlockCipher
|
||||
{
|
||||
public:
|
||||
virtual ~AESCommon();
|
||||
|
||||
size_t blockSize() const;
|
||||
size_t keySize() const;
|
||||
|
||||
bool setKey(const uint8_t *key, size_t len);
|
||||
|
||||
void encryptBlock(uint8_t *output, const uint8_t *input);
|
||||
void decryptBlock(uint8_t *output, const uint8_t *input);
|
||||
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
AESCommon(uint8_t keySize);
|
||||
|
||||
private:
|
||||
uint8_t ctx[CRYPTO_ESP32_CONTEXT_SIZE];
|
||||
};
|
||||
|
||||
class AES128 : public AESCommon
|
||||
{
|
||||
public:
|
||||
AES128() : AESCommon(16) {}
|
||||
virtual ~AES128();
|
||||
};
|
||||
|
||||
class AES192 : public AESCommon
|
||||
{
|
||||
public:
|
||||
AES192() : AESCommon(24) {}
|
||||
virtual ~AES192();
|
||||
};
|
||||
|
||||
class AES256 : public AESCommon
|
||||
{
|
||||
public:
|
||||
AES256() : AESCommon(32) {}
|
||||
virtual ~AES256();
|
||||
};
|
||||
|
||||
// The ESP32 AES context is so small that it already qualifies as "tiny".
|
||||
typedef AES128 AESTiny128;
|
||||
typedef AES256 AESTiny256;
|
||||
typedef AES128 AESSmall128;
|
||||
typedef AES256 AESSmall256;
|
||||
|
||||
#endif // CRYPTO_AES_ESP32
|
||||
|
||||
#endif
|
||||
+356
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2018 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 "AES.h"
|
||||
#include "Crypto.h"
|
||||
#include <string.h>
|
||||
|
||||
#if defined(CRYPTO_AES_DEFAULT) || defined(CRYPTO_DOC)
|
||||
|
||||
/**
|
||||
* \class AES128 AES.h <AES.h>
|
||||
* \brief AES block cipher with 128-bit keys.
|
||||
*
|
||||
* \sa AES192, AES256, AESTiny128, AESSmall128
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Constructs an AES 128-bit block cipher with no initial key.
|
||||
*
|
||||
* This constructor must be followed by a call to setKey() before the
|
||||
* block cipher can be used for encryption or decryption.
|
||||
*/
|
||||
AES128::AES128()
|
||||
{
|
||||
rounds = 10;
|
||||
schedule = sched;
|
||||
}
|
||||
|
||||
AES128::~AES128()
|
||||
{
|
||||
clean(sched);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Size of a 128-bit AES key in bytes.
|
||||
* \return Always returns 16.
|
||||
*/
|
||||
size_t AES128::keySize() const
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
bool AES128::setKey(const uint8_t *key, size_t len)
|
||||
{
|
||||
if (len != 16)
|
||||
return false;
|
||||
|
||||
// Copy the key itself into the first 16 bytes of the schedule.
|
||||
uint8_t *schedule = sched;
|
||||
memcpy(schedule, key, 16);
|
||||
|
||||
// Expand the key schedule until we have 176 bytes of expanded key.
|
||||
uint8_t iteration = 1;
|
||||
uint8_t n = 16;
|
||||
uint8_t w = 4;
|
||||
while (n < 176) {
|
||||
if (w == 4) {
|
||||
// Every 16 bytes (4 words) we need to apply the key schedule core.
|
||||
keyScheduleCore(schedule + 16, schedule + 12, iteration);
|
||||
schedule[16] ^= schedule[0];
|
||||
schedule[17] ^= schedule[1];
|
||||
schedule[18] ^= schedule[2];
|
||||
schedule[19] ^= schedule[3];
|
||||
++iteration;
|
||||
w = 0;
|
||||
} else {
|
||||
// Otherwise just XOR the word with the one 16 bytes previous.
|
||||
schedule[16] = schedule[12] ^ schedule[0];
|
||||
schedule[17] = schedule[13] ^ schedule[1];
|
||||
schedule[18] = schedule[14] ^ schedule[2];
|
||||
schedule[19] = schedule[15] ^ schedule[3];
|
||||
}
|
||||
|
||||
// Advance to the next word in the schedule.
|
||||
schedule += 4;
|
||||
n += 4;
|
||||
++w;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \class AESTiny128 AES.h <AES.h>
|
||||
* \brief AES block cipher with 128-bit keys and tiny memory usage.
|
||||
*
|
||||
* This class differs from the AES128 class in the following ways:
|
||||
*
|
||||
* \li RAM requirements are vastly reduced. The key is stored directly
|
||||
* and then expanded to the full key schedule round by round. The setKey()
|
||||
* method is very fast because of this.
|
||||
* \li Performance of encryptBlock() is slower than for AES128 due to
|
||||
* expanding the key on the fly rather than ahead of time.
|
||||
* \li The decryptBlock() function is not supported, which means that CBC
|
||||
* mode cannot be used but the CTR, CFB, OFB, EAX, and GCM modes can be used.
|
||||
*
|
||||
* This class is useful when RAM is at a premium, CBC mode is not required,
|
||||
* and reduced encryption performance is not a hindrance to the application.
|
||||
*
|
||||
* The companion AESSmall128 class supports decryptBlock() at the cost of
|
||||
* some additional memory and slower setKey() times.
|
||||
*
|
||||
* \sa AESSmall128, AES128
|
||||
*/
|
||||
|
||||
/** @cond */
|
||||
|
||||
// Helper macros.
|
||||
#define KCORE(n) \
|
||||
do { \
|
||||
AESCommon::keyScheduleCore(temp, schedule + 12, (n)); \
|
||||
schedule[0] ^= temp[0]; \
|
||||
schedule[1] ^= temp[1]; \
|
||||
schedule[2] ^= temp[2]; \
|
||||
schedule[3] ^= temp[3]; \
|
||||
} while (0)
|
||||
#define KXOR(a, b) \
|
||||
do { \
|
||||
schedule[(a) * 4] ^= schedule[(b) * 4]; \
|
||||
schedule[(a) * 4 + 1] ^= schedule[(b) * 4 + 1]; \
|
||||
schedule[(a) * 4 + 2] ^= schedule[(b) * 4 + 2]; \
|
||||
schedule[(a) * 4 + 3] ^= schedule[(b) * 4 + 3]; \
|
||||
} while (0)
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* \brief Constructs an AES 128-bit block cipher with no initial key.
|
||||
*
|
||||
* This constructor must be followed by a call to setKey() before the
|
||||
* block cipher can be used for encryption or decryption.
|
||||
*/
|
||||
AESTiny128::AESTiny128()
|
||||
{
|
||||
}
|
||||
|
||||
AESTiny128::~AESTiny128()
|
||||
{
|
||||
clean(schedule);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Size of an AES block in bytes.
|
||||
* \return Always returns 16.
|
||||
*/
|
||||
size_t AESTiny128::blockSize() const
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Size of a 128-bit AES key in bytes.
|
||||
* \return Always returns 16.
|
||||
*/
|
||||
size_t AESTiny128::keySize() const
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
bool AESTiny128::setKey(const uint8_t *key, size_t len)
|
||||
{
|
||||
if (len == 16) {
|
||||
// Make a copy of the key - it will be expanded in encryptBlock().
|
||||
memcpy(schedule, key, 16);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AESTiny128::encryptBlock(uint8_t *output, const uint8_t *input)
|
||||
{
|
||||
uint8_t schedule[16];
|
||||
uint8_t posn;
|
||||
uint8_t round;
|
||||
uint8_t state1[16];
|
||||
uint8_t state2[16];
|
||||
uint8_t temp[4];
|
||||
|
||||
// Start with the key in the schedule buffer.
|
||||
memcpy(schedule, this->schedule, 16);
|
||||
|
||||
// Copy the input into the state and XOR with the key schedule.
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
state1[posn] = input[posn] ^ schedule[posn];
|
||||
|
||||
// Perform the first 9 rounds of the cipher.
|
||||
for (round = 1; round <= 9; ++round) {
|
||||
// Expand the next 16 bytes of the key schedule.
|
||||
KCORE(round);
|
||||
KXOR(1, 0);
|
||||
KXOR(2, 1);
|
||||
KXOR(3, 2);
|
||||
|
||||
// Encrypt using the key schedule.
|
||||
AESCommon::subBytesAndShiftRows(state2, state1);
|
||||
AESCommon::mixColumn(state1, state2);
|
||||
AESCommon::mixColumn(state1 + 4, state2 + 4);
|
||||
AESCommon::mixColumn(state1 + 8, state2 + 8);
|
||||
AESCommon::mixColumn(state1 + 12, state2 + 12);
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
state1[posn] ^= schedule[posn];
|
||||
}
|
||||
|
||||
// Expand the final 16 bytes of the key schedule.
|
||||
KCORE(10);
|
||||
KXOR(1, 0);
|
||||
KXOR(2, 1);
|
||||
KXOR(3, 2);
|
||||
|
||||
// Perform the final round.
|
||||
AESCommon::subBytesAndShiftRows(state2, state1);
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
output[posn] = state2[posn] ^ schedule[posn];
|
||||
}
|
||||
|
||||
void AESTiny128::decryptBlock(uint8_t *output, const uint8_t *input)
|
||||
{
|
||||
// Decryption is not supported by AESTiny128.
|
||||
}
|
||||
|
||||
void AESTiny128::clear()
|
||||
{
|
||||
clean(schedule);
|
||||
}
|
||||
|
||||
/**
|
||||
* \class AESSmall128 AES.h <AES.h>
|
||||
* \brief AES block cipher with 128-bit keys and reduced memory usage.
|
||||
*
|
||||
* This class differs from the AES128 class in that the RAM requirements are
|
||||
* vastly reduced. The key schedule is expanded round by round instead of
|
||||
* being generated and stored by setKey(). The performance of encryption
|
||||
* and decryption is slightly less because of this.
|
||||
*
|
||||
* This class is useful when RAM is at a premium and reduced encryption
|
||||
* performance is not a hindrance to the application.
|
||||
*
|
||||
* The companion AESTiny128 class uses even less RAM but only supports the
|
||||
* encryptBlock() operation. Block cipher modes like CTR, EAX, and GCM
|
||||
* do not need the decryptBlock() operation, so AESTiny128 may be a better
|
||||
* option than AESSmall128 for many applications.
|
||||
*
|
||||
* \sa AESTiny128, AES128
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Constructs an AES 128-bit block cipher with no initial key.
|
||||
*
|
||||
* This constructor must be followed by a call to setKey() before the
|
||||
* block cipher can be used for encryption or decryption.
|
||||
*/
|
||||
AESSmall128::AESSmall128()
|
||||
{
|
||||
}
|
||||
|
||||
AESSmall128::~AESSmall128()
|
||||
{
|
||||
clean(reverse);
|
||||
}
|
||||
|
||||
bool AESSmall128::setKey(const uint8_t *key, size_t len)
|
||||
{
|
||||
uint8_t *schedule;
|
||||
uint8_t round;
|
||||
uint8_t temp[4];
|
||||
|
||||
// Set the encryption key first.
|
||||
if (!AESTiny128::setKey(key, len))
|
||||
return false;
|
||||
|
||||
// Expand the key schedule up to the last round which gives
|
||||
// us the round keys to use for the final two rounds. We can
|
||||
// then work backwards from there in decryptBlock().
|
||||
schedule = reverse;
|
||||
memcpy(schedule, key, 16);
|
||||
for (round = 1; round <= 10; ++round) {
|
||||
KCORE(round);
|
||||
KXOR(1, 0);
|
||||
KXOR(2, 1);
|
||||
KXOR(3, 2);
|
||||
}
|
||||
|
||||
// Key is ready to go.
|
||||
return true;
|
||||
}
|
||||
|
||||
void AESSmall128::decryptBlock(uint8_t *output, const uint8_t *input)
|
||||
{
|
||||
uint8_t schedule[16];
|
||||
uint8_t round;
|
||||
uint8_t posn;
|
||||
uint8_t state1[16];
|
||||
uint8_t state2[16];
|
||||
uint8_t temp[4];
|
||||
|
||||
// Start with the end of the decryption schedule.
|
||||
memcpy(schedule, reverse, 16);
|
||||
|
||||
// Copy the input into the state and reverse the final round.
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
state1[posn] = input[posn] ^ schedule[posn];
|
||||
AESCommon::inverseShiftRowsAndSubBytes(state2, state1);
|
||||
KXOR(3, 2);
|
||||
KXOR(2, 1);
|
||||
KXOR(1, 0);
|
||||
KCORE(10);
|
||||
|
||||
// Perform the next 9 rounds of the decryption process.
|
||||
for (round = 9; round >= 1; --round) {
|
||||
// Decrypt using the key schedule.
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
state2[posn] ^= schedule[posn];
|
||||
AESCommon::inverseMixColumn(state1, state2);
|
||||
AESCommon::inverseMixColumn(state1 + 4, state2 + 4);
|
||||
AESCommon::inverseMixColumn(state1 + 8, state2 + 8);
|
||||
AESCommon::inverseMixColumn(state1 + 12, state2 + 12);
|
||||
AESCommon::inverseShiftRowsAndSubBytes(state2, state1);
|
||||
|
||||
// Expand the next 16 bytes of the key schedule in reverse.
|
||||
KXOR(3, 2);
|
||||
KXOR(2, 1);
|
||||
KXOR(1, 0);
|
||||
KCORE(round);
|
||||
}
|
||||
|
||||
// Reverse the initial round and create the output words.
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
output[posn] = state2[posn] ^ schedule[posn];
|
||||
}
|
||||
|
||||
void AESSmall128::clear()
|
||||
{
|
||||
clean(reverse);
|
||||
AESTiny128::clear();
|
||||
}
|
||||
|
||||
#endif // CRYPTO_AES_DEFAULT
|
||||
+363
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* 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 "AES.h"
|
||||
#include "Crypto.h"
|
||||
#include "utility/ProgMemUtil.h"
|
||||
|
||||
#if defined(CRYPTO_AES_DEFAULT) || defined(CRYPTO_DOC)
|
||||
|
||||
/**
|
||||
* \class AESCommon AES.h <AES.h>
|
||||
* \brief Abstract base class for AES block ciphers.
|
||||
*
|
||||
* This class is abstract. The caller should instantiate AES128,
|
||||
* AES192, or AES256 to create an AES block cipher with a specific
|
||||
* key size.
|
||||
*
|
||||
* \note This AES implementation does not have constant cache behaviour due
|
||||
* to the use of table lookups. It may not be safe to use this implementation
|
||||
* in an environment where the attacker can observe the timing of encryption
|
||||
* and decryption operations. Unless AES compatibility is required,
|
||||
* it is recommended that the ChaCha stream cipher be used instead.
|
||||
*
|
||||
* Reference: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||||
*
|
||||
* \sa ChaCha, AES128, AES192, AES256
|
||||
*/
|
||||
|
||||
/** @cond sbox */
|
||||
|
||||
// AES S-box (http://en.wikipedia.org/wiki/Rijndael_S-box)
|
||||
static uint8_t const sbox[256] PROGMEM = {
|
||||
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, // 0x00
|
||||
0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
|
||||
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, // 0x10
|
||||
0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
|
||||
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, // 0x20
|
||||
0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
|
||||
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, // 0x30
|
||||
0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
|
||||
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, // 0x40
|
||||
0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
|
||||
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, // 0x50
|
||||
0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
|
||||
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, // 0x60
|
||||
0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
|
||||
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, // 0x70
|
||||
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
|
||||
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, // 0x80
|
||||
0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, // 0x90
|
||||
0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
|
||||
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, // 0xA0
|
||||
0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
|
||||
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, // 0xB0
|
||||
0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
|
||||
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, // 0xC0
|
||||
0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
|
||||
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, // 0xD0
|
||||
0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
|
||||
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, // 0xE0
|
||||
0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
|
||||
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, // 0xF0
|
||||
0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
|
||||
};
|
||||
|
||||
// AES inverse S-box (http://en.wikipedia.org/wiki/Rijndael_S-box)
|
||||
static uint8_t const sbox_inverse[256] PROGMEM = {
|
||||
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, // 0x00
|
||||
0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
|
||||
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, // 0x10
|
||||
0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
|
||||
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, // 0x20
|
||||
0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
|
||||
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, // 0x30
|
||||
0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
|
||||
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, // 0x40
|
||||
0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
|
||||
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, // 0x50
|
||||
0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
|
||||
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, // 0x60
|
||||
0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
|
||||
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, // 0x70
|
||||
0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
|
||||
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, // 0x80
|
||||
0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
|
||||
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, // 0x90
|
||||
0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
|
||||
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, // 0xA0
|
||||
0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
|
||||
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, // 0xB0
|
||||
0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
|
||||
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, // 0xC0
|
||||
0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
|
||||
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, // 0xD0
|
||||
0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
|
||||
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, // 0xE0
|
||||
0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, // 0xF0
|
||||
0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
|
||||
};
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* \brief Constructs an AES block cipher object.
|
||||
*/
|
||||
AESCommon::AESCommon()
|
||||
: rounds(0), schedule(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destroys this AES block cipher object after clearing
|
||||
* sensitive information.
|
||||
*/
|
||||
AESCommon::~AESCommon()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Size of an AES block in bytes.
|
||||
* \return Always returns 16.
|
||||
*/
|
||||
size_t AESCommon::blockSize() const
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
// Constants to correct Galois multiplication for the high bits
|
||||
// that are shifted out when multiplying by powers of two.
|
||||
static uint8_t const K[8] = {
|
||||
0x00,
|
||||
0x1B,
|
||||
(0x1B << 1),
|
||||
(0x1B << 1) ^ 0x1B,
|
||||
(0x1B << 2),
|
||||
(0x1B << 2) ^ 0x1B,
|
||||
(0x1B << 2) ^ (0x1B << 1),
|
||||
(0x1B << 2) ^ (0x1B << 1) ^ 0x1B
|
||||
};
|
||||
|
||||
// Multiply x by 2 in the Galois field, to achieve the effect of the following:
|
||||
//
|
||||
// if (x & 0x80)
|
||||
// return (x << 1) ^ 0x1B;
|
||||
// else
|
||||
// return (x << 1);
|
||||
//
|
||||
// However, we don't want to use runtime conditionals if we can help it
|
||||
// to avoid leaking timing information from the implementation.
|
||||
// In this case, multiplication is slightly faster than table lookup on AVR.
|
||||
#define gmul2(x) (t = ((uint16_t)(x)) << 1, \
|
||||
((uint8_t)t) ^ (uint8_t)(0x1B * ((uint8_t)(t >> 8))))
|
||||
|
||||
// Multiply x by 4 in the Galois field.
|
||||
#define gmul4(x) (t = ((uint16_t)(x)) << 2, ((uint8_t)t) ^ K[t >> 8])
|
||||
|
||||
// Multiply x by 8 in the Galois field.
|
||||
#define gmul8(x) (t = ((uint16_t)(x)) << 3, ((uint8_t)t) ^ K[t >> 8])
|
||||
|
||||
#define OUT(col, row) output[(col) * 4 + (row)]
|
||||
#define IN(col, row) input[(col) * 4 + (row)]
|
||||
|
||||
/** @cond aes_funcs */
|
||||
|
||||
void AESCommon::subBytesAndShiftRows(uint8_t *output, const uint8_t *input)
|
||||
{
|
||||
OUT(0, 0) = pgm_read_byte(sbox + IN(0, 0));
|
||||
OUT(0, 1) = pgm_read_byte(sbox + IN(1, 1));
|
||||
OUT(0, 2) = pgm_read_byte(sbox + IN(2, 2));
|
||||
OUT(0, 3) = pgm_read_byte(sbox + IN(3, 3));
|
||||
OUT(1, 0) = pgm_read_byte(sbox + IN(1, 0));
|
||||
OUT(1, 1) = pgm_read_byte(sbox + IN(2, 1));
|
||||
OUT(1, 2) = pgm_read_byte(sbox + IN(3, 2));
|
||||
OUT(1, 3) = pgm_read_byte(sbox + IN(0, 3));
|
||||
OUT(2, 0) = pgm_read_byte(sbox + IN(2, 0));
|
||||
OUT(2, 1) = pgm_read_byte(sbox + IN(3, 1));
|
||||
OUT(2, 2) = pgm_read_byte(sbox + IN(0, 2));
|
||||
OUT(2, 3) = pgm_read_byte(sbox + IN(1, 3));
|
||||
OUT(3, 0) = pgm_read_byte(sbox + IN(3, 0));
|
||||
OUT(3, 1) = pgm_read_byte(sbox + IN(0, 1));
|
||||
OUT(3, 2) = pgm_read_byte(sbox + IN(1, 2));
|
||||
OUT(3, 3) = pgm_read_byte(sbox + IN(2, 3));
|
||||
}
|
||||
|
||||
void AESCommon::inverseShiftRowsAndSubBytes(uint8_t *output, const uint8_t *input)
|
||||
{
|
||||
OUT(0, 0) = pgm_read_byte(sbox_inverse + IN(0, 0));
|
||||
OUT(0, 1) = pgm_read_byte(sbox_inverse + IN(3, 1));
|
||||
OUT(0, 2) = pgm_read_byte(sbox_inverse + IN(2, 2));
|
||||
OUT(0, 3) = pgm_read_byte(sbox_inverse + IN(1, 3));
|
||||
OUT(1, 0) = pgm_read_byte(sbox_inverse + IN(1, 0));
|
||||
OUT(1, 1) = pgm_read_byte(sbox_inverse + IN(0, 1));
|
||||
OUT(1, 2) = pgm_read_byte(sbox_inverse + IN(3, 2));
|
||||
OUT(1, 3) = pgm_read_byte(sbox_inverse + IN(2, 3));
|
||||
OUT(2, 0) = pgm_read_byte(sbox_inverse + IN(2, 0));
|
||||
OUT(2, 1) = pgm_read_byte(sbox_inverse + IN(1, 1));
|
||||
OUT(2, 2) = pgm_read_byte(sbox_inverse + IN(0, 2));
|
||||
OUT(2, 3) = pgm_read_byte(sbox_inverse + IN(3, 3));
|
||||
OUT(3, 0) = pgm_read_byte(sbox_inverse + IN(3, 0));
|
||||
OUT(3, 1) = pgm_read_byte(sbox_inverse + IN(2, 1));
|
||||
OUT(3, 2) = pgm_read_byte(sbox_inverse + IN(1, 2));
|
||||
OUT(3, 3) = pgm_read_byte(sbox_inverse + IN(0, 3));
|
||||
}
|
||||
|
||||
void AESCommon::mixColumn(uint8_t *output, uint8_t *input)
|
||||
{
|
||||
uint16_t t; // Needed by the gmul2 macro.
|
||||
uint8_t a = input[0];
|
||||
uint8_t b = input[1];
|
||||
uint8_t c = input[2];
|
||||
uint8_t d = input[3];
|
||||
uint8_t a2 = gmul2(a);
|
||||
uint8_t b2 = gmul2(b);
|
||||
uint8_t c2 = gmul2(c);
|
||||
uint8_t d2 = gmul2(d);
|
||||
output[0] = a2 ^ b2 ^ b ^ c ^ d;
|
||||
output[1] = a ^ b2 ^ c2 ^ c ^ d;
|
||||
output[2] = a ^ b ^ c2 ^ d2 ^ d;
|
||||
output[3] = a2 ^ a ^ b ^ c ^ d2;
|
||||
}
|
||||
|
||||
void AESCommon::inverseMixColumn(uint8_t *output, const uint8_t *input)
|
||||
{
|
||||
uint16_t t; // Needed by the gmul2, gmul4, and gmul8 macros.
|
||||
uint8_t a = input[0];
|
||||
uint8_t b = input[1];
|
||||
uint8_t c = input[2];
|
||||
uint8_t d = input[3];
|
||||
uint8_t a2 = gmul2(a);
|
||||
uint8_t b2 = gmul2(b);
|
||||
uint8_t c2 = gmul2(c);
|
||||
uint8_t d2 = gmul2(d);
|
||||
uint8_t a4 = gmul4(a);
|
||||
uint8_t b4 = gmul4(b);
|
||||
uint8_t c4 = gmul4(c);
|
||||
uint8_t d4 = gmul4(d);
|
||||
uint8_t a8 = gmul8(a);
|
||||
uint8_t b8 = gmul8(b);
|
||||
uint8_t c8 = gmul8(c);
|
||||
uint8_t d8 = gmul8(d);
|
||||
output[0] = a8 ^ a4 ^ a2 ^ b8 ^ b2 ^ b ^ c8 ^ c4 ^ c ^ d8 ^ d;
|
||||
output[1] = a8 ^ a ^ b8 ^ b4 ^ b2 ^ c8 ^ c2 ^ c ^ d8 ^ d4 ^ d;
|
||||
output[2] = a8 ^ a4 ^ a ^ b8 ^ b ^ c8 ^ c4 ^ c2 ^ d8 ^ d2 ^ d;
|
||||
output[3] = a8 ^ a2 ^ a ^ b8 ^ b4 ^ b ^ c8 ^ c ^ d8 ^ d4 ^ d2;
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
void AESCommon::encryptBlock(uint8_t *output, const uint8_t *input)
|
||||
{
|
||||
const uint8_t *roundKey = schedule;
|
||||
uint8_t posn;
|
||||
uint8_t round;
|
||||
uint8_t state1[16];
|
||||
uint8_t state2[16];
|
||||
|
||||
// Copy the input into the state and XOR with the first round key.
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
state1[posn] = input[posn] ^ roundKey[posn];
|
||||
roundKey += 16;
|
||||
|
||||
// Perform all rounds except the last.
|
||||
for (round = rounds; round > 1; --round) {
|
||||
subBytesAndShiftRows(state2, state1);
|
||||
mixColumn(state1, state2);
|
||||
mixColumn(state1 + 4, state2 + 4);
|
||||
mixColumn(state1 + 8, state2 + 8);
|
||||
mixColumn(state1 + 12, state2 + 12);
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
state1[posn] ^= roundKey[posn];
|
||||
roundKey += 16;
|
||||
}
|
||||
|
||||
// Perform the final round.
|
||||
subBytesAndShiftRows(state2, state1);
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
output[posn] = state2[posn] ^ roundKey[posn];
|
||||
}
|
||||
|
||||
void AESCommon::decryptBlock(uint8_t *output, const uint8_t *input)
|
||||
{
|
||||
const uint8_t *roundKey = schedule + rounds * 16;
|
||||
uint8_t round;
|
||||
uint8_t posn;
|
||||
uint8_t state1[16];
|
||||
uint8_t state2[16];
|
||||
|
||||
// Copy the input into the state and reverse the final round.
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
state1[posn] = input[posn] ^ roundKey[posn];
|
||||
inverseShiftRowsAndSubBytes(state2, state1);
|
||||
|
||||
// Perform all other rounds in reverse.
|
||||
for (round = rounds; round > 1; --round) {
|
||||
roundKey -= 16;
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
state2[posn] ^= roundKey[posn];
|
||||
inverseMixColumn(state1, state2);
|
||||
inverseMixColumn(state1 + 4, state2 + 4);
|
||||
inverseMixColumn(state1 + 8, state2 + 8);
|
||||
inverseMixColumn(state1 + 12, state2 + 12);
|
||||
inverseShiftRowsAndSubBytes(state2, state1);
|
||||
}
|
||||
|
||||
// Reverse the initial round and create the output words.
|
||||
roundKey -= 16;
|
||||
for (posn = 0; posn < 16; ++posn)
|
||||
output[posn] = state2[posn] ^ roundKey[posn];
|
||||
}
|
||||
|
||||
void AESCommon::clear()
|
||||
{
|
||||
clean(schedule, (rounds + 1) * 16);
|
||||
}
|
||||
|
||||
/** @cond aes_keycore */
|
||||
|
||||
void AESCommon::keyScheduleCore(uint8_t *output, const uint8_t *input, uint8_t iteration)
|
||||
{
|
||||
// Rcon(i), 2^i in the Rijndael finite field, for i = 0..10.
|
||||
// http://en.wikipedia.org/wiki/Rijndael_key_schedule
|
||||
static uint8_t const rcon[11] PROGMEM = {
|
||||
0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, // 0x00
|
||||
0x80, 0x1B, 0x36
|
||||
};
|
||||
output[0] = pgm_read_byte(sbox + input[1]) ^ pgm_read_byte(rcon + iteration);
|
||||
output[1] = pgm_read_byte(sbox + input[2]);
|
||||
output[2] = pgm_read_byte(sbox + input[3]);
|
||||
output[3] = pgm_read_byte(sbox + input[0]);
|
||||
}
|
||||
|
||||
void AESCommon::applySbox(uint8_t *output, const uint8_t *input)
|
||||
{
|
||||
output[0] = pgm_read_byte(sbox + input[0]);
|
||||
output[1] = pgm_read_byte(sbox + input[1]);
|
||||
output[2] = pgm_read_byte(sbox + input[2]);
|
||||
output[3] = pgm_read_byte(sbox + input[3]);
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
#endif // CRYPTO_AES_DEFAULT
|
||||
+769
@@ -0,0 +1,769 @@
|
||||
/*
|
||||
* 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 "BigNumberUtil.h"
|
||||
#include "utility/EndianUtil.h"
|
||||
#include "utility/LimbUtil.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* \class BigNumberUtil BigNumberUtil.h <BigNumberUtil.h>
|
||||
* \brief Utilities to assist with implementing big number arithmetic.
|
||||
*
|
||||
* Big numbers are represented as arrays of limb_t words, which may be
|
||||
* 8 bits, 16 bits, or 32 bits in size depending upon how the library
|
||||
* was configured. For AVR, 16 bit limbs usually give the best performance.
|
||||
*
|
||||
* Limb arrays are ordered from the least significant word to the most
|
||||
* significant.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Unpacks the little-endian byte representation of a big number
|
||||
* into a limb array.
|
||||
*
|
||||
* \param limbs The limb array, starting with the least significant word.
|
||||
* \param count The number of elements in the \a limbs array.
|
||||
* \param bytes The bytes to unpack.
|
||||
* \param len The number of bytes to unpack.
|
||||
*
|
||||
* If \a len is shorter than the length of \a limbs, then the high bytes
|
||||
* will be filled with zeroes. If \a len is longer than the length of
|
||||
* \a limbs, then the high bytes will be truncated and lost.
|
||||
*
|
||||
* \sa packLE(), unpackBE()
|
||||
*/
|
||||
void BigNumberUtil::unpackLE(limb_t *limbs, size_t count,
|
||||
const uint8_t *bytes, size_t len)
|
||||
{
|
||||
#if BIGNUMBER_LIMB_8BIT
|
||||
if (len < count) {
|
||||
memcpy(limbs, bytes, len);
|
||||
memset(limbs + len, 0, count - len);
|
||||
} else {
|
||||
memcpy(limbs, bytes, count);
|
||||
}
|
||||
#elif CRYPTO_LITTLE_ENDIAN
|
||||
count *= sizeof(limb_t);
|
||||
if (len < count) {
|
||||
memcpy(limbs, bytes, len);
|
||||
memset(((uint8_t *)limbs) + len, 0, count - len);
|
||||
} else {
|
||||
memcpy(limbs, bytes, count);
|
||||
}
|
||||
#elif BIGNUMBER_LIMB_16BIT
|
||||
while (count > 0 && len >= 2) {
|
||||
*limbs++ = ((limb_t)(bytes[0])) |
|
||||
(((limb_t)(bytes[1])) << 8);
|
||||
bytes += 2;
|
||||
--count;
|
||||
len -= 2;
|
||||
}
|
||||
if (count > 0 && len == 1) {
|
||||
*limbs++ = ((limb_t)(bytes[0]));
|
||||
--count;
|
||||
}
|
||||
while (count > 0) {
|
||||
*limbs++ = 0;
|
||||
--count;
|
||||
}
|
||||
#elif BIGNUMBER_LIMB_32BIT
|
||||
while (count > 0 && len >= 4) {
|
||||
*limbs++ = ((limb_t)(bytes[0])) |
|
||||
(((limb_t)(bytes[1])) << 8) |
|
||||
(((limb_t)(bytes[2])) << 16) |
|
||||
(((limb_t)(bytes[3])) << 24);
|
||||
bytes += 4;
|
||||
--count;
|
||||
len -= 4;
|
||||
}
|
||||
if (count > 0 && len > 0) {
|
||||
if (len == 3) {
|
||||
*limbs++ = ((limb_t)(bytes[0])) |
|
||||
(((limb_t)(bytes[1])) << 8) |
|
||||
(((limb_t)(bytes[2])) << 16);
|
||||
} else if (len == 2) {
|
||||
*limbs++ = ((limb_t)(bytes[0])) |
|
||||
(((limb_t)(bytes[1])) << 8);
|
||||
} else {
|
||||
*limbs++ = ((limb_t)(bytes[0]));
|
||||
}
|
||||
--count;
|
||||
}
|
||||
while (count > 0) {
|
||||
*limbs++ = 0;
|
||||
--count;
|
||||
}
|
||||
#elif BIGNUMBER_LIMB_64BIT
|
||||
while (count > 0 && len >= 8) {
|
||||
*limbs++ = ((limb_t)(bytes[0])) |
|
||||
(((limb_t)(bytes[1])) << 8) |
|
||||
(((limb_t)(bytes[2])) << 16) |
|
||||
(((limb_t)(bytes[3])) << 24) |
|
||||
(((limb_t)(bytes[4])) << 32) |
|
||||
(((limb_t)(bytes[5])) << 40) |
|
||||
(((limb_t)(bytes[6])) << 48) |
|
||||
(((limb_t)(bytes[7])) << 56);
|
||||
bytes += 8;
|
||||
--count;
|
||||
len -= 8;
|
||||
}
|
||||
if (count > 0 && len > 0) {
|
||||
limb_t word = 0;
|
||||
uint8_t shift = 0;
|
||||
while (len > 0 && shift < 64) {
|
||||
word |= (((limb_t)(*bytes++)) << shift);
|
||||
shift += 8;
|
||||
--len;
|
||||
}
|
||||
*limbs++ = word;
|
||||
--count;
|
||||
}
|
||||
while (count > 0) {
|
||||
*limbs++ = 0;
|
||||
--count;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Unpacks the big-endian byte representation of a big number
|
||||
* into a limb array.
|
||||
*
|
||||
* \param limbs The limb array, starting with the least significant word.
|
||||
* \param count The number of elements in the \a limbs array.
|
||||
* \param bytes The bytes to unpack.
|
||||
* \param len The number of bytes to unpack.
|
||||
*
|
||||
* If \a len is shorter than the length of \a limbs, then the high bytes
|
||||
* will be filled with zeroes. If \a len is longer than the length of
|
||||
* \a limbs, then the high bytes will be truncated and lost.
|
||||
*
|
||||
* \sa packBE(), unpackLE()
|
||||
*/
|
||||
void BigNumberUtil::unpackBE(limb_t *limbs, size_t count,
|
||||
const uint8_t *bytes, size_t len)
|
||||
{
|
||||
#if BIGNUMBER_LIMB_8BIT
|
||||
while (count > 0 && len > 0) {
|
||||
--count;
|
||||
--len;
|
||||
*limbs++ = bytes[len];
|
||||
}
|
||||
memset(limbs, 0, count);
|
||||
#elif BIGNUMBER_LIMB_16BIT
|
||||
bytes += len;
|
||||
while (count > 0 && len >= 2) {
|
||||
--count;
|
||||
bytes -= 2;
|
||||
len -= 2;
|
||||
*limbs++ = ((limb_t)(bytes[1])) |
|
||||
(((limb_t)(bytes[0])) << 8);
|
||||
}
|
||||
if (count > 0 && len == 1) {
|
||||
--count;
|
||||
--bytes;
|
||||
*limbs++ = (limb_t)(bytes[0]);
|
||||
}
|
||||
memset(limbs, 0, count * sizeof(limb_t));
|
||||
#elif BIGNUMBER_LIMB_32BIT
|
||||
bytes += len;
|
||||
while (count > 0 && len >= 4) {
|
||||
--count;
|
||||
bytes -= 4;
|
||||
len -= 4;
|
||||
*limbs++ = ((limb_t)(bytes[3])) |
|
||||
(((limb_t)(bytes[2])) << 8) |
|
||||
(((limb_t)(bytes[1])) << 16) |
|
||||
(((limb_t)(bytes[0])) << 24);
|
||||
}
|
||||
if (count > 0) {
|
||||
if (len == 3) {
|
||||
--count;
|
||||
bytes -= 3;
|
||||
*limbs++ = ((limb_t)(bytes[2])) |
|
||||
(((limb_t)(bytes[1])) << 8) |
|
||||
(((limb_t)(bytes[0])) << 16);
|
||||
} else if (len == 2) {
|
||||
--count;
|
||||
bytes -= 2;
|
||||
*limbs++ = ((limb_t)(bytes[1])) |
|
||||
(((limb_t)(bytes[0])) << 8);
|
||||
} else if (len == 1) {
|
||||
--count;
|
||||
--bytes;
|
||||
*limbs++ = (limb_t)(bytes[0]);
|
||||
}
|
||||
}
|
||||
memset(limbs, 0, count * sizeof(limb_t));
|
||||
#elif BIGNUMBER_LIMB_64BIT
|
||||
bytes += len;
|
||||
while (count > 0 && len >= 8) {
|
||||
--count;
|
||||
bytes -= 8;
|
||||
len -= 8;
|
||||
*limbs++ = ((limb_t)(bytes[7])) |
|
||||
(((limb_t)(bytes[6])) << 8) |
|
||||
(((limb_t)(bytes[5])) << 16) |
|
||||
(((limb_t)(bytes[4])) << 24) |
|
||||
(((limb_t)(bytes[3])) << 32) |
|
||||
(((limb_t)(bytes[2])) << 40) |
|
||||
(((limb_t)(bytes[1])) << 48) |
|
||||
(((limb_t)(bytes[0])) << 56);
|
||||
}
|
||||
if (count > 0 && len > 0) {
|
||||
limb_t word = 0;
|
||||
uint8_t shift = 0;
|
||||
while (len > 0 && shift < 64) {
|
||||
word |= (((limb_t)(*(--bytes))) << shift);
|
||||
shift += 8;
|
||||
--len;
|
||||
}
|
||||
*limbs++ = word;
|
||||
--count;
|
||||
}
|
||||
memset(limbs, 0, count * sizeof(limb_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Packs the little-endian byte representation of a big number
|
||||
* into a byte array.
|
||||
*
|
||||
* \param bytes The byte array to pack into.
|
||||
* \param len The number of bytes in the destination \a bytes array.
|
||||
* \param limbs The limb array representing the big number, starting with
|
||||
* the least significant word.
|
||||
* \param count The number of elements in the \a limbs array.
|
||||
*
|
||||
* If \a len is shorter than the length of \a limbs, then the number will
|
||||
* be truncated to the least significant \a len bytes. If \a len is longer
|
||||
* than the length of \a limbs, then the high bytes will be filled with zeroes.
|
||||
*
|
||||
* \sa unpackLE(), packBE()
|
||||
*/
|
||||
void BigNumberUtil::packLE(uint8_t *bytes, size_t len,
|
||||
const limb_t *limbs, size_t count)
|
||||
{
|
||||
#if BIGNUMBER_LIMB_8BIT
|
||||
if (len <= count) {
|
||||
memcpy(bytes, limbs, len);
|
||||
} else {
|
||||
memcpy(bytes, limbs, count);
|
||||
memset(bytes + count, 0, len - count);
|
||||
}
|
||||
#elif CRYPTO_LITTLE_ENDIAN
|
||||
count *= sizeof(limb_t);
|
||||
if (len <= count) {
|
||||
memcpy(bytes, limbs, len);
|
||||
} else {
|
||||
memcpy(bytes, limbs, count);
|
||||
memset(bytes + count, 0, len - count);
|
||||
}
|
||||
#elif BIGNUMBER_LIMB_16BIT
|
||||
limb_t word;
|
||||
while (count > 0 && len >= 2) {
|
||||
word = *limbs++;
|
||||
bytes[0] = (uint8_t)word;
|
||||
bytes[1] = (uint8_t)(word >> 8);
|
||||
--count;
|
||||
len -= 2;
|
||||
bytes += 2;
|
||||
}
|
||||
if (count > 0 && len == 1) {
|
||||
bytes[0] = (uint8_t)(*limbs);
|
||||
--len;
|
||||
++bytes;
|
||||
}
|
||||
memset(bytes, 0, len);
|
||||
#elif BIGNUMBER_LIMB_32BIT
|
||||
limb_t word;
|
||||
while (count > 0 && len >= 4) {
|
||||
word = *limbs++;
|
||||
bytes[0] = (uint8_t)word;
|
||||
bytes[1] = (uint8_t)(word >> 8);
|
||||
bytes[2] = (uint8_t)(word >> 16);
|
||||
bytes[3] = (uint8_t)(word >> 24);
|
||||
--count;
|
||||
len -= 4;
|
||||
bytes += 4;
|
||||
}
|
||||
if (count > 0) {
|
||||
if (len == 3) {
|
||||
word = *limbs;
|
||||
bytes[0] = (uint8_t)word;
|
||||
bytes[1] = (uint8_t)(word >> 8);
|
||||
bytes[2] = (uint8_t)(word >> 16);
|
||||
len -= 3;
|
||||
bytes += 3;
|
||||
} else if (len == 2) {
|
||||
word = *limbs;
|
||||
bytes[0] = (uint8_t)word;
|
||||
bytes[1] = (uint8_t)(word >> 8);
|
||||
len -= 2;
|
||||
bytes += 2;
|
||||
} else if (len == 1) {
|
||||
bytes[0] = (uint8_t)(*limbs);
|
||||
--len;
|
||||
++bytes;
|
||||
}
|
||||
}
|
||||
memset(bytes, 0, len);
|
||||
#elif BIGNUMBER_LIMB_64BIT
|
||||
limb_t word;
|
||||
while (count > 0 && len >= 8) {
|
||||
word = *limbs++;
|
||||
bytes[0] = (uint8_t)word;
|
||||
bytes[1] = (uint8_t)(word >> 8);
|
||||
bytes[2] = (uint8_t)(word >> 16);
|
||||
bytes[3] = (uint8_t)(word >> 24);
|
||||
bytes[4] = (uint8_t)(word >> 32);
|
||||
bytes[5] = (uint8_t)(word >> 40);
|
||||
bytes[6] = (uint8_t)(word >> 48);
|
||||
bytes[7] = (uint8_t)(word >> 56);
|
||||
--count;
|
||||
len -= 8;
|
||||
bytes += 8;
|
||||
}
|
||||
if (count > 0) {
|
||||
word = *limbs;
|
||||
while (len > 0) {
|
||||
*bytes++ = (uint8_t)word;
|
||||
word >>= 8;
|
||||
--len;
|
||||
}
|
||||
}
|
||||
memset(bytes, 0, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Packs the big-endian byte representation of a big number
|
||||
* into a byte array.
|
||||
*
|
||||
* \param bytes The byte array to pack into.
|
||||
* \param len The number of bytes in the destination \a bytes array.
|
||||
* \param limbs The limb array representing the big number, starting with
|
||||
* the least significant word.
|
||||
* \param count The number of elements in the \a limbs array.
|
||||
*
|
||||
* If \a len is shorter than the length of \a limbs, then the number will
|
||||
* be truncated to the least significant \a len bytes. If \a len is longer
|
||||
* than the length of \a limbs, then the high bytes will be filled with zeroes.
|
||||
*
|
||||
* \sa unpackLE(), packBE()
|
||||
*/
|
||||
void BigNumberUtil::packBE(uint8_t *bytes, size_t len,
|
||||
const limb_t *limbs, size_t count)
|
||||
{
|
||||
#if BIGNUMBER_LIMB_8BIT
|
||||
if (len > count) {
|
||||
size_t size = len - count;
|
||||
memset(bytes, 0, size);
|
||||
len -= size;
|
||||
bytes += size;
|
||||
} else if (len < count) {
|
||||
count = len;
|
||||
}
|
||||
limbs += count;
|
||||
while (count > 0) {
|
||||
--count;
|
||||
*bytes++ = *(--limbs);
|
||||
}
|
||||
#elif BIGNUMBER_LIMB_16BIT
|
||||
size_t countBytes = count * sizeof(limb_t);
|
||||
limb_t word;
|
||||
if (len >= countBytes) {
|
||||
size_t size = len - countBytes;
|
||||
memset(bytes, 0, size);
|
||||
len -= size;
|
||||
bytes += size;
|
||||
limbs += count;
|
||||
} else {
|
||||
count = len / sizeof(limb_t);
|
||||
limbs += count;
|
||||
if ((len & 1) != 0)
|
||||
*bytes++ = (uint8_t)(*limbs);
|
||||
}
|
||||
while (count > 0) {
|
||||
--count;
|
||||
word = *(--limbs);
|
||||
*bytes++ = (uint8_t)(word >> 8);
|
||||
*bytes++ = (uint8_t)word;
|
||||
}
|
||||
#elif BIGNUMBER_LIMB_32BIT
|
||||
size_t countBytes = count * sizeof(limb_t);
|
||||
limb_t word;
|
||||
if (len >= countBytes) {
|
||||
size_t size = len - countBytes;
|
||||
memset(bytes, 0, size);
|
||||
len -= size;
|
||||
bytes += size;
|
||||
limbs += count;
|
||||
} else {
|
||||
count = len / sizeof(limb_t);
|
||||
limbs += count;
|
||||
if ((len & 3) == 3) {
|
||||
word = *limbs;
|
||||
*bytes++ = (uint8_t)(word >> 16);
|
||||
*bytes++ = (uint8_t)(word >> 8);
|
||||
*bytes++ = (uint8_t)word;
|
||||
} else if ((len & 3) == 2) {
|
||||
word = *limbs;
|
||||
*bytes++ = (uint8_t)(word >> 8);
|
||||
*bytes++ = (uint8_t)word;
|
||||
} else if ((len & 3) == 1) {
|
||||
*bytes++ = (uint8_t)(*limbs);
|
||||
}
|
||||
}
|
||||
while (count > 0) {
|
||||
--count;
|
||||
word = *(--limbs);
|
||||
*bytes++ = (uint8_t)(word >> 24);
|
||||
*bytes++ = (uint8_t)(word >> 16);
|
||||
*bytes++ = (uint8_t)(word >> 8);
|
||||
*bytes++ = (uint8_t)word;
|
||||
}
|
||||
#elif BIGNUMBER_LIMB_64BIT
|
||||
size_t countBytes = count * sizeof(limb_t);
|
||||
limb_t word;
|
||||
if (len >= countBytes) {
|
||||
size_t size = len - countBytes;
|
||||
memset(bytes, 0, size);
|
||||
len -= size;
|
||||
bytes += size;
|
||||
limbs += count;
|
||||
} else {
|
||||
count = len / sizeof(limb_t);
|
||||
limbs += count;
|
||||
uint8_t size = len & 7;
|
||||
uint8_t shift = size * 8;
|
||||
word = *limbs;
|
||||
while (size > 0) {
|
||||
shift -= 8;
|
||||
*bytes++ = (uint8_t)(word >> shift);
|
||||
--size;
|
||||
}
|
||||
}
|
||||
while (count > 0) {
|
||||
--count;
|
||||
word = *(--limbs);
|
||||
*bytes++ = (uint8_t)(word >> 56);
|
||||
*bytes++ = (uint8_t)(word >> 48);
|
||||
*bytes++ = (uint8_t)(word >> 40);
|
||||
*bytes++ = (uint8_t)(word >> 32);
|
||||
*bytes++ = (uint8_t)(word >> 24);
|
||||
*bytes++ = (uint8_t)(word >> 16);
|
||||
*bytes++ = (uint8_t)(word >> 8);
|
||||
*bytes++ = (uint8_t)word;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds two big numbers.
|
||||
*
|
||||
* \param result The result of the addition. This can be the same
|
||||
* as either \a x or \a y.
|
||||
* \param x The first big number.
|
||||
* \param y The second big number.
|
||||
* \param size The size of the values in limbs.
|
||||
*
|
||||
* \return Returns 1 if there was a carry out or 0 if there was no carry out.
|
||||
*
|
||||
* \sa sub(), mul()
|
||||
*/
|
||||
limb_t BigNumberUtil::add(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size)
|
||||
{
|
||||
dlimb_t carry = 0;
|
||||
while (size > 0) {
|
||||
carry += *x++;
|
||||
carry += *y++;
|
||||
*result++ = (limb_t)carry;
|
||||
carry >>= LIMB_BITS;
|
||||
--size;
|
||||
}
|
||||
return (limb_t)carry;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Subtracts one big number from another.
|
||||
*
|
||||
* \param result The result of the subtraction. This can be the same
|
||||
* as either \a x or \a y.
|
||||
* \param x The first big number.
|
||||
* \param y The second big number to subtract from \a x.
|
||||
* \param size The size of the values in limbs.
|
||||
*
|
||||
* \return Returns 1 if there was a borrow, or 0 if there was no borrow.
|
||||
*
|
||||
* \sa add(), mul()
|
||||
*/
|
||||
limb_t BigNumberUtil::sub(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size)
|
||||
{
|
||||
dlimb_t borrow = 0;
|
||||
while (size > 0) {
|
||||
borrow = ((dlimb_t)(*x++)) - (*y++) - ((borrow >> LIMB_BITS) & 0x01);
|
||||
*result++ = (limb_t)borrow;
|
||||
--size;
|
||||
}
|
||||
return ((limb_t)(borrow >> LIMB_BITS)) & 0x01;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Multiplies two big numbers.
|
||||
*
|
||||
* \param result The result of the multiplication. The array must be
|
||||
* \a xcount + \a ycount limbs in size.
|
||||
* \param x Points to the first value to multiply.
|
||||
* \param xcount The number of limbs in \a x.
|
||||
* \param y Points to the second value to multiply.
|
||||
* \param ycount The number of limbs in \a y.
|
||||
*
|
||||
* \sa mul_P()
|
||||
*/
|
||||
void BigNumberUtil::mul(limb_t *result, const limb_t *x, size_t xcount,
|
||||
const limb_t *y, size_t ycount)
|
||||
{
|
||||
size_t i, j;
|
||||
dlimb_t carry;
|
||||
limb_t word;
|
||||
const limb_t *xx;
|
||||
limb_t *rr;
|
||||
|
||||
// Multiply the lowest limb of y by x.
|
||||
carry = 0;
|
||||
word = y[0];
|
||||
xx = x;
|
||||
rr = result;
|
||||
for (i = 0; i < xcount; ++i) {
|
||||
carry += ((dlimb_t)(*xx++)) * word;
|
||||
*rr++ = (limb_t)carry;
|
||||
carry >>= LIMB_BITS;
|
||||
}
|
||||
*rr = (limb_t)carry;
|
||||
|
||||
// Multiply and add the remaining limbs of y by x.
|
||||
for (i = 1; i < ycount; ++i) {
|
||||
word = y[i];
|
||||
carry = 0;
|
||||
xx = x;
|
||||
rr = result + i;
|
||||
for (j = 0; j < xcount; ++j) {
|
||||
carry += ((dlimb_t)(*xx++)) * word;
|
||||
carry += *rr;
|
||||
*rr++ = (limb_t)carry;
|
||||
carry >>= LIMB_BITS;
|
||||
}
|
||||
*rr = (limb_t)carry;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reduces \a x modulo \a y using subtraction.
|
||||
*
|
||||
* \param result The result of the reduction. This can be the
|
||||
* same as \a x.
|
||||
* \param x The number to be reduced.
|
||||
* \param y The base to use for the modulo reduction.
|
||||
* \param size The size of the values in limbs.
|
||||
*
|
||||
* It is assumed that \a x is less than \a y * 2 so that a single
|
||||
* conditional subtraction will bring it down below \a y. The reduction
|
||||
* is performed in constant time.
|
||||
*
|
||||
* \sa reduceQuick_P()
|
||||
*/
|
||||
void BigNumberUtil::reduceQuick(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size)
|
||||
{
|
||||
// Subtract "y" from "x" and turn the borrow into an AND mask.
|
||||
limb_t mask = sub(result, x, y, size);
|
||||
mask = (~mask) + 1;
|
||||
|
||||
// Add "y" back to the result if the mask is non-zero.
|
||||
dlimb_t carry = 0;
|
||||
while (size > 0) {
|
||||
carry += *result;
|
||||
carry += (*y++ & mask);
|
||||
*result++ = (limb_t)carry;
|
||||
carry >>= LIMB_BITS;
|
||||
--size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds two big numbers where one of them is in program memory.
|
||||
*
|
||||
* \param result The result of the addition. This can be the same as \a x.
|
||||
* \param x The first big number.
|
||||
* \param y The second big number. This must point into program memory.
|
||||
* \param size The size of the values in limbs.
|
||||
*
|
||||
* \return Returns 1 if there was a carry out or 0 if there was no carry out.
|
||||
*
|
||||
* \sa sub_P(), mul_P()
|
||||
*/
|
||||
limb_t BigNumberUtil::add_P(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size)
|
||||
{
|
||||
dlimb_t carry = 0;
|
||||
while (size > 0) {
|
||||
carry += *x++;
|
||||
carry += pgm_read_limb(y++);
|
||||
*result++ = (limb_t)carry;
|
||||
carry >>= LIMB_BITS;
|
||||
--size;
|
||||
}
|
||||
return (limb_t)carry;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Subtracts one big number from another where one is in program memory.
|
||||
*
|
||||
* \param result The result of the subtraction. This can be the same as \a x.
|
||||
* \param x The first big number.
|
||||
* \param y The second big number to subtract from \a x. This must point
|
||||
* into program memory.
|
||||
* \param size The size of the values in limbs.
|
||||
*
|
||||
* \return Returns 1 if there was a borrow, or 0 if there was no borrow.
|
||||
*
|
||||
* \sa add_P(), mul_P()
|
||||
*/
|
||||
limb_t BigNumberUtil::sub_P(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size)
|
||||
{
|
||||
dlimb_t borrow = 0;
|
||||
while (size > 0) {
|
||||
borrow = ((dlimb_t)(*x++)) - pgm_read_limb(y++) - ((borrow >> LIMB_BITS) & 0x01);
|
||||
*result++ = (limb_t)borrow;
|
||||
--size;
|
||||
}
|
||||
return ((limb_t)(borrow >> LIMB_BITS)) & 0x01;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Multiplies two big numbers where one is in program memory.
|
||||
*
|
||||
* \param result The result of the multiplication. The array must be
|
||||
* \a xcount + \a ycount limbs in size.
|
||||
* \param x Points to the first value to multiply.
|
||||
* \param xcount The number of limbs in \a x.
|
||||
* \param y Points to the second value to multiply. This must point
|
||||
* into program memory.
|
||||
* \param ycount The number of limbs in \a y.
|
||||
*
|
||||
* \sa mul()
|
||||
*/
|
||||
void BigNumberUtil::mul_P(limb_t *result, const limb_t *x, size_t xcount,
|
||||
const limb_t *y, size_t ycount)
|
||||
{
|
||||
size_t i, j;
|
||||
dlimb_t carry;
|
||||
limb_t word;
|
||||
const limb_t *xx;
|
||||
limb_t *rr;
|
||||
|
||||
// Multiply the lowest limb of y by x.
|
||||
carry = 0;
|
||||
word = pgm_read_limb(&(y[0]));
|
||||
xx = x;
|
||||
rr = result;
|
||||
for (i = 0; i < xcount; ++i) {
|
||||
carry += ((dlimb_t)(*xx++)) * word;
|
||||
*rr++ = (limb_t)carry;
|
||||
carry >>= LIMB_BITS;
|
||||
}
|
||||
*rr = (limb_t)carry;
|
||||
|
||||
// Multiply and add the remaining limb of y by x.
|
||||
for (i = 1; i < ycount; ++i) {
|
||||
word = pgm_read_limb(&(y[i]));
|
||||
carry = 0;
|
||||
xx = x;
|
||||
rr = result + i;
|
||||
for (j = 0; j < xcount; ++j) {
|
||||
carry += ((dlimb_t)(*xx++)) * word;
|
||||
carry += *rr;
|
||||
*rr++ = (limb_t)carry;
|
||||
carry >>= LIMB_BITS;
|
||||
}
|
||||
*rr = (limb_t)carry;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reduces \a x modulo \a y using subtraction where \a y is
|
||||
* in program memory.
|
||||
*
|
||||
* \param result The result of the reduction. This can be the
|
||||
* same as \a x.
|
||||
* \param x The number to be reduced.
|
||||
* \param y The base to use for the modulo reduction. This must point
|
||||
* into program memory.
|
||||
* \param size The size of the values in limbs.
|
||||
*
|
||||
* It is assumed that \a x is less than \a y * 2 so that a single
|
||||
* conditional subtraction will bring it down below \a y. The reduction
|
||||
* is performed in constant time.
|
||||
*
|
||||
* \sa reduceQuick()
|
||||
*/
|
||||
void BigNumberUtil::reduceQuick_P(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size)
|
||||
{
|
||||
// Subtract "y" from "x" and turn the borrow into an AND mask.
|
||||
limb_t mask = sub_P(result, x, y, size);
|
||||
mask = (~mask) + 1;
|
||||
|
||||
// Add "y" back to the result if the mask is non-zero.
|
||||
dlimb_t carry = 0;
|
||||
while (size > 0) {
|
||||
carry += *result;
|
||||
carry += (pgm_read_limb(y++) & mask);
|
||||
*result++ = (limb_t)carry;
|
||||
carry >>= LIMB_BITS;
|
||||
--size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Determine if a big number is zero.
|
||||
*
|
||||
* \param x Points to the number to test.
|
||||
* \param size The number of limbs in \a x.
|
||||
* \return Returns 1 if \a x is zero or 0 otherwise.
|
||||
*
|
||||
* This function attempts to make the determination in constant time.
|
||||
*/
|
||||
limb_t BigNumberUtil::isZero(const limb_t *x, size_t size)
|
||||
{
|
||||
limb_t word = 0;
|
||||
while (size > 0) {
|
||||
word |= *x++;
|
||||
--size;
|
||||
}
|
||||
return (limb_t)(((((dlimb_t)1) << LIMB_BITS) - word) >> LIMB_BITS);
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_BIGNUMBERUTIL_h
|
||||
#define CRYPTO_BIGNUMBERUTIL_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Define exactly one of these to 1 to set the size of the basic limb type.
|
||||
#if defined(__AVR__) || defined(ESP8266)
|
||||
// 16-bit limbs seem to give the best performance on 8-bit AVR micros.
|
||||
// They also seem to give better performance on ESP8266 as well.
|
||||
#define BIGNUMBER_LIMB_8BIT 0
|
||||
#define BIGNUMBER_LIMB_16BIT 1
|
||||
#define BIGNUMBER_LIMB_32BIT 0
|
||||
#define BIGNUMBER_LIMB_64BIT 0
|
||||
#elif defined(__GNUC__) && __WORDSIZE == 64
|
||||
// 64-bit system with 128-bit double limbs.
|
||||
#define BIGNUMBER_LIMB_8BIT 0
|
||||
#define BIGNUMBER_LIMB_16BIT 0
|
||||
#define BIGNUMBER_LIMB_32BIT 0
|
||||
#define BIGNUMBER_LIMB_64BIT 1
|
||||
#else
|
||||
// On all other platforms, assume 32-bit is best.
|
||||
#define BIGNUMBER_LIMB_8BIT 0
|
||||
#define BIGNUMBER_LIMB_16BIT 0
|
||||
#define BIGNUMBER_LIMB_32BIT 1
|
||||
#define BIGNUMBER_LIMB_64BIT 0
|
||||
#endif
|
||||
|
||||
// Define the limb types to use on this platform.
|
||||
#if BIGNUMBER_LIMB_8BIT
|
||||
typedef uint8_t limb_t;
|
||||
typedef int8_t slimb_t;
|
||||
typedef uint16_t dlimb_t;
|
||||
#elif BIGNUMBER_LIMB_16BIT
|
||||
typedef uint16_t limb_t;
|
||||
typedef int16_t slimb_t;
|
||||
typedef uint32_t dlimb_t;
|
||||
#elif BIGNUMBER_LIMB_32BIT
|
||||
typedef uint32_t limb_t;
|
||||
typedef int32_t slimb_t;
|
||||
typedef uint64_t dlimb_t;
|
||||
#elif BIGNUMBER_LIMB_64BIT
|
||||
typedef uint64_t limb_t;
|
||||
typedef int64_t slimb_t;
|
||||
typedef unsigned __int128 dlimb_t;
|
||||
#else
|
||||
#error "limb_t must be 8, 16, 32, or 64 bits in size"
|
||||
#endif
|
||||
|
||||
class BigNumberUtil
|
||||
{
|
||||
public:
|
||||
static void unpackLE(limb_t *limbs, size_t count,
|
||||
const uint8_t *bytes, size_t len);
|
||||
static void unpackBE(limb_t *limbs, size_t count,
|
||||
const uint8_t *bytes, size_t len);
|
||||
static void packLE(uint8_t *bytes, size_t len,
|
||||
const limb_t *limbs, size_t count);
|
||||
static void packBE(uint8_t *bytes, size_t len,
|
||||
const limb_t *limbs, size_t count);
|
||||
|
||||
static limb_t add(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size);
|
||||
static limb_t sub(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size);
|
||||
static void mul(limb_t *result, const limb_t *x, size_t xcount,
|
||||
const limb_t *y, size_t ycount);
|
||||
static void reduceQuick(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size);
|
||||
|
||||
static limb_t add_P(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size);
|
||||
static limb_t sub_P(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size);
|
||||
static void mul_P(limb_t *result, const limb_t *x, size_t xcount,
|
||||
const limb_t *y, size_t ycount);
|
||||
static void reduceQuick_P(limb_t *result, const limb_t *x,
|
||||
const limb_t *y, size_t size);
|
||||
|
||||
static limb_t isZero(const limb_t *x, size_t size);
|
||||
|
||||
private:
|
||||
// Constructor and destructor are private - cannot instantiate this class.
|
||||
BigNumberUtil() {}
|
||||
~BigNumberUtil() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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 "BlockCipher.h"
|
||||
|
||||
/**
|
||||
* \class BlockCipher BlockCipher.h <BlockCipher.h>
|
||||
* \brief Abstract base class for block ciphers.
|
||||
*
|
||||
* Block ciphers always operate in electronic codebook (ECB) mode.
|
||||
* Higher-level classes such as CFB128 and CTR128 wrap the block cipher to
|
||||
* create more useful classes for encryption and decryption of bulk data.
|
||||
*
|
||||
* References: http://en.wikipedia.org/wiki/Block_cipher,
|
||||
* http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Constructs a block cipher.
|
||||
*/
|
||||
BlockCipher::BlockCipher()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destroys this block cipher object.
|
||||
*
|
||||
* Subclasses are responsible for clearing temporary key schedules
|
||||
* and other buffers so as to avoid leaking sensitive information.
|
||||
*
|
||||
* \sa clear()
|
||||
*/
|
||||
BlockCipher::~BlockCipher()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn size_t BlockCipher::blockSize() const
|
||||
* \brief Size of a single block processed by this cipher, in bytes.
|
||||
*
|
||||
* \return Returns the size of a block in bytes.
|
||||
*
|
||||
* \sa keySize(), encryptBlock()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn size_t BlockCipher::keySize() const
|
||||
* \brief Default size of the key for this block cipher, in bytes.
|
||||
*
|
||||
* This value indicates the default, or recommended, size for the key.
|
||||
*
|
||||
* \sa setKey(), blockSize()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn bool BlockCipher::setKey(const uint8_t *key, size_t len)
|
||||
* \brief Sets the key to use for future encryption and decryption operations.
|
||||
*
|
||||
* \param key The key to use.
|
||||
* \param len The length of the key.
|
||||
* \return Returns false if the key length is not supported, or the key
|
||||
* is somehow "weak" and unusable by this cipher.
|
||||
*
|
||||
* Use clear() or the destructor to remove the key and any other sensitive
|
||||
* data from the object once encryption or decryption is complete.
|
||||
*
|
||||
* \sa keySize(), clear()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void BlockCipher::encryptBlock(uint8_t *output, const uint8_t *input)
|
||||
* \brief Encrypts a single block using this cipher.
|
||||
*
|
||||
* \param output The output buffer to put the ciphertext into.
|
||||
* Must be at least blockSize() bytes in length.
|
||||
* \param input The input buffer to read the plaintext from which is
|
||||
* allowed to overlap with \a output. Must be at least blockSize()
|
||||
* bytes in length.
|
||||
*
|
||||
* \sa decryptBlock(), blockSize()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void BlockCipher::decryptBlock(uint8_t *output, const uint8_t *input)
|
||||
* \brief Decrypts a single block using this cipher.
|
||||
*
|
||||
* \param output The output buffer to put the plaintext into.
|
||||
* Must be at least blockSize() bytes in length.
|
||||
* \param input The input buffer to read the ciphertext from which is
|
||||
* allowed to overlap with \a output. Must be at least blockSize()
|
||||
* bytes in length.
|
||||
*
|
||||
* \sa encryptBlock(), blockSize()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void BlockCipher::clear()
|
||||
* \brief Clears all security-sensitive state from this block cipher.
|
||||
*
|
||||
* Security-sensitive information includes key schedules and any
|
||||
* temporary state that is used by encryptBlock() or decryptBlock()
|
||||
* which is stored in the object itself.
|
||||
*
|
||||
* \sa setKey(), encryptBlock(), decryptBlock()
|
||||
*/
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_BLOCKCIPHER_h
|
||||
#define CRYPTO_BLOCKCIPHER_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
class BlockCipher
|
||||
{
|
||||
public:
|
||||
BlockCipher();
|
||||
virtual ~BlockCipher();
|
||||
|
||||
virtual size_t blockSize() const = 0;
|
||||
virtual size_t keySize() const = 0;
|
||||
|
||||
virtual bool setKey(const uint8_t *key, size_t len) = 0;
|
||||
|
||||
virtual void encryptBlock(uint8_t *output, const uint8_t *input) = 0;
|
||||
virtual void decryptBlock(uint8_t *output, const uint8_t *input) = 0;
|
||||
|
||||
virtual void clear() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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 "Crypto.h"
|
||||
|
||||
/**
|
||||
* \brief Cleans a block of bytes.
|
||||
*
|
||||
* \param dest The destination block to be cleaned.
|
||||
* \param size The size of the destination to be cleaned in bytes.
|
||||
*
|
||||
* Unlike memset(), this function attempts to prevent the compiler
|
||||
* from optimizing away the clear on a memory buffer.
|
||||
*/
|
||||
void clean(void *dest, size_t size)
|
||||
{
|
||||
// Force the use of volatile so that we actually clear the memory.
|
||||
// Otherwise the compiler might optimise the entire contents of this
|
||||
// function away, which will not be secure.
|
||||
volatile uint8_t *d = (volatile uint8_t *)dest;
|
||||
while (size > 0) {
|
||||
*d++ = 0;
|
||||
--size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn void clean(T &var)
|
||||
* \brief Template function that cleans a variable.
|
||||
*
|
||||
* \param var A reference to the variable to clean.
|
||||
*
|
||||
* The variable will be cleared to all-zeroes in a secure manner.
|
||||
* Unlike memset(), this function attempts to prevent the compiler
|
||||
* from optimizing away the variable clear.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Compares two memory blocks for equality.
|
||||
*
|
||||
* \param data1 Points to the first memory block.
|
||||
* \param data2 Points to the second memory block.
|
||||
* \param len The size of the memory blocks in bytes.
|
||||
*
|
||||
* Unlike memcmp(), this function attempts to compare the two memory blocks
|
||||
* in a way that will not reveal the contents in the instruction timing.
|
||||
* In particular, this function will not stop early if a byte is different.
|
||||
* It will instead continue onto the end of the array.
|
||||
*/
|
||||
bool secure_compare(const void *data1, const void *data2, size_t len)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
const uint8_t *d1 = (const uint8_t *)data1;
|
||||
const uint8_t *d2 = (const uint8_t *)data2;
|
||||
while (len > 0) {
|
||||
result |= (*d1++ ^ *d2++);
|
||||
--len;
|
||||
}
|
||||
return (bool)((((uint16_t)0x0100) - result) >> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculates the CRC-8 value over an array in memory.
|
||||
*
|
||||
* \param tag Starting tag to distinguish this calculation.
|
||||
* \param data The data to checksum.
|
||||
* \param size The number of bytes to checksum.
|
||||
* \return The CRC-8 value over the data.
|
||||
*
|
||||
* This function does not provide any real security. It is a simple
|
||||
* check that seed values have been initialized within EEPROM or Flash.
|
||||
* If the CRC-8 check fails, then it is assumed that the EEPROM/Flash
|
||||
* contents are invalid and should be re-initialized.
|
||||
*
|
||||
* Reference: http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html#ch4
|
||||
*/
|
||||
uint8_t crypto_crc8(uint8_t tag, const void *data, unsigned size)
|
||||
{
|
||||
const uint8_t *d = (const uint8_t *)data;
|
||||
uint8_t crc = 0xFF ^ tag;
|
||||
uint8_t bit;
|
||||
while (size > 0) {
|
||||
crc ^= *d++;
|
||||
for (bit = 0; bit < 8; ++bit) {
|
||||
// if (crc & 0x80)
|
||||
// crc = (crc << 1) ^ 0x1D;
|
||||
// else
|
||||
// crc = (crc << 1);
|
||||
uint8_t generator = (uint8_t)((((int8_t)crc) >> 7) & 0x1D);
|
||||
crc = (crc << 1) ^ generator;
|
||||
}
|
||||
--size;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_h
|
||||
#define CRYPTO_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void clean(void *dest, size_t size);
|
||||
|
||||
template <typename T>
|
||||
inline void clean(T &var)
|
||||
{
|
||||
clean(&var, sizeof(T));
|
||||
}
|
||||
|
||||
bool secure_compare(const void *data1, const void *data2, size_t len);
|
||||
|
||||
#if defined(ESP8266)
|
||||
extern "C" void system_soft_wdt_feed(void);
|
||||
#define crypto_feed_watchdog() system_soft_wdt_feed()
|
||||
#else
|
||||
#define crypto_feed_watchdog() do { ; } while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+1610
File diff suppressed because it is too large
Load Diff
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_CURVE25519_h
|
||||
#define CRYPTO_CURVE25519_h
|
||||
|
||||
#include "BigNumberUtil.h"
|
||||
|
||||
class Ed25519;
|
||||
|
||||
class Curve25519
|
||||
{
|
||||
public:
|
||||
static bool eval(uint8_t result[32], const uint8_t s[32], const uint8_t x[32]);
|
||||
|
||||
static void dh1(uint8_t k[32], uint8_t f[32]);
|
||||
static bool dh2(uint8_t k[32], uint8_t f[32]);
|
||||
|
||||
#if defined(TEST_CURVE25519_FIELD_OPS)
|
||||
public:
|
||||
#else
|
||||
private:
|
||||
#endif
|
||||
static uint8_t isWeakPoint(const uint8_t k[32]);
|
||||
|
||||
static void reduce(limb_t *result, limb_t *x, uint8_t size);
|
||||
static limb_t reduceQuick(limb_t *x);
|
||||
|
||||
static void mulNoReduce(limb_t *result, const limb_t *x, const limb_t *y);
|
||||
|
||||
static void mul(limb_t *result, const limb_t *x, const limb_t *y);
|
||||
static void square(limb_t *result, const limb_t *x)
|
||||
{
|
||||
mul(result, x, x);
|
||||
}
|
||||
|
||||
static void mulA24(limb_t *result, const limb_t *x);
|
||||
|
||||
static void mul_P(limb_t *result, const limb_t *x, const limb_t *y);
|
||||
|
||||
static void add(limb_t *result, const limb_t *x, const limb_t *y);
|
||||
static void sub(limb_t *result, const limb_t *x, const limb_t *y);
|
||||
|
||||
static void cswap(limb_t select, limb_t *x, limb_t *y);
|
||||
static void cmove(limb_t select, limb_t *x, const limb_t *y);
|
||||
|
||||
static void pow250(limb_t *result, const limb_t *x);
|
||||
static void recip(limb_t *result, const limb_t *x);
|
||||
static bool sqrt(limb_t *result, const limb_t *x);
|
||||
|
||||
// Constructor and destructor are private - cannot instantiate this class.
|
||||
Curve25519() {}
|
||||
~Curve25519() {}
|
||||
|
||||
friend class Ed25519;
|
||||
};
|
||||
|
||||
#endif
|
||||
+642
@@ -0,0 +1,642 @@
|
||||
/*
|
||||
* 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 "Ed25519.h"
|
||||
#include "Curve25519.h"
|
||||
#include "Crypto.h"
|
||||
#include "RNG.h"
|
||||
#include "utility/LimbUtil.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* \class Ed25519 Ed25519.h <Ed25519.h>
|
||||
* \brief Digital signatures based on the elliptic curve modulo 2^255 - 19.
|
||||
*
|
||||
* The first step in creating a digital signature with Ed25519 is to
|
||||
* generate a key pair:
|
||||
*
|
||||
* \code
|
||||
* uint8_t privateKey[32];
|
||||
* uint8_t publicKey[32];
|
||||
*
|
||||
* Ed25519::generatePrivateKey(privateKey);
|
||||
* Ed25519::derivePublicKey(publicKey, privateKey);
|
||||
* \endcode
|
||||
*
|
||||
* The application can store both the private and public key for later
|
||||
* signing operations. Or it can store just the private key and then
|
||||
* derive the public key at the point where signing is to occur.
|
||||
*
|
||||
* Message signing produces a 64-byte signature as follows:
|
||||
*
|
||||
* \code
|
||||
* uint8_t message[N];
|
||||
* uint8_t signature[64];
|
||||
*
|
||||
* Ed25519::sign(signature, privateKey, publicKey, message, N);
|
||||
* \endcode
|
||||
*
|
||||
* And then to verify the signature:
|
||||
*
|
||||
* \code
|
||||
* if (!Ed25519::verify(signature, publicKey, message, N)) {
|
||||
* // The signature is invalid.
|
||||
* ...
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \note The public functions in this class need a substantial amount of
|
||||
* stack space to store intermediate results while the curve function is
|
||||
* being evaluated. About 1.5k of free stack space is recommended for safety.
|
||||
*
|
||||
* References: https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05
|
||||
*
|
||||
* \sa Curve25519
|
||||
*/
|
||||
|
||||
/** @cond */
|
||||
|
||||
// 37095705934669439343138083508754565189542113879843219016388785533085940283555
|
||||
static limb_t const numD[NUM_LIMBS_256BIT] PROGMEM = {
|
||||
LIMB_PAIR(0x135978A3, 0x75EB4DCA), LIMB_PAIR(0x4141D8AB, 0x00700A4D),
|
||||
LIMB_PAIR(0x7779E898, 0x8CC74079), LIMB_PAIR(0x2B6FFE73, 0x52036CEE)
|
||||
};
|
||||
|
||||
// d * 2
|
||||
static limb_t const numDx2[NUM_LIMBS_256BIT] PROGMEM = {
|
||||
LIMB_PAIR(0x26B2F159, 0xEBD69B94), LIMB_PAIR(0x8283B156, 0x00E0149A),
|
||||
LIMB_PAIR(0xEEF3D130, 0x198E80F2), LIMB_PAIR(0x56DFFCE7, 0x2406D9DC)
|
||||
};
|
||||
|
||||
// Extended homogenous co-ordinates for the base point.
|
||||
static limb_t const numBx[NUM_LIMBS_256BIT] PROGMEM = {
|
||||
LIMB_PAIR(0x8F25D51A, 0xC9562D60), LIMB_PAIR(0x9525A7B2, 0x692CC760),
|
||||
LIMB_PAIR(0xFDD6DC5C, 0xC0A4E231), LIMB_PAIR(0xCD6E53FE, 0x216936D3)
|
||||
};
|
||||
static limb_t const numBy[NUM_LIMBS_256BIT] PROGMEM = {
|
||||
LIMB_PAIR(0x66666658, 0x66666666), LIMB_PAIR(0x66666666, 0x66666666),
|
||||
LIMB_PAIR(0x66666666, 0x66666666), LIMB_PAIR(0x66666666, 0x66666666)
|
||||
};
|
||||
static limb_t const numBz[NUM_LIMBS_256BIT] PROGMEM = {
|
||||
LIMB_PAIR(0x00000001, 0x00000000), LIMB_PAIR(0x00000000, 0x00000000),
|
||||
LIMB_PAIR(0x00000000, 0x00000000), LIMB_PAIR(0x00000000, 0x00000000)
|
||||
};
|
||||
static limb_t const numBt[NUM_LIMBS_256BIT] PROGMEM = {
|
||||
LIMB_PAIR(0xA5B7DDA3, 0x6DDE8AB3), LIMB_PAIR(0x775152F5, 0x20F09F80),
|
||||
LIMB_PAIR(0x64ABE37D, 0x66EA4E8E), LIMB_PAIR(0xD78B7665, 0x67875F0F)
|
||||
};
|
||||
|
||||
// 2^252 + 27742317777372353535851937790883648493
|
||||
static limb_t const numQ[NUM_LIMBS_256BIT] PROGMEM = {
|
||||
LIMB_PAIR(0x5CF5D3ED, 0x5812631A), LIMB_PAIR(0xA2F79CD6, 0x14DEF9DE),
|
||||
LIMB_PAIR(0x00000000, 0x00000000), LIMB_PAIR(0x00000000, 0x10000000)
|
||||
};
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* \brief Signs a message using a specific Ed25519 private key.
|
||||
*
|
||||
* \param signature The signature value.
|
||||
* \param privateKey The private key to use to sign the message.
|
||||
* \param publicKey The public key corresponding to \a privateKey.
|
||||
* \param message Points to the message to be signed.
|
||||
* \param len The length of the \a message to be signed.
|
||||
*
|
||||
* \sa verify(), derivePublicKey()
|
||||
*/
|
||||
void Ed25519::sign(uint8_t signature[64], const uint8_t privateKey[32],
|
||||
const uint8_t publicKey[32], const void *message, size_t len)
|
||||
{
|
||||
SHA512 hash;
|
||||
uint8_t *buf = (uint8_t *)(hash.state.w); // Reuse hash buffer to save memory.
|
||||
limb_t a[NUM_LIMBS_256BIT];
|
||||
limb_t r[NUM_LIMBS_256BIT];
|
||||
limb_t k[NUM_LIMBS_256BIT];
|
||||
limb_t t[NUM_LIMBS_512BIT + 1];
|
||||
Point rB;
|
||||
|
||||
// Derive the secret scalar a and the message prefix from the private key.
|
||||
deriveKeys(&hash, a, privateKey);
|
||||
|
||||
// Hash the prefix and the message to derive r.
|
||||
hash.reset();
|
||||
hash.update(buf + 32, 32);
|
||||
hash.update(message, len);
|
||||
hash.finalize(buf, 0);
|
||||
reduceQFromBuffer(r, buf, t);
|
||||
|
||||
// Encode rB into the first half of the signature buffer as R.
|
||||
mul(rB, r);
|
||||
encodePoint(signature, rB);
|
||||
|
||||
// Hash R, A, and the message to get k.
|
||||
hash.reset();
|
||||
hash.update(signature, 32); // R
|
||||
hash.update(publicKey, 32); // A
|
||||
hash.update(message, len);
|
||||
hash.finalize(buf, 0);
|
||||
reduceQFromBuffer(k, buf, t);
|
||||
|
||||
// Compute s = (r + k * a) mod q.
|
||||
Curve25519::mulNoReduce(t, k, a);
|
||||
t[NUM_LIMBS_512BIT] = 0;
|
||||
reduceQ(t, t);
|
||||
BigNumberUtil::add(t, t, r, NUM_LIMBS_256BIT);
|
||||
BigNumberUtil::reduceQuick_P(t, t, numQ, NUM_LIMBS_256BIT);
|
||||
BigNumberUtil::packLE(signature + 32, 32, t, NUM_LIMBS_256BIT);
|
||||
|
||||
// Clean up.
|
||||
clean(a);
|
||||
clean(r);
|
||||
clean(k);
|
||||
clean(t);
|
||||
clean(rB);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Verifies a signature using a specific Ed25519 public key.
|
||||
*
|
||||
* \param signature The signature value to be verified.
|
||||
* \param publicKey The public key to use to verify the signature.
|
||||
* \param message The message whose signature is to be verified.
|
||||
* \param len The length of the \a message to be verified.
|
||||
*
|
||||
* \return Returns true if the \a signature is valid for \a message;
|
||||
* or false if the \a signature is not valid.
|
||||
*
|
||||
* \sa sign()
|
||||
*/
|
||||
bool Ed25519::verify(const uint8_t signature[64], const uint8_t publicKey[32],
|
||||
const void *message, size_t len)
|
||||
{
|
||||
SHA512 hash;
|
||||
Point A;
|
||||
Point R;
|
||||
Point sB;
|
||||
Point kA;
|
||||
uint8_t *k = (uint8_t *)(hash.state.w); // Reuse hash buffer to save memory.
|
||||
bool result = false;
|
||||
|
||||
// Decode the public key and the R component of the signature.
|
||||
if (decodePoint(A, publicKey) && decodePoint(R, signature)) {
|
||||
// Reconstruct the k value from the signing step.
|
||||
hash.reset();
|
||||
hash.update(signature, 32);
|
||||
hash.update(publicKey, 32);
|
||||
hash.update(message, len);
|
||||
hash.finalize(k, 0);
|
||||
|
||||
// Calculate s * B. The s value is stored temporarily in kA.t.
|
||||
BigNumberUtil::unpackLE(kA.t, NUM_LIMBS_256BIT, signature + 32, 32);
|
||||
mul(sB, kA.t, false);
|
||||
|
||||
// Calculate R + k * A. We don't need sB.t in equal() below,
|
||||
// so we reuse that as a temporary buffer when reducing k.
|
||||
reduceQFromBuffer(sB.t, k, kA.x);
|
||||
mul(kA, sB.t, A, false);
|
||||
add(R, kA);
|
||||
|
||||
// Compare s * B and R + k * A for equality.
|
||||
result = equal(sB, R);
|
||||
}
|
||||
|
||||
// Clean up and exit.
|
||||
clean(A);
|
||||
clean(R);
|
||||
clean(sB);
|
||||
clean(kA);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Generates a private key for Ed25519 signing operations.
|
||||
*
|
||||
* \param privateKey The resulting private key.
|
||||
*
|
||||
* The private key is generated with \link RNGClass::rand() RNG.rand()\endlink.
|
||||
* It is the caller's responsibility to ensure that the global random number
|
||||
* pool has sufficient entropy to generate the 32 bytes of the key safely
|
||||
* before calling this function.
|
||||
*
|
||||
* \sa derivePublicKey()
|
||||
*/
|
||||
void Ed25519::generatePrivateKey(uint8_t privateKey[32])
|
||||
{
|
||||
RNG.rand(privateKey, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Derives the public key from a private key.
|
||||
*
|
||||
* \param publicKey The public key.
|
||||
* \param privateKey The private key.
|
||||
*
|
||||
* \sa generatePrivateKey()
|
||||
*/
|
||||
void Ed25519::derivePublicKey(uint8_t publicKey[32], const uint8_t privateKey[32])
|
||||
{
|
||||
SHA512 hash;
|
||||
limb_t a[NUM_LIMBS_256BIT];
|
||||
Point ptA;
|
||||
|
||||
// Derive the secret scalar a from the private key.
|
||||
deriveKeys(&hash, a, privateKey);
|
||||
|
||||
// Compute the point A = aB and encode it.
|
||||
mul(ptA, a);
|
||||
encodePoint(publicKey, ptA);
|
||||
|
||||
// Clean up and exit.
|
||||
clean(a);
|
||||
clean(ptA);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reduces a number modulo q that was specified in a 512 bit buffer.
|
||||
*
|
||||
* \param result The result array, which must be NUM_LIMBS_256BIT limbs in size.
|
||||
* \param buf The buffer containing the value to reduce in little-endian order.
|
||||
* \param temp A temporary buffer of at least NUM_LIMBS_512BIT + 1 in size.
|
||||
*
|
||||
* \sa reduceQ()
|
||||
*/
|
||||
void Ed25519::reduceQFromBuffer(limb_t *result, const uint8_t buf[64], limb_t *temp)
|
||||
{
|
||||
BigNumberUtil::unpackLE(temp, NUM_LIMBS_512BIT, buf, 64);
|
||||
temp[NUM_LIMBS_512BIT] = 0;
|
||||
reduceQ(result, temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reduces a number modulo q.
|
||||
*
|
||||
* \param result The result array, which must be NUM_LIMBS_256BIT limbs in size.
|
||||
* \param r The value to reduce, which must be NUM_LIMBS_512BIT + 1
|
||||
* limbs in size.
|
||||
*
|
||||
* The \a r array will be modified by this function as a side effect of
|
||||
* the division. It is allowed for \a result to be the same as \a r.
|
||||
*
|
||||
* \sa reduceQFromBuffer()
|
||||
*/
|
||||
void Ed25519::reduceQ(limb_t *result, limb_t *r)
|
||||
{
|
||||
// Algorithm from: http://en.wikipedia.org/wiki/Barrett_reduction
|
||||
//
|
||||
// We assume that r is less than or equal to (q - 1)^2.
|
||||
//
|
||||
// We want to compute result = r mod q. Find the smallest k such
|
||||
// that 2^k > q. In our case, k = 253. Then set m = floor(4^k / q)
|
||||
// and let r = r - q * floor(m * r / 4^k). This will be the result
|
||||
// or it will be at most one subtraction of q away from the result.
|
||||
//
|
||||
// Note: 4^k = 4^253 = 2^506 = 2^512/2^6. We can more easily compute
|
||||
// the result we want if we set m = floor(4^k * 2^6 / q) instead and
|
||||
// then r = r - q * floor(m * r / 2^512). Because the slight extra
|
||||
// precision in m, r is at most two subtractions of q away from the
|
||||
// final result.
|
||||
static limb_t const numM[NUM_LIMBS_256BIT + 1] PROGMEM = {
|
||||
LIMB_PAIR(0x0A2C131B, 0xED9CE5A3), LIMB_PAIR(0x086329A7, 0x2106215D),
|
||||
LIMB_PAIR(0xFFFFFFEB, 0xFFFFFFFF), LIMB_PAIR(0xFFFFFFFF, 0xFFFFFFFF),
|
||||
0x0F
|
||||
};
|
||||
limb_t temp[NUM_LIMBS_512BIT + NUM_LIMBS_256BIT + 1];
|
||||
|
||||
// Multiply r by m.
|
||||
BigNumberUtil::mul_P(temp, r, NUM_LIMBS_512BIT, numM, NUM_LIMBS_256BIT + 1);
|
||||
|
||||
// Multiply (m * r) / 2^512 by q and subtract it from r.
|
||||
// We can ignore the high words of the subtraction result
|
||||
// because they will all turn into zero after the subtraction.
|
||||
BigNumberUtil::mul_P(temp, temp + NUM_LIMBS_512BIT, NUM_LIMBS_256BIT + 1,
|
||||
numQ, NUM_LIMBS_256BIT);
|
||||
BigNumberUtil::sub(r, r, temp, NUM_LIMBS_256BIT);
|
||||
|
||||
// Perform two subtractions of q from the result to reduce it.
|
||||
BigNumberUtil::reduceQuick_P(result, r, numQ, NUM_LIMBS_256BIT);
|
||||
BigNumberUtil::reduceQuick_P(result, result, numQ, NUM_LIMBS_256BIT);
|
||||
|
||||
// Clean up and exit.
|
||||
clean(temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Multiplies a value by a curve point.
|
||||
*
|
||||
* \param result The result of the multiplication.
|
||||
* \param s The value, which must be NUM_LIMBS_256BIT limbs in size.
|
||||
* \param p The curve point, which will be modified by this function.
|
||||
* \param constTime Set to true if the evaluation must be constant-time
|
||||
* because \a s is a secret value.
|
||||
*/
|
||||
void Ed25519::mul(Point &result, const limb_t *s, Point &p, bool constTime)
|
||||
{
|
||||
Point q;
|
||||
limb_t A[NUM_LIMBS_256BIT];
|
||||
limb_t B[NUM_LIMBS_256BIT];
|
||||
limb_t C[NUM_LIMBS_256BIT];
|
||||
limb_t D[NUM_LIMBS_256BIT];
|
||||
limb_t mask, select;
|
||||
uint8_t sposn, t;
|
||||
|
||||
// Initialize the result to (0, 1, 1, 0).
|
||||
memset(&result, 0, sizeof(Point));
|
||||
result.y[0] = 1;
|
||||
result.z[0] = 1;
|
||||
|
||||
// Iterate over the 255 bits of "s" to calculate "s * p".
|
||||
mask = 1;
|
||||
sposn = 0;
|
||||
for (t = 255; t > 0; --t) {
|
||||
// Add p to the result to produce q. The specification refers
|
||||
// to temporary variables A to H. We can dispense with E to H
|
||||
// by using B, D, q.z, and q.t to hold those values temporarily.
|
||||
select = s[sposn] & mask;
|
||||
if (constTime || select) {
|
||||
Curve25519::sub(A, result.y, result.x);
|
||||
Curve25519::sub(C, p.y, p.x);
|
||||
Curve25519::mul(A, A, C);
|
||||
Curve25519::add(B, result.y, result.x);
|
||||
Curve25519::add(C, p.y, p.x);
|
||||
Curve25519::mul(B, B, C);
|
||||
Curve25519::mul(C, result.t, p.t);
|
||||
Curve25519::mul_P(C, C, numDx2);
|
||||
Curve25519::mul(D, result.z, p.z);
|
||||
Curve25519::add(D, D, D);
|
||||
Curve25519::sub(q.t, B, A); // E = B - A
|
||||
Curve25519::sub(q.z, D, C); // F = D - C
|
||||
Curve25519::add(D, D, C); // G = D + C
|
||||
Curve25519::add(B, B, A); // H = B + A
|
||||
if (constTime) {
|
||||
// Put the intermediate value into q.
|
||||
Curve25519::mul(q.x, q.t, q.z); // q.x = E * F
|
||||
Curve25519::mul(q.y, D, B); // q.y = G * H
|
||||
Curve25519::mul(q.z, q.z, D); // q.z = F * G
|
||||
Curve25519::mul(q.t, q.t, B); // q.t = E * H
|
||||
|
||||
// Copy q into the result if the current bit of s is 1.
|
||||
Curve25519::cmove(select, result.x, q.x);
|
||||
Curve25519::cmove(select, result.y, q.y);
|
||||
Curve25519::cmove(select, result.z, q.z);
|
||||
Curve25519::cmove(select, result.t, q.t);
|
||||
} else {
|
||||
// Put the intermediate value directly into the result.
|
||||
Curve25519::mul(result.x, q.t, q.z); // q.x = E * F
|
||||
Curve25519::mul(result.y, D, B); // q.y = G * H
|
||||
Curve25519::mul(result.z, q.z, D); // q.z = F * G
|
||||
Curve25519::mul(result.t, q.t, B); // q.t = E * H
|
||||
}
|
||||
}
|
||||
|
||||
// Double p for the next iteration.
|
||||
Curve25519::sub(A, p.y, p.x);
|
||||
Curve25519::square(A, A);
|
||||
Curve25519::add(B, p.y, p.x);
|
||||
Curve25519::square(B, B);
|
||||
Curve25519::square(C, p.t);
|
||||
Curve25519::mul_P(C, C, numDx2);
|
||||
Curve25519::square(D, p.z);
|
||||
Curve25519::add(D, D, D);
|
||||
Curve25519::sub(p.t, B, A); // E = B - A
|
||||
Curve25519::sub(p.z, D, C); // F = D - C
|
||||
Curve25519::add(D, D, C); // G = D + C
|
||||
Curve25519::add(B, B, A); // H = B + A
|
||||
Curve25519::mul(p.x, p.t, p.z); // p.x = E * F
|
||||
Curve25519::mul(p.y, D, B); // p.y = G * H
|
||||
Curve25519::mul(p.z, p.z, D); // p.z = F * G
|
||||
Curve25519::mul(p.t, p.t, B); // p.t = E * H
|
||||
|
||||
// Move onto the next bit of s from lowest to highest.
|
||||
if (mask != (((limb_t)1) << (LIMB_BITS - 1))) {
|
||||
mask <<= 1;
|
||||
} else {
|
||||
++sposn;
|
||||
mask = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
clean(q);
|
||||
clean(A);
|
||||
clean(B);
|
||||
clean(C);
|
||||
clean(D);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Multiplies a value by the base point of the curve.
|
||||
*
|
||||
* \param result The result of the multiplication.
|
||||
* \param s The value, which must be NUM_LIMBS_256BIT limbs in size.
|
||||
* \param constTime Set to true if the evaluation must be constant-time
|
||||
* because \a s is a secret values.
|
||||
*/
|
||||
void Ed25519::mul(Point &result, const limb_t *s, bool constTime)
|
||||
{
|
||||
Point P;
|
||||
memcpy_P(P.x, numBx, sizeof(P.x));
|
||||
memcpy_P(P.y, numBy, sizeof(P.y));
|
||||
memcpy_P(P.z, numBz, sizeof(P.z));
|
||||
memcpy_P(P.t, numBt, sizeof(P.t));
|
||||
mul(result, s, P, constTime);
|
||||
clean(P);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds two curve points.
|
||||
*
|
||||
* \param p The first point and the result.
|
||||
* \param q The second point.
|
||||
*/
|
||||
void Ed25519::add(Point &p, const Point &q)
|
||||
{
|
||||
limb_t A[NUM_LIMBS_256BIT];
|
||||
limb_t B[NUM_LIMBS_256BIT];
|
||||
limb_t C[NUM_LIMBS_256BIT];
|
||||
limb_t D[NUM_LIMBS_256BIT];
|
||||
|
||||
Curve25519::sub(A, p.y, p.x);
|
||||
Curve25519::sub(C, q.y, q.x);
|
||||
Curve25519::mul(A, A, C);
|
||||
Curve25519::add(B, p.y, p.x);
|
||||
Curve25519::add(C, q.y, q.x);
|
||||
Curve25519::mul(B, B, C);
|
||||
Curve25519::mul(C, p.t, q.t);
|
||||
Curve25519::mul_P(C, C, numDx2);
|
||||
Curve25519::mul(D, p.z, q.z);
|
||||
Curve25519::add(D, D, D);
|
||||
Curve25519::sub(p.t, B, A); // E = B - A
|
||||
Curve25519::sub(p.z, D, C); // F = D - C
|
||||
Curve25519::add(D, D, C); // G = D + C
|
||||
Curve25519::add(B, B, A); // H = B + A
|
||||
Curve25519::mul(p.x, p.t, p.z); // p.x = E * F
|
||||
Curve25519::mul(p.y, D, B); // p.y = G * H
|
||||
Curve25519::mul(p.z, p.z, D); // p.z = F * G
|
||||
Curve25519::mul(p.t, p.t, B); // p.t = E * H
|
||||
|
||||
clean(A);
|
||||
clean(B);
|
||||
clean(C);
|
||||
clean(D);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Determine if two curve points are equal.
|
||||
*
|
||||
* \param p The first curve point.
|
||||
* \param q The second curve point.
|
||||
*
|
||||
* \return Returns true if \a p and \a q are equal; false otherwise.
|
||||
*/
|
||||
bool Ed25519::equal(const Point &p, const Point &q)
|
||||
{
|
||||
limb_t a[NUM_LIMBS_256BIT];
|
||||
limb_t b[NUM_LIMBS_256BIT];
|
||||
bool result = true;
|
||||
|
||||
Curve25519::mul(a, p.x, q.z);
|
||||
Curve25519::mul(b, q.x, p.z);
|
||||
result &= secure_compare(a, b, sizeof(a));
|
||||
|
||||
Curve25519::mul(a, p.y, q.z);
|
||||
Curve25519::mul(b, q.y, p.z);
|
||||
result &= secure_compare(a, b, sizeof(a));
|
||||
|
||||
clean(a);
|
||||
clean(b);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Encodes a curve point into a 32-byte buffer.
|
||||
*
|
||||
* \param buf The buffer to encode into.
|
||||
* \param point The curve point to encode. This value will be modified
|
||||
* the function and effectively destroyed.
|
||||
*
|
||||
* \sa decodePoint()
|
||||
*/
|
||||
void Ed25519::encodePoint(uint8_t *buf, Point &point)
|
||||
{
|
||||
// Convert the homogeneous coordinates into plain (x, y) coordinates:
|
||||
// zinv = z^(-1) mod p
|
||||
// x = x * zinv mod p
|
||||
// y = y * zinv mod p
|
||||
// We don't need the t coordinate, so use that to store zinv temporarily.
|
||||
Curve25519::recip(point.t, point.z);
|
||||
Curve25519::mul(point.x, point.x, point.t);
|
||||
Curve25519::mul(point.y, point.y, point.t);
|
||||
|
||||
// Copy the lowest bit of x to the highest bit of y.
|
||||
point.y[NUM_LIMBS_256BIT - 1] |= (point.x[0] << (LIMB_BITS - 1));
|
||||
|
||||
// Convert y into little-endian in the return buffer.
|
||||
BigNumberUtil::packLE(buf, 32, point.y, NUM_LIMBS_256BIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Decodes a curve point from a 32-byte buffer.
|
||||
*
|
||||
* \param point The curve point that was decoded from the buffer.
|
||||
* \param buf The buffer to decode.
|
||||
*
|
||||
* \return Returns true if the point was decoded or false if the contents
|
||||
* of the buffer do not correspond to a legitimate curve point.
|
||||
*
|
||||
* \note This function is not constant time so it should only be used
|
||||
* on publicly-known values.
|
||||
*/
|
||||
bool Ed25519::decodePoint(Point &point, const uint8_t *buf)
|
||||
{
|
||||
limb_t temp[NUM_LIMBS_256BIT];
|
||||
|
||||
// Convert the input buffer from little-endian into the limbs of y.
|
||||
BigNumberUtil::unpackLE(point.y, NUM_LIMBS_256BIT, buf, 32);
|
||||
|
||||
// The high bit of y is the sign bit for x.
|
||||
limb_t sign = point.y[NUM_LIMBS_256BIT - 1] >> (LIMB_BITS - 1);
|
||||
point.y[NUM_LIMBS_256BIT - 1] &= ~(((limb_t)1) << (LIMB_BITS - 1));
|
||||
|
||||
// Set z to 1.
|
||||
memcpy_P(point.z, numBz, sizeof(point.z));
|
||||
|
||||
// Compute t = (y * y - 1) * modinv(d * y * y + 1).
|
||||
Curve25519::square(point.t, point.y);
|
||||
Curve25519::sub(point.x, point.t, point.z);
|
||||
Curve25519::mul_P(point.t, point.t, numD);
|
||||
Curve25519::add(point.t, point.t, point.z);
|
||||
Curve25519::recip(temp, point.t);
|
||||
Curve25519::mul(point.t, point.x, temp);
|
||||
clean(temp);
|
||||
|
||||
// Check for t = 0.
|
||||
limb_t check = point.t[0];
|
||||
for (uint8_t posn = 1; posn < NUM_LIMBS_256BIT; ++posn)
|
||||
check |= point.t[posn];
|
||||
if (!check) {
|
||||
// If the sign bit is set, then decoding has failed.
|
||||
// Otherwise x is zero and we're done.
|
||||
if (sign)
|
||||
return false;
|
||||
memset(point.x, 0, sizeof(point.x));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Recover x by taking the sqrt of t and flipping the sign if necessary.
|
||||
if (!Curve25519::sqrt(point.x, point.t))
|
||||
return false;
|
||||
if (sign != (point.x[0] & ((limb_t)1))) {
|
||||
// The signs are different so we want the other square root.
|
||||
memset(point.t, 0, sizeof(point.t));
|
||||
Curve25519::sub(point.x, point.t, point.x);
|
||||
}
|
||||
|
||||
// Finally, t = x * y.
|
||||
Curve25519::mul(point.t, point.x, point.y);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Derive key material from a 32-byte private key.
|
||||
*
|
||||
* \param hash SHA512 hash object from the caller for use in this function.
|
||||
* The 64-byte output buffer within this hash object will contain the
|
||||
* hash prefix on exit.
|
||||
* \param a The secret scalar derived from \a privateKey. This must be
|
||||
* NUM_LIMBS_256BIT limbs in size.
|
||||
* \param privateKey The 32-byte private key to derive all other values from.
|
||||
*/
|
||||
void Ed25519::deriveKeys(SHA512 *hash, limb_t *a, const uint8_t privateKey[32])
|
||||
{
|
||||
// Hash the private key to get the "a" scalar and the message prefix.
|
||||
uint8_t *buf = (uint8_t *)(hash->state.w); // Reuse hash buffer to save memory.
|
||||
hash->reset();
|
||||
hash->update(privateKey, 32);
|
||||
hash->finalize(buf, 0);
|
||||
buf[0] &= 0xF8;
|
||||
buf[31] &= 0x7F;
|
||||
buf[31] |= 0x40;
|
||||
|
||||
// Unpack the first half of the hash value into "a".
|
||||
BigNumberUtil::unpackLE(a, NUM_LIMBS_256BIT, buf, 32);
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_ED25519_h
|
||||
#define CRYPTO_ED25519_h
|
||||
|
||||
#include "BigNumberUtil.h"
|
||||
#include "SHA512.h"
|
||||
|
||||
class Ed25519
|
||||
{
|
||||
public:
|
||||
static void sign(uint8_t signature[64], const uint8_t privateKey[32],
|
||||
const uint8_t publicKey[32], const void *message,
|
||||
size_t len);
|
||||
static bool verify(const uint8_t signature[64], const uint8_t publicKey[32],
|
||||
const void *message, size_t len);
|
||||
|
||||
static void generatePrivateKey(uint8_t privateKey[32]);
|
||||
static void derivePublicKey(uint8_t publicKey[32], const uint8_t privateKey[32]);
|
||||
|
||||
private:
|
||||
// Constructor and destructor are private - cannot instantiate this class.
|
||||
Ed25519();
|
||||
~Ed25519();
|
||||
|
||||
// Curve point represented in extended homogeneous coordinates.
|
||||
struct Point
|
||||
{
|
||||
limb_t x[32 / sizeof(limb_t)];
|
||||
limb_t y[32 / sizeof(limb_t)];
|
||||
limb_t z[32 / sizeof(limb_t)];
|
||||
limb_t t[32 / sizeof(limb_t)];
|
||||
};
|
||||
|
||||
static void reduceQFromBuffer(limb_t *result, const uint8_t buf[64], limb_t *temp);
|
||||
static void reduceQ(limb_t *result, limb_t *r);
|
||||
|
||||
static void mul(Point &result, const limb_t *s, Point &p, bool constTime = true);
|
||||
static void mul(Point &result, const limb_t *s, bool constTime = true);
|
||||
|
||||
static void add(Point &p, const Point &q);
|
||||
|
||||
static bool equal(const Point &p, const Point &q);
|
||||
|
||||
static void encodePoint(uint8_t *buf, Point &point);
|
||||
static bool decodePoint(Point &point, const uint8_t *buf);
|
||||
|
||||
static void deriveKeys(SHA512 *hash, limb_t *a, const uint8_t privateKey[32]);
|
||||
};
|
||||
|
||||
#endif
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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 "Hash.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* \class Hash Hash.h <Hash.h>
|
||||
* \brief Abstract base class for cryptographic hash algorithms.
|
||||
*
|
||||
* \sa SHA224, SHA256, SHA384, SHA3_256, BLAKE2s
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Constructs a new hash object.
|
||||
*/
|
||||
Hash::Hash()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destroys this hash object.
|
||||
*
|
||||
* \note Subclasses are responsible for clearing any sensitive data
|
||||
* that remains in the hash object when it is destroyed.
|
||||
*
|
||||
* \sa clear()
|
||||
*/
|
||||
Hash::~Hash()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn size_t Hash::hashSize() const
|
||||
* \brief Size of the hash result from finalize().
|
||||
*
|
||||
* \sa finalize(), blockSize()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn size_t Hash::blockSize() const
|
||||
* \brief Size of the internal block used by the hash algorithm.
|
||||
*
|
||||
* \sa update(), hashSize()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void Hash::reset()
|
||||
* \brief Resets the hash ready for a new hashing process.
|
||||
*
|
||||
* \sa update(), finalize(), resetHMAC()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void Hash::update(const void *data, size_t len)
|
||||
* \brief Updates the hash with more data.
|
||||
*
|
||||
* \param data Data to be hashed.
|
||||
* \param len Number of bytes of data to be hashed.
|
||||
*
|
||||
* If finalize() has already been called, then the behavior of update() will
|
||||
* be undefined. Call reset() first to start a new hashing process.
|
||||
*
|
||||
* \sa reset(), finalize()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void Hash::finalize(void *hash, size_t len)
|
||||
* \brief Finalizes the hashing process and returns the hash.
|
||||
*
|
||||
* \param hash The buffer to return the hash value in.
|
||||
* \param len The length of the \a hash buffer, normally hashSize().
|
||||
*
|
||||
* If \a len is less than hashSize(), then the hash value will be
|
||||
* truncated to the first \a len bytes. If \a len is greater than
|
||||
* hashSize(), then the remaining bytes will left unchanged.
|
||||
*
|
||||
* If finalize() is called again, then the returned \a hash value is
|
||||
* undefined. Call reset() first to start a new hashing process.
|
||||
*
|
||||
* \sa reset(), update(), finalizeHMAC()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void Hash::clear()
|
||||
* \brief Clears the hash state, removing all sensitive data, and then
|
||||
* resets the hash ready for a new hashing process.
|
||||
*
|
||||
* \sa reset()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void Hash::resetHMAC(const void *key, size_t keyLen)
|
||||
* \brief Resets the hash ready for a new HMAC hashing process.
|
||||
*
|
||||
* \param key Points to the HMAC key for the hashing process.
|
||||
* \param keyLen Size of the HMAC \a key in bytes.
|
||||
*
|
||||
* The following example computes a HMAC over a series of data blocks
|
||||
* with a specific key:
|
||||
*
|
||||
* \code
|
||||
* hash.resetHMAC(key, sizeof(key));
|
||||
* hash.update(data1, sizeof(data1));
|
||||
* hash.update(data2, sizeof(data2));
|
||||
* ...
|
||||
* hash.update(dataN, sizeof(dataN));
|
||||
* hash.finalizeHMAC(key, sizeof(key), hmac, sizeof(hmac));
|
||||
* \endcode
|
||||
*
|
||||
* The same key must be passed to both resetHMAC() and finalizeHMAC().
|
||||
*
|
||||
* \sa finalizeHMAC(), reset()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void Hash::finalizeHMAC(const void *key, size_t keyLen, void *hash, size_t hashLen)
|
||||
* \brief Finalizes the HMAC hashing process and returns the hash.
|
||||
*
|
||||
* \param key Points to the HMAC key for the hashing process. The contents
|
||||
* of this array must be identical to the value passed to resetHMAC().
|
||||
* \param keyLen Size of the HMAC \a key in bytes.
|
||||
* \param hash The buffer to return the hash value in.
|
||||
* \param hashLen The length of the \a hash buffer, normally hashSize().
|
||||
*
|
||||
* \sa resetHMAC(), finalize()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Formats a HMAC key into a block.
|
||||
*
|
||||
* \param block The block to format the key into. Must be at least
|
||||
* blockSize() bytes in length.
|
||||
* \param key Points to the HMAC key for the hashing process.
|
||||
* \param len Length of the HMAC \a key in bytes.
|
||||
* \param pad Inner (0x36) or outer (0x5C) padding value to XOR with
|
||||
* the formatted HMAC key.
|
||||
*
|
||||
* This function is intended to help subclasses implement resetHMAC() and
|
||||
* finalizeHMAC() by directly formatting the HMAC key into the subclass's
|
||||
* internal block buffer and resetting the hash.
|
||||
*/
|
||||
void Hash::formatHMACKey(void *block, const void *key, size_t len, uint8_t pad)
|
||||
{
|
||||
size_t size = blockSize();
|
||||
reset();
|
||||
if (len <= size) {
|
||||
memcpy(block, key, len);
|
||||
} else {
|
||||
update(key, len);
|
||||
len = hashSize();
|
||||
finalize(block, len);
|
||||
reset();
|
||||
}
|
||||
uint8_t *b = (uint8_t *)block;
|
||||
memset(b + len, pad, size - len);
|
||||
while (len > 0) {
|
||||
*b++ ^= pad;
|
||||
--len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn void hmac<T>(void *out, size_t outLen, const void *key, size_t keyLen, const void *data, size_t dataLen)
|
||||
* \brief All-in-one convenience function for computing HMAC values.
|
||||
*
|
||||
* \param out Points to the buffer to receive the output HMAC value.
|
||||
* \param outLen Length of the buffer to receive the output HMAC value.
|
||||
* \param key Points to the HMAC key for the hashing process.
|
||||
* \param keyLen Length of the HMAC \a key in bytes.
|
||||
* \param data Points to the data to hash under the HMAC \a key.
|
||||
* \param dataLen Length of the input \a data in bytes.
|
||||
*
|
||||
* This is a convenience function for computing a HMAC value over a block
|
||||
* of input data under a given key. The template argument T must be the
|
||||
* name of a class that inherits from Hash. The following example
|
||||
* computes a HMAC value using the SHA256 hash algorithm:
|
||||
*
|
||||
* \code
|
||||
* uint8_t out[SHA256::HASH_SIZE];
|
||||
* hmac<SHA256>(out, sizeof(out), key, keyLen, data, dataLen);
|
||||
* \endcode
|
||||
*/
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_HASH_h
|
||||
#define CRYPTO_HASH_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
class Hash
|
||||
{
|
||||
public:
|
||||
Hash();
|
||||
virtual ~Hash();
|
||||
|
||||
virtual size_t hashSize() const = 0;
|
||||
virtual size_t blockSize() const = 0;
|
||||
|
||||
virtual void reset() = 0;
|
||||
virtual void update(const void *data, size_t len) = 0;
|
||||
virtual void finalize(void *hash, size_t len) = 0;
|
||||
|
||||
virtual void clear() = 0;
|
||||
|
||||
virtual void resetHMAC(const void *key, size_t keyLen) = 0;
|
||||
virtual void finalizeHMAC(const void *key, size_t keyLen, void *hash, size_t hashLen) = 0;
|
||||
|
||||
protected:
|
||||
void formatHMACKey(void *block, const void *key, size_t len, uint8_t pad);
|
||||
};
|
||||
|
||||
template <typename T> void hmac
|
||||
(void *out, size_t outLen, const void *key, size_t keyLen,
|
||||
const void *data, size_t dataLen)
|
||||
{
|
||||
T context;
|
||||
context.resetHMAC(key, keyLen);
|
||||
context.update(data, dataLen);
|
||||
context.finalizeHMAC(key, keyLen, out, outLen);
|
||||
}
|
||||
|
||||
#endif
|
||||
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_RNG_h
|
||||
#define CRYPTO_RNG_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
class NoiseSource;
|
||||
|
||||
class RNGClass
|
||||
{
|
||||
public:
|
||||
RNGClass();
|
||||
~RNGClass();
|
||||
|
||||
void begin(const char *tag);
|
||||
void addNoiseSource(NoiseSource &source);
|
||||
|
||||
void setAutoSaveTime(uint16_t minutes);
|
||||
|
||||
void rand(uint8_t *data, size_t len);
|
||||
bool available(size_t len) const;
|
||||
|
||||
void stir(const uint8_t *data, size_t len, unsigned int credit = 0);
|
||||
|
||||
void save();
|
||||
|
||||
void loop();
|
||||
|
||||
void destroy();
|
||||
|
||||
static const int SEED_SIZE = 48;
|
||||
|
||||
private:
|
||||
uint32_t block[16];
|
||||
uint32_t stream[16];
|
||||
uint16_t credits : 13;
|
||||
uint16_t firstSave : 1;
|
||||
uint16_t initialized : 1;
|
||||
uint16_t trngPending : 1;
|
||||
unsigned long timer;
|
||||
unsigned long timeout;
|
||||
NoiseSource *noiseSources[4];
|
||||
uint8_t count;
|
||||
uint8_t trngPosn;
|
||||
|
||||
void rekey();
|
||||
void mixTRNG();
|
||||
};
|
||||
|
||||
extern RNGClass RNG;
|
||||
|
||||
#endif
|
||||
+269
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* 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 "SHA256.h"
|
||||
#include "Crypto.h"
|
||||
#include "utility/RotateUtil.h"
|
||||
#include "utility/EndianUtil.h"
|
||||
#include "utility/ProgMemUtil.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* \class SHA256 SHA256.h <SHA256.h>
|
||||
* \brief SHA-256 hash algorithm.
|
||||
*
|
||||
* Reference: http://en.wikipedia.org/wiki/SHA-2
|
||||
*
|
||||
* \sa SHA224, SHA384, SHA512, SHA3_256, BLAKE2s
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var SHA256::HASH_SIZE
|
||||
* \brief Constant for the size of the hash output of SHA256.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var SHA256::BLOCK_SIZE
|
||||
* \brief Constant for the block size of SHA256.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Constructs a SHA-256 hash object.
|
||||
*/
|
||||
SHA256::SHA256()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destroys this SHA-256 hash object after clearing
|
||||
* sensitive information.
|
||||
*/
|
||||
SHA256::~SHA256()
|
||||
{
|
||||
clean(state);
|
||||
}
|
||||
|
||||
size_t SHA256::hashSize() const
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
size_t SHA256::blockSize() const
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
|
||||
void SHA256::reset()
|
||||
{
|
||||
state.h[0] = 0x6a09e667;
|
||||
state.h[1] = 0xbb67ae85;
|
||||
state.h[2] = 0x3c6ef372;
|
||||
state.h[3] = 0xa54ff53a,
|
||||
state.h[4] = 0x510e527f;
|
||||
state.h[5] = 0x9b05688c;
|
||||
state.h[6] = 0x1f83d9ab;
|
||||
state.h[7] = 0x5be0cd19;
|
||||
state.chunkSize = 0;
|
||||
state.length = 0;
|
||||
}
|
||||
|
||||
void SHA256::update(const void *data, size_t len)
|
||||
{
|
||||
// Update the total length (in bits, not bytes).
|
||||
state.length += ((uint64_t)len) << 3;
|
||||
|
||||
// Break the input up into 512-bit chunks and process each in turn.
|
||||
const uint8_t *d = (const uint8_t *)data;
|
||||
while (len > 0) {
|
||||
uint8_t size = 64 - state.chunkSize;
|
||||
if (size > len)
|
||||
size = len;
|
||||
memcpy(((uint8_t *)state.w) + state.chunkSize, d, size);
|
||||
state.chunkSize += size;
|
||||
len -= size;
|
||||
d += size;
|
||||
if (state.chunkSize == 64) {
|
||||
processChunk();
|
||||
state.chunkSize = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHA256::finalize(void *hash, size_t len)
|
||||
{
|
||||
// Pad the last chunk. We may need two padding chunks if there
|
||||
// isn't enough room in the first for the padding and length.
|
||||
uint8_t *wbytes = (uint8_t *)state.w;
|
||||
if (state.chunkSize <= (64 - 9)) {
|
||||
wbytes[state.chunkSize] = 0x80;
|
||||
memset(wbytes + state.chunkSize + 1, 0x00, 64 - 8 - (state.chunkSize + 1));
|
||||
state.w[14] = htobe32((uint32_t)(state.length >> 32));
|
||||
state.w[15] = htobe32((uint32_t)state.length);
|
||||
processChunk();
|
||||
} else {
|
||||
wbytes[state.chunkSize] = 0x80;
|
||||
memset(wbytes + state.chunkSize + 1, 0x00, 64 - (state.chunkSize + 1));
|
||||
processChunk();
|
||||
memset(wbytes, 0x00, 64 - 8);
|
||||
state.w[14] = htobe32((uint32_t)(state.length >> 32));
|
||||
state.w[15] = htobe32((uint32_t)state.length);
|
||||
processChunk();
|
||||
}
|
||||
|
||||
// Convert the result into big endian and return it.
|
||||
for (uint8_t posn = 0; posn < 8; ++posn)
|
||||
state.w[posn] = htobe32(state.h[posn]);
|
||||
|
||||
// Copy the hash to the caller's return buffer.
|
||||
size_t maxHashSize = hashSize();
|
||||
if (len > maxHashSize)
|
||||
len = maxHashSize;
|
||||
memcpy(hash, state.w, len);
|
||||
}
|
||||
|
||||
void SHA256::clear()
|
||||
{
|
||||
clean(state);
|
||||
reset();
|
||||
}
|
||||
|
||||
void SHA256::resetHMAC(const void *key, size_t keyLen)
|
||||
{
|
||||
formatHMACKey(state.w, key, keyLen, 0x36);
|
||||
state.length += 64 * 8;
|
||||
processChunk();
|
||||
}
|
||||
|
||||
void SHA256::finalizeHMAC(const void *key, size_t keyLen, void *hash, size_t hashLen)
|
||||
{
|
||||
uint8_t temp[32];
|
||||
finalize(temp, sizeof(temp));
|
||||
formatHMACKey(state.w, key, keyLen, 0x5C);
|
||||
state.length += 64 * 8;
|
||||
processChunk();
|
||||
update(temp, hashSize());
|
||||
finalize(hash, hashLen);
|
||||
clean(temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Processes a single 512-bit chunk with the core SHA-256 algorithm.
|
||||
*
|
||||
* Reference: http://en.wikipedia.org/wiki/SHA-2
|
||||
*/
|
||||
void SHA256::processChunk()
|
||||
{
|
||||
// Round constants for SHA-256.
|
||||
static uint32_t const k[64] PROGMEM = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
// Convert the first 16 words from big endian to host byte order.
|
||||
uint8_t index;
|
||||
for (index = 0; index < 16; ++index)
|
||||
state.w[index] = be32toh(state.w[index]);
|
||||
|
||||
// Initialise working variables to the current hash value.
|
||||
uint32_t a = state.h[0];
|
||||
uint32_t b = state.h[1];
|
||||
uint32_t c = state.h[2];
|
||||
uint32_t d = state.h[3];
|
||||
uint32_t e = state.h[4];
|
||||
uint32_t f = state.h[5];
|
||||
uint32_t g = state.h[6];
|
||||
uint32_t h = state.h[7];
|
||||
|
||||
// Perform the first 16 rounds of the compression function main loop.
|
||||
uint32_t temp1, temp2;
|
||||
for (index = 0; index < 16; ++index) {
|
||||
temp1 = h + pgm_read_dword(k + index) + state.w[index] +
|
||||
(rightRotate6(e) ^ rightRotate11(e) ^ rightRotate25(e)) +
|
||||
((e & f) ^ ((~e) & g));
|
||||
temp2 = (rightRotate2(a) ^ rightRotate13(a) ^ rightRotate22(a)) +
|
||||
((a & b) ^ (a & c) ^ (b & c));
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + temp1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = temp1 + temp2;
|
||||
}
|
||||
|
||||
// Perform the 48 remaining rounds. We expand the first 16 words to
|
||||
// 64 in-place in the "w" array. This saves 192 bytes of memory
|
||||
// that would have otherwise need to be allocated to the "w" array.
|
||||
for (; index < 64; ++index) {
|
||||
// Expand the next word.
|
||||
temp1 = state.w[(index - 15) & 0x0F];
|
||||
temp2 = state.w[(index - 2) & 0x0F];
|
||||
temp1 = state.w[index & 0x0F] =
|
||||
state.w[(index - 16) & 0x0F] + state.w[(index - 7) & 0x0F] +
|
||||
(rightRotate7(temp1) ^ rightRotate18(temp1) ^ (temp1 >> 3)) +
|
||||
(rightRotate17(temp2) ^ rightRotate19(temp2) ^ (temp2 >> 10));
|
||||
|
||||
// Perform the round.
|
||||
temp1 = h + pgm_read_dword(k + index) + temp1 +
|
||||
(rightRotate6(e) ^ rightRotate11(e) ^ rightRotate25(e)) +
|
||||
((e & f) ^ ((~e) & g));
|
||||
temp2 = (rightRotate2(a) ^ rightRotate13(a) ^ rightRotate22(a)) +
|
||||
((a & b) ^ (a & c) ^ (b & c));
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + temp1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = temp1 + temp2;
|
||||
}
|
||||
|
||||
// Add the compressed chunk to the current hash value.
|
||||
state.h[0] += a;
|
||||
state.h[1] += b;
|
||||
state.h[2] += c;
|
||||
state.h[3] += d;
|
||||
state.h[4] += e;
|
||||
state.h[5] += f;
|
||||
state.h[6] += g;
|
||||
state.h[7] += h;
|
||||
|
||||
// Attempt to clean up the stack.
|
||||
a = b = c = d = e = f = g = h = temp1 = temp2 = 0;
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_SHA256_h
|
||||
#define CRYPTO_SHA256_h
|
||||
|
||||
#include "Hash.h"
|
||||
|
||||
class SHA256 : public Hash
|
||||
{
|
||||
public:
|
||||
SHA256();
|
||||
virtual ~SHA256();
|
||||
|
||||
size_t hashSize() const;
|
||||
size_t blockSize() const;
|
||||
|
||||
void reset();
|
||||
void update(const void *data, size_t len);
|
||||
void finalize(void *hash, size_t len);
|
||||
|
||||
void clear();
|
||||
|
||||
void resetHMAC(const void *key, size_t keyLen);
|
||||
void finalizeHMAC(const void *key, size_t keyLen, void *hash, size_t hashLen);
|
||||
|
||||
static const size_t HASH_SIZE = 32;
|
||||
static const size_t BLOCK_SIZE = 64;
|
||||
|
||||
protected:
|
||||
struct {
|
||||
uint32_t h[8];
|
||||
uint32_t w[16];
|
||||
uint64_t length;
|
||||
uint8_t chunkSize;
|
||||
} state;
|
||||
|
||||
void processChunk();
|
||||
};
|
||||
|
||||
#endif
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* 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 "SHA512.h"
|
||||
#include "Crypto.h"
|
||||
#include "utility/RotateUtil.h"
|
||||
#include "utility/EndianUtil.h"
|
||||
#include "utility/ProgMemUtil.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* \class SHA512 SHA512.h <SHA512.h>
|
||||
* \brief SHA-512 hash algorithm.
|
||||
*
|
||||
* Reference: http://en.wikipedia.org/wiki/SHA-2
|
||||
*
|
||||
* \sa SHA224, SHA256, SHA3_512, BLAKE2b
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var SHA512::HASH_SIZE
|
||||
* \brief Constant for the size of the hash output of SHA512.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var SHA512::BLOCK_SIZE
|
||||
* \brief Constant for the block size of SHA512.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Constructs a SHA-512 hash object.
|
||||
*/
|
||||
SHA512::SHA512()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destroys this SHA-512 hash object after clearing
|
||||
* sensitive information.
|
||||
*/
|
||||
SHA512::~SHA512()
|
||||
{
|
||||
clean(state);
|
||||
}
|
||||
|
||||
size_t SHA512::hashSize() const
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
|
||||
size_t SHA512::blockSize() const
|
||||
{
|
||||
return 128;
|
||||
}
|
||||
|
||||
void SHA512::reset()
|
||||
{
|
||||
static uint64_t const hashStart[8] PROGMEM = {
|
||||
0x6A09E667F3BCC908ULL, 0xBB67AE8584CAA73BULL, 0x3C6EF372FE94F82BULL,
|
||||
0xA54FF53A5F1D36F1ULL, 0x510E527FADE682D1ULL, 0x9B05688C2B3E6C1FULL,
|
||||
0x1F83D9ABFB41BD6BULL, 0x5BE0CD19137E2179ULL
|
||||
};
|
||||
memcpy_P(state.h, hashStart, sizeof(hashStart));
|
||||
state.chunkSize = 0;
|
||||
state.lengthLow = 0;
|
||||
state.lengthHigh = 0;
|
||||
}
|
||||
|
||||
void SHA512::update(const void *data, size_t len)
|
||||
{
|
||||
// Update the total length in bits, not bytes.
|
||||
uint64_t temp = state.lengthLow;
|
||||
state.lengthLow += (((uint64_t)len) << 3);
|
||||
state.lengthHigh += (((uint64_t)len) >> 61);
|
||||
if (state.lengthLow < temp)
|
||||
++state.lengthHigh;
|
||||
|
||||
// Break the input up into 1024-bit chunks and process each in turn.
|
||||
const uint8_t *d = (const uint8_t *)data;
|
||||
while (len > 0) {
|
||||
uint8_t size = 128 - state.chunkSize;
|
||||
if (size > len)
|
||||
size = len;
|
||||
memcpy(((uint8_t *)state.w) + state.chunkSize, d, size);
|
||||
state.chunkSize += size;
|
||||
len -= size;
|
||||
d += size;
|
||||
if (state.chunkSize == 128) {
|
||||
processChunk();
|
||||
state.chunkSize = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHA512::finalize(void *hash, size_t len)
|
||||
{
|
||||
// Pad the last chunk. We may need two padding chunks if there
|
||||
// isn't enough room in the first for the padding and length.
|
||||
uint8_t *wbytes = (uint8_t *)state.w;
|
||||
if (state.chunkSize <= (128 - 17)) {
|
||||
wbytes[state.chunkSize] = 0x80;
|
||||
memset(wbytes + state.chunkSize + 1, 0x00, 128 - 16 - (state.chunkSize + 1));
|
||||
state.w[14] = htobe64(state.lengthHigh);
|
||||
state.w[15] = htobe64(state.lengthLow);
|
||||
processChunk();
|
||||
} else {
|
||||
wbytes[state.chunkSize] = 0x80;
|
||||
memset(wbytes + state.chunkSize + 1, 0x00, 128 - (state.chunkSize + 1));
|
||||
processChunk();
|
||||
memset(wbytes, 0x00, 128 - 16);
|
||||
state.w[14] = htobe64(state.lengthHigh);
|
||||
state.w[15] = htobe64(state.lengthLow);
|
||||
processChunk();
|
||||
}
|
||||
|
||||
// Convert the result into big endian and return it.
|
||||
for (uint8_t posn = 0; posn < 8; ++posn)
|
||||
state.w[posn] = htobe64(state.h[posn]);
|
||||
|
||||
// Copy the hash to the caller's return buffer.
|
||||
size_t maxHashSize = hashSize();
|
||||
if (len > maxHashSize)
|
||||
len = maxHashSize;
|
||||
memcpy(hash, state.w, len);
|
||||
}
|
||||
|
||||
void SHA512::clear()
|
||||
{
|
||||
clean(state);
|
||||
reset();
|
||||
}
|
||||
|
||||
void SHA512::resetHMAC(const void *key, size_t keyLen)
|
||||
{
|
||||
formatHMACKey(state.w, key, keyLen, 0x36);
|
||||
state.lengthLow += 128 * 8;
|
||||
processChunk();
|
||||
}
|
||||
|
||||
void SHA512::finalizeHMAC(const void *key, size_t keyLen, void *hash, size_t hashLen)
|
||||
{
|
||||
uint8_t temp[64];
|
||||
finalize(temp, sizeof(temp));
|
||||
formatHMACKey(state.w, key, keyLen, 0x5C);
|
||||
state.lengthLow += 128 * 8;
|
||||
processChunk();
|
||||
update(temp, hashSize());
|
||||
finalize(hash, hashLen);
|
||||
clean(temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Processes a single 1024-bit chunk with the core SHA-512 algorithm.
|
||||
*
|
||||
* Reference: http://en.wikipedia.org/wiki/SHA-2
|
||||
*/
|
||||
void SHA512::processChunk()
|
||||
{
|
||||
// Round constants for SHA-512.
|
||||
static uint64_t const k[80] PROGMEM = {
|
||||
0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL, 0xB5C0FBCFEC4D3B2FULL,
|
||||
0xE9B5DBA58189DBBCULL, 0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL,
|
||||
0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL, 0xD807AA98A3030242ULL,
|
||||
0x12835B0145706FBEULL, 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
|
||||
0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL, 0x9BDC06A725C71235ULL,
|
||||
0xC19BF174CF692694ULL, 0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL,
|
||||
0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL, 0x2DE92C6F592B0275ULL,
|
||||
0x4A7484AA6EA6E483ULL, 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
|
||||
0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL, 0xB00327C898FB213FULL,
|
||||
0xBF597FC7BEEF0EE4ULL, 0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL,
|
||||
0x06CA6351E003826FULL, 0x142929670A0E6E70ULL, 0x27B70A8546D22FFCULL,
|
||||
0x2E1B21385C26C926ULL, 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
|
||||
0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL, 0x81C2C92E47EDAEE6ULL,
|
||||
0x92722C851482353BULL, 0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL,
|
||||
0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL, 0xD192E819D6EF5218ULL,
|
||||
0xD69906245565A910ULL, 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
|
||||
0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL, 0x2748774CDF8EEB99ULL,
|
||||
0x34B0BCB5E19B48A8ULL, 0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL,
|
||||
0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL, 0x748F82EE5DEFB2FCULL,
|
||||
0x78A5636F43172F60ULL, 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
|
||||
0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL, 0xBEF9A3F7B2C67915ULL,
|
||||
0xC67178F2E372532BULL, 0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL,
|
||||
0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL, 0x06F067AA72176FBAULL,
|
||||
0x0A637DC5A2C898A6ULL, 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
|
||||
0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL, 0x3C9EBE0A15C9BEBCULL,
|
||||
0x431D67C49C100D4CULL, 0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL,
|
||||
0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL
|
||||
};
|
||||
|
||||
// Convert the first 16 words from big endian to host byte order.
|
||||
uint8_t index;
|
||||
for (index = 0; index < 16; ++index)
|
||||
state.w[index] = be64toh(state.w[index]);
|
||||
|
||||
// Initialise working variables to the current hash value.
|
||||
uint64_t a = state.h[0];
|
||||
uint64_t b = state.h[1];
|
||||
uint64_t c = state.h[2];
|
||||
uint64_t d = state.h[3];
|
||||
uint64_t e = state.h[4];
|
||||
uint64_t f = state.h[5];
|
||||
uint64_t g = state.h[6];
|
||||
uint64_t h = state.h[7];
|
||||
|
||||
// Perform the first 16 rounds of the compression function main loop.
|
||||
uint64_t temp1, temp2;
|
||||
for (index = 0; index < 16; ++index) {
|
||||
temp1 = h + pgm_read_qword(k + index) + state.w[index] +
|
||||
(rightRotate14_64(e) ^ rightRotate18_64(e) ^
|
||||
rightRotate41_64(e)) + ((e & f) ^ ((~e) & g));
|
||||
temp2 = (rightRotate28_64(a) ^ rightRotate34_64(a) ^
|
||||
rightRotate39_64(a)) + ((a & b) ^ (a & c) ^ (b & c));
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + temp1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = temp1 + temp2;
|
||||
}
|
||||
|
||||
// Perform the 64 remaining rounds. We expand the first 16 words to
|
||||
// 80 in-place in the "w" array. This saves 512 bytes of memory
|
||||
// that would have otherwise need to be allocated to the "w" array.
|
||||
for (; index < 80; ++index) {
|
||||
// Expand the next word.
|
||||
temp1 = state.w[(index - 15) & 0x0F];
|
||||
temp2 = state.w[(index - 2) & 0x0F];
|
||||
temp1 = state.w[index & 0x0F] =
|
||||
state.w[(index - 16) & 0x0F] + state.w[(index - 7) & 0x0F] +
|
||||
(rightRotate1_64(temp1) ^ rightRotate8_64(temp1) ^
|
||||
(temp1 >> 7)) +
|
||||
(rightRotate19_64(temp2) ^ rightRotate61_64(temp2) ^
|
||||
(temp2 >> 6));
|
||||
|
||||
// Perform the round.
|
||||
temp1 = h + pgm_read_qword(k + index) + temp1 +
|
||||
(rightRotate14_64(e) ^ rightRotate18_64(e) ^
|
||||
rightRotate41_64(e)) + ((e & f) ^ ((~e) & g));
|
||||
temp2 = (rightRotate28_64(a) ^ rightRotate34_64(a) ^
|
||||
rightRotate39_64(a)) + ((a & b) ^ (a & c) ^ (b & c));
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + temp1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = temp1 + temp2;
|
||||
}
|
||||
|
||||
// Add the compressed chunk to the current hash value.
|
||||
state.h[0] += a;
|
||||
state.h[1] += b;
|
||||
state.h[2] += c;
|
||||
state.h[3] += d;
|
||||
state.h[4] += e;
|
||||
state.h[5] += f;
|
||||
state.h[6] += g;
|
||||
state.h[7] += h;
|
||||
|
||||
// Attempt to clean up the stack.
|
||||
a = b = c = d = e = f = g = h = temp1 = temp2 = 0;
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_SHA512_h
|
||||
#define CRYPTO_SHA512_h
|
||||
|
||||
#include "Hash.h"
|
||||
|
||||
class Ed25519;
|
||||
|
||||
class SHA512 : public Hash
|
||||
{
|
||||
public:
|
||||
SHA512();
|
||||
virtual ~SHA512();
|
||||
|
||||
size_t hashSize() const;
|
||||
size_t blockSize() const;
|
||||
|
||||
void reset();
|
||||
void update(const void *data, size_t len);
|
||||
void finalize(void *hash, size_t len);
|
||||
|
||||
void clear();
|
||||
|
||||
void resetHMAC(const void *key, size_t keyLen);
|
||||
void finalizeHMAC(const void *key, size_t keyLen, void *hash, size_t hashLen);
|
||||
|
||||
static const size_t HASH_SIZE = 64;
|
||||
static const size_t BLOCK_SIZE = 128;
|
||||
|
||||
protected:
|
||||
struct {
|
||||
uint64_t h[8];
|
||||
uint64_t w[16];
|
||||
uint64_t lengthLow;
|
||||
uint64_t lengthHigh;
|
||||
uint8_t chunkSize;
|
||||
} state;
|
||||
|
||||
void processChunk();
|
||||
|
||||
friend class Ed25519;
|
||||
};
|
||||
|
||||
#endif
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// Minimal native stand-in for rweather/Crypto's own RNGClass (RNG.cpp /
|
||||
// NoiseSource.cpp are Arduino/AVR/ESP-hardware-entropy-only -- EEPROM/NVS
|
||||
// seed persistence, TRNG registers, etc. -- and were deliberately NOT vendored
|
||||
// here). Ed25519::generatePrivateKey() and Curve25519::dh1() reference the
|
||||
// global `RNG` object even though MeshCore itself never calls either
|
||||
// (real keypair generation goes through lib/ed25519 + mesh::RNG /
|
||||
// SimRNG, see variants/sim/SimRNG.h) -- the symbol still has to resolve
|
||||
// because it's referenced inside Ed25519.cpp/Curve25519.cpp regardless of
|
||||
// which functions actually get called at runtime.
|
||||
#include <RNG.h>
|
||||
#include <cstdlib>
|
||||
|
||||
RNGClass::RNGClass() { }
|
||||
RNGClass::~RNGClass() { }
|
||||
|
||||
void RNGClass::begin(const char *tag) { }
|
||||
void RNGClass::addNoiseSource(NoiseSource &source) { }
|
||||
void RNGClass::setAutoSaveTime(uint16_t minutes) { }
|
||||
|
||||
void RNGClass::rand(uint8_t *data, size_t len) {
|
||||
for (size_t i = 0; i < len; i++) data[i] = (uint8_t)::rand();
|
||||
}
|
||||
|
||||
bool RNGClass::available(size_t len) const { return true; }
|
||||
void RNGClass::stir(const uint8_t *data, size_t len, unsigned int credit) { }
|
||||
void RNGClass::save() { }
|
||||
void RNGClass::loop() { }
|
||||
void RNGClass::destroy() { }
|
||||
void RNGClass::rekey() { }
|
||||
void RNGClass::mixTRNG() { }
|
||||
|
||||
RNGClass RNG;
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_ENDIANUTIL_H
|
||||
#define CRYPTO_ENDIANUTIL_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#if !defined(HOST_BUILD)
|
||||
|
||||
// CPU is assumed to be little endian. Edit this file if you
|
||||
// need to port this library to a big endian CPU.
|
||||
|
||||
#define CRYPTO_LITTLE_ENDIAN 1
|
||||
|
||||
#define htole16(x) (x)
|
||||
#define le16toh(x) (x)
|
||||
#define htobe16(x) \
|
||||
(__extension__ ({ \
|
||||
uint16_t _temp = (x); \
|
||||
((_temp >> 8) & 0x00FF) | \
|
||||
((_temp << 8) & 0xFF00); \
|
||||
}))
|
||||
#define be16toh(x) (htobe16((x)))
|
||||
|
||||
#define htole32(x) (x)
|
||||
#define le32toh(x) (x)
|
||||
#define htobe32(x) \
|
||||
(__extension__ ({ \
|
||||
uint32_t _temp = (x); \
|
||||
((_temp >> 24) & 0x000000FF) | \
|
||||
((_temp >> 8) & 0x0000FF00) | \
|
||||
((_temp << 8) & 0x00FF0000) | \
|
||||
((_temp << 24) & 0xFF000000); \
|
||||
}))
|
||||
#define be32toh(x) (htobe32((x)))
|
||||
|
||||
#define htole64(x) (x)
|
||||
#define le64toh(x) (x)
|
||||
#define htobe64(x) \
|
||||
(__extension__ ({ \
|
||||
uint64_t __temp = (x); \
|
||||
uint32_t __low = htobe32((uint32_t)__temp); \
|
||||
uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \
|
||||
(((uint64_t)__low) << 32) | __high; \
|
||||
}))
|
||||
#define be64toh(x) (htobe64((x)))
|
||||
|
||||
#else // HOST_BUILD
|
||||
|
||||
#include <endian.h>
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define CRYPTO_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#endif // HOST_BUILD
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_LIMBUTIL_H
|
||||
#define CRYPTO_LIMBUTIL_H
|
||||
|
||||
#include "ProgMemUtil.h"
|
||||
|
||||
// Number of limbs in a big number value of various sizes.
|
||||
#define NUM_LIMBS_BITS(n) \
|
||||
(((n) + sizeof(limb_t) * 8 - 1) / (8 * sizeof(limb_t)))
|
||||
#define NUM_LIMBS_128BIT NUM_LIMBS_BITS(128)
|
||||
#define NUM_LIMBS_256BIT NUM_LIMBS_BITS(256)
|
||||
#define NUM_LIMBS_512BIT NUM_LIMBS_BITS(512)
|
||||
|
||||
// The number of bits in a limb.
|
||||
#define LIMB_BITS (8 * sizeof(limb_t))
|
||||
|
||||
// Read a limb-sized quantity from program memory.
|
||||
#if BIGNUMBER_LIMB_8BIT
|
||||
#define pgm_read_limb(x) (pgm_read_byte((x)))
|
||||
#elif BIGNUMBER_LIMB_16BIT
|
||||
#define pgm_read_limb(x) (pgm_read_word((x)))
|
||||
#elif BIGNUMBER_LIMB_32BIT
|
||||
#define pgm_read_limb(x) (pgm_read_dword((x)))
|
||||
#elif BIGNUMBER_LIMB_64BIT
|
||||
#define pgm_read_limb(x) (pgm_read_qword((x)))
|
||||
#endif
|
||||
|
||||
// Expand a 32-bit value into a set of limbs depending upon the limb size.
|
||||
// This is used when initializing constant big number values in the code.
|
||||
// For 64-bit system compatibility it is necessary to use LIMB_PAIR(x, y).
|
||||
#if BIGNUMBER_LIMB_8BIT
|
||||
#define LIMB(value) ((uint8_t)(value)), \
|
||||
((uint8_t)((value) >> 8)), \
|
||||
((uint8_t)((value) >> 16)), \
|
||||
((uint8_t)((value) >> 24))
|
||||
#define LIMB_PAIR(x,y) LIMB((x)), LIMB((y))
|
||||
#elif BIGNUMBER_LIMB_16BIT
|
||||
#define LIMB(value) ((uint16_t)(value)), \
|
||||
((uint16_t)(((uint32_t)(value)) >> 16))
|
||||
#define LIMB_PAIR(x,y) LIMB((x)), LIMB((y))
|
||||
#elif BIGNUMBER_LIMB_32BIT
|
||||
#define LIMB(value) (value)
|
||||
#define LIMB_PAIR(x,y) LIMB((x)), LIMB((y))
|
||||
#elif BIGNUMBER_LIMB_64BIT
|
||||
#define LIMB(value) (value)
|
||||
#define LIMB_PAIR(x,y) ((((uint64_t)(y)) << 32) | ((uint64_t)(x)))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_PROGMEMUTIL_H
|
||||
#define CRYPTO_PROGMEMUTIL_H
|
||||
|
||||
#if defined(__AVR__)
|
||||
#include <avr/pgmspace.h>
|
||||
#define pgm_read_qword(x) \
|
||||
(__extension__ ({ \
|
||||
const uint32_t *_temp = (const uint32_t *)(x); \
|
||||
((uint64_t)pgm_read_dword(_temp)) | \
|
||||
(((uint64_t)pgm_read_dword(_temp + 1)) << 32); \
|
||||
}))
|
||||
#elif defined(ESP8266) || defined(ESP32)
|
||||
#include <pgmspace.h>
|
||||
#define pgm_read_qword(x) \
|
||||
(__extension__ ({ \
|
||||
const uint32_t *_temp = (const uint32_t *)(x); \
|
||||
((uint64_t)pgm_read_dword(_temp)) | \
|
||||
(((uint64_t)pgm_read_dword(_temp + 1)) << 32); \
|
||||
}))
|
||||
#else
|
||||
#include <string.h>
|
||||
#define PROGMEM
|
||||
#ifndef pgm_read_byte
|
||||
# define pgm_read_byte(x) (*(x))
|
||||
#endif
|
||||
#ifndef pgm_read_word
|
||||
# define pgm_read_word(x) (*(x))
|
||||
#endif
|
||||
#ifndef pgm_read_dword
|
||||
# define pgm_read_dword(x) (*(x))
|
||||
#endif
|
||||
#ifndef pgm_read_qword
|
||||
# define pgm_read_qword(x) (*(x))
|
||||
#endif
|
||||
#ifndef memcpy_P
|
||||
# define memcpy_P(d,s,l) memcpy((d), (s), (l))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+696
@@ -0,0 +1,696 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_ROTATEUTIL_H
|
||||
#define CRYPTO_ROTATEUTIL_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
// Rotation functions that are optimised for best performance on AVR.
|
||||
// The most efficient rotations are where the number of bits is 1 or a
|
||||
// multiple of 8, so we compose the efficient rotations to produce all
|
||||
// other rotation counts of interest.
|
||||
|
||||
#if defined(__AVR__)
|
||||
#define CRYPTO_ROTATE32_COMPOSED 1
|
||||
#define CRYPTO_ROTATE64_COMPOSED 0
|
||||
#else
|
||||
#define CRYPTO_ROTATE32_COMPOSED 0
|
||||
#define CRYPTO_ROTATE64_COMPOSED 0
|
||||
#endif
|
||||
|
||||
#if CRYPTO_ROTATE32_COMPOSED
|
||||
|
||||
// Rotation macros for 32-bit arguments.
|
||||
|
||||
// Generic left rotate - best performance when "bits" is 1 or a multiple of 8.
|
||||
#define leftRotate(a, bits) \
|
||||
(__extension__ ({ \
|
||||
uint32_t _temp = (a); \
|
||||
(_temp << (bits)) | (_temp >> (32 - (bits))); \
|
||||
}))
|
||||
|
||||
// Generic right rotate - best performance when "bits" is 1 or a multiple of 8.
|
||||
#define rightRotate(a, bits) \
|
||||
(__extension__ ({ \
|
||||
uint32_t _temp = (a); \
|
||||
(_temp >> (bits)) | (_temp << (32 - (bits))); \
|
||||
}))
|
||||
|
||||
// Left rotate by 1.
|
||||
#define leftRotate1(a) (leftRotate((a), 1))
|
||||
|
||||
// Left rotate by 2.
|
||||
#define leftRotate2(a) (leftRotate(leftRotate((a), 1), 1))
|
||||
|
||||
// Left rotate by 3.
|
||||
#define leftRotate3(a) (leftRotate(leftRotate(leftRotate((a), 1), 1), 1))
|
||||
|
||||
// Left rotate by 4.
|
||||
#define leftRotate4(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 5: Rotate left by 8, then right by 3.
|
||||
#define leftRotate5(a) (rightRotate(rightRotate(rightRotate(leftRotate((a), 8), 1), 1), 1))
|
||||
|
||||
// Left rotate by 6: Rotate left by 8, then right by 2.
|
||||
#define leftRotate6(a) (rightRotate(rightRotate(leftRotate((a), 8), 1), 1))
|
||||
|
||||
// Left rotate by 7: Rotate left by 8, then right by 1.
|
||||
#define leftRotate7(a) (rightRotate(leftRotate((a), 8), 1))
|
||||
|
||||
// Left rotate by 8.
|
||||
#define leftRotate8(a) (leftRotate((a), 8))
|
||||
|
||||
// Left rotate by 9: Rotate left by 8, then left by 1.
|
||||
#define leftRotate9(a) (leftRotate(leftRotate((a), 8), 1))
|
||||
|
||||
// Left rotate by 10: Rotate left by 8, then left by 2.
|
||||
#define leftRotate10(a) (leftRotate(leftRotate(leftRotate((a), 8), 1), 1))
|
||||
|
||||
// Left rotate by 11: Rotate left by 8, then left by 3.
|
||||
#define leftRotate11(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 8), 1), 1), 1))
|
||||
|
||||
// Left rotate by 12: Rotate left by 16, then right by 4.
|
||||
#define leftRotate12(a) (rightRotate(rightRotate(rightRotate(rightRotate(leftRotate((a), 16), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 13: Rotate left by 16, then right by 3.
|
||||
#define leftRotate13(a) (rightRotate(rightRotate(rightRotate(leftRotate((a), 16), 1), 1), 1))
|
||||
|
||||
// Left rotate by 14: Rotate left by 16, then right by 2.
|
||||
#define leftRotate14(a) (rightRotate(rightRotate(leftRotate((a), 16), 1), 1))
|
||||
|
||||
// Left rotate by 15: Rotate left by 16, then right by 1.
|
||||
#define leftRotate15(a) (rightRotate(leftRotate((a), 16), 1))
|
||||
|
||||
// Left rotate by 16.
|
||||
#define leftRotate16(a) (leftRotate((a), 16))
|
||||
|
||||
// Left rotate by 17: Rotate left by 16, then left by 1.
|
||||
#define leftRotate17(a) (leftRotate(leftRotate((a), 16), 1))
|
||||
|
||||
// Left rotate by 18: Rotate left by 16, then left by 2.
|
||||
#define leftRotate18(a) (leftRotate(leftRotate(leftRotate((a), 16), 1), 1))
|
||||
|
||||
// Left rotate by 19: Rotate left by 16, then left by 3.
|
||||
#define leftRotate19(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 16), 1), 1), 1))
|
||||
|
||||
// Left rotate by 20: Rotate left by 16, then left by 4.
|
||||
#define leftRotate20(a) (leftRotate(leftRotate(leftRotate(leftRotate(leftRotate((a), 16), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 21: Rotate left by 24, then right by 3.
|
||||
#define leftRotate21(a) (rightRotate(rightRotate(rightRotate(leftRotate((a), 24), 1), 1), 1))
|
||||
|
||||
// Left rotate by 22: Rotate left by 24, then right by 2.
|
||||
#define leftRotate22(a) (rightRotate(rightRotate(leftRotate((a), 24), 1), 1))
|
||||
|
||||
// Left rotate by 23: Rotate left by 24, then right by 1.
|
||||
#define leftRotate23(a) (rightRotate(leftRotate((a), 24), 1))
|
||||
|
||||
// Left rotate by 24.
|
||||
#define leftRotate24(a) (leftRotate((a), 24))
|
||||
|
||||
// Left rotate by 25: Rotate left by 24, then left by 1.
|
||||
#define leftRotate25(a) (leftRotate(leftRotate((a), 24), 1))
|
||||
|
||||
// Left rotate by 26: Rotate left by 24, then left by 2.
|
||||
#define leftRotate26(a) (leftRotate(leftRotate(leftRotate((a), 24), 1), 1))
|
||||
|
||||
// Left rotate by 27: Rotate left by 24, then left by 3.
|
||||
#define leftRotate27(a) (leftRotate(leftRotate(leftRotate(leftRotate((a), 24), 1), 1), 1))
|
||||
|
||||
// Left rotate by 28: Rotate right by 4.
|
||||
#define leftRotate28(a) (rightRotate(rightRotate(rightRotate(rightRotate((a), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 29: Rotate right by 3.
|
||||
#define leftRotate29(a) (rightRotate(rightRotate(rightRotate((a), 1), 1), 1))
|
||||
|
||||
// Left rotate by 30: Rotate right by 2.
|
||||
#define leftRotate30(a) (rightRotate(rightRotate((a), 1), 1))
|
||||
|
||||
// Left rotate by 31: Rotate right by 1.
|
||||
#define leftRotate31(a) (rightRotate((a), 1))
|
||||
|
||||
// Define the 32-bit right rotations in terms of left rotations.
|
||||
#define rightRotate1(a) (leftRotate31((a)))
|
||||
#define rightRotate2(a) (leftRotate30((a)))
|
||||
#define rightRotate3(a) (leftRotate29((a)))
|
||||
#define rightRotate4(a) (leftRotate28((a)))
|
||||
#define rightRotate5(a) (leftRotate27((a)))
|
||||
#define rightRotate6(a) (leftRotate26((a)))
|
||||
#define rightRotate7(a) (leftRotate25((a)))
|
||||
#define rightRotate8(a) (leftRotate24((a)))
|
||||
#define rightRotate9(a) (leftRotate23((a)))
|
||||
#define rightRotate10(a) (leftRotate22((a)))
|
||||
#define rightRotate11(a) (leftRotate21((a)))
|
||||
#define rightRotate12(a) (leftRotate20((a)))
|
||||
#define rightRotate13(a) (leftRotate19((a)))
|
||||
#define rightRotate14(a) (leftRotate18((a)))
|
||||
#define rightRotate15(a) (leftRotate17((a)))
|
||||
#define rightRotate16(a) (leftRotate16((a)))
|
||||
#define rightRotate17(a) (leftRotate15((a)))
|
||||
#define rightRotate18(a) (leftRotate14((a)))
|
||||
#define rightRotate19(a) (leftRotate13((a)))
|
||||
#define rightRotate20(a) (leftRotate12((a)))
|
||||
#define rightRotate21(a) (leftRotate11((a)))
|
||||
#define rightRotate22(a) (leftRotate10((a)))
|
||||
#define rightRotate23(a) (leftRotate9((a)))
|
||||
#define rightRotate24(a) (leftRotate8((a)))
|
||||
#define rightRotate25(a) (leftRotate7((a)))
|
||||
#define rightRotate26(a) (leftRotate6((a)))
|
||||
#define rightRotate27(a) (leftRotate5((a)))
|
||||
#define rightRotate28(a) (leftRotate4((a)))
|
||||
#define rightRotate29(a) (leftRotate3((a)))
|
||||
#define rightRotate30(a) (leftRotate2((a)))
|
||||
#define rightRotate31(a) (leftRotate1((a)))
|
||||
|
||||
#else // !CRYPTO_ROTATE32_COMPOSED
|
||||
|
||||
// Generic rotation functions. All bit shifts are considered to have
|
||||
// similar performance. Usually true of 32-bit and higher platforms.
|
||||
|
||||
// Rotation macros for 32-bit arguments.
|
||||
|
||||
// Generic left rotate.
|
||||
#define leftRotate(a, bits) \
|
||||
(__extension__ ({ \
|
||||
uint32_t _temp = (a); \
|
||||
(_temp << (bits)) | (_temp >> (32 - (bits))); \
|
||||
}))
|
||||
|
||||
// Generic right rotate.
|
||||
#define rightRotate(a, bits) \
|
||||
(__extension__ ({ \
|
||||
uint32_t _temp = (a); \
|
||||
(_temp >> (bits)) | (_temp << (32 - (bits))); \
|
||||
}))
|
||||
|
||||
// Left rotate by a specific number of bits.
|
||||
#define leftRotate1(a) (leftRotate((a), 1))
|
||||
#define leftRotate2(a) (leftRotate((a), 2))
|
||||
#define leftRotate3(a) (leftRotate((a), 3))
|
||||
#define leftRotate4(a) (leftRotate((a), 4))
|
||||
#define leftRotate5(a) (leftRotate((a), 5))
|
||||
#define leftRotate6(a) (leftRotate((a), 6))
|
||||
#define leftRotate7(a) (leftRotate((a), 7))
|
||||
#define leftRotate8(a) (leftRotate((a), 8))
|
||||
#define leftRotate9(a) (leftRotate((a), 9))
|
||||
#define leftRotate10(a) (leftRotate((a), 10))
|
||||
#define leftRotate11(a) (leftRotate((a), 11))
|
||||
#define leftRotate12(a) (leftRotate((a), 12))
|
||||
#define leftRotate13(a) (leftRotate((a), 13))
|
||||
#define leftRotate14(a) (leftRotate((a), 14))
|
||||
#define leftRotate15(a) (leftRotate((a), 15))
|
||||
#define leftRotate16(a) (leftRotate((a), 16))
|
||||
#define leftRotate17(a) (leftRotate((a), 17))
|
||||
#define leftRotate18(a) (leftRotate((a), 18))
|
||||
#define leftRotate19(a) (leftRotate((a), 19))
|
||||
#define leftRotate20(a) (leftRotate((a), 20))
|
||||
#define leftRotate21(a) (leftRotate((a), 21))
|
||||
#define leftRotate22(a) (leftRotate((a), 22))
|
||||
#define leftRotate23(a) (leftRotate((a), 23))
|
||||
#define leftRotate24(a) (leftRotate((a), 24))
|
||||
#define leftRotate25(a) (leftRotate((a), 25))
|
||||
#define leftRotate26(a) (leftRotate((a), 26))
|
||||
#define leftRotate27(a) (leftRotate((a), 27))
|
||||
#define leftRotate28(a) (leftRotate((a), 28))
|
||||
#define leftRotate29(a) (leftRotate((a), 29))
|
||||
#define leftRotate30(a) (leftRotate((a), 30))
|
||||
#define leftRotate31(a) (leftRotate((a), 31))
|
||||
|
||||
// Right rotate by a specific number of bits.
|
||||
#define rightRotate1(a) (rightRotate((a), 1))
|
||||
#define rightRotate2(a) (rightRotate((a), 2))
|
||||
#define rightRotate3(a) (rightRotate((a), 3))
|
||||
#define rightRotate4(a) (rightRotate((a), 4))
|
||||
#define rightRotate5(a) (rightRotate((a), 5))
|
||||
#define rightRotate6(a) (rightRotate((a), 6))
|
||||
#define rightRotate7(a) (rightRotate((a), 7))
|
||||
#define rightRotate8(a) (rightRotate((a), 8))
|
||||
#define rightRotate9(a) (rightRotate((a), 9))
|
||||
#define rightRotate10(a) (rightRotate((a), 10))
|
||||
#define rightRotate11(a) (rightRotate((a), 11))
|
||||
#define rightRotate12(a) (rightRotate((a), 12))
|
||||
#define rightRotate13(a) (rightRotate((a), 13))
|
||||
#define rightRotate14(a) (rightRotate((a), 14))
|
||||
#define rightRotate15(a) (rightRotate((a), 15))
|
||||
#define rightRotate16(a) (rightRotate((a), 16))
|
||||
#define rightRotate17(a) (rightRotate((a), 17))
|
||||
#define rightRotate18(a) (rightRotate((a), 18))
|
||||
#define rightRotate19(a) (rightRotate((a), 19))
|
||||
#define rightRotate20(a) (rightRotate((a), 20))
|
||||
#define rightRotate21(a) (rightRotate((a), 21))
|
||||
#define rightRotate22(a) (rightRotate((a), 22))
|
||||
#define rightRotate23(a) (rightRotate((a), 23))
|
||||
#define rightRotate24(a) (rightRotate((a), 24))
|
||||
#define rightRotate25(a) (rightRotate((a), 25))
|
||||
#define rightRotate26(a) (rightRotate((a), 26))
|
||||
#define rightRotate27(a) (rightRotate((a), 27))
|
||||
#define rightRotate28(a) (rightRotate((a), 28))
|
||||
#define rightRotate29(a) (rightRotate((a), 29))
|
||||
#define rightRotate30(a) (rightRotate((a), 30))
|
||||
#define rightRotate31(a) (rightRotate((a), 31))
|
||||
|
||||
#endif // !CRYPTO_ROTATE32_COMPOSED
|
||||
|
||||
#if CRYPTO_ROTATE64_COMPOSED
|
||||
|
||||
// Rotation macros for 64-bit arguments.
|
||||
|
||||
// Generic left rotate - best performance when "bits" is 1 or a multiple of 8.
|
||||
#define leftRotate_64(a, bits) \
|
||||
(__extension__ ({ \
|
||||
uint64_t _temp = (a); \
|
||||
(_temp << (bits)) | (_temp >> (64 - (bits))); \
|
||||
}))
|
||||
|
||||
// Generic right rotate - best performance when "bits" is 1 or a multiple of 8.
|
||||
#define rightRotate_64(a, bits) \
|
||||
(__extension__ ({ \
|
||||
uint64_t _temp = (a); \
|
||||
(_temp >> (bits)) | (_temp << (64 - (bits))); \
|
||||
}))
|
||||
|
||||
// Left rotate by 1.
|
||||
#define leftRotate1_64(a) (leftRotate_64((a), 1))
|
||||
|
||||
// Left rotate by 2.
|
||||
#define leftRotate2_64(a) (leftRotate_64(leftRotate_64((a), 1), 1))
|
||||
|
||||
// Left rotate by 3.
|
||||
#define leftRotate3_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 1), 1), 1))
|
||||
|
||||
// Left rotate by 4.
|
||||
#define leftRotate4_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 5: Rotate left by 8, then right by 3.
|
||||
#define leftRotate5_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 8), 1), 1), 1))
|
||||
|
||||
// Left rotate by 6: Rotate left by 8, then right by 2.
|
||||
#define leftRotate6_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 8), 1), 1))
|
||||
|
||||
// Left rotate by 7: Rotate left by 8, then right by 1.
|
||||
#define leftRotate7_64(a) (rightRotate_64(leftRotate_64((a), 8), 1))
|
||||
|
||||
// Left rotate by 8.
|
||||
#define leftRotate8_64(a) (leftRotate_64((a), 8))
|
||||
|
||||
// Left rotate by 9: Rotate left by 8, then left by 1.
|
||||
#define leftRotate9_64(a) (leftRotate_64(leftRotate_64((a), 8), 1))
|
||||
|
||||
// Left rotate by 10: Rotate left by 8, then left by 2.
|
||||
#define leftRotate10_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 8), 1), 1))
|
||||
|
||||
// Left rotate by 11: Rotate left by 8, then left by 3.
|
||||
#define leftRotate11_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 8), 1), 1), 1))
|
||||
|
||||
// Left rotate by 12: Rotate left by 16, then right by 4.
|
||||
#define leftRotate12_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 16), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 13: Rotate left by 16, then right by 3.
|
||||
#define leftRotate13_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 16), 1), 1), 1))
|
||||
|
||||
// Left rotate by 14: Rotate left by 16, then right by 2.
|
||||
#define leftRotate14_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 16), 1), 1))
|
||||
|
||||
// Left rotate by 15: Rotate left by 16, then right by 1.
|
||||
#define leftRotate15_64(a) (rightRotate_64(leftRotate_64((a), 16), 1))
|
||||
|
||||
// Left rotate by 16.
|
||||
#define leftRotate16_64(a) (leftRotate_64((a), 16))
|
||||
|
||||
// Left rotate by 17: Rotate left by 16, then left by 1.
|
||||
#define leftRotate17_64(a) (leftRotate_64(leftRotate_64((a), 16), 1))
|
||||
|
||||
// Left rotate by 18: Rotate left by 16, then left by 2.
|
||||
#define leftRotate18_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 16), 1), 1))
|
||||
|
||||
// Left rotate by 19: Rotate left by 16, then left by 3.
|
||||
#define leftRotate19_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 16), 1), 1), 1))
|
||||
|
||||
// Left rotate by 20: Rotate left by 16, then left by 4.
|
||||
#define leftRotate20_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 16), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 21: Rotate left by 24, then right by 3.
|
||||
#define leftRotate21_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 24), 1), 1), 1))
|
||||
|
||||
// Left rotate by 22: Rotate left by 24, then right by 2.
|
||||
#define leftRotate22_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 24), 1), 1))
|
||||
|
||||
// Left rotate by 23: Rotate left by 24, then right by 1.
|
||||
#define leftRotate23_64(a) (rightRotate_64(leftRotate_64((a), 24), 1))
|
||||
|
||||
// Left rotate by 24.
|
||||
#define leftRotate24_64(a) (leftRotate_64((a), 24))
|
||||
|
||||
// Left rotate by 25: Rotate left by 24, then left by 1.
|
||||
#define leftRotate25_64(a) (leftRotate_64(leftRotate_64((a), 24), 1))
|
||||
|
||||
// Left rotate by 26: Rotate left by 24, then left by 2.
|
||||
#define leftRotate26_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 24), 1), 1))
|
||||
|
||||
// Left rotate by 27: Rotate left by 24, then left by 3.
|
||||
#define leftRotate27_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 24), 1), 1), 1))
|
||||
|
||||
// Left rotate by 28: Rotate left by 24, then left by 4.
|
||||
#define leftRotate28_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 24), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 29: Rotate left by 32, then right by 3.
|
||||
#define leftRotate29_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 32), 1), 1), 1))
|
||||
|
||||
// Left rotate by 30: Rotate left by 32, then right by 2.
|
||||
#define leftRotate30_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 32), 1), 1))
|
||||
|
||||
// Left rotate by 31: Rotate left by 32, then right by 1.
|
||||
#define leftRotate31_64(a) (rightRotate_64(leftRotate_64((a), 32), 1))
|
||||
|
||||
// Left rotate by 32.
|
||||
#define leftRotate32_64(a) (leftRotate_64((a), 32))
|
||||
|
||||
// Left rotate by 33: Rotate left by 32, then left by 1.
|
||||
#define leftRotate33_64(a) (leftRotate_64(leftRotate_64((a), 32), 1))
|
||||
|
||||
// Left rotate by 34: Rotate left by 32, then left by 2.
|
||||
#define leftRotate34_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 32), 1), 1))
|
||||
|
||||
// Left rotate by 35: Rotate left by 32, then left by 3.
|
||||
#define leftRotate35_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 32), 1), 1), 1))
|
||||
|
||||
// Left rotate by 36: Rotate left by 32, then left by 4.
|
||||
#define leftRotate36_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 32), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 37: Rotate left by 40, then right by 3.
|
||||
#define leftRotate37_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 40), 1), 1), 1))
|
||||
|
||||
// Left rotate by 38: Rotate left by 40, then right by 2.
|
||||
#define leftRotate38_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 40), 1), 1))
|
||||
|
||||
// Left rotate by 39: Rotate left by 40, then right by 1.
|
||||
#define leftRotate39_64(a) (rightRotate_64(leftRotate_64((a), 40), 1))
|
||||
|
||||
// Left rotate by 40.
|
||||
#define leftRotate40_64(a) (leftRotate_64((a), 40))
|
||||
|
||||
// Left rotate by 41: Rotate left by 40, then left by 1.
|
||||
#define leftRotate41_64(a) (leftRotate_64(leftRotate_64((a), 40), 1))
|
||||
|
||||
// Left rotate by 42: Rotate left by 40, then left by 2.
|
||||
#define leftRotate42_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 40), 1), 1))
|
||||
|
||||
// Left rotate by 43: Rotate left by 40, then left by 3.
|
||||
#define leftRotate43_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 40), 1), 1), 1))
|
||||
|
||||
// Left rotate by 44: Rotate left by 40, then left by 4.
|
||||
#define leftRotate44_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 40), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 45: Rotate left by 48, then right by 3.
|
||||
#define leftRotate45_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 48), 1), 1), 1))
|
||||
|
||||
// Left rotate by 46: Rotate left by 48, then right by 2.
|
||||
#define leftRotate46_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 48), 1), 1))
|
||||
|
||||
// Left rotate by 47: Rotate left by 48, then right by 1.
|
||||
#define leftRotate47_64(a) (rightRotate_64(leftRotate_64((a), 48), 1))
|
||||
|
||||
// Left rotate by 48.
|
||||
#define leftRotate48_64(a) (leftRotate_64((a), 48))
|
||||
|
||||
// Left rotate by 49: Rotate left by 48, then left by 1.
|
||||
#define leftRotate49_64(a) (leftRotate_64(leftRotate_64((a), 48), 1))
|
||||
|
||||
// Left rotate by 50: Rotate left by 48, then left by 2.
|
||||
#define leftRotate50_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 48), 1), 1))
|
||||
|
||||
// Left rotate by 51: Rotate left by 48, then left by 3.
|
||||
#define leftRotate51_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 48), 1), 1), 1))
|
||||
|
||||
// Left rotate by 52: Rotate left by 48, then left by 4.
|
||||
#define leftRotate52_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 48), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 53: Rotate left by 56, then right by 3.
|
||||
#define leftRotate53_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 56), 1), 1), 1))
|
||||
|
||||
// Left rotate by 54: Rotate left by 56, then right by 2.
|
||||
#define leftRotate54_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 56), 1), 1))
|
||||
|
||||
// Left rotate by 55: Rotate left by 56, then right by 1.
|
||||
#define leftRotate55_64(a) (rightRotate_64(leftRotate_64((a), 56), 1))
|
||||
|
||||
// Left rotate by 56.
|
||||
#define leftRotate56_64(a) (leftRotate_64((a), 56))
|
||||
|
||||
// Left rotate by 57: Rotate left by 56, then left by 1.
|
||||
#define leftRotate57_64(a) (leftRotate_64(leftRotate_64((a), 56), 1))
|
||||
|
||||
// Left rotate by 58: Rotate left by 56, then left by 2.
|
||||
#define leftRotate58_64(a) (leftRotate_64(leftRotate_64(leftRotate_64((a), 56), 1), 1))
|
||||
|
||||
// Left rotate by 59: Rotate left by 56, then left by 3.
|
||||
#define leftRotate59_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 56), 1), 1), 1))
|
||||
|
||||
// Left rotate by 60: Rotate left by 60, then left by 4.
|
||||
#define leftRotate60_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 56), 1), 1), 1), 1))
|
||||
|
||||
// Left rotate by 61: Rotate right by 3.
|
||||
#define leftRotate61_64(a) (rightRotate_64(rightRotate_64(rightRotate_64((a), 1), 1), 1))
|
||||
|
||||
// Left rotate by 62: Rotate right by 2.
|
||||
#define leftRotate62_64(a) (rightRotate_64(rightRotate_64((a), 1), 1))
|
||||
|
||||
// Left rotate by 63: Rotate right by 1.
|
||||
#define leftRotate63_64(a) (rightRotate_64((a), 1))
|
||||
|
||||
// Define the 64-bit right rotations in terms of left rotations.
|
||||
#define rightRotate1_64(a) (leftRotate63_64((a)))
|
||||
#define rightRotate2_64(a) (leftRotate62_64((a)))
|
||||
#define rightRotate3_64(a) (leftRotate61_64((a)))
|
||||
#define rightRotate4_64(a) (leftRotate60_64((a)))
|
||||
#define rightRotate5_64(a) (leftRotate59_64((a)))
|
||||
#define rightRotate6_64(a) (leftRotate58_64((a)))
|
||||
#define rightRotate7_64(a) (leftRotate57_64((a)))
|
||||
#define rightRotate8_64(a) (leftRotate56_64((a)))
|
||||
#define rightRotate9_64(a) (leftRotate55_64((a)))
|
||||
#define rightRotate10_64(a) (leftRotate54_64((a)))
|
||||
#define rightRotate11_64(a) (leftRotate53_64((a)))
|
||||
#define rightRotate12_64(a) (leftRotate52_64((a)))
|
||||
#define rightRotate13_64(a) (leftRotate51_64((a)))
|
||||
#define rightRotate14_64(a) (leftRotate50_64((a)))
|
||||
#define rightRotate15_64(a) (leftRotate49_64((a)))
|
||||
#define rightRotate16_64(a) (leftRotate48_64((a)))
|
||||
#define rightRotate17_64(a) (leftRotate47_64((a)))
|
||||
#define rightRotate18_64(a) (leftRotate46_64((a)))
|
||||
#define rightRotate19_64(a) (leftRotate45_64((a)))
|
||||
#define rightRotate20_64(a) (leftRotate44_64((a)))
|
||||
#define rightRotate21_64(a) (leftRotate43_64((a)))
|
||||
#define rightRotate22_64(a) (leftRotate42_64((a)))
|
||||
#define rightRotate23_64(a) (leftRotate41_64((a)))
|
||||
#define rightRotate24_64(a) (leftRotate40_64((a)))
|
||||
#define rightRotate25_64(a) (leftRotate39_64((a)))
|
||||
#define rightRotate26_64(a) (leftRotate38_64((a)))
|
||||
#define rightRotate27_64(a) (leftRotate37_64((a)))
|
||||
#define rightRotate28_64(a) (leftRotate36_64((a)))
|
||||
#define rightRotate29_64(a) (leftRotate35_64((a)))
|
||||
#define rightRotate30_64(a) (leftRotate34_64((a)))
|
||||
#define rightRotate31_64(a) (leftRotate33_64((a)))
|
||||
#define rightRotate32_64(a) (leftRotate32_64((a)))
|
||||
#define rightRotate33_64(a) (leftRotate31_64((a)))
|
||||
#define rightRotate34_64(a) (leftRotate30_64((a)))
|
||||
#define rightRotate35_64(a) (leftRotate29_64((a)))
|
||||
#define rightRotate36_64(a) (leftRotate28_64((a)))
|
||||
#define rightRotate37_64(a) (leftRotate27_64((a)))
|
||||
#define rightRotate38_64(a) (leftRotate26_64((a)))
|
||||
#define rightRotate39_64(a) (leftRotate25_64((a)))
|
||||
#define rightRotate40_64(a) (leftRotate24_64((a)))
|
||||
#define rightRotate41_64(a) (leftRotate23_64((a)))
|
||||
#define rightRotate42_64(a) (leftRotate22_64((a)))
|
||||
#define rightRotate43_64(a) (leftRotate21_64((a)))
|
||||
#define rightRotate44_64(a) (leftRotate20_64((a)))
|
||||
#define rightRotate45_64(a) (leftRotate19_64((a)))
|
||||
#define rightRotate46_64(a) (leftRotate18_64((a)))
|
||||
#define rightRotate47_64(a) (leftRotate17_64((a)))
|
||||
#define rightRotate48_64(a) (leftRotate16_64((a)))
|
||||
#define rightRotate49_64(a) (leftRotate15_64((a)))
|
||||
#define rightRotate50_64(a) (leftRotate14_64((a)))
|
||||
#define rightRotate51_64(a) (leftRotate13_64((a)))
|
||||
#define rightRotate52_64(a) (leftRotate12_64((a)))
|
||||
#define rightRotate53_64(a) (leftRotate11_64((a)))
|
||||
#define rightRotate54_64(a) (leftRotate10_64((a)))
|
||||
#define rightRotate55_64(a) (leftRotate9_64((a)))
|
||||
#define rightRotate56_64(a) (leftRotate8_64((a)))
|
||||
#define rightRotate57_64(a) (leftRotate7_64((a)))
|
||||
#define rightRotate58_64(a) (leftRotate6_64((a)))
|
||||
#define rightRotate59_64(a) (leftRotate5_64((a)))
|
||||
#define rightRotate60_64(a) (leftRotate4_64((a)))
|
||||
#define rightRotate61_64(a) (leftRotate3_64((a)))
|
||||
#define rightRotate62_64(a) (leftRotate2_64((a)))
|
||||
#define rightRotate63_64(a) (leftRotate1_64((a)))
|
||||
|
||||
#else // !CRYPTO_ROTATE64_COMPOSED
|
||||
|
||||
// Rotation macros for 64-bit arguments.
|
||||
|
||||
// Generic left rotate.
|
||||
#define leftRotate_64(a, bits) \
|
||||
(__extension__ ({ \
|
||||
uint64_t _temp = (a); \
|
||||
(_temp << (bits)) | (_temp >> (64 - (bits))); \
|
||||
}))
|
||||
|
||||
// Generic right rotate.
|
||||
#define rightRotate_64(a, bits) \
|
||||
(__extension__ ({ \
|
||||
uint64_t _temp = (a); \
|
||||
(_temp >> (bits)) | (_temp << (64 - (bits))); \
|
||||
}))
|
||||
|
||||
// Left rotate by a specific number of bits.
|
||||
#define leftRotate1_64(a) (leftRotate_64((a), 1))
|
||||
#define leftRotate2_64(a) (leftRotate_64((a), 2))
|
||||
#define leftRotate3_64(a) (leftRotate_64((a), 3))
|
||||
#define leftRotate4_64(a) (leftRotate_64((a), 4))
|
||||
#define leftRotate5_64(a) (leftRotate_64((a), 5))
|
||||
#define leftRotate6_64(a) (leftRotate_64((a), 6))
|
||||
#define leftRotate7_64(a) (leftRotate_64((a), 7))
|
||||
#define leftRotate8_64(a) (leftRotate_64((a), 8))
|
||||
#define leftRotate9_64(a) (leftRotate_64((a), 9))
|
||||
#define leftRotate10_64(a) (leftRotate_64((a), 10))
|
||||
#define leftRotate11_64(a) (leftRotate_64((a), 11))
|
||||
#define leftRotate12_64(a) (leftRotate_64((a), 12))
|
||||
#define leftRotate13_64(a) (leftRotate_64((a), 13))
|
||||
#define leftRotate14_64(a) (leftRotate_64((a), 14))
|
||||
#define leftRotate15_64(a) (leftRotate_64((a), 15))
|
||||
#define leftRotate16_64(a) (leftRotate_64((a), 16))
|
||||
#define leftRotate17_64(a) (leftRotate_64((a), 17))
|
||||
#define leftRotate18_64(a) (leftRotate_64((a), 18))
|
||||
#define leftRotate19_64(a) (leftRotate_64((a), 19))
|
||||
#define leftRotate20_64(a) (leftRotate_64((a), 20))
|
||||
#define leftRotate21_64(a) (leftRotate_64((a), 21))
|
||||
#define leftRotate22_64(a) (leftRotate_64((a), 22))
|
||||
#define leftRotate23_64(a) (leftRotate_64((a), 23))
|
||||
#define leftRotate24_64(a) (leftRotate_64((a), 24))
|
||||
#define leftRotate25_64(a) (leftRotate_64((a), 25))
|
||||
#define leftRotate26_64(a) (leftRotate_64((a), 26))
|
||||
#define leftRotate27_64(a) (leftRotate_64((a), 27))
|
||||
#define leftRotate28_64(a) (leftRotate_64((a), 28))
|
||||
#define leftRotate29_64(a) (leftRotate_64((a), 29))
|
||||
#define leftRotate30_64(a) (leftRotate_64((a), 30))
|
||||
#define leftRotate31_64(a) (leftRotate_64((a), 31))
|
||||
#define leftRotate32_64(a) (leftRotate_64((a), 32))
|
||||
#define leftRotate33_64(a) (leftRotate_64((a), 33))
|
||||
#define leftRotate34_64(a) (leftRotate_64((a), 34))
|
||||
#define leftRotate35_64(a) (leftRotate_64((a), 35))
|
||||
#define leftRotate36_64(a) (leftRotate_64((a), 36))
|
||||
#define leftRotate37_64(a) (leftRotate_64((a), 37))
|
||||
#define leftRotate38_64(a) (leftRotate_64((a), 38))
|
||||
#define leftRotate39_64(a) (leftRotate_64((a), 39))
|
||||
#define leftRotate40_64(a) (leftRotate_64((a), 40))
|
||||
#define leftRotate41_64(a) (leftRotate_64((a), 41))
|
||||
#define leftRotate42_64(a) (leftRotate_64((a), 42))
|
||||
#define leftRotate43_64(a) (leftRotate_64((a), 43))
|
||||
#define leftRotate44_64(a) (leftRotate_64((a), 44))
|
||||
#define leftRotate45_64(a) (leftRotate_64((a), 45))
|
||||
#define leftRotate46_64(a) (leftRotate_64((a), 46))
|
||||
#define leftRotate47_64(a) (leftRotate_64((a), 47))
|
||||
#define leftRotate48_64(a) (leftRotate_64((a), 48))
|
||||
#define leftRotate49_64(a) (leftRotate_64((a), 49))
|
||||
#define leftRotate50_64(a) (leftRotate_64((a), 50))
|
||||
#define leftRotate51_64(a) (leftRotate_64((a), 51))
|
||||
#define leftRotate52_64(a) (leftRotate_64((a), 52))
|
||||
#define leftRotate53_64(a) (leftRotate_64((a), 53))
|
||||
#define leftRotate54_64(a) (leftRotate_64((a), 54))
|
||||
#define leftRotate55_64(a) (leftRotate_64((a), 55))
|
||||
#define leftRotate56_64(a) (leftRotate_64((a), 56))
|
||||
#define leftRotate57_64(a) (leftRotate_64((a), 57))
|
||||
#define leftRotate58_64(a) (leftRotate_64((a), 58))
|
||||
#define leftRotate59_64(a) (leftRotate_64((a), 59))
|
||||
#define leftRotate60_64(a) (leftRotate_64((a), 60))
|
||||
#define leftRotate61_64(a) (leftRotate_64((a), 61))
|
||||
#define leftRotate62_64(a) (leftRotate_64((a), 62))
|
||||
#define leftRotate63_64(a) (leftRotate_64((a), 63))
|
||||
|
||||
// Right rotate by a specific number of bits.
|
||||
#define rightRotate1_64(a) (rightRotate_64((a), 1))
|
||||
#define rightRotate2_64(a) (rightRotate_64((a), 2))
|
||||
#define rightRotate3_64(a) (rightRotate_64((a), 3))
|
||||
#define rightRotate4_64(a) (rightRotate_64((a), 4))
|
||||
#define rightRotate5_64(a) (rightRotate_64((a), 5))
|
||||
#define rightRotate6_64(a) (rightRotate_64((a), 6))
|
||||
#define rightRotate7_64(a) (rightRotate_64((a), 7))
|
||||
#define rightRotate8_64(a) (rightRotate_64((a), 8))
|
||||
#define rightRotate9_64(a) (rightRotate_64((a), 9))
|
||||
#define rightRotate10_64(a) (rightRotate_64((a), 10))
|
||||
#define rightRotate11_64(a) (rightRotate_64((a), 11))
|
||||
#define rightRotate12_64(a) (rightRotate_64((a), 12))
|
||||
#define rightRotate13_64(a) (rightRotate_64((a), 13))
|
||||
#define rightRotate14_64(a) (rightRotate_64((a), 14))
|
||||
#define rightRotate15_64(a) (rightRotate_64((a), 15))
|
||||
#define rightRotate16_64(a) (rightRotate_64((a), 16))
|
||||
#define rightRotate17_64(a) (rightRotate_64((a), 17))
|
||||
#define rightRotate18_64(a) (rightRotate_64((a), 18))
|
||||
#define rightRotate19_64(a) (rightRotate_64((a), 19))
|
||||
#define rightRotate20_64(a) (rightRotate_64((a), 20))
|
||||
#define rightRotate21_64(a) (rightRotate_64((a), 21))
|
||||
#define rightRotate22_64(a) (rightRotate_64((a), 22))
|
||||
#define rightRotate23_64(a) (rightRotate_64((a), 23))
|
||||
#define rightRotate24_64(a) (rightRotate_64((a), 24))
|
||||
#define rightRotate25_64(a) (rightRotate_64((a), 25))
|
||||
#define rightRotate26_64(a) (rightRotate_64((a), 26))
|
||||
#define rightRotate27_64(a) (rightRotate_64((a), 27))
|
||||
#define rightRotate28_64(a) (rightRotate_64((a), 28))
|
||||
#define rightRotate29_64(a) (rightRotate_64((a), 29))
|
||||
#define rightRotate30_64(a) (rightRotate_64((a), 30))
|
||||
#define rightRotate31_64(a) (rightRotate_64((a), 31))
|
||||
#define rightRotate32_64(a) (rightRotate_64((a), 32))
|
||||
#define rightRotate33_64(a) (rightRotate_64((a), 33))
|
||||
#define rightRotate34_64(a) (rightRotate_64((a), 34))
|
||||
#define rightRotate35_64(a) (rightRotate_64((a), 35))
|
||||
#define rightRotate36_64(a) (rightRotate_64((a), 36))
|
||||
#define rightRotate37_64(a) (rightRotate_64((a), 37))
|
||||
#define rightRotate38_64(a) (rightRotate_64((a), 38))
|
||||
#define rightRotate39_64(a) (rightRotate_64((a), 39))
|
||||
#define rightRotate40_64(a) (rightRotate_64((a), 40))
|
||||
#define rightRotate41_64(a) (rightRotate_64((a), 41))
|
||||
#define rightRotate42_64(a) (rightRotate_64((a), 42))
|
||||
#define rightRotate43_64(a) (rightRotate_64((a), 43))
|
||||
#define rightRotate44_64(a) (rightRotate_64((a), 44))
|
||||
#define rightRotate45_64(a) (rightRotate_64((a), 45))
|
||||
#define rightRotate46_64(a) (rightRotate_64((a), 46))
|
||||
#define rightRotate47_64(a) (rightRotate_64((a), 47))
|
||||
#define rightRotate48_64(a) (rightRotate_64((a), 48))
|
||||
#define rightRotate49_64(a) (rightRotate_64((a), 49))
|
||||
#define rightRotate50_64(a) (rightRotate_64((a), 50))
|
||||
#define rightRotate51_64(a) (rightRotate_64((a), 51))
|
||||
#define rightRotate52_64(a) (rightRotate_64((a), 52))
|
||||
#define rightRotate53_64(a) (rightRotate_64((a), 53))
|
||||
#define rightRotate54_64(a) (rightRotate_64((a), 54))
|
||||
#define rightRotate55_64(a) (rightRotate_64((a), 55))
|
||||
#define rightRotate56_64(a) (rightRotate_64((a), 56))
|
||||
#define rightRotate57_64(a) (rightRotate_64((a), 57))
|
||||
#define rightRotate58_64(a) (rightRotate_64((a), 58))
|
||||
#define rightRotate59_64(a) (rightRotate_64((a), 59))
|
||||
#define rightRotate60_64(a) (rightRotate_64((a), 60))
|
||||
#define rightRotate61_64(a) (rightRotate_64((a), 61))
|
||||
#define rightRotate62_64(a) (rightRotate_64((a), 62))
|
||||
#define rightRotate63_64(a) (rightRotate_64((a), 63))
|
||||
|
||||
#endif // !CRYPTO_ROTATE64_COMPOSED
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user