-
Notifications
You must be signed in to change notification settings - Fork 69
/
bitcoin.md
417 lines (260 loc) · 19.8 KB
/
bitcoin.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# Bitcoin application: Technical Specifications
This page described the _deprecated_ version 0 of the protocol, as implemented in the v2.0.0 of the Bitcoin app. This protocol is still supported at this time, but we encourage integrations to switch to [version 1 of the protocol](../bitcoin.md).
## Framework
### APDUs
The messaging format of the app is compatible with the [APDU protocol](https://developers.ledger.com/docs/nano-app/application-structure/#apdu-interpretation-loop). The `P1` and `P2` fields are reserved for future use and must be set to `0` in all messages.
The main commands use `CLA = 0xE1`, unlike the legacy Bitcoin application that used `CLA = 0xE0`.
| CLA | INS | COMMAND NAME | DESCRIPTION |
|-----|-----|---------------------|-------------|
| E1 | 00 | GET_EXTENDED_PUBKEY | Return (and optionally show on screen) extended pubkey |
| E1 | 02 | REGISTER_WALLET | Registers a wallet on the device (with user's approval) |
| E1 | 03 | GET_WALLET_ADDRESS | Return and show on screen an address for a registered or default wallet |
| E1 | 04 | SIGN_PSBT | Signs a PSBT with a registered or default wallet |
| E1 | 10 | SIGN_MESSAGE | Sign a message with a key from a BIP32 path (Bitcoin Message Signing) |
The `CLA = 0xF8` is used for framework-specific (rather than app-specific) APDUs; at this time, only one command is present.
| CLA | INS | COMMAND NAME | DESCRIPTION |
|-----|-----|--------------|-------------|
| F8 | 01 | CONTINUE | Respond to an interruption and continue processing a command |
The `CONTINUE` command is sent as a response to a client command from the Hardware Wallet; the format and content on the response depends on the client command, and is documented below for each client command.
### Interactive commands
Several commands are executed via an interactive protocol that requires multiple rounds. At any time after receiving the command and before returning the commands final response (which is status word `0x9000` in case of success), the Hardware Wallet can respond with a special status word `SW_INTERRUPTED_EXECUTION` (`0xE000`), containing a request for the client in the response data. The first byte of the response is the *client command code*, identified what kind of request the Hardware Wallet is asking the client to perform. The client *must* comply with the request and send a special *CONTINUE* command `CLA = 0xF8` and `INS = 0x01`, with the appropriate response.
The specs for the client commands are detailed below.
## Descriptors and wallet policies
The Bitcoin app uses a language similar to [output script descriptors](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md) in order to represent the wallets that can be used to sign transactions.
Wallet policies need to be registered on the device, with an interactive process that requires user's approval.
See [here](wallet.md) for detailed information on the wallet policy language.
## Wallet registration flow
In order to use a wallet policy that is not one of the default ones, the policy must first be registered on the wallet, which is a protocol that requires explicit approval from the user.
A wallet policy is initiated using the `REGISTER_WALLET` command. The screen of the hardware wallet will ask the user to inspect the wallet descriptor template, followed by each of the keys of the cosigners that are part of the wallet policy.
Once the user approves, the `REGISTER_WALLET` returns to the client a 32-byte HMAC-SHA256. This will be provided to any future command that makes use of the wallet policy; therefore, the HMAC should be permanently stored on the client. In case of loss of the HMAC, the registration flow must be repeated from scratch.
## Status Words
| SW | SW name | Description |
|--------|------------------------------|-------------|
| 0x6985 | `SW_DENY` | Rejected by user |
| 0x6A86 | `SW_WRONG_P1P2` | Either `P1` or `P2` is incorrect |
| 0x6A87 | `SW_WRONG_DATA_LENGTH` | `Lc` or minimum APDU length is incorrect |
| 0x6D00 | `SW_INS_NOT_SUPPORTED` | No command exists with `INS` |
| 0x6E00 | `SW_CLA_NOT_SUPPORTED` | Bad `CLA` used for this application |
| 0xB000 | `SW_WRONG_RESPONSE_LENGTH` | Wrong response length (buffer size problem) |
| 0xB007 | `SW_BAD_STATE` | Abrted because unexpected state reached |
| 0xB008 | `SW_SIGNATURE_FAIL` | Invalid signature or HMAC |
| 0xE000 | `SW_INTERRUPTED_EXECUTION` | The command is interrupted, and requires the client's response |
| 0x9000 | `SW_OK` | Success |
<!-- TODO: add an introduction section explaining the comand reference notations (e.g. the Bitcoin style varint) -->
## Commands
### GET_EXTENDED_PUBKEY
Returns an extended public key at the given derivation path, serialized as per BIP-32.
#### Encoding
**Command**
| *CLA* | *INS* |
|-------|-------|
| E1 | 00 |
**Input data**
| Length | Name | Description |
|--------|-------------------|-------------|
| `1` | `display` | `0` or `1` |
| `1` | `n` | Number of derivation steps (maximum 6) |
| `4` | `bip32_path[0]` | First derivation step (big endian) |
| `4` | `bip32_path[1]` | Second derivation step (big endian) |
| | ... | |
| `4` | `bip32_path[n-1]` | `n`-th derivation step (big endian) |
**Output data**
| Length | Description |
|--------|-------------|
| `<variable>` | The full serialized extended public key as per BIP-32 |
#### Description
This command returns the extended public key for the given BIP 32 path.
The paths defined in [BIP-44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki), [BIP-48](https://github.com/bitcoin/bips/blob/master/bip-0048.mediawiki), [BIP-49](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki), [BIP-84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki) and [BIP-86](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki), either in full or are at the deepest hardened level (excluding `change` and `address_index`), are considered standard.
If the `display` parameter is `0` and the path is not standard, an error is returned.
If the `display` parameter is `1`, the result is also shown on the secure screen for verification. The UX flow shows on the device screen the exact path and the complete serialized extended pubkey as defined in [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) for that path. If the path is not standard, an additional warning is shown to the user.
### REGISTER_WALLET
Registers a wallet policy on the device, after validating it with the user.
#### Encoding
**Command**
| *CLA* | *INS* |
|-------|-------|
| E1 | 02 |
**Input data**
| Length | Name | Description |
|-----------------|-----------------|-------------|
| `<variable>` | `policy_length` | The length of the policy (unsigned varint) |
| `policy_length` | `policy` | The serialized wallet policy |
The `policy` is serialized as described [here](wallet.md). At this time, no policy can be longer than 252 bytes, therefore the `policy_length` field is always encoded as 1 byte.
**Output data**
| Length | Description |
|--------|----------------------------|
| `32` | The `wallet_id` |
| `32` | The `hmac` for this wallet |
#### Description
This command allows to register a wallet policy on the device. The wallet's name, descriptor template and each of the keys information is shown to the user.
After user's validation is completed successfully, the application returns the `wallet_id` (sha256 of the wallet serialization), and the `hmac` for this wallet.
#### Client commands
The client must respond to the `GET_PREIMAGE`, `GET_MERKLE_LEAF_PROOF` and `GET_MERKLE_LEAF_INDEX` queries related to the Merkle tree of the list of keys information.
The `GET_MORE_ELEMENTS` command must be handled.
### GET_WALLET_ADDRESS
Get a receive or change a address for a registered or default wallet, after validating it with the user using the trusted screen.
#### Encoding
**Command**
| *CLA* | *INS* |
|-------|-------|
| E1 | 03 |
**Input data**
| Length | Name | Description |
|--------|-----------------|-------------|
| `1` | `display` | `0` or `1` |
| `32` | `wallet_id` | The id of the wallet |
| `32` | `wallet_hmac` | The hmac of a registered wallet, or exactly 32 0 bytes |
| `1` | `change` | `0` for a receive address, `1` for a change address |
| `4` | `address_index` | The desired address index (big-endian) |
**Output data**
| Length | Description |
|-------------|-----------------|
| <variable> | The wallet address for the given change/address_index |
#### Description
For a registered wallet, the hmac must be correct. Once that is validated, this command computes the address of the wallet for the given `change` and `address_index` choice.
For a default wallet, `hmac` must be equal to 32 bytes `0`.
If the `display` parameter is `1`, the resulting wallet address is also shown on the secure screen, and only returns successfully after the user confirms it. If the `display` parameter is `0`, the result is silently returned.
#### Client commands
`GET_PREIMAGE` must know and respond for the full serialized wallet policy whose sha256 hash is `wallet_id`.
The client must respond to the `GET_PREIMAGE`, `GET_MERKLE_LEAF_PROOF` and `GET_MERKLE_LEAF_INDEX` queries related to the Merkle tree of the list of keys information.
The `GET_MORE_ELEMENTS` command must be handled.
### SIGN_PSBT
Given a PSBTv2 and a registered wallet (or a standard one), sign all the inputs that are owned by that wallet.
#### Encoding
**Command**
| *CLA* | *INS* |
|-------|-------|
| E1 | 04 |
**Input data**
| Length | Name | Description |
|---------|------------------------|-------------|
| `<var>` | `global_map_size` | The number of key/value pairs of the global map of the psbt |
| `32` | `global_map_keys_root` | The Merkle root of the keys of the global map |
| `32` | `global_map_vals_root` | The Merkle root of the values of the global map |
| `<var>` | `n_inputs` | The number of inputs of the psbt |
| `32` | `inputs_maps_root` | The Merkle root of the vector of Merkleized map commitments for the input maps |
| `<var>` | `n_outputs` | The number of outputs of the psbt |
| `32` | `outputs_maps_root` | The Merkle root of the vector of Merkleized map commitments for the output maps |
| `32` | `wallet_id` | The id of the wallet |
| `32` | `wallet_hmac` | The hmac of a registered wallet, or exactly 32 0 bytes |
**Output data**
No output data; the signature are returned using the YIELD client command.
#### Description
Using the information in the PSBT and the wallet description, this command verifies what inputs are internal and what output matches the pattern for a change address. After validating all the external outputs and the transaction fee with the user, it signs each of the internal inputs; each signature is sent to the client using the YIELD command, encoded as `<input_index> <signature>`, where the `input_index` is a Bitcoin style varint (currently, always 1 byte).
For a registered wallet, the hmac must be correct.
For a default wallet, `hmac` must be equal to 32 bytes `0`.
#### Client commands
`GET_PREIMAGE` must know and respond for the full serialized wallet policy whose sha256 hash is `wallet_id`.
The client must respond to the `GET_PREIMAGE`, `GET_MERKLE_LEAF_PROOF` and `GET_MERKLE_LEAF_INDEX` queries for all the Merkle trees in the input, including each of the Merkle trees for keys and values of the Merkleized map commitments of each of the inputs/outputs maps of the psbt.
The `GET_MORE_ELEMENTS` command must be handled.
The `YIELD` command must be processed in order to receive the signatures.
### GET_MASTER_FINGERPRINT
Returns the fingerprint of the master public key, as defined in [BIP-0032#Key identifiers](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#key-identifiers).
#### Encoding
**Command**
| *CLA* | *INS* |
|-------|-------|
| E1 | 05 |
**Input data**
No input data.
**Output data**
| Length | Description |
|--------|----------------------------|
| `4` | The master key fingerprint |
#### Description
The fingerprint is necessary to fill the key origin information for some PSBT fields, or to create wallet descriptors.
User interaction is not required for this command.
### SIGN_MESSAGE
Signs a message, according to the standard Bitcoin Message Signing.
The device shows on its secure screen the BIP-32 path used for signing, and the SHA256 hash of the message; the hash should be verified by the user using an external tool if the client is untrusted.
#### Encoding
**Command**
| *CLA* | *INS* |
|-------|-------|
| E1 | 10 |
**Input data**
| Length | Name | Description |
|---------|-------------------|-------------|
| `1` | `n` | Number of derivation steps (maximum 6) |
| `4` | `bip32_path[0]` | First derivation step (big endian) |
| `4` | `bip32_path[1]` | Second derivation step (big endian) |
| | ... | |
| `4` | `bip32_path[n-1]` | `n`-th derivation step (big endian) |
| `<var>` | `msg_length` | The byte length of the message to sign (Bitcoin-style varint) |
| `32` | `msg_merkle_root` | The Merkle root of the message, split in 64-byte chunks |
The message to be signed is split into `ceil(msg_length/64)` chunks of 64 bytes (except the last chunk that could be smaller); `msg_merkle_root` is the root of the Merkle tree of the corresponding list of chunks.
The theoretical maximum valid length of the message is 2<sup>32</sup>-1 = 4 294 967 295 bytes.
**Output data**
| Length | Description |
|--------|-------------|
| `65` | The returned signature, encoded in the standard Bitcoin message signing format |
The signature is returned as a 65-byte binary string (1 byte equal to 32 or 33, followed by `r` and `s`, each of them represented as a 32-byte big-endian integer).
#### Description
The digest being signed is the double-SHA256 of the message, after prefixing the message with:
- the magic string `"\x18Bitcoin Signed Message:\n"` (equal to `18426974636f696e205369676e6564204d6573736167653a0a` in hexadecimal)
- the length of the message, encoded as a Bitcoin-style variable length integer.
#### Client commands
The client must respond to the `GET_PREIMAGE`, `GET_MERKLE_LEAF_PROOF` and `GET_MERKLE_LEAF_INDEX` queries for the Merkle tree of the list of chunks in the message.
## Client commands reference
This section documents the commands that the Hardware Wallet can request to the client when returning with a `SW_INTERRUPTED_EXECUTION` status word.
| CMD | COMMAND NAME | DESCRIPTION |
|-----|-----------------------|-------------|
| 10 | YIELD | Receive some elements during command execution |
| 40 | GET_PREIMAGE | Return the preimage corresponding to the given sha256 hash |
| 41 | GET_MERKLE_LEAF_PROOF | Returns the Merkle proof for a given leaf |
| 42 | GET_MERKLE_LEAF_INDEX | Returns the index of a leaf in a Merkle tree |
| A0 | GET_MORE_ELEMENTS | Receive more data that could not fit in the previous responses |
### YIELD
**Command code**: 0x10
The `YIELD` client command is sent to the client to communicate some result during the execution of a command. Currently only used during `SIGN_PSBT` in order to communicate each of the signatures. The format of the attached message is documented for each command that uses `YIELD`.
The client must respond with an empty message.
### 40 GET_PREIMAGE
**Command code**: 0x40
The `GET_PREIMAGE` command requests the client to reveal a SHA-256 preimage.
The request contains:
- `1` byte: must equal 0, reserved for future usage. (The client should abort if non-zero);
- `32` bytes: a sha-256 hash.
The response must contain:
- `<var>`: the length of the preimage, encoded as a Bitcoin-style varint;
- `1` byte: a 1-byte unsigned integer `b`, the length of the prefix of the pre-image that is part of the response;
- `b` bytes: corresponding to the first `b` bytes of the preimage.
If the pre-image is too long to be contained in a single response, the client should choose `b` to be as large as possible; subsequent bytes are enqueued as single-byte elements that the Hardware Wallet will request with one ore more `GET_MORE_ELEMENTS` requests.
### GET_MERKLE_LEAF_PROOF
**Command code**: 0x41
The `GET_MERKLE_LEAF_PROOF` command requests the hash of a given leaf of a Merkle tree, together with the Merkle proof.
The request contains:
- `32` bytes: the Merkle root hash;
- `<var>` bytes: the tree size `n`, encoded as a Bitcoin-style varint;
- `<var>` bytes: the leaf index `i`, encoded as a Bitcoin-style varint.
The client must respond with:
- `32` bytes: the hash of the leaf with index `i` in the requested Merkle tree;
- `1` byte: the length of the Merkle proof;
- `1` byte: the amount `p` of hashes of the proof that are contained in the response;
- `32 * p` bytes: the concatenation of the first `p` hashes in the Merkle proof.
If the proof is too long to be contained in a single response, the client should choose `p` to be as large as possible; subsequent bytes are enqueued as 32-byte elements that the Hardware Wallet will request with one or more `GET_MORE_ELEMENTS` requests.
### GET_MERKLE_LEAF_INDEX
**Command code**: 0x42
The `GET_MERKLE_LEAF_INDEX` requests the index of a leaf with a certain hash. if multiple leafs have the same hash, the client could respond with either.
The request contains:
- `32` bytes: the Merkle root hash;
- `32` bytes: the leaf hash.
The response contains:
- `1` byte: `1` if the leaf is found, `0` if matching leaf exists;
- `<var>`: the index of the leaf, encoded as a Bitcoin-style varint.
### GET_MORE_ELEMENTS
**Command code**: 0xA0
The `GET_MORE_ELEMENTS` command requests the client to return more elements that were enqueued by previous client commands (like `GET_PREIMAGE` and `GET_MERKLE_LEAF_PROOF`).
All of the elements in the queue must all be byte strings of the same length; the command fails otherwise. The client should return as many elements as it is possible to fit in the response, while leaving the remaining ones (if any) in the queue.
The request is empty.
The response contains:
- `1` byte: the number `n` of returned element;
- `1` byte: the size `s` of each returned element;
- `n * s` bytes: the concatenation of the `n` returned elements.
## Security considerations
Some of the client commands are used to allow the client to reveal some information that is not known to the hardware wallet. This approach allows to create protocols that work with an amount of data that is too large to fit in a single APDU, or even in the limited RAM of a device like a Ledger Nano S.
In designing the interactive protocol, care is taken to avoid security risks associated with a malicious, possibly compromised client.
All the current commands use a commit-and-reveal approach: the APDU that starts the protocol (first message) commits to all the relevant data (for example, the entirety of the PSBT), by using hashes and/or Merkle trees. Any time the client is asked to reveal some committed information, the app does not consider it trusted:
- If a preimage is asked via `GET_PREIMAGE`, the hash is computed to validate that the correct preimage is returned by the client.
- If a Merkle proof is asked via `GET_MERKLE_LEAF_PROOF`, the proof is verified.
- If the index of a leaf is asked `GET_MERKLE_LEAF_INDEX`, the proof for that element is requested via `GET_MERKLE_LEAF_PROOF` and the proof verified, *even if the leaf value is known*.
Care needs to be taken in designing protocols, as the client might lie by omission (for example, fail to reveal that a leaf of a Merkle tree is present during a call to `GET_MERKLE_LEAF_INDEX`).