Implement the menu
parent
4396e6a43d
commit
f83638bfae
167
src/main.rs
167
src/main.rs
|
@ -27,8 +27,9 @@ const SET_TIMESTAMP: u8 = 10;
|
||||||
const ADD_TOKEN: u8 = 20;
|
const ADD_TOKEN: u8 = 20;
|
||||||
const DELETE_TOKEN: u8 = 30;
|
const DELETE_TOKEN: u8 = 30;
|
||||||
const GET_TOKENS: u8 = 40;
|
const GET_TOKENS: u8 = 40;
|
||||||
const WIPE_TOKENS: u8 = 50;
|
const SOFT_WIPE_TOKENS: u8 = 50;
|
||||||
const EXIT: u8 = 254;
|
const HARD_WIPE_TOKENS: u8 = 60;
|
||||||
|
const EXIT: u8 = 255;
|
||||||
|
|
||||||
#[arduino_hal::entry]
|
#[arduino_hal::entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
|
@ -62,68 +63,31 @@ fn main() -> ! {
|
||||||
let mut tokens = storage::Tokens::new(&mut eeprom, datetime.unix_epoch());
|
let mut tokens = storage::Tokens::new(&mut eeprom, datetime.unix_epoch());
|
||||||
|
|
||||||
let up = pins.d6.into_pull_up_input();
|
let up = pins.d6.into_pull_up_input();
|
||||||
let mut button = button::Button::new(&up, true);
|
let mut up_button = button::Button::new(&up, true);
|
||||||
|
let down = pins.d7.into_pull_up_input();
|
||||||
|
let mut down_button = button::Button::new(&down, true);
|
||||||
|
|
||||||
button.update();
|
up_button.update();
|
||||||
if button.update() == button::Event::Pressed {
|
if up_button.update() == button::Event::Pressed {
|
||||||
display.write_str("Connected to");
|
display.write_str("Connected to");
|
||||||
display.set_cursor(0, 1);
|
display.set_cursor(0, 1);
|
||||||
display.write_str("USB...");
|
display.write_str("USB...");
|
||||||
loop {
|
loop {
|
||||||
// Waiting from a command since the tool
|
// Waiting from a command from the tool
|
||||||
let cmd = block!(serial.read()).unwrap_or(u8::MAX);
|
let cmd = block!(serial.read()).unwrap_or(u8::MAX);
|
||||||
display.set_cursor(8, 1);
|
|
||||||
display.write_str("---");
|
|
||||||
display.set_cursor(8, 1);
|
|
||||||
display.write_u32(cmd as u32);
|
|
||||||
|
|
||||||
match cmd {
|
match cmd {
|
||||||
EXIT => {}
|
EXIT => {}
|
||||||
HANDSHAKE => serial.write(OK).unwrap(),
|
HANDSHAKE => serial.write(OK).unwrap(),
|
||||||
SET_TIMESTAMP => {
|
SET_TIMESTAMP => {
|
||||||
serial.write(OK).unwrap();
|
serial.write(OK).unwrap();
|
||||||
let year = loop {
|
let year = block!(serial.read()).unwrap();
|
||||||
let y = block!(serial.read()).unwrap();
|
let month = block!(serial.read()).unwrap();
|
||||||
serial.write(y).unwrap();
|
let day = block!(serial.read()).unwrap();
|
||||||
if block!(serial.read()).unwrap() == OK {
|
let hours = block!(serial.read()).unwrap();
|
||||||
break y;
|
let minutes = block!(serial.read()).unwrap();
|
||||||
}
|
let seconds = block!(serial.read()).unwrap();
|
||||||
};
|
|
||||||
let month = loop {
|
|
||||||
let m = block!(serial.read()).unwrap();
|
|
||||||
serial.write(m).unwrap();
|
|
||||||
if block!(serial.read()).unwrap() == OK {
|
|
||||||
break m;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let day = loop {
|
|
||||||
let d = block!(serial.read()).unwrap();
|
|
||||||
serial.write(d).unwrap();
|
|
||||||
if block!(serial.read()).unwrap() == OK {
|
|
||||||
break d;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let hours = loop {
|
|
||||||
let h = block!(serial.read()).unwrap();
|
|
||||||
serial.write(h).unwrap();
|
|
||||||
if block!(serial.read()).unwrap() == OK {
|
|
||||||
break h;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let minutes = loop {
|
|
||||||
let m = block!(serial.read()).unwrap();
|
|
||||||
serial.write(m).unwrap();
|
|
||||||
if block!(serial.read()).unwrap() == OK {
|
|
||||||
break m;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let seconds = loop {
|
|
||||||
let s = block!(serial.read()).unwrap();
|
|
||||||
serial.write(s).unwrap();
|
|
||||||
if block!(serial.read()).unwrap() == OK {
|
|
||||||
break s;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
rtc.set_year(year as u16 + 2000).unwrap();
|
rtc.set_year(year as u16 + 2000).unwrap();
|
||||||
rtc.set_month(month).unwrap();
|
rtc.set_month(month).unwrap();
|
||||||
rtc.set_day(day).unwrap();
|
rtc.set_day(day).unwrap();
|
||||||
|
@ -155,53 +119,84 @@ fn main() -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match tokens.write(index, &name_buff, &key_buff) {
|
match tokens.write(index, &name_buff, &key_buff) {
|
||||||
Some(_) => serial.write(OK).unwrap(),
|
Ok(_) => serial.write(OK).unwrap(),
|
||||||
None => serial.write(ERROR).unwrap(),
|
Err(_) => serial.write(ERROR).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => serial.write(ERROR).unwrap(),
|
None => serial.write(ERROR).unwrap(),
|
||||||
},
|
},
|
||||||
WIPE_TOKENS => {
|
SOFT_WIPE_TOKENS => {
|
||||||
serial.write(OK).unwrap();
|
serial.write(OK).unwrap();
|
||||||
tokens.wipe_all_tokens();
|
tokens.soft_wipe_all_tokens();
|
||||||
serial.write(OK).unwrap();
|
serial.write(OK).unwrap();
|
||||||
}
|
}
|
||||||
|
HARD_WIPE_TOKENS => {
|
||||||
|
serial.write(OK).unwrap();
|
||||||
|
tokens.hard_wipe_all_tokens();
|
||||||
|
serial.write(OK).unwrap();
|
||||||
|
}
|
||||||
|
EXIT => break,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match tokens.current {
|
let mut changed = false;
|
||||||
Some(index) => {
|
let mut last_index = 100;
|
||||||
let mut buff_name = [0u8; SECRET_KEY_NAME_LEN as usize];
|
let mut last_time = 0;
|
||||||
let mut buff_key = [0u8; SECRET_KEY_MAX_LEN as usize];
|
|
||||||
match tokens.read(index, &mut buff_name, &mut buff_key) {
|
|
||||||
Some((len_name, len_key)) => {
|
|
||||||
let name = core::str::from_utf8(&buff_name[..len_name]).unwrap();
|
|
||||||
let key = &buff_key[..len_key];
|
|
||||||
let dt = datetime::Datetime::from_ds3231(&mut rtc);
|
|
||||||
|
|
||||||
let timestamp = dt.unix_epoch();
|
|
||||||
|
|
||||||
let token = generate_otp_token(key, timestamp);
|
|
||||||
|
|
||||||
display.set_cursor(0, 0);
|
|
||||||
display.write_str(name);
|
|
||||||
display.set_cursor(0, 1);
|
|
||||||
display.write_u32(token);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// display.clear();
|
|
||||||
// display.set_cursor(0, 0);
|
|
||||||
// display.write_str("ERROR");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
led.toggle();
|
let timestamp = datetime::Datetime::from_ds3231(&mut rtc).unix_epoch();
|
||||||
delay_ms(1000);
|
|
||||||
|
if up_button.update() == button::Event::PressUp {
|
||||||
|
changed = true;
|
||||||
|
tokens.next();
|
||||||
|
}
|
||||||
|
if down_button.update() == button::Event::PressUp {
|
||||||
|
todo!("To be implemented");
|
||||||
|
}
|
||||||
|
let curr_time = INTERVAL - (timestamp % INTERVAL);
|
||||||
|
if curr_time == last_time {
|
||||||
|
delay_ms(10);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
last_time = curr_time;
|
||||||
|
display.set_cursor(12, 1);
|
||||||
|
display.write_str(" ");
|
||||||
|
display.set_cursor(12, 1);
|
||||||
|
display.write_u8(curr_time as u8);
|
||||||
|
|
||||||
|
if changed {
|
||||||
|
display.set_cursor(0, 0);
|
||||||
|
display.write_str(" ");
|
||||||
|
changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match tokens.current {
|
||||||
|
Some(index) => {
|
||||||
|
let mut buff_name = [0u8; SECRET_KEY_NAME_LEN as usize];
|
||||||
|
let mut buff_key = [0u8; SECRET_KEY_MAX_LEN as usize];
|
||||||
|
match tokens.read(index, &mut buff_name, &mut buff_key) {
|
||||||
|
Ok((len_name, len_key)) => {
|
||||||
|
let name = core::str::from_utf8(&buff_name[..len_name]).unwrap();
|
||||||
|
let key = &buff_key[..len_key];
|
||||||
|
|
||||||
|
let token = generate_otp_token(key, timestamp);
|
||||||
|
|
||||||
|
display.set_cursor(0, 0);
|
||||||
|
display.write_str(name);
|
||||||
|
display.set_cursor(0, 1);
|
||||||
|
display.write_token(token);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
display.clear();
|
||||||
|
display.set_cursor(0, 0);
|
||||||
|
display.write_str("ERROR");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
changed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,40 @@ impl<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_token(&mut self, mut token: u32) {
|
||||||
|
let mut buff = [0u8; 7];
|
||||||
|
for (n, chr) in buff.iter_mut().enumerate() {
|
||||||
|
*chr = if n == 3 {
|
||||||
|
'-' as u8
|
||||||
|
} else {
|
||||||
|
let ch = (token % 10) as u8 + '0' as u8;
|
||||||
|
token /= 10;
|
||||||
|
ch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buff.reverse();
|
||||||
|
let s = core::str::from_utf8(&buff).unwrap();
|
||||||
|
self.write_str(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_u8(&mut self, mut num: u8) {
|
||||||
|
if num == 0 {
|
||||||
|
self.write_char('0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buff = [0u8; 3];
|
||||||
|
let num_len = num.ilog10() as usize;
|
||||||
|
for i in (0..=num_len).rev() {
|
||||||
|
buff[i] = num % 10 + '0' as u8;
|
||||||
|
num /= 10;
|
||||||
|
}
|
||||||
|
self.write_str(core::str::from_utf8(&buff[..=num_len]).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_u32(&mut self, num: u32) {
|
pub fn write_u32(&mut self, num: u32) {
|
||||||
|
// This function is for debugging purposes only, it does not show
|
||||||
|
// The 0's to the right of the number
|
||||||
// The max number in an u32 is: 4,294,967,295
|
// The max number in an u32 is: 4,294,967,295
|
||||||
let mut buff = [0; 10];
|
let mut buff = [0; 10];
|
||||||
let len = num_chars(num, &mut buff);
|
let len = num_chars(num, &mut buff);
|
||||||
|
|
|
@ -64,19 +64,15 @@ impl<'a> Tokens<'a> {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&self, index: u16, name: &mut [u8], key: &mut [u8]) -> Option<(usize, usize)> {
|
pub fn read(&self, index: u16, name: &mut [u8], key: &mut [u8]) -> Result<(usize, usize), ()> {
|
||||||
name.fill(0);
|
name.fill(0);
|
||||||
key.fill(0);
|
key.fill(0);
|
||||||
let index_name = index * SECRET_KEY_FULL_LEN;
|
let index_name = index * SECRET_KEY_FULL_LEN;
|
||||||
let index_key = (index * SECRET_KEY_FULL_LEN) + SECRET_KEY_NAME_LEN;
|
let index_key = (index * SECRET_KEY_FULL_LEN) + SECRET_KEY_NAME_LEN;
|
||||||
match self.mem.read(index_name, name) {
|
|
||||||
Ok(_) => {}
|
self.mem.read(index_name, name).map_err(|_| ())?;
|
||||||
Err(_) => return None,
|
self.mem.read(index_key, key).map_err(|_| ())?;
|
||||||
}
|
|
||||||
match self.mem.read(index_key, key) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(_) => return None,
|
|
||||||
}
|
|
||||||
let len_name = name
|
let len_name = name
|
||||||
.iter()
|
.iter()
|
||||||
.position(|&n| n == 0)
|
.position(|&n| n == 0)
|
||||||
|
@ -85,21 +81,17 @@ impl<'a> Tokens<'a> {
|
||||||
.iter()
|
.iter()
|
||||||
.position(|&n| n == 0)
|
.position(|&n| n == 0)
|
||||||
.unwrap_or(SECRET_KEY_MAX_LEN as usize);
|
.unwrap_or(SECRET_KEY_MAX_LEN as usize);
|
||||||
Some((len_name, len_key))
|
Ok((len_name, len_key))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&mut self, index: u16, name: &[u8], key: &[u8]) -> Option<u16> {
|
pub fn write(&mut self, index: u16, name: &[u8], key: &[u8]) -> Result<u16, ()> {
|
||||||
let index_name = index * SECRET_KEY_FULL_LEN;
|
let index_name = index * SECRET_KEY_FULL_LEN;
|
||||||
let index_key = (index * SECRET_KEY_FULL_LEN) + SECRET_KEY_NAME_LEN;
|
let index_key = (index * SECRET_KEY_FULL_LEN) + SECRET_KEY_NAME_LEN;
|
||||||
match self.mem.write(index_name, name) {
|
|
||||||
Ok(_) => {}
|
self.mem.write(index_name, name).map_err(|_| ())?;
|
||||||
Err(_) => return None,
|
self.mem.write(index_key, key).map_err(|_| ())?;
|
||||||
}
|
|
||||||
match self.mem.write(index_key, key) {
|
Ok(index)
|
||||||
Ok(_) => {}
|
|
||||||
Err(_) => return None,
|
|
||||||
}
|
|
||||||
Some(index)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(&mut self, index: u16) -> Option<u16> {
|
pub fn delete(&mut self, index: u16) -> Option<u16> {
|
||||||
|
@ -116,7 +108,7 @@ impl<'a> Tokens<'a> {
|
||||||
Some(index)
|
Some(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wipe_all_tokens(&mut self) -> u8 {
|
pub fn soft_wipe_all_tokens(&mut self) -> u8 {
|
||||||
let mut inc = 0;
|
let mut inc = 0;
|
||||||
|
|
||||||
for n in 0..self.capacity {
|
for n in 0..self.capacity {
|
||||||
|
@ -128,4 +120,8 @@ impl<'a> Tokens<'a> {
|
||||||
}
|
}
|
||||||
inc
|
inc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hard_wipe_all_tokens(&mut self) {
|
||||||
|
self.mem.erase(0, self.mem.capacity()).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,18 +37,6 @@ def process_secret(secret: str) -> bytes:
|
||||||
secret += "=" * offset
|
secret += "=" * offset
|
||||||
return base64.b32decode(secret, casefold=True)
|
return base64.b32decode(secret, casefold=True)
|
||||||
|
|
||||||
def send_and_validate(value: bytes, conn):
|
|
||||||
while True:
|
|
||||||
print(f"Send {list(value)}")
|
|
||||||
conn.write(value)
|
|
||||||
resp = conn.read()
|
|
||||||
print(f"Received {list(resp)}")
|
|
||||||
if resp == value:
|
|
||||||
conn.write(OK)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
conn.write(ERROR)
|
|
||||||
|
|
||||||
def get_datetime_items() -> dict[str, bytes]:
|
def get_datetime_items() -> dict[str, bytes]:
|
||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
|
|
||||||
|
@ -98,12 +86,12 @@ def main(argv: list[str]):
|
||||||
print(f"Error in the communication: Error {resp}")
|
print(f"Error in the communication: Error {resp}")
|
||||||
continue
|
continue
|
||||||
date_items = get_datetime_items();
|
date_items = get_datetime_items();
|
||||||
send_and_validate(date_items["year"], conn)
|
conn.write(date_items["year"])
|
||||||
send_and_validate(date_items["month"], conn)
|
conn.write(date_items["month"])
|
||||||
send_and_validate(date_items["day"], conn)
|
conn.write(date_items["day"])
|
||||||
send_and_validate(date_items["hours"], conn)
|
conn.write(date_items["hours"])
|
||||||
send_and_validate(date_items["minutes"], conn)
|
conn.write(date_items["minutes"])
|
||||||
send_and_validate(date_items["seconds"], conn)
|
conn.write(date_items["seconds"])
|
||||||
resp = conn.read()
|
resp = conn.read()
|
||||||
if resp != OK:
|
if resp != OK:
|
||||||
print(f"Error in the communication: Error {resp}")
|
print(f"Error in the communication: Error {resp}")
|
||||||
|
|
Loading…
Reference in New Issue