Refactor platform cryptography, add tests

This commit is contained in:
Jonathan Bennett
2024-08-10 22:38:05 -05:00
parent 192af05a25
commit c3aa56ef30
11 changed files with 88 additions and 276 deletions

View File

@@ -1,6 +1,7 @@
#include "CryptoEngine.h"
#include "NodeDB.h"
#include "RadioInterface.h"
#include "architecture.h"
#include "configuration.h"
#if !(MESHTASTIC_EXCLUDE_PKI)
@@ -188,14 +189,44 @@ void CryptoEngine::setKey(const CryptoKey &k)
*
* @param bytes is updated in place
*/
void CryptoEngine::encrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes)
void CryptoEngine::encryptPacket(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes)
{
LOG_WARN("noop encryption!\n");
if (key.length > 0) {
initNonce(fromNode, packetId);
if (numBytes <= MAX_BLOCKSIZE) {
encryptAESCtr(key, nonce, numBytes, bytes);
} else {
LOG_ERROR("Packet too large for crypto engine: %d. noop encryption!\n", numBytes);
}
}
}
void CryptoEngine::decrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes)
{
LOG_WARN("noop decryption!\n");
// For CTR, the implementation is the same
encryptPacket(fromNode, packetId, numBytes, bytes);
}
// Generic implementation of AES-CTR encryption.
void CryptoEngine::encryptAESCtr(CryptoKey _key, uint8_t *_nonce, size_t numBytes, uint8_t *bytes)
{
if (ctr) {
delete ctr;
ctr = nullptr;
}
if (_key.length == 16)
ctr = new CTR<AES128>();
else
ctr = new CTR<AES256>();
ctr->setKey(_key.bytes, _key.length);
static uint8_t scratch[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, 16);
ctr->setCounterSize(4);
ctr->encrypt(bytes, scratch, numBytes);
}
/**
@@ -208,4 +239,7 @@ void CryptoEngine::initNonce(uint32_t fromNode, uint64_t packetId)
// use memcpy to avoid breaking strict-aliasing
memcpy(nonce, &packetId, sizeof(uint64_t));
memcpy(nonce + sizeof(uint64_t), &fromNode, sizeof(uint32_t));
}
}
#ifndef HAS_CUSTOM_CRYPTO_ENGINE
CryptoEngine *crypto = new CryptoEngine;
#endif

View File

@@ -1,5 +1,6 @@
#pragma once
#include "AES.h"
#include "CTR.h"
#include "concurrency/LockGuard.h"
#include "configuration.h"
#include "mesh-pb-constants.h"
@@ -65,15 +66,16 @@ class CryptoEngine
*
* @param bytes is updated in place
*/
virtual void encrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes);
virtual void encryptPacket(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes);
virtual void decrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes);
virtual void encryptAESCtr(CryptoKey key, uint8_t *nonce, size_t numBytes, uint8_t *bytes);
#ifndef PIO_UNIT_TESTING
protected:
#endif
/** Our per packet nonce */
uint8_t nonce[16] = {0};
CryptoKey key = {};
CTRCommon *ctr = NULL;
#if !(MESHTASTIC_EXCLUDE_PKI)
uint8_t shared_key[32] = {0};
uint8_t private_key[32] = {0};

View File

@@ -480,7 +480,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
memcpy(p->encrypted.bytes, ScratchEncrypted, numbytes);
p->channel = 0;
} else {
crypto->encrypt(getFrom(p), p->id, numbytes, bytes);
crypto->encryptPacket(getFrom(p), p->id, numbytes, bytes);
memcpy(p->encrypted.bytes, bytes, numbytes);
}
#else