diff --git a/.github/workflows/build_stm32.yml b/.github/workflows/build_stm32.yml index 6858812e1..e78178db3 100644 --- a/.github/workflows/build_stm32.yml +++ b/.github/workflows/build_stm32.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Build Raspberry Pi 2040 + - name: Build STM32WL id: build uses: ./.github/actions/build-variant with: diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index ca9f1d37f..87ba8cf85 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -32,7 +32,7 @@ jobs: name: Checkout base - id: jsonStep run: | - TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}}) + TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick) echo "$TARGETS" echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT outputs: diff --git a/bin/generate_ci_matrix.py b/bin/generate_ci_matrix.py index 46398dd59..4d8759ecc 100755 --- a/bin/generate_ci_matrix.py +++ b/bin/generate_ci_matrix.py @@ -6,6 +6,7 @@ import configparser import json import os import sys +import random rootdir = "variants/" @@ -39,5 +40,7 @@ for subdir, dirs, files in os.walk(rootdir): "check" in options ): outlist.append(section) - -print(json.dumps(outlist)) +if ("quick" in options) & (len(outlist) > 3): + print(json.dumps(random.sample(outlist, 3))) +else: + print(json.dumps(outlist)) diff --git a/platformio.ini b/platformio.ini index b3898ba93..799645306 100644 --- a/platformio.ini +++ b/platformio.ini @@ -88,7 +88,9 @@ monitor_speed = 115200 monitor_filters = direct lib_deps = - jgromes/RadioLib@~7.0.0 + ;jgromes/RadioLib@~7.0.0 + ;7.0.1pre needed for LR1121 support and SX127x CRC Bugfix + https://github.com/jgromes/RadioLib.git#42ae7c92ed584317d7206cfc463ba6260295dbbc https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95 ; ESP8266_SSD1306 https://github.com/mathertel/OneButton@~2.6.1 ; OneButton library for non-blocking button debounce https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159 diff --git a/src/mesh/CryptoEngine.cpp b/src/mesh/CryptoEngine.cpp index f705bae03..535e11e9b 100644 --- a/src/mesh/CryptoEngine.cpp +++ b/src/mesh/CryptoEngine.cpp @@ -70,8 +70,9 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_ long extraNonceTmp = random(); auth = bytesOut + numBytes; extraNonce = (uint32_t *)(auth + 8); - *extraNonce = extraNonceTmp; - LOG_INFO("Random nonce value: %d\n", *extraNonce); + memcpy(extraNonce, &extraNonceTmp, + 4); // do not use dereference on potential non aligned pointers : *extraNonce = extraNonceTmp; + LOG_INFO("Random nonce value: %d\n", extraNonceTmp); meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(toNode); if (node->num < 1 || node->user.public_key.size == 0) { LOG_DEBUG("Node %d or their public_key not found\n", toNode); @@ -80,14 +81,15 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_ if (!crypto->setDHKey(toNode)) { return false; } - initNonce(fromNode, packetNum, *extraNonce); + initNonce(fromNode, packetNum, extraNonceTmp); // Calculate the shared secret with the destination node and encrypt printBytes("Attempting encrypt using nonce: ", nonce, 13); printBytes("Attempting encrypt using shared_key starting with: ", shared_key, 8); aes_ccm_ae(shared_key, 32, nonce, 8, bytes, numBytes, nullptr, 0, bytesOut, auth); // this can write up to 15 bytes longer than numbytes past bytesOut - *extraNonce = extraNonceTmp; + memcpy(extraNonce, &extraNonceTmp, + 4); // do not use dereference on potential non aligned pointers : *extraNonce = extraNonceTmp; return true; } @@ -99,11 +101,12 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_ */ bool CryptoEngine::decryptCurve25519(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes, uint8_t *bytesOut) { - uint8_t *auth; // set to last 8 bytes of text? - uint32_t *extraNonce; + uint8_t *auth; // set to last 8 bytes of text? + uint32_t extraNonce; // pointer was not really used auth = bytes + numBytes - 12; - extraNonce = (uint32_t *)(auth + 8); - LOG_INFO("Random nonce value: %d\n", *extraNonce); +#ifndef PIO_UNIT_TESTING + memcpy(&extraNonce, auth + 8, 4); // do not use dereference on potential non aligned pointers : (uint32_t *)(auth + 8); + LOG_INFO("Random nonce value: %d\n", extraNonce); meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(fromNode); if (node == nullptr || node->num < 1 || node->user.public_key.size == 0) { @@ -115,7 +118,8 @@ bool CryptoEngine::decryptCurve25519(uint32_t fromNode, uint64_t packetNum, size if (!crypto->setDHKey(fromNode)) { return false; } - initNonce(fromNode, packetNum, *extraNonce); +#endif + initNonce(fromNode, packetNum, extraNonce); printBytes("Attempting decrypt using nonce: ", nonce, 13); printBytes("Attempting decrypt using shared_key starting with: ", shared_key, 8); return aes_ccm_ad(shared_key, 32, nonce, 8, bytes, numBytes - 12, nullptr, 0, auth, bytesOut); diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index a993ee7c0..f06f54165 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -36,8 +36,8 @@ static MemoryDynamic staticPool; Allocator &packetPool = staticPool; -static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1]; -static uint8_t ScratchEncrypted[MAX_LORA_PAYLOAD_LEN + 1]; +static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1] __attribute__ ((__aligned__)); +static uint8_t ScratchEncrypted[MAX_LORA_PAYLOAD_LEN + 1] __attribute__ ((__aligned__)); /** * Constructor diff --git a/src/meshUtils.cpp b/src/meshUtils.cpp index 2789a143c..e98a6f1ce 100644 --- a/src/meshUtils.cpp +++ b/src/meshUtils.cpp @@ -68,7 +68,7 @@ void printBytes(const char *label, const uint8_t *p, size_t numbytes) snprintf(messageBuffer + labelSize + i * 3, 4, " %02x", p[i]); strcpy(messageBuffer + labelSize + numbytes * 3, "\n"); LOG_DEBUG(messageBuffer); - delete messageBuffer; + delete[] messageBuffer; } } diff --git a/test/test_crypto/test_main.cpp b/test/test_crypto/test_main.cpp index 0c820178a..cbe366048 100644 --- a/test/test_crypto/test_main.cpp +++ b/test/test_crypto/test_main.cpp @@ -98,7 +98,44 @@ void test_DH25519(void) HexToBytes(private_key, "18630f93598637c35da623a74559cf944374a559114c7937811041fc8605564a"); crypto->setDHPrivateKey(private_key); TEST_ASSERT(!crypto->setDHPublicKey(public_key)); // Weak public key results in 0 shared key + + HexToBytes(public_key, "f7e13a1a067d2f4e1061bf9936fde5be6b0c2494a8f809cbac7f290ef719e91c"); + HexToBytes(private_key, "10300724f3bea134eb1575245ef26ff9b8ccd59849cd98ce1a59002fe1d5986c"); + HexToBytes(expected_shared, "24becd5dfed9e9289ba2e15b82b0d54f8e9aacb72f5e4248c58d8d74b451ce76"); + crypto->setDHPrivateKey(private_key); + TEST_ASSERT(crypto->setDHPublicKey(public_key)); + crypto->hash(crypto->shared_key, 32); + TEST_ASSERT_EQUAL_MEMORY(expected_shared, crypto->shared_key, 32); } + +void test_PKC_Decrypt(void) +{ + uint8_t private_key[32]; + uint8_t public_key[32]; + uint8_t expected_shared[32]; + uint8_t expected_decrypted[32]; + uint8_t radioBytes[128] __attribute__((__aligned__)); + uint8_t decrypted[128] __attribute__((__aligned__)); + uint8_t expected_nonce[16]; + + uint32_t fromNode; + HexToBytes(public_key, "db18fc50eea47f00251cb784819a3cf5fc361882597f589f0d7ff820e8064457"); + HexToBytes(private_key, "a00330633e63522f8a4d81ec6d9d1e6617f6c8ffd3a4c698229537d44e522277"); + HexToBytes(expected_shared, "777b1545c9d6f9a2"); + HexToBytes(expected_decrypted, "08011204746573744800"); + HexToBytes(radioBytes, "8c646d7a2909000062d6b2136b00000040df24abfcc30a17a3d9046726099e796a1c036a792b"); + HexToBytes(expected_nonce, "62d6b213036a792b2909000000"); + fromNode = 0x0929; + crypto->setDHPrivateKey(private_key); + TEST_ASSERT(crypto->setDHPublicKey(public_key)); + crypto->hash(crypto->shared_key, 32); + crypto->decryptCurve25519(fromNode, 0x13b2d662, 22, radioBytes + 16, decrypted); + TEST_ASSERT_EQUAL_MEMORY(expected_shared, crypto->shared_key, 8); + TEST_ASSERT_EQUAL_MEMORY(expected_nonce, crypto->nonce, 13); + + TEST_ASSERT_EQUAL_MEMORY(expected_decrypted, decrypted, 10); +} + void test_AES_CTR(void) { uint8_t expected[32]; @@ -137,6 +174,7 @@ void setup() RUN_TEST(test_ECB_AES256); RUN_TEST(test_DH25519); RUN_TEST(test_AES_CTR); + RUN_TEST(test_PKC_Decrypt); } void loop()