128 lines
3.7 KiB
Rust
128 lines
3.7 KiB
Rust
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<u16>,
|
|
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<u16> {
|
|
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<u16> {
|
|
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<u16> {
|
|
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<u16> {
|
|
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<u16, ()> {
|
|
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<u16> {
|
|
// 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);
|
|
}
|
|
}
|
|
}
|