Skip to content
Open
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
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_ED25519
#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_ED25519
// 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_ED25519
#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_ED25519
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_ED25519
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_ED25519
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_ED25519
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_ED25519
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_ED25519
{
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;
}

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

#ifdef USE_CC310_ED25519
#include <Adafruit_nRFCrypto.h>
#endif

class RadioLibWrapper : public mesh::Radio {
protected:
PhysicalLayer* _radio;
Expand Down Expand Up @@ -80,8 +84,15 @@ class RadioNoiseListener : public mesh::RNG {
RadioNoiseListener(PhysicalLayer& radio): _radio(&radio) { }

void random(uint8_t* dest, size_t sz) override {
#ifdef USE_CC310_ED25519
// 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++) {
dest[i] = _radio->randomByte() ^ (::random(0, 256) & 0xFF);
}
#endif
}
};
1 change: 1 addition & 0 deletions variants/heltec_t096/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ build_flags = ${nrf52_base.build_flags}
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D USE_CC310_ED25519=1
-D PIN_VEXT_EN=26 ; Vext is connected to VDD which is also connected to TFT & GPS
-D PIN_VEXT_EN_ACTIVE=HIGH
-D PIN_GPS_RX=25
Expand Down
1 change: 1 addition & 0 deletions variants/rak3401/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ build_flags = ${nrf52_base.build_flags}
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D SX126X_REGISTER_PATCH=1 ; Patch register 0x8B5 for improved RX with SKY66122 FEM
-D USE_CC310_ED25519=1
build_src_filter = ${nrf52_base.build_src_filter}
+<../variants/rak3401>
+<helpers/sensors>
Expand Down
1 change: 1 addition & 0 deletions variants/rak4631/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ build_flags = ${nrf52_base.build_flags}
-D LORA_TX_POWER=22
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D USE_CC310_ED25519=1
-D ENV_INCLUDE_RAK12035=1
-UENV_INCLUDE_BME680
-D ENV_INCLUDE_BME680_BSEC=1
Expand Down
1 change: 1 addition & 0 deletions variants/t1000-e/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ build_flags = ${nrf52_base.build_flags}
-D LORA_TX_POWER=22
-D RF_SWITCH_TABLE
-D RX_BOOSTED_GAIN=true
-D USE_CC310_ED25519=1
-D P_LORA_BUSY=7 ; P0.7
-D P_LORA_SCLK=11 ; P0.11
-D P_LORA_NSS=12 ; P0.12
Expand Down