-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transport Encryption for Mitosis #18
base: master
Are you sure you want to change the base?
Conversation
The assumption is that AES-CMAC will be faster than HMAC-SHA256 because of the AES hardware acceleration, however testing doesn't seem to show any difference. AES-CMAC seems to *feel* faster, i.e. less perceived delay between button press and glyph appearing on-screen. During testing, it was noticed that transmit failures increased sharply as distance increased; this may be due to electromagnetic interference in the testing environment, or perhaps added processing delay on the receiver from AES-CMAC vs. HMAC-SHA256. Additional testing or perfomance diagnostics will be needed to rule out potential delays as a factor.
When reusing a mitosis_cmac_context, the plaintext_index and multiblock flag weren't being reset in mitosis_cmac_complete(), which caused calls subsequent to the first to generate incorrect hashes. This commit fixes this bug by resetting that state in the complete() call. Also added a test for this particular scenario to catch it in the future.
Are there plans to merge this pull request? My main concern about using the mitosis firmware is its lack of encryption. |
@jcharnetsky I'd be happy to have it merged, but I haven't seen any interest here. It looks like this project is dead. |
@rossica do you mind if we adapt your code for the Redox ? |
@LucidityCrash Feel free to, with the caveat that I don't know about the Redox project, and I make no guarantees about the fitness of this code for that purpose, nor any guarantees about the security of the adapted code. I recommend you have a cryptography expert review your adapted code. |
@rossica thank you for all your work on this! Took care of the one nagging concern I had about my Mitosis. |
Abstract
These changes implement transport encryption between the keyboard halves and the receiver.
Hard-coded encryption keys are used to protect randomly-generated keys which are used to encrypt the bulk of transfers. Periodically, new randomly-generated keys are created and used.
Hardware features of the NRF51 SoC are utilized where possible to reduce impact to battery life as much as possible.
Encryption Implementation
Authenticated encryption with associated data (AEAD) is used to secure data sent between the keyboard halves and the receiver, using AES in Counter mode (AES-CTR) for confidentiality, and Cipher-based Message Authentication Code (AES-CMAC) for authenticity. It is implemented as Encrypt-then-MAC.
AES was selected due to the presence of a hardware AES engine in the NRF51 SoC. CMAC was similarly selected over HMAC to take advantage of the hardware AES engine, and due to reduced memory footprint.
Key Generation
A single master seed value is used as input to Cipher-based Key Derivation Function (CKDF), along with per-device salt values, which generates the AES-128 key for AES-CTR encryption/decryption, the nonce value for AES-CTR, and the key for CMAC.
The keys generated from the master seed are used to establish a root-of-trust for data sent to the keyboard halves from the receiver, and are used as the initial transport keys for data sent from the keyboard halves to the receiver, until session keys are ready.
CKDF was selected over HKDF to take advantage of the hardware AES engine.
Over-the-Air Data Format
Data messages from the keyboard halves to the receiver use the following format:
The encrypted payload is the key matrix bitmap that has been encrypted using the keyboard's encryption key, and the counter value.
The key ID is used to distinguish which decryption key to use for a given keyboard half. The key ID is incremented for each rekeying the occurs. Key IDs are not unique between keyboard halves, and may be in use by both keyboard halves at the same time. Key IDs may also be reused by the same keyboard half, provided it is not the same as the current key ID.
The message authentication code is calculated over the encrypted payload, key ID, and counter value.
Rekeying messages from the receiver to a keyboard half use the following format:
The encrypted seed is 15 randomly-generated bytes that have been encrypted using the receiver's root-of-trust key.
The message authentication code is calculated over the encrypted seed and key ID.
Rekeying Process
As soon as the receiver powers on, the hardware random number generator (RNG) is enabled and begins generating seed values to be used to derive the transport session key, nonce, and CMAC key for each keyboard half. When the receiver receives a message from a keyboard half that is using the initial root-of-trust keys, the receiver responds with a randomly generated seed, encrypted using the receiver's root-of-trust key, and monotonically-incremented key ID. The encryption of the seed uses the new key ID as the counter value.
The receiver must guarantee the key ID is not the same as the current key ID and is not zero (0). Key ID 0 is reserved for the initial key, and can never be used to identify any other encryption key.
The receiver will also respond with a new encrypted seed after the keyboard half's counter value exceeds a chosen threshold.
Upon receiving the encrypted seed, the keyboard half verifies the MAC, then decrypts the seed and generates a new nonce, encryption key, and CMAC key using CKDF with the same salt values as in the initial key generation. All subsequent messages sent by the keyboard half will use the new key and key ID to distinguish them from the previous encryption key.
Testing
All cryptographic algorithms were tested and verified with officially-published test vectors, where available, and executed on an AMD64 system. It is assumed the hardware AES engine in NRF51 is correct, and it was not tested itself. The tests can be found in the
mitosis-crypto/test
directory.End to end testing was manually performed with Mitosis keyboard hardware using the
precompiled-crypto-*
firmware in theprecompiled
directory. Testing covered: typical start up; resetting the receiver and not the keyboard halves; resetting the keyboard halves and not the receiver; and rekeying of a keyboard half once its counter exceeded a threshold. In all cases, the keyboard continued operation with no apparent loss of key presses or delay.Other Changes
During development, it was discovered that the main loop on the receiver was very sensitive to timing disruptions and would de-sync with the UART, causing the SoC to reset. This was particularly frequent when generating the random seed values, and computing the new encryption keys for rekeying. Decryption of messages didn't seem to affect it, however.
In order to solve this problem, the UART code was changed from a polling-based approach to a callback-based approach. The UART callback executes at the highest priority, so it supercedes any cryptographic work going on in the main loop, and can interrupt the Gazell callbacks.
This removes most of the timing sensitivity from the UART code, because it always takes priority. Responsiveness is unaffected, and it simplifies the UART code.
Miscellaneous Future Improvements
Various thoughts and features I would like to have, but aren't necessary and I don't have time for:
Addresses #12