diff options
author | Alex Gaynor <alex.gaynor@gmail.com> | 2013-11-18 10:15:20 -0800 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2013-11-18 10:15:20 -0800 |
commit | 286433de03ad1f54f1f563922a327d22945b0733 (patch) | |
tree | 06ff5a0c238251e1e4c39e4af72b77d8706e1f52 | |
parent | dcc3f668c590bd0da898f331b968ed56d46936cf (diff) | |
download | cryptography-286433de03ad1f54f1f563922a327d22945b0733.tar.gz cryptography-286433de03ad1f54f1f563922a327d22945b0733.tar.bz2 cryptography-286433de03ad1f54f1f563922a327d22945b0733.zip |
Make it more constant time
-rw-r--r-- | cryptography/fernet.py | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/cryptography/fernet.py b/cryptography/fernet.py index 2a9f6a96..abd5e251 100644 --- a/cryptography/fernet.py +++ b/cryptography/fernet.py @@ -30,24 +30,39 @@ class InvalidToken(Exception): pass -ffi = cffi.FFI() -ffi.cdef(""" -bool constant_time_compare(uint8_t *, size_t, uint8_t *, size_t); +_ffi = cffi.FFI() +_ffi.cdef(""" +bool Cryptography_constant_time_compare(uint8_t *, size_t, uint8_t *, size_t); """) -lib = ffi.verify(""" +_lib = _ffi.verify(""" #include <stdbool.h> -bool constant_time_compare(uint8_t *a, size_t len_a, uint8_t *b, - size_t len_b) { + +/* Returns the value of the input with the most-significant-bit copied to all + of the bits. This relies on implementation details of computers with 2's + complement representations of integers, which is not required by the C + standard. */ +static uint8_t Cryptography_DUPLICATE_MSB_TO_ALL(uint8_t a) { + return (uint8_t)((int8_t)(a) >> (sizeof(int8_t) * 8 - 1)); +} + +bool Cryptography_constant_time_compare(uint8_t *a, size_t len_a, uint8_t *b, + size_t len_b) { size_t i = 0; - int result = 0; + uint8_t mismatch = 0; if (len_a != len_b) { return false; } for (i = 0; i < len_a; i++) { - result |= a[i] ^ b[i]; + mismatch |= a[i] ^ b[i]; } - return result == 0; + + /* Make sure any bits set are copied to the lowest bit */ + mismatch |= mismatch >> 4; + mismatch |= mismatch >> 2; + mismatch |= mismatch >> 1; + /* Now check the low bit to see if it's set */ + return (mismatch & 1) == 0; } """) @@ -112,8 +127,10 @@ class Fernet(object): h = HMAC(self.signing_key, hashes.SHA256(), self.backend) h.update(data[:-32]) hmac = h.finalize() - - if not lib.constant_time_compare(hmac, len(hmac), data[-32:], 32): + valid = _lib.Cryptography_constant_time_compare( + hmac, len(hmac), data[-32:], 32 + ) + if not valid: raise InvalidToken decryptor = Cipher( |