diff --git a/embed/extmod/modtrezorconfig/modtrezorconfig.c b/embed/extmod/modtrezorconfig/modtrezorconfig.c index 09c6bda8d..431a93dfa 100644 --- a/embed/extmod/modtrezorconfig/modtrezorconfig.c +++ b/embed/extmod/modtrezorconfig/modtrezorconfig.c @@ -65,14 +65,17 @@ STATIC mp_obj_t mod_trezorconfig_change_pin(mp_obj_t pin, mp_obj_t newpin, mp_ob } STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorconfig_change_pin_obj, mod_trezorconfig_change_pin); -/// def get(app: int, key: int) -> bytes: +/// def get(app: int, key: int, public: bool=False) -> bytes: /// ''' /// Gets a value of given key for given app (or empty bytes if not set). /// ''' -STATIC mp_obj_t mod_trezorconfig_get(mp_obj_t app, mp_obj_t key) { - uint8_t a = mp_obj_get_int(app); - uint8_t k = mp_obj_get_int(key); - uint16_t appkey = a << 8 | k; +STATIC mp_obj_t mod_trezorconfig_get(size_t n_args, const mp_obj_t *args) { + uint8_t app = mp_obj_get_int(args[0]) & 0x7F; + uint8_t key = mp_obj_get_int(args[1]); + if (n_args > 2 && args[2] == mp_const_true) { + app |= 0x80; + } + uint16_t appkey = (app << 8) | key; uint16_t len = 0; const void *val; if (sectrue != storage_get(appkey, &val, &len) || len == 0) { @@ -80,24 +83,27 @@ STATIC mp_obj_t mod_trezorconfig_get(mp_obj_t app, mp_obj_t key) { } return mp_obj_new_bytes(val, len); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorconfig_get_obj, mod_trezorconfig_get); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_get_obj, 2, 3, mod_trezorconfig_get); -/// def set(app: int, key: int, value: bytes) -> None: +/// def set(app: int, key: int, value: bytes, public: bool=False) -> None: /// ''' /// Sets a value of given key for given app. /// ''' -STATIC mp_obj_t mod_trezorconfig_set(mp_obj_t app, mp_obj_t key, mp_obj_t value) { - uint8_t a = mp_obj_get_int(app); - uint8_t k = mp_obj_get_int(key); - uint16_t appkey = a << 8 | k; - mp_buffer_info_t v; - mp_get_buffer_raise(value, &v, MP_BUFFER_READ); - if (sectrue != storage_set(appkey, v.buf, v.len)) { +STATIC mp_obj_t mod_trezorconfig_set(size_t n_args, const mp_obj_t *args) { + uint8_t app = mp_obj_get_int(args[0]) & 0x7F; + uint8_t key = mp_obj_get_int(args[1]); + if (n_args > 3 && args[3] == mp_const_true) { + app |= 0x80; + } + uint16_t appkey = (app << 8) | key; + mp_buffer_info_t value; + mp_get_buffer_raise(args[2], &value, MP_BUFFER_READ); + if (sectrue != storage_set(appkey, value.buf, value.len)) { mp_raise_msg(&mp_type_RuntimeError, "Could not save value"); } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorconfig_set_obj, mod_trezorconfig_set); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_set_obj, 3, 4, mod_trezorconfig_set); /// def wipe() -> None: /// ''' diff --git a/embed/extmod/modtrezorconfig/storage.c b/embed/extmod/modtrezorconfig/storage.c index c408a730d..7ecf46051 100644 --- a/embed/extmod/modtrezorconfig/storage.c +++ b/embed/extmod/modtrezorconfig/storage.c @@ -169,7 +169,13 @@ secbool storage_unlock(const uint32_t pin, mp_obj_t callback) secbool storage_get(uint16_t key, const void **val, uint16_t *len) { - if (sectrue != initialized || sectrue != unlocked || (key >> 8) == 0) { + const uint8_t app = key >> 8; + // APP == 0 is reserved for PIN related values + if (sectrue != initialized || app == 0) { + return secfalse; + } + // top bit of APP set indicates the value can be read from unlocked device + if (sectrue != unlocked && ((app & 0x80) == 0)) { return secfalse; } return norcow_get(key, val, len); @@ -177,7 +183,9 @@ secbool storage_get(uint16_t key, const void **val, uint16_t *len) secbool storage_set(uint16_t key, const void *val, uint16_t len) { - if (sectrue != initialized || sectrue != unlocked || (key >> 8) == 0) { + const uint8_t app = key >> 8; + // APP == 0 is reserved for PIN related values + if (sectrue != initialized || sectrue != unlocked || app == 0) { return secfalse; } return norcow_set(key, val, len); diff --git a/tests/test_trezor.config.py b/tests/test_trezor.config.py index cb9137e88..98d38e9d1 100644 --- a/tests/test_trezor.config.py +++ b/tests/test_trezor.config.py @@ -11,7 +11,7 @@ PINKEY = 0x00 def random_entry(): while True: - appid, key = 1 + random.uniform(255), random.uniform(256) + appid, key = 1 + random.uniform(127), random.uniform(256) if appid != PINAPP or key != PINKEY: break return appid, key @@ -56,6 +56,33 @@ class TestConfig(unittest.TestCase): config.wipe() self.assertEqual(config.change_pin(pin_to_int(''), pin_to_int('000'), None), False) + def test_public(self): + config.init() + config.wipe() + self.assertEqual(config.unlock(pin_to_int(''), None), 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, bytes()) + self.assertEqual(v2, value16) + + def test_change_pin(self): config.init() config.wipe()