|
|
@@ -5,7 +5,7 @@
|
|
5
|
5
|
use core::convert::TryInto;
|
|
6
|
6
|
|
|
7
|
7
|
use crc16::{State, KERMIT};
|
|
8
|
|
-use xxtea_nostd::decrypt;
|
|
|
8
|
+use xxtea_nostd::{decrypt, encrypt};
|
|
9
|
9
|
|
|
10
|
10
|
#[derive(Debug, Clone)]
|
|
11
|
11
|
pub enum Packet {
|
|
|
@@ -27,6 +27,17 @@ impl Packet {
|
|
27
|
27
|
Self::decode(&checksummed[..22])
|
|
28
|
28
|
}
|
|
29
|
29
|
|
|
|
30
|
+ pub fn encode_and_encrypt(&self, key: &[u8], salt: u64, data: &mut [u8]) -> bool {
|
|
|
31
|
+ data[0..8].copy_from_slice(&salt.to_le_bytes());
|
|
|
32
|
+ if !self.encode(&mut data[8..30]) {
|
|
|
33
|
+ return false;
|
|
|
34
|
+ }
|
|
|
35
|
+ let checksum = State::<KERMIT>::calculate(&data[0..30]);
|
|
|
36
|
+ data[30..].copy_from_slice(&checksum.to_le_bytes());
|
|
|
37
|
+ encrypt_cbc(key, data);
|
|
|
38
|
+ true
|
|
|
39
|
+ }
|
|
|
40
|
+
|
|
30
|
41
|
fn decode(data: &[u8]) -> Option<Packet> {
|
|
31
|
42
|
let type_ = data[0] & 0x1f;
|
|
32
|
43
|
// count can be at most 7, so we do not need any checks when indexing 8-element arrays
|
|
|
@@ -44,6 +55,32 @@ impl Packet {
|
|
44
|
55
|
_ => None,
|
|
45
|
56
|
}
|
|
46
|
57
|
}
|
|
|
58
|
+
|
|
|
59
|
+ fn encode(&self, data: &mut [u8]) -> bool {
|
|
|
60
|
+ match self {
|
|
|
61
|
+ Self::GetSalt => {
|
|
|
62
|
+ data[0] = 0;
|
|
|
63
|
+ true
|
|
|
64
|
+ }
|
|
|
65
|
+ Self::Salt(salt) => {
|
|
|
66
|
+ data[0] = 1;
|
|
|
67
|
+ data[1..9].copy_from_slice(&salt.to_le_bytes());
|
|
|
68
|
+ true
|
|
|
69
|
+ }
|
|
|
70
|
+ Self::Report(report) => {
|
|
|
71
|
+ // TODO
|
|
|
72
|
+ false
|
|
|
73
|
+ }
|
|
|
74
|
+ Self::GetValues(get_values) => {
|
|
|
75
|
+ // TODO
|
|
|
76
|
+ false
|
|
|
77
|
+ }
|
|
|
78
|
+ Self::Values(values) => {
|
|
|
79
|
+ // TODO
|
|
|
80
|
+ false
|
|
|
81
|
+ }
|
|
|
82
|
+ }
|
|
|
83
|
+ }
|
|
47
|
84
|
}
|
|
48
|
85
|
|
|
49
|
86
|
#[derive(Debug, Clone)]
|
|
|
@@ -144,6 +181,16 @@ pub enum ValueType {
|
|
144
|
181
|
Humidity,
|
|
145
|
182
|
}
|
|
146
|
183
|
|
|
|
184
|
+fn encrypt_cbc(key: &[u8], data: &mut [u8]) {
|
|
|
185
|
+ for i in 0..data.len() / 8 - 1 {
|
|
|
186
|
+ let (prev, block) = data[i * 8..i * 8 + 16].split_at_mut(8);
|
|
|
187
|
+ for j in 0..8 {
|
|
|
188
|
+ block[j] ^= prev[j];
|
|
|
189
|
+ }
|
|
|
190
|
+ encrypt(&key, block);
|
|
|
191
|
+ }
|
|
|
192
|
+}
|
|
|
193
|
+
|
|
147
|
194
|
fn decrypt_cbc(key: &[u8], data: &mut [u8]) {
|
|
148
|
195
|
let mut blocks = data.rchunks_mut(8).peekable();
|
|
149
|
196
|
loop {
|