|
Embedded SDK
Embedded SDK
|
The Address Book feature allows a Ledger device to securely associate human-readable names with blockchain identifiers or Ledger-managed accounts. The device is stateless: nothing is stored persistently. On registration the device generates a random group_id (gid, 32 bytes), authenticates it as a group_handle (64 bytes), and returns two independent HMAC Proofs of Registration that the wallet stores alongside the contact record.
The feature provides:
group_handle — all addresses then share the same name and rename atomicallygroup_handle and the relevant HMAC proof(s)gid itselfThe Address Book implementation is split between the SDK and coin applications:
The Address Book APDU (CLA=0xB0, INS=0x10) dispatches on P1:
| P1 | Sub-command | Struct type | Guard |
|---|---|---|---|
| 0x01 | Register Identity | 0x2d | HAVE_ADDRESS_BOOK |
| 0x02 | Edit Contact Name | 0x2e | HAVE_ADDRESS_BOOK |
| 0x03 | Edit Identifier | 0x31 | HAVE_ADDRESS_BOOK |
| 0x04 | Edit Scope | 0x32 | HAVE_ADDRESS_BOOK |
| 0x11 | Register Ledger Account | 0x2f | HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT |
| 0x12 | Edit Ledger Account | 0x30 | HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT |
| 0x20 | Provide Contact | 0x33 | HAVE_ADDRESS_BOOK |
| 0x21 | Provide Ledger Account Contact | 0x34 | HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT |
Sequence diagrams for Register Identity (P1=0x01) and Register Ledger Account (P1=0x11) are available in Mermaid format in app_features/address_book/doc/address_book_spec.md (viewable on GitHub/GitLab).
| Tag | Name | Description | Max size |
|---|---|---|---|
| 0x01 | STRUCT_TYPE | Sub-command type discriminator (0x2d–0x33) | 1 B |
| 0x02 | STRUCT_VERSION | Always 0x01 | 1 B |
| 0xf0 | CONTACT_NAME | Human-readable contact/account name | 32 B |
| 0xf1 | SCOPE | Scope/namespace for the identifier | 32 B |
| 0xf3 | PREVIOUS_CONTACT_NAME | old name (Edit Contact Name only) | 32 B |
| 0xf2 | ACCOUNT_IDENTIFIER | Opaque identifier (e.g. 20-byte Ethereum address) | 80 B |
| 0xf4 | PREVIOUS_IDENTIFIER | old identifier (Edit Identifier only) | 80 B |
| 0xf5 | PREVIOUS_SCOPE | old scope (Edit Scope only) | 32 B |
| 0xf6 | GROUP_HANDLE | Device-generated token: gid(32) + HMAC-SHA256(K_group, gid)(32) | 64 B |
| 0x21 | DERIVATION_PATH | BIP32 path for HMAC key derivation | 43 B |
| 0x23 | CHAIN_ID | Chain ID (mandatory for Ethereum family) | 8 B |
| 0x51 | BLOCKCHAIN_FAMILY | Blockchain family enum | 1 B |
| 0x29 | HMAC_PROOF | HMAC-SHA256 over gid + contact name | 32 B |
| 0xf7 | HMAC_REST | HMAC-SHA256 over gid + scope + identifier + network | 32 B |
At registration the device generates a random 32-byte Group ID (gid) and authenticates it with a separate device key:
The wallet stores group_handle opaquely. For each Edit operation the wallet re-sends the full group_handle; the device verifies the MAC in constant time and — only on success — extracts gid to authenticate the HMAC proofs.
This closes the proof splicing attack: a wallet that registers two contacts cannot mix HMAC_PROOF from one with HMAC_REST from the other, because neither can fabricate a valid group_handle for an arbitrary gid.
Three independent KDFs prevent cross-feature key reuse:
Identity — HMAC_PROOF (covers name only):
Identity — HMAC_REST (covers scope, identifier, and network):
chain_id is included only when BLOCKCHAIN_FAMILY = 1 (Ethereum), encoded as 8 bytes big-endian.
Ledger Account — HMAC_PROOF:
gid randomly rather than accepting a wallet-chosen contact ID. Combined with the authenticated group_handle, this prevents proof splicing attacks where a malicious wallet mixes proofs from different contacts.HMAC_PROOF covers only gid + name, while HMAC_REST covers gid + scope + identifier + network. This allows the wallet to rename a contact without re-presenting the identifier or scope, and vice-versa.group_handle + HMAC_PROOF to link a second (scope, identifier) pair to the same gid. The device verifies ownership before issuing a new HMAC_REST. Because all addresses share the same gid, a single Edit Contact Name invalidates the HMAC_PROOF for every address in the group simultaneously.gid are computed on-device. The host receives only the opaque group_handle and HMAC proofs.Applications must implement the following callbacks to support Address Book:
Register Identity:
Edit Identifier:
Edit Contact Name / Edit Scope (SDK handles display):
Register Ledger Account (requires HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT):
Provide Contact:
Provide Ledger Account Contact (requires HAVE_ADDRESS_BOOK_LEDGER_ACCOUNT):
Key functions provided by the Address Book module:
See the source files for detailed API documentation.