diff --git a/services/root-keys/locales/i18n.json b/services/root-keys/locales/i18n.json index 95da67f21..c2189c3c7 100644 --- a/services/root-keys/locales/i18n.json +++ b/services/root-keys/locales/i18n.json @@ -19,6 +19,11 @@ "zh": "这将初始化根密钥\n需要两个密码\n1.解锁\n2.软件更新", "en-audio": "This will initialize the root keys. We're going to need two passwords, one for device unlock, and one for software updates." }, + "rootkeys.setup_wait": { + "en": "Initializing keys. This may\ntake a couple minutes.\nDo not reset or sleep!", + "zh": "现在正在初始化\n可能还要等一下\n不要重置或睡眠!\n", + "en-audio": "Initializing keys. This may take a while, don't reset or sleep the device." + }, "rootkeys.policy_clear": { "en": "Clear after use", "zh": "使用后删除", diff --git a/services/root-keys/src/api.rs b/services/root-keys/src/api.rs index 5ffdf5c4a..420d86b19 100644 --- a/services/root-keys/src/api.rs +++ b/services/root-keys/src/api.rs @@ -11,10 +11,11 @@ pub(crate) enum Opcode { /// attempt to initialize keys on a brand new system. Does nothing if the keys are already provisioned. UxTryInitKeys, - UxRequestBootPassword, - UxPasswordReturn, - UxPolicyReturn, + UxInitRequestPassword, + UxInitPasswordReturn, UxGutter, // NOP for UX calls that require a destination + UxGetPolicy, + UxPolicyReturn, /// UX opcodes MenuRedraw, MenuKeys, diff --git a/services/root-keys/src/implementation.rs b/services/root-keys/src/implementation.rs index 2d668e724..dabce82cb 100755 --- a/services/root-keys/src/implementation.rs +++ b/services/root-keys/src/implementation.rs @@ -313,9 +313,10 @@ impl RootKeys { } } - pub fn set_ux_password_type(&mut self, cur_type: PasswordType) { - self.cur_password_type = Some(cur_type); + pub fn set_ux_password_type(&mut self, cur_type: Option) { + self.cur_password_type = cur_type; } + pub fn get_ux_password_type(&self) -> Option {self.cur_password_type} pub fn is_initialized(&self) -> bool { let config = self.keyrom.rf(utra::keyrom::DATA_DATA); @@ -343,6 +344,10 @@ impl RootKeys { } } + pub fn do_key_init(&mut self) { + + } + pub fn finish_key_init(&mut self) { let sensitive_slice = self.sensitive_data.as_slice_mut::(); // zeroize the RAM-backed data diff --git a/services/root-keys/src/main.rs b/services/root-keys/src/main.rs index dc2895bfa..d67f12e85 100644 --- a/services/root-keys/src/main.rs +++ b/services/root-keys/src/main.rs @@ -31,11 +31,13 @@ mod implementation { use crate::PasswordType; pub struct RootKeys { + password_type: Option, } impl RootKeys { pub fn new(xns: &xous_names::XousNames) -> RootKeys { RootKeys { + password_type: None, } } pub fn suspend(&self) { @@ -51,10 +53,13 @@ mod implementation { } pub fn try_init_keys(&mut self) { } - pub fn set_ux_password_type(&mut self, _cur_type: PasswordType) { + pub fn set_ux_password_type(&mut self, cur_type: Option) { + self.password_type = cur_type; } pub fn is_initialized(&self) -> bool {false} pub fn setup_key_init(&mut self) {} + pub fn do_key_init(&mut self) {} + pub fn get_ux_password_type(&self) -> Option {self.password_type} } } @@ -124,11 +129,11 @@ fn xmain() -> ! { Opcode::MenuKeys.to_u32().unwrap(), Opcode::MenuDrop.to_u32().unwrap()); - let password_action = TextEntry { + let mut password_action = TextEntry { is_password: true, visibility: TextEntryVisibility::LastChars, action_conn: main_cid, - action_opcode: Opcode::UxPasswordReturn.to_u32().unwrap(), + action_opcode: Opcode::UxInitPasswordReturn.to_u32().unwrap(), action_payload: TextEntryPayload::new(), validator: None, }; @@ -188,18 +193,22 @@ fn xmain() -> ! { Some(ActionType::Notification(dismiss_modal_action)), Some(t!("rootkeys.already_init", xous::LANG)), false, None, true, None); + keys.set_ux_password_type(None); } else { - dismiss_modal_action.set_action_opcode(Opcode::UxRequestBootPassword.to_u32().unwrap()); + dismiss_modal_action.set_action_opcode(Opcode::UxInitRequestPassword.to_u32().unwrap()); rootkeys_modal.modify( Some(ActionType::Notification(dismiss_modal_action)), Some(t!("rootkeys.setup", xous::LANG)), false, None, true, None); + // setup_key_init() prepares the salt and other items necessary to receive a password safely + keys.setup_key_init(); + // request the boot password first + keys.set_ux_password_type(Some(PasswordType::Boot)); } rootkeys_modal.activate(); }), - Some(Opcode::UxRequestBootPassword) => { - keys.setup_key_init(); - keys.set_ux_password_type(PasswordType::Boot); + Some(Opcode::UxInitRequestPassword) => { + password_action.set_action_opcode(Opcode::UxInitPasswordReturn.to_u32().unwrap()); rootkeys_modal.modify( Some(ActionType::TextEntry(password_action)), Some(t!("rootpass.top", xous::LANG)), false, @@ -207,7 +216,10 @@ fn xmain() -> ! { ); rootkeys_modal.activate(); } - Some(Opcode::UxPasswordReturn) => { + Some(Opcode::UxInitPasswordReturn) => { + // assume: + // - setup_key_init has also been called (exactly once, before anything happens) + // - set_ux_password_type has been called already let mut buf = unsafe { Buffer::from_memory_message(msg.body.memory_message().unwrap()) }; let mut plaintext_pw = buf.to_original::().unwrap(); @@ -215,12 +227,33 @@ fn xmain() -> ! { plaintext_pw.volatile_clear(); // ensure the data is destroyed after sending to the keys enclave buf.volatile_clear(); - // always explicitly request a policy decision for rootkeys - policy_menu.activate(); + if let Some(pwt) = keys.get_ux_password_type() { + match pwt { + PasswordType::Boot => { + // now grab the update password + keys.set_ux_password_type(Some(PasswordType::Update)); + send_message(main_cid, + xous::Message::new_scalar(Opcode::UxInitRequestPassword.to_usize().unwrap(), 0, 0, 0, 0)).expect("couldn't initiate dialog box"); + } + PasswordType::Update => { + keys.set_ux_password_type(None); + // now show the init wait note... + dismiss_modal_action.set_action_opcode(Opcode::UxGutter.to_u32().unwrap()); + rootkeys_modal.modify( + Some(ActionType::Notification(dismiss_modal_action)), + Some(t!("rootkeys.setup_wait", xous::LANG)), false, + None, true, None); + rootkeys_modal.activate(); + + xous:: yield_slice(); // give some time to the GAM to render + + keys.do_key_init(); + } + } + } else { + log::error!("invalid UX state -- someone called init password return, but no password type was set!"); + } }, - Some(Opcode::UxPolicyReturn) => msg_scalar_unpack!(msg, policy_code, _, _, _, { - keys.update_policy(FromPrimitive::from_usize(policy_code)); - }), /* Some(Opcode::TestUx) => msg_scalar_unpack!(msg, arg, _, _, _, { log::debug!("activating password modal"); @@ -228,6 +261,12 @@ fn xmain() -> ! { rootkeys_modal.activate(); //policy_menu.activate(); }),*/ + Some(Opcode::UxGetPolicy) => { + policy_menu.activate(); + } + Some(Opcode::UxPolicyReturn) => msg_scalar_unpack!(msg, policy_code, _, _, _, { + keys.update_policy(FromPrimitive::from_usize(policy_code)); + }), Some(Opcode::UxGutter) => { // an intentional NOP for UX actions that require a destintation but need no action },