201 lines
6.8 KiB
Rust
201 lines
6.8 KiB
Rust
#![no_std]
|
|
#![no_main]
|
|
|
|
mod button;
|
|
mod crypto;
|
|
mod datetime;
|
|
mod screen;
|
|
mod storage;
|
|
|
|
use arduino_hal::default_serial;
|
|
use arduino_hal::delay_ms;
|
|
// use arduino_hal::delay_ms;
|
|
use arduino_hal::prelude::*;
|
|
use crypto::generate_otp_token;
|
|
use crypto::INTERVAL;
|
|
use ds323x::Rtcc;
|
|
use nb::block;
|
|
use panic_halt as _;
|
|
use storage::SECRET_KEY_MAX_LEN;
|
|
use storage::SECRET_KEY_NAME_LEN;
|
|
|
|
const ENDL: u8 = 0;
|
|
const OK: u8 = 1;
|
|
const ERROR: u8 = 2;
|
|
const HANDSHAKE: u8 = 3;
|
|
const SET_TIMESTAMP: u8 = 10;
|
|
const ADD_TOKEN: u8 = 20;
|
|
const DELETE_TOKEN: u8 = 30;
|
|
const GET_TOKENS: u8 = 40;
|
|
const SOFT_WIPE_TOKENS: u8 = 50;
|
|
const HARD_WIPE_TOKENS: u8 = 60;
|
|
const EXIT: u8 = 255;
|
|
|
|
#[arduino_hal::entry]
|
|
fn main() -> ! {
|
|
let dp = arduino_hal::Peripherals::take().unwrap();
|
|
let pins = arduino_hal::pins!(dp);
|
|
|
|
let mut led = pins.d13.into_output();
|
|
let mut serial = default_serial!(dp, pins, 9600);
|
|
|
|
let mut rs = pins.d9.into_output();
|
|
let mut en = pins.d8.into_output();
|
|
let mut d4 = pins.d5.into_output();
|
|
let mut d5 = pins.d4.into_output();
|
|
let mut d6 = pins.d3.into_output();
|
|
let mut d7 = pins.d2.into_output();
|
|
|
|
let mut display = screen::StnScreen::new(&mut rs, &mut en, &mut d4, &mut d5, &mut d6, &mut d7);
|
|
display.clear();
|
|
|
|
let i2c_clock = arduino_hal::I2c::new(
|
|
dp.TWI,
|
|
pins.a4.into_pull_up_input(), // SDA
|
|
pins.a5.into_pull_up_input(), // SCL
|
|
50000,
|
|
);
|
|
let mut rtc = ds323x::Ds323x::new_ds3231(i2c_clock);
|
|
|
|
let mut eeprom = arduino_hal::Eeprom::new(dp.EEPROM);
|
|
let mut tokens = storage::Tokens::new(&mut eeprom);
|
|
|
|
let up = pins.a2.into_pull_up_input();
|
|
let mut up_button = button::Button::new(&up, true);
|
|
let down = pins.a1.into_pull_up_input();
|
|
let mut down_button = button::Button::new(&down, true);
|
|
|
|
up_button.update();
|
|
if up_button.update() == button::Event::Pressed || tokens.current.is_none() {
|
|
display.write_str("Connected to");
|
|
display.set_cursor(0, 1);
|
|
display.write_str("USB...");
|
|
loop {
|
|
// Waiting from a command from the tool
|
|
let cmd = block!(serial.read()).unwrap_or(u8::MAX);
|
|
|
|
match cmd {
|
|
HANDSHAKE => serial.write(OK).unwrap(),
|
|
SET_TIMESTAMP => {
|
|
serial.write(OK).unwrap();
|
|
let year = block!(serial.read()).unwrap();
|
|
let month = block!(serial.read()).unwrap();
|
|
let day = block!(serial.read()).unwrap();
|
|
let hours = block!(serial.read()).unwrap();
|
|
let minutes = block!(serial.read()).unwrap();
|
|
let seconds = block!(serial.read()).unwrap();
|
|
|
|
rtc.set_year(year as u16 + 2000).unwrap();
|
|
rtc.set_month(month).unwrap();
|
|
rtc.set_day(day).unwrap();
|
|
rtc.set_hours(ds323x::Hours::H24(hours)).unwrap();
|
|
rtc.set_minutes(minutes).unwrap();
|
|
rtc.set_seconds(seconds).unwrap();
|
|
serial.write(OK).unwrap();
|
|
}
|
|
ADD_TOKEN => match tokens.search_free() {
|
|
Some(index) => {
|
|
serial.write(OK).unwrap();
|
|
let mut name_buff = [0u8; SECRET_KEY_NAME_LEN as usize];
|
|
for i in 0..name_buff.len() {
|
|
let ch = block!(serial.read()).unwrap();
|
|
if ch == ENDL {
|
|
break;
|
|
} else {
|
|
name_buff[i] = ch;
|
|
}
|
|
}
|
|
|
|
let mut key_buff = [0u8; SECRET_KEY_MAX_LEN as usize];
|
|
for i in 0..key_buff.len() {
|
|
let ch = block!(serial.read()).unwrap();
|
|
if ch == ENDL {
|
|
break;
|
|
} else {
|
|
key_buff[i] = ch;
|
|
}
|
|
}
|
|
match tokens.write(index, &name_buff, &key_buff) {
|
|
Ok(_) => serial.write(OK).unwrap(),
|
|
Err(_) => serial.write(ERROR).unwrap(),
|
|
}
|
|
}
|
|
None => serial.write(ERROR).unwrap(),
|
|
},
|
|
SOFT_WIPE_TOKENS => {
|
|
serial.write(OK).unwrap();
|
|
let deleted_tokens = tokens.soft_wipe_all_tokens();
|
|
serial.write(deleted_tokens).unwrap();
|
|
serial.write(OK).unwrap();
|
|
}
|
|
HARD_WIPE_TOKENS => {
|
|
serial.write(OK).unwrap();
|
|
tokens.hard_wipe_all_tokens();
|
|
serial.write(OK).unwrap();
|
|
}
|
|
EXIT => break,
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
let mut last_time = 0;
|
|
let mut changed = false;
|
|
|
|
loop {
|
|
let timestamp = datetime::Datetime::from_ds3231(&mut rtc).unix_epoch();
|
|
|
|
if up_button.update() == button::Event::PressUp {
|
|
changed = true;
|
|
tokens.next();
|
|
}
|
|
if down_button.update() == button::Event::PressUp {
|
|
changed = true;
|
|
tokens.prev();
|
|
}
|
|
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;
|
|
}
|
|
}
|