async def bootscreen() -> None: ui.display.orientation(storage_device.get_rotation()) salt_auth_key = storage_device.get_sd_salt_auth_key() while True: try: if salt_auth_key is not None or config.has_pin(): await lockscreen() if salt_auth_key is not None: salt = await request_sd_salt(None, salt_auth_key ) # type: Optional[bytearray] else: salt = None if not config.has_pin(): config.unlock(pin_to_int(""), salt) storage.init_unlocked() return label = "Enter your PIN" while True: pin = await request_pin(label, config.get_pin_rem()) if config.unlock(pin_to_int(pin), salt): storage.init_unlocked() return else: label = "Wrong PIN, enter again" except (OSError, PinCancelled, SdProtectCancelled) as e: if __debug__: log.exception(__name__, e) except BaseException as e: utils.halt(e.__class__.__name__)
async def sd_protect_disable(ctx: wire.Context, msg: SdProtect) -> Success: if device.get_sd_salt_auth_key() is None: raise wire.ProcessError("SD card protection not enabled") # Confirm that user wants to proceed with the operation. await require_confirm_sd_protect(ctx, msg) # Get the current PIN and salt from the SD card. pin, salt = await request_pin_and_sd_salt(ctx, "Enter PIN") # Check PIN and remove salt. if not config.change_pin(pin_to_int(pin), pin_to_int(pin), salt, None): await show_pin_invalid(ctx) raise wire.PinInvalid("PIN invalid") device.set_sd_salt_auth_key(None) try: # Clean up. await remove_sd_salt(ctx) except Exception: # The cleanup is not necessary for the correct functioning of # SD-protection. If it fails for any reason, we suppress the exception, # because overall SD-protection was successfully disabled. pass await show_success(ctx, ("You have successfully", "disabled SD protection.")) return Success(message="SD card protection disabled")
async def request_pin_and_sd_salt( ctx: wire.Context, prompt: str = "Enter your PIN", allow_cancel: bool = True ) -> Tuple[str, Optional[bytearray]]: salt_auth_key = device.get_sd_salt_auth_key() if salt_auth_key is not None: salt = await request_sd_salt(ctx, salt_auth_key) # type: Optional[bytearray] else: salt = None if config.has_pin(): pin = await request_pin_ack(ctx, prompt, config.get_pin_rem(), allow_cancel) else: pin = "" return pin, salt
async def sd_protect_enable(ctx: wire.Context, msg: SdProtect) -> Success: salt_auth_key = device.get_sd_salt_auth_key() if salt_auth_key is not None: raise wire.ProcessError("SD card protection already enabled") # Confirm that user wants to proceed with the operation. await require_confirm_sd_protect(ctx, msg) # Get the current PIN. if config.has_pin(): pin = pin_to_int(await request_pin_ack(ctx, "Enter PIN", config.get_pin_rem())) else: pin = pin_to_int("") # Check PIN and prepare salt file. salt = random.bytes(SD_SALT_LEN_BYTES) salt_auth_key = random.bytes(SD_SALT_AUTH_KEY_LEN_BYTES) salt_tag = hmac.new(salt_auth_key, salt, sha256).digest()[:SD_SALT_AUTH_TAG_LEN_BYTES] try: await set_sd_salt(ctx, salt, salt_tag) except Exception: raise wire.ProcessError("Failed to write to SD card") if not config.change_pin(pin, pin, None, salt): # Wrong PIN. Clean up the prepared salt file. try: await remove_sd_salt(ctx) except Exception: # The cleanup is not necessary for the correct functioning of # SD-protection. If it fails for any reason, we suppress the # exception, because primarily we need to raise wire.PinInvalid. pass await show_pin_invalid(ctx) raise wire.PinInvalid("PIN invalid") device.set_sd_salt_auth_key(salt_auth_key) await show_success(ctx, ("You have successfully", "enabled SD protection.")) return Success(message="SD card protection enabled")
async def verify_user_pin( prompt: str = "Enter your PIN", allow_cancel: bool = True, retry: bool = True ) -> None: salt_auth_key = device.get_sd_salt_auth_key() if salt_auth_key is not None: salt = await request_sd_salt(None, salt_auth_key) # type: Optional[bytearray] else: salt = None if not config.has_pin() and not config.check_pin(pin_to_int(""), salt): raise RuntimeError while retry: pin = await request_pin(prompt, config.get_pin_rem(), allow_cancel) if config.check_pin(pin_to_int(pin), salt): return else: prompt = "Wrong PIN, enter again" raise PinInvalid
async def sd_protect_refresh(ctx: wire.Context, msg: SdProtect) -> Success: if device.get_sd_salt_auth_key() is None: raise wire.ProcessError("SD card protection not enabled") # Confirm that user wants to proceed with the operation. await require_confirm_sd_protect(ctx, msg) # Get the current PIN and salt from the SD card. pin, old_salt = await request_pin_and_sd_salt(ctx, "Enter PIN") # Check PIN and change salt. new_salt = random.bytes(SD_SALT_LEN_BYTES) new_salt_auth_key = random.bytes(SD_SALT_AUTH_KEY_LEN_BYTES) new_salt_tag = hmac.new(new_salt_auth_key, new_salt, sha256).digest()[:SD_SALT_AUTH_TAG_LEN_BYTES] try: await stage_sd_salt(ctx, new_salt, new_salt_tag) except Exception: raise wire.ProcessError("Failed to write to SD card") if not config.change_pin(pin_to_int(pin), pin_to_int(pin), old_salt, new_salt): await show_pin_invalid(ctx) raise wire.PinInvalid("PIN invalid") device.set_sd_salt_auth_key(new_salt_auth_key) try: # Clean up. await commit_sd_salt(ctx) except Exception: # If the cleanup fails, then request_sd_salt() will bring the SD card # into a consistent state. We suppress the exception, because overall # SD-protection was successfully refreshed. pass await show_success(ctx, ("You have successfully", "refreshed SD protection.")) return Success(message="SD card protection refreshed")