Preserve main GNSS and volume behavior while porting verified TLS, receive fixes and full-handshake optimizations. Add MQTT connection diagnostics and route MQTT through banban.api.talkingq.com:1883. Include migration documentation and regression tools. Firmware builds and package checks passed; user confirmed new-board connectivity after switching the MQTT host to the domain.
41 lines
2.4 KiB
Python
41 lines
2.4 KiB
Python
"""Probe TLS 1.2 full-handshake group negotiation with the firmware root CA."""
|
|
import json
|
|
from pathlib import Path
|
|
import re
|
|
import subprocess
|
|
|
|
root = Path(__file__).resolve().parents[1]
|
|
source = (root / 'ql-application/threadx/interface/custom_app/talkingq_root_ca.c').read_text()
|
|
pem = ''.join(json.loads('"' + value + '"') for value in re.findall(r'"(.*?)"', source)
|
|
if 'CERTIFICATE' in value or value.endswith(r'\n'))
|
|
output = root / 'artifacts/wss/full-handshake'
|
|
output.mkdir(parents=True, exist_ok=True)
|
|
ca = output / 'compiled-root.pem'
|
|
ca.write_text(pem)
|
|
openssl = Path('C:/Program Files/Git/usr/bin/openssl.exe')
|
|
groups = {
|
|
'sdk_order': 'P-521:brainpoolP512r1:P-384:brainpoolP384r1:P-256:brainpoolP256r1:P-224:secp224k1:P-192:secp192k1:X25519:X448',
|
|
'x25519_first': 'X25519:P-256:P-384:P-521',
|
|
'p256_first': 'P-256:X25519:P-384:P-521',
|
|
}
|
|
firmware = (root / 'ql-application/threadx/interface/custom_app/lib/librws/src/rws_socketpriv.c').read_bytes().decode('latin1')
|
|
array = re.search(r'rws_tls_preferred_curves\[\]\s*=\s*\{(.*?)\}', firmware, re.S).group(1)
|
|
names = {'CURVE25519': 'X25519', 'CURVE448': 'X448',
|
|
'SECP256R1': 'P-256', 'SECP384R1': 'P-384', 'SECP521R1': 'P-521',
|
|
'SECP224R1': 'P-224', 'SECP192R1': 'P-192',
|
|
'SECP224K1': 'secp224k1', 'SECP192K1': 'secp192k1',
|
|
'BP512R1': 'brainpoolP512r1', 'BP384R1': 'brainpoolP384r1', 'BP256R1': 'brainpoolP256r1'}
|
|
groups['firmware_policy'] = ':'.join(names[name] for name in re.findall(r'MBEDTLS_ECP_DP_(\w+)', array) if name != 'NONE')
|
|
report = {}
|
|
for name, group_list in groups.items():
|
|
result = subprocess.run([str(openssl), 's_client', '-connect', 'banban.api.talkingq.com:443',
|
|
'-servername', 'banban.api.talkingq.com', '-verify_hostname', 'banban.api.talkingq.com',
|
|
'-verify_return_error', '-CAfile', str(ca), '-no-CApath', '-no-CAstore',
|
|
'-tls1_2', '-no_ticket', '-groups', group_list, '-brief'],
|
|
input='', text=True, capture_output=True, timeout=20)
|
|
text = result.stdout + result.stderr
|
|
report[name] = {'groups': group_list, 'returncode': result.returncode, 'output': text}
|
|
print(name + ':\n' + text, flush=True)
|
|
assert result.returncode == 0 and 'Verification: OK' in text, name
|
|
(output / 'group-probe.json').write_text(json.dumps(report, indent=2))
|