From 511cd8f77c9360a53c4cb3550baab046675629a0 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Sun, 1 Apr 2018 15:58:00 +1000 Subject: [PATCH] Make the Crypto examples work for ESP8266 --- libraries/Crypto/Crypto.h | 7 +++ libraries/Crypto/Curve25519.cpp | 1 + libraries/Crypto/P521.cpp | 1 + libraries/Crypto/examples/TestAES/TestAES.ino | 3 + .../examples/TestBLAKE2b/TestBLAKE2b.ino | 4 ++ .../examples/TestBLAKE2s/TestBLAKE2s.ino | 4 ++ .../Crypto/examples/TestChaCha/TestChaCha.ino | 4 ++ .../TestChaChaPoly/TestChaChaPoly.ino | 4 ++ libraries/Crypto/examples/TestEAX/TestEAX.ino | 16 ++++++ libraries/Crypto/examples/TestGCM/TestGCM.ino | 16 ++++++ .../Crypto/examples/TestP521/TestP521.ino | 4 ++ .../Crypto/examples/TestSpeck/TestSpeck.ino | 4 ++ libraries/Crypto/examples/TestXTS/TestXTS.ino | 14 +++++ libraries/NewHope/NewHope.cpp | 57 ++++++++++++++++--- .../examples/TestNewHope/TestNewHope.ino | 4 ++ 15 files changed, 135 insertions(+), 8 deletions(-) diff --git a/libraries/Crypto/Crypto.h b/libraries/Crypto/Crypto.h index 98d8d9fc..b780f257 100644 --- a/libraries/Crypto/Crypto.h +++ b/libraries/Crypto/Crypto.h @@ -36,4 +36,11 @@ inline void clean(T &var) 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 diff --git a/libraries/Crypto/Curve25519.cpp b/libraries/Crypto/Curve25519.cpp index 902ad1b8..84744f04 100644 --- a/libraries/Crypto/Curve25519.cpp +++ b/libraries/Crypto/Curve25519.cpp @@ -934,6 +934,7 @@ void Curve25519::mul(limb_t *result, const limb_t *x, const limb_t *y) mulNoReduce(temp, x, y); reduce(result, temp, NUM_LIMBS_256BIT); strict_clean(temp); + crypto_feed_watchdog(); } /** diff --git a/libraries/Crypto/P521.cpp b/libraries/Crypto/P521.cpp index a8c5e425..f46df3c0 100644 --- a/libraries/Crypto/P521.cpp +++ b/libraries/Crypto/P521.cpp @@ -965,6 +965,7 @@ void P521::mul(limb_t *result, const limb_t *x, const limb_t *y) mulNoReduce(temp, x, y); reduce(result, temp); strict_clean(temp); + crypto_feed_watchdog(); } /** diff --git a/libraries/Crypto/examples/TestAES/TestAES.ino b/libraries/Crypto/examples/TestAES/TestAES.ino index 6ff1ad5f..c63e331b 100644 --- a/libraries/Crypto/examples/TestAES/TestAES.ino +++ b/libraries/Crypto/examples/TestAES/TestAES.ino @@ -76,6 +76,7 @@ byte buffer[16]; void testCipher(BlockCipher *cipher, const struct TestVector *test) { + crypto_feed_watchdog(); Serial.print(test->name); Serial.print(" Encryption ... "); cipher->setKey(test->key, cipher->keySize()); @@ -100,6 +101,8 @@ void perfCipher(BlockCipher *cipher, const struct TestVector *test) unsigned long elapsed; int count; + crypto_feed_watchdog(); + Serial.print(test->name); Serial.print(" Set Key ... "); start = micros(); diff --git a/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino b/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino index 683bbc6a..4f1177c1 100644 --- a/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino +++ b/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino @@ -27,7 +27,11 @@ This example runs tests on the BLAKE2b implementation to verify correct behaviou #include #include #include +#if defined(ESP8266) +#include +#else #include +#endif #define HASH_SIZE 64 #define BLOCK_SIZE 128 diff --git a/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino b/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino index 153e9b35..a655832a 100644 --- a/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino +++ b/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino @@ -27,7 +27,11 @@ This example runs tests on the BLAKE2s implementation to verify correct behaviou #include #include #include +#if defined(ESP8266) +#include +#else #include +#endif #define HASH_SIZE 32 #define BLOCK_SIZE 64 diff --git a/libraries/Crypto/examples/TestChaCha/TestChaCha.ino b/libraries/Crypto/examples/TestChaCha/TestChaCha.ino index 177a2f69..774bfd27 100644 --- a/libraries/Crypto/examples/TestChaCha/TestChaCha.ino +++ b/libraries/Crypto/examples/TestChaCha/TestChaCha.ino @@ -27,7 +27,11 @@ This example runs tests on the ChaCha implementation to verify correct behaviour #include #include #include +#if defined(ESP8266) +#include +#else #include +#endif #define MAX_PLAINTEXT_SIZE 64 #define MAX_CIPHERTEXT_SIZE 64 diff --git a/libraries/Crypto/examples/TestChaChaPoly/TestChaChaPoly.ino b/libraries/Crypto/examples/TestChaChaPoly/TestChaChaPoly.ino index dea947f5..6cdf7d34 100644 --- a/libraries/Crypto/examples/TestChaChaPoly/TestChaChaPoly.ino +++ b/libraries/Crypto/examples/TestChaChaPoly/TestChaChaPoly.ino @@ -28,7 +28,11 @@ correct behaviour. #include #include #include +#if defined(ESP8266) +#include +#else #include +#endif #define MAX_PLAINTEXT_LEN 265 diff --git a/libraries/Crypto/examples/TestEAX/TestEAX.ino b/libraries/Crypto/examples/TestEAX/TestEAX.ino index 142fb44b..9b2e29ca 100644 --- a/libraries/Crypto/examples/TestEAX/TestEAX.ino +++ b/libraries/Crypto/examples/TestEAX/TestEAX.ino @@ -30,7 +30,11 @@ This example runs tests on the EAX implementation to verify correct behaviour. #include #include #include +#if defined(ESP8266) +#include +#else #include +#endif #define MAX_PLAINTEXT_LEN 64 @@ -244,6 +248,8 @@ bool testCipher_N(AuthenticatedCipher *cipher, const struct TestVector *test, si size_t posn, len; uint8_t tag[16]; + crypto_feed_watchdog(); + cipher->clear(); if (!cipher->setKey(test->key, 16)) { Serial.print("setKey "); @@ -344,6 +350,8 @@ void perfCipherSetKey(AuthenticatedCipher *cipher, const struct TestVector *test unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(TestVector)); test = &testVector; @@ -371,6 +379,8 @@ void perfCipherEncrypt(AuthenticatedCipher *cipher, const struct TestVector *tes unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(TestVector)); test = &testVector; @@ -399,6 +409,8 @@ void perfCipherDecrypt(AuthenticatedCipher *cipher, const struct TestVector *tes unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(TestVector)); test = &testVector; @@ -427,6 +439,8 @@ void perfCipherAddAuthData(AuthenticatedCipher *cipher, const struct TestVector unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(TestVector)); test = &testVector; @@ -456,6 +470,8 @@ void perfCipherComputeTag(AuthenticatedCipher *cipher, const struct TestVector * unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(TestVector)); test = &testVector; diff --git a/libraries/Crypto/examples/TestGCM/TestGCM.ino b/libraries/Crypto/examples/TestGCM/TestGCM.ino index bebf8c4a..7f04594f 100644 --- a/libraries/Crypto/examples/TestGCM/TestGCM.ino +++ b/libraries/Crypto/examples/TestGCM/TestGCM.ino @@ -30,7 +30,11 @@ This example runs tests on the GCM implementation to verify correct behaviour. #include #include #include +#if defined(ESP8266) +#include +#else #include +#endif // There isn't enough memory to test both AES and Speck on the Uno, // so disable Speck testing on AVR platforms unless explicitly enabled. @@ -270,6 +274,8 @@ bool testCipher_N(AuthenticatedCipher *cipher, const struct TestVector *test, si size_t posn, len; uint8_t tag[16]; + crypto_feed_watchdog(); + cipher->clear(); if (!cipher->setKey(test->key, cipher->keySize())) { Serial.print("setKey "); @@ -367,6 +373,8 @@ void perfCipherSetKey(AuthenticatedCipher *cipher, const struct TestVector *test unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(TestVector)); test = &testVector; @@ -392,6 +400,8 @@ void perfCipherEncrypt(AuthenticatedCipher *cipher, const struct TestVector *tes unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(TestVector)); test = &testVector; @@ -418,6 +428,8 @@ void perfCipherDecrypt(AuthenticatedCipher *cipher, const struct TestVector *tes unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(TestVector)); test = &testVector; @@ -444,6 +456,8 @@ void perfCipherAddAuthData(AuthenticatedCipher *cipher, const struct TestVector unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(TestVector)); test = &testVector; @@ -471,6 +485,8 @@ void perfCipherComputeTag(AuthenticatedCipher *cipher, const struct TestVector * unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(TestVector)); test = &testVector; diff --git a/libraries/Crypto/examples/TestP521/TestP521.ino b/libraries/Crypto/examples/TestP521/TestP521.ino index 20c03142..b79d8c3b 100644 --- a/libraries/Crypto/examples/TestP521/TestP521.ino +++ b/libraries/Crypto/examples/TestP521/TestP521.ino @@ -34,7 +34,11 @@ AVR platforms with 32K or less of flash memory. #include #include #include +#if defined(ESP8266) +#include +#else #include +#endif void printNumber(const char *name, const uint8_t *x, size_t len) { diff --git a/libraries/Crypto/examples/TestSpeck/TestSpeck.ino b/libraries/Crypto/examples/TestSpeck/TestSpeck.ino index d70d905e..bd64c84b 100644 --- a/libraries/Crypto/examples/TestSpeck/TestSpeck.ino +++ b/libraries/Crypto/examples/TestSpeck/TestSpeck.ino @@ -78,6 +78,8 @@ byte buffer[16]; void testCipher(BlockCipher *cipher, const struct TestVector *test, size_t keySize, bool decryption = true) { + crypto_feed_watchdog(); + Serial.print(test->name); Serial.print(" Encryption ... "); cipher->setKey(test->key, keySize); @@ -105,6 +107,8 @@ void perfCipher(BlockCipher *cipher, const struct TestVector *test, size_t keySi unsigned long elapsed; int count; + crypto_feed_watchdog(); + Serial.print(test->name); Serial.print(" Set Key ... "); start = micros(); diff --git a/libraries/Crypto/examples/TestXTS/TestXTS.ino b/libraries/Crypto/examples/TestXTS/TestXTS.ino index cad61064..765219ad 100644 --- a/libraries/Crypto/examples/TestXTS/TestXTS.ino +++ b/libraries/Crypto/examples/TestXTS/TestXTS.ino @@ -31,7 +31,11 @@ This example runs tests on the XTS implementation to verify correct behaviour. #include #include #include +#if defined(ESP8266) +#include +#else #include +#endif #define MAX_SECTOR_SIZE 64 @@ -207,6 +211,8 @@ void _printProgMem(const char *str) void testXTS(XTSCommon *cipher, const struct TestVector *test) { + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(testVector)); Serial.print(testVector.name); @@ -261,6 +267,8 @@ void perfEncrypt(const char *name, XTSCommon *cipher, const struct TestVector *t unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(testVector)); Serial.print(name); @@ -288,6 +296,8 @@ void perfDecrypt(const char *name, XTSCommon *cipher, const struct TestVector *t unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(testVector)); Serial.print(name); @@ -314,6 +324,8 @@ void perfSetKey(const char *name, XTSCommon *cipher, const struct TestVector *te unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(testVector)); Serial.print(name); @@ -337,6 +349,8 @@ void perfSetTweak(const char *name, XTSCommon *cipher, const struct TestVector * unsigned long elapsed; int count; + crypto_feed_watchdog(); + memcpy_P(&testVector, test, sizeof(testVector)); Serial.print(name); diff --git a/libraries/NewHope/NewHope.cpp b/libraries/NewHope/NewHope.cpp index 5e89b812..603bd58b 100644 --- a/libraries/NewHope/NewHope.cpp +++ b/libraries/NewHope/NewHope.cpp @@ -36,7 +36,10 @@ void *operator new(size_t size, void *ptr) return ptr; } -#if defined(__AVR__) +#if defined(ESP8266) +#include +#define table_read(name, index) (pgm_read_word(&((name)[(index)]))) +#elif defined(__AVR__) #include #define table_read(name, index) (pgm_read_word(&((name)[(index)]))) #else @@ -987,9 +990,17 @@ static void poly_getnoise(uint16_t *r, NewHopeChaChaState *chacha, unsigned char #define INIT_OBJ(type, name) \ type *name = new (state.name##_x) type -#if defined(__AVR__) +#if defined(ESP8266) +// If we try to put the state on the stack, then it causes a stack smash. +// Possibly a system stack size limitation. Allocate the NewHope state on +// the heap instead for ESP8266. +#define NEWHOPE_HEAP_STATE 1 +#define NEWHOPE_BYTE_ALIGNED 0 +#elif defined(__AVR__) +#define NEWHOPE_HEAP_STATE 0 #define NEWHOPE_BYTE_ALIGNED 1 #else +#define NEWHOPE_HEAP_STATE 0 #define NEWHOPE_BYTE_ALIGNED 0 #endif @@ -1021,7 +1032,7 @@ void NewHope::keygen(uint8_t send[NEWHOPE_SENDABYTES], NewHopePrivateKey &sk, // We also combine most of the state into a single union, which allows // us to overlap some of the larger objects and reuse the stack space // at different points within this function. - union { + typedef union { struct { uint16_t a[PARAM_N]; // Value of "a" as a "poly" object. uint16_t pk[PARAM_N]; // Value of "pk" as a "poly" object. @@ -1031,7 +1042,13 @@ void NewHope::keygen(uint8_t send[NEWHOPE_SENDABYTES], NewHopePrivateKey &sk, ALLOC_OBJ(SHAKE128, shake); // SHAKE128 object for poly_uniform(). }; ALLOC_OBJ(SHA3_256, sha3); // SHA3 object for hashing the seed. - } state; + } NewHopeKeygenState; +#if NEWHOPE_HEAP_STATE + NewHopeKeygenState *heapState = new NewHopeKeygenState(); + #define state (*heapState) +#else + NewHopeKeygenState state; +#endif // Hide the ChaCha state and the noise seed inside "send". #if NEWHOPE_BYTE_ALIGNED @@ -1087,6 +1104,10 @@ void NewHope::keygen(uint8_t send[NEWHOPE_SENDABYTES], NewHopePrivateKey &sk, #endif #undef noiseseed #undef chacha +#if NEWHOPE_HEAP_STATE + delete heapState; + #undef state +#endif } /** @@ -1202,7 +1223,7 @@ void NewHope::sharedb(uint8_t shared_key[NEWHOPE_SHAREDBYTES], // We also combine most of the state into a single union, which allows // us to overlap some of the larger objects and reuse the stack space // at different points within this function. - union { + typedef union { struct { uint16_t a[PARAM_N]; // Value of "a" as a "poly" object. uint16_t v[PARAM_N]; // Value of "v" as a "poly" object. @@ -1213,7 +1234,13 @@ void NewHope::sharedb(uint8_t shared_key[NEWHOPE_SHAREDBYTES], ALLOC_OBJ(SHAKE128, shake); // SHAKE128 object for poly_uniform(). }; ALLOC_OBJ(SHA3_256, sha3); // SHA3 object for hashing the result. - } state; + } NewHopeSharedBState; +#if NEWHOPE_HEAP_STATE + NewHopeSharedBState *heapState = new NewHopeSharedBState(); + #define state (*heapState) +#else + NewHopeSharedBState state; +#endif // Hide the ChaCha state and the noise seed inside "send". // Put them at the end of the "send" buffer in case "received" @@ -1274,6 +1301,10 @@ void NewHope::sharedb(uint8_t shared_key[NEWHOPE_SHAREDBYTES], #undef noiseseed #undef chacha #endif +#if NEWHOPE_HEAP_STATE + delete heapState; + #undef state +#endif } /** @@ -1296,7 +1327,7 @@ void NewHope::shareda(uint8_t shared_key[NEWHOPE_SHAREDBYTES], // We also combine most of the state into a single union, which allows // us to overlap some of the larger objects and reuse the stack space // at different points within this function. - union { + typedef union { struct { uint16_t v[PARAM_N]; // Value of "v" as a "poly" object. uint16_t bp[PARAM_N]; // Value of "bp" as a "poly" object. @@ -1306,7 +1337,13 @@ void NewHope::shareda(uint8_t shared_key[NEWHOPE_SHAREDBYTES], ALLOC_OBJ(NewHopeChaChaState, chacha); }; ALLOC_OBJ(SHA3_256, sha3); // SHA3 object for hashing the result. - } state; + } NewHopeSharedAState; +#if NEWHOPE_HEAP_STATE + NewHopeSharedAState *heapState = new NewHopeSharedAState(); + #define state (*heapState) +#else + NewHopeSharedAState state; +#endif #if NEWHOPE_SMALL_FOOTPRINT // Re-create the full private key for Alice from the seed. @@ -1333,4 +1370,8 @@ void NewHope::shareda(uint8_t shared_key[NEWHOPE_SHAREDBYTES], sha3->finalize(shared_key, 32); clean(&state, sizeof(state)); +#if NEWHOPE_HEAP_STATE + delete heapState; + #undef state +#endif } diff --git a/libraries/NewHope/examples/TestNewHope/TestNewHope.ino b/libraries/NewHope/examples/TestNewHope/TestNewHope.ino index 0c811593..1ac7dd74 100644 --- a/libraries/NewHope/examples/TestNewHope/TestNewHope.ino +++ b/libraries/NewHope/examples/TestNewHope/TestNewHope.ino @@ -28,10 +28,14 @@ This example runs tests on the NewHope class to verify correct behaviour. #include #include #include +#if defined(ESP8266) +#include +#else #include #if !defined(__AVR__) #define memcmp_P(a,b,c) memcmp((a), (b), (c)) #endif +#endif // Test vectors that were generated by the reference C implementation.