nx_tuya_smartconfig.nx source
↩ module page · 89 lines · 3378 B
1// nx_tuya_smartconfig.nx -- SOVEREIGN Tuya smartconfig BROADCAST encoder.
2//
3// Faithful port of tuya-convert's broadcast.py + crc.py (kueblc 2019, broadcast ported from
4// tuyapi/link), sovereignly fetched to knowledge/fetched/tuya_{broadcast,crc}.raw. Produces the UDP
5// packet-LENGTH body a Tuya device in EZ mode sniffs. The FULL broadcast = broadcast_head [1,3,6,10]
6// (sent in the header phase) + this body, sent as UDP to 255.255.255.255:30011 (payload = `\0`*len),
7// 5ms gap. Tuya CRC-8 is its OWN polynomial (per-bit: if (r^b)&1: r^=0x18;r>>=1;r|=0x80 else r>>=1) --
8// NOT the Dallas/Maxim of ESP-Touch. The device DECODES the lengths -> SSID+password+token -> joins.
9// NEVER-BRICK #26: emits reversible Wi-Fi creds only. license_tier: ORIGINAL
10import "nx_syscalls_x86_64.nx"
11const K_MAGIC_1024: i64 = 1024
12
13// Tuya CRC-8 of one byte (local r starts 0).
14func nx_tuya_crc8_byte(bIn: i64) -> i64 {
15 var r: i64 = 0
16 var b: i64 = bIn
17 var i: i64 = 0
18 while i < 8 {
19 if ((r ^ b) & 1) != 0 { r = r ^ 0x18; r = r >> 1; r = r | 0x80 } else { r = r >> 1 }
20 b = b >> 1
21 i = i + 1
22 }
23 return r
24}
25// crc_8 fold over n i64 values: r=0; for b: r = crc8byte(r ^ b)
26func nx_tuya_crc8(arr: *i64, n: i64) -> i64 {
27 var r: i64 = 0
28 var i: i64 = 0
29 while i < n { r = nx_tuya_crc8_byte(r ^ arr[i]); i = i + 1 }
30 return r
31}
32
33// encode_broadcast_body -> out[] body lengths; returns count or -1 on overflow.
34// r = [len(pw)] + pw + [len(tok)] + tok + ssid ; device decodes pw/token/ssid from these.
35func nx_tuya_bcast(pw: *u8, pw_n: i64, ssid: *u8, ssid_n: i64, tok: *u8, tok_n: i64,
36 out: *i64, cap: i64) -> i64 {
37 let r: *i64 = sys_mmap(8 * K_MAGIC_1024) as *i64
38 var rn: i64 = 0
39 r[rn] = pw_n; rn = rn + 1
40 var i: i64 = 0
41 while i < pw_n { r[rn] = (pw[i] as i64) & 0xff; rn = rn + 1; i = i + 1 }
42 r[rn] = tok_n; rn = rn + 1
43 i = 0
44 while i < tok_n { r[rn] = (tok[i] as i64) & 0xff; rn = rn + 1; i = i + 1 }
45 i = 0
46 while i < ssid_n { r[rn] = (ssid[i] as i64) & 0xff; rn = rn + 1; i = i + 1 }
47 let length: i64 = rn
48
49 let onev: *i64 = sys_mmap(16) as *i64
50 onev[0] = length
51 let lcrc: i64 = nx_tuya_crc8(onev, 1)
52
53 if cap < 4 { return 0 - 1 }
54 var o: i64 = 0
55 out[o] = (length >> 4) | 16; o = o + 1
56 out[o] = (length & 0xF) | 32; o = o + 1
57 out[o] = (lcrc >> 4) | 48; o = o + 1
58 out[o] = (lcrc & 0xF) | 64; o = o + 1
59
60 var seq: i64 = 0
61 var idx: i64 = 0
62 var last_i: i64 = 0
63 while idx < length {
64 last_i = idx
65 // group_crc = crc_8([seq, r[idx..idx+4] padded to 0])
66 var gcrc: i64 = nx_tuya_crc8_byte(0 ^ seq)
67 var k: i64 = 0
68 while k < 4 {
69 var bv: i64 = 0
70 if (idx + k) < length { bv = r[idx + k] }
71 gcrc = nx_tuya_crc8_byte(gcrc ^ bv)
72 k = k + 1
73 }
74 if (o + 2) > cap { return 0 - 1 }
75 out[o] = (gcrc & 0x7F) | 128; o = o + 1
76 out[o] = seq | 128; o = o + 1
77 k = 0
78 while k < 4 {
79 if (idx + k) < length { if o >= cap { return 0 - 1 } out[o] = r[idx + k] | 256; o = o + 1 }
80 k = k + 1
81 }
82 seq = seq + 1
83 idx = idx + 4
84 }
85 var pad: i64 = length - last_i
86 var p: i64 = 0
87 while p < pad { if o >= cap { return 0 - 1 } out[o] = 256; o = o + 1; p = p + 1 }
88 return o
89}