use arduino_hal::eeprom::Eeprom; pub const SECRET_KEY_MAX_LEN: u16 = 32; pub const SECRET_KEY_NAME_LEN: u16 = 16; pub const SECRET_KEY_FULL_LEN: u16 = SECRET_KEY_MAX_LEN + SECRET_KEY_NAME_LEN; pub const ENDL: u8 = 0; pub struct Tokens<'a> { mem: &'a mut Eeprom, pub current: Option, capacity: u16, } impl<'a> Tokens<'a> { pub fn new(mem: &'a mut Eeprom) -> Self { let capacity = mem.capacity() / SECRET_KEY_FULL_LEN; let mut tokens = Tokens { mem, capacity, current: None, }; tokens.current = tokens.first(); tokens } pub fn search_free(&self) -> Option { for n in 0..self.capacity { let index = SECRET_KEY_FULL_LEN * n; if self.mem.read_byte(index) == ENDL { return Some(n); } } None } fn first(&self) -> Option { for n in 0..self.capacity { let index = SECRET_KEY_FULL_LEN * n; if self.mem.read_byte(index) != ENDL { return Some(n); } } return None; } pub fn next(&mut self) -> Option { let mut index = self.current.unwrap(); for _ in 0..self.capacity { index = (index + 1) % self.capacity; if self.mem.read_byte(index * SECRET_KEY_FULL_LEN) != ENDL { self.current = Some(index); return Some(index); } } None } pub fn prev(&mut self) -> Option { todo!(); } pub fn read(&self, index: u16, name: &mut [u8], key: &mut [u8]) -> Result<(usize, usize), ()> { name.fill(0); key.fill(0); let index_name = index * SECRET_KEY_FULL_LEN; let index_key = (index * SECRET_KEY_FULL_LEN) + SECRET_KEY_NAME_LEN; self.mem.read(index_name, name).map_err(|_| ())?; self.mem.read(index_key, key).map_err(|_| ())?; let len_name = name .iter() .position(|&n| n == 0) .unwrap_or(SECRET_KEY_NAME_LEN as usize); let len_key = key .iter() .position(|&n| n == 0) .unwrap_or(SECRET_KEY_MAX_LEN as usize); Ok((len_name, len_key)) } pub fn write(&mut self, index: u16, name: &[u8], key: &[u8]) -> Result { let index_name = index * SECRET_KEY_FULL_LEN; let index_key = (index * SECRET_KEY_FULL_LEN) + SECRET_KEY_NAME_LEN; self.mem.write(index_name, name).map_err(|_| ())?; self.mem.write(index_key, key).map_err(|_| ())?; Ok(index) } pub fn delete(&mut self, index: u16) -> Option { // The Arduino's EEPROM memory has a maximum number of write cycles. // To keep writes to a minimum, only the first byte of the token name is set to 0 // and wipe all the secret key let index_token = index * SECRET_KEY_FULL_LEN; let index_key_start = index_token + SECRET_KEY_NAME_LEN; let index_key_end = index_key_start + SECRET_KEY_MAX_LEN - 1; self.mem.write_byte(index_token, ENDL); for index in index_key_start..index_key_end { self.mem.write_byte(index, ENDL); } Some(index) } pub fn soft_wipe_all_tokens(&mut self) -> u8 { let mut inc = 0; for n in 0..self.capacity { let index = SECRET_KEY_FULL_LEN * n; if self.mem.read_byte(index) != ENDL { self.delete(index); inc += 1; } } inc } pub fn hard_wipe_all_tokens(&mut self) { for index in 0..self.mem.capacity() { self.mem.write_byte(index, ENDL); } } }