diff --git a/Cargo.lock b/Cargo.lock index c9ee47a..5472a24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,6 +101,7 @@ dependencies = [ [[package]] name = "ds323x" version = "0.5.0" +source = "git+https://github.com/kirbylife/ds323x-rs?branch=fix-set-day-format#e204b77494f921cfc276c9a66e6e9ba95dc4e142" dependencies = [ "embedded-hal", "rtcc", @@ -122,6 +123,11 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "723dce4e9f25b6e6c5f35628e144794e5b459216ed7da97b7c4b66cdb3fa82ca" +[[package]] +name = "hmac-sha1-compact" +version = "1.1.3" +source = "git+https://github.com/kirbylife/rust-hmac-sha1#a3c4116837efb8a850fb0d03985831ce4dc2bc12" + [[package]] name = "nb" version = "0.1.3" @@ -220,19 +226,13 @@ dependencies = [ "arduino-hal", "ds323x", "embedded-hal", + "hmac-sha1-compact", "nb 1.1.0", "panic-halt", "randomize", - "sha1_smol", "ufmt 0.2.0", ] -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - [[package]] name = "syn" version = "1.0.109" diff --git a/Cargo.toml b/Cargo.toml index 14336d6..5119130 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" [dependencies] arduino-hal = { git = "https://github.com/rahix/avr-hal", features = ["arduino-uno"] } +ds323x = { git = "https://github.com/kirbylife/ds323x-rs", branch = "fix-set-day-format" } +hmac-sha1-compact = { git = "https://github.com/kirbylife/rust-hmac-sha1" } panic-halt = "0.2.0" -sha1_smol = "1.0.0" -ds323x = { path = "../ds323x-rs" } embedded-hal = "0.2.7" nb = "1.1.0" randomize = "3.0.1" diff --git a/src/crypto.rs b/src/crypto.rs index 259b648..3e0f132 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -1,34 +1,16 @@ -use sha1_smol::Sha1; +use hmac_sha1_compact::HMAC; -const BLOCK_SIZE: usize = 64; +pub const INTERVAL: u64 = 30; -pub fn hmac_sha1(key: &[u8], message: &[u8], output: &mut [u8]) { - // Preprocess the key. - let mut key_padded = [0u8; BLOCK_SIZE]; - key_padded[..key.len()].copy_from_slice(key); +pub fn generate_otp_token(private_key: &[u8], actual_time: u64) -> u32 { + let interval = actual_time / INTERVAL; + let msg = interval.to_be_bytes(); - for byte in &mut key_padded { - *byte ^= 0x36; - } + let hmac_digest = HMAC::mac(&msg, private_key); - // Hash the inner padded key and the message. - let mut hash = Sha1::new(); - hash.update(&key_padded[..]); - hash.update(message); - let mut inner_hash = [0u8; 20]; - inner_hash.copy_from_slice(&hash.digest().bytes()); + let start = (hmac_digest[19] & 0xF) as usize; + let bytes: [u8; 4] = hmac_digest[start..start + 4].try_into().unwrap(); - // Preprocess the key again. - for byte in &mut key_padded { - *byte ^= 0x36 ^ 0x5c; - } - - // Hash the outer padded key and the inner hash. - let mut hash = Sha1::new(); - hash.update(&key_padded[..]); - hash.update(&inner_hash[..]); - let hmac_digest = hash.digest().bytes(); - - // Copy the result into the output buffer. - output.copy_from_slice(&hmac_digest); + let raw_token = u32::from_be_bytes(bytes); + ((raw_token & 0x7F_FF_FF_FF) % 1_000_000) as u32 } diff --git a/src/datetime.rs b/src/datetime.rs index 2b181c7..14e65e7 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -11,8 +11,8 @@ pub struct Datetime { impl Datetime { pub fn unix_epoch(&self) -> u64 { - let mut year: i64 = self.year as i64 - 1900; - let mut month: i64 = self.month as i64 - 1; + let year: i64 = self.year as i64 - 1900; + let month: i64 = self.month as i64 - 1; let (mut t, is_leap) = year_to_secs(year); t += month_to_secs(month, is_leap); diff --git a/src/main.rs b/src/main.rs index 5e330c6..2934843 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,15 +11,14 @@ use arduino_hal::default_serial; use arduino_hal::delay_ms; // use arduino_hal::delay_ms; use arduino_hal::prelude::*; -use crypto::hmac_sha1; +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 INTERVAL: u64 = 30; - const ENDL: u8 = 0; const OK: u8 = 1; const ERROR: u8 = 2; @@ -31,24 +30,6 @@ const GET_TOKENS: u8 = 40; const WIPE_TOKENS: u8 = 50; const EXIT: u8 = 254; -fn decimal_to_packed_bcd(dec: u8) -> u8 { - ((dec / 10) << 4) | (dec % 10) -} - -fn generate_otp_token(private_key: &[u8], actual_time: u64) -> u32 { - let interval = actual_time / INTERVAL; - let msg = interval.to_be_bytes(); - - let mut hmac_digest = [0u8; 20]; - hmac_sha1(private_key, &msg, &mut hmac_digest); - - let start = (hmac_digest[19] & 0xF) as usize; - let bytes: [u8; 4] = hmac_digest[start..start + 4].try_into().unwrap(); - - let raw_token = u32::from_be_bytes(bytes); - ((raw_token & 0x7F_FF_FF_FF) % 1_000_000) as u32 -} - #[arduino_hal::entry] fn main() -> ! { let dp = arduino_hal::Peripherals::take().unwrap(); @@ -83,114 +64,112 @@ fn main() -> ! { let up = pins.d6.into_pull_up_input(); let mut button = button::Button::new(&up, true); - // button.update(); - // if button.update() == button::Event::Pressed || true { - // display.write_str("Connected to"); - // display.set_cursor(0, 1); - // display.write_str("USB..."); - // loop { - // // Waiting from a command since the tool - // 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); + button.update(); + if button.update() == button::Event::Pressed { + display.write_str("Connected to"); + display.set_cursor(0, 1); + display.write_str("USB..."); + loop { + // Waiting from a command since the tool + 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 { - // EXIT => {} - // HANDSHAKE => serial.write(OK).unwrap(), - // SET_TIMESTAMP => { - // serial.write(OK).unwrap(); - // let year = loop { - // let y = block!(serial.read()).unwrap(); - // serial.write(y).unwrap(); - // if block!(serial.read()).unwrap() == OK { - // break y; - // } - // }; - // 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_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; - // } - // } + match cmd { + EXIT => {} + HANDSHAKE => serial.write(OK).unwrap(), + SET_TIMESTAMP => { + serial.write(OK).unwrap(); + let year = loop { + let y = block!(serial.read()).unwrap(); + serial.write(y).unwrap(); + if block!(serial.read()).unwrap() == OK { + break y; + } + }; + 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_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) { - // Some(_) => serial.write(OK).unwrap(), - // None => serial.write(ERROR).unwrap(), - // } - // } - // None => serial.write(ERROR).unwrap(), - // }, - // WIPE_TOKENS => { - // serial.write(OK).unwrap(); - // tokens.wipe_all_tokens(); - // serial.write(OK).unwrap(); - // } - // _ => {} - // u8::MAX => {} - // } - // } - // } - // loop {} + 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) { + Some(_) => serial.write(OK).unwrap(), + None => serial.write(ERROR).unwrap(), + } + } + None => serial.write(ERROR).unwrap(), + }, + WIPE_TOKENS => { + serial.write(OK).unwrap(); + tokens.wipe_all_tokens(); + serial.write(OK).unwrap(); + } + _ => {} + } + } + } match tokens.current { Some(index) => { @@ -202,15 +181,6 @@ fn main() -> ! { let key = &buff_key[..len_key]; let dt = datetime::Datetime::from_ds3231(&mut rtc); - let datetime::Datetime { - year, - month, - day, - hours, - minutes, - seconds, - } = dt; - let timestamp = dt.unix_epoch(); let token = generate_otp_token(key, timestamp); diff --git a/src/storage.rs b/src/storage.rs index a3d88d6..7494c65 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -70,18 +70,18 @@ impl<'a> Tokens<'a> { let index_name = index * SECRET_KEY_FULL_LEN; let index_key = (index * SECRET_KEY_FULL_LEN) + SECRET_KEY_NAME_LEN; match self.mem.read(index_name, name) { - Ok(n) => {} + Ok(_) => {} Err(_) => return None, } match self.mem.read(index_key, key) { - Ok(n) => {} + Ok(_) => {} Err(_) => return None, } - let mut len_name = name + let len_name = name .iter() .position(|&n| n == 0) .unwrap_or(SECRET_KEY_NAME_LEN as usize); - let mut len_key = key + let len_key = key .iter() .position(|&n| n == 0) .unwrap_or(SECRET_KEY_MAX_LEN as usize);