Skip to content

Latest commit

 

History

History
141 lines (101 loc) · 6.4 KB

app-encryption.md

File metadata and controls

141 lines (101 loc) · 6.4 KB

Ledger Signature

Each official app will be signed by a Ledger HSM. Given an ELF file, the HSM generates a .zip archive where the app's manifest is signed by the Ledger HSM using ECDSA. The manifest contains the SHA-256 hash of the app (code_start || code_end || data_start || data_end || code.bin || data.bin) as well as ELF addresses and the initial merkletree.

$ python host/hsm.py --elf-path app-eth.elf --app-path /tmp/app.zip
$ unzip -l /tmp/app.zip
Archive:  /tmp/app.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      160  2022-04-11 10:20   manifest.bin
       71  2022-04-11 10:20   manifest.hsm.sig
    45824  2022-04-11 10:20   code.bin
     4864  2022-04-11 10:20   data.bin
---------                     -------
    50919                     4 files
$ python host/app.py --show-manifest --app-path /tmp/app.zip
    manifest_version = 1
    name = u'Ethereum' (total 8)
    version = u'0.1' (total 3)
    app_hash = unhexlify('b89f8f1b30fbeec3c098c763868e9931158ddc8aad3e1f883e119e18f6412492')
    entrypoint = 0x000160B4
    bss = 0x0001D500
    code_start = 0x00010000
    code_end = 0x0001B300
    stack_start = 0x7FFF0000
    stack_end = 0x80000000
    data_start = 0x0001C200
    data_end = 0x0002D500
    mt_root_hash = unhexlify('010d84b42c7f8ed7b99942d13bb3bb8601538c990f5b775355f54430a037010d')
    mt_size = 19
    mt_last_entry = unhexlify('00d4010000000000')

Note that code.bin and data.bin aren't encrypted.

This .zip archive is generated once and available publicly for download by clients such as Ledger Live.

Device Signature

The VM dones't allow apps to be streamed until they are signed by the device itself. An app can be signed by the device if its manifest is signed by a Ledger HSM, as described previously (the Ledger HSM public key is embedded in the VM). Once the app is signed by the device, 3 files are added to the .zip archive: the code pages HMACs, the data pages HMACs and the ECDSA signature of the manifest.

Protocol overview

 Host                                  Device
──────────────────────────────────────────────

       Send the manifest signed by
       Ledger HSMs along its signature
      ──────────────────────────────►

       Ack
      ◄──────────────────────────────

       Send the 1st code page
      ──────────────────────────────►

       Receive encrypted HMAC
      ◄──────────────────────────────

       Send the 2nd code page
      ──────────────────────────────►

       Receive encrypted HMAC
      ◄──────────────────────────────

       ...

       Send the 1st data page
      ──────────────────────────────►

       Receive encrypted HMAC
      ◄──────────────────────────────

       Send the 2nd data page
      ──────────────────────────────►

       Receive encrypted HMAC
      ◄──────────────────────────────

       ...

       Receive the manifest signature
       along TmpAES
      ◄──────────────────────────────


──────────────────────────────────────────────

Key Derivation

In order to guarantee the uniqueness of keys used to authenticate each apps, 2 random seeds of 32 bytes are generated during the first launch of the VM by the device:

  • ECDSASeed: derives the private ECDSA key (DevPrivKey) to sign the manifest
  • AppHMACSeed: derives the KeyHMAC1 key

Secrets are derived from these seeds using SHA256(seed || app_hash) where app_hash is the hash of the application.

This derivation mechanism allows the VM to derive the same set of keys for a given app_hash.

Code and Data HMACs

Once the device has verified that the manifest's signature (generated by a Ledger HSM) is valid, a random AES key (TmpAES) is generated. This key is used to encrypt data sent to the host and will eventually be transmitted to the host if and only if the signature over the app manifest and the pages is valid.

Computing HMACs of code and data pages is done through the following steps. For each code and each data page:

  • The host sends the page;
  • The VM computes the HMAC-SHA256 page || addr || counter where the key is KeyHMAC1 and counter is 0;
  • The VM encrypts this HMAC using AES-256-CBC with the key TmpAES. The first iv is 0.
  • The VM sends the encrypted HMAC to the host.
  • The VM updates the SHA-256 context used to update app_hash.

Once each page has been received, the VM is able to compute app_hash. If the SHA-256 is equal to the one in the manifest, it means that the code and data pages sent by the host are valid. The VM sends the AES key TmpAES to the host, which eventually decrypt every HMAC.

The VM finally signs the manifest using DevPrivKey and sends the signature to the host.

Manifest Signature

The host is now able do decrypt all HMACs received from the device and generate the final .zip archive. As shown below, the .zip archive has now 3 additional files in the device folder: manifest.device.sig, code.mac.bin and data.mac.bin.

$ python host/app.py --speculos --app-path /tmp/app.zip
$ unzip -l app.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      160  2022-04-11 10:22   manifest.bin
       71  2022-04-11 10:22   manifest.hsm.sig
    45824  2022-04-11 10:22   code.bin
     4864  2022-04-11 10:22   data.bin
       71  2022-04-11 10:22   device/manifest.device.sig
     5728  2022-04-11 10:22   device/code.mac.bin
      608  2022-04-11 10:22   device/data.mac.bin
---------                     -------
    57326                     7 files

The app can now be streamed to the device as long as the VM isn't reinstalled (since it would lead to the generation of new seeds).