Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ build_flags = ${arduino_base.build_flags}
-D NRF52_PLATFORM
-D LFS_NO_ASSERT=1
-D EXTRAFS=1
-D USE_CC310_HW_CRYPTO=1
lib_deps =
${arduino_base.lib_deps}
https://github.com/oltaco/CustomLFS#0.2.2
Expand Down
20 changes: 19 additions & 1 deletion src/Identity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
#include <ed_25519.h>
#include <Ed25519.h>

#ifdef USE_CC310_HW_CRYPTO
#include <Adafruit_nRFCrypto.h>
#include "nrf_cc310/include/crys_ec_edw_api.h"
#endif

namespace mesh {

Identity::Identity() {
Expand All @@ -15,7 +20,20 @@ Identity::Identity(const char* pub_hex) {
}

bool Identity::verify(const uint8_t* sig, const uint8_t* message, int msg_len) const {
#if 0
#ifdef USE_CC310_HW_CRYPTO
// nRF52840 CryptoCell CC310 hardware Ed25519 verification. The software
// implementations need ~3KB of stack (which can overflow the Adafruit core's
// 4KB loop task stack from the advert receive path); the hardware path
// needs much less, around 600-700bytes. The CC310 workspace is static, faster,
// should save power at scale as well.
static CRYS_ECEDW_TempBuff_t cc310_tmp;
nRFCrypto.begin();
CRYSError_t rc = CRYS_ECEDW_Verify((uint8_t*)sig, CRYS_ECEDW_SIGNATURE_BYTES,
(uint8_t*)pub_key, CRYS_ECEDW_MOD_SIZE_IN_BYTES,
(uint8_t*)message, (size_t)msg_len, &cc310_tmp);
nRFCrypto.end();
return rc == CRYS_OK;
#elif 0
// NOTE: memory corruption bug was found in this function!!
return ed25519_verify(sig, message, msg_len, pub_key);
#else
Expand Down
98 changes: 97 additions & 1 deletion src/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
#include <AES.h>
#include <SHA256.h>

#ifdef USE_CC310_HW_CRYPTO
#include <Adafruit_nRFCrypto.h>
#include "nrf_cc310/include/crys_hash.h"
#include "nrf_cc310/include/crys_hmac.h"
#include "nrf_cc310/include/ssi_aes.h"
#endif

#ifdef ARDUINO
#include <Arduino.h>
#endif
Expand All @@ -15,19 +22,58 @@ uint32_t RNG::nextInt(uint32_t _min, uint32_t _max) {
}

void Utils::sha256(uint8_t *hash, size_t hash_len, const uint8_t* msg, int msg_len) {
#ifdef USE_CC310_HW_CRYPTO
static CRYS_HASH_Result_t result;
nRFCrypto.begin();
CRYS_HASH(CRYS_HASH_SHA256_mode, (uint8_t*)msg, (size_t)msg_len, result);
nRFCrypto.end();
memcpy(hash, result, hash_len);
#else
SHA256 sha;
sha.update(msg, msg_len);
sha.finalize(hash, hash_len);
#endif
}

void Utils::sha256(uint8_t *hash, size_t hash_len, const uint8_t* frag1, int frag1_len, const uint8_t* frag2, int frag2_len) {
#ifdef USE_CC310_HW_CRYPTO
static CRYS_HASHUserContext_t ctx;
static CRYS_HASH_Result_t result;
nRFCrypto.begin();
CRYS_HASH_Init(&ctx, CRYS_HASH_SHA256_mode);
CRYS_HASH_Update(&ctx, (uint8_t*)frag1, (size_t)frag1_len);
CRYS_HASH_Update(&ctx, (uint8_t*)frag2, (size_t)frag2_len);
CRYS_HASH_Finish(&ctx, result);
nRFCrypto.end();
memcpy(hash, result, hash_len);
#else
SHA256 sha;
sha.update(frag1, frag1_len);
sha.update(frag2, frag2_len);
sha.finalize(hash, hash_len);
#endif
}

int Utils::decrypt(const uint8_t* shared_secret, uint8_t* dest, const uint8_t* src, int src_len) {
#ifdef USE_CC310_HW_CRYPTO
static SaSiAesUserContext_t ctx;
SaSiAesUserKeyData_t keyData = { (uint8_t*)shared_secret, CIPHER_KEY_SIZE };
uint8_t* dp = dest;
const uint8_t* sp = src;
size_t dummy_out = 0;

nRFCrypto.begin();
SaSi_AesInit(&ctx, SASI_AES_DECRYPT, SASI_AES_MODE_ECB, SASI_AES_PADDING_NONE);
SaSi_AesSetKey(&ctx, SASI_AES_USER_KEY, &keyData, sizeof(keyData));
while (sp - src < src_len) {
SaSi_AesBlock(&ctx, (uint8_t*)sp, 16, dp);
dp += 16; sp += 16;
}
SaSi_AesFinish(&ctx, 0, NULL, 0, NULL, &dummy_out);
SaSi_AesFree(&ctx);
nRFCrypto.end();
return sp - src;
#else
AES128 aes;
uint8_t* dp = dest;
const uint8_t* sp = src;
Expand All @@ -39,9 +85,34 @@ int Utils::decrypt(const uint8_t* shared_secret, uint8_t* dest, const uint8_t* s
}

return sp - src; // will always be multiple of 16
#endif
}

int Utils::encrypt(const uint8_t* shared_secret, uint8_t* dest, const uint8_t* src, int src_len) {
#ifdef USE_CC310_HW_CRYPTO
static SaSiAesUserContext_t ctx;
SaSiAesUserKeyData_t keyData = { (uint8_t*)shared_secret, CIPHER_KEY_SIZE };
uint8_t* dp = dest;
size_t dummy_out = 0;

nRFCrypto.begin();
SaSi_AesInit(&ctx, SASI_AES_ENCRYPT, SASI_AES_MODE_ECB, SASI_AES_PADDING_NONE);
SaSi_AesSetKey(&ctx, SASI_AES_USER_KEY, &keyData, sizeof(keyData));
while (src_len >= 16) {
SaSi_AesBlock(&ctx, (uint8_t*)src, 16, dp);
dp += 16; src += 16; src_len -= 16;
}
if (src_len > 0) { // remaining partial block — zero-pad to 16 bytes
uint8_t tmp[16] = {};
memcpy(tmp, src, src_len);
SaSi_AesBlock(&ctx, tmp, 16, dp);
dp += 16;
}
SaSi_AesFinish(&ctx, 0, NULL, 0, NULL, &dummy_out);
SaSi_AesFree(&ctx);
nRFCrypto.end();
return dp - dest;
#else
AES128 aes;
uint8_t* dp = dest;

Expand All @@ -58,15 +129,27 @@ int Utils::encrypt(const uint8_t* shared_secret, uint8_t* dest, const uint8_t* s
dp += 16;
}
return dp - dest; // will always be multiple of 16
#endif
}

int Utils::encryptThenMAC(const uint8_t* shared_secret, uint8_t* dest, const uint8_t* src, int src_len) {
int enc_len = encrypt(shared_secret, dest + CIPHER_MAC_SIZE, src, src_len);

#ifdef USE_CC310_HW_CRYPTO
static CRYS_HMACUserContext_t hmac_ctx;
static CRYS_HASH_Result_t hmac_result;
nRFCrypto.begin();
CRYS_HMAC_Init(&hmac_ctx, CRYS_HASH_SHA256_mode, (uint8_t*)shared_secret, PUB_KEY_SIZE);
CRYS_HMAC_Update(&hmac_ctx, dest + CIPHER_MAC_SIZE, enc_len);
CRYS_HMAC_Finish(&hmac_ctx, hmac_result);
nRFCrypto.end();
memcpy(dest, hmac_result, CIPHER_MAC_SIZE);
#else
SHA256 sha;
sha.resetHMAC(shared_secret, PUB_KEY_SIZE);
sha.update(dest + CIPHER_MAC_SIZE, enc_len);
sha.finalizeHMAC(shared_secret, PUB_KEY_SIZE, dest, CIPHER_MAC_SIZE);
#endif

return CIPHER_MAC_SIZE + enc_len;
}
Expand All @@ -75,12 +158,25 @@ int Utils::MACThenDecrypt(const uint8_t* shared_secret, uint8_t* dest, const uin
if (src_len <= CIPHER_MAC_SIZE) return 0; // invalid src bytes

uint8_t hmac[CIPHER_MAC_SIZE];
#ifdef USE_CC310_HW_CRYPTO
{
static CRYS_HMACUserContext_t hmac_ctx;
static CRYS_HASH_Result_t hmac_result;
nRFCrypto.begin();
CRYS_HMAC_Init(&hmac_ctx, CRYS_HASH_SHA256_mode, (uint8_t*)shared_secret, PUB_KEY_SIZE);
CRYS_HMAC_Update(&hmac_ctx, (uint8_t*)(src + CIPHER_MAC_SIZE), src_len - CIPHER_MAC_SIZE);
CRYS_HMAC_Finish(&hmac_ctx, hmac_result);
nRFCrypto.end();
memcpy(hmac, hmac_result, CIPHER_MAC_SIZE);
}
#else
{
SHA256 sha;
sha.resetHMAC(shared_secret, PUB_KEY_SIZE);
sha.update(src + CIPHER_MAC_SIZE, src_len - CIPHER_MAC_SIZE);
sha.finalizeHMAC(shared_secret, PUB_KEY_SIZE, hmac, CIPHER_MAC_SIZE);
}
#endif
if (memcmp(hmac, src, CIPHER_MAC_SIZE) == 0) {
return decrypt(shared_secret, dest, src + CIPHER_MAC_SIZE, src_len - CIPHER_MAC_SIZE);
}
Expand Down Expand Up @@ -150,4 +246,4 @@ int Utils::parseTextParts(char* text, const char* parts[], int max_num, char sep
return num;
}

}
}
10 changes: 10 additions & 0 deletions src/helpers/radiolib/RadioLibWrappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include <Mesh.h>
#include <RadioLib.h>

#ifdef USE_CC310_HW_CRYPTO
#include <Adafruit_nRFCrypto.h>
#endif
struct PacketMillis {
uint32_t preambleMillis; // preamble-detect -> header-valid deadline
uint32_t payloadMillis; // header-valid -> rx-done deadline
Expand Down Expand Up @@ -86,8 +89,15 @@ class RadioNoiseListener : public mesh::RNG {
RadioNoiseListener(PhysicalLayer& radio): _radio(&radio) { }

void random(uint8_t* dest, size_t sz) override {
#ifdef USE_CC310_HW_CRYPTO
// CC310 TRNG is higher quality and environment-independent vs radio RSSI noise.
nRFCrypto.begin();
nRFCrypto.Random.generate(dest, (uint16_t)sz);

@nextgens nextgens Aug 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nRFCrypto.end();
#else
for (int i = 0; i < sz; i++) {
dest[i] = _radio->randomByte() ^ (::random(0, 256) & 0xFF);
}
#endif
}
};
Loading