Orthrus dramatically simplifies the problems of providing a securely encrypted data store. There are no passwords or key material to manage. The act of pairing two cards together automatically creates all of the key material necessary to secure the store without any human action (other than initiating the paring process by pressing and holding a single button). The security offered by Orthrus is simple to explain and trivial to use. It's simply that if you have both of the cards, you have the data. If you have only one of them, then it is cryptographically opaque.
The first block of each card is reserved as a key storage block. The size of the volume reported to the USB host is determined by taking the smaller of the two card sizes, subtracting one and doubling that. The first block on each card contains a structure with the following:
- A magic constant compiled into the firmware to identify the card as belonging to an Orthrus volume.
- A flag bit identifying the card as either the "A" or "B" card (the cards can be inserted in either order and it should still work).
- A 64 byte volume ID.
- A 32 byte card key value.
- A 16 byte nonce value for the block tweaking (of which 12 bytes are used).
When the device is initialized (either when its inserted into a host with two cards already installed or when the second card is inserted), each of the key blocks is checked. If the magic value is wrong, or if the two volume ID values don't match or if there isn't one "A" and one "B" card, then the error light is turned on and the volume isn't mounted. This prevents cards inserted mistakenly from being corrupted. To bootstrap, there's a button on the board. If the button is pushed while the error light is on, then the two key blocks are initialized and the device made ready.
If the pre-initialization checks succeed, then the two card key values are shuffled together (in "A" "B" order) to make a 64 byte buffer. The two halves of this shuffled data is fed through AES CMAC with an all-zero key, with the two results concatenated together. The result of that becomes the new AES key and the CMAC is run over the two halves of the volume ID, again, with the two results concatenated together. The result of that becomes the AES key for the volume. At that point, the drive is ready.
To read and write individual blocks, AES XEX mode is used. The incoming block number in the request is translated by using the LSB to select either the "A" or "B" card. The rest of the block number is right-shifted once and 1 is added to make the physical block number for the card. The XEX mode uses a 16 byte nonce. The nonce consists of the first 12 bytes of the nonce value stored on the opposite card from the one being read or written, concatenated with the (logical) block number. The nonce is encrypted with the volume key to form the first "tweak" block. For each 16 byte AES block of the disk sector, the plaintext is XORed with the tweak block, then encrypted with AES ECB mode, then XORed again with the tweak block to form the ciphertext. Decryption is the same, except that an AES ECB decryption operation is performed in the middle (the tweak is still formed with an ECB encryption). After each block is processed, the tweak block is transformed into a new tweak block by multiplying it by 2 within a Galois Field of 2^128 (I confess I don't really understand GF math properly - I just read a bunch of examples and pseudocode on the net) and then is ready for the next 16 byte block.
In an earlier iteration of Orthrus, AES counter mode was used, which allowed us to precompute the cipher stream bytes for XORing with the card data, but counter mode has some cryptographic weaknesses that make up for the speed advantage that background precomputation affords. XEX mode can't be precomputed, and unfortunately gives us a 33% speed penalty, but is the mode used almost universally for whole-disk encryption (most implementations actually use XTS, but if the sector size is divisible by the encryption...Read more »