Aucune description
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

lib.rs 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. //! Library which implements serialization and deserialization for the packet format used by the
  2. //! base station and all sensor/display nodes.
  3. #![no_std]
  4. #[cfg(test)]
  5. extern crate std;
  6. use core::convert::TryInto;
  7. use crc16::{State, KERMIT};
  8. use xxtea_nostd::{decrypt, encrypt};
  9. #[derive(Debug, Clone, PartialEq)]
  10. pub enum Packet {
  11. GetSalt,
  12. Salt(u64),
  13. Report(Report),
  14. GetValues(GetValues),
  15. Values(Values),
  16. }
  17. impl Packet {
  18. pub fn decrypt_and_decode(key: &[u8], data: &mut [u8]) -> Result<Packet, Error> {
  19. decrypt_cbc(key, data);
  20. let checksummed = &data[8..];
  21. let remainder = State::<KERMIT>::calculate(&checksummed);
  22. if remainder != 0 {
  23. return Err(Error::CRC);
  24. }
  25. Self::decode(&checksummed[..22])
  26. }
  27. pub fn encode_and_encrypt(&self, key: &[u8], salt: u64, data: &mut [u8]) -> bool {
  28. data[0..8].copy_from_slice(&salt.to_le_bytes());
  29. if !self.encode(&mut data[8..30]) {
  30. return false;
  31. }
  32. let checksum = State::<KERMIT>::calculate(&data[8..30]);
  33. data[30..].copy_from_slice(&checksum.to_le_bytes());
  34. encrypt_cbc(key, data);
  35. true
  36. }
  37. fn decode(data: &[u8]) -> Result<Packet, Error> {
  38. let type_ = data[0] & 0x1f;
  39. // count can be at most 7, so we do not need any checks when indexing 8-element arrays
  40. // below.
  41. let count = data[0] >> 5;
  42. match type_ {
  43. 0 => Ok(Self::GetSalt),
  44. 1 => Ok(Self::Salt({
  45. // The lowest 8 bit of the salt are the device ID and are filled in by the caller.
  46. u64::from_le_bytes(data[1..9].try_into().unwrap()) << 8
  47. })),
  48. 2 => Ok(Self::Report(Report::decode(count, &data[1..])?)),
  49. 3 => Ok(Self::GetValues(GetValues::decode(count, &data[1..])?)),
  50. 4 => Ok(Self::Values(Values::decode(count, &data[1..])?)),
  51. _ => Err(Error::InvalidPacketType),
  52. }
  53. }
  54. fn encode(&self, data: &mut [u8]) -> bool {
  55. match self {
  56. Self::GetSalt => {
  57. data[0] = 0;
  58. true
  59. }
  60. Self::Salt(salt) => {
  61. data[0] = 1;
  62. data[1..8].copy_from_slice(&(salt >> 8 as u64).to_le_bytes()[0..7]);
  63. true
  64. }
  65. Self::Report(report) => {
  66. data[0] = (report.count << 5) | 2;
  67. report.encode(&mut data[1..])
  68. }
  69. Self::GetValues(get_values) => {
  70. data[0] = (get_values.count << 5) | 2;
  71. get_values.encode(&mut data[1..])
  72. }
  73. Self::Values(values) => {
  74. data[0] = (values.count << 5) | 2;
  75. values.encode(&mut data[1..])
  76. }
  77. }
  78. }
  79. }
  80. #[derive(Debug, Clone, PartialEq)]
  81. pub struct Report {
  82. pub count: u8,
  83. pub values: [Value; 8],
  84. }
  85. impl Report {
  86. fn decode(count: u8, mut data: &[u8]) -> Result<Report, Error> {
  87. let mut report = Self {
  88. count,
  89. values: [Value::Invalid; 8],
  90. };
  91. for i in 0..count {
  92. report.values[i as usize] = Value::decode(&mut data)?;
  93. }
  94. Ok(report)
  95. }
  96. fn encode(&self, mut data: &mut [u8]) -> bool {
  97. for i in 0..self.count {
  98. let value_len = self.values[i as usize].encoded_length();
  99. if data.len() < value_len {
  100. return false;
  101. }
  102. if !self.values[i as usize].encode(data) {
  103. return false;
  104. }
  105. data = &mut data[value_len..];
  106. }
  107. true
  108. }
  109. }
  110. #[derive(Debug, Clone, PartialEq)]
  111. pub struct GetValues {
  112. pub count: u8,
  113. pub location: Location,
  114. pub types_: [ValueType; 8],
  115. }
  116. impl GetValues {
  117. fn decode(_count: u8, _data: &[u8]) -> Result<GetValues, Error> {
  118. // TODO
  119. Err(Error::InvalidPacketType)
  120. }
  121. fn encode(&self, mut _data: &[u8]) -> bool {
  122. // TODO
  123. false
  124. }
  125. }
  126. #[derive(Debug, Clone, PartialEq)]
  127. pub struct Values {
  128. pub count: u8,
  129. pub location: Location,
  130. pub values: [Value; 8],
  131. }
  132. impl Values {
  133. fn decode(_count: u8, _data: &[u8]) -> Result<Values, Error> {
  134. // TODO
  135. Err(Error::InvalidPacketType)
  136. }
  137. fn encode(&self, mut _data: &[u8]) -> bool {
  138. // TODO
  139. false
  140. }
  141. }
  142. #[derive(Debug, Clone, Copy, PartialEq)]
  143. pub enum Location {
  144. Livingroom,
  145. Bathroom,
  146. Bedroom,
  147. Kitchen,
  148. Balcony,
  149. }
  150. #[derive(Debug, Clone, Copy, PartialEq)]
  151. pub enum Value {
  152. Invalid,
  153. Time(u64),
  154. Temperature(i16),
  155. Pressure(u32),
  156. Humidity(u16),
  157. }
  158. impl Value {
  159. fn decode(data: &mut &[u8]) -> Result<Value, Error> {
  160. let type_ = data[0];
  161. let length = match type_ {
  162. 0 => 9,
  163. 1 => 3,
  164. 2 => 5,
  165. 3 => 3,
  166. _ => return Err(Error::InvalidValueType),
  167. };
  168. if data.len() < length {
  169. return Err(Error::TooShort);
  170. }
  171. let result = match type_ {
  172. 0 => Self::Time(u64::from_le_bytes(data[1..9].try_into().unwrap())),
  173. 1 => Self::Temperature(i16::from_le_bytes(data[1..3].try_into().unwrap())),
  174. 2 => Self::Pressure(u32::from_le_bytes(data[1..5].try_into().unwrap())),
  175. 3 => Self::Humidity(u16::from_le_bytes(data[1..3].try_into().unwrap())),
  176. _ => return Err(Error::InvalidValueType),
  177. };
  178. *data = &data[length..];
  179. Ok(result)
  180. }
  181. fn encode(&self, data: &mut [u8]) -> bool {
  182. match self {
  183. Self::Invalid => {}
  184. Self::Time(time) => {
  185. data[0] = 0;
  186. data[1..9].copy_from_slice(&time.to_le_bytes());
  187. }
  188. Self::Temperature(temperature) => {
  189. data[0] = 1;
  190. data[1..3].copy_from_slice(&temperature.to_le_bytes());
  191. }
  192. Self::Pressure(pressure) => {
  193. data[0] = 2;
  194. data[1..5].copy_from_slice(&pressure.to_le_bytes());
  195. }
  196. Self::Humidity(humidity) => {
  197. data[0] = 3;
  198. data[1..3].copy_from_slice(&humidity.to_le_bytes());
  199. }
  200. };
  201. true
  202. }
  203. fn encoded_length(&self) -> usize {
  204. match self {
  205. Self::Invalid => 0,
  206. Self::Time(_) => 9,
  207. Self::Temperature(_) => 3,
  208. Self::Pressure(_) => 5,
  209. Self::Humidity(_) => 3,
  210. }
  211. }
  212. pub fn split(&self) -> Option<(ValueType, i64)> {
  213. match self {
  214. Self::Invalid => None,
  215. Self::Time(t) => Some((ValueType::Time, *t as i64)),
  216. Self::Temperature(t) => Some((ValueType::Temperature, *t as i64)),
  217. Self::Pressure(p) => Some((ValueType::Pressure, *p as i64)),
  218. Self::Humidity(h) => Some((ValueType::Humidity, *h as i64)),
  219. }
  220. }
  221. pub fn combine(type_: ValueType, value: i64) -> Value {
  222. match type_ {
  223. ValueType::Time => Self::Time(value as u64),
  224. ValueType::Temperature => Self::Temperature(value as i16),
  225. ValueType::Pressure => Self::Pressure(value as u32),
  226. ValueType::Humidity => Self::Humidity(value as u16),
  227. }
  228. }
  229. }
  230. #[derive(Debug, Clone, Copy, PartialEq)]
  231. pub enum ValueType {
  232. Time,
  233. Temperature,
  234. Pressure,
  235. Humidity,
  236. }
  237. fn encrypt_cbc(key: &[u8], data: &mut [u8]) {
  238. for i in 0..data.len() / 8 - 1 {
  239. let (prev, block) = data[i * 8..i * 8 + 16].split_at_mut(8);
  240. for j in 0..8 {
  241. block[j] ^= prev[j];
  242. }
  243. encrypt(&key, block);
  244. }
  245. }
  246. fn decrypt_cbc(key: &[u8], data: &mut [u8]) {
  247. let mut blocks = data.rchunks_mut(8).peekable();
  248. loop {
  249. let block = blocks.next().unwrap();
  250. let prev_block = match blocks.peek() {
  251. Some(b) => b,
  252. None => break,
  253. };
  254. decrypt(&key, block);
  255. for i in 0..8 {
  256. block[i] ^= prev_block[i];
  257. }
  258. }
  259. }
  260. #[derive(Debug, Copy, Clone)]
  261. pub enum Error {
  262. CRC,
  263. InvalidPacketType,
  264. InvalidValueType,
  265. InvalidLocation,
  266. TooShort,
  267. }
  268. #[cfg(test)]
  269. mod tests {
  270. use super::*;
  271. use std::println;
  272. #[test]
  273. fn test_identity() {
  274. let packets = [Packet::GetSalt, Packet::Salt(0x12345678abcdef12)];
  275. let key = [
  276. 0x12, 0x34, 0x56, 0x78, 0xab, 0xcd, 0xef, 0x12, 0x12, 0x34, 0x56, 0x78, 0xab, 0xcd,
  277. 0xef, 0x12,
  278. ];
  279. for packet in packets.iter() {
  280. let mut encoded = [0u8; 32];
  281. packet.encode_and_encrypt(&key, 0x1234123412341234, &mut encoded);
  282. assert_eq!(encoded[0], 0x34);
  283. assert_eq!(encoded[7], 0x12);
  284. let decoded = Packet::decrypt_and_decode(&key, &mut encoded).unwrap();
  285. // TODO: Compare encoded and decoded.
  286. }
  287. }
  288. }