This document is explaining symmetric encryption on hardware devices, using deterministic hierarchy.
##Motivation
This is a section for a motivation.
We want to provide a symmetric encryption in the hardware wallet, where the key doesn't exit the device, and where the user might be forced to confirm the encryption/decryption on the display.
##Body
This is a section for a body. The title of the section should be changed
and the section can be split into multiple sections and subsections.
### Overview
The following data are sent to the hardware wallet:
* BIP 32 path
* key (that is beging asked on the device)
* value
* encrypt/decrypt direction
* should user confirm on encrypt?
* should user confirm on decrypt?
* optional IV
Value is what is actually being encrypted. The key for the encryption is constructed from the private key on the BIP address, the key displayed on the device, and the two informations about whether to ask for confirmation.
It is constructed in such a way, that different path, key or the confirm information will get a different encryption key and IV. So, you cannot "skip" the confirmation by using different input.
IV can be either manually set, or it is computed together with the key.
### Details
The details are best explained on a slightly simplified code from TREZOR Python emulator.
res = ''.join([aes.encrypt(value[i:i+16]) for i in range(0, len(value), 16)])
else:
res = ''.join([aes.decrypt(value[i:i+16]) for i in range(0, len(value), 16)])
return CipheredKeyValue(value=res)
````
````python
if len(value) % 16 > 0:
return Failure(message="Input length must be a multiple of 16")
````
First, the value is checked, if it is divisable into 16-byte blocks, since the symmetric cipher is block cipher. The application has to pad the blocks itself and ensure safety; for example, by using PKCS7.
The key, displayed on the device, is concatenated with either E1 or E0 and either D1 or D0, depending on whether the confirmation is enabled in a given direction.
res = ''.join([aes.encrypt(value[i:i+16]) for i in range(0, len(value), 16)])
else:
res = ''.join([aes.decrypt(value[i:i+16]) for i in range(0, len(value), 16)])
````
The result are the encrypted/decrypted blocks, concatenated together.
##References
This is a section for references such as links to other documents (BIP or SLIP)
or to reference implementations.
The algorithm is implemented in [TREZOR firmware](https://github.com/trezor/trezor-mcu/blob/master/firmware/fsm.c) (function `fsm_msgCipherKeyValue`) and its [emulator](https://github.com/trezor/trezor-emu/blob/master/trezor/machine.py#L781) (function `_cipher_keyvalue`).