mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-24 23:38:09 +00:00
feat(core/ui): implement webauthn layouts for UI2
[no changelog]
This commit is contained in:
parent
e80712f4d9
commit
61277bd80a
@ -579,13 +579,13 @@ if FROZEN:
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/reset.py'))
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/recovery.py'))
|
||||
if EVERYTHING:
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/webauthn.py'))
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/fido.py'))
|
||||
if TREZOR_MODEL in ('T',):
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/__init__.py'))
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/reset.py'))
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/recovery.py'))
|
||||
if EVERYTHING:
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/webauthn.py'))
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/fido.py'))
|
||||
elif TREZOR_MODEL in ('1',):
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/t1.py'))
|
||||
elif TREZOR_MODEL in ('R',):
|
||||
|
@ -533,13 +533,13 @@ if FROZEN:
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/reset.py'))
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/recovery.py'))
|
||||
if EVERYTHING:
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/webauthn.py'))
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/fido.py'))
|
||||
if TREZOR_MODEL in ('T',):
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/__init__.py'))
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/reset.py'))
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/recovery.py'))
|
||||
if EVERYTHING:
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/webauthn.py'))
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/fido.py'))
|
||||
elif TREZOR_MODEL in ('1',):
|
||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/t1.py'))
|
||||
elif TREZOR_MODEL in ('R',):
|
||||
|
@ -20,6 +20,7 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_confirm_blob;
|
||||
MP_QSTR_confirm_properties;
|
||||
MP_QSTR_confirm_coinjoin;
|
||||
MP_QSTR_confirm_fido;
|
||||
MP_QSTR_confirm_joint_total;
|
||||
MP_QSTR_confirm_modify_fee;
|
||||
MP_QSTR_confirm_modify_output;
|
||||
@ -91,4 +92,7 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_active;
|
||||
MP_QSTR_info_button;
|
||||
MP_QSTR_time_ms;
|
||||
MP_QSTR_app_name;
|
||||
MP_QSTR_icon_name;
|
||||
MP_QSTR_accounts;
|
||||
}
|
||||
|
210
core/embed/rust/src/ui/model_tt/component/fido.rs
Normal file
210
core/embed/rust/src/ui/model_tt/component/fido.rs
Normal file
@ -0,0 +1,210 @@
|
||||
use core::ops::Deref;
|
||||
|
||||
use crate::ui::{
|
||||
component::{Child, Component, Event, EventCtx, Image, Label},
|
||||
display,
|
||||
geometry::{Alignment, Insets, Rect},
|
||||
model_tt::component::{
|
||||
fido_icons::get_fido_icon_data,
|
||||
swipe::{Swipe, SwipeDirection},
|
||||
theme, ScrollBar,
|
||||
},
|
||||
};
|
||||
|
||||
use super::CancelConfirmMsg;
|
||||
|
||||
const ICON_HEIGHT: i16 = 70;
|
||||
const SCROLLBAR_INSET_TOP: i16 = 5;
|
||||
const SCROLLBAR_HEIGHT: i16 = 10;
|
||||
const APP_NAME_PADDING: i16 = 12;
|
||||
const APP_NAME_HEIGHT: i16 = 30;
|
||||
|
||||
pub enum FidoMsg {
|
||||
Confirmed(usize),
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
pub struct FidoConfirm<F: Fn(usize) -> T, T, U> {
|
||||
page_swipe: Swipe,
|
||||
app_name: Label<T>,
|
||||
account_name: Label<T>,
|
||||
icon: Child<Image>,
|
||||
/// Function/closure that will return appropriate page on demand.
|
||||
get_account: F,
|
||||
scrollbar: ScrollBar,
|
||||
fade: bool,
|
||||
controls: U,
|
||||
}
|
||||
|
||||
impl<F, T, U> FidoConfirm<F, T, U>
|
||||
where
|
||||
F: Fn(usize) -> T,
|
||||
T: Deref<Target = str> + From<&'static str>,
|
||||
U: Component<Msg = CancelConfirmMsg>,
|
||||
{
|
||||
pub fn new(
|
||||
app_name: T,
|
||||
get_account: F,
|
||||
page_count: usize,
|
||||
icon_name: Option<T>,
|
||||
controls: U,
|
||||
) -> Self {
|
||||
let icon_data = get_fido_icon_data(icon_name.as_deref());
|
||||
|
||||
// Preparing scrollbar and setting its page-count.
|
||||
let mut scrollbar = ScrollBar::horizontal();
|
||||
scrollbar.set_count_and_active_page(page_count, 0);
|
||||
|
||||
// Preparing swipe component and setting possible initial
|
||||
// swipe directions according to number of pages.
|
||||
let mut page_swipe = Swipe::horizontal();
|
||||
page_swipe.allow_right = scrollbar.has_previous_page();
|
||||
page_swipe.allow_left = scrollbar.has_next_page();
|
||||
|
||||
Self {
|
||||
app_name: Label::new(app_name, Alignment::Center, theme::TEXT_BOLD),
|
||||
account_name: Label::new("".into(), Alignment::Center, theme::TEXT_BOLD),
|
||||
page_swipe,
|
||||
icon: Child::new(Image::new(icon_data)),
|
||||
get_account,
|
||||
scrollbar,
|
||||
fade: false,
|
||||
controls,
|
||||
}
|
||||
}
|
||||
|
||||
fn on_page_swipe(&mut self, ctx: &mut EventCtx, swipe: SwipeDirection) {
|
||||
// Change the page number.
|
||||
match swipe {
|
||||
SwipeDirection::Left if self.scrollbar.has_next_page() => {
|
||||
self.scrollbar.go_to_next_page();
|
||||
}
|
||||
SwipeDirection::Right if self.scrollbar.has_previous_page() => {
|
||||
self.scrollbar.go_to_previous_page();
|
||||
}
|
||||
_ => {} // page did not change
|
||||
};
|
||||
|
||||
// Disable swipes on the boundaries. Not allowing carousel effect.
|
||||
self.page_swipe.allow_right = self.scrollbar.has_previous_page();
|
||||
self.page_swipe.allow_left = self.scrollbar.has_next_page();
|
||||
|
||||
// Redraw the page.
|
||||
ctx.request_paint();
|
||||
|
||||
// Reset backlight to normal level on next paint.
|
||||
self.fade = true;
|
||||
}
|
||||
|
||||
fn active_page(&self) -> usize {
|
||||
self.scrollbar.active_page
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T, U> Component for FidoConfirm<F, T, U>
|
||||
where
|
||||
F: Fn(usize) -> T,
|
||||
T: Deref<Target = str> + From<&'static str>,
|
||||
U: Component<Msg = CancelConfirmMsg>,
|
||||
{
|
||||
type Msg = FidoMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.page_swipe.place(bounds);
|
||||
|
||||
// Place the control buttons.
|
||||
let controls_area = self.controls.place(bounds);
|
||||
|
||||
// Get the image and content areas.
|
||||
let content_area = bounds.inset(Insets::bottom(controls_area.height()));
|
||||
let (image_area, content_area) = content_area.split_top(ICON_HEIGHT);
|
||||
|
||||
// In case of showing a scrollbar, getting its area and placing it.
|
||||
let remaining_area = if self.scrollbar.page_count > 1 {
|
||||
let (scrollbar_area, remaining_area) = content_area
|
||||
.inset(Insets::top(SCROLLBAR_INSET_TOP))
|
||||
.split_top(SCROLLBAR_HEIGHT);
|
||||
self.scrollbar.place(scrollbar_area);
|
||||
remaining_area
|
||||
} else {
|
||||
content_area
|
||||
};
|
||||
|
||||
// Place the icon image.
|
||||
self.icon.place(image_area);
|
||||
|
||||
// Place the text labels.
|
||||
let (app_name_area, account_name_area) = remaining_area
|
||||
.inset(Insets::top(APP_NAME_PADDING))
|
||||
.split_top(APP_NAME_HEIGHT);
|
||||
|
||||
self.app_name.place(app_name_area);
|
||||
self.account_name.place(account_name_area);
|
||||
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
if let Some(swipe) = self.page_swipe.event(ctx, event) {
|
||||
// Swipe encountered, update the page.
|
||||
self.on_page_swipe(ctx, swipe);
|
||||
}
|
||||
if let Some(msg) = self.controls.event(ctx, event) {
|
||||
// Some button was clicked, send results.
|
||||
match msg {
|
||||
CancelConfirmMsg::Confirmed => return Some(FidoMsg::Confirmed(self.active_page())),
|
||||
CancelConfirmMsg::Cancelled => return Some(FidoMsg::Cancelled),
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
self.icon.paint();
|
||||
self.controls.paint();
|
||||
self.app_name.paint();
|
||||
|
||||
if self.scrollbar.page_count > 1 {
|
||||
self.scrollbar.paint();
|
||||
}
|
||||
|
||||
let current_account = (self.get_account)(self.active_page());
|
||||
|
||||
// Erasing the old text content before writing the new one.
|
||||
let account_name_area = self.account_name.area();
|
||||
let real_area = account_name_area
|
||||
.with_height(account_name_area.height() + self.account_name.font().text_baseline() + 1);
|
||||
display::rect_fill(real_area, theme::BG);
|
||||
|
||||
// Account name is optional.
|
||||
// Showing it only if it differs from app name.
|
||||
// (Dummy requests usually have some text as both app_name and account_name.)
|
||||
if !current_account.is_empty() && current_account.deref() != self.app_name.text().deref() {
|
||||
self.account_name.set_text(current_account);
|
||||
self.account_name.paint();
|
||||
}
|
||||
|
||||
if self.fade {
|
||||
self.fade = false;
|
||||
// Note that this is blocking and takes some time.
|
||||
display::fade_backlight(theme::BACKLIGHT_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||
self.icon.bounds(sink);
|
||||
self.app_name.bounds(sink);
|
||||
self.account_name.bounds(sink);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl<F, T, U> crate::trace::Trace for FidoConfirm<F, T, U>
|
||||
where
|
||||
F: Fn(usize) -> T,
|
||||
{
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("FidoPaginatedPage");
|
||||
t.close();
|
||||
}
|
||||
}
|
77
core/embed/rust/src/ui/model_tt/component/fido_icons.rs
Normal file
77
core/embed/rust/src/ui/model_tt/component/fido_icons.rs
Normal file
@ -0,0 +1,77 @@
|
||||
//! generated from webauthn_icons.rs.mako
|
||||
//! (by running `make templates` in `core`)
|
||||
//! do not edit manually!
|
||||
|
||||
const ICON_AWS: &[u8] = include_res!("model_tt/res/fido/icon_aws.toif");
|
||||
const ICON_BINANCE: &[u8] = include_res!("model_tt/res/fido/icon_binance.toif");
|
||||
const ICON_BITBUCKET: &[u8] = include_res!("model_tt/res/fido/icon_bitbucket.toif");
|
||||
const ICON_BITFINEX: &[u8] = include_res!("model_tt/res/fido/icon_bitfinex.toif");
|
||||
const ICON_BITWARDEN: &[u8] = include_res!("model_tt/res/fido/icon_bitwarden.toif");
|
||||
const ICON_CLOUDFLARE: &[u8] = include_res!("model_tt/res/fido/icon_cloudflare.toif");
|
||||
const ICON_COINBASE: &[u8] = include_res!("model_tt/res/fido/icon_coinbase.toif");
|
||||
const ICON_DASHLANE: &[u8] = include_res!("model_tt/res/fido/icon_dashlane.toif");
|
||||
const ICON_DROPBOX: &[u8] = include_res!("model_tt/res/fido/icon_dropbox.toif");
|
||||
const ICON_DUO: &[u8] = include_res!("model_tt/res/fido/icon_duo.toif");
|
||||
const ICON_FACEBOOK: &[u8] = include_res!("model_tt/res/fido/icon_facebook.toif");
|
||||
const ICON_FASTMAIL: &[u8] = include_res!("model_tt/res/fido/icon_fastmail.toif");
|
||||
const ICON_FEDORA: &[u8] = include_res!("model_tt/res/fido/icon_fedora.toif");
|
||||
const ICON_GANDI: &[u8] = include_res!("model_tt/res/fido/icon_gandi.toif");
|
||||
const ICON_GEMINI: &[u8] = include_res!("model_tt/res/fido/icon_gemini.toif");
|
||||
const ICON_GITHUB: &[u8] = include_res!("model_tt/res/fido/icon_github.toif");
|
||||
const ICON_GITLAB: &[u8] = include_res!("model_tt/res/fido/icon_gitlab.toif");
|
||||
const ICON_GOOGLE: &[u8] = include_res!("model_tt/res/fido/icon_google.toif");
|
||||
const ICON_INVITY: &[u8] = include_res!("model_tt/res/fido/icon_invity.toif");
|
||||
const ICON_KEEPER: &[u8] = include_res!("model_tt/res/fido/icon_keeper.toif");
|
||||
const ICON_KRAKEN: &[u8] = include_res!("model_tt/res/fido/icon_kraken.toif");
|
||||
const ICON_LOGIN_GOV: &[u8] = include_res!("model_tt/res/fido/icon_login.gov.toif");
|
||||
const ICON_MICROSOFT: &[u8] = include_res!("model_tt/res/fido/icon_microsoft.toif");
|
||||
const ICON_MOJEID: &[u8] = include_res!("model_tt/res/fido/icon_mojeid.toif");
|
||||
const ICON_NAMECHEAP: &[u8] = include_res!("model_tt/res/fido/icon_namecheap.toif");
|
||||
const ICON_PROTON: &[u8] = include_res!("model_tt/res/fido/icon_proton.toif");
|
||||
const ICON_SLUSHPOOL: &[u8] = include_res!("model_tt/res/fido/icon_slushpool.toif");
|
||||
const ICON_STRIPE: &[u8] = include_res!("model_tt/res/fido/icon_stripe.toif");
|
||||
const ICON_TUTANOTA: &[u8] = include_res!("model_tt/res/fido/icon_tutanota.toif");
|
||||
/// Default icon when app does not have its own
|
||||
const ICON_WEBAUTHN: &[u8] = include_res!("model_tt/res/fido/icon_webauthn.toif");
|
||||
|
||||
/// Translates icon name into its data.
|
||||
/// Returns default `ICON_WEBAUTHN` when the icon is not found or name not
|
||||
/// supplied.
|
||||
pub fn get_fido_icon_data<T: AsRef<str>>(icon_name: Option<T>) -> &'static [u8] {
|
||||
if let Some(icon_name) = icon_name {
|
||||
match icon_name.as_ref() {
|
||||
"aws" => ICON_AWS,
|
||||
"binance" => ICON_BINANCE,
|
||||
"bitbucket" => ICON_BITBUCKET,
|
||||
"bitfinex" => ICON_BITFINEX,
|
||||
"bitwarden" => ICON_BITWARDEN,
|
||||
"cloudflare" => ICON_CLOUDFLARE,
|
||||
"coinbase" => ICON_COINBASE,
|
||||
"dashlane" => ICON_DASHLANE,
|
||||
"dropbox" => ICON_DROPBOX,
|
||||
"duo" => ICON_DUO,
|
||||
"facebook" => ICON_FACEBOOK,
|
||||
"fastmail" => ICON_FASTMAIL,
|
||||
"fedora" => ICON_FEDORA,
|
||||
"gandi" => ICON_GANDI,
|
||||
"gemini" => ICON_GEMINI,
|
||||
"github" => ICON_GITHUB,
|
||||
"gitlab" => ICON_GITLAB,
|
||||
"google" => ICON_GOOGLE,
|
||||
"invity" => ICON_INVITY,
|
||||
"keeper" => ICON_KEEPER,
|
||||
"kraken" => ICON_KRAKEN,
|
||||
"login.gov" => ICON_LOGIN_GOV,
|
||||
"microsoft" => ICON_MICROSOFT,
|
||||
"mojeid" => ICON_MOJEID,
|
||||
"namecheap" => ICON_NAMECHEAP,
|
||||
"proton" => ICON_PROTON,
|
||||
"slushpool" => ICON_SLUSHPOOL,
|
||||
"stripe" => ICON_STRIPE,
|
||||
"tutanota" => ICON_TUTANOTA,
|
||||
_ => ICON_WEBAUTHN,
|
||||
}
|
||||
} else {
|
||||
ICON_WEBAUTHN
|
||||
}
|
||||
}
|
34
core/embed/rust/src/ui/model_tt/component/fido_icons.rs.mako
Normal file
34
core/embed/rust/src/ui/model_tt/component/fido_icons.rs.mako
Normal file
@ -0,0 +1,34 @@
|
||||
//! generated from webauthn_icons.rs.mako
|
||||
//! (by running `make templates` in `core`)
|
||||
//! do not edit manually!
|
||||
<%
|
||||
icons: list[tuple[str, str]] = []
|
||||
for app in fido:
|
||||
if app.icon is not None:
|
||||
# Variable names cannot have a dot in themselves
|
||||
icon_name = app.key
|
||||
var_name = icon_name.replace(".", "_").upper()
|
||||
icons.append((icon_name, var_name))
|
||||
%>\
|
||||
|
||||
% for icon_name, var_name in icons:
|
||||
const ICON_${var_name}: &[u8] = include_res!("model_tt/res/fido/icon_${icon_name}.toif");
|
||||
% endfor
|
||||
/// Default icon when app does not have its own
|
||||
const ICON_WEBAUTHN: &[u8] = include_res!("model_tt/res/fido/icon_webauthn.toif");
|
||||
|
||||
/// Translates icon name into its data.
|
||||
/// Returns default `ICON_WEBAUTHN` when the icon is not found or name not
|
||||
/// supplied.
|
||||
pub fn get_fido_icon_data<T: AsRef<str>>(icon_name: Option<T>) -> &'static [u8] {
|
||||
if let Some(icon_name) = icon_name {
|
||||
match icon_name.as_ref() {
|
||||
% for icon_name, var_name in icons:
|
||||
"${icon_name}" => ICON_${var_name},
|
||||
% endfor
|
||||
_ => ICON_WEBAUTHN,
|
||||
}
|
||||
} else {
|
||||
ICON_WEBAUTHN
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
mod button;
|
||||
mod dialog;
|
||||
mod fido;
|
||||
mod fido_icons;
|
||||
mod frame;
|
||||
mod hold_to_confirm;
|
||||
mod keyboard;
|
||||
@ -14,6 +16,7 @@ pub use button::{
|
||||
CancelInfoConfirmMsg, SelectWordMsg,
|
||||
};
|
||||
pub use dialog::{Dialog, DialogMsg, IconDialog};
|
||||
pub use fido::{FidoConfirm, FidoMsg};
|
||||
pub use frame::{Frame, NotificationFrame};
|
||||
pub use hold_to_confirm::{HoldToConfirm, HoldToConfirmMsg};
|
||||
pub use keyboard::{
|
||||
|
@ -6,7 +6,9 @@ use crate::{
|
||||
error::Error,
|
||||
micropython::{
|
||||
buffer::StrBuffer,
|
||||
gc::Gc,
|
||||
iter::{Iter, IterBuf},
|
||||
list::List,
|
||||
map::Map,
|
||||
module::Module,
|
||||
obj::Obj,
|
||||
@ -37,11 +39,11 @@ use crate::{
|
||||
use super::{
|
||||
component::{
|
||||
Bip39Input, Button, ButtonMsg, ButtonStyleSheet, CancelConfirmMsg, CancelInfoConfirmMsg,
|
||||
Dialog, DialogMsg, Frame, HoldToConfirm, HoldToConfirmMsg, IconDialog, MnemonicInput,
|
||||
MnemonicKeyboard, MnemonicKeyboardMsg, NotificationFrame, NumberInputDialog,
|
||||
NumberInputDialogMsg, PassphraseKeyboard, PassphraseKeyboardMsg, PinKeyboard,
|
||||
PinKeyboardMsg, SelectWordCount, SelectWordCountMsg, SelectWordMsg, Slip39Input,
|
||||
SwipeHoldPage, SwipePage,
|
||||
Dialog, DialogMsg, FidoConfirm, FidoMsg, Frame, HoldToConfirm, HoldToConfirmMsg,
|
||||
IconDialog, MnemonicInput, MnemonicKeyboard, MnemonicKeyboardMsg, NotificationFrame,
|
||||
NumberInputDialog, NumberInputDialogMsg, PassphraseKeyboard, PassphraseKeyboardMsg,
|
||||
PinKeyboard, PinKeyboardMsg, SelectWordCount, SelectWordCountMsg, SelectWordMsg,
|
||||
Slip39Input, SwipeHoldPage, SwipePage,
|
||||
},
|
||||
theme,
|
||||
};
|
||||
@ -89,6 +91,20 @@ impl TryFrom<SelectWordCountMsg> for Obj {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T, U> ComponentMsgObj for FidoConfirm<F, T, U>
|
||||
where
|
||||
F: Fn(usize) -> T,
|
||||
T: Deref<Target = str> + From<&'static str>,
|
||||
U: Component<Msg = CancelConfirmMsg>,
|
||||
{
|
||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||
match msg {
|
||||
FidoMsg::Confirmed(page) => Ok((page as u8).into()),
|
||||
FidoMsg::Cancelled => Ok(CANCELLED.as_obj()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> ComponentMsgObj for Dialog<T, U>
|
||||
where
|
||||
T: ComponentMsgObj,
|
||||
@ -661,6 +677,37 @@ extern "C" fn new_show_error(n_args: usize, args: *const Obj, kwargs: *mut Map)
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||
let app_name: StrBuffer = kwargs.get(Qstr::MP_QSTR_app_name)?.try_into()?;
|
||||
let icon: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_icon_name)?.try_into_option()?;
|
||||
let accounts: Gc<List> = kwargs.get(Qstr::MP_QSTR_accounts)?.try_into()?;
|
||||
|
||||
// Cache the page count so that we can move `accounts` into the closure.
|
||||
let page_count = accounts.len();
|
||||
// Closure to lazy-load the information on given page index.
|
||||
// Done like this to allow arbitrarily many pages without
|
||||
// the need of any allocation here in Rust.
|
||||
let get_page = move |page_index| {
|
||||
let account = unwrap!(accounts.get(page_index));
|
||||
account.try_into().unwrap_or_else(|_| "".into())
|
||||
};
|
||||
|
||||
let controls = Button::cancel_confirm(
|
||||
Button::with_icon(theme::ICON_CANCEL).styled(theme::button_cancel()),
|
||||
Button::with_text("CONFIRM").styled(theme::button_confirm()),
|
||||
2,
|
||||
);
|
||||
|
||||
let fido_page = FidoConfirm::new(app_name, get_page, page_count, icon, controls);
|
||||
|
||||
let obj = LayoutObj::new(Frame::new(title, fido_page).with_border(theme::borders()))?;
|
||||
Ok(obj.into())
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let icon = BlendedImage::new(
|
||||
@ -1172,6 +1219,19 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// """Decrease or increase transaction fee."""
|
||||
Qstr::MP_QSTR_confirm_modify_fee => obj_fn_kw!(0, new_confirm_modify_fee).as_obj(),
|
||||
|
||||
/// def confirm_fido(
|
||||
/// *,
|
||||
/// title: str,
|
||||
/// app_name: str,
|
||||
/// icon_name: str | None,
|
||||
/// accounts: list[str | None],
|
||||
/// ) -> int | object:
|
||||
/// """FIDO confirmation.
|
||||
///
|
||||
/// Returns page index in case of confirmation and CANCELLED otherwise.
|
||||
/// """
|
||||
Qstr::MP_QSTR_confirm_fido => obj_fn_kw!(0, new_confirm_fido).as_obj(),
|
||||
|
||||
/// def show_error(
|
||||
/// *,
|
||||
/// title: str,
|
||||
|
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_aws.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_aws.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_binance.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_binance.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_bitbucket.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_bitbucket.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_bitfinex.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_bitfinex.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_bitwarden.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_bitwarden.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_cloudflare.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_cloudflare.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_coinbase.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_coinbase.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_dashlane.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_dashlane.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_dropbox.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_dropbox.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_duo.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_duo.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_facebook.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_facebook.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_fastmail.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_fastmail.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_fedora.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_fedora.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_gandi.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_gandi.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_gemini.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_gemini.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_github.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_github.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_gitlab.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_gitlab.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_google.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_google.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_invity.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_invity.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_keeper.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_keeper.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_kraken.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_kraken.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_login.gov.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_login.gov.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_microsoft.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_microsoft.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_mojeid.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_mojeid.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_namecheap.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_namecheap.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_proton.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_proton.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_slushpool.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_slushpool.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_stripe.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_stripe.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_tutanota.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_tutanota.toif
Normal file
Binary file not shown.
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_webauthn.toif
Normal file
BIN
core/embed/rust/src/ui/model_tt/res/fido/icon_webauthn.toif
Normal file
Binary file not shown.
@ -159,6 +159,19 @@ def confirm_modify_fee(
|
||||
"""Decrease or increase transaction fee."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_fido(
|
||||
*,
|
||||
title: str,
|
||||
app_name: str,
|
||||
icon_name: str | None,
|
||||
accounts: list[str | None],
|
||||
) -> int | object:
|
||||
"""FIDO confirmation.
|
||||
Returns page index in case of confirmation and CANCELLED otherwise.
|
||||
"""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_error(
|
||||
*,
|
||||
|
@ -155,6 +155,8 @@ trezor.ui.layouts
|
||||
import trezor.ui.layouts
|
||||
trezor.ui.layouts.common
|
||||
import trezor.ui.layouts.common
|
||||
trezor.ui.layouts.fido
|
||||
import trezor.ui.layouts.fido
|
||||
trezor.ui.layouts.recovery
|
||||
import trezor.ui.layouts.recovery
|
||||
trezor.ui.layouts.reset
|
||||
@ -165,6 +167,8 @@ trezor.ui.layouts.tr
|
||||
import trezor.ui.layouts.tr
|
||||
trezor.ui.layouts.tt_v2
|
||||
import trezor.ui.layouts.tt_v2
|
||||
trezor.ui.layouts.tt_v2.fido
|
||||
import trezor.ui.layouts.tt_v2.fido
|
||||
trezor.ui.layouts.tt_v2.recovery
|
||||
import trezor.ui.layouts.tt_v2.recovery
|
||||
trezor.ui.layouts.tt_v2.reset
|
||||
@ -405,12 +409,6 @@ if not utils.BITCOIN_ONLY:
|
||||
import trezor.enums.TezosBallotType
|
||||
trezor.enums.TezosContractType
|
||||
import trezor.enums.TezosContractType
|
||||
trezor.ui.components.common.webauthn
|
||||
import trezor.ui.components.common.webauthn
|
||||
trezor.ui.layouts.tt_v2.webauthn
|
||||
import trezor.ui.layouts.tt_v2.webauthn
|
||||
trezor.ui.layouts.webauthn
|
||||
import trezor.ui.layouts.webauthn
|
||||
apps.binance
|
||||
import apps.binance
|
||||
apps.binance.get_address
|
||||
|
@ -1,27 +1,8 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from trezor.ui.components.common.webauthn import ConfirmInfo
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from trezor.messages import WebAuthnAddResidentCredential, Success
|
||||
from trezor.wire import Context
|
||||
from .credential import Fido2Credential
|
||||
|
||||
|
||||
class ConfirmAddCredential(ConfirmInfo):
|
||||
def __init__(self, cred: Fido2Credential):
|
||||
super().__init__()
|
||||
self._cred = cred
|
||||
self.load_icon(cred.rp_id_hash)
|
||||
|
||||
def get_header(self) -> str:
|
||||
return "Import credential"
|
||||
|
||||
def app_name(self) -> str:
|
||||
return self._cred.app_name()
|
||||
|
||||
def account_name(self) -> str | None:
|
||||
return self._cred.account_name()
|
||||
|
||||
|
||||
async def add_resident_credential(
|
||||
@ -30,7 +11,7 @@ async def add_resident_credential(
|
||||
import storage.device as storage_device
|
||||
from trezor import wire
|
||||
from trezor.ui.layouts import show_error_and_raise
|
||||
from trezor.ui.layouts.webauthn import confirm_webauthn
|
||||
from trezor.ui.layouts.fido import confirm_fido
|
||||
from trezor.messages import Success
|
||||
from .credential import Fido2Credential
|
||||
from .resident_credentials import store_resident_credential
|
||||
@ -49,8 +30,13 @@ async def add_resident_credential(
|
||||
"The credential you are trying to import does\nnot belong to this authenticator.",
|
||||
)
|
||||
|
||||
if not await confirm_webauthn(ctx, ConfirmAddCredential(cred)):
|
||||
raise wire.ActionCancelled
|
||||
await confirm_fido(
|
||||
ctx,
|
||||
"Import credential",
|
||||
cred.app_name(),
|
||||
cred.icon_name(),
|
||||
[cred.account_name()],
|
||||
)
|
||||
|
||||
if store_resident_credential(cred):
|
||||
return Success(message="Credential added")
|
||||
|
@ -71,6 +71,12 @@ class Credential:
|
||||
def app_name(self) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
def icon_name(self) -> str | None:
|
||||
from . import knownapps
|
||||
|
||||
fido_app = knownapps.by_rp_id_hash(self.rp_id_hash)
|
||||
return None if fido_app is None else fido_app.icon_name
|
||||
|
||||
def account_name(self) -> str | None:
|
||||
return None
|
||||
|
||||
|
@ -5,13 +5,10 @@ from micropython import const
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import storage.device as storage_device
|
||||
from trezor import config, io, log, loop, utils, workflow
|
||||
from trezor import config, io, log, loop, utils, wire, workflow
|
||||
from trezor.crypto import hashlib
|
||||
from trezor.crypto.curve import nist256p1
|
||||
from trezor.ui.components.common.confirm import Pageable
|
||||
from trezor.ui.components.common.webauthn import ConfirmInfo
|
||||
from trezor.ui.layouts import show_popup
|
||||
from trezor.ui.layouts.webauthn import confirm_webauthn
|
||||
|
||||
from apps.base import set_homescreen
|
||||
from apps.common import cbor
|
||||
@ -20,7 +17,7 @@ from . import common
|
||||
from .credential import Credential, Fido2Credential
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Callable, Coroutine, Iterable, Iterator
|
||||
from typing import Any, Awaitable, Callable, Coroutine, Iterable, Iterator
|
||||
from .credential import U2fCredential
|
||||
|
||||
HID = io.HID
|
||||
@ -587,6 +584,33 @@ async def verify_user(keepalive_callback: KeepaliveCallback) -> bool:
|
||||
return ret
|
||||
|
||||
|
||||
def _confirm_fido_choose(title: str, credentials: list[Credential]) -> Awaitable[int]:
|
||||
from trezor.ui.layouts.fido import confirm_fido
|
||||
from . import knownapps
|
||||
|
||||
assert len(credentials) > 0
|
||||
repr_credential = credentials[0]
|
||||
|
||||
if __debug__:
|
||||
for cred in credentials:
|
||||
assert cred.rp_id_hash == repr_credential.rp_id_hash
|
||||
|
||||
app_name = repr_credential.app_name()
|
||||
app = knownapps.by_rp_id_hash(repr_credential.rp_id_hash)
|
||||
icon_name = None if app is None else app.icon_name
|
||||
return confirm_fido(
|
||||
None, title, app_name, icon_name, [c.account_name() for c in credentials]
|
||||
)
|
||||
|
||||
|
||||
async def _confirm_fido(title: str, credential: Credential) -> bool:
|
||||
try:
|
||||
await _confirm_fido_choose(title, [credential])
|
||||
return True
|
||||
except wire.ActionCancelled:
|
||||
return False
|
||||
|
||||
|
||||
class State:
|
||||
def __init__(self, cid: int, iface: HID) -> None:
|
||||
self.cid = cid
|
||||
@ -616,13 +640,11 @@ class State:
|
||||
pass
|
||||
|
||||
|
||||
class U2fState(State, ConfirmInfo):
|
||||
class U2fState(State):
|
||||
def __init__(self, cid: int, iface: HID, req_data: bytes, cred: Credential) -> None:
|
||||
State.__init__(self, cid, iface)
|
||||
ConfirmInfo.__init__(self)
|
||||
self._cred = cred
|
||||
self._req_data = req_data
|
||||
self.load_icon(self._cred.rp_id_hash)
|
||||
|
||||
def timeout_ms(self) -> int:
|
||||
return _U2F_CONFIRM_TIMEOUT_MS
|
||||
@ -658,10 +680,7 @@ class U2fConfirmRegister(U2fState):
|
||||
)
|
||||
return False
|
||||
else:
|
||||
return await confirm_webauthn(None, self)
|
||||
|
||||
def get_header(self) -> str:
|
||||
return "U2F Register"
|
||||
return await _confirm_fido("U2F Register", self._cred)
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
return (
|
||||
@ -675,11 +694,8 @@ class U2fConfirmAuthenticate(U2fState):
|
||||
def __init__(self, cid: int, iface: HID, req_data: bytes, cred: Credential) -> None:
|
||||
super().__init__(cid, iface, req_data, cred)
|
||||
|
||||
def get_header(self) -> str:
|
||||
return "U2F Authenticate"
|
||||
|
||||
async def confirm_dialog(self) -> bool:
|
||||
return await confirm_webauthn(None, self)
|
||||
return await _confirm_fido("U2F Authenticate", self._cred)
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
return (
|
||||
@ -767,7 +783,7 @@ class Fido2Unlock(Fido2State):
|
||||
await send_cmd(self.resp, self.iface)
|
||||
|
||||
|
||||
class Fido2ConfirmMakeCredential(Fido2State, ConfirmInfo):
|
||||
class Fido2ConfirmMakeCredential(Fido2State):
|
||||
def __init__(
|
||||
self,
|
||||
cid: int,
|
||||
@ -778,24 +794,13 @@ class Fido2ConfirmMakeCredential(Fido2State, ConfirmInfo):
|
||||
user_verification: bool,
|
||||
) -> None:
|
||||
Fido2State.__init__(self, cid, iface)
|
||||
ConfirmInfo.__init__(self)
|
||||
self._client_data_hash = client_data_hash
|
||||
self._cred = cred
|
||||
self._resident = resident
|
||||
self._user_verification = user_verification
|
||||
self.load_icon(cred.rp_id_hash)
|
||||
|
||||
def get_header(self) -> str:
|
||||
return "FIDO2 Register"
|
||||
|
||||
def app_name(self) -> str:
|
||||
return self._cred.app_name()
|
||||
|
||||
def account_name(self) -> str | None:
|
||||
return self._cred.account_name()
|
||||
|
||||
async def confirm_dialog(self) -> bool:
|
||||
if not await confirm_webauthn(None, self):
|
||||
if not await _confirm_fido("FIDO2 Register", self._cred):
|
||||
return False
|
||||
if self._user_verification:
|
||||
return await verify_user(KeepaliveCallback(self.cid, self.iface))
|
||||
@ -839,7 +844,7 @@ class Fido2ConfirmExcluded(Fido2ConfirmMakeCredential):
|
||||
)
|
||||
|
||||
|
||||
class Fido2ConfirmGetAssertion(Fido2State, ConfirmInfo, Pageable):
|
||||
class Fido2ConfirmGetAssertion(Fido2State):
|
||||
def __init__(
|
||||
self,
|
||||
cid: int,
|
||||
@ -851,30 +856,21 @@ class Fido2ConfirmGetAssertion(Fido2State, ConfirmInfo, Pageable):
|
||||
user_verification: bool,
|
||||
) -> None:
|
||||
Fido2State.__init__(self, cid, iface)
|
||||
ConfirmInfo.__init__(self)
|
||||
Pageable.__init__(self)
|
||||
self._client_data_hash = client_data_hash
|
||||
self._creds = creds
|
||||
self._hmac_secret = hmac_secret
|
||||
self._resident = resident
|
||||
self._user_verification = user_verification
|
||||
self.load_icon(self._creds[0].rp_id_hash)
|
||||
|
||||
def get_header(self) -> str:
|
||||
return "FIDO2 Authenticate"
|
||||
|
||||
def app_name(self) -> str:
|
||||
return self._creds[self.page()].app_name()
|
||||
|
||||
def account_name(self) -> str | None:
|
||||
return self._creds[self.page()].account_name()
|
||||
|
||||
def page_count(self) -> int:
|
||||
return len(self._creds)
|
||||
self._selected_cred: Credential | None = None
|
||||
|
||||
async def confirm_dialog(self) -> bool:
|
||||
if not await confirm_webauthn(None, self, pageable=self):
|
||||
# There is a choice from more than one credential.
|
||||
try:
|
||||
index = await _confirm_fido_choose("FIDO2 Authenticate", self._creds)
|
||||
except wire.ActionCancelled:
|
||||
return False
|
||||
|
||||
self._selected_cred = self._creds[index]
|
||||
if self._user_verification:
|
||||
return await verify_user(KeepaliveCallback(self.cid, self.iface))
|
||||
return True
|
||||
@ -882,13 +878,13 @@ class Fido2ConfirmGetAssertion(Fido2State, ConfirmInfo, Pageable):
|
||||
async def on_confirm(self) -> None:
|
||||
cid = self.cid # local_cache_attribute
|
||||
|
||||
cred = self._creds[self.page()]
|
||||
assert self._selected_cred is not None
|
||||
try:
|
||||
send_cmd_sync(cmd_keepalive(cid, _KEEPALIVE_STATUS_PROCESSING), self.iface)
|
||||
response_data = cbor_get_assertion_sign(
|
||||
self._client_data_hash,
|
||||
cred.rp_id_hash,
|
||||
cred,
|
||||
self._selected_cred.rp_id_hash,
|
||||
self._selected_cred,
|
||||
self._hmac_secret,
|
||||
self._resident,
|
||||
True,
|
||||
@ -954,9 +950,9 @@ class Fido2ConfirmReset(Fido2State):
|
||||
super().__init__(cid, iface)
|
||||
|
||||
async def confirm_dialog(self) -> bool:
|
||||
from trezor.ui.layouts.webauthn import confirm_webauthn_reset
|
||||
from trezor.ui.layouts.fido import confirm_fido_reset
|
||||
|
||||
return await confirm_webauthn_reset()
|
||||
return await confirm_fido_reset()
|
||||
|
||||
async def on_confirm(self) -> None:
|
||||
import storage.resident_credentials
|
||||
|
@ -9,12 +9,12 @@ class FIDOApp:
|
||||
def __init__(
|
||||
self,
|
||||
label: str,
|
||||
icon: str | None,
|
||||
icon_name: str | None,
|
||||
use_sign_count: bool | None,
|
||||
use_self_attestation: bool | None,
|
||||
) -> None:
|
||||
self.label = label
|
||||
self.icon = icon
|
||||
self.icon_name = icon_name
|
||||
self.use_sign_count = use_sign_count
|
||||
self.use_self_attestation = use_self_attestation
|
||||
|
||||
@ -25,7 +25,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Amazon Web Services
|
||||
return FIDOApp(
|
||||
"aws.amazon.com", # label
|
||||
"apps/webauthn/res/icon_aws.toif", # icon
|
||||
"aws", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -33,7 +33,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Binance
|
||||
return FIDOApp(
|
||||
"www.binance.com", # label
|
||||
"apps/webauthn/res/icon_binance.toif", # icon
|
||||
"binance", # icon_name
|
||||
False, # use_sign_count
|
||||
True, # use_self_attestation
|
||||
)
|
||||
@ -41,7 +41,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Binance
|
||||
return FIDOApp(
|
||||
"binance.com", # label
|
||||
"apps/webauthn/res/icon_binance.toif", # icon
|
||||
"binance", # icon_name
|
||||
False, # use_sign_count
|
||||
True, # use_self_attestation
|
||||
)
|
||||
@ -49,7 +49,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Bitbucket
|
||||
return FIDOApp(
|
||||
"bitbucket.org", # label
|
||||
"apps/webauthn/res/icon_bitbucket.toif", # icon
|
||||
"bitbucket", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -57,7 +57,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Bitfinex
|
||||
return FIDOApp(
|
||||
"www.bitfinex.com", # label
|
||||
"apps/webauthn/res/icon_bitfinex.toif", # icon
|
||||
"bitfinex", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -65,7 +65,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Bitwarden
|
||||
return FIDOApp(
|
||||
"vault.bitwarden.com", # label
|
||||
"apps/webauthn/res/icon_bitwarden.toif", # icon
|
||||
"bitwarden", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -73,7 +73,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Cloudflare
|
||||
return FIDOApp(
|
||||
"dash.cloudflare.com", # label
|
||||
"apps/webauthn/res/icon_cloudflare.toif", # icon
|
||||
"cloudflare", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -81,7 +81,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Coinbase
|
||||
return FIDOApp(
|
||||
"coinbase.com", # label
|
||||
"apps/webauthn/res/icon_coinbase.toif", # icon
|
||||
"coinbase", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -89,7 +89,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Dashlane
|
||||
return FIDOApp(
|
||||
"www.dashlane.com", # label
|
||||
"apps/webauthn/res/icon_dashlane.toif", # icon
|
||||
"dashlane", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -97,7 +97,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Dropbox
|
||||
return FIDOApp(
|
||||
"www.dropbox.com", # label
|
||||
"apps/webauthn/res/icon_dropbox.toif", # icon
|
||||
"dropbox", # icon_name
|
||||
False, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -105,7 +105,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Dropbox
|
||||
return FIDOApp(
|
||||
"www.dropbox.com", # label
|
||||
"apps/webauthn/res/icon_dropbox.toif", # icon
|
||||
"dropbox", # icon_name
|
||||
False, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -113,7 +113,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Duo
|
||||
return FIDOApp(
|
||||
"duosecurity.com", # label
|
||||
"apps/webauthn/res/icon_duo.toif", # icon
|
||||
"duo", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -121,7 +121,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Facebook
|
||||
return FIDOApp(
|
||||
"facebook.com", # label
|
||||
"apps/webauthn/res/icon_facebook.toif", # icon
|
||||
"facebook", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -129,7 +129,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for FastMail
|
||||
return FIDOApp(
|
||||
"www.fastmail.com", # label
|
||||
"apps/webauthn/res/icon_fastmail.toif", # icon
|
||||
"fastmail", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -137,7 +137,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for FastMail
|
||||
return FIDOApp(
|
||||
"fastmail.com", # label
|
||||
"apps/webauthn/res/icon_fastmail.toif", # icon
|
||||
"fastmail", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -145,7 +145,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Fedora
|
||||
return FIDOApp(
|
||||
"fedoraproject.org", # label
|
||||
"apps/webauthn/res/icon_fedora.toif", # icon
|
||||
"fedora", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -153,7 +153,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Gandi
|
||||
return FIDOApp(
|
||||
"gandi.net", # label
|
||||
"apps/webauthn/res/icon_gandi.toif", # icon
|
||||
"gandi", # icon_name
|
||||
False, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -161,7 +161,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Gandi
|
||||
return FIDOApp(
|
||||
"gandi.net", # label
|
||||
"apps/webauthn/res/icon_gandi.toif", # icon
|
||||
"gandi", # icon_name
|
||||
False, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -169,7 +169,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Gemini
|
||||
return FIDOApp(
|
||||
"gemini.com", # label
|
||||
"apps/webauthn/res/icon_gemini.toif", # icon
|
||||
"gemini", # icon_name
|
||||
False, # use_sign_count
|
||||
True, # use_self_attestation
|
||||
)
|
||||
@ -177,7 +177,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for GitHub
|
||||
return FIDOApp(
|
||||
"github.com", # label
|
||||
"apps/webauthn/res/icon_github.toif", # icon
|
||||
"github", # icon_name
|
||||
True, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -185,7 +185,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for GitHub
|
||||
return FIDOApp(
|
||||
"github.com", # label
|
||||
"apps/webauthn/res/icon_github.toif", # icon
|
||||
"github", # icon_name
|
||||
True, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -193,7 +193,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for GitLab
|
||||
return FIDOApp(
|
||||
"gitlab.com", # label
|
||||
"apps/webauthn/res/icon_gitlab.toif", # icon
|
||||
"gitlab", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -201,7 +201,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Google
|
||||
return FIDOApp(
|
||||
"google.com", # label
|
||||
"apps/webauthn/res/icon_google.toif", # icon
|
||||
"google", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -209,7 +209,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Google
|
||||
return FIDOApp(
|
||||
"google.com", # label
|
||||
"apps/webauthn/res/icon_google.toif", # icon
|
||||
"google", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -217,7 +217,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Invity
|
||||
return FIDOApp(
|
||||
"invity.io", # label
|
||||
"apps/webauthn/res/icon_invity.toif", # icon
|
||||
"invity", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -225,7 +225,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Keeper
|
||||
return FIDOApp(
|
||||
"keepersecurity.com", # label
|
||||
"apps/webauthn/res/icon_keeper.toif", # icon
|
||||
"keeper", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -233,7 +233,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Keeper
|
||||
return FIDOApp(
|
||||
"keepersecurity.eu", # label
|
||||
"apps/webauthn/res/icon_keeper.toif", # icon
|
||||
"keeper", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -241,7 +241,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Kraken
|
||||
return FIDOApp(
|
||||
"kraken.com", # label
|
||||
"apps/webauthn/res/icon_kraken.toif", # icon
|
||||
"kraken", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -249,7 +249,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for login.gov
|
||||
return FIDOApp(
|
||||
"secure.login.gov", # label
|
||||
"apps/webauthn/res/icon_login.gov.toif", # icon
|
||||
"login.gov", # icon_name
|
||||
False, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -257,7 +257,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Microsoft
|
||||
return FIDOApp(
|
||||
"login.microsoft.com", # label
|
||||
"apps/webauthn/res/icon_microsoft.toif", # icon
|
||||
"microsoft", # icon_name
|
||||
False, # use_sign_count
|
||||
False, # use_self_attestation
|
||||
)
|
||||
@ -265,7 +265,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for mojeID
|
||||
return FIDOApp(
|
||||
"mojeid.cz", # label
|
||||
"apps/webauthn/res/icon_mojeid.toif", # icon
|
||||
"mojeid", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -273,7 +273,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Namecheap
|
||||
return FIDOApp(
|
||||
"www.namecheap.com", # label
|
||||
"apps/webauthn/res/icon_namecheap.toif", # icon
|
||||
"namecheap", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -281,7 +281,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for Proton
|
||||
return FIDOApp(
|
||||
"proton.me", # label
|
||||
"apps/webauthn/res/icon_proton.toif", # icon
|
||||
"proton", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -289,7 +289,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Slush Pool
|
||||
return FIDOApp(
|
||||
"slushpool.com", # label
|
||||
"apps/webauthn/res/icon_slushpool.toif", # icon
|
||||
"slushpool", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -297,7 +297,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Slush Pool
|
||||
return FIDOApp(
|
||||
"slushpool.com", # label
|
||||
"apps/webauthn/res/icon_slushpool.toif", # icon
|
||||
"slushpool", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -305,7 +305,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Stripe
|
||||
return FIDOApp(
|
||||
"stripe.com", # label
|
||||
"apps/webauthn/res/icon_stripe.toif", # icon
|
||||
"stripe", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -313,7 +313,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for Tutanota
|
||||
return FIDOApp(
|
||||
"tutanota.com", # label
|
||||
"apps/webauthn/res/icon_tutanota.toif", # icon
|
||||
"tutanota", # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -321,7 +321,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# U2F key for u2f.bin.coffee
|
||||
return FIDOApp(
|
||||
"u2f.bin.coffee", # label
|
||||
None, # icon
|
||||
None, # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -329,7 +329,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for webauthn.bin.coffee
|
||||
return FIDOApp(
|
||||
"webauthn.bin.coffee", # label
|
||||
None, # icon
|
||||
None, # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -337,7 +337,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for WebAuthn.io
|
||||
return FIDOApp(
|
||||
"webauthn.io", # label
|
||||
None, # icon
|
||||
None, # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -345,7 +345,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for WebAuthn.me
|
||||
return FIDOApp(
|
||||
"webauthn.me", # label
|
||||
None, # icon
|
||||
None, # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
@ -353,7 +353,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# WebAuthn key for demo.yubico.com
|
||||
return FIDOApp(
|
||||
"demo.yubico.com", # label
|
||||
None, # icon
|
||||
None, # icon_name
|
||||
None, # use_sign_count
|
||||
None, # use_self_attestation
|
||||
)
|
||||
|
@ -9,12 +9,12 @@ class FIDOApp:
|
||||
def __init__(
|
||||
self,
|
||||
label: str,
|
||||
icon: str | None,
|
||||
icon_name: str | None,
|
||||
use_sign_count: bool | None,
|
||||
use_self_attestation: bool | None,
|
||||
) -> None:
|
||||
self.label = label
|
||||
self.icon = icon
|
||||
self.icon_name = icon_name
|
||||
self.use_sign_count = use_sign_count
|
||||
self.use_self_attestation = use_self_attestation
|
||||
|
||||
@ -30,9 +30,9 @@ for app in fido:
|
||||
rp_id_hash = sha256(origin.encode()).digest()
|
||||
fido_entries.append((origin, rp_id_hash, "WebAuthn", app))
|
||||
if app.icon is not None:
|
||||
app.icon_res = f"apps/webauthn/res/icon_{app.key}.toif"
|
||||
app.icon_name = app.key
|
||||
else:
|
||||
app.icon_res = None
|
||||
app.icon_name = None
|
||||
%>\
|
||||
# fmt: off
|
||||
def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
@ -41,7 +41,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
||||
# ${type} key for ${app.name}
|
||||
return FIDOApp(
|
||||
${black_repr(label)}, # label
|
||||
${black_repr(app.icon_res)}, # icon
|
||||
${black_repr(app.icon_name)}, # icon_name
|
||||
${black_repr(app.use_sign_count)}, # use_sign_count
|
||||
${black_repr(app.use_self_attestation)}, # use_self_attestation
|
||||
)
|
||||
|
@ -1,29 +1,10 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from trezor.ui.components.common.webauthn import ConfirmInfo
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from trezor.messages import WebAuthnRemoveResidentCredential, Success
|
||||
from .credential import Fido2Credential
|
||||
from trezor.wire import Context
|
||||
|
||||
|
||||
class ConfirmRemoveCredential(ConfirmInfo):
|
||||
def __init__(self, cred: Fido2Credential):
|
||||
super().__init__()
|
||||
self._cred = cred
|
||||
self.load_icon(cred.rp_id_hash)
|
||||
|
||||
def get_header(self) -> str:
|
||||
return "Remove credential"
|
||||
|
||||
def app_name(self) -> str:
|
||||
return self._cred.app_name()
|
||||
|
||||
def account_name(self) -> str | None:
|
||||
return self._cred.account_name()
|
||||
|
||||
|
||||
async def remove_resident_credential(
|
||||
ctx: Context, msg: WebAuthnRemoveResidentCredential
|
||||
) -> Success:
|
||||
@ -31,7 +12,7 @@ async def remove_resident_credential(
|
||||
import storage.resident_credentials
|
||||
from trezor import wire
|
||||
from trezor.messages import Success
|
||||
from trezor.ui.layouts.webauthn import confirm_webauthn
|
||||
from trezor.ui.layouts.fido import confirm_fido
|
||||
from .resident_credentials import get_resident_credential
|
||||
|
||||
if not storage.device.is_initialized():
|
||||
@ -43,8 +24,13 @@ async def remove_resident_credential(
|
||||
if cred is None:
|
||||
raise wire.ProcessError("Invalid credential index.")
|
||||
|
||||
if not await confirm_webauthn(ctx, ConfirmRemoveCredential(cred)):
|
||||
raise wire.ActionCancelled
|
||||
await confirm_fido(
|
||||
ctx,
|
||||
"Remove credential",
|
||||
cred.app_name(),
|
||||
cred.icon_name(),
|
||||
[cred.account_name()],
|
||||
)
|
||||
|
||||
assert cred.index is not None
|
||||
storage.resident_credentials.delete(cred.index)
|
||||
|
@ -1,25 +0,0 @@
|
||||
DEFAULT_ICON = "apps/webauthn/res/icon_webauthn.toif"
|
||||
|
||||
|
||||
class ConfirmInfo:
|
||||
def __init__(self) -> None:
|
||||
self.app_icon: bytes | None = None
|
||||
|
||||
def get_header(self) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
def app_name(self) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
def account_name(self) -> str | None:
|
||||
return None
|
||||
|
||||
def load_icon(self, rp_id_hash: bytes) -> None:
|
||||
from trezor import res
|
||||
from apps.webauthn import knownapps
|
||||
|
||||
fido_app = knownapps.by_rp_id_hash(rp_id_hash)
|
||||
if fido_app is not None and fido_app.icon is not None:
|
||||
self.app_icon = res.load(fido_app.icon)
|
||||
else:
|
||||
self.app_icon = res.load(DEFAULT_ICON)
|
1
core/src/trezor/ui/layouts/fido.py
Normal file
1
core/src/trezor/ui/layouts/fido.py
Normal file
@ -0,0 +1 @@
|
||||
from .tt_v2.fido import * # noqa: F401,F403
|
96
core/src/trezor/ui/layouts/tt_v2/fido.py
Normal file
96
core/src/trezor/ui/layouts/tt_v2/fido.py
Normal file
@ -0,0 +1,96 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from trezor.enums import ButtonRequestType
|
||||
|
||||
import trezorui2
|
||||
|
||||
from ..common import interact
|
||||
from . import _RustLayout
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from trezor.loop import AwaitableTask
|
||||
from trezor.wire import GenericContext
|
||||
|
||||
|
||||
if __debug__:
|
||||
from trezor import io
|
||||
from ... import Result
|
||||
|
||||
class _RustFidoLayoutImpl(_RustLayout):
|
||||
def create_tasks(self) -> tuple[AwaitableTask, ...]:
|
||||
return (
|
||||
self.handle_timers(),
|
||||
self.handle_input_and_rendering(),
|
||||
self.handle_swipe(),
|
||||
self.handle_debug_confirm(),
|
||||
)
|
||||
|
||||
async def handle_debug_confirm(self) -> None:
|
||||
from apps.debug import confirm_signal
|
||||
|
||||
try:
|
||||
await confirm_signal()
|
||||
except Result as r:
|
||||
if r.value is not trezorui2.CONFIRMED:
|
||||
raise
|
||||
else:
|
||||
return
|
||||
|
||||
for event, x, y in (
|
||||
(io.TOUCH_START, 220, 220),
|
||||
(io.TOUCH_END, 220, 220),
|
||||
):
|
||||
msg = self.layout.touch_event(event, x, y)
|
||||
self.layout.paint()
|
||||
if msg is not None:
|
||||
raise Result(msg)
|
||||
|
||||
_RustFidoLayout = _RustFidoLayoutImpl
|
||||
|
||||
else:
|
||||
_RustFidoLayout = _RustLayout
|
||||
|
||||
|
||||
async def confirm_fido(
|
||||
ctx: GenericContext | None,
|
||||
header: str,
|
||||
app_name: str,
|
||||
icon_name: str | None,
|
||||
accounts: list[str | None],
|
||||
) -> int:
|
||||
"""Webauthn confirmation for one or more credentials."""
|
||||
confirm = _RustFidoLayout(
|
||||
trezorui2.confirm_fido(
|
||||
title=header.upper(),
|
||||
app_name=app_name,
|
||||
icon_name=icon_name,
|
||||
accounts=accounts,
|
||||
)
|
||||
)
|
||||
|
||||
if ctx is None:
|
||||
result = await confirm
|
||||
else:
|
||||
result = await interact(ctx, confirm, "confirm_fido", ButtonRequestType.Other)
|
||||
|
||||
# The Rust side returns either an int or `CANCELLED`. We detect the int situation
|
||||
# and assume cancellation otherwise.
|
||||
if isinstance(result, int):
|
||||
return result
|
||||
|
||||
# Late import won't get executed on the happy path.
|
||||
from trezor.wire import ActionCancelled
|
||||
|
||||
raise ActionCancelled
|
||||
|
||||
|
||||
async def confirm_fido_reset() -> bool:
|
||||
confirm = _RustLayout(
|
||||
trezorui2.confirm_action(
|
||||
title="FIDO2 RESET",
|
||||
action="erase all credentials?",
|
||||
description="Do you really want to",
|
||||
reverse=True,
|
||||
)
|
||||
)
|
||||
return (await confirm) is trezorui2.CONFIRMED
|
@ -1,49 +0,0 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from trezor.enums import ButtonRequestType
|
||||
|
||||
import trezorui2
|
||||
|
||||
from ...components.common.confirm import is_confirmed
|
||||
from ...components.common.webauthn import ConfirmInfo
|
||||
from ..common import interact
|
||||
from . import _RustLayout
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from trezor.wire import GenericContext
|
||||
|
||||
Pageable = object
|
||||
|
||||
|
||||
async def confirm_webauthn(
|
||||
ctx: GenericContext | None,
|
||||
info: ConfirmInfo,
|
||||
pageable: Pageable | None = None,
|
||||
) -> bool:
|
||||
if pageable is not None:
|
||||
raise NotImplementedError
|
||||
|
||||
confirm = _RustLayout(
|
||||
trezorui2.confirm_blob(
|
||||
title=info.get_header().upper(),
|
||||
data=f"{info.app_name()}\n{info.account_name()}",
|
||||
)
|
||||
)
|
||||
|
||||
if ctx is None:
|
||||
return is_confirmed(await confirm)
|
||||
else:
|
||||
return is_confirmed(
|
||||
await interact(ctx, confirm, "confirm_webauthn", ButtonRequestType.Other)
|
||||
)
|
||||
|
||||
|
||||
async def confirm_webauthn_reset() -> bool:
|
||||
return is_confirmed(
|
||||
await _RustLayout(
|
||||
trezorui2.confirm_blob(
|
||||
title="FIDO2 RESET",
|
||||
data="Do you really want to\nerase all credentials?",
|
||||
)
|
||||
)
|
||||
)
|
@ -1 +0,0 @@
|
||||
from .tt_v2.webauthn import * # noqa: F401,F403
|
@ -12,7 +12,9 @@ HERE = Path(__file__).resolve().parent
|
||||
ROOT = HERE.parent.parent
|
||||
|
||||
ICON_SIZE = (64, 64)
|
||||
DESTINATION = ROOT / "core" / "src" / "apps" / "webauthn" / "res"
|
||||
DESTINATION = (
|
||||
ROOT / "core" / "embed" / "rust" / "src" / "ui" / "model_tt" / "res" / "fido"
|
||||
)
|
||||
EXCLUDE = {"icon_webauthn"}
|
||||
|
||||
# insert ../../common/tools to sys.path, so that we can import coin_info
|
||||
|
@ -4,7 +4,8 @@ set -e
|
||||
CWD=`dirname "$0"`
|
||||
RENDER="$CWD/../vendor/trezor-common/tools/cointool.py render"
|
||||
|
||||
FIND_TEMPLATES="find $CWD/../src -name *.mako -not -name _proto*"
|
||||
# Search both in `core/src` and `core/embed`
|
||||
FIND_TEMPLATES="find $CWD/.. -name *.mako -not -name _proto*"
|
||||
|
||||
check_results() {
|
||||
CHECK_FAIL=0
|
||||
|
@ -1667,7 +1667,7 @@
|
||||
"TT_tezos-test_sign_tx.py::test_tezos_smart_contract_delegation": "683a47bb078a50bf08a16446c90fab70a68a3cec8689abca494fd99b31da2ea6",
|
||||
"TT_tezos-test_sign_tx.py::test_tezos_smart_contract_transfer": "295eac0f3667c0af660575fedefa98cae89ec0882892dc8769adf61751dc12fb",
|
||||
"TT_tezos-test_sign_tx.py::test_tezos_smart_contract_transfer_to_contract": "3e781bd83c0019ba51b9034b8bc53c5a09ea9c5c6fe73570004d46a061ba43ea",
|
||||
"TT_webauthn-test_msg_webauthn.py::test_add_remove": "7ac75b93373119b69a38c4bacfa51579d7052abc8b10f74f937a78e9a4afb5d9",
|
||||
"TT_webauthn-test_msg_webauthn.py::test_add_remove": "943e29255d6738cc6824c2565001c05906c2cd032aa2eb09993782564e890a16",
|
||||
"TT_webauthn-test_u2f_counter.py::test_u2f_counter": "c6a8e270ce726c7693e2ff88f9af57c56f2d3d8b1cc9c04b6f1dc71e13fcb88e",
|
||||
"TT_zcash-test_sign_tx.py::test_external_presigned": "8781b601169bd64c90ee4dd9c517af905e2cf5fe10bdb474116d17f3d633e06a",
|
||||
"TT_zcash-test_sign_tx.py::test_one_two": "003f12c0ff194bde070fdeb6c8663bf322efca094e9787b2304231c25938b715",
|
||||
|
Loading…
Reference in New Issue
Block a user