From e2420adfc51c0506606c7983a3a639e384d5131d Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 2 Apr 2018 15:02:42 +1000 Subject: [PATCH] Port the crypto library to ESP32 --- libraries/Crypto/RNG.cpp | 77 ++++++++++++++++--- .../examples/TestBLAKE2b/TestBLAKE2b.ino | 2 +- .../examples/TestBLAKE2s/TestBLAKE2s.ino | 2 +- .../Crypto/examples/TestChaCha/TestChaCha.ino | 2 +- .../TestChaChaPoly/TestChaChaPoly.ino | 2 +- libraries/Crypto/examples/TestEAX/TestEAX.ino | 4 +- libraries/Crypto/examples/TestGCM/TestGCM.ino | 2 +- .../Crypto/examples/TestP521/TestP521.ino | 2 +- libraries/Crypto/examples/TestXTS/TestXTS.ino | 2 +- libraries/Crypto/utility/ProgMemUtil.h | 2 +- 10 files changed, 76 insertions(+), 21 deletions(-) diff --git a/libraries/Crypto/RNG.cpp b/libraries/Crypto/RNG.cpp index 6ac56196..3a34bbba 100644 --- a/libraries/Crypto/RNG.cpp +++ b/libraries/Crypto/RNG.cpp @@ -41,11 +41,28 @@ // ESP8266 does not have EEPROM but it does have SPI flash memory. // It also has a TRNG register for generating "true" random numbers. // For now we use the TRNG but don't save the seed in flash memory. -#define RNG_ESP8266 1 -#define RNG_ESP8266_GET_TRNG() (ESP8266_DREG(0x20E44)) +#define RNG_WORD_TRNG 1 +#define RNG_WORD_TRNG_GET() (ESP8266_DREG(0x20E44)) +#elif defined(ESP32) +// ESP32 has a word-based TRNG and an API for Non-Volatile Storage (NVS). +#define RNG_WORD_TRNG 1 +#define RNG_WORD_TRNG_GET() (esp_random()) +#define RNG_ESP_NVS 1 +#include #endif #include +// Throw an error if there is no built-in hardware random number source. +// If this happens, then you need to do one of two things: +// 1. Edit RNG.cpp to add your platform's hardware TRNG. +// 2. Provide a proper noise source like TransistorNoiseSource +// in your sketch and then comment out the #error line below. +#if !defined(RNG_DUE_TRNG) && \ + !defined(RNG_WATCHDOG) && \ + !defined(RNG_WORD_TRNG) +#error "no hardware random number source detected for this platform" +#endif + /** * \class RNGClass RNG.h * \brief Pseudo random number generator suitable for cryptography. @@ -400,8 +417,25 @@ void RNGClass::begin(const char *tag) REG_TRNG_CR = TRNG_CR_KEY(0x524E47) | TRNG_CR_ENABLE; REG_TRNG_IDR = TRNG_IDR_DATRDY; // Disable interrupts - we will poll. mixTRNG(); -#elif defined(RNG_ESP8266) - // Mix in some output from the ESP8266's TRNG to initialize the state. +#endif +#if defined(RNG_ESP_NVS) + // Do we have a seed saved in ESP non-volatile storage (NVS)? + nvs_handle handle = 0; + if (nvs_open("rng", NVS_READONLY, &handle) == 0) { + size_t len = 0; + if (nvs_get_blob(handle, "seed", NULL, &len) == 0 && len == SEED_SIZE) { + uint32_t seed[12]; + if (nvs_get_blob(handle, "seed", seed, &len) == 0) { + for (int posn = 0; posn < 12; ++posn) + block[posn + 4] ^= seed[posn]; + } + clean(seed); + } + nvs_close(handle); + } +#endif +#if defined(RNG_WORD_TRNG) + // Mix in some output from a word-based TRNG to initialize the state. mixTRNG(); #endif @@ -422,13 +456,17 @@ void RNGClass::begin(const char *tag) // Stir in the unique identifier for the CPU so that different // devices will give different outputs even without seeding. stirUniqueIdentifier(); -#elif defined(RNG_ESP8266) +#elif defined(ESP8266) // ESP8266's have a 32-bit CPU chip ID and 32-bit flash chip ID // that we can use as a device unique identifier. uint32_t ids[2]; ids[0] = ESP.getChipId(); ids[1] = ESP.getFlashChipId(); stir((const uint8_t *)ids, sizeof(ids)); +#elif defined(ESP32) + // ESP32's have a MAC address that can be used as a device identifier. + uint64_t mac = ESP.getEfuseMac(); + stir((const uint8_t *)&mac, sizeof(mac)); #else // AVR devices don't have anything like a serial number so it is // difficult to make every device unique. Use the compilation @@ -743,6 +781,15 @@ void RNGClass::save() for (posn = 13; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn) ((uint32_t *)(RNG_SEED_ADDR))[posn + 13] = 0xFFFFFFFF; eraseAndWriteSeed(); +#elif defined(RNG_ESP_NVS) + // Save the seed into ESP non-volatile storage (NVS). + nvs_handle handle = 0; + if (nvs_open("rng", NVS_READWRITE, &handle) == 0) { + nvs_erase_all(handle); + nvs_set_blob(handle, "seed", stream, SEED_SIZE); + nvs_commit(handle); + nvs_close(handle); + } #endif rekey(); timer = millis(); @@ -792,9 +839,9 @@ void RNGClass::loop() } trngPending = 1; } -#elif defined(RNG_ESP8266) - // Read a word from the ESP8266's TRNG and XOR it into the state. - block[4 + trngPosn] ^= RNG_ESP8266_GET_TRNG(); +#elif defined(RNG_WORD_TRNG) + // Read a word from the TRNG and XOR it into the state. + block[4 + trngPosn] ^= RNG_WORD_TRNG_GET(); if (++trngPosn >= 12) trngPosn = 0; if (credits < RNG_MAX_CREDITS) { @@ -876,7 +923,15 @@ void RNGClass::destroy() for (unsigned posn = 0; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn) ((uint32_t *)(RNG_SEED_ADDR))[posn] = 0xFFFFFFFF; eraseAndWriteSeed(); +#elif defined(RNG_ESP_NVS) + nvs_handle handle = 0; + if (nvs_open("rng", NVS_READWRITE, &handle) == 0) { + nvs_erase_all(handle); + nvs_commit(handle); + nvs_close(handle); + } #endif + initialized = 0; } /** @@ -921,10 +976,10 @@ void RNGClass::mixTRNG() break; block[posn + 4] ^= REG_TRNG_ODATA; } -#elif defined(RNG_ESP8266) - // Read 12 words from the ESP8266's TRNG and XOR them into the state. +#elif defined(RNG_WORD_TRNG) + // Read 12 words from the TRNG and XOR them into the state. for (uint8_t index = 4; index < 16; ++index) - block[index] ^= RNG_ESP8266_GET_TRNG(); + block[index] ^= RNG_WORD_TRNG_GET(); #elif defined(RNG_WATCHDOG) // Read the pending 32 bit buffer from the WDT interrupt and mix it in. cli(); diff --git a/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino b/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino index 4f1177c1..28daa00d 100644 --- a/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino +++ b/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino @@ -27,7 +27,7 @@ This example runs tests on the BLAKE2b implementation to verify correct behaviou #include #include #include -#if defined(ESP8266) +#if defined(ESP8266) || defined(ESP32) #include #else #include diff --git a/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino b/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino index a655832a..65ec25f2 100644 --- a/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino +++ b/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino @@ -27,7 +27,7 @@ This example runs tests on the BLAKE2s implementation to verify correct behaviou #include #include #include -#if defined(ESP8266) +#if defined(ESP8266) || defined(ESP32) #include #else #include diff --git a/libraries/Crypto/examples/TestChaCha/TestChaCha.ino b/libraries/Crypto/examples/TestChaCha/TestChaCha.ino index 774bfd27..7101f97e 100644 --- a/libraries/Crypto/examples/TestChaCha/TestChaCha.ino +++ b/libraries/Crypto/examples/TestChaCha/TestChaCha.ino @@ -27,7 +27,7 @@ This example runs tests on the ChaCha implementation to verify correct behaviour #include #include #include -#if defined(ESP8266) +#if defined(ESP8266) || defined(ESP32) #include #else #include diff --git a/libraries/Crypto/examples/TestChaChaPoly/TestChaChaPoly.ino b/libraries/Crypto/examples/TestChaChaPoly/TestChaChaPoly.ino index 6cdf7d34..41fbe9cd 100644 --- a/libraries/Crypto/examples/TestChaChaPoly/TestChaChaPoly.ino +++ b/libraries/Crypto/examples/TestChaChaPoly/TestChaChaPoly.ino @@ -28,7 +28,7 @@ correct behaviour. #include #include #include -#if defined(ESP8266) +#if defined(ESP8266) || defined(ESP32) #include #else #include diff --git a/libraries/Crypto/examples/TestEAX/TestEAX.ino b/libraries/Crypto/examples/TestEAX/TestEAX.ino index 9b2e29ca..e33191bc 100644 --- a/libraries/Crypto/examples/TestEAX/TestEAX.ino +++ b/libraries/Crypto/examples/TestEAX/TestEAX.ino @@ -30,7 +30,7 @@ This example runs tests on the EAX implementation to verify correct behaviour. #include #include #include -#if defined(ESP8266) +#if defined(ESP8266) || defined(ESP32) #include #else #include @@ -540,7 +540,7 @@ void setup() Serial.println(); delete eax; eax256 = new EAX(); - perfCipher(eax, &testVectorEAX1, "AES-256"); + perfCipher(eax256, &testVectorEAX1, "AES-256"); Serial.println(); delete eax256; eaxSpeck = new EAX(); diff --git a/libraries/Crypto/examples/TestGCM/TestGCM.ino b/libraries/Crypto/examples/TestGCM/TestGCM.ino index 7f04594f..a47bfd6a 100644 --- a/libraries/Crypto/examples/TestGCM/TestGCM.ino +++ b/libraries/Crypto/examples/TestGCM/TestGCM.ino @@ -30,7 +30,7 @@ This example runs tests on the GCM implementation to verify correct behaviour. #include #include #include -#if defined(ESP8266) +#if defined(ESP8266) || defined(ESP32) #include #else #include diff --git a/libraries/Crypto/examples/TestP521/TestP521.ino b/libraries/Crypto/examples/TestP521/TestP521.ino index b79d8c3b..6e50ade6 100644 --- a/libraries/Crypto/examples/TestP521/TestP521.ino +++ b/libraries/Crypto/examples/TestP521/TestP521.ino @@ -34,7 +34,7 @@ AVR platforms with 32K or less of flash memory. #include #include #include -#if defined(ESP8266) +#if defined(ESP8266) || defined(ESP32) #include #else #include diff --git a/libraries/Crypto/examples/TestXTS/TestXTS.ino b/libraries/Crypto/examples/TestXTS/TestXTS.ino index 765219ad..8ea04fec 100644 --- a/libraries/Crypto/examples/TestXTS/TestXTS.ino +++ b/libraries/Crypto/examples/TestXTS/TestXTS.ino @@ -31,7 +31,7 @@ This example runs tests on the XTS implementation to verify correct behaviour. #include #include #include -#if defined(ESP8266) +#if defined(ESP8266) || defined(ESP32) #include #else #include diff --git a/libraries/Crypto/utility/ProgMemUtil.h b/libraries/Crypto/utility/ProgMemUtil.h index 41126793..d7588e8a 100644 --- a/libraries/Crypto/utility/ProgMemUtil.h +++ b/libraries/Crypto/utility/ProgMemUtil.h @@ -31,7 +31,7 @@ ((uint64_t)pgm_read_dword(_temp)) | \ (((uint64_t)pgm_read_dword(_temp + 1)) << 32); \ })) -#elif defined(ESP8266) +#elif defined(ESP8266) || defined(ESP32) #include #define pgm_read_qword(x) \ (__extension__ ({ \