use crate::hash::HashFunction;
#[cfg(feature = "oath-uri")]
const DEFAULT_KEY_URI_PARAM_POLICY: ParametersVisibility = ParametersVisibility::ShowNonDefault;
const DEFAULT_OTP_HASH: HashFunction = HashFunction::Sha1;
const DEFAULT_OTP_OUT_BASE: &str = "0123456789";
const DEFAULT_OTP_OUT_LEN: usize = 6;
const DEFAULT_TOTP_PERIOD: u32 = 30;
const DEFAULT_TOTP_T0: u64 = 0;
const DEFAULT_LOOK_AHEAD: u64 = 0;
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum ErrorCode {
Success = 0,
NullPtr = 1,
NotEnoughSpace = 2,
InvalidBaseLen = 10,
InvalidKeyLen = 11,
CodeTooSmall = 12,
CodeTooBig = 13,
InvalidKey = 20,
InvalidPeriod = 21,
InvalidUTF8 = 30,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "thiserror", derive(thiserror::Error))]
pub enum Error {
#[cfg_attr(feature = "thiserror", error("Code too small"))]
CodeTooSmall,
#[cfg_attr(feature = "thiserror", error("Code too big"))]
CodeTooBig,
#[cfg_attr(feature = "thiserror", error("Invalid key"))]
InvalidKey,
#[cfg_attr(feature = "thiserror", error("Invalid period"))]
InvalidPeriod,
}
impl From<Error> for ErrorCode {
fn from(error: Error) -> Self {
match error {
Error::CodeTooSmall => ErrorCode::CodeTooSmall,
Error::CodeTooBig => ErrorCode::CodeTooBig,
Error::InvalidKey => ErrorCode::InvalidKey,
Error::InvalidPeriod => ErrorCode::InvalidPeriod,
}
}
}
macro_rules! builder_common {
() => {
pub fn key(&mut self, key: &[u8]) -> &mut Self {
self.key = Some(key.to_owned());
self
}
pub fn ascii_key(&mut self, key: &str) -> &mut Self {
self.key = Some(key.as_bytes().to_vec());
self
}
pub fn hex_key(&mut self, key: &str) -> &mut Self {
match hex::decode(key) {
Ok(k) => {
self.key = Some(k);
}
Err(_) => {
self.runtime_error = Some(Error::InvalidKey);
}
}
self
}
pub fn base32_key(&mut self, key: &str) -> &mut Self {
match base32::decode(base32::Alphabet::Rfc4648 { padding: false }, &key) {
Some(k) => {
self.key = Some(k);
}
None => {
self.runtime_error = Some(Error::InvalidKey);
}
}
self
}
pub fn base64_key(&mut self, key: &str) -> &mut Self {
use base64::Engine;
match base64::engine::general_purpose::STANDARD.decode(key) {
Ok(k) => {
self.key = Some(k);
}
Err(_) => {
self.runtime_error = Some(Error::InvalidKey);
}
}
self
}
fn code_length(&self) -> usize {
let base_len = self.output_base.len();
let mut nb_bits = base_len;
for _ in 1..self.output_len {
nb_bits = match nb_bits.checked_mul(base_len) {
Some(nb_bits) => nb_bits,
None => return usize::MAX,
};
}
nb_bits
}
pub fn output_len(&mut self, output_len: usize) -> &mut Self {
self.output_len = output_len;
self
}
pub fn output_base(&mut self, base: &str) -> &mut Self {
self.output_base = base.to_string();
self
}
pub fn hash_function(&mut self, hash_function: HashFunction) -> &mut Self {
self.hash_function = hash_function;
self
}
};
}
#[cfg(feature = "oath-uri")]
mod key_uri;
#[cfg(feature = "oath-uri")]
pub use self::key_uri::{KeyUriBuilder, ParametersVisibility};
mod hotp;
pub use self::hotp::HOTP;
pub use self::hotp::HOTPBuilder;
mod totp;
pub use self::totp::TOTP;
pub use self::totp::TOTPBuilder;
#[cfg(feature = "cbindings")]
mod cbindings;
#[cfg(feature = "cbindings")]
pub use self::cbindings::HOTPcfg;
#[cfg(feature = "cbindings")]
pub use self::cbindings::libreauth_hotp_generate;
#[cfg(all(feature = "cbindings", feature = "oath-uri"))]
pub use self::cbindings::libreauth_hotp_get_uri;
#[cfg(feature = "cbindings")]
pub use self::cbindings::libreauth_hotp_init;
#[cfg(feature = "cbindings")]
pub use self::cbindings::libreauth_hotp_is_valid;
#[cfg(feature = "cbindings")]
pub use self::cbindings::TOTPcfg;
#[cfg(feature = "cbindings")]
pub use self::cbindings::libreauth_totp_generate;
#[cfg(all(feature = "cbindings", feature = "oath-uri"))]
pub use self::cbindings::libreauth_totp_get_uri;
#[cfg(feature = "cbindings")]
pub use self::cbindings::libreauth_totp_init;
#[cfg(feature = "cbindings")]
pub use self::cbindings::libreauth_totp_is_valid;