Fix constrained logging matrix builds
This commit is contained in:
1 parent
65a53285d9
commit
1e32abc41e
9 files changed
+324
-4
No files matched your search
@@ -0,0 +1,107 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ed_25519.h"
|
||||
|
||||
typedef struct {
|
||||
const char *seed;
|
||||
const char *public_key;
|
||||
const char *message;
|
||||
const char *signature;
|
||||
} rfc8032_vector;
|
||||
|
||||
static int hex_nibble(char c) {
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int decode_hex(unsigned char *out, size_t out_len, const char *hex) {
|
||||
size_t i;
|
||||
|
||||
if (strlen(hex) != out_len * 2) return 0;
|
||||
for (i = 0; i < out_len; ++i) {
|
||||
const int high = hex_nibble(hex[i * 2]);
|
||||
const int low = hex_nibble(hex[i * 2 + 1]);
|
||||
if (high < 0 || low < 0) return 0;
|
||||
out[i] = (unsigned char)((high << 4) | low);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int run_vector(const rfc8032_vector *vector, int number) {
|
||||
unsigned char seed[32];
|
||||
unsigned char expected_public_key[32];
|
||||
unsigned char expected_signature[64];
|
||||
unsigned char public_key[32];
|
||||
unsigned char private_key[64];
|
||||
unsigned char signature[64];
|
||||
unsigned char message[256];
|
||||
const size_t message_len = strlen(vector->message) / 2;
|
||||
|
||||
if (message_len > sizeof(message) ||
|
||||
!decode_hex(seed, sizeof(seed), vector->seed) ||
|
||||
!decode_hex(expected_public_key, sizeof(expected_public_key), vector->public_key) ||
|
||||
!decode_hex(message, message_len, vector->message) ||
|
||||
!decode_hex(expected_signature, sizeof(expected_signature), vector->signature)) {
|
||||
fprintf(stderr, "RFC 8032 vector %d is malformed\n", number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ed25519_create_keypair(public_key, private_key, seed);
|
||||
if (memcmp(public_key, expected_public_key, sizeof(public_key)) != 0) {
|
||||
fprintf(stderr, "RFC 8032 vector %d public key mismatch\n", number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ed25519_sign(signature, message, message_len, public_key, private_key);
|
||||
if (memcmp(signature, expected_signature, sizeof(signature)) != 0) {
|
||||
fprintf(stderr, "RFC 8032 vector %d signature mismatch\n", number);
|
||||
return 0;
|
||||
}
|
||||
if (!ed25519_verify(signature, message, message_len, public_key)) {
|
||||
fprintf(stderr, "RFC 8032 vector %d signature did not verify\n", number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
signature[17] ^= 0x01;
|
||||
if (ed25519_verify(signature, message, message_len, public_key)) {
|
||||
fprintf(stderr, "RFC 8032 vector %d accepted a damaged signature\n", number);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
static const rfc8032_vector vectors[] = {
|
||||
{
|
||||
"9d61b19deffd5a60ba844af492ec2cc4"
|
||||
"4449c5697b326919703bac031cae7f60",
|
||||
"d75a980182b10ab7d54bfed3c964073a"
|
||||
"0ee172f3daa62325af021a68f707511a",
|
||||
"",
|
||||
"e5564300c360ac729086e2cc806e828a"
|
||||
"84877f1eb8e5d974d873e06522490155"
|
||||
"5fb8821590a33bacc61e39701cf9b46b"
|
||||
"d25bf5f0595bbe24655141438e7a100b"
|
||||
},
|
||||
{
|
||||
"4ccd089b28ff96da9db6c346ec114e0f"
|
||||
"5b8a319f35aba624da8cf6ed4fb8a6fb",
|
||||
"3d4017c3e843895a92b70aa74d1b7ebc"
|
||||
"9c982ccf2ec4968cc0cd55f12af4660c",
|
||||
"72",
|
||||
"92a009a9f0d4cab8720e820b5f642540"
|
||||
"a2b27b5416503f8fb3762223ebdb69da"
|
||||
"085ac1e43e15996e458f3613d0f11d8c"
|
||||
"387b2eaeb4302aeeb00d291612bb0c00"
|
||||
}
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(vectors) / sizeof(vectors[0]); ++i) {
|
||||
if (!run_vector(&vectors[i], (int)i + 1)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -500,10 +500,27 @@ for full_env in "${SUPPORTED_PIO_ENVS[@]}"; do
|
||||
|| fail "$full_env Full Companion omitted USB folder seeding"
|
||||
[[ "$PLATFORMIO_BUILD_FLAGS" == *"COMPANION_FEATURE_BLE_MOTA_SOURCE=1"* ]] \
|
||||
|| fail "$full_env Full Companion omitted BLE folder seeding"
|
||||
if ! pio_env_option_contains "$pio_env" build_src_filter "helpers/ota/*.cpp" \
|
||||
&& [[ "$PLATFORMIO_BUILD_SRC_FILTER" != *"helpers/ota/*.cpp"* ]]; then
|
||||
fail "$full_env Full Companion omitted the OTA C++ implementation"
|
||||
fi
|
||||
done
|
||||
unset PLATFORMIO_BUILD_FLAGS PLATFORMIO_BUILD_UNFLAGS \
|
||||
PLATFORMIO_BUILD_SRC_FILTER
|
||||
|
||||
# An environment that includes only the tiny OTA inflater still needs the C++
|
||||
# protocol implementation when build.sh overlays LoRa OTA.
|
||||
reduced_nrf_ota_env=RAK_3401_repeater_lora_ota_no_external_sensors
|
||||
reduced_nrf_pio_env=$(get_pio_build_env "$reduced_nrf_ota_env")
|
||||
PLATFORMIO_BUILD_SRC_FILTER=""
|
||||
PLATFORMIO_EXTRA_SCRIPTS=""
|
||||
apply_nrf52_lora_ota_build_recipe "$reduced_nrf_ota_env" "$reduced_nrf_pio_env"
|
||||
if ! pio_env_option_contains "$reduced_nrf_pio_env" build_src_filter "helpers/ota/*.cpp" \
|
||||
&& [[ "$PLATFORMIO_BUILD_SRC_FILTER" != *"helpers/ota/*.cpp"* ]]; then
|
||||
fail "$reduced_nrf_ota_env omitted the OTA C++ implementation"
|
||||
fi
|
||||
unset PLATFORMIO_BUILD_SRC_FILTER PLATFORMIO_EXTRA_SCRIPTS
|
||||
|
||||
# The bounded AsyncTCP task stack belongs to every ESP32 Full profile, including
|
||||
# expanded non-Companion builds, but must not leak into ordinary or nRF52
|
||||
# recipes.
|
||||
@@ -764,6 +781,29 @@ if declare -f run_logging_matrix_build_targets | grep -q 'Profile 2'; then
|
||||
fail "logging matrix still labels a separate Profile 2"
|
||||
fi
|
||||
|
||||
# Option 3 must not publish an oversized standard ESP32 image, but its expected
|
||||
# portable-slot status is satisfied by the mandatory expanded FULL pass.
|
||||
saved_supports_esp32_full_build=$(declare -f supports_esp32_full_build)
|
||||
supports_esp32_full_build() { [ "$1" = esp32_portable_overflow ]; }
|
||||
build_firmware() { return 42; }
|
||||
saved_output_dir=$OUTPUT_DIR
|
||||
OUTPUT_DIR=$version_test_dir
|
||||
LOGGING_MATRIX_FAILURES=()
|
||||
LOGGING_MATRIX_DEFERRED_TARGETS=()
|
||||
DEFER_ESP32_PORTABLE_OVERFLOW_TO_FULL=1
|
||||
FIRMWARE_FILENAME_INFIX=""
|
||||
MQTT_BRIDGE_OVERRIDE="off"
|
||||
if ! run_logged_build_targets esp32_portable_overflow >/dev/null; then
|
||||
fail "portable ESP32 overflow made the logging pass fail"
|
||||
fi
|
||||
[ ${#LOGGING_MATRIX_FAILURES[@]} -eq 0 ] \
|
||||
|| fail "portable ESP32 overflow remained a logging-matrix failure"
|
||||
[ "${LOGGING_MATRIX_DEFERRED_TARGETS[*]}" = esp32_portable_overflow ] \
|
||||
|| fail "portable ESP32 overflow was not deferred to FULL"
|
||||
OUTPUT_DIR=$saved_output_dir
|
||||
unset DEFER_ESP32_PORTABLE_OVERFLOW_TO_FULL
|
||||
eval "$saved_supports_esp32_full_build"
|
||||
|
||||
calls=()
|
||||
build_firmware() {
|
||||
calls+=("$1:$BUILD_PROFILE_EFFECTIVE:$SKIP_DECLARED_REDUCTIONS:$FIRMWARE_OUTPUT_ENV_NAME")
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
ED25519 = ROOT / "lib" / "ed25519"
|
||||
HARNESS = ROOT / "test" / "fixtures" / "ed25519_compact" / "test_ed25519_compact.c"
|
||||
SOURCES = [
|
||||
ED25519 / name
|
||||
for name in (
|
||||
"fe.c",
|
||||
"ge.c",
|
||||
"keypair.c",
|
||||
"sc.c",
|
||||
"sha512.c",
|
||||
"sign.c",
|
||||
"verify.c",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
class Ed25519CompactTest(unittest.TestCase):
|
||||
def test_stm32_builds_enable_compact_base_table(self):
|
||||
platformio = (ROOT / "platformio.ini").read_text()
|
||||
stm32_base = platformio.split("[stm32_base]", 1)[1].split("\n[", 1)[0]
|
||||
self.assertIn("-D ED25519_COMPACT_BASE=1", stm32_base)
|
||||
|
||||
def test_standard_and_compact_paths_match_rfc8032(self):
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
for label, extra_flags in (
|
||||
("standard", []),
|
||||
("compact", ["-DED25519_COMPACT_BASE=1"]),
|
||||
):
|
||||
executable = Path(temp_dir) / label
|
||||
subprocess.run(
|
||||
[
|
||||
"cc",
|
||||
"-std=c99",
|
||||
"-O2",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
"-DED25519_NO_SEED=1",
|
||||
*extra_flags,
|
||||
f"-I{ED25519}",
|
||||
str(HARNESS),
|
||||
*(str(source) for source in SOURCES),
|
||||
"-o",
|
||||
str(executable),
|
||||
],
|
||||
check=True,
|
||||
cwd=ROOT,
|
||||
)
|
||||
subprocess.run([str(executable)], check=True, cwd=ROOT)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -108,6 +108,14 @@ int main() {
|
||||
companion = (ROOT / "examples/companion_radio/MyMesh.cpp").read_text()
|
||||
formatter = (ROOT / "src/helpers/StorageLayout.cpp").read_text()
|
||||
|
||||
stm32_include = formatter.index("#elif defined(STM32_PLATFORM)")
|
||||
stm32_include_end = formatter.index("#endif", stm32_include)
|
||||
stm32_headers = formatter[stm32_include:stm32_include_end]
|
||||
self.assertLess(
|
||||
stm32_headers.index("#include <Arduino.h>"),
|
||||
stm32_headers.index("#include <InternalFileSystem.h>"),
|
||||
)
|
||||
|
||||
self.assertIn('#include "StorageLayout.h"', common)
|
||||
self.assertIn(
|
||||
"mesh::cli::handleStorageLayoutGet(config, *_board, reply, 160)",
|
||||
|
||||
Reference in new issue
Block a user