def load_settings( label: str = None, use_passphrase: bool = None, homescreen: bytes = None, passphrase_source: int = None, display_rotation: int = None, ) -> None: if label is not None: config.set(_APP, _LABEL, label.encode(), True) # public if use_passphrase is not None: _set_bool(_APP, _USE_PASSPHRASE, use_passphrase) if homescreen is not None: if homescreen[:8] == b"TOIf\x90\x00\x90\x00": if len(homescreen) <= HOMESCREEN_MAXSIZE: config.set(_APP, _HOMESCREEN, homescreen, True) # public else: config.set(_APP, _HOMESCREEN, b"", True) # public if passphrase_source is not None: if passphrase_source in (0, 1, 2): config.set(_APP, _PASSPHRASE_SOURCE, bytes([passphrase_source])) if display_rotation is not None: if display_rotation not in (0, 90, 180, 270): raise ValueError("Unsupported display rotation degrees: %d" % display_rotation) else: config.set(_APP, _ROTATION, display_rotation.to_bytes(2, "big"), True) # public
def test_change_sd_salt(self): salt1 = b"0123456789abcdef0123456789abcdef" salt2 = b"0123456789ABCDEF0123456789ABCDEF" # Enable PIN and SD salt. config.init() config.wipe() self.assertTrue(config.unlock('', None)) config.set(1, 1, b'value') self.assertFalse(config.change_pin('', '', salt1, None)) self.assertTrue(config.change_pin('', '000', None, salt1)) self.assertEqual(config.get(1, 1), b'value') # Disable PIN and change SD salt. config.init() self.assertFalse(config.unlock('000', None)) self.assertIsNone(config.get(1, 1)) self.assertTrue(config.unlock('000', salt1)) self.assertTrue(config.change_pin('000', '', salt1, salt2)) self.assertEqual(config.get(1, 1), b'value') # Disable SD salt. config.init() self.assertFalse(config.unlock('000', salt2)) self.assertIsNone(config.get(1, 1)) self.assertTrue(config.unlock('', salt2)) self.assertTrue(config.change_pin('', '', salt2, None)) self.assertEqual(config.get(1, 1), b'value') # Check that PIN and SD salt are disabled. config.init() self.assertTrue(config.unlock('', None)) self.assertEqual(config.get(1, 1), b'value')
def test_public(self): config.init() config.wipe() self.assertEqual(config.unlock(pin_to_int('')), True) appid, key = random_entry() value32 = random.bytes(32) config.set(appid, key, value32) value16 = random.bytes(16) config.set(appid, key, value16, True) v1 = config.get(appid, key) v2 = config.get(appid, key, True) self.assertNotEqual(v1, v2) self.assertEqual(v1, value32) self.assertEqual(v2, value16) config.init() v1 = config.get(appid, key) v2 = config.get(appid, key, True) self.assertNotEqual(v1, v2) self.assertEqual(v1, None) self.assertEqual(v2, value16)
def test_set_get(self): config.wipe() for _ in range(64): appid, key = random.uniform(256), random.uniform(256) value = random.bytes(128) config.set(appid, key, value) value2 = config.get(appid, key) self.assertEqual(value, value2)
def store_mnemonic( secret: bytes, mnemonic_type: int, needs_backup: bool = False, no_backup: bool = False, ) -> None: config.set(_APP, _MNEMONIC_SECRET, secret) _set_uint8(_APP, _MNEMONIC_TYPE, mnemonic_type) _init(needs_backup, no_backup)
def set_flags(flags: int) -> None: b = config.get(_APP, _FLAGS) if b is None: b = 0 else: b = int.from_bytes(b, "big") flags = (flags | b) & 0xFFFFFFFF if flags != b: config.set(_APP, _FLAGS, flags.to_bytes(4, "big"))
def store_mnemonic( secret: bytes, mnemonic_type: int, needs_backup: bool, no_backup: bool ) -> None: config.set(_APP, _MNEMONIC_SECRET, secret) _set_uint8(_APP, _MNEMONIC_TYPE, mnemonic_type) config.set(_APP, _VERSION, _STORAGE_VERSION) _set_bool(_APP, _NO_BACKUP, no_backup) if not no_backup: _set_bool(_APP, _NEEDS_BACKUP, needs_backup)
def create_nonce(idx): if idx != get_master_nonce_idx(): old_nonce = config.get(beam_app_id(), idx) new_nonce = bytearray(32) if old_nonce: new_nonce = bytearray(old_nonce) master_nonce = config.get(beam_app_id(), get_master_nonce_idx()) beam.create_derived_nonce(master_nonce, idx, new_nonce) config.set(beam_app_id(), idx, new_nonce) return old_nonce, new_nonce
def test_compact(self): config.init() config.wipe() self.assertEqual(config.unlock(pin_to_int(''), None), True) appid, key = 1, 1 for _ in range(259): value = random.bytes(259) config.set(appid, key, value) value2 = config.get(appid, key) self.assertEqual(value, value2)
def test_set_get(self): config.init() config.wipe() self.assertEqual(config.unlock(pin_to_int(''), None), True) for _ in range(32): appid, key = random_entry() value = random.bytes(128) config.set(appid, key, value) value2 = config.get(appid, key) self.assertEqual(value, value2)
def init_unlocked(): # Check for storage version upgrade. version = config.get(_APP, _VERSION) if version == b"\x01": # Make the U2F counter public and writable even when storage is locked. counter = config.get(_APP, _U2F_COUNTER) if counter is not None: config.set_counter(_APP, _U2F_COUNTER, counter, True) # writable when locked config.delete(_APP, _U2F_COUNTER) config.set(_APP, _VERSION, _STORAGE_VERSION)
def load_settings(label: str=None, use_passphrase: bool=None, homescreen: bytes=None) -> None: if label is not None: config.set(_APP, _LABEL, label.encode(), True) # public if use_passphrase is True: config.set(_APP, _USE_PASSPHRASE, b'\x01') if use_passphrase is False: config.set(_APP, _USE_PASSPHRASE, b'') if homescreen is not None: if homescreen[:8] == b'TOIf\x90\x00\x90\x00': config.set(_APP, _HOMESCREEN, homescreen, True) # public else: config.set(_APP, _HOMESCREEN, b'', True) # public
def test_wipe(self): config.wipe() config.set(0, 0, b'hello') config.set(1, 1, b'world') v0 = config.get(0, 0) v1 = config.get(1, 1) self.assertEqual(v0, b'hello') self.assertEqual(v1, b'world') config.wipe() v0 = config.get(0, 0) v1 = config.get(1, 1) self.assertEqual(v0, bytes()) self.assertEqual(v1, bytes())
def test_lock(self): for _ in range(128): config.init() config.wipe() self.assertEqual(config.unlock(pin_to_int('')), True) appid, key = random_entry() value = random.bytes(16) config.set(appid, key, value) config.init() self.assertEqual(config.get(appid, key), None) with self.assertRaises(RuntimeError): config.set(appid, key, bytes()) config.init() config.wipe()
def load_mnemonic(mnemonic: str, needs_backup: bool) -> None: config.set(_APP, _MNEMONIC, mnemonic.encode()) config.set(_APP, _VERSION, _STORAGE_VERSION) if needs_backup: config.set(_APP, _NEEDS_BACKUP, b'\x01') else: config.set(_APP, _NEEDS_BACKUP, b'')
def test_wipe(self): config.init() config.wipe() self.assertEqual(config.unlock(pin_to_int(''), None), True) config.set(1, 1, b'hello') config.set(1, 2, b'world') v0 = config.get(1, 1) v1 = config.get(1, 2) self.assertEqual(v0, b'hello') self.assertEqual(v1, b'world') config.wipe() v0 = config.get(1, 1) v1 = config.get(1, 2) self.assertEqual(v0, bytes()) self.assertEqual(v1, bytes())
def test_change_pin(self): config.init() config.wipe() self.assertEqual(config.unlock(pin_to_int('')), True) with self.assertRaises(RuntimeError): config.set(PINAPP, PINKEY, b'value') self.assertEqual( config.change_pin(pin_to_int('000'), pin_to_int('666')), False) self.assertEqual(config.change_pin(pin_to_int(''), pin_to_int('000')), True) self.assertEqual(config.get(PINAPP, PINKEY), None) config.set(1, 1, b'value') config.init() self.assertEqual(config.unlock(pin_to_int('000')), True) config.change_pin(pin_to_int('000'), pin_to_int('')) config.init() self.assertEqual(config.unlock(pin_to_int('000')), False) self.assertEqual(config.unlock(pin_to_int('')), True) self.assertEqual(config.get(1, 1), b'value')
def test_set_get(self): config.init() config.wipe() self.assertEqual(config.unlock('', None), True) for _ in range(32): appid, key = random_entry() value = random.bytes(128) config.set(appid, key, value) value2 = config.get(appid, key) self.assertEqual(value, value2) # Test value deletion. self.assertTrue(config.delete(appid, key)) self.assertIsNone(config.get(appid, key)) self.assertFalse(config.delete(appid, key)) # Test get/set for APP out ouf range. with self.assertRaises(ValueError): config.set(0, 1, b'test') with self.assertRaises(ValueError): config.get(0, 1) with self.assertRaises(ValueError): config.set(192, 1, b'test') with self.assertRaises(ValueError): config.get(192, 1)
def load_settings( label: str = None, use_passphrase: bool = None, homescreen: bytes = None, passphrase_source: int = None, ) -> None: if label is not None: config.set(_APP, _LABEL, label.encode(), True) # public if use_passphrase is not None: _set_bool(_APP, _USE_PASSPHRASE, use_passphrase) if homescreen is not None: if homescreen[:8] == b"TOIf\x90\x00\x90\x00": if len(homescreen) <= HOMESCREEN_MAXSIZE: config.set(_APP, _HOMESCREEN, homescreen, True) # public else: config.set(_APP, _HOMESCREEN, b"", True) # public if passphrase_source is not None: if passphrase_source in [0, 1, 2]: config.set(_APP, _PASSPHRASE_SOURCE, bytes([passphrase_source]))
def test_change_pin(self): config.init() config.wipe() self.assertTrue(config.unlock('', None)) config.set(1, 1, b'value') PINS = ('123', '123', 'Trezor T', '3141592653589793238462643383279502884197', '') old_pin = '' for new_pin in PINS: self.assertTrue(config.unlock(old_pin, None)) # The APP namespace which is reserved for storage related values is inaccessible even # when unlocked. with self.assertRaises(ValueError): config.set(PINAPP, PINKEY, b'value') self.assertTrue(config.change_pin(old_pin, new_pin, None, None)) # Old PIN cannot be used to change the current PIN. if old_pin != new_pin: self.assertFalse(config.change_pin(old_pin, '666', None, None)) # Storage remains unlocked. self.assertEqual(config.get(1, 1), b'value') # The APP namespace which is reserved for storage related values is inaccessible even # when unlocked. with self.assertRaises(ValueError): config.get(PINAPP, PINKEY) # Old PIN cannot be used to unlock storage. if old_pin != new_pin: config.init() self.assertFalse(config.unlock(old_pin, None)) self.assertEqual(config.get(1, 1), None) with self.assertRaises(RuntimeError): config.set(1, 1, b'new value') # New PIN unlocks the storage. self.assertTrue(config.unlock(new_pin, None)) self.assertEqual(config.get(1, 1), b'value') # Lock the storage. config.init() old_pin = new_pin
def get_device_id() -> str: dev_id = config.get(_APP, _DEVICE_ID, True).decode() # public if not dev_id: dev_id = _new_device_id() config.set(_APP, _DEVICE_ID, dev_id.encode(), True) # public return dev_id
def set_u2f_counter(cntr: int): config.set(_APP, _U2F_COUNTER, cntr.to_bytes(4, "big"))
def set_autolock_delay_ms(delay_ms: int) -> None: if delay_ms < 60 * 1000: delay_ms = 60 * 1000 config.set(_APP, _AUTOLOCK_DELAY_MS, delay_ms.to_bytes(4, "big"))
def _set_bool(app: int, key: int, value: bool, public: bool = False) -> None: if value: config.set(app, key, _TRUE_BYTE, public) else: config.set(app, key, _FALSE_BYTE, public)
def _set_uint16(app: int, key: int, val: int): config.set(app, key, val.to_bytes(2, "big"))
def set_backed_up() -> None: config.set(_APP, _NEEDS_BACKUP, b"")
def set_slip39_mnemonic(index: int, mnemonic: str): config.set(_SLIP39_MNEMONICS, index, mnemonic.encode())
def set(app: int, key: int, data: bytes, public: bool = False) -> None: config.set(app, key, data, public)
def set_unfinished_backup(state: bool) -> None: if state: config.set(_APP, _UNFINISHED_BACKUP, b"\x01") else: config.set(_APP, _UNFINISHED_BACKUP, b"")
def _init(needs_backup=False, no_backup=False): config.set(_APP, _VERSION, _STORAGE_VERSION) _set_bool(_APP, _NO_BACKUP, no_backup) if not no_backup: _set_bool(_APP, _NEEDS_BACKUP, needs_backup)