mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-12 00:10:58 +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/reset.py'))
|
||||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/recovery.py'))
|
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/recovery.py'))
|
||||||
if EVERYTHING:
|
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',):
|
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/__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/reset.py'))
|
||||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/recovery.py'))
|
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/recovery.py'))
|
||||||
if EVERYTHING:
|
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',):
|
elif TREZOR_MODEL in ('1',):
|
||||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/t1.py'))
|
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/t1.py'))
|
||||||
elif TREZOR_MODEL in ('R',):
|
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/reset.py'))
|
||||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/recovery.py'))
|
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/recovery.py'))
|
||||||
if EVERYTHING:
|
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',):
|
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/__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/reset.py'))
|
||||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/recovery.py'))
|
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/recovery.py'))
|
||||||
if EVERYTHING:
|
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',):
|
elif TREZOR_MODEL in ('1',):
|
||||||
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/t1.py'))
|
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/t1.py'))
|
||||||
elif TREZOR_MODEL in ('R',):
|
elif TREZOR_MODEL in ('R',):
|
||||||
|
@ -20,6 +20,7 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_confirm_blob;
|
MP_QSTR_confirm_blob;
|
||||||
MP_QSTR_confirm_properties;
|
MP_QSTR_confirm_properties;
|
||||||
MP_QSTR_confirm_coinjoin;
|
MP_QSTR_confirm_coinjoin;
|
||||||
|
MP_QSTR_confirm_fido;
|
||||||
MP_QSTR_confirm_joint_total;
|
MP_QSTR_confirm_joint_total;
|
||||||
MP_QSTR_confirm_modify_fee;
|
MP_QSTR_confirm_modify_fee;
|
||||||
MP_QSTR_confirm_modify_output;
|
MP_QSTR_confirm_modify_output;
|
||||||
@ -91,4 +92,7 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_active;
|
MP_QSTR_active;
|
||||||
MP_QSTR_info_button;
|
MP_QSTR_info_button;
|
||||||
MP_QSTR_time_ms;
|
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 button;
|
||||||
mod dialog;
|
mod dialog;
|
||||||
|
mod fido;
|
||||||
|
mod fido_icons;
|
||||||
mod frame;
|
mod frame;
|
||||||
mod hold_to_confirm;
|
mod hold_to_confirm;
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
@ -14,6 +16,7 @@ pub use button::{
|
|||||||
CancelInfoConfirmMsg, SelectWordMsg,
|
CancelInfoConfirmMsg, SelectWordMsg,
|
||||||
};
|
};
|
||||||
pub use dialog::{Dialog, DialogMsg, IconDialog};
|
pub use dialog::{Dialog, DialogMsg, IconDialog};
|
||||||
|
pub use fido::{FidoConfirm, FidoMsg};
|
||||||
pub use frame::{Frame, NotificationFrame};
|
pub use frame::{Frame, NotificationFrame};
|
||||||
pub use hold_to_confirm::{HoldToConfirm, HoldToConfirmMsg};
|
pub use hold_to_confirm::{HoldToConfirm, HoldToConfirmMsg};
|
||||||
pub use keyboard::{
|
pub use keyboard::{
|
||||||
|
@ -6,7 +6,9 @@ use crate::{
|
|||||||
error::Error,
|
error::Error,
|
||||||
micropython::{
|
micropython::{
|
||||||
buffer::StrBuffer,
|
buffer::StrBuffer,
|
||||||
|
gc::Gc,
|
||||||
iter::{Iter, IterBuf},
|
iter::{Iter, IterBuf},
|
||||||
|
list::List,
|
||||||
map::Map,
|
map::Map,
|
||||||
module::Module,
|
module::Module,
|
||||||
obj::Obj,
|
obj::Obj,
|
||||||
@ -37,11 +39,11 @@ use crate::{
|
|||||||
use super::{
|
use super::{
|
||||||
component::{
|
component::{
|
||||||
Bip39Input, Button, ButtonMsg, ButtonStyleSheet, CancelConfirmMsg, CancelInfoConfirmMsg,
|
Bip39Input, Button, ButtonMsg, ButtonStyleSheet, CancelConfirmMsg, CancelInfoConfirmMsg,
|
||||||
Dialog, DialogMsg, Frame, HoldToConfirm, HoldToConfirmMsg, IconDialog, MnemonicInput,
|
Dialog, DialogMsg, FidoConfirm, FidoMsg, Frame, HoldToConfirm, HoldToConfirmMsg,
|
||||||
MnemonicKeyboard, MnemonicKeyboardMsg, NotificationFrame, NumberInputDialog,
|
IconDialog, MnemonicInput, MnemonicKeyboard, MnemonicKeyboardMsg, NotificationFrame,
|
||||||
NumberInputDialogMsg, PassphraseKeyboard, PassphraseKeyboardMsg, PinKeyboard,
|
NumberInputDialog, NumberInputDialogMsg, PassphraseKeyboard, PassphraseKeyboardMsg,
|
||||||
PinKeyboardMsg, SelectWordCount, SelectWordCountMsg, SelectWordMsg, Slip39Input,
|
PinKeyboard, PinKeyboardMsg, SelectWordCount, SelectWordCountMsg, SelectWordMsg,
|
||||||
SwipeHoldPage, SwipePage,
|
Slip39Input, SwipeHoldPage, SwipePage,
|
||||||
},
|
},
|
||||||
theme,
|
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>
|
impl<T, U> ComponentMsgObj for Dialog<T, U>
|
||||||
where
|
where
|
||||||
T: ComponentMsgObj,
|
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) }
|
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 {
|
extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||||
let icon = BlendedImage::new(
|
let icon = BlendedImage::new(
|
||||||
@ -1172,6 +1219,19 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// """Decrease or increase transaction fee."""
|
/// """Decrease or increase transaction fee."""
|
||||||
Qstr::MP_QSTR_confirm_modify_fee => obj_fn_kw!(0, new_confirm_modify_fee).as_obj(),
|
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(
|
/// def show_error(
|
||||||
/// *,
|
/// *,
|
||||||
/// title: str,
|
/// 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."""
|
"""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
|
# rust/src/ui/model_tt/layout.rs
|
||||||
def show_error(
|
def show_error(
|
||||||
*,
|
*,
|
||||||
|
@ -155,6 +155,8 @@ trezor.ui.layouts
|
|||||||
import trezor.ui.layouts
|
import trezor.ui.layouts
|
||||||
trezor.ui.layouts.common
|
trezor.ui.layouts.common
|
||||||
import trezor.ui.layouts.common
|
import trezor.ui.layouts.common
|
||||||
|
trezor.ui.layouts.fido
|
||||||
|
import trezor.ui.layouts.fido
|
||||||
trezor.ui.layouts.recovery
|
trezor.ui.layouts.recovery
|
||||||
import trezor.ui.layouts.recovery
|
import trezor.ui.layouts.recovery
|
||||||
trezor.ui.layouts.reset
|
trezor.ui.layouts.reset
|
||||||
@ -165,6 +167,8 @@ trezor.ui.layouts.tr
|
|||||||
import trezor.ui.layouts.tr
|
import trezor.ui.layouts.tr
|
||||||
trezor.ui.layouts.tt_v2
|
trezor.ui.layouts.tt_v2
|
||||||
import 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
|
trezor.ui.layouts.tt_v2.recovery
|
||||||
import trezor.ui.layouts.tt_v2.recovery
|
import trezor.ui.layouts.tt_v2.recovery
|
||||||
trezor.ui.layouts.tt_v2.reset
|
trezor.ui.layouts.tt_v2.reset
|
||||||
@ -405,12 +409,6 @@ if not utils.BITCOIN_ONLY:
|
|||||||
import trezor.enums.TezosBallotType
|
import trezor.enums.TezosBallotType
|
||||||
trezor.enums.TezosContractType
|
trezor.enums.TezosContractType
|
||||||
import 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
|
apps.binance
|
||||||
import apps.binance
|
import apps.binance
|
||||||
apps.binance.get_address
|
apps.binance.get_address
|
||||||
|
@ -1,27 +1,8 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from trezor.ui.components.common.webauthn import ConfirmInfo
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from trezor.messages import WebAuthnAddResidentCredential, Success
|
from trezor.messages import WebAuthnAddResidentCredential, Success
|
||||||
from trezor.wire import Context
|
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(
|
async def add_resident_credential(
|
||||||
@ -30,7 +11,7 @@ async def add_resident_credential(
|
|||||||
import storage.device as storage_device
|
import storage.device as storage_device
|
||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.ui.layouts import show_error_and_raise
|
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 trezor.messages import Success
|
||||||
from .credential import Fido2Credential
|
from .credential import Fido2Credential
|
||||||
from .resident_credentials import store_resident_credential
|
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.",
|
"The credential you are trying to import does\nnot belong to this authenticator.",
|
||||||
)
|
)
|
||||||
|
|
||||||
if not await confirm_webauthn(ctx, ConfirmAddCredential(cred)):
|
await confirm_fido(
|
||||||
raise wire.ActionCancelled
|
ctx,
|
||||||
|
"Import credential",
|
||||||
|
cred.app_name(),
|
||||||
|
cred.icon_name(),
|
||||||
|
[cred.account_name()],
|
||||||
|
)
|
||||||
|
|
||||||
if store_resident_credential(cred):
|
if store_resident_credential(cred):
|
||||||
return Success(message="Credential added")
|
return Success(message="Credential added")
|
||||||
|
@ -71,6 +71,12 @@ class Credential:
|
|||||||
def app_name(self) -> str:
|
def app_name(self) -> str:
|
||||||
raise NotImplementedError
|
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:
|
def account_name(self) -> str | None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -5,13 +5,10 @@ from micropython import const
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import storage.device as storage_device
|
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 import hashlib
|
||||||
from trezor.crypto.curve import nist256p1
|
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 import show_popup
|
||||||
from trezor.ui.layouts.webauthn import confirm_webauthn
|
|
||||||
|
|
||||||
from apps.base import set_homescreen
|
from apps.base import set_homescreen
|
||||||
from apps.common import cbor
|
from apps.common import cbor
|
||||||
@ -20,7 +17,7 @@ from . import common
|
|||||||
from .credential import Credential, Fido2Credential
|
from .credential import Credential, Fido2Credential
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Callable, Coroutine, Iterable, Iterator
|
from typing import Any, Awaitable, Callable, Coroutine, Iterable, Iterator
|
||||||
from .credential import U2fCredential
|
from .credential import U2fCredential
|
||||||
|
|
||||||
HID = io.HID
|
HID = io.HID
|
||||||
@ -587,6 +584,33 @@ async def verify_user(keepalive_callback: KeepaliveCallback) -> bool:
|
|||||||
return ret
|
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:
|
class State:
|
||||||
def __init__(self, cid: int, iface: HID) -> None:
|
def __init__(self, cid: int, iface: HID) -> None:
|
||||||
self.cid = cid
|
self.cid = cid
|
||||||
@ -616,13 +640,11 @@ class State:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class U2fState(State, ConfirmInfo):
|
class U2fState(State):
|
||||||
def __init__(self, cid: int, iface: HID, req_data: bytes, cred: Credential) -> None:
|
def __init__(self, cid: int, iface: HID, req_data: bytes, cred: Credential) -> None:
|
||||||
State.__init__(self, cid, iface)
|
State.__init__(self, cid, iface)
|
||||||
ConfirmInfo.__init__(self)
|
|
||||||
self._cred = cred
|
self._cred = cred
|
||||||
self._req_data = req_data
|
self._req_data = req_data
|
||||||
self.load_icon(self._cred.rp_id_hash)
|
|
||||||
|
|
||||||
def timeout_ms(self) -> int:
|
def timeout_ms(self) -> int:
|
||||||
return _U2F_CONFIRM_TIMEOUT_MS
|
return _U2F_CONFIRM_TIMEOUT_MS
|
||||||
@ -658,10 +680,7 @@ class U2fConfirmRegister(U2fState):
|
|||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return await confirm_webauthn(None, self)
|
return await _confirm_fido("U2F Register", self._cred)
|
||||||
|
|
||||||
def get_header(self) -> str:
|
|
||||||
return "U2F Register"
|
|
||||||
|
|
||||||
def __eq__(self, other: object) -> bool:
|
def __eq__(self, other: object) -> bool:
|
||||||
return (
|
return (
|
||||||
@ -675,11 +694,8 @@ class U2fConfirmAuthenticate(U2fState):
|
|||||||
def __init__(self, cid: int, iface: HID, req_data: bytes, cred: Credential) -> None:
|
def __init__(self, cid: int, iface: HID, req_data: bytes, cred: Credential) -> None:
|
||||||
super().__init__(cid, iface, req_data, cred)
|
super().__init__(cid, iface, req_data, cred)
|
||||||
|
|
||||||
def get_header(self) -> str:
|
|
||||||
return "U2F Authenticate"
|
|
||||||
|
|
||||||
async def confirm_dialog(self) -> bool:
|
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:
|
def __eq__(self, other: object) -> bool:
|
||||||
return (
|
return (
|
||||||
@ -767,7 +783,7 @@ class Fido2Unlock(Fido2State):
|
|||||||
await send_cmd(self.resp, self.iface)
|
await send_cmd(self.resp, self.iface)
|
||||||
|
|
||||||
|
|
||||||
class Fido2ConfirmMakeCredential(Fido2State, ConfirmInfo):
|
class Fido2ConfirmMakeCredential(Fido2State):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
cid: int,
|
cid: int,
|
||||||
@ -778,24 +794,13 @@ class Fido2ConfirmMakeCredential(Fido2State, ConfirmInfo):
|
|||||||
user_verification: bool,
|
user_verification: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
Fido2State.__init__(self, cid, iface)
|
Fido2State.__init__(self, cid, iface)
|
||||||
ConfirmInfo.__init__(self)
|
|
||||||
self._client_data_hash = client_data_hash
|
self._client_data_hash = client_data_hash
|
||||||
self._cred = cred
|
self._cred = cred
|
||||||
self._resident = resident
|
self._resident = resident
|
||||||
self._user_verification = user_verification
|
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:
|
async def confirm_dialog(self) -> bool:
|
||||||
if not await confirm_webauthn(None, self):
|
if not await _confirm_fido("FIDO2 Register", self._cred):
|
||||||
return False
|
return False
|
||||||
if self._user_verification:
|
if self._user_verification:
|
||||||
return await verify_user(KeepaliveCallback(self.cid, self.iface))
|
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__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
cid: int,
|
cid: int,
|
||||||
@ -851,30 +856,21 @@ class Fido2ConfirmGetAssertion(Fido2State, ConfirmInfo, Pageable):
|
|||||||
user_verification: bool,
|
user_verification: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
Fido2State.__init__(self, cid, iface)
|
Fido2State.__init__(self, cid, iface)
|
||||||
ConfirmInfo.__init__(self)
|
|
||||||
Pageable.__init__(self)
|
|
||||||
self._client_data_hash = client_data_hash
|
self._client_data_hash = client_data_hash
|
||||||
self._creds = creds
|
self._creds = creds
|
||||||
self._hmac_secret = hmac_secret
|
self._hmac_secret = hmac_secret
|
||||||
self._resident = resident
|
self._resident = resident
|
||||||
self._user_verification = user_verification
|
self._user_verification = user_verification
|
||||||
self.load_icon(self._creds[0].rp_id_hash)
|
self._selected_cred: Credential | None = None
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
async def confirm_dialog(self) -> bool:
|
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
|
return False
|
||||||
|
|
||||||
|
self._selected_cred = self._creds[index]
|
||||||
if self._user_verification:
|
if self._user_verification:
|
||||||
return await verify_user(KeepaliveCallback(self.cid, self.iface))
|
return await verify_user(KeepaliveCallback(self.cid, self.iface))
|
||||||
return True
|
return True
|
||||||
@ -882,13 +878,13 @@ class Fido2ConfirmGetAssertion(Fido2State, ConfirmInfo, Pageable):
|
|||||||
async def on_confirm(self) -> None:
|
async def on_confirm(self) -> None:
|
||||||
cid = self.cid # local_cache_attribute
|
cid = self.cid # local_cache_attribute
|
||||||
|
|
||||||
cred = self._creds[self.page()]
|
assert self._selected_cred is not None
|
||||||
try:
|
try:
|
||||||
send_cmd_sync(cmd_keepalive(cid, _KEEPALIVE_STATUS_PROCESSING), self.iface)
|
send_cmd_sync(cmd_keepalive(cid, _KEEPALIVE_STATUS_PROCESSING), self.iface)
|
||||||
response_data = cbor_get_assertion_sign(
|
response_data = cbor_get_assertion_sign(
|
||||||
self._client_data_hash,
|
self._client_data_hash,
|
||||||
cred.rp_id_hash,
|
self._selected_cred.rp_id_hash,
|
||||||
cred,
|
self._selected_cred,
|
||||||
self._hmac_secret,
|
self._hmac_secret,
|
||||||
self._resident,
|
self._resident,
|
||||||
True,
|
True,
|
||||||
@ -954,9 +950,9 @@ class Fido2ConfirmReset(Fido2State):
|
|||||||
super().__init__(cid, iface)
|
super().__init__(cid, iface)
|
||||||
|
|
||||||
async def confirm_dialog(self) -> bool:
|
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:
|
async def on_confirm(self) -> None:
|
||||||
import storage.resident_credentials
|
import storage.resident_credentials
|
||||||
|
@ -9,12 +9,12 @@ class FIDOApp:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
label: str,
|
label: str,
|
||||||
icon: str | None,
|
icon_name: str | None,
|
||||||
use_sign_count: bool | None,
|
use_sign_count: bool | None,
|
||||||
use_self_attestation: bool | None,
|
use_self_attestation: bool | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.label = label
|
self.label = label
|
||||||
self.icon = icon
|
self.icon_name = icon_name
|
||||||
self.use_sign_count = use_sign_count
|
self.use_sign_count = use_sign_count
|
||||||
self.use_self_attestation = use_self_attestation
|
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
|
# U2F key for Amazon Web Services
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"aws.amazon.com", # label
|
"aws.amazon.com", # label
|
||||||
"apps/webauthn/res/icon_aws.toif", # icon
|
"aws", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -33,7 +33,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Binance
|
# WebAuthn key for Binance
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"www.binance.com", # label
|
"www.binance.com", # label
|
||||||
"apps/webauthn/res/icon_binance.toif", # icon
|
"binance", # icon_name
|
||||||
False, # use_sign_count
|
False, # use_sign_count
|
||||||
True, # use_self_attestation
|
True, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -41,7 +41,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Binance
|
# WebAuthn key for Binance
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"binance.com", # label
|
"binance.com", # label
|
||||||
"apps/webauthn/res/icon_binance.toif", # icon
|
"binance", # icon_name
|
||||||
False, # use_sign_count
|
False, # use_sign_count
|
||||||
True, # use_self_attestation
|
True, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -49,7 +49,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Bitbucket
|
# U2F key for Bitbucket
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"bitbucket.org", # label
|
"bitbucket.org", # label
|
||||||
"apps/webauthn/res/icon_bitbucket.toif", # icon
|
"bitbucket", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -57,7 +57,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Bitfinex
|
# U2F key for Bitfinex
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"www.bitfinex.com", # label
|
"www.bitfinex.com", # label
|
||||||
"apps/webauthn/res/icon_bitfinex.toif", # icon
|
"bitfinex", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -65,7 +65,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Bitwarden
|
# U2F key for Bitwarden
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"vault.bitwarden.com", # label
|
"vault.bitwarden.com", # label
|
||||||
"apps/webauthn/res/icon_bitwarden.toif", # icon
|
"bitwarden", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -73,7 +73,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Cloudflare
|
# WebAuthn key for Cloudflare
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"dash.cloudflare.com", # label
|
"dash.cloudflare.com", # label
|
||||||
"apps/webauthn/res/icon_cloudflare.toif", # icon
|
"cloudflare", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -81,7 +81,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Coinbase
|
# WebAuthn key for Coinbase
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"coinbase.com", # label
|
"coinbase.com", # label
|
||||||
"apps/webauthn/res/icon_coinbase.toif", # icon
|
"coinbase", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -89,7 +89,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Dashlane
|
# U2F key for Dashlane
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"www.dashlane.com", # label
|
"www.dashlane.com", # label
|
||||||
"apps/webauthn/res/icon_dashlane.toif", # icon
|
"dashlane", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -97,7 +97,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Dropbox
|
# U2F key for Dropbox
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"www.dropbox.com", # label
|
"www.dropbox.com", # label
|
||||||
"apps/webauthn/res/icon_dropbox.toif", # icon
|
"dropbox", # icon_name
|
||||||
False, # use_sign_count
|
False, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -105,7 +105,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Dropbox
|
# WebAuthn key for Dropbox
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"www.dropbox.com", # label
|
"www.dropbox.com", # label
|
||||||
"apps/webauthn/res/icon_dropbox.toif", # icon
|
"dropbox", # icon_name
|
||||||
False, # use_sign_count
|
False, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -113,7 +113,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Duo
|
# U2F key for Duo
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"duosecurity.com", # label
|
"duosecurity.com", # label
|
||||||
"apps/webauthn/res/icon_duo.toif", # icon
|
"duo", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -121,7 +121,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Facebook
|
# WebAuthn key for Facebook
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"facebook.com", # label
|
"facebook.com", # label
|
||||||
"apps/webauthn/res/icon_facebook.toif", # icon
|
"facebook", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -129,7 +129,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for FastMail
|
# U2F key for FastMail
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"www.fastmail.com", # label
|
"www.fastmail.com", # label
|
||||||
"apps/webauthn/res/icon_fastmail.toif", # icon
|
"fastmail", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -137,7 +137,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for FastMail
|
# WebAuthn key for FastMail
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"fastmail.com", # label
|
"fastmail.com", # label
|
||||||
"apps/webauthn/res/icon_fastmail.toif", # icon
|
"fastmail", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -145,7 +145,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Fedora
|
# U2F key for Fedora
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"fedoraproject.org", # label
|
"fedoraproject.org", # label
|
||||||
"apps/webauthn/res/icon_fedora.toif", # icon
|
"fedora", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -153,7 +153,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Gandi
|
# U2F key for Gandi
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"gandi.net", # label
|
"gandi.net", # label
|
||||||
"apps/webauthn/res/icon_gandi.toif", # icon
|
"gandi", # icon_name
|
||||||
False, # use_sign_count
|
False, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -161,7 +161,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Gandi
|
# WebAuthn key for Gandi
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"gandi.net", # label
|
"gandi.net", # label
|
||||||
"apps/webauthn/res/icon_gandi.toif", # icon
|
"gandi", # icon_name
|
||||||
False, # use_sign_count
|
False, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -169,7 +169,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Gemini
|
# WebAuthn key for Gemini
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"gemini.com", # label
|
"gemini.com", # label
|
||||||
"apps/webauthn/res/icon_gemini.toif", # icon
|
"gemini", # icon_name
|
||||||
False, # use_sign_count
|
False, # use_sign_count
|
||||||
True, # use_self_attestation
|
True, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -177,7 +177,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for GitHub
|
# U2F key for GitHub
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"github.com", # label
|
"github.com", # label
|
||||||
"apps/webauthn/res/icon_github.toif", # icon
|
"github", # icon_name
|
||||||
True, # use_sign_count
|
True, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -185,7 +185,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for GitHub
|
# WebAuthn key for GitHub
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"github.com", # label
|
"github.com", # label
|
||||||
"apps/webauthn/res/icon_github.toif", # icon
|
"github", # icon_name
|
||||||
True, # use_sign_count
|
True, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -193,7 +193,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for GitLab
|
# U2F key for GitLab
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"gitlab.com", # label
|
"gitlab.com", # label
|
||||||
"apps/webauthn/res/icon_gitlab.toif", # icon
|
"gitlab", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -201,7 +201,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Google
|
# U2F key for Google
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"google.com", # label
|
"google.com", # label
|
||||||
"apps/webauthn/res/icon_google.toif", # icon
|
"google", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -209,7 +209,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Google
|
# WebAuthn key for Google
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"google.com", # label
|
"google.com", # label
|
||||||
"apps/webauthn/res/icon_google.toif", # icon
|
"google", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -217,7 +217,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Invity
|
# WebAuthn key for Invity
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"invity.io", # label
|
"invity.io", # label
|
||||||
"apps/webauthn/res/icon_invity.toif", # icon
|
"invity", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -225,7 +225,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Keeper
|
# U2F key for Keeper
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"keepersecurity.com", # label
|
"keepersecurity.com", # label
|
||||||
"apps/webauthn/res/icon_keeper.toif", # icon
|
"keeper", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -233,7 +233,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Keeper
|
# U2F key for Keeper
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"keepersecurity.eu", # label
|
"keepersecurity.eu", # label
|
||||||
"apps/webauthn/res/icon_keeper.toif", # icon
|
"keeper", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -241,7 +241,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Kraken
|
# WebAuthn key for Kraken
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"kraken.com", # label
|
"kraken.com", # label
|
||||||
"apps/webauthn/res/icon_kraken.toif", # icon
|
"kraken", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -249,7 +249,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for login.gov
|
# WebAuthn key for login.gov
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"secure.login.gov", # label
|
"secure.login.gov", # label
|
||||||
"apps/webauthn/res/icon_login.gov.toif", # icon
|
"login.gov", # icon_name
|
||||||
False, # use_sign_count
|
False, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -257,7 +257,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Microsoft
|
# WebAuthn key for Microsoft
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"login.microsoft.com", # label
|
"login.microsoft.com", # label
|
||||||
"apps/webauthn/res/icon_microsoft.toif", # icon
|
"microsoft", # icon_name
|
||||||
False, # use_sign_count
|
False, # use_sign_count
|
||||||
False, # use_self_attestation
|
False, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -265,7 +265,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for mojeID
|
# WebAuthn key for mojeID
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"mojeid.cz", # label
|
"mojeid.cz", # label
|
||||||
"apps/webauthn/res/icon_mojeid.toif", # icon
|
"mojeid", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -273,7 +273,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Namecheap
|
# WebAuthn key for Namecheap
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"www.namecheap.com", # label
|
"www.namecheap.com", # label
|
||||||
"apps/webauthn/res/icon_namecheap.toif", # icon
|
"namecheap", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -281,7 +281,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for Proton
|
# WebAuthn key for Proton
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"proton.me", # label
|
"proton.me", # label
|
||||||
"apps/webauthn/res/icon_proton.toif", # icon
|
"proton", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -289,7 +289,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Slush Pool
|
# U2F key for Slush Pool
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"slushpool.com", # label
|
"slushpool.com", # label
|
||||||
"apps/webauthn/res/icon_slushpool.toif", # icon
|
"slushpool", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -297,7 +297,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Slush Pool
|
# U2F key for Slush Pool
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"slushpool.com", # label
|
"slushpool.com", # label
|
||||||
"apps/webauthn/res/icon_slushpool.toif", # icon
|
"slushpool", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -305,7 +305,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Stripe
|
# U2F key for Stripe
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"stripe.com", # label
|
"stripe.com", # label
|
||||||
"apps/webauthn/res/icon_stripe.toif", # icon
|
"stripe", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -313,7 +313,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# U2F key for Tutanota
|
# U2F key for Tutanota
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"tutanota.com", # label
|
"tutanota.com", # label
|
||||||
"apps/webauthn/res/icon_tutanota.toif", # icon
|
"tutanota", # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
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
|
# U2F key for u2f.bin.coffee
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"u2f.bin.coffee", # label
|
"u2f.bin.coffee", # label
|
||||||
None, # icon
|
None, # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
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
|
# WebAuthn key for webauthn.bin.coffee
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"webauthn.bin.coffee", # label
|
"webauthn.bin.coffee", # label
|
||||||
None, # icon
|
None, # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -337,7 +337,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for WebAuthn.io
|
# WebAuthn key for WebAuthn.io
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"webauthn.io", # label
|
"webauthn.io", # label
|
||||||
None, # icon
|
None, # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
@ -345,7 +345,7 @@ def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
|||||||
# WebAuthn key for WebAuthn.me
|
# WebAuthn key for WebAuthn.me
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"webauthn.me", # label
|
"webauthn.me", # label
|
||||||
None, # icon
|
None, # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
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
|
# WebAuthn key for demo.yubico.com
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
"demo.yubico.com", # label
|
"demo.yubico.com", # label
|
||||||
None, # icon
|
None, # icon_name
|
||||||
None, # use_sign_count
|
None, # use_sign_count
|
||||||
None, # use_self_attestation
|
None, # use_self_attestation
|
||||||
)
|
)
|
||||||
|
@ -9,12 +9,12 @@ class FIDOApp:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
label: str,
|
label: str,
|
||||||
icon: str | None,
|
icon_name: str | None,
|
||||||
use_sign_count: bool | None,
|
use_sign_count: bool | None,
|
||||||
use_self_attestation: bool | None,
|
use_self_attestation: bool | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.label = label
|
self.label = label
|
||||||
self.icon = icon
|
self.icon_name = icon_name
|
||||||
self.use_sign_count = use_sign_count
|
self.use_sign_count = use_sign_count
|
||||||
self.use_self_attestation = use_self_attestation
|
self.use_self_attestation = use_self_attestation
|
||||||
|
|
||||||
@ -30,9 +30,9 @@ for app in fido:
|
|||||||
rp_id_hash = sha256(origin.encode()).digest()
|
rp_id_hash = sha256(origin.encode()).digest()
|
||||||
fido_entries.append((origin, rp_id_hash, "WebAuthn", app))
|
fido_entries.append((origin, rp_id_hash, "WebAuthn", app))
|
||||||
if app.icon is not None:
|
if app.icon is not None:
|
||||||
app.icon_res = f"apps/webauthn/res/icon_{app.key}.toif"
|
app.icon_name = app.key
|
||||||
else:
|
else:
|
||||||
app.icon_res = None
|
app.icon_name = None
|
||||||
%>\
|
%>\
|
||||||
# fmt: off
|
# fmt: off
|
||||||
def by_rp_id_hash(rp_id_hash: bytes) -> FIDOApp | None:
|
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}
|
# ${type} key for ${app.name}
|
||||||
return FIDOApp(
|
return FIDOApp(
|
||||||
${black_repr(label)}, # label
|
${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_sign_count)}, # use_sign_count
|
||||||
${black_repr(app.use_self_attestation)}, # use_self_attestation
|
${black_repr(app.use_self_attestation)}, # use_self_attestation
|
||||||
)
|
)
|
||||||
|
@ -1,29 +1,10 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from trezor.ui.components.common.webauthn import ConfirmInfo
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from trezor.messages import WebAuthnRemoveResidentCredential, Success
|
from trezor.messages import WebAuthnRemoveResidentCredential, Success
|
||||||
from .credential import Fido2Credential
|
|
||||||
from trezor.wire import Context
|
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(
|
async def remove_resident_credential(
|
||||||
ctx: Context, msg: WebAuthnRemoveResidentCredential
|
ctx: Context, msg: WebAuthnRemoveResidentCredential
|
||||||
) -> Success:
|
) -> Success:
|
||||||
@ -31,7 +12,7 @@ async def remove_resident_credential(
|
|||||||
import storage.resident_credentials
|
import storage.resident_credentials
|
||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages import Success
|
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
|
from .resident_credentials import get_resident_credential
|
||||||
|
|
||||||
if not storage.device.is_initialized():
|
if not storage.device.is_initialized():
|
||||||
@ -43,8 +24,13 @@ async def remove_resident_credential(
|
|||||||
if cred is None:
|
if cred is None:
|
||||||
raise wire.ProcessError("Invalid credential index.")
|
raise wire.ProcessError("Invalid credential index.")
|
||||||
|
|
||||||
if not await confirm_webauthn(ctx, ConfirmRemoveCredential(cred)):
|
await confirm_fido(
|
||||||
raise wire.ActionCancelled
|
ctx,
|
||||||
|
"Remove credential",
|
||||||
|
cred.app_name(),
|
||||||
|
cred.icon_name(),
|
||||||
|
[cred.account_name()],
|
||||||
|
)
|
||||||
|
|
||||||
assert cred.index is not None
|
assert cred.index is not None
|
||||||
storage.resident_credentials.delete(cred.index)
|
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
|
ROOT = HERE.parent.parent
|
||||||
|
|
||||||
ICON_SIZE = (64, 64)
|
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"}
|
EXCLUDE = {"icon_webauthn"}
|
||||||
|
|
||||||
# insert ../../common/tools to sys.path, so that we can import coin_info
|
# insert ../../common/tools to sys.path, so that we can import coin_info
|
||||||
|
@ -4,7 +4,8 @@ set -e
|
|||||||
CWD=`dirname "$0"`
|
CWD=`dirname "$0"`
|
||||||
RENDER="$CWD/../vendor/trezor-common/tools/cointool.py render"
|
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_results() {
|
||||||
CHECK_FAIL=0
|
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_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": "295eac0f3667c0af660575fedefa98cae89ec0882892dc8769adf61751dc12fb",
|
||||||
"TT_tezos-test_sign_tx.py::test_tezos_smart_contract_transfer_to_contract": "3e781bd83c0019ba51b9034b8bc53c5a09ea9c5c6fe73570004d46a061ba43ea",
|
"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_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_external_presigned": "8781b601169bd64c90ee4dd9c517af905e2cf5fe10bdb474116d17f3d633e06a",
|
||||||
"TT_zcash-test_sign_tx.py::test_one_two": "003f12c0ff194bde070fdeb6c8663bf322efca094e9787b2304231c25938b715",
|
"TT_zcash-test_sign_tx.py::test_one_two": "003f12c0ff194bde070fdeb6c8663bf322efca094e9787b2304231c25938b715",
|
||||||
|
Loading…
Reference in New Issue
Block a user