diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/_cffi_src/hazmat_src/padding.c | 24 | ||||
-rw-r--r-- | src/_cffi_src/hazmat_src/padding.h | 1 | ||||
-rw-r--r-- | src/_cffi_src/openssl/dsa.py | 8 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/padding.py | 172 |
4 files changed, 150 insertions, 55 deletions
diff --git a/src/_cffi_src/hazmat_src/padding.c b/src/_cffi_src/hazmat_src/padding.c index 570bad9f..1a0c869d 100644 --- a/src/_cffi_src/hazmat_src/padding.c +++ b/src/_cffi_src/hazmat_src/padding.c @@ -37,3 +37,27 @@ uint8_t Cryptography_check_pkcs7_padding(const uint8_t *data, /* Now check the low bit to see if it's set */ return (mismatch & 1) == 0; } + +uint8_t Cryptography_check_ansix923_padding(const uint8_t *data, + uint8_t block_len) { + uint8_t i; + uint8_t pad_size = data[block_len - 1]; + uint8_t mismatch = 0; + /* Skip the first one with the pad size */ + for (i = 1; i < block_len; i++) { + unsigned int mask = Cryptography_constant_time_lt(i, pad_size); + uint8_t b = data[block_len - 1 - i]; + mismatch |= (mask & b); + } + + /* Check to make sure the pad_size was within the valid range. */ + mismatch |= ~Cryptography_constant_time_lt(0, pad_size); + mismatch |= Cryptography_constant_time_lt(block_len, pad_size); + + /* 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; +} diff --git a/src/_cffi_src/hazmat_src/padding.h b/src/_cffi_src/hazmat_src/padding.h index 4d218b1a..fb023c17 100644 --- a/src/_cffi_src/hazmat_src/padding.h +++ b/src/_cffi_src/hazmat_src/padding.h @@ -3,3 +3,4 @@ // repository for complete details. uint8_t Cryptography_check_pkcs7_padding(const uint8_t *, uint8_t); +uint8_t Cryptography_check_ansix923_padding(const uint8_t *, uint8_t); diff --git a/src/_cffi_src/openssl/dsa.py b/src/_cffi_src/openssl/dsa.py index 89511e44..69935c1d 100644 --- a/src/_cffi_src/openssl/dsa.py +++ b/src/_cffi_src/openssl/dsa.py @@ -22,10 +22,6 @@ typedef struct dsa_st { BIGNUM *pub_key; ...; } DSA; -typedef struct { - BIGNUM *r; - BIGNUM *s; -} DSA_SIG; """ FUNCTIONS = """ @@ -34,10 +30,6 @@ DSA *DSA_generate_parameters(int, unsigned char *, int, int *, unsigned long *, int DSA_generate_key(DSA *); DSA *DSA_new(void); void DSA_free(DSA *); -DSA_SIG *DSA_SIG_new(void); -void DSA_SIG_free(DSA_SIG *); -int i2d_DSA_SIG(const DSA_SIG *, unsigned char **); -DSA_SIG *d2i_DSA_SIG(DSA_SIG **, const unsigned char **, long); int DSA_size(const DSA *); int DSA_sign(int, const unsigned char *, int, unsigned char *, unsigned int *, DSA *); diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py index f6491eb7..77fb8f83 100644 --- a/src/cryptography/hazmat/primitives/padding.py +++ b/src/cryptography/hazmat/primitives/padding.py @@ -28,14 +28,75 @@ class PaddingContext(object): """ -class PKCS7(object): - def __init__(self, block_size): - if not (0 <= block_size < 256): - raise ValueError("block_size must be in range(0, 256).") +def _byte_padding_check(block_size): + if not (0 <= block_size < 256): + raise ValueError("block_size must be in range(0, 256).") + + if block_size % 8 != 0: + raise ValueError("block_size must be a multiple of 8.") + + +def _byte_padding_update(buffer_, data, block_size): + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + if not isinstance(data, bytes): + raise TypeError("data must be bytes.") + + buffer_ += data + + finished_blocks = len(buffer_) // (block_size // 8) + + result = buffer_[:finished_blocks * (block_size // 8)] + buffer_ = buffer_[finished_blocks * (block_size // 8):] + + return buffer_, result + + +def _byte_padding_pad(buffer_, block_size, paddingfn): + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + pad_size = block_size // 8 - len(buffer_) + return buffer_ + paddingfn(pad_size) + + +def _byte_unpadding_update(buffer_, data, block_size): + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + if not isinstance(data, bytes): + raise TypeError("data must be bytes.") - if block_size % 8 != 0: - raise ValueError("block_size must be a multiple of 8.") + buffer_ += data + finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0) + + result = buffer_[:finished_blocks * (block_size // 8)] + buffer_ = buffer_[finished_blocks * (block_size // 8):] + + return buffer_, result + + +def _byte_unpadding_check(buffer_, block_size, checkfn): + if buffer_ is None: + raise AlreadyFinalized("Context was already finalized.") + + if len(buffer_) != block_size // 8: + raise ValueError("Invalid padding bytes.") + + valid = checkfn(buffer_, block_size // 8) + + if not valid: + raise ValueError("Invalid padding bytes.") + + pad_size = six.indexbytes(buffer_, -1) + return buffer_[:-pad_size] + + +class PKCS7(object): + def __init__(self, block_size): + _byte_padding_check(block_size) self.block_size = block_size def padder(self): @@ -53,27 +114,16 @@ class _PKCS7PaddingContext(object): self._buffer = b"" def update(self, data): - if self._buffer is None: - raise AlreadyFinalized("Context was already finalized.") - - if not isinstance(data, bytes): - raise TypeError("data must be bytes.") - - self._buffer += data - - finished_blocks = len(self._buffer) // (self.block_size // 8) - - result = self._buffer[:finished_blocks * (self.block_size // 8)] - self._buffer = self._buffer[finished_blocks * (self.block_size // 8):] - + self._buffer, result = _byte_padding_update( + self._buffer, data, self.block_size) return result - def finalize(self): - if self._buffer is None: - raise AlreadyFinalized("Context was already finalized.") + def _padding(self, size): + return six.int2byte(size) * size - pad_size = self.block_size // 8 - len(self._buffer) - result = self._buffer + six.int2byte(pad_size) * pad_size + def finalize(self): + result = _byte_padding_pad( + self._buffer, self.block_size, self._padding) self._buffer = None return result @@ -86,39 +136,67 @@ class _PKCS7UnpaddingContext(object): self._buffer = b"" def update(self, data): - if self._buffer is None: - raise AlreadyFinalized("Context was already finalized.") + self._buffer, result = _byte_unpadding_update( + self._buffer, data, self.block_size) + return result + + def finalize(self): + result = _byte_unpadding_check( + self._buffer, self.block_size, + lib.Cryptography_check_pkcs7_padding) + self._buffer = None + return result - if not isinstance(data, bytes): - raise TypeError("data must be bytes.") - self._buffer += data +class ANSIX923(object): + def __init__(self, block_size): + _byte_padding_check(block_size) + self.block_size = block_size + + def padder(self): + return _ANSIX923PaddingContext(self.block_size) + + def unpadder(self): + return _ANSIX923UnpaddingContext(self.block_size) - finished_blocks = max( - len(self._buffer) // (self.block_size // 8) - 1, - 0 - ) - result = self._buffer[:finished_blocks * (self.block_size // 8)] - self._buffer = self._buffer[finished_blocks * (self.block_size // 8):] +@utils.register_interface(PaddingContext) +class _ANSIX923PaddingContext(object): + def __init__(self, block_size): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" + def update(self, data): + self._buffer, result = _byte_padding_update( + self._buffer, data, self.block_size) return result + def _padding(self, size): + return six.int2byte(0) * (size - 1) + six.int2byte(size) + def finalize(self): - if self._buffer is None: - raise AlreadyFinalized("Context was already finalized.") + result = _byte_padding_pad( + self._buffer, self.block_size, self._padding) + self._buffer = None + return result - if len(self._buffer) != self.block_size // 8: - raise ValueError("Invalid padding bytes.") - valid = lib.Cryptography_check_pkcs7_padding( - self._buffer, self.block_size // 8 - ) +@utils.register_interface(PaddingContext) +class _ANSIX923UnpaddingContext(object): + def __init__(self, block_size): + self.block_size = block_size + # TODO: more copies than necessary, we should use zero-buffer (#193) + self._buffer = b"" - if not valid: - raise ValueError("Invalid padding bytes.") + def update(self, data): + self._buffer, result = _byte_unpadding_update( + self._buffer, data, self.block_size) + return result - pad_size = six.indexbytes(self._buffer, -1) - res = self._buffer[:-pad_size] + def finalize(self): + result = _byte_unpadding_check( + self._buffer, self.block_size, + lib.Cryptography_check_ansix923_padding) self._buffer = None - return res + return result |