1use crate::utils::*;
2use botan_sys::*;
3
4#[derive(Debug)]
6#[allow(clippy::upper_case_acronyms)]
7pub struct HOTP {
8 obj: botan_hotp_t,
9}
10
11unsafe impl Sync for HOTP {}
12unsafe impl Send for HOTP {}
13
14botan_impl_drop!(HOTP, botan_hotp_destroy);
15
16#[derive(Debug)]
18#[allow(clippy::upper_case_acronyms)]
19pub struct TOTP {
20 obj: botan_totp_t,
21}
22
23unsafe impl Sync for TOTP {}
24unsafe impl Send for TOTP {}
25
26botan_impl_drop!(TOTP, botan_totp_destroy);
27
28impl HOTP {
29 pub fn new(key: &[u8], hash_algo: &str, digits: usize) -> Result<HOTP> {
37 let hash_algo = make_cstr(hash_algo)?;
38
39 let obj = botan_init!(
40 botan_hotp_init,
41 key.as_ptr(),
42 key.len(),
43 hash_algo.as_ptr(),
44 digits
45 )?;
46
47 Ok(HOTP { obj })
48 }
49
50 pub fn generate(&self, counter: u64) -> Result<u32> {
52 let mut code = 0;
53 botan_call!(botan_hotp_generate, self.obj, &mut code, counter)?;
54 Ok(code)
55 }
56
57 pub fn check(&self, code: u32, counter: u64) -> Result<bool> {
59 let cmp_code = self.generate(counter)?;
60 Ok(cmp_code == code)
61 }
62
63 pub fn check_with_resync(
65 &self,
66 code: u32,
67 counter: u64,
68 resync_range: usize,
69 ) -> Result<(bool, u64)> {
70 let mut new_ctr = 0;
71 let res = botan_bool_in_rc!(
72 botan_hotp_check,
73 self.obj,
74 &mut new_ctr,
75 code,
76 counter,
77 resync_range
78 )?;
79
80 if !res {
82 Ok((true, new_ctr))
83 } else {
84 Ok((false, counter))
85 }
86 }
87}
88
89impl TOTP {
90 pub fn new(key: &[u8], hash_algo: &str, digits: usize, time_step: usize) -> Result<TOTP> {
98 let hash_algo = make_cstr(hash_algo)?;
99
100 let obj = botan_init!(
101 botan_totp_init,
102 key.as_ptr(),
103 key.len(),
104 hash_algo.as_ptr(),
105 digits,
106 time_step
107 )?;
108
109 Ok(TOTP { obj })
110 }
111
112 pub fn generate(&self, timestamp: u64) -> Result<u32> {
114 let mut code = 0;
115 botan_call!(botan_totp_generate, self.obj, &mut code, timestamp)?;
116 Ok(code)
117 }
118
119 pub fn check(&self, code: u32, timestamp: u64, allowed_drift: usize) -> Result<bool> {
121 Ok(!botan_bool_in_rc!(
123 botan_totp_check,
124 self.obj,
125 code,
126 timestamp,
127 allowed_drift
128 )?)
129 }
130}