feat: check locked state
Some checks are pending
CI / Check (push) Waiting to run
CI / Test Suite (push) Waiting to run
CI / Rustfmt (push) Waiting to run
CI / Clippy (push) Waiting to run
CI / cargo-deny (push) Waiting to run

This commit is contained in:
Grimmauld 2025-02-15 10:40:14 +01:00
parent 1ffd5b1c87
commit d57c03e643
No known key found for this signature in database
2 changed files with 40 additions and 11 deletions

View file

@ -104,7 +104,6 @@ impl<'a> RefreshableOathCredential<'a> {
let valid_from = SystemTime::UNIX_EPOCH let valid_from = SystemTime::UNIX_EPOCH
.checked_add(self.cred.id_data.period.saturating_mul(time_step as u32)) .checked_add(self.cred.id_data.period.saturating_mul(time_step as u32))
.unwrap(); .unwrap();
// time_step * (self.cred.id_data.period.as_secs());
let valid_to = valid_from.checked_add(self.cred.id_data.period).unwrap(); let valid_to = valid_from.checked_add(self.cred.id_data.period).unwrap();
valid_from..valid_to valid_from..valid_to
} }
@ -134,11 +133,6 @@ impl OathSession {
transaction_context.apdu_read_all(0, INS_SELECT, 0x04, 0, Some(&OATH_AID))?; transaction_context.apdu_read_all(0, INS_SELECT, 0x04, 0, Some(&OATH_AID))?;
let info_map = tlv_to_map(info_buffer); let info_map = tlv_to_map(info_buffer);
for (tag, data) in &info_map {
// Printing tag and data
println!("{:?}: {:?}", tag, data);
}
let challenge = info_map.get(&(Tag::Challenge as u8)).map(Vec::to_owned); let challenge = info_map.get(&(Tag::Challenge as u8)).map(Vec::to_owned);
Ok(Self { Ok(Self {
locked: challenge.is_some(), locked: challenge.is_some(),
@ -171,7 +165,7 @@ impl OathSession {
} }
let hmac = _hmac_sha1(key, &chal); let hmac = _hmac_sha1(key, &chal);
let random_chal = getrandom::u64().unwrap().to_be_bytes(); // FIXME: unwrap let random_chal = getrandom::u64()?.to_be_bytes();
let data = &[ let data = &[
to_tlv(Tag::Response, &hmac), to_tlv(Tag::Response, &hmac),
to_tlv(Tag::Challenge, &random_chal), to_tlv(Tag::Challenge, &random_chal),
@ -189,12 +183,15 @@ impl OathSession {
self.locked = false; self.locked = false;
Ok(()) Ok(())
} else { } else {
Err(Error::FailedAuthentication) Err(Error::Authentication)
} }
} }
pub fn set_key(&mut self, key: &[u8]) -> Result<(), Error> { pub fn set_key(&mut self, key: &[u8]) -> Result<(), Error> {
let random_chal = getrandom::u64().unwrap().to_be_bytes(); // FIXME: unwrap if self.locked {
return Err(Error::Authentication);
}
let random_chal = getrandom::u64()?.to_be_bytes();
let hmac = _hmac_sha1(key, &random_chal); let hmac = _hmac_sha1(key, &random_chal);
let data = &[ let data = &[
to_tlv( to_tlv(
@ -218,6 +215,10 @@ impl OathSession {
} }
pub fn unset_key(&mut self) -> Result<(), Error> { pub fn unset_key(&mut self) -> Result<(), Error> {
if self.locked {
return Err(Error::Authentication);
}
self.transaction_context.apdu( self.transaction_context.apdu(
0, 0,
Instruction::SetCode as u8, Instruction::SetCode as u8,
@ -235,6 +236,10 @@ impl OathSession {
old: CredentialIDData, old: CredentialIDData,
new: CredentialIDData, new: CredentialIDData,
) -> Result<CredentialIDData, Error> { ) -> Result<CredentialIDData, Error> {
if self.locked {
return Err(Error::Authentication);
}
// require_version(self.version, (5, 3, 1)) TODO: version checking // require_version(self.version, (5, 3, 1)) TODO: version checking
self.transaction_context.apdu( self.transaction_context.apdu(
0, 0,
@ -247,6 +252,10 @@ impl OathSession {
} }
pub fn delete_code(&self, cred: OathCredential) -> Result<ApduResponse, Error> { pub fn delete_code(&self, cred: OathCredential) -> Result<ApduResponse, Error> {
if self.locked {
return Err(Error::Authentication);
}
self.transaction_context.apdu( self.transaction_context.apdu(
0, 0,
Instruction::Delete as u8, Instruction::Delete as u8,
@ -266,6 +275,10 @@ impl OathSession {
cred: OathCredential, cred: OathCredential,
timestamp_sys: Option<SystemTime>, timestamp_sys: Option<SystemTime>,
) -> Result<OathCodeDisplay, Error> { ) -> Result<OathCodeDisplay, Error> {
if self.locked {
return Err(Error::Authentication);
}
if self.name != cred.device_id { if self.name != cred.device_id {
return Err(Error::DeviceMismatch); return Err(Error::DeviceMismatch);
} }
@ -300,6 +313,10 @@ impl OathSession {
/// Read the OATH codes from the device, calculate TOTP codes that don't /// Read the OATH codes from the device, calculate TOTP codes that don't
/// need touch /// need touch
pub fn calculate_oath_codes(&self) -> Result<Vec<RefreshableOathCredential>, Error> { pub fn calculate_oath_codes(&self) -> Result<Vec<RefreshableOathCredential>, Error> {
if self.locked {
return Err(Error::Authentication);
}
let timestamp = SystemTime::now(); let timestamp = SystemTime::now();
// Request OATH codes from device // Request OATH codes from device
let response = self.transaction_context.apdu_read_all( let response = self.transaction_context.apdu_read_all(
@ -338,6 +355,10 @@ impl OathSession {
Ok(key_buffer) Ok(key_buffer)
} }
pub fn list_oath_codes(&self) -> Result<Vec<CredentialIDData>, Error> { pub fn list_oath_codes(&self) -> Result<Vec<CredentialIDData>, Error> {
if self.locked {
return Err(Error::Authentication);
}
// Request OATH codes from device // Request OATH codes from device
let response = let response =
self.transaction_context self.transaction_context

View file

@ -14,7 +14,8 @@ pub enum Error {
Pcsc(pcsc::Error), Pcsc(pcsc::Error),
Parsing(String), Parsing(String),
DeviceMismatch, DeviceMismatch,
FailedAuthentication, Authentication,
Random(getrandom::Error),
} }
impl Error { impl Error {
@ -39,6 +40,12 @@ impl From<pcsc::Error> for Error {
} }
} }
impl From<getrandom::Error> for Error {
fn from(value: getrandom::Error) -> Self {
Self::Random(value)
}
}
impl Display for Error { impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
@ -47,7 +54,8 @@ impl Display for Error {
Self::Pcsc(error) => f.write_fmt(format_args!("{}", error)), Self::Pcsc(error) => f.write_fmt(format_args!("{}", error)),
Self::Parsing(msg) => f.write_str(msg), Self::Parsing(msg) => f.write_str(msg),
Self::DeviceMismatch => f.write_str("Devices do not match"), Self::DeviceMismatch => f.write_str("Devices do not match"),
Error::FailedAuthentication => f.write_str("Authentication failure"), Self::Authentication => f.write_str("Authentication failure"),
Self::Random(error_response) => f.write_fmt(format_args!("{}", error_response)),
} }
} }
} }