Skip to content

Commit 5924f15

Browse files
prestwichgzliudan
authored andcommitted
accounts/usbwallet: mitigate ledger app chunking issue (ethereum#26773)
This PR mitigates an issue with Ledger's on-device RLP deserialization, see LedgerHQ/app-ethereum#409 Ledger's RLP deserialization code does not validate the length of the RLP list received, and it may prematurely enter the signing flow when a APDU chunk boundary falls immediately before the EIP-155 chain_id when deserializing a transaction. Since the chain_id is uninitialized, it is 0 during this signing flow. This may cause the user to accidentally sign the transaction with chain_id = 0. That signature would be returned from the device 1 packet earlier than expected by the communication loop. The device blocks the second-to-last packet waiting for the signer flow, and then errors on the successive packet (which contains the chain_id, zeroed r, and zeroed s) Since the signature's early arrival causes successive errors during the communication process, geth does not parse the improper signature produced by the device, and therefore no improperly-signed transaction can be created. User funds are not at risk. We mitigate by selecting the highest chunk size that leaves at least 4 bytes in the final chunk.
1 parent e3605a8 commit 5924f15

File tree

1 file changed

+9
-1
lines changed

1 file changed

+9
-1
lines changed

accounts/usbwallet/ledger.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ const (
5959
ledgerP1InitTransactionData ledgerParam1 = 0x00 // First transaction data block for signing
6060
ledgerP1ContTransactionData ledgerParam1 = 0x80 // Subsequent transaction data block for signing
6161
ledgerP2DiscardAddressChainCode ledgerParam2 = 0x00 // Do not return the chain code along with the address
62+
63+
ledgerEip155Size int = 3 // Size of the EIP-155 chain_id,r,s in unsigned transactions
6264
)
6365

6466
// errLedgerReplyInvalidHeader is the error message returned by a Ledger data exchange
@@ -347,9 +349,15 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
347349
op = ledgerP1InitTransactionData
348350
reply []byte
349351
)
352+
353+
// Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app.
354+
// https://github.com/LedgerHQ/app-ethereum/issues/409
355+
chunk := 255
356+
for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
357+
}
358+
350359
for len(payload) > 0 {
351360
// Calculate the size of the next data chunk
352-
chunk := 255
353361
if chunk > len(payload) {
354362
chunk = len(payload)
355363
}

0 commit comments

Comments
 (0)