1
0
mirror of https://github.com/taigrr/arduinolibs synced 2025-01-18 04:33:12 -08:00

KeyRing implementation

This commit is contained in:
Rhys Weatherley 2018-06-16 14:08:01 +10:00
parent 7423609e64
commit fa1400ea83
7 changed files with 1494 additions and 161 deletions

View File

@ -43,7 +43,8 @@ in the repository:
\li Message authenticators: Poly1305, GHASH, OMAC \li Message authenticators: Poly1305, GHASH, OMAC
\li Public key algorithms: Curve25519, Ed25519, P521 \li Public key algorithms: Curve25519, Ed25519, P521
\li Random number generation: \link RNGClass RNG\endlink \li Random number generation: \link RNGClass RNG\endlink
\li Storage of key pairs and other key material in EEPROM or Flash: KeyRing \li Storage of key pairs and other key material in EEPROM or Flash:
\link KeyRingClass KeyRing\endlink
Reduced memory versions of some algorithms (encryption is slower, but the Reduced memory versions of some algorithms (encryption is slower, but the
RAM required for the key schedule is less): RAM required for the key schedule is less):

View File

@ -133,6 +133,7 @@ SKETCHES = \
TestEd25519/TestEd25519.ino \ TestEd25519/TestEd25519.ino \
TestGCM/TestGCM.ino \ TestGCM/TestGCM.ino \
TestGHASH/TestGHASH.ino \ TestGHASH/TestGHASH.ino \
TestKeyRing/TestKeyRing.ino \
TestNewHope/TestNewHope.ino \ TestNewHope/TestNewHope.ino \
TestOFB/TestOFB.ino \ TestOFB/TestOFB.ino \
TestP521/TestP521.ino \ TestP521/TestP521.ino \

File diff suppressed because it is too large Load Diff

View File

@ -26,40 +26,38 @@
#include <inttypes.h> #include <inttypes.h>
#include <stddef.h> #include <stddef.h>
class KeyRing class KeyRingClass
{ {
private:
KeyRing() {}
~KeyRing() {}
public: public:
static bool setLocalKeyPair KeyRingClass();
(uint16_t id, const void *pair, size_t size); ~KeyRingClass();
static size_t getLocalKeyPair
(uint16_t id, void *pair, size_t maxSize);
static size_t getLocalKeyPairSize(uint16_t id);
static void removeLocalKeyPair(uint16_t id);
static bool setRemotePublicKey void begin();
(uint16_t id, const void *key, size_t size); void begin(const void *key, size_t size);
static size_t getRemotePublicKey void begin(const char *passphrase);
(uint16_t id, void *key, size_t maxSize); void end();
static size_t getRemotePublicKeySize(uint16_t id);
static void removeRemotePublicKey(uint16_t id);
static bool setSharedSymmetricKey bool setLocalKeyPair(uint16_t id, const void *pair, size_t size);
(uint16_t id, const void *key, size_t size); size_t getLocalKeyPair(uint16_t id, void *pair, size_t maxSize);
static size_t getSharedSymmetricKey size_t getLocalKeyPairSize(uint16_t id);
(uint16_t id, void *key, size_t maxSize); void removeLocalKeyPair(uint16_t id);
static size_t getSharedSymmetricKeySize(uint16_t id);
static void removeSharedSymmetricKey(uint16_t id);
static bool setOtherData bool setRemotePublicKey(uint16_t id, const void *key, size_t size);
(uint16_t id, const void *data, size_t size); size_t getRemotePublicKey(uint16_t id, void *key, size_t maxSize);
static size_t getOtherData size_t getRemotePublicKeySize(uint16_t id);
(uint16_t id, void *data, size_t maxSize); void removeRemotePublicKey(uint16_t id);
static size_t getOtherDataSize(uint16_t id);
static void removeOtherData(uint16_t id); bool setSharedSymmetricKey(uint16_t id, const void *key, size_t size);
size_t getSharedSymmetricKey(uint16_t id, void *key, size_t maxSize);
size_t getSharedSymmetricKeySize(uint16_t id);
void removeSharedSymmetricKey(uint16_t id);
bool setOtherData(uint16_t id, const void *data, size_t size);
size_t getOtherData(uint16_t id, void *data, size_t maxSize);
size_t getOtherDataSize(uint16_t id);
void removeOtherData(uint16_t id);
void removeAll();
static const uint16_t LocalCurve25519Default = 0x4301; // 'C', 0x01 static const uint16_t LocalCurve25519Default = 0x4301; // 'C', 0x01
static const uint16_t RemoteCurve25519Default = 0x6301; // 'c', 0x01 static const uint16_t RemoteCurve25519Default = 0x6301; // 'c', 0x01
@ -68,96 +66,117 @@ public:
static const uint16_t RemoteEd25519Default = 0x6501; // 'e', 0x01 static const uint16_t RemoteEd25519Default = 0x6501; // 'e', 0x01
private: private:
static bool set(uint16_t id, uint8_t type, const void *data, size_t size); static const size_t ChunkSize = 36;
static size_t get(uint16_t id, uint8_t type, void *data, size_t maxSize);
static size_t getSize(uint16_t id, uint8_t type); uint8_t k[16];
static void remove(uint16_t id, uint8_t type);
void (*crypt)(uint8_t k[16], uint8_t chunk[ChunkSize],
unsigned posn, bool encrypt);
bool set(uint16_t id, uint8_t type, const void *data, size_t size);
size_t get(uint16_t id, uint8_t type, void *data, size_t maxSize);
size_t getSize(uint16_t id, uint8_t type);
void remove(uint16_t id, uint8_t type);
void readStart(unsigned &posn);
bool readChunk(unsigned &posn, uint8_t chunk[ChunkSize], unsigned &actual);
bool readChunk
(unsigned &posn, uint8_t chunk[ChunkSize], uint16_t id,
uint8_t type, bool setMode, bool decrypt);
bool writeChunk(unsigned posn, uint8_t chunk[ChunkSize]);
bool writeExtraChunk(unsigned& posn, uint8_t chunk[ChunkSize]);
bool eraseChunk(unsigned &posn);
void readWriteEnd();
}; };
inline bool KeyRing::setLocalKeyPair extern KeyRingClass KeyRing;
inline bool KeyRingClass::setLocalKeyPair
(uint16_t id, const void *pair, size_t size) (uint16_t id, const void *pair, size_t size)
{ {
return set(id, 0, pair, size); return set(id, 0, pair, size);
} }
inline size_t KeyRing::getLocalKeyPair inline size_t KeyRingClass::getLocalKeyPair
(uint16_t id, void *pair, size_t maxSize) (uint16_t id, void *pair, size_t maxSize)
{ {
return get(id, 0, pair, maxSize); return get(id, 0, pair, maxSize);
} }
inline size_t KeyRing::getLocalKeyPairSize(uint16_t id) inline size_t KeyRingClass::getLocalKeyPairSize(uint16_t id)
{ {
return getSize(id, 0); return getSize(id, 0);
} }
inline void KeyRing::removeLocalKeyPair(uint16_t id) inline void KeyRingClass::removeLocalKeyPair(uint16_t id)
{ {
remove(id, 0); remove(id, 0);
} }
inline bool KeyRing::setRemotePublicKey inline bool KeyRingClass::setRemotePublicKey
(uint16_t id, const void *key, size_t size) (uint16_t id, const void *key, size_t size)
{ {
return set(id, 1, key, size); return set(id, 1, key, size);
} }
inline size_t KeyRing::getRemotePublicKey inline size_t KeyRingClass::getRemotePublicKey
(uint16_t id, void *key, size_t maxSize) (uint16_t id, void *key, size_t maxSize)
{ {
return get(id, 1, key, maxSize); return get(id, 1, key, maxSize);
} }
inline size_t KeyRing::getRemotePublicKeySize(uint16_t id) inline size_t KeyRingClass::getRemotePublicKeySize(uint16_t id)
{ {
return getSize(id, 1); return getSize(id, 1);
} }
inline void KeyRing::removeRemotePublicKey(uint16_t id) inline void KeyRingClass::removeRemotePublicKey(uint16_t id)
{ {
remove(id, 1); remove(id, 1);
} }
inline bool KeyRing::setSharedSymmetricKey inline bool KeyRingClass::setSharedSymmetricKey
(uint16_t id, const void *key, size_t size) (uint16_t id, const void *key, size_t size)
{ {
return set(id, 2, key, size); return set(id, 2, key, size);
} }
inline size_t KeyRing::getSharedSymmetricKey inline size_t KeyRingClass::getSharedSymmetricKey
(uint16_t id, void *key, size_t maxSize) (uint16_t id, void *key, size_t maxSize)
{ {
return get(id, 2, key, maxSize); return get(id, 2, key, maxSize);
} }
inline size_t KeyRing::getSharedSymmetricKeySize(uint16_t id) inline size_t KeyRingClass::getSharedSymmetricKeySize(uint16_t id)
{ {
return getSize(id, 2); return getSize(id, 2);
} }
inline void KeyRing::removeSharedSymmetricKey(uint16_t id) inline void KeyRingClass::removeSharedSymmetricKey(uint16_t id)
{ {
remove(id, 2); remove(id, 2);
} }
inline bool KeyRing::setOtherData inline bool KeyRingClass::setOtherData
(uint16_t id, const void *data, size_t size) (uint16_t id, const void *data, size_t size)
{ {
return set(id, 3, data, size); return set(id, 3, data, size);
} }
inline size_t KeyRing::getOtherData inline size_t KeyRingClass::getOtherData
(uint16_t id, void *data, size_t maxSize) (uint16_t id, void *data, size_t maxSize)
{ {
return get(id, 3, data, maxSize); return get(id, 3, data, maxSize);
} }
inline size_t KeyRing::getOtherDataSize(uint16_t id) inline size_t KeyRingClass::getOtherDataSize(uint16_t id)
{ {
return getSize(id, 3); return getSize(id, 3);
} }
inline void KeyRing::removeOtherData(uint16_t id) inline void KeyRingClass::removeOtherData(uint16_t id)
{ {
remove(id, 3); remove(id, 3);
} }

View File

@ -300,30 +300,7 @@ RNGClass::~RNGClass()
#if defined(RNG_DUE_TRNG) #if defined(RNG_DUE_TRNG)
// Find the flash memory of interest. Allow for the possibility #include "utility/SamFlashUtil.h"
// of other SAM-based Arduino variants in the future.
#if defined(IFLASH1_ADDR)
#define RNG_FLASH_ADDR IFLASH1_ADDR
#define RNG_FLASH_SIZE IFLASH1_SIZE
#define RNG_FLASH_PAGE_SIZE IFLASH1_PAGE_SIZE
#define RNG_EFC EFC1
#elif defined(IFLASH0_ADDR)
#define RNG_FLASH_ADDR IFLASH0_ADDR
#define RNG_FLASH_SIZE IFLASH0_SIZE
#define RNG_FLASH_PAGE_SIZE IFLASH0_PAGE_SIZE
#define RNG_EFC EFC0
#else
#define RNG_FLASH_ADDR IFLASH_ADDR
#define RNG_FLASH_SIZE IFLASH_SIZE
#define RNG_FLASH_PAGE_SIZE IFLASH_PAGE_SIZE
#define RNG_EFC EFC
#endif
// Address of the flash page to use for saving the seed on the Due.
// All SAM variants have a page size of 256 bytes or greater so there is
// plenty of room for the 48 byte seed in the last page of flash memory.
#define RNG_SEED_ADDR (RNG_FLASH_ADDR + RNG_FLASH_SIZE - RNG_FLASH_PAGE_SIZE)
#define RNG_SEED_PAGE ((RNG_FLASH_SIZE / RNG_FLASH_PAGE_SIZE) - 1)
// Stir in the unique identifier for the Arduino Due's CPU. // Stir in the unique identifier for the Arduino Due's CPU.
// This function must be in RAM because programs running out of // This function must be in RAM because programs running out of
@ -335,38 +312,25 @@ static void stirUniqueIdentifier(void)
uint32_t id[4]; uint32_t id[4];
// Start Read Unique Identifier. // Start Read Unique Identifier.
RNG_EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI; SAM_EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) != 0) while ((SAM_EFC->EEFC_FSR & EEFC_FSR_FRDY) != 0)
; // do nothing until FRDY falls. ; // do nothing until FRDY falls.
// Read the identifier. // Read the identifier.
id[0] = *((const uint32_t *)RNG_FLASH_ADDR); id[0] = *((const uint32_t *)SAM_FLASH_ADDR);
id[1] = *((const uint32_t *)(RNG_FLASH_ADDR + 4)); id[1] = *((const uint32_t *)(SAM_FLASH_ADDR + 4));
id[2] = *((const uint32_t *)(RNG_FLASH_ADDR + 8)); id[2] = *((const uint32_t *)(SAM_FLASH_ADDR + 8));
id[3] = *((const uint32_t *)(RNG_FLASH_ADDR + 12)); id[3] = *((const uint32_t *)(SAM_FLASH_ADDR + 12));
// Stop Read Unique Identifier. // Stop Read Unique Identifier.
RNG_EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI; SAM_EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI;
while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0) while ((SAM_EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
; // do nothing until FRDY rises. ; // do nothing until FRDY rises.
// Stir the unique identifier into the entropy pool. // Stir the unique identifier into the entropy pool.
RNG.stir((uint8_t *)id, sizeof(id)); RNG.stir((uint8_t *)id, sizeof(id));
} }
// Erases the flash page containing the seed and then writes the new seed.
// It is assumed the seed has already been loaded into the latch registers.
__attribute__((section(".ramfunc")))
static void eraseAndWriteSeed()
{
// Execute the "Erase and Write Page" command.
RNG_EFC->EEFC_FCR = (0x5A << 24) | (RNG_SEED_PAGE << 8) | EFC_FCMD_EWP;
// Wait for the FRDY bit to be raised.
while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
; // do nothing until FRDY rises.
}
#endif #endif
/** /**
@ -775,12 +739,15 @@ void RNGClass::save()
crypto_crc8('S', stream, SEED_SIZE - 1)); crypto_crc8('S', stream, SEED_SIZE - 1));
#elif defined(RNG_DUE_TRNG) #elif defined(RNG_DUE_TRNG)
unsigned posn; unsigned posn;
crypto_sam_flash_init();
crypto_sam_unlock_page(RNG_SEED_PAGE);
((uint32_t *)(RNG_SEED_ADDR))[0] = crypto_crc8('S', stream, SEED_SIZE); ((uint32_t *)(RNG_SEED_ADDR))[0] = crypto_crc8('S', stream, SEED_SIZE);
for (posn = 0; posn < 12; ++posn) for (posn = 0; posn < 12; ++posn)
((uint32_t *)(RNG_SEED_ADDR))[posn + 1] = stream[posn]; ((uint32_t *)(RNG_SEED_ADDR))[posn + 1] = stream[posn];
for (posn = 13; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn) for (posn = 13; posn < (SAM_FLASH_PAGE_SIZE / 4); ++posn)
((uint32_t *)(RNG_SEED_ADDR))[posn + 13] = 0xFFFFFFFF; ((uint32_t *)(RNG_SEED_ADDR))[posn + 13] = 0xFFFFFFFF;
eraseAndWriteSeed(); crypto_sam_erase_and_write(RNG_SEED_PAGE);
crypto_sam_lock_page(RNG_SEED_PAGE);
#elif defined(RNG_ESP_NVS) #elif defined(RNG_ESP_NVS)
// Save the seed into ESP non-volatile storage (NVS). // Save the seed into ESP non-volatile storage (NVS).
nvs_handle handle = 0; nvs_handle handle = 0;
@ -920,9 +887,12 @@ void RNGClass::destroy()
for (int posn = 0; posn < SEED_SIZE; ++posn) for (int posn = 0; posn < SEED_SIZE; ++posn)
eeprom_write_byte((uint8_t *)(address + posn), 0xFF); eeprom_write_byte((uint8_t *)(address + posn), 0xFF);
#elif defined(RNG_DUE_TRNG) #elif defined(RNG_DUE_TRNG)
for (unsigned posn = 0; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn) crypto_sam_flash_init();
crypto_sam_unlock_page(RNG_SEED_PAGE);
for (unsigned posn = 0; posn < (SAM_FLASH_PAGE_SIZE / 4); ++posn)
((uint32_t *)(RNG_SEED_ADDR))[posn] = 0xFFFFFFFF; ((uint32_t *)(RNG_SEED_ADDR))[posn] = 0xFFFFFFFF;
eraseAndWriteSeed(); crypto_sam_erase_and_write(RNG_SEED_PAGE);
crypto_sam_lock_page(RNG_SEED_PAGE);
#elif defined(RNG_ESP_NVS) #elif defined(RNG_ESP_NVS)
nvs_handle handle = 0; nvs_handle handle = 0;
if (nvs_open("rng", NVS_READWRITE, &handle) == 0) { if (nvs_open("rng", NVS_READWRITE, &handle) == 0) {

View File

@ -0,0 +1,206 @@
/*
* 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.
*/
/*
This example runs tests on the KeyRing class.
*/
#include <Crypto.h>
#include <KeyRing.h>
#include <string.h>
uint8_t const testKey1[32] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20
};
uint8_t const testKey2[64] = {
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60,
0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80
};
uint8_t buffer[128];
void verifyKey(const char *name, uint16_t id, const void *expected, size_t len,
const void *actual, size_t size, size_t size2)
{
if (expected) {
if (size == len) {
if (memcmp(actual, expected, len) != 0) {
Serial.print(name);
Serial.println(" failed: wrong value returned");
}
} else {
Serial.print(name);
Serial.println(" failed: wrong size returned");
}
} else {
if (size != 0) {
Serial.print(name);
Serial.println(" failed: value returned when none expected");
}
}
if (size2 != len) {
Serial.print(name);
Serial.println(" failed: incorrect size report");
}
}
#define verifyLocalKeyPair(name,id,expected,len) \
do { \
memset(buffer, 0, sizeof(buffer)); \
size_t size = KeyRing.getLocalKeyPair(id, buffer, sizeof(buffer)); \
size_t size2 = KeyRing.getLocalKeyPairSize(id); \
verifyKey((name), (id), (expected), (len), buffer, size, size2); \
} while (0)
#define verifyRemotePublicKey(name,id,expected,len) \
do { \
memset(buffer, 0, sizeof(buffer)); \
size_t size = KeyRing.getRemotePublicKey(id, buffer, sizeof(buffer)); \
size_t size2 = KeyRing.getRemotePublicKeySize(id); \
verifyKey((name), (id), (expected), (len), buffer, size, size2); \
} while (0)
#define verifySharedSymmetricKey(name,id,expected,len) \
do { \
memset(buffer, 0, sizeof(buffer)); \
size_t size = KeyRing.getSharedSymmetricKey(id, buffer, sizeof(buffer)); \
size_t size2 = KeyRing.getSharedSymmetricKeySize(id); \
verifyKey((name), (id), (expected), (len), buffer, size, size2); \
} while (0)
#define verifyOtherData(name,id,expected,len) \
do { \
memset(buffer, 0, sizeof(buffer)); \
size_t size = KeyRing.getOtherData(id, buffer, sizeof(buffer)); \
size_t size2 = KeyRing.getOtherDataSize(id); \
verifyKey((name), (id), (expected), (len), buffer, size, size2); \
} while (0)
void runAllTests()
{
Serial.println("Writing keys ...");
KeyRing.setLocalKeyPair(1, testKey1, 32);
KeyRing.setLocalKeyPair(2, testKey2, 64);
KeyRing.setRemotePublicKey(2, testKey2, 48);
KeyRing.setRemotePublicKey(0xABCD, testKey1, 27);
KeyRing.setSharedSymmetricKey(0xFFFF, testKey1, sizeof(testKey1));
KeyRing.setSharedSymmetricKey(3, testKey2, 1);
KeyRing.setOtherData(1, testKey1, 15);
KeyRing.setOtherData(2, testKey2, 33);
Serial.println("Verifying keys ...");
verifyLocalKeyPair("local #1", 1, testKey1, 32);
verifyLocalKeyPair("local #2", 2, testKey2, 64);
verifyLocalKeyPair("local #3", 0xABCD, 0, 0);
verifyRemotePublicKey("remote #1", 2, testKey2, 48);
verifyRemotePublicKey("remote #2", 0xABCD, testKey1, 27);
verifyRemotePublicKey("remote #3", 1, 0, 0);
verifySharedSymmetricKey("shared #1", 0xFFFF, testKey1, sizeof(testKey1));
verifySharedSymmetricKey("shared #2", 3, testKey2, 1);
verifySharedSymmetricKey("shared #3", 0xABCD, 0, 0);
verifyOtherData("other #1", 1, testKey1, 15);
verifyOtherData("other #2", 2, testKey2, 33);
Serial.println("Removing some keys ...");
KeyRing.removeLocalKeyPair(1);
KeyRing.removeRemotePublicKey(2);
KeyRing.removeSharedSymmetricKey(2); // Not present, so not removed.
KeyRing.removeOtherData(1);
Serial.println("Verifying remaining keys ...");
verifyLocalKeyPair("local #1", 1, 0, 0);
verifyLocalKeyPair("local #2", 2, testKey2, 64);
verifyLocalKeyPair("local #3", 0xABCD, 0, 0);
verifyRemotePublicKey("remote #1", 2, 0, 0);
verifyRemotePublicKey("remote #2", 0xABCD, testKey1, 27);
verifyRemotePublicKey("remote #3", 1, 0, 0);
verifySharedSymmetricKey("shared #1", 0xFFFF, testKey1, sizeof(testKey1));
verifySharedSymmetricKey("shared #2", 3, testKey2, 1);
verifySharedSymmetricKey("shared #3", 0xABCD, 0, 0);
verifyOtherData("other #1", 1, 0, 0);
verifyOtherData("other #2", 2, testKey2, 33);
Serial.println("Removing all keys ...");
KeyRing.removeAll();
Serial.println("Verifying that no keys remain ...");
verifyLocalKeyPair("local #1", 1, 0, 0);
verifyLocalKeyPair("local #2", 2, 0, 0);
verifyLocalKeyPair("local #3", 0xABCD, 0, 0);
verifyRemotePublicKey("remote #1", 2, 0, 0);
verifyRemotePublicKey("remote #2", 0xABCD, 0, 0);
verifyRemotePublicKey("remote #3", 1, 0, 0);
verifySharedSymmetricKey("shared #1", 0xFFFF, 0, 0);
verifySharedSymmetricKey("shared #2", 3, 0, 0);
verifySharedSymmetricKey("shared #3", 0xABCD, 0, 0);
verifyOtherData("other #1", 1, 0, 0);
verifyOtherData("other #2", 2, 0, 0);
}
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println("No passphrase:");
KeyRing.begin();
runAllTests();
Serial.println();
Serial.println("With passphrase:");
KeyRing.begin("Hello World!");
runAllTests();
Serial.println();
Serial.println("Done");
}
void loop()
{
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (C) 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_SAMFLASHUTIL_H
#define CRYPTO_SAMFLASHUTIL_H
// Utility definitions for accessing flash memory in the
// Arduino Due and other SAM-based Arduino variants.
#if defined (__arm__) && defined (__SAM3X8E__)
#include <Arduino.h>
// Find the highest-numbered flash memory region on this device.
#if defined(IFLASH1_ADDR)
#define SAM_FLASH_ADDR IFLASH1_ADDR
#define SAM_FLASH_SIZE IFLASH1_SIZE
#define SAM_FLASH_PAGE_SIZE IFLASH1_PAGE_SIZE
#define SAM_FLASH_REGION_SIZE IFLASH1_LOCK_REGION_SIZE
#define SAM_EFC EFC1
#elif defined(IFLASH0_ADDR)
#define SAM_FLASH_ADDR IFLASH0_ADDR
#define SAM_FLASH_SIZE IFLASH0_SIZE
#define SAM_FLASH_PAGE_SIZE IFLASH0_PAGE_SIZE
#define SAM_FLASH_REGION_SIZE IFLASH0_LOCK_REGION_SIZE
#define SAM_EFC EFC0
#else
#define SAM_FLASH_ADDR IFLASH_ADDR
#define SAM_FLASH_SIZE IFLASH_SIZE
#define SAM_FLASH_PAGE_SIZE IFLASH_PAGE_SIZE
#define SAM_FLASH_REGION_SIZE IFLASH_LOCK_REGION_SIZE
#define SAM_EFC EFC
#endif
// Storage for the RNG seed in the last page of flash memory.
#define RNG_SEED_ADDR (SAM_FLASH_ADDR + SAM_FLASH_SIZE - SAM_FLASH_PAGE_SIZE)
#define RNG_SEED_PAGE ((SAM_FLASH_SIZE / SAM_FLASH_PAGE_SIZE) - 1)
// Storage for the KeyRing implementation.
#define KEY_RING_STORAGE_SIZE 4096
#define KEY_RING_STORAGE_ADDR \
(SAM_FLASH_ADDR + SAM_FLASH_SIZE - KEY_RING_STORAGE_SIZE - \
SAM_FLASH_PAGE_SIZE)
#define KEY_RING_STORAGE_NUM_PAGES \
(KEY_RING_STORAGE_SIZE / SAM_FLASH_PAGE_SIZE)
#define KEY_RING_STORAGE_FIRST_PAGE \
((SAM_FLASH_SIZE / SAM_FLASH_PAGE_SIZE) - KEY_RING_STORAGE_NUM_PAGES - 1)
// Initialize the device for write access to flash memory.
inline void crypto_sam_flash_init(void)
{
// Initialize the flash memory chip for access mode 128 and 6 wait states.
efc_init(SAM_EFC, EFC_ACCESS_MODE_128, 6);
}
// Erase and write a specific page. It is assumed that the data
// to write has already been loaded into the latch registers.
inline void crypto_sam_erase_and_write(unsigned page)
{
// Erase the page and write its new contents.
efc_perform_command(SAM_EFC, EFC_FCMD_EWP, page);
}
// Unlock the memory region containing a page.
inline void crypto_sam_unlock_page(unsigned page)
{
unsigned pagesPerRegion = SAM_FLASH_REGION_SIZE / SAM_FLASH_PAGE_SIZE;
unsigned region = page - (page % pagesPerRegion);
efc_perform_command(SAM_EFC, EFC_FCMD_CLB, region);
}
// Lock the memory region containing a page.
inline void crypto_sam_lock_page(unsigned page)
{
unsigned pagesPerRegion = SAM_FLASH_REGION_SIZE / SAM_FLASH_PAGE_SIZE;
unsigned region = page - (page % pagesPerRegion);
efc_perform_command(SAM_EFC, EFC_FCMD_SLB, region);
}
#endif
#endif