Files
banban/tools/verify_wss_package.py
T
chenjintao 551a7bb1e6 Prefer X25519 for legacy WSS full handshakes
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.
2026-09-16 15:32:22 +08:00

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'])