Prioritize X25519 while retaining enabled curve fallbacks and log the negotiated ECDHE group. Extend ABI checks, crypto benchmarks and backend group probes, and document the updated APP package.
62 lines
4.1 KiB
Python
62 lines
4.1 KiB
Python
"""Verify the WSS flash package against the current legacy-board build."""
|
|
import hashlib
|
|
import json
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
import zipfile
|
|
from pathlib import Path
|
|
|
|
root = Path(__file__).resolve().parents[1]
|
|
package = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else root / 'artifacts/wss/full-handshake/EG800AKCN_11LG-legacy-wss-x25519.zip'
|
|
output = package.parent
|
|
output.mkdir(parents=True, exist_ok=True)
|
|
objdump = root / 'ql-cross-tool/win32/owtoolchain/gcc-arm-none-eabi/bin/arm-none-eabi-objdump.exe'
|
|
app = root / 'ql-application/threadx/build/app.elf'
|
|
symbols = subprocess.check_output([str(objdump.with_name('arm-none-eabi-nm.exe')), str(app)], text=True)
|
|
required = ['talkingq_parse_wss_url', 'talkingq_root_ca', 'rws_check_handshake', 'rws_ssl_conn',
|
|
'mbedtls_ssl_set_hostname', 'mbedtls_ssl_get_verify_result', 'mbedtls_ssl_conf_authmode',
|
|
'mbedtls_ctr_drbg_random', 'mbedtls_sha1', 'mbedtls_base64_encode', 'mbedtls_ssl_handshake_step',
|
|
'rws_tls_preferred_curves']
|
|
for symbol in required:
|
|
assert re.search(r'\b' + symbol + r'$', symbols, re.M), 'Missing linked symbol: ' + symbol
|
|
kernel_symbols = subprocess.check_output([str(objdump.with_name('arm-none-eabi-nm.exe')),
|
|
str(root / 'ql-kernel/threadx/build/kernel.axf')], text=True)
|
|
kernel_required = ['ecdsa_verify_restartable', 'mbedtls_ecdsa_read_signature',
|
|
'mbedtls_gcm_crypt_and_tag', 'mbedtls_x509_time_is_future',
|
|
'mbedtls_x509_time_is_past', 'mbedtls_platform_gmtime_r', 'mbedtls_time',
|
|
'ecp_mod_p256', 'ecp_mod_p384', 'ecp_mod_p521']
|
|
for symbol in kernel_required:
|
|
assert re.search(r'\b' + symbol + r'$', kernel_symbols, re.M), 'Missing kernel capability: ' + symbol
|
|
clock_body = subprocess.check_output([str(objdump), '-d', '--disassemble=x509_get_current_time',
|
|
str(root / 'ql-kernel/threadx/build/kernel.axf')], text=True)
|
|
assert '<mbedtls_platform_gmtime_r>' in clock_body and '<GetCurrentCompTime>' not in clock_body
|
|
(output / 'x509-clock.disasm.txt').write_text(clock_body)
|
|
report = {'package': package.name, 'sha256': hashlib.sha256(package.read_bytes()).hexdigest(),
|
|
'linked_symbols': required, 'kernel_symbols': kernel_required,
|
|
'hardware_test': '2026-09-16 14:38 device log: NIST TLS handshake 1820 ms and HTTP 101 passed; X25519 preference awaits device test',
|
|
'backend': '2026-09-16 11:32 CST: WSS 443 /ws HTTP 101; 8080 plaintext WS'}
|
|
with zipfile.ZipFile(package) as archive:
|
|
assert archive.testzip() is None, 'ZIP CRC failure'
|
|
for name, source in {'cp.bin': 'ql-kernel/threadx/build/release_kernel.bin',
|
|
'customer_app.bin': 'ql-application/threadx/build/app.bin'}.items():
|
|
data = archive.read(name)
|
|
assert data == (root / source).read_bytes(), 'Stale image: ' + name
|
|
report[name] = {'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest()}
|
|
assert b'wss://banban.api.talkingq.com:443/ws' in archive.read('customer_app.bin')
|
|
assert b'WSS TLS handshake total=' in archive.read('customer_app.bin')
|
|
assert b'WSS TLS full handshake: prefer X25519' in archive.read('customer_app.bin')
|
|
report['download_manifest'] = json.loads(archive.read('download.json'))
|
|
printf_address = int(re.search(r'^([0-9a-fA-F]+) T printf$', symbols, re.M).group(1), 16)
|
|
for symbol, binary, expected in [
|
|
('quec_get_gnssid_task', root / 'ql-kernel/threadx/build/kernel.axf', '<RTI_LOG>'),
|
|
('app_gnss_init', app, '0x%08x' % (printf_address | 1)),
|
|
('set_gnss_mode', app, 'bx\tlr')]:
|
|
body = subprocess.check_output([str(objdump), '-d', '--disassemble=' + symbol, str(binary)], text=True)
|
|
assert '<' + symbol + '>:' in body and expected in body and 'task_create' not in body
|
|
(output / (symbol + '.disasm.txt')).write_text(body)
|
|
report['verification'] = 'PASS: ZIP CRC, current APP/kernel identity, GNSS bypass, WSS URL, ECDSA/GCM/RTC/NIST kernel symbols and handshake timing logs'
|
|
(output / 'verification.json').write_text(json.dumps(report, indent=2))
|
|
print(report['verification'])
|
|
print('SHA256:', report['sha256'])
|