Skip to content

Commit 1e68072

Browse files
committed
add in some more of the totp functional frameworks + itemcache
these frameworks are mostly unused at the moment but it lets us hook more easily into these artifacts once they are populated. next up...menu behavior in the totp widget
1 parent 79b8411 commit 1e68072

File tree

6 files changed

+79
-34
lines changed

6 files changed

+79
-34
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/vault2/src/itemcache.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use core::num::NonZeroUsize;
22
use std::cmp::Ordering;
33
use std::ops::Range;
44

5-
use crate::ux::framework::NavDir;
5+
use crate::ux::NavDir;
66
use crate::{SelectedEntry, VaultMode};
77

88
pub struct ListKey {
@@ -140,6 +140,7 @@ pub struct FilteredListView {
140140
items_per_screen: NonZeroUsize,
141141
filter_range: Option<Range<usize>>,
142142
}
143+
#[allow(dead_code)]
143144
impl FilteredListView {
144145
pub fn new() -> Self {
145146
Self {
@@ -429,32 +430,24 @@ impl FilteredListView {
429430
}
430431
}
431432
pub struct ItemLists {
432-
fido: FilteredListView,
433433
totp: FilteredListView,
434434
pw: FilteredListView,
435435
}
436+
#[allow(dead_code)]
436437
impl ItemLists {
437-
pub fn new() -> Self {
438-
ItemLists {
439-
fido: FilteredListView::new(),
440-
totp: FilteredListView::new(),
441-
pw: FilteredListView::new(),
442-
}
443-
}
438+
pub fn new() -> Self { ItemLists { totp: FilteredListView::new(), pw: FilteredListView::new() } }
444439

445440
pub fn is_db_empty(&self, list_type: VaultMode) -> bool { self.li(list_type).is_db_empty() }
446441

447442
fn li_mut(&mut self, list_type: VaultMode) -> &mut FilteredListView {
448443
match list_type {
449-
VaultMode::Fido => &mut self.fido,
450444
VaultMode::Totp => &mut self.totp,
451445
VaultMode::Password => &mut self.pw,
452446
}
453447
}
454448

455449
fn li(&self, list_type: VaultMode) -> &FilteredListView {
456450
match list_type {
457-
VaultMode::Fido => &self.fido,
458451
VaultMode::Totp => &self.totp,
459452
VaultMode::Password => &self.pw,
460453
}
@@ -479,13 +472,11 @@ impl ItemLists {
479472
}
480473

481474
pub fn set_items_per_screen(&mut self, ips: isize) {
482-
self.fido.set_items_per_screen(ips as usize);
483475
self.totp.set_items_per_screen(ips as usize);
484476
self.pw.set_items_per_screen(ips as usize);
485477
}
486478

487479
pub fn mark_all_dirty(&mut self) {
488-
self.fido.mark_all_dirty();
489480
self.totp.mark_all_dirty();
490481
self.pw.mark_all_dirty();
491482
}
@@ -495,7 +486,6 @@ impl ItemLists {
495486
pub fn clear(&mut self, list_type: VaultMode) { self.li_mut(list_type).clear(); }
496487

497488
pub fn clear_all(&mut self) {
498-
self.fido.clear();
499489
self.pw.clear();
500490
self.totp.clear();
501491
}

apps/vault2/src/main.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
1+
use core::sync::atomic::{AtomicBool, Ordering};
22
use std::sync::{Arc, Mutex};
33

44
use num_traits::*;
5-
6-
mod ux;
75
use totp::PumpOp;
6+
mod ux;
87
use ux::*;
8+
mod itemcache;
9+
use itemcache::*;
910
mod totp;
1011

1112
pub(crate) const SERVER_NAME_VAULT2: &str = "_Vault2_";
@@ -24,6 +25,13 @@ pub enum VaultMode {
2425
Password,
2526
}
2627

28+
#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Clone)]
29+
pub struct SelectedEntry {
30+
pub key_guid: String,
31+
pub description: String,
32+
pub mode: VaultMode,
33+
}
34+
2735
fn main() -> ! {
2836
log_server::init_wait().unwrap();
2937
log::set_max_level(log::LevelFilter::Info);
@@ -35,11 +43,12 @@ fn main() -> ! {
3543
let sid = xns.register_name(SERVER_NAME_VAULT2, None).expect("can't register server");
3644
let conn = xous::connect(sid).unwrap();
3745

38-
let mut vault_ui = VaultUi::new(&xns, conn);
39-
4046
// global shared state
4147
let mode = Arc::new(Mutex::new(VaultMode::Totp));
4248
let allow_totp_rendering = Arc::new(AtomicBool::new(true));
49+
let item_lists = Arc::new(Mutex::new(ItemLists::new()));
50+
51+
let mut vault_ui = VaultUi::new(&xns, conn, item_lists.clone());
4352

4453
// spawn the TOTP pumper
4554
let pump_sid = xous::create_server().unwrap();

apps/vault2/src/totp.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::{
66
};
77

88
use hmac::{Hmac, Mac};
9+
use locales::t;
910
use num_traits::*;
1011
use sha1::Sha1;
1112
use xous::{Message, send_message};
@@ -21,6 +22,11 @@ pub enum TotpAlgorithm {
2122
None,
2223
}
2324

25+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
26+
pub enum TotpError {
27+
BadRecord,
28+
}
29+
2430
impl Default for TotpAlgorithm {
2531
fn default() -> Self { Self::None }
2632
}
@@ -194,3 +200,32 @@ pub(crate) fn pumper(
194200
}
195201
});
196202
}
203+
204+
pub(crate) fn db_str_to_code(db_str: &str) -> Result<String, TotpError> {
205+
let fields = db_str.split(':').collect::<Vec<&str>>();
206+
if fields.len() == 5 {
207+
let shared_secret =
208+
base32::decode(base32::Alphabet::RFC4648 { padding: false }, fields[0]).unwrap_or(vec![]);
209+
let digit_count = u8::from_str_radix(fields[1], 10).unwrap_or(6);
210+
let step_seconds = u64::from_str_radix(fields[2], 10).unwrap_or(30);
211+
let algorithm = TotpAlgorithm::try_from(fields[3]).unwrap_or(TotpAlgorithm::HmacSha1);
212+
let is_hotp = fields[4].to_uppercase() == "HOTP";
213+
let totp = TotpEntry {
214+
step_seconds: if !is_hotp { step_seconds } else { 1 }, /* step_seconds is re-used
215+
* by hotp as the code. */
216+
shared_secret,
217+
digit_count,
218+
algorithm,
219+
};
220+
let code = if !is_hotp {
221+
generate_totp_code(get_current_unix_time().unwrap_or(0), &totp)
222+
.unwrap_or(t!("vault.error.record_error", locales::LANG).to_string())
223+
} else {
224+
generate_totp_code(step_seconds, &totp)
225+
.unwrap_or(t!("vault.error.record_error", locales::LANG).to_string())
226+
};
227+
Ok(code)
228+
} else {
229+
Err(TotpError::BadRecord)
230+
}
231+
}

apps/vault2/src/ux.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
use core::fmt::Write;
2+
use std::sync::{Arc, Mutex};
23

34
use blitstr2::GlyphStyle;
4-
use locales::t;
5-
use num_traits::*;
65
use ux_api::minigfx::*;
76
use ux_api::service::api::Gid;
87
use ux_api::service::gfx::Gfx;
98
use ux_api::widgets::ScrollableList;
109
use xous::CID;
1110

12-
use crate::VaultOp;
11+
use crate::ItemLists;
12+
use crate::VaultMode;
13+
14+
pub enum NavDir {
15+
Up,
16+
Down,
17+
PageUp,
18+
PageDown,
19+
}
1320

1421
/// Centralizes tunable UI parameters for TOTP
1522
struct TotpLayout {}
@@ -37,14 +44,15 @@ pub struct VaultUi {
3744
main_cid: CID,
3845
gfx: Gfx,
3946
totp_list: ScrollableList,
47+
item_lists: Arc<Mutex<ItemLists>>,
4048

4149
/// totp redraw state
42-
totp_code: Option<u32>,
50+
totp_code: Option<String>,
4351
last_epoch: u64,
4452
}
4553

4654
impl VaultUi {
47-
pub fn new(xns: &xous_names::XousNames, cid: xous::CID) -> Self {
55+
pub fn new(xns: &xous_names::XousNames, cid: xous::CID, item_lists: Arc<Mutex<ItemLists>>) -> Self {
4856
let mut totp_list = ScrollableList::default()
4957
.set_margin(TotpLayout::totp_margin())
5058
.pane_size(TotpLayout::list_box())
@@ -56,6 +64,7 @@ impl VaultUi {
5664
main_cid: cid,
5765
gfx: Gfx::new(&xns).unwrap(),
5866
totp_list,
67+
item_lists,
5968
totp_code: None,
6069
last_epoch: crate::totp::get_current_unix_time().expect("couldn't get current time") / 30,
6170
}
@@ -85,12 +94,12 @@ impl VaultUi {
8594
tv.style = TotpLayout::totp_font();
8695
tv.draw_border = false;
8796

88-
match self.totp_code {
97+
match &self.totp_code {
8998
Some(code) => {
90-
write!(tv, "{} {}", code / 1000, code % 1000).ok();
99+
write!(tv, "{}", code).ok();
91100
}
92101
_ => {
93-
write!(tv, "*** ***").ok();
102+
write!(tv, "******").ok();
94103
}
95104
}
96105
self.gfx.draw_textview(&mut tv).expect("couldn't draw text");
@@ -113,6 +122,14 @@ impl VaultUi {
113122
let epoch = (current_time / (30 * 1000)) as u64;
114123
if self.last_epoch != epoch {
115124
self.last_epoch = epoch;
125+
if !self.item_lists.lock().unwrap().is_db_empty(VaultMode::Totp) {
126+
match crate::totp::db_str_to_code(
127+
&self.item_lists.lock().unwrap().selected_extra(VaultMode::Totp),
128+
) {
129+
Ok(s) => self.totp_code = Some(s),
130+
_ => self.totp_code = None,
131+
}
132+
}
116133
}
117134

118135
let mut timer_remaining = TotpLayout::timer_box();

apps/vault2/src/ux/framework.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,6 @@ use crate::actions::ActionOp;
1919
use crate::totp::{TotpAlgorithm, TotpEntry, generate_totp_code, get_current_unix_time};
2020
use crate::{ItemLists, SelectedEntry, VaultMode};
2121

22-
pub enum NavDir {
23-
Up,
24-
Down,
25-
PageUp,
26-
PageDown,
27-
}
28-
2922
#[allow(dead_code)]
3023
pub struct VaultUx {
3124
/// the content area

0 commit comments

Comments
 (0)