Files
ESP32_Serial_Swiss_Army_Knife/tests/web_security/run.py
T

89 lines
3.4 KiB
Python

#!/usr/bin/env python3
"""Compile unchanged production security implementation with real host mbedTLS."""
from pathlib import Path
import subprocess
import re
import tempfile
ROOT = Path(__file__).resolve().parents[2]
HEADERS = {
"esp_err.h": """#pragma once
typedef int esp_err_t;
#define ESP_OK 0
#define ESP_FAIL -1
#define ESP_ERR_INVALID_ARG 1
#define ESP_ERR_INVALID_STATE 2
#define ESP_ERR_INVALID_SIZE 3
#define ESP_ERR_INVALID_VERSION 4
#define ESP_ERR_INVALID_RESPONSE 5
#define ESP_ERR_NO_MEM 6
#define ESP_ERR_TIMEOUT 7
""",
"esp_mac.h": """#pragma once
#include <stdint.h>
#include "esp_err.h"
#define ESP_MAC_WIFI_SOFTAP 1
esp_err_t esp_read_mac(uint8_t *, int);
""",
"freertos/FreeRTOS.h": """#pragma once
#define portMAX_DELAY 0xffffffffU
#define pdTRUE 1
""",
"freertos/semphr.h": """#pragma once
typedef void *SemaphoreHandle_t;
SemaphoreHandle_t xSemaphoreCreateMutex(void);
int xSemaphoreTake(SemaphoreHandle_t, unsigned);
int xSemaphoreGive(SemaphoreHandle_t);
""",
"nvs.h": """#pragma once
#include <stddef.h>
#include "esp_err.h"
typedef int nvs_handle_t;
#define NVS_READONLY 0
#define NVS_READWRITE 1
#define ESP_ERR_NVS_NOT_FOUND 10
#define ESP_ERR_NVS_TYPE_MISMATCH 11
#define ESP_ERR_NVS_INVALID_LENGTH 12
esp_err_t nvs_open(const char *, int, nvs_handle_t *);
esp_err_t nvs_get_blob(nvs_handle_t, const char *, void *, size_t *);
esp_err_t nvs_set_blob(nvs_handle_t, const char *, const void *, size_t);
esp_err_t nvs_commit(nvs_handle_t);
void nvs_close(nvs_handle_t);
""",
}
with tempfile.TemporaryDirectory(prefix="web-security-") as directory:
out = Path(directory)
for name, text in HEADERS.items():
path = out / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(text)
executable = out / "security"
subprocess.run([
"cc", "-std=c11", "-Wall", "-Wextra", "-Werror", "-O1", "-g",
"-I", str(out), "-I", str(ROOT / "src"),
str(ROOT / "tests/web_security/security.c"),
"-lmbedx509", "-lmbedcrypto", "-o", str(executable),
], check=True)
subprocess.run([str(executable)], check=True)
symbols = subprocess.check_output(["nm", "-g", str(executable)], text=True)
assert "web_security_show_credentials" not in symbols
assert "web_security_rotate_credentials" not in symbols
assert set(re.findall(r" T (web_security_\w+)$", symbols, re.MULTILINE)) == {
"web_security_init", "web_security_copy_tls_material",
"web_security_get_certificate_metadata", "web_security_rotate_certificate",
"web_security_reset_all", "web_security_get_identity_snapshot",
"web_security_reserve_identity", "web_security_replace_reserved", "web_security_release_identity",
}
header = (ROOT / "src/web_security.h").read_text()
assert "web_security_credentials_t" not in header
assert "WEB_SECURITY_PASSWORD" not in header
assert "WEB_SECURITY_USERNAME" not in header
console = (ROOT / "src/web_console.c").read_text()
for forbidden in ('"credentials"', "web credentials", "user_database_sync_legacy", "synchronize_migrated", "Password:"):
assert forbidden not in console, forbidden
assert "web_server_replace_identity(0, 0, reset, &committed)" in console
assert set(re.findall(r"\b(user_database_\w+)\s*\(", console)) == {
"user_database_get_snapshot",
}
print("PASS exact public/owner API and legacy credential/console DB-mutation absence")