enable gateware updates when no root keys are present

This commit is contained in:
bunnie 2022-06-30 22:58:54 +08:00
parent 3aeec85e06
commit ead5bd7dac
6 changed files with 115 additions and 0 deletions

View file

@ -11,6 +11,18 @@
"zh": "输入密码 软件更新 安全含义:至关重要 ",
"en-tts": "Enter update password. This password is critically important."
},
"rootkeys.blind_update": {
"en": "No root keys detected. Shall we copy the staged gateware anyways, overwriting the current image?",
"ja": "ルートキーが検出されませんでした。 とにかくステージングされたゲートウェアをコピーして、現在のイメージを上書きしませんか?",
"zh": "未检测到根密钥。 我们是否要复制暂存的网关软件,覆盖当前映像?",
"en-tts": "No root keys detected. Shall we copy the staged gateware anyways, overwriting the current image?"
},
"rootkeys.wrong_state": {
"en": "System in an unexpected state. Aborting.",
"ja": "予期しない状態のシステム。 中止します。",
"zh": "系统处于意外状态。 中止。",
"en-tts": "System in an unexpected state. Aborting."
},
"rootkeys.already_init": {
"en": "Root keys already initialized.",
"ja": "ルートキーはすでに初期化されています。",

View file

@ -67,6 +67,10 @@ pub(crate) enum Opcode {
SuspendResume = 32,
Quit = 33,
/// makes a "blind copy" of the staged gateware. This will destroy root keys,
/// but the call will not succeed if the image was provisioned.
UxBlindCopy = 34,
}
#[derive(Debug, num_derive::FromPrimitive, num_derive::ToPrimitive, PartialEq, Eq)]
@ -93,6 +97,8 @@ pub enum RootkeyResult {
KeyError = 1,
IntegrityError = 2,
FlashError = 3,
/// enclave is in the wrong state to do the requested operation
StateError = 4,
}
/// AES operation definitions

View file

@ -1527,6 +1527,32 @@ impl<'a> RootKeys {
Ok(())
}
/// blind-copy a staged gateware to the boot location. This can only be done if not root keys
/// have been initialized. This routine exists just to make the UX flow consistent between
/// unprovisioned and provisioned devices.
pub(crate) fn do_gateware_provision_uninitialized(&mut self, rootkeys_modal: &mut Modal, main_cid: xous::CID) -> Result<(), RootkeyResult> {
if self.is_initialized() {
return Err(RootkeyResult::StateError);
}
let mut progress_action = Slider::new(main_cid, Opcode::UxGutter.to_u32().unwrap(),
0, 100, 10, Some("%"), 0, true, true
);
progress_action.set_is_password(true);
rootkeys_modal.modify(
Some(ActionType::Slider(progress_action)),
Some(t!("rootkeys.gwup_starting", xous::LANG)), false,
None, true, None);
rootkeys_modal.activate();
xous::yield_slice(); // give some time to the GAM to render
let mut pb = ProgressBar::new(rootkeys_modal, &mut progress_action);
pb.set_percentage(1);
self.ticktimer.sleep_ms(250).expect("couldn't show final message");
self.make_gateware_backup(Some(&mut pb), true)?;
pb.set_percentage(100);
self.ticktimer.sleep_ms(250).expect("couldn't show final message");
Ok(())
}
/// copy data from a source region to a destination region, re-encrypting and patching as we go along.
/// the region/region_base should be specified for the destination oracle
///

View file

@ -51,6 +51,9 @@ impl RootKeys {
pub fn get_update_gateware_op(&self) -> u32 {
Opcode::UxUpdateGateware.to_u32().unwrap()
}
pub fn get_blind_copy_gateware_op(&self) -> u32 {
Opcode::UxBlindCopy.to_u32().unwrap()
}
pub fn get_try_selfsign_op(&self) -> u32 {
Opcode::UxSelfSignXous.to_u32().unwrap()
}

View file

@ -591,6 +591,9 @@ fn main() -> ! {
Err(RootkeyResult::FlashError) => {
modals.show_notification(t!("rootkeys.init.fail_burn", xous::LANG), None).expect("modals error");
}
Err(RootkeyResult::StateError) => {
modals.show_notification(t!("rootkeys.wrong_state", xous::LANG), None).expect("modals error");
}
}
},
Some(Opcode::UxTryReboot) => {
@ -643,6 +646,53 @@ fn main() -> ! {
xous::Message::new_scalar(Opcode::UxTryReboot.to_usize().unwrap(), 0, 0, 0, 0)
).expect("couldn't initiate dialog box");
}
Some(Opcode::UxBlindCopy) => {
modals.add_list_item(t!("rootkeys.gwup.yes", xous::LANG)).expect("modals error");
modals.add_list_item(t!("rootkeys.gwup.no", xous::LANG)).expect("modals error");
match modals.get_radiobutton(t!("rootkeys.blind_update", xous::LANG)) {
Ok(response) => {
if response == t!("rootkeys.gwup.no", xous::LANG) {
continue;
} if response != t!("rootkeys.gwup.yes", xous::LANG) {
log::error!("got unexpected response from radio box: {:?}", response);
continue;
} else {
// just proceed forward!
}
}
_ => {
log::error!("modals error, aborting");
continue;
}
}
let result = keys.do_gateware_provision_uninitialized(&mut rootkeys_modal, main_cid);
// the stop emoji, when sent to the slider action bar in progress mode, will cause it to close and relinquish focus
rootkeys_modal.key_event(['🛑', '\u{0000}', '\u{0000}', '\u{0000}']);
match result {
Ok(_) => {
modals.show_notification(t!("rootkeys.gwup.finished", xous::LANG), None).expect("modals error");
}
Err(RootkeyResult::AlignmentError) => {
modals.show_notification(t!("rootkeys.init.fail_alignment", xous::LANG), None).expect("modals error");
}
Err(RootkeyResult::KeyError) => {
// probably a bad password, purge it, so the user can try again
keys.purge_password(PasswordType::Update);
modals.show_notification(t!("rootkeys.init.fail_key", xous::LANG), None).expect("modals error");
}
Err(RootkeyResult::IntegrityError) => {
modals.show_notification(t!("rootkeys.init.fail_verify", xous::LANG), None).expect("modals error");
}
Err(RootkeyResult::FlashError) => {
modals.show_notification(t!("rootkeys.init.fail_burn", xous::LANG), None).expect("modals error");
}
Err(RootkeyResult::StateError) => {
modals.show_notification(t!("rootkeys.wrong_state", xous::LANG), None).expect("modals error");
}
}
}
Some(Opcode::UxUpdateGateware) => {
// steps:
// - check update signature "Inspecting gateware update, this will take a moment..."
@ -808,6 +858,9 @@ fn main() -> ! {
Err(RootkeyResult::FlashError) => {
modals.show_notification(t!("rootkeys.init.fail_burn", xous::LANG), None).expect("modals error");
}
Err(RootkeyResult::StateError) => {
modals.show_notification(t!("rootkeys.wrong_state", xous::LANG), None).expect("modals error");
}
}
}
Some(Opcode::UxSelfSignXous) => {
@ -883,6 +936,9 @@ fn main() -> ! {
Err(RootkeyResult::FlashError) => {
modals.show_notification(t!("rootkeys.init.fail_burn", xous::LANG), None).expect("modals error");
}
Err(RootkeyResult::StateError) => {
modals.show_notification(t!("rootkeys.wrong_state", xous::LANG), None).expect("modals error");
}
}
}
Some(Opcode::UxAesEnsurePassword) => msg_blocking_scalar_unpack!(msg, key_index, _, _, _, {
@ -1088,6 +1144,9 @@ fn main() -> ! {
Err(RootkeyResult::FlashError) => {
modals.show_notification(t!("rootkeys.init.fail_burn", xous::LANG), None).expect("modals error");
}
Err(RootkeyResult::StateError) => {
modals.show_notification(t!("rootkeys.wrong_state", xous::LANG), None).expect("modals error");
}
}
}

View file

@ -75,10 +75,19 @@ pub fn create_main_menu(keys: Arc<Mutex<RootKeys>>, menu_management_sid: xous::S
action_payload: MenuPayload::Scalar([0, 0, 0, 0]),
close_on_select: true,
});
menuitems.push(MenuItem {
name: String::from_str(t!("mainmenu.provision_gateware", xous::LANG)),
action_conn: Some(key_conn),
// note this is using the blind copy opcode -- makes a copy without installing keys
action_opcode: keys.lock().unwrap().get_blind_copy_gateware_op(),
action_payload: MenuPayload::Scalar([0, 0, 0, 0]),
close_on_select: true,
});
} else {
menuitems.push(MenuItem {
name: String::from_str(t!("mainmenu.provision_gateware", xous::LANG)),
action_conn: Some(key_conn),
// note this is using the update opcode -- makes a copy while installing keys
action_opcode: keys.lock().unwrap().get_update_gateware_op(),
action_payload: MenuPayload::Scalar([0, 0, 0, 0]),
close_on_select: true,