Skip to content

Latest commit

 

History

History
1380 lines (946 loc) · 55.4 KB

ethapp.adoc

File metadata and controls

1380 lines (946 loc) · 55.4 KB

Ethereum application : Common Technical Specifications

About

This application describes the APDU messages interface to communicate with the Ethereum application.

The application covers the following functionalities :

  • Retrieve a public Ethereum address given a BIP 32 path

  • Sign a basic Ethereum transaction given a BIP 32 path

  • Provide callbacks to validate the data associated to an Ethereum transaction

The application interface can be accessed over HID or BLE

APDUs list

The following APDUs are managed by the application. They are detailed in the following chapters.

Description

Instruction

GET ETH PUBLIC ADDRESS

0x02

SIGN ETH TRANSACTION

0x04

GET APP CONFIGURATION

0x06

SIGN ETH PERSONAL MESSAGE

0x08

PROVIDE ERC 20 TOKEN INFORMATION

0x0A

SIGN ETH EIP 712

0x0C

GET ETH2 PUBLIC KEY

0x0E

SET ETH2 WITHDRAWAL INDEX

0x10

SET EXTERNAL PLUGIN

0x12

PROVIDE NFT INFORMATION

0x14

SET PLUGIN

0x16

PERFORM PRIVACY OPERATION

0x18

EIP712 SEND STRUCT DEFINITION

0x1A

EIP712 SEND STRUCT IMPLEMENTATION

0x1C

EIP712 FILTERING

0x1E

GET CHALLENGE

0x20

PROVIDE DOMAIN NAME

0x22

PROVIDE NETWORK INFORMATION

0x30

General purpose APDUs

GET ETH PUBLIC ADDRESS

Description

This command returns the public key and Ethereum address for the given BIP 32 path.

The address can be optionally checked on the device before being returned.

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

02

00 : return address

01 : display address and confirm before returning

00 : do not return the chain code

01 : return the chain code

variable

variable

'Input data'

Description

Length

Number of BIP 32 derivations to perform (max 10)

1

First derivation index (big endian)

4

…​

4

Last derivation index (big endian)

4

Chain ID (big endian) (optional)

8

'Output data'

Description

Length

Public Key length

1

Uncompressed Public Key

var

Ethereum address length

1

Ethereum address

var

Chain code if requested

32

SIGN ETH TRANSACTION

Description

This command signs an Ethereum transaction after having the user validate the following parameters

  • Gas price

  • Gas limit

  • Recipient address

  • Value

The input data is the RLP encoded transaction (as per https://github.com/ethereum/pyethereum/blob/develop/ethereum/transactions.py#L22), without v/r/s present, streamed to the device in 255 bytes maximum data chunks.

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

04

00 : first transaction data block

80 : subsequent transaction data block

00 : process & start flow

01 : store only

02 : start flow

variable

variable

'Input data (first transaction data block)'

If P2 == 0x02, then no data is provided.

Description

Length

Number of BIP 32 derivations to perform (max 10)

1

First derivation index (big endian)

4

…​

4

Last derivation index (big endian)

4

RLP transaction chunk

variable

'Input data (other transaction data block)'

Description

Length

RLP transaction chunk

variable

'Output data'

If P2 == 0x01, then no data is returned.

Description

Length

v

1

r

32

s

32

GET APP CONFIGURATION

Description

This command returns specific application configuration

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

06

00

00

00

04

'Input data'

None

'Output data'

Description

Length

Flags 0x01 : arbitrary data signature enabled by user

0x02 : ERC 20 Token information needs to be provided externally

01

Application major version

01

Application minor version

01

Application patch version

01

SIGN ETH PERSONAL MESSAGE

Description

This command signs an Ethereum message following the personal_sign specification (ethereum/go-ethereum#2940) after having the user validate the SHA-256 hash of the message being signed.

This command has been supported since firmware version 1.0.8

The input data is the message to sign, streamed to the device in 255 bytes maximum data chunks

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

08

00 : first message data block

80 : subsequent message data block

00

variable

variable

'Input data (first message data block)'

Description

Length

Number of BIP 32 derivations to perform (max 10)

1

First derivation index (big endian)

4

…​

4

Last derivation index (big endian)

4

Message length

4

Message chunk

variable

'Input data (other transaction data block)'

Description

Length

Message chunk

variable

'Output data'

Description

Length

v

1

r

32

s

32

PROVIDE ERC 20 TOKEN INFORMATION

Description

This command provides a trusted description of an ERC 20 token to associate a contract address with a ticker and number of decimals.

It shall be run immediately before performing a transaction involving a contract calling this contract address to display the proper token information to the user if necessary, as marked in GET APP CONFIGURATION flags.

The signature is computed on

ticker || address || number of decimals (uint4be) || chainId (uint4be)

signed by the following secp256k1 public key 045e6c1020c14dc46442fe89f97c0b68cdb15976dc24f24c316e7b30fe4e8cc76b1489150c21514ebf440ff5dea5393d83de5358cd098fce8fd0f81daa94979183

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

0A

00

00

variable

00

'Input data'

Description

Length

Length of ERC 20 ticker

1

ERC 20 ticker

variable

ERC 20 contract address

20

Number of decimals (big endian encoded)

4

Chain ID (big endian encoded)

4

Token information signature

variable

'Output data'

Description

Length

Asset index where the information has been stored

1

SIGN ETH EIP 712

Description

This command signs an Ethereum message following the EIP 712 specification (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md)

For implementation version 0, the domain hash and message hash are provided to the device, which displays them and returns the signature

This command has been supported since app version 1.5.0

The full implementation uses all the JSON data and does all the hashing on the device, it has been supported since app version 1.9.19. This command should come last, after all the EIP712 SEND STRUCT DEFINITION & SEND STRUCT IMPLEMENTATION.

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

0C

00

00: v0 implementation

01: full implementation

variable

variable

'Input data'

Description

Length

Number of BIP 32 derivations to perform (max 10)

1

First derivation index (big endian)

4

…​

4

Last derivation index (big endian)

4

Domain hash (only for v0)

32

Message hash (only for v0)

32

'Output data'

Description

Length

v

1

r

32

s

32

GET ETH2 PUBLIC KEY

Description

This command returns an Ethereum 2 BLS12-381 public key derived following EIP 2333 specification (https://eips.ethereum.org/EIPS/eip-2333)

This command has been supported since firmware version 1.6.0

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

0E

00 : return public key

01 : display public key and confirm before returning

00

variable

variable

'Input data'

Description

Length

Number of BIP 32 derivations to perform (max 10)

1

First derivation index (big endian)

4

…​

4

Last derivation index (big endian)

4

'Output data'

Description

Length

Public key

48

SET ETH2 WITHDRAWAL INDEX

Description

This command sets the index of the Withdrawal key used as withdrawal credentials in an ETH2 deposit contract call signature. The path of the Withdrawal key is defined as m/12381/3600/index/0 according to EIP 2334 (https://eips.ethereum.org/EIPS/eip-2334)

The default index used is 0 if this method isn’t called before the deposit contract transaction is sent to the device to be signed

This command has been supported since firmware version 1.5.0

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

10

00

00

variable

variable

'Input data'

Description

Length

Withdrawal key index (big endian)

4

'Output data'

None

SET EXTERNAL PLUGIN

Description

This command provides the name of a trusted binding of a plugin with a contract address and a supported method selector. This plugin will be called to interpret contract data in the following transaction signing command.

It shall be run immediately before performing a transaction involving a contract supported by this plugin to display the proper information to the user if necessary.

The function returns an error sw (0x6984) if the plugin requested is not installed on the device, 0x9000 otherwise.

The signature is computed on

len(pluginName) || pluginName || contractAddress || methodSelector

signed by the following secp256k1 public key 0482bbf2f34f367b2e5bc21847b6566f21f0976b22d3388a9a5e446ac62d25cf725b62a2555b2dd464a4da0ab2f4d506820543af1d242470b1b1a969a27578f353

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

12

00

00

variable

00

'Input data'

Description

Length

Length of plugin name

1

plugin name

variable

contract address

20

method selector

4

signature

variable

'Output data'

None

PROVIDE NFT INFORMATION

Description

This command provides a trusted description of an NFT to associate a contract address with a collectionName.

It shall be run immediately before performing a transaction involving a contract calling this contract address to display the proper nft information to the user if necessary, as marked in GET APP CONFIGURATION flags.

The signature is computed on:

type || version || len(collectionName) || collectionName || address || chainId || keyId || algorithmId

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

14

00

00

variable

00

'Input data'

Description

Length

Type

1

Version

1

Collection Name Length

1

Collection Name

variable

Address

20

Chain ID

8

KeyID

1

Algorithm ID

1

Signature Length

1

Signature

variable

'Output data'

Description

Length

Asset index where the information has been stored

1

SET PLUGIN

Description

This command provides the name of a trusted binding of a plugin with a contract address and a supported method selector. This plugin will be called to interpret contract data in the following transaction signing command.

It can be used to set both internal and external plugins.

It shall be run immediately before performing a transaction involving a contract supported by this plugin to display the proper information to the user if necessary.

The function returns an error sw (0x6984) if the plugin requested is not installed on the device, 0x9000 otherwise.

The plugin names ERC20, ERC721 and ERC1155 are reserved. Additional plugin names might be added to this list in the future.

The signature is computed on

type || version || len(pluginName) || pluginName || address || selector || chainId || keyId || algorithmId

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

16

00

00

variable

00

'Input data'

Description

Length

Type

1

Version

1

Plugin Name Length

1

Plugin Name

variable

Address

20

Selector

4

Chain ID

8

KeyID

1

Algorithm ID

1

Signature Length

1

Signature

variable

'Output data'

None

PERFORM PRIVACY OPERATION

Description

This command performs privacy operations as defined in EIP 1024 (https://ethereum-magicians.org/t/eip-1024-cross-client-encrypt-decrypt/505)

It can return the public encryption key on Curve25519 for a given Ethereum account or the shared secret (generated by the scalar multiplication of the remote public key by the account private key on Curve25519) used to decrypt private data encrypted for a given Ethereum account

All data can be optionally checked on the device before being returned.

Coding

'Command'

CLA

INS

P1

P2

Lc

Le

E0

18

00 : return data

01 : display data and confirm before returning

00 : return the public encryption key

01 : return the shared secret

variable

variable

'Input data'

Description

Length

Number of BIP 32 derivations to perform (max 10)

1

First derivation index (big endian)

4

…​

4

Last derivation index (big endian)

4

Third party public key on Curve25519, if returning the shared secret

32

'Output data'

Description

Length

Public encryption key or shared secret

32

EIP712 SEND STRUCT DEFINITION

Description

This command sends the message definition with all its types.
These commands should come before the EIP712 SEND STRUCT IMPLEMENTATION ones.

Coding

Command

CLA

INS

P1

P2

LC

Le

E0

1A

00

00 : struct name

FF : struct field

variable

variable

Input data

If P2 == struct name

Description

Length (byte)

Name

LC

If P2 == struct field

Description

Length (byte)

Mandatory

TypeDesc (type description)

1

TypeNameLength

1

TypeName

variable

TypeSize

1

ArrayLevelCount

1

ArrayLevels

variable

KeyNameLength

1

KeyName

variable

TypeDesc

From MSB to LSB:

Description

Length (bit)

TypeArray (is it an array?)

1

TypeSize (is a type size specified?)

1

Unused

2

Type

4

How to interpret Type from its value :

Value

Type

0

custom (struct type)

1

int

2

uint

3

address

4

bool

5

string

6

fixed-sized bytes

7

dynamic-sized bytes

TypeName

Only present if the Type is set to custom.

Indicates the name of the struct that will be the type of the field.

TypeSize

Only present if the TypeSize bit is set in TypeDesc.

Indicates the byte size of the field. (Ex: 8 for an int64)

ArrayLevelCount

Only present if the TypeArray bit is set in TypeDesc.

Indicates how many array levels that field has (Ex: 3 for int16[2][][4]).

ArrayLevels

Only present if the TypeArray bit is set in TypeDesc.

Types of array level:

Byte value

Type

0

Dynamic sized (type[])

1

Fixed size (type[N])

Each fixed-sized array level is followed by a byte indicating its size (number of elements).

Output data

None

EIP712 SEND STRUCT IMPLEMENTATION

Description

This command sends the message implementation with all its values.
These commands should come after the EIP712 SEND STRUCT DEFINITION ones.

Coding

Command

CLA

INS

P1

P2

LC

Le

E0

1C

00 : complete send

01 : partial send, more to come

00 : root struct

0F : array

FF : struct field

variable

variable

Input data

If P2 == root struct

Description

Length (byte)

Name

LC

Sets the name of the upcoming root structure all the following fields will be apart of until we set another root structure.

If P2 == array

Description

Length (byte)

Array size

1

Sets the size of the upcoming array the following N fields will be apart of.

If P2 == struct field

Description

Length (byte)

Value length

2 (BE)

Value

variable

Sets the raw value of the next field in order in the current root structure. Raw as in, an integer in the JSON file represented as "128" would only be 1 byte long (0x80) instead of 3 as an array of ASCII characters, same for addresses and so on.

Output data

None

EIP712 FILTERING

Description

This command provides a trusted way of deciding what information from the JSON data to show and replace some values by more meaningful ones.

This mode can be overridden by the in-app setting to fully clear-sign EIP-712 messages.

For the signatures :

  • The chain ID used for the signature must be 8 bytes wide.

  • The schema hash = sha224sum of the value of types at the root of the JSON data (stripped of all spaces and newlines)

Activation

Full filtering is disabled by default and has to be changed with this APDU (default behaviour is basic filtering handled by the app itself).

Field substitution will be ignored if the full filtering is not activated.

This command should come before the domain & message implementations. If activated, fields will be by default hidden unless they receive a field name substitution.

Discarded filter path

This command gives the app the absolute path of the upcoming filter which will be discarded (because it targets a field within an empty array).

The next filter should be marked as discarded (with P1) to be able to use this given filter path.

Message info

This command should come right after the implementation of the domain has been sent with SEND STRUCT IMPLEMENTATION, just before sending the message implementation. The first byte is used so that a signature of one type cannot be valid as another type.

The signature is computed on :

183 || chain ID (BE) || contract address || schema hash || filters count || display name

Amount-join token

This command should come before the corresponding SEND STRUCT IMPLEMENTATION and are only usable for message fields (and not domain ones). The first byte is used so that a signature of one type cannot be valid as another type.

The signature is computed on :

11 || chain ID (BE) || contract address || schema hash || field path || token index

Amount-join value

This command should come before the corresponding SEND STRUCT IMPLEMENTATION and are only usable for message fields (and not domain ones). The first byte is used so that a signature of one type cannot be valid as another type.

A token index of 0xFF indicates the token address is in the verifyingContract field of the EIP712Domain so the app won’t receive an amount-join token filtering APDU. This enables support for Permit (ERC-2612) messages.

The signature is computed on :

22 || chain ID (BE) || contract address || schema hash || field path || display name || token index

Date / Time

This command should come before the corresponding SEND STRUCT IMPLEMENTATION and are only usable for message fields (and not domain ones). The first byte is used so that a signature of one type cannot be valid as another type.

The signature is computed on :

33 || chain ID (BE) || contract address || schema hash || field path || display name

Trusted name

This command should come right after the implementation of the domain has been sent with SEND STRUCT IMPLEMENTATION, just before sending the message implementation. The first byte is used so that a signature of one type cannot be valid as another type.

The signature is computed on :

44 || chain ID (BE) || contract address || schema hash || field path || display name || name types || name sources

Show raw field

This command should come before the corresponding SEND STRUCT IMPLEMENTATION and are only usable for message fields (and not domain ones). The first byte is used so that a signature of one type cannot be valid as another type.

The signature is computed on :

72 || chain ID (BE) || contract address || schema hash || field path || display name

Coding

Command

CLA

INS

P1

P2

LC

Le

E0

1E

00 : standard

01 : discarded

00 : activation

01 : discarded filter path

0F : message info

FB : trusted name

FC : date/time

FD : amount-join token

FE : amount-join value

FF : raw field

variable

variable

Input data

If P2 == activation

None

If P2 == discarded filter path

Description

Length (byte)

Path length

1

Path

variable

If P2 == message info

Description

Length (byte)

Display name length

1

Display name

variable

Filters count

1

Signature length

1

Signature

variable

If P2 == trusted name

Description

Length (byte)

Display name length

1

Display name

variable

Name types count

1

Name types

variable

Name sources count

1

Name sources

variable

Signature length

1

Signature

variable

If P2 == date / time

Description

Length (byte)

Display name length

1

Display name

variable

Signature length

1

Signature

variable

If P2 == amount-join token

Description

Length (byte)

Token index

1

Signature length

1

Signature

variable

If P2 == amount-join value

Description

Length (byte)

Display name length

1

Display name

variable

Token index

1

Signature length

1

Signature

variable

If P2 == show raw field

Description

Length (byte)

Display name length

1

Display name

variable

Signature length

1

Signature

variable

Output data

None

GET CHALLENGE

Description

Sends a random 32-bit long value. Can prevent replay of signed payloads when the challenge is included in said payload.

Coding

Command

CLA

INS

P1

P2

LC

E0

20

00

00

00

Input data

None

Output data

Description

Length

Challenge value (BE)

4

PROVIDE TRUSTED NAME

Description

This command provides a trusted name (like an ENS domain) to be displayed during transactions in place of the address it is associated to. It shall be run just before a transaction/message involving the associated address that would be displayed on the device.

The signature is computed on the TLV payload (minus the signature obviously).

Coding

Command

CLA

INS

P1

P2

LC

E0

22

01 : first chunk

00 : following chunk

00

00

Input data

If P1 == first chunk

Description

Length (byte)

Payload length

2

TLV payload

variable

If P1 == following chunk

Description

Length (byte)

TLV payload

variable

Output data

None

PROVIDE ENUM VALUE

Command

CLA

INS

P1

P2

LC

E0

24

01 : first chunk

00 : following chunk

00

00

Input data

If P1 == first chunk

Description

Length (byte)

Payload length

2

TLV payload

variable

If P1 == following chunk

Description

Length (byte)

TLV payload

variable

Output data

None

TRANSACTION INFO

Command

CLA

INS

P1

P2

LC

E0

26

01 : first chunk

00 : following chunk

00

00

Input data

If P1 == first chunk

Description

Length (byte)

Payload length

2

TLV payload

variable

If P1 == following chunk

Description

Length (byte)

TLV payload

variable

Output data

None

TRANSACTION FIELD DESCRIPTION

Command

CLA

INS

P1

P2

LC

E0

28

01 : first chunk

00 : following chunk

00

00

Input data

If P1 == first chunk

Description

Length (byte)

Payload length

2

TLV payload

variable

If P1 == following chunk

Description

Length (byte)

TLV payload

variable

Output data

None

PROVIDE NETWORK CONFIGURATION

Description

This command handles the dynamic networks configuration, allowing to access funds without needing to update the application for each new network.

This configuration must be send before any access to a network and stays valid until a new config is sent. Up to 2 different configurations can be used. The targeted slot is configured automatically to the next available one.

The configuration is sent in TLV (Tag-Length-Value) mode, whereas the icon itself is send as raw bytes in dedicated chunk(s). The configuration doesn’t include the icon itself, but only its hash (sha256), and it is signed.

For the configuration, the following tags are supported:

Tag name

Tag value

Length (byte)

Value

STRUCTURE_TYPE

0x01

0x01

0x08 (for TYPE_DYNAMIC_NETWORK)

STRUCTURE_VERSION

0x02

0x01

0x01

BLOCKCHAIN_FAMILY

0x51

0x01

0x01 (for Ethereum)

CHAIN_ID

0x23

0x08

(uint64_t value)

NETWORK_NAME

0x52

variable (max 31)

string without '\0'

NETWORK_TICKER

0x24

variable (max 10)

string without '\0'

NETWORK_ICON_HASH

0x53

0x20

sha256 of the network icon, sent separately

SIGNATURE

0x15

variable

Signature of the TLV payload data

The signature is mandatory, and is computed on the full payload data, using CX_CURVE_SECP256K1.

Coding

Command

CLA

INS

P1

P2

LC

Le

E0

30

00

00 : Network configuration

variable

variable

01 : First chunk

00: Next chunks

01 : Network Icon

variable

variable

00

02 : Get Info

Input data

If P1 == Network configuration

Description

Length (byte)

TLV payload data

variable

If P1 == Network Icon

Description

Length (byte)

Icon data

variable

Notes:

  • No need to specify the full size because it is already included in the data header

  • The icon is not supported on Nano devices and the corresponding APDU will be ignored.

  • Depending on its size, it may be split on several chunks. The maximum allowed bitmap size is 1KB.

  • The data correspond the hex string generated by the script <SDK_PATH>/lib_nbgl/tools/icon2glyph.py, with parameter --hexbitmap

Output data

If P1 == Get Info

Description

Length (byte)

Number of networks

1

Networks chain_id

8

…​

8

Networks chain_id

8

Transport protocol

General transport description

Ledger APDUs requests and responses are encapsulated using a flexible protocol allowing to fragment large payloads over different underlying transport mechanisms.

The common transport header is defined as follows :

Description

Length

Communication channel ID (big endian)

2

Command tag

1

Packet sequence index (big endian)

2

Payload

var

The Communication channel ID allows commands multiplexing over the same physical link. It is not used for the time being, and should be set to 0101 to avoid compatibility issues with implementations ignoring a leading 00 byte.

The Command tag describes the message content. Use TAG_APDU (0x05) for standard APDU payloads, or TAG_PING (0x02) for a simple link test.

The Packet sequence index describes the current sequence for fragmented payloads. The first fragment index is 0x00.

APDU Command payload encoding

APDU Command payloads are encoded as follows :

Description

Length

APDU length (big endian)

2

APDU CLA

1

APDU INS

1

APDU P1

1

APDU P2

1

APDU length

1

Optional APDU data

var

APDU payload is encoded according to the APDU case

Case Number

Lc

Le

Case description

1

0

0

No data in either direction - L is set to 00

2

0

!0

Input Data present, no Output Data - L is set to Lc

3

!0

0

Output Data present, no Input Data - L is set to Le

4

!0

!0

Both Input and Output Data are present - L is set to Lc

APDU Response payload encoding

APDU Response payloads are encoded as follows :

Description

Length

APDU response length (big endian)

2

APDU response data and Status Word

var

USB mapping

Messages are exchanged with the dongle over HID endpoints over interrupt transfers, with each chunk being 64 bytes long. The HID Report ID is ignored.

BLE mapping

A similar encoding is used over BLE, without the Communication channel ID.

The application acts as a GATT server defining service UUID D973F2E0-B19E-11E2-9E96-0800200C9A66

When using this service, the client sends requests to the characteristic D973F2E2-B19E-11E2-9E96-0800200C9A66, and gets notified on the characteristic D973F2E1-B19E-11E2-9E96-0800200C9A66 after registering for it.

Requests are encoded using the standard BLE 20 bytes MTU size

Status Words

The following standard Status Words are returned for all APDUs - some specific Status Words can be used for specific commands and are mentioned in the command description.

'Status Words'

SW

Description

0x6001

Mode check fail

0x6501

TransactionType not supported

0x6502

Output buffer too small for chainId conversion

0x68xx

Internal error (Please report)

0x6982

Security status not satisfied (Canceled by user)

0x6983

Wrong Data length

0x6984

Plugin not installed

0x6985

Condition not satisfied

0x6A00

Error without info

0x6A80

Invalid data

0x6A84

Insufficient memory

0x6A88

Data not found

0x6B00

Incorrect parameter P1 or P2

0x6D00

Incorrect parameter INS

0x6E00

Incorrect parameter CLA

0x6Fxx

Technical problem (Internal error, please report)

0x9000

Normal ending of the command

0x911C

Command code not supported (i.e. Ledger-PKI not yet available)