diff --git a/platformio.ini b/platformio.ini
index aa8e3eb84..977d2cd55 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 000000000..b9e818c0b
--- /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 6af006664..2d5f0a36c 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!