mirror of
https://github.com/taigrr/arduinolibs
synced 2025-01-18 04:33:12 -08:00
Use CRC-8 to validate the random seed in EEPROM/Flash
This commit is contained in:
parent
8400d51420
commit
06987988be
@ -160,7 +160,7 @@ void setup() {
|
||||
}
|
||||
\endcode
|
||||
|
||||
The random number generator uses 49 bytes of space at the end of
|
||||
The random number generator uses 48 bytes of space at the end of
|
||||
EEPROM memory to store the previous seed. When the system is started
|
||||
next time, the previous saved seed is loaded and then deliberately
|
||||
overwritten with a new seed. This ensures that the device will not
|
||||
|
@ -77,3 +77,38 @@ bool secure_compare(const void *data1, const void *data2, size_t 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;
|
||||
}
|
||||
|
@ -154,6 +154,9 @@ RNGClass RNG;
|
||||
|
||||
/** @cond */
|
||||
|
||||
// Imported from Crypto.cpp.
|
||||
extern uint8_t crypto_crc8(uint8_t tag, const void *data, unsigned size);
|
||||
|
||||
// Tag for 256-bit ChaCha20 keys. This will always appear in the
|
||||
// first 16 bytes of the block. The remaining 48 bytes are the seed.
|
||||
static const char tagRNG[16] PROGMEM = {
|
||||
@ -361,17 +364,19 @@ void RNGClass::begin(const char *tag)
|
||||
memcpy_P(block + 4, initRNG, sizeof(initRNG));
|
||||
#if defined(RNG_EEPROM)
|
||||
int address = RNG_EEPROM_ADDRESS;
|
||||
if (eeprom_read_byte((const uint8_t *)address) == 'S') {
|
||||
eeprom_read_block(stream, (const void *)address, SEED_SIZE);
|
||||
if (crypto_crc8('S', stream, SEED_SIZE - 1) ==
|
||||
((const uint8_t *)stream)[SEED_SIZE - 1]) {
|
||||
// We have a saved seed: XOR it with the initialization block.
|
||||
for (int posn = 0; posn < 12; ++posn) {
|
||||
block[posn + 4] ^=
|
||||
eeprom_read_dword((const uint32_t *)(address + posn * 4 + 1));
|
||||
}
|
||||
// Note: the CRC-8 value is included. No point throwing it away.
|
||||
for (int posn = 0; posn < 12; ++posn)
|
||||
block[posn + 4] ^= stream[posn];
|
||||
}
|
||||
#elif defined(RNG_DUE_TRNG)
|
||||
// Do we have a seed saved in the last page of flash memory on the Due?
|
||||
int posn, counter;
|
||||
if (((const uint32_t *)RNG_SEED_ADDR)[0] == 'S') {
|
||||
if (crypto_crc8('S', ((const uint32_t *)RNG_SEED_ADDR) + 1, SEED_SIZE)
|
||||
== ((const uint32_t *)RNG_SEED_ADDR)[0]) {
|
||||
// XOR the saved seed with the initialization block.
|
||||
for (posn = 0; posn < 12; ++posn)
|
||||
block[posn + 4] ^= ((const uint32_t *)RNG_SEED_ADDR)[posn + 1];
|
||||
@ -694,12 +699,16 @@ void RNGClass::save()
|
||||
++(block[12]);
|
||||
ChaCha::hashCore(stream, block, RNG_ROUNDS);
|
||||
#if defined(RNG_EEPROM)
|
||||
// We shorten the seed from 48 bytes to 47 to leave room for
|
||||
// the CRC-8 value. We do this to align the data on an 8-byte
|
||||
// boundary in EERPOM.
|
||||
int address = RNG_EEPROM_ADDRESS;
|
||||
eeprom_write_block(stream, (void *)(address + 1), 48);
|
||||
eeprom_update_byte((uint8_t *)address, 'S');
|
||||
eeprom_write_block(stream, (void *)address, SEED_SIZE - 1);
|
||||
eeprom_write_byte((uint8_t *)(address + SEED_SIZE - 1),
|
||||
crypto_crc8('S', stream, SEED_SIZE - 1));
|
||||
#elif defined(RNG_DUE_TRNG)
|
||||
unsigned posn;
|
||||
((uint32_t *)(RNG_SEED_ADDR))[0] = 'S';
|
||||
((uint32_t *)(RNG_SEED_ADDR))[0] = crypto_crc8('S', stream, SEED_SIZE);
|
||||
for (posn = 0; posn < 12; ++posn)
|
||||
((uint32_t *)(RNG_SEED_ADDR))[posn + 1] = stream[posn];
|
||||
for (posn = 13; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn)
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
|
||||
void destroy();
|
||||
|
||||
static const int SEED_SIZE = 49;
|
||||
static const int SEED_SIZE = 48;
|
||||
|
||||
private:
|
||||
uint32_t block[16];
|
||||
|
Loading…
x
Reference in New Issue
Block a user