NickDunklee 5 days ago
committed by GitHub
parent
commit
9321ddad9d
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      platformio.ini
  2. 20
      src/Identity.cpp
  3. 98
      src/Utils.cpp
  4. 10
      src/helpers/radiolib/RadioLibWrappers.h

1
platformio.ini

@ -91,6 +91,7 @@ build_flags = ${arduino_base.build_flags}
-D NRF52_PLATFORM -D NRF52_PLATFORM
-D LFS_NO_ASSERT=1 -D LFS_NO_ASSERT=1
-D EXTRAFS=1 -D EXTRAFS=1
-D USE_CC310_HW_CRYPTO=1
lib_deps = lib_deps =
${arduino_base.lib_deps} ${arduino_base.lib_deps}
https://github.com/oltaco/CustomLFS#0.2.2 https://github.com/oltaco/CustomLFS#0.2.2

20
src/Identity.cpp

@ -4,6 +4,11 @@
#include <ed_25519.h> #include <ed_25519.h>
#include <Ed25519.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 { namespace mesh {
Identity::Identity() { Identity::Identity() {
@ -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 { 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!! // NOTE: memory corruption bug was found in this function!!
return ed25519_verify(sig, message, msg_len, pub_key); return ed25519_verify(sig, message, msg_len, pub_key);
#else #else

98
src/Utils.cpp

@ -2,6 +2,13 @@
#include <AES.h> #include <AES.h>
#include <SHA256.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 #ifdef ARDUINO
#include <Arduino.h> #include <Arduino.h>
#endif #endif
@ -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) { 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; SHA256 sha;
sha.update(msg, msg_len); sha.update(msg, msg_len);
sha.finalize(hash, hash_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) { 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; SHA256 sha;
sha.update(frag1, frag1_len); sha.update(frag1, frag1_len);
sha.update(frag2, frag2_len); sha.update(frag2, frag2_len);
sha.finalize(hash, hash_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) { 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; AES128 aes;
uint8_t* dp = dest; uint8_t* dp = dest;
const uint8_t* sp = src; const uint8_t* sp = src;
@ -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 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) { 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; AES128 aes;
uint8_t* dp = dest; uint8_t* dp = dest;
@ -58,15 +129,27 @@ int Utils::encrypt(const uint8_t* shared_secret, uint8_t* dest, const uint8_t* s
dp += 16; dp += 16;
} }
return dp - dest; // will always be multiple of 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 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); 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; SHA256 sha;
sha.resetHMAC(shared_secret, PUB_KEY_SIZE); sha.resetHMAC(shared_secret, PUB_KEY_SIZE);
sha.update(dest + CIPHER_MAC_SIZE, enc_len); sha.update(dest + CIPHER_MAC_SIZE, enc_len);
sha.finalizeHMAC(shared_secret, PUB_KEY_SIZE, dest, CIPHER_MAC_SIZE); sha.finalizeHMAC(shared_secret, PUB_KEY_SIZE, dest, CIPHER_MAC_SIZE);
#endif
return CIPHER_MAC_SIZE + enc_len; return CIPHER_MAC_SIZE + enc_len;
} }
@ -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 if (src_len <= CIPHER_MAC_SIZE) return 0; // invalid src bytes
uint8_t hmac[CIPHER_MAC_SIZE]; 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; SHA256 sha;
sha.resetHMAC(shared_secret, PUB_KEY_SIZE); sha.resetHMAC(shared_secret, PUB_KEY_SIZE);
sha.update(src + CIPHER_MAC_SIZE, src_len - CIPHER_MAC_SIZE); sha.update(src + CIPHER_MAC_SIZE, src_len - CIPHER_MAC_SIZE);
sha.finalizeHMAC(shared_secret, PUB_KEY_SIZE, hmac, CIPHER_MAC_SIZE); sha.finalizeHMAC(shared_secret, PUB_KEY_SIZE, hmac, CIPHER_MAC_SIZE);
} }
#endif
if (memcmp(hmac, src, CIPHER_MAC_SIZE) == 0) { if (memcmp(hmac, src, CIPHER_MAC_SIZE) == 0) {
return decrypt(shared_secret, dest, src + CIPHER_MAC_SIZE, src_len - CIPHER_MAC_SIZE); return decrypt(shared_secret, dest, src + CIPHER_MAC_SIZE, src_len - CIPHER_MAC_SIZE);
} }
@ -150,4 +246,4 @@ int Utils::parseTextParts(char* text, const char* parts[], int max_num, char sep
return num; return num;
} }
} }

10
src/helpers/radiolib/RadioLibWrappers.h

@ -3,6 +3,9 @@
#include <Mesh.h> #include <Mesh.h>
#include <RadioLib.h> #include <RadioLib.h>
#ifdef USE_CC310_HW_CRYPTO
#include <Adafruit_nRFCrypto.h>
#endif
struct PacketMillis { struct PacketMillis {
uint32_t preambleMillis; // preamble-detect -> header-valid deadline uint32_t preambleMillis; // preamble-detect -> header-valid deadline
uint32_t payloadMillis; // header-valid -> rx-done deadline uint32_t payloadMillis; // header-valid -> rx-done deadline
@ -86,8 +89,15 @@ public:
RadioNoiseListener(PhysicalLayer& radio): _radio(&radio) { } RadioNoiseListener(PhysicalLayer& radio): _radio(&radio) { }
void random(uint8_t* dest, size_t sz) override { 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);
nRFCrypto.end();
#else
for (int i = 0; i < sz; i++) { for (int i = 0; i < sz; i++) {
dest[i] = _radio->randomByte() ^ (::random(0, 256) & 0xFF); dest[i] = _radio->randomByte() ^ (::random(0, 256) & 0xFF);
} }
#endif
} }
}; };

Loading…
Cancel
Save