From a7f93de3ad62914d74bc172290934d60aa01dbe1 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 2 Jan 2021 18:20:51 +0800 Subject: [PATCH] add a software based cross platform AES-CTR implementation --- platformio.ini | 3 + src/portduino/CrossPlatformCryptoEngine.cpp | 82 +++++++++++++++++++++ src/portduino/PortduinoGlue.cpp | 3 - 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 src/portduino/CrossPlatformCryptoEngine.cpp diff --git a/platformio.ini b/platformio.ini index aa8e3eb8..977d2cd5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -314,6 +314,9 @@ src_filter = ${env.src_filter} - - - - build_flags = ${arduino_base.build_flags} -O0 framework = arduino board = linux_x86_64 +lib_deps = + ${arduino_base.lib_deps} + rweather/Crypto ; The GenieBlocks LORA prototype board [env:genieblocks_lora] diff --git a/src/portduino/CrossPlatformCryptoEngine.cpp b/src/portduino/CrossPlatformCryptoEngine.cpp new file mode 100644 index 00000000..b9e818c0 --- /dev/null +++ b/src/portduino/CrossPlatformCryptoEngine.cpp @@ -0,0 +1,82 @@ +#include "AES.h" +#include "CTR.h" +#include "CryptoEngine.h" +#include "configuration.h" + +/** A platform independent AES engine implemented using Tiny-AES + */ +class CrossPlatformCryptoEngine : public CryptoEngine +{ + + CTRCommon *ctr = NULL; + + /// How many bytes in our key + uint8_t keySize = 0; + + public: + CrossPlatformCryptoEngine() {} + + ~CrossPlatformCryptoEngine() {} + + /** + * Set the key used for encrypt, decrypt. + * + * As a special case: If all bytes are zero, we assume _no encryption_ and send all data in cleartext. + * + * @param numBytes must be 16 (AES128), 32 (AES256) or 0 (no crypt) + * @param bytes a _static_ buffer that will remain valid for the life of this crypto instance (i.e. this class will cache the + * provided pointer) + */ + virtual void setKey(size_t numBytes, uint8_t *bytes) + { + keySize = numBytes; + DEBUG_MSG("Installing AES%d key!\n", numBytes * 8); + if (ctr) { + delete ctr; + ctr = NULL; + } + if (numBytes != 0) { + if (numBytes == 16) + ctr = new CTR(); + else + ctr = new CTR(); + + ctr->setKey(bytes, numBytes); + } + } + + /** + * Encrypt a packet + * + * @param bytes is updated in place + */ + virtual void encrypt(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes) + { + if (keySize != 0) { + uint8_t stream_block[16]; + static uint8_t scratch[MAX_BLOCKSIZE]; + size_t nc_off = 0; + + // DEBUG_MSG("ESP32 encrypt!\n"); + initNonce(fromNode, packetNum); + assert(numBytes <= MAX_BLOCKSIZE); + memcpy(scratch, bytes, numBytes); + memset(scratch + numBytes, 0, + sizeof(scratch) - numBytes); // Fill rest of buffer with zero (in case cypher looks at it) + + ctr->setIV(nonce, sizeof(nonce)); + ctr->setCounterSize(4); + ctr->encrypt(bytes, scratch, numBytes); + } + } + + virtual void decrypt(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes) + { + // For CTR, the implementation is the same + encrypt(fromNode, packetNum, numBytes, bytes); + } + + private: +}; + +CryptoEngine *crypto = new CrossPlatformCryptoEngine(); diff --git a/src/portduino/PortduinoGlue.cpp b/src/portduino/PortduinoGlue.cpp index 6af00666..2d5f0a36 100644 --- a/src/portduino/PortduinoGlue.cpp +++ b/src/portduino/PortduinoGlue.cpp @@ -35,9 +35,6 @@ void cpuDeepSleep(uint64_t msecs) { notImplemented("cpuDeepSleep"); } -// FIXME - implement real crypto for linux -CryptoEngine *crypto = new CryptoEngine(); - void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel"); /** Dear pinetab hardware geeks!