Skip to content

Latest commit

 

History

History
260 lines (231 loc) · 16.6 KB

Storage.md

File metadata and controls

260 lines (231 loc) · 16.6 KB

STORAGE_VERSION 1 layout

This is the original storage layout, derived from the use of un-serialized protobuf structs as a serialization format. This made storage extremely sensitive to changes in the protobuf descriptors, and is considered bad practice.

Field Type Size (bytes) Offset (bytes)
version u32 4 0
has_node bool 1 4
node StorageHDNode 129 8
reserved N/A 3 137
has_mnemonic bool 1 140
mnemonic char[241] 241 141
reserved N/A 1 382
passphrase_protection bool 1 383
has_pin_failed_attempts bool 1 384
reserved N/A 3 385
pin_failed_attempts u32 4 388
has_pin bool 1 392
pin char[10] 10 393
has_language bool 1 403
language char[17] 17 404
has_label bool 1 421
label char[33] 33 422
reserved N/A 1 455
imported bool 1 456

STORAGE_VERSION 2-10 layout

This version added the root seed cache, and policy objects. Since it is closely aligned with V1's layout, it shares many of the same reader functions, which accounts for the "missing" storage_readStorageV2().

Field Type Size (bytes) Offset (bytes)
version u32 4 0
has_node bool 1 4
node StorageHDNode 129 8
reserved N/A 3 137
has_mnemonic bool 1 140
mnemonic char[241] 241 141
reserved N/A 1 382
passphrase_protection bool 1 383
has_pin_failed_attempts bool 1 384
reserved N/A 3 385
pin_failed_attempts u32 4 388
has_pin bool 1 392
pin char[10] 10 393
has_language bool 1 403
language char[17] 17 404
has_label bool 1 421
label char[33] 33 422
reserved N/A 1 455
imported bool 1 456
reserved N/A 3 457
policies_count u32 4 460
policies[0] StoragePolicy 17 464
reserved N/A 3 481
root_seed_cache_status u8 1 484
root_seed_cache char[64] 64 485
root_ecdsa_curve_type char[10] 10 549

STORAGE_VERSION 11 layout

This is the third generation of storage layouts. It leverages a clean breaking point to compactify fields, and arrange things in two sections: one for secrets, and one for public(ish) information. The secret area is then aes256 encrypted with a randomly generated 64-bit key, which is then wrapped with the user's pin. This further hardens the security of a powered-down device. Additionally, it leaves reserved bytes & bits open for future additions, making it easier to extend for new features later on.

Public(ish) Storage

Field Type Size (bytes) Offset (bytes)
version u32 4 0
flags u32 4 4
has_pin bit 0
has_language bit 1
has_label bit 2
has_auto_lock_delay_ms bit 3
imported bit 4
passphrase_protection bit 5
formerly: ShapeShift bit 6
formerly: Pin Caching bit 7
has_node bit 8
has_mnemonic bit 9
has_u2froot bit 10
Experinemtal policy bit 11
AdvancedMode policy bit 12
no backup (seedless) bit 13
has_sec_fingerprint bit 14
sca_hardened bit 15
reserved bits 16 - 31
pin_failed_attempts u32 4 8
auto_lock_delay_ms u32 4 12
language char[16] 16 16
label char[48] 48 32
wrapped_storage_key char[64] 64 80
storage_key_fingerprint char[64] 32 144
u2froot StorageHDNode 129 176
u2f_counter u32 4 305
sec_fingerprint char[32] 32 309
random_salt char[32] 32 341
reserved char[91] 91 373
encrypted_secrets_version u32 4 464
encrypted_secrets char[512] 512 468

Secret Storage

Field Type Size (bytes) Offset (bytes)
node StorageHDNode 129 0
mnemonic char[241] 241 129
root_seed_cache_status u8 1 370
root_seed_cache char[64] 64 371
root_ecdsa_curve_type char[10] 10 435
reserved char[67] 67 445

STORAGE_VERSION 16 layout

Public(ish) Storage

Field Type Size (bytes) Offset (bytes)
version u32 4 0
flags u32 4 4
has_pin bit 0
has_language bit 1
has_label bit 2
has_auto_lock_delay_ms bit 3
imported bit 4
passphrase_protection bit 5
formerly: ShapeShift bit 6
formerly: Pin Caching bit 7
has_node bit 8
has_mnemonic bit 9
has_u2froot bit 10
Experinemtal policy bit 11
AdvancedMode policy bit 12
no backup (seedless) bit 13
has_sec_fingerprint bit 14
sca_hardened bit 15
has_wipe_code bit 16
v15_16_trans bit 17
reserved bits 18 - 31
pin_failed_attempts u32 4 8
auto_lock_delay_ms u32 4 12
language char[16] 16 16
label char[48] 48 32
wrapped_storage_key char[64] 64 80
storage_key_fingerprint char[64] 32 144
wrapped_wipe_code_key char[64] 64 176
wipe_code_key_fingerprint char[64] 32 240
u2froot StorageHDNode 129 272
u2f_counter u32 4 401
sec_fingerprint char[32] 32 405
random_salt char[32] 32 437
reserved char[1028] 1028 469
encrypted_secrets_version u32 4 1497
encrypted_secrets char[512] 512 1501

Secret Storage

Field Type Size (bytes) Offset (bytes)
node StorageHDNode 129 0
mnemonic char[241] 241 129
root_seed_cache_status u8 1 370
root_seed_cache char[64] 64 371
root_ecdsa_curve_type char[10] 10 435
reserved char[67] 67 445

STORAGE_VERSION 17 layout

This version increased the size of the secret storage to accomodate the authenticator feature secrets

Public(ish) Storage

Field Type Size (bytes) Offset (bytes)
version u32 4 0
flags u32 4 4
has_pin bit 0
has_language bit 1
has_label bit 2
has_auto_lock_delay_ms bit 3
imported bit 4
passphrase_protection bit 5
formerly: ShapeShift bit 6
formerly: Pin Caching bit 7
has_node bit 8
has_mnemonic bit 9
has_u2froot bit 10
Experimental policy bit 11
AdvancedMode policy bit 12
no backup (seedless) bit 13
has_sec_fingerprint bit 14
sca_hardened bit 15
has_wipe_code bit 16
v15_16_trans bit 17
authdata_initialized bit 18
authdata_encrypted bit 19
reserved bits 20 - 31
pin_failed_attempts u32 4 8
auto_lock_delay_ms u32 4 12
language char[16] 16 16
label char[48] 48 32
wrapped_storage_key char[64] 64 80
storage_key_fingerprint char[64] 32 144
wrapped_wipe_code_key char[64] 64 176
wipe_code_key_fingerprint char[64] 32 240
u2froot StorageHDNode 129 272
u2f_counter u32 4 401
sec_fingerprint char[32] 32 405
random_salt char[32] 32 437
authdata_fingerprint char[32] 32 469
reserved char[996] 1028 501
encrypted_secrets_version u32 4 1497
encrypted_secrets char[1024] 512 1501

Secret Storage

Field section Type Size (bytes) Offset (bytes)
node crypto StorageHDNode 129 0
mnemonic crypto char[241] 241 129
cache->
root_seed_cache_status crypto u8 1 370
root_seed_cache crypto char[64] 64 371
root_ecdsa_curve_type crypto char[10] 10 435
sec_reserved crypto char[67] 67 445
Block boundary - N256 bytes above, M256 bytes below
authenticator_accounts authenticator 10 * char[45] 450 512
authenticator_reserved authenticator char[62] 62 962

Secret storage is split into two sections block-multiple size sections, crypto secrets and authenticator secrets. Because the authenticator data is encrypted independently with the bip39 passphrase, sizeof(authenticator_accounts) + sizeof(authenticator_reserved) % 256 == 0.

Cache specifics:

typedef struct _Cache { /* Root node cache */ uint8_t root_seed_cache_status; uint8_t root_seed_cache[64]; char root_ecdsa_curve_type[10]; } Cache;