2021-07-21 11:47:09 +00:00
|
|
|
pub(crate) const SERVER_NAME_KEYS: &str = "_Root key server and update manager_";
|
2021-07-28 15:58:15 +00:00
|
|
|
#[allow(dead_code)]
|
2021-07-25 16:51:22 +00:00
|
|
|
pub(crate) const ROOTKEY_MODAL_NAME: &'static str = "rootkeys modal";
|
2021-08-07 14:21:49 +00:00
|
|
|
#[allow(dead_code)]
|
2021-07-28 19:30:03 +00:00
|
|
|
pub(crate) const ROOTKEY_MENU_NAME: &'static str = "rootkeys menu";
|
2022-01-03 11:06:21 +00:00
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub(crate) const SIG_VERSION: u32 = 1;
|
2021-07-21 11:47:09 +00:00
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
#[derive(num_derive::FromPrimitive, num_derive::ToPrimitive, Debug)]
|
|
|
|
|
pub(crate) enum Opcode {
|
2021-07-30 11:04:02 +00:00
|
|
|
/// use to check if we've been initialized
|
|
|
|
|
KeysInitialized,
|
2021-08-08 19:27:43 +00:00
|
|
|
/// check that the digital signature on the gateware
|
|
|
|
|
CheckGatewareSignature,
|
2021-08-11 18:32:38 +00:00
|
|
|
/// check if the efuse has been locked down
|
|
|
|
|
IsEfuseSecured,
|
|
|
|
|
/// quick check to see if the JTAG can read its IDCODE
|
|
|
|
|
IsJtagWorking,
|
2021-08-18 20:22:28 +00:00
|
|
|
/// initiate an AES oracle operation
|
|
|
|
|
AesOracle,
|
|
|
|
|
/// create new FPGA keys; provisioning requires a slave device to be connected that can run the JTAG sequence
|
|
|
|
|
BbramProvision,
|
2021-07-21 11:47:09 +00:00
|
|
|
|
2021-08-07 14:21:49 +00:00
|
|
|
TestUx,
|
|
|
|
|
|
2021-07-30 19:27:16 +00:00
|
|
|
/// attempt to initialize keys on a brand new system. Does nothing if the keys are already provisioned.
|
|
|
|
|
UxTryInitKeys,
|
2021-08-09 18:48:32 +00:00
|
|
|
UxConfirmInitKeys,
|
|
|
|
|
UxConfirmation,
|
2021-07-30 19:54:10 +00:00
|
|
|
UxInitRequestPassword,
|
|
|
|
|
UxInitPasswordReturn,
|
2021-08-12 15:01:34 +00:00
|
|
|
|
|
|
|
|
/// provision a gateware update with our secret data
|
|
|
|
|
UxUpdateGateware,
|
|
|
|
|
UxUpdateGwCheckSig,
|
|
|
|
|
UxUpdateGwShowInfo,
|
|
|
|
|
UxUpdateGwShowLog,
|
|
|
|
|
UxUpdateGwShowStatus,
|
|
|
|
|
UxUpdateGwConfirm,
|
|
|
|
|
UxUpdateGwDecidePassword,
|
2021-08-12 22:00:21 +00:00
|
|
|
UxUpdateGwPasswordPolicy,
|
2021-08-12 15:01:34 +00:00
|
|
|
UxUpdateGwRun,
|
|
|
|
|
|
|
|
|
|
/// self-sign kernel/loader
|
|
|
|
|
UxSelfSignXous,
|
2021-08-14 11:46:42 +00:00
|
|
|
UxSignXousPasswordPolicy,
|
|
|
|
|
UxSignXousRun,
|
2021-08-12 15:01:34 +00:00
|
|
|
|
2021-08-16 15:35:36 +00:00
|
|
|
/// Ux AES calls
|
2021-08-16 20:15:24 +00:00
|
|
|
UxAesEnsurePassword,
|
|
|
|
|
UxAesPasswordPolicy,
|
|
|
|
|
UxAesEnsureReturn,
|
2021-08-16 15:35:36 +00:00
|
|
|
|
2021-08-18 20:22:28 +00:00
|
|
|
/// Ux BBRAM flow
|
|
|
|
|
UxBbramCheckHelper,
|
|
|
|
|
UxBbramCheckReturn,
|
|
|
|
|
UxBbramPasswordReturn,
|
|
|
|
|
UxBbramRun,
|
|
|
|
|
|
2021-08-12 15:01:34 +00:00
|
|
|
// General Ux calls
|
2021-07-30 19:27:16 +00:00
|
|
|
UxGutter, // NOP for UX calls that require a destination
|
2021-07-30 19:54:10 +00:00
|
|
|
UxGetPolicy,
|
|
|
|
|
UxPolicyReturn,
|
2021-08-10 22:15:04 +00:00
|
|
|
UxTryReboot,
|
2021-08-11 15:22:15 +00:00
|
|
|
UxDoReboot,
|
2021-08-12 15:01:34 +00:00
|
|
|
|
2021-07-27 09:30:37 +00:00
|
|
|
/// UX opcodes
|
2021-07-28 19:30:03 +00:00
|
|
|
MenuRedraw,
|
|
|
|
|
MenuKeys,
|
|
|
|
|
MenuDrop,
|
|
|
|
|
ModalRedraw,
|
|
|
|
|
ModalKeys,
|
|
|
|
|
ModalDrop,
|
2021-07-27 09:30:37 +00:00
|
|
|
|
2021-07-21 11:47:09 +00:00
|
|
|
/// Suspend/resume callback
|
|
|
|
|
SuspendResume,
|
2021-07-25 16:51:22 +00:00
|
|
|
|
|
|
|
|
Quit
|
2021-07-21 11:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
2021-08-12 22:00:21 +00:00
|
|
|
#[derive(Debug, num_derive::FromPrimitive, num_derive::ToPrimitive, PartialEq, Eq)]
|
2021-07-29 20:07:10 +00:00
|
|
|
pub enum PasswordRetentionPolicy {
|
2021-07-21 11:47:09 +00:00
|
|
|
AlwaysKeep,
|
|
|
|
|
EraseOnSuspend,
|
|
|
|
|
AlwaysPurge,
|
|
|
|
|
}
|
2021-08-03 08:28:17 +00:00
|
|
|
|
|
|
|
|
/// Enumerate the possible password types dealt with by this manager.
|
|
|
|
|
/// Note that the discriminant of the enum is used to every-so-slightly change the salt going into bcrypt
|
|
|
|
|
/// I don't think it hurts; more importantly, it also prevents an off-the-shelf "hashcat" run from
|
|
|
|
|
/// being used to brute force both passwords in a single go, as the salt has to be (slightly)
|
|
|
|
|
/// recomputed for each type of password.
|
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
|
|
|
pub enum PasswordType {
|
|
|
|
|
Boot = 1,
|
|
|
|
|
Update = 2,
|
2021-08-07 14:21:49 +00:00
|
|
|
}
|
2021-08-14 16:46:16 +00:00
|
|
|
#[cfg_attr(not(any(target_os = "none", target_os = "xous")), allow(dead_code))]
|
2021-08-07 14:21:49 +00:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
|
|
|
pub enum RootkeyResult {
|
|
|
|
|
AlignmentError,
|
|
|
|
|
KeyError,
|
|
|
|
|
IntegrityError,
|
|
|
|
|
FlashError,
|
|
|
|
|
}
|
2021-08-16 15:35:36 +00:00
|
|
|
|
|
|
|
|
/// AES operation definitions
|
|
|
|
|
pub use cipher::{BlockCipher, consts::U16};
|
2021-08-16 16:02:24 +00:00
|
|
|
use zeroize::Zeroize;
|
2021-08-16 15:35:36 +00:00
|
|
|
|
2021-08-16 20:15:24 +00:00
|
|
|
/// 128-bit AES block
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub type Block = cipher::generic_array::GenericArray<u8, cipher::consts::U16>;
|
|
|
|
|
/// 16 x 128-bit AES blocks to be processed in bulk
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub type ParBlocks = cipher::generic_array::GenericArray<Block, cipher::consts::U16>;
|
|
|
|
|
|
2021-08-16 16:53:26 +00:00
|
|
|
pub const PAR_BLOCKS: usize = 16;
|
2021-08-16 15:35:36 +00:00
|
|
|
/// Selects which key to use for the decryption/encryption oracle.
|
|
|
|
|
/// currently only one type is available, the User key, but dozens more
|
|
|
|
|
/// could be accommodated.
|
2021-08-16 20:15:24 +00:00
|
|
|
#[derive(Debug, num_derive::FromPrimitive, num_derive::ToPrimitive, PartialEq, Eq, Copy, Clone)]
|
2021-08-16 15:35:36 +00:00
|
|
|
pub enum AesRootkeyType {
|
|
|
|
|
User0 = 0x28,
|
|
|
|
|
NoneSpecified = 0xff,
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-16 16:02:24 +00:00
|
|
|
#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Zeroize)]
|
|
|
|
|
#[zeroize(drop)]
|
2021-08-16 15:35:36 +00:00
|
|
|
pub enum AesBlockType {
|
|
|
|
|
SingleBlock([u8; 16]),
|
2021-08-16 16:53:26 +00:00
|
|
|
ParBlock([[u8; 16]; PAR_BLOCKS]),
|
2021-08-16 15:35:36 +00:00
|
|
|
}
|
2021-08-16 16:02:24 +00:00
|
|
|
#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Zeroize)]
|
|
|
|
|
#[zeroize(drop)]
|
2021-08-16 15:35:36 +00:00
|
|
|
pub enum AesOpType {
|
|
|
|
|
Encrypt,
|
|
|
|
|
Decrypt,
|
|
|
|
|
}
|
2021-08-16 16:02:24 +00:00
|
|
|
#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Zeroize)]
|
|
|
|
|
#[zeroize(drop)]
|
2021-08-16 15:35:36 +00:00
|
|
|
pub struct AesOp {
|
|
|
|
|
/// the caller can try to request "any" index, but it's checked inside the oracle first.
|
|
|
|
|
pub key_index: u8,
|
|
|
|
|
pub block: AesBlockType,
|
|
|
|
|
pub aes_op: AesOpType,
|
|
|
|
|
}
|
|
|
|
|
impl AesOp {
|
|
|
|
|
pub fn clear(&mut self) {
|
|
|
|
|
match self.block {
|
|
|
|
|
AesBlockType::SingleBlock(mut blk) => {
|
|
|
|
|
for b in blk.iter_mut() {
|
|
|
|
|
*b = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AesBlockType::ParBlock(mut blks) => {
|
|
|
|
|
for blk in blks.iter_mut() {
|
|
|
|
|
for b in blk.iter_mut() {
|
|
|
|
|
*b = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|