From 966821aa1ab232e52c71d1ad7a7745bc9c6a08fb Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 19 Jan 2014 21:22:08 -0600 Subject: add cipher support to the commoncrypto backend --- .../hazmat/backends/commoncrypto/backend.py | 164 ++++++++++++++++++++- tests/hazmat/backends/test_commoncrypto.py | 31 ++++ 2 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 tests/hazmat/backends/test_commoncrypto.py diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py index 58e57efb..bdaff301 100644 --- a/cryptography/hazmat/backends/commoncrypto/backend.py +++ b/cryptography/hazmat/backends/commoncrypto/backend.py @@ -18,10 +18,16 @@ from collections import namedtuple from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends.interfaces import ( - HashBackend, HMACBackend, + HashBackend, HMACBackend, CipherBackend ) from cryptography.hazmat.bindings.commoncrypto.binding import Binding from cryptography.hazmat.primitives import interfaces +from cryptography.hazmat.primitives.ciphers.algorithms import ( + AES, Blowfish, TripleDES, ARC4 +) +from cryptography.hazmat.primitives.ciphers.modes import ( + CBC, CTR, ECB, OFB, CFB +) HashMethods = namedtuple( @@ -29,6 +35,7 @@ HashMethods = namedtuple( ) +@utils.register_interface(CipherBackend) @utils.register_interface(HashBackend) @utils.register_interface(HMACBackend) class Backend(object): @@ -42,6 +49,8 @@ class Backend(object): self._ffi = self._binding.ffi self._lib = self._binding.lib + self._cipher_registry = {} + self._register_default_ciphers() self._hash_mapping = { "md5": HashMethods( "CC_MD5_CTX *", self._lib.CC_MD5_Init, @@ -98,6 +107,159 @@ class Backend(object): def create_hmac_ctx(self, key, algorithm): return _HMACContext(self, key, algorithm) + def cipher_supported(self, cipher, mode): + try: + self._cipher_registry[type(cipher), type(mode)] + except KeyError: + return False + return True + + def create_symmetric_encryption_ctx(self, cipher, mode): + return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT) + + def create_symmetric_decryption_ctx(self, cipher, mode): + return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT) + + def register_cipher_adapter(self, cipher_cls, mode_cls, adapter): + if (cipher_cls, mode_cls) in self._cipher_registry: + raise ValueError("Duplicate registration for: {0} {1}".format( + cipher_cls, mode_cls) + ) + self._cipher_registry[cipher_cls, mode_cls] = adapter + + def _register_default_ciphers(self): + for mode_cls in [CBC, ECB, CFB, OFB, CTR]: + self.register_cipher_adapter( + AES, + mode_cls, + _GetCipherModeEnum() + ) + for mode_cls in [CBC, CFB, OFB]: + self.register_cipher_adapter( + TripleDES, + mode_cls, + _GetCipherModeEnum() + ) + for mode_cls in [CBC, CFB, OFB, ECB]: + self.register_cipher_adapter( + Blowfish, + mode_cls, + _GetCipherModeEnum() + ) + self.register_cipher_adapter( + ARC4, + type(None), + _GetCipherModeEnum() + ) + + +class _GetCipherModeEnum(object): + def __call__(self, backend, cipher, mode): + cipher_enum = { + AES: backend._lib.kCCAlgorithmAES128, + TripleDES: backend._lib.kCCAlgorithm3DES, + Blowfish: backend._lib.kCCAlgorithmBlowfish, + ARC4: backend._lib.kCCAlgorithmRC4, + }[type(cipher)] + + mode_enum = { + ECB: backend._lib.kCCModeECB, + CBC: backend._lib.kCCModeCBC, + CTR: backend._lib.kCCModeCTR, + CFB: backend._lib.kCCModeCFB, + OFB: backend._lib.kCCModeOFB, + type(None): backend._lib.kCCModeRC4, + }[type(mode)] + + return (cipher_enum, mode_enum) + + +@utils.register_interface(interfaces.CipherContext) +class _CipherContext(object): + _ENCRYPT = 0 # kCCEncrypt + _DECRYPT = 1 # kCCDecrypt + + def __init__(self, backend, cipher, mode, operation): + self._backend = backend + self._cipher = cipher + self._mode = mode + self._operation = operation + # bytes_processed is needed to work around rdar://15589470, a bug where + # kCCAlignmentError fails to raise when supplying non-block-aligned + # data. + self._bytes_processed = 0 + if (isinstance(cipher, interfaces.BlockCipherAlgorithm) and not + isinstance(mode, (OFB, CFB, CTR))): + self._byte_block_size = cipher.block_size // 8 + else: + self._byte_block_size = 1 + + registry = self._backend._cipher_registry + try: + adapter = registry[type(cipher), type(mode)] + except KeyError: + raise UnsupportedAlgorithm( + "cipher {0} in {1} mode is not supported " + "by this backend".format( + cipher.name, mode.name if mode else mode) + ) + + cipher_enum, mode_enum = adapter(self._backend, cipher, mode) + ctx = self._backend._ffi.new("CCCryptorRef *") + ctx[0] = self._backend._ffi.gc( + ctx[0], self._backend._lib.CCCryptorRelease + ) + + if isinstance(mode, interfaces.ModeWithInitializationVector): + iv_nonce = mode.initialization_vector + elif isinstance(mode, interfaces.ModeWithNonce): + iv_nonce = mode.nonce + else: + iv_nonce = self._backend._ffi.NULL + + if isinstance(mode, CTR): + mode_option = self._backend._lib.kCCModeOptionCTR_BE + else: + mode_option = 0 + + res = self._backend._lib.CCCryptorCreateWithMode( + operation, + mode_enum, cipher_enum, + self._backend._lib.ccNoPadding, iv_nonce, + cipher.key, len(cipher.key), + self._backend._ffi.NULL, 0, 0, mode_option, ctx) + assert res == self._backend._lib.kCCSuccess + + self._ctx = ctx + + def update(self, data): + # Count bytes processed to handle block alignment. + self._bytes_processed += len(data) + buf = self._backend._ffi.new( + "unsigned char[]", len(data) + self._byte_block_size - 1) + outlen = self._backend._ffi.new("size_t *") + res = self._backend._lib.CCCryptorUpdate( + self._ctx[0], data, len(data), buf, + len(data) + self._byte_block_size - 1, outlen) + assert res == self._backend._lib.kCCSuccess + return self._backend._ffi.buffer(buf)[:outlen[0]] + + def finalize(self): + # Raise error if block alignment is wrong. + if self._bytes_processed % self._byte_block_size: + raise ValueError( + "The length of the provided data is not a multiple of " + "the block length" + ) + buf = self._backend._ffi.new("unsigned char[]", self._byte_block_size) + outlen = self._backend._ffi.new("size_t *") + res = self._backend._lib.CCCryptorFinal( + self._ctx[0], buf, len(buf), outlen) + assert res == self._backend._lib.kCCSuccess + res = self._backend._lib.CCCryptorRelease(self._ctx[0]) + assert res == self._backend._lib.kCCSuccess + return self._backend._ffi.buffer(buf)[:outlen[0]] + @utils.register_interface(interfaces.HashContext) class _HashContext(object): diff --git a/tests/hazmat/backends/test_commoncrypto.py b/tests/hazmat/backends/test_commoncrypto.py new file mode 100644 index 00000000..1d768ec4 --- /dev/null +++ b/tests/hazmat/backends/test_commoncrypto.py @@ -0,0 +1,31 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pytest + +from cryptography.hazmat.bindings.commoncrypto.binding import Binding +from cryptography.hazmat.primitives.ciphers.algorithms import AES +from cryptography.hazmat.primitives.ciphers.modes import CBC + + +@pytest.mark.skipif(not Binding.is_available(), + reason="CommonCrypto not available") +class TestCommonCrypto(object): + def test_supports_cipher(self): + from cryptography.hazmat.backends.commoncrypto.backend import backend + assert backend.cipher_supported(None, None) is False + + def test_register_duplicate_cipher_adapter(self): + from cryptography.hazmat.backends.commoncrypto.backend import backend + with pytest.raises(ValueError): + backend.register_cipher_adapter(AES, CBC, None) -- cgit v1.2.3 From ed8d864f5412defe18d54dbf3c027120d4baeebe Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 19 Jan 2014 22:02:43 -0600 Subject: update changelog for commoncrypto backend --- docs/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 819b426a..c3859c25 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -6,7 +6,7 @@ Changelog **In development** -* Added :doc:`/hazmat/backends/commoncrypto` with hash and HMAC support. +* Added :doc:`/hazmat/backends/commoncrypto`. * Added initial :doc:`/hazmat/bindings/commoncrypto`. 0.1 - 2014-01-08 -- cgit v1.2.3 From a33a5e3e17140f8877aafa9db55f69008d4f42d2 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 19 Jan 2014 22:27:00 -0600 Subject: add error handler --- .../hazmat/backends/commoncrypto/backend.py | 23 ++++++++++++++++++---- tests/hazmat/backends/test_commoncrypto.py | 12 +++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py index bdaff301..314df0bd 100644 --- a/cryptography/hazmat/backends/commoncrypto/backend.py +++ b/cryptography/hazmat/backends/commoncrypto/backend.py @@ -152,6 +152,21 @@ class Backend(object): _GetCipherModeEnum() ) + def _check_response(self, response): + if response == self._lib.kCCSuccess: + return + elif response == self._lib.kCCAlignmentError: + # This error is not currently triggered due to a bug filed as + # rdar://15589470 + raise ValueError( + "The length of the provided data is not a multiple of " + "the block length" + ) + else: + raise SystemError( + "The backend returned an error. Code: {0}".format(response) + ) + class _GetCipherModeEnum(object): def __call__(self, backend, cipher, mode): @@ -228,7 +243,7 @@ class _CipherContext(object): self._backend._lib.ccNoPadding, iv_nonce, cipher.key, len(cipher.key), self._backend._ffi.NULL, 0, 0, mode_option, ctx) - assert res == self._backend._lib.kCCSuccess + self._backend._check_response(res) self._ctx = ctx @@ -241,7 +256,7 @@ class _CipherContext(object): res = self._backend._lib.CCCryptorUpdate( self._ctx[0], data, len(data), buf, len(data) + self._byte_block_size - 1, outlen) - assert res == self._backend._lib.kCCSuccess + self._backend._check_response(res) return self._backend._ffi.buffer(buf)[:outlen[0]] def finalize(self): @@ -255,9 +270,9 @@ class _CipherContext(object): outlen = self._backend._ffi.new("size_t *") res = self._backend._lib.CCCryptorFinal( self._ctx[0], buf, len(buf), outlen) - assert res == self._backend._lib.kCCSuccess + self._backend._check_response(res) res = self._backend._lib.CCCryptorRelease(self._ctx[0]) - assert res == self._backend._lib.kCCSuccess + self._backend._check_response(res) return self._backend._ffi.buffer(buf)[:outlen[0]] diff --git a/tests/hazmat/backends/test_commoncrypto.py b/tests/hazmat/backends/test_commoncrypto.py index 1d768ec4..8b353237 100644 --- a/tests/hazmat/backends/test_commoncrypto.py +++ b/tests/hazmat/backends/test_commoncrypto.py @@ -29,3 +29,15 @@ class TestCommonCrypto(object): from cryptography.hazmat.backends.commoncrypto.backend import backend with pytest.raises(ValueError): backend.register_cipher_adapter(AES, CBC, None) + + def test_handle_response(self): + from cryptography.hazmat.backends.commoncrypto.backend import backend + + with pytest.raises(ValueError): + backend._check_response(backend._lib.kCCAlignmentError) + + with pytest.raises(SystemError): + backend._check_response(backend._lib.kCCMemoryFailure) + + with pytest.raises(SystemError): + backend._check_response(backend._lib.kCCDecodeError) -- cgit v1.2.3 From 404769442e9dab3a0dab67d890cb7441b34fd007 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 19 Jan 2014 23:17:47 -0600 Subject: add comment and change gc for cipher context --- .../hazmat/backends/commoncrypto/backend.py | 25 ++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py index 314df0bd..8b48fecc 100644 --- a/cryptography/hazmat/backends/commoncrypto/backend.py +++ b/cryptography/hazmat/backends/commoncrypto/backend.py @@ -189,6 +189,15 @@ class _GetCipherModeEnum(object): return (cipher_enum, mode_enum) +def _release_cipher_ctx(ctx): + """ + Called by the garbage collector and used to safely dereference and + release the context. + """ + res = backend._lib.CCCryptorRelease(ctx[0]) + backend._check_response(res) + + @utils.register_interface(interfaces.CipherContext) class _CipherContext(object): _ENCRYPT = 0 # kCCEncrypt @@ -199,9 +208,15 @@ class _CipherContext(object): self._cipher = cipher self._mode = mode self._operation = operation - # bytes_processed is needed to work around rdar://15589470, a bug where - # kCCAlignmentError fails to raise when supplying non-block-aligned - # data. + # There is a bug in CommonCrypto where block ciphers do not raise + # kCCAlignmentError when finalizing if you supply non-block aligned + # data. To work around this we need to keep track of the block + # alignment ourselves, but only for alg+mode combos that require + # block alignment. OFB, CFB, and CTR make a block cipher algorithm + # into a stream cipher so we don't need to track them (and thus their + # block size is effectively 1 byte just like OpenSSL/CommonCrypto + # treat RC4 and other stream cipher block sizes). + # This bug has been filed as rdar://15589470 self._bytes_processed = 0 if (isinstance(cipher, interfaces.BlockCipherAlgorithm) and not isinstance(mode, (OFB, CFB, CTR))): @@ -221,9 +236,7 @@ class _CipherContext(object): cipher_enum, mode_enum = adapter(self._backend, cipher, mode) ctx = self._backend._ffi.new("CCCryptorRef *") - ctx[0] = self._backend._ffi.gc( - ctx[0], self._backend._lib.CCCryptorRelease - ) + ctx = self._backend._ffi.gc(ctx, self._release_cipher_ctx) if isinstance(mode, interfaces.ModeWithInitializationVector): iv_nonce = mode.initialization_vector -- cgit v1.2.3 From 263a3352159cac0073df7d23c9dbbc6c0749d9aa Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 20 Jan 2014 00:07:34 -0600 Subject: change cipher registry to store enums --- .../hazmat/backends/commoncrypto/backend.py | 64 ++++++++++------------ tests/hazmat/backends/test_commoncrypto.py | 5 +- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py index 8b48fecc..a9ffba4e 100644 --- a/cryptography/hazmat/backends/commoncrypto/backend.py +++ b/cryptography/hazmat/backends/commoncrypto/backend.py @@ -120,36 +120,52 @@ class Backend(object): def create_symmetric_decryption_ctx(self, cipher, mode): return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT) - def register_cipher_adapter(self, cipher_cls, mode_cls, adapter): + def register_cipher_adapter(self, cipher_cls, cipher_const, mode_cls, + mode_const): if (cipher_cls, mode_cls) in self._cipher_registry: raise ValueError("Duplicate registration for: {0} {1}".format( cipher_cls, mode_cls) ) - self._cipher_registry[cipher_cls, mode_cls] = adapter + self._cipher_registry[cipher_cls, mode_cls] = (cipher_const, + mode_const) def _register_default_ciphers(self): - for mode_cls in [CBC, ECB, CFB, OFB, CTR]: + for mode_cls, mode_const in [ + (CBC, self._lib.kCCModeCBC), (ECB, self._lib.kCCModeECB), + (CFB, self._lib.kCCModeCFB), (OFB, self._lib.kCCModeOFB), + (CTR, self._lib.kCCModeCTR) + ]: self.register_cipher_adapter( AES, + self._lib.kCCAlgorithmAES128, mode_cls, - _GetCipherModeEnum() + mode_const ) - for mode_cls in [CBC, CFB, OFB]: + for mode_cls, mode_const in [ + (CBC, self._lib.kCCModeCBC), (CFB, self._lib.kCCModeCFB), + (OFB, self._lib.kCCModeOFB), + ]: self.register_cipher_adapter( TripleDES, + self._lib.kCCAlgorithm3DES, mode_cls, - _GetCipherModeEnum() + mode_const ) - for mode_cls in [CBC, CFB, OFB, ECB]: + for mode_cls, mode_const in [ + (CBC, self._lib.kCCModeCBC), (ECB, self._lib.kCCModeECB), + (CFB, self._lib.kCCModeCFB), (OFB, self._lib.kCCModeOFB), + ]: self.register_cipher_adapter( Blowfish, + self._lib.kCCAlgorithmBlowfish, mode_cls, - _GetCipherModeEnum() + mode_const ) self.register_cipher_adapter( ARC4, + self._lib.kCCAlgorithmRC4, type(None), - _GetCipherModeEnum() + self._lib.kCCModeRC4 ) def _check_response(self, response): @@ -168,27 +184,6 @@ class Backend(object): ) -class _GetCipherModeEnum(object): - def __call__(self, backend, cipher, mode): - cipher_enum = { - AES: backend._lib.kCCAlgorithmAES128, - TripleDES: backend._lib.kCCAlgorithm3DES, - Blowfish: backend._lib.kCCAlgorithmBlowfish, - ARC4: backend._lib.kCCAlgorithmRC4, - }[type(cipher)] - - mode_enum = { - ECB: backend._lib.kCCModeECB, - CBC: backend._lib.kCCModeCBC, - CTR: backend._lib.kCCModeCTR, - CFB: backend._lib.kCCModeCFB, - OFB: backend._lib.kCCModeOFB, - type(None): backend._lib.kCCModeRC4, - }[type(mode)] - - return (cipher_enum, mode_enum) - - def _release_cipher_ctx(ctx): """ Called by the garbage collector and used to safely dereference and @@ -226,7 +221,7 @@ class _CipherContext(object): registry = self._backend._cipher_registry try: - adapter = registry[type(cipher), type(mode)] + cipher_enum, mode_enum = registry[type(cipher), type(mode)] except KeyError: raise UnsupportedAlgorithm( "cipher {0} in {1} mode is not supported " @@ -234,9 +229,8 @@ class _CipherContext(object): cipher.name, mode.name if mode else mode) ) - cipher_enum, mode_enum = adapter(self._backend, cipher, mode) ctx = self._backend._ffi.new("CCCryptorRef *") - ctx = self._backend._ffi.gc(ctx, self._release_cipher_ctx) + ctx = self._backend._ffi.gc(ctx, _release_cipher_ctx) if isinstance(mode, interfaces.ModeWithInitializationVector): iv_nonce = mode.initialization_vector @@ -284,8 +278,8 @@ class _CipherContext(object): res = self._backend._lib.CCCryptorFinal( self._ctx[0], buf, len(buf), outlen) self._backend._check_response(res) - res = self._backend._lib.CCCryptorRelease(self._ctx[0]) - self._backend._check_response(res) + # TODO: how do we release this here without causing a crash when + # the GC also releases it? return self._backend._ffi.buffer(buf)[:outlen[0]] diff --git a/tests/hazmat/backends/test_commoncrypto.py b/tests/hazmat/backends/test_commoncrypto.py index 8b353237..8022863c 100644 --- a/tests/hazmat/backends/test_commoncrypto.py +++ b/tests/hazmat/backends/test_commoncrypto.py @@ -28,7 +28,10 @@ class TestCommonCrypto(object): def test_register_duplicate_cipher_adapter(self): from cryptography.hazmat.backends.commoncrypto.backend import backend with pytest.raises(ValueError): - backend.register_cipher_adapter(AES, CBC, None) + backend.register_cipher_adapter( + AES, backend._lib.kCCAlgorithmAES128, + CBC, backend._lib.kCCModeCBC + ) def test_handle_response(self): from cryptography.hazmat.backends.commoncrypto.backend import backend -- cgit v1.2.3 From 5ab6a208c46f1de6e261646a0ad34482ea755922 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 20 Jan 2014 12:03:46 -0600 Subject: make register_cipher_adapter private and fix cryptorref release --- .../hazmat/backends/commoncrypto/backend.py | 21 +++++++++++---------- tests/hazmat/backends/test_commoncrypto.py | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py index a9ffba4e..cdce5f43 100644 --- a/cryptography/hazmat/backends/commoncrypto/backend.py +++ b/cryptography/hazmat/backends/commoncrypto/backend.py @@ -120,8 +120,8 @@ class Backend(object): def create_symmetric_decryption_ctx(self, cipher, mode): return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT) - def register_cipher_adapter(self, cipher_cls, cipher_const, mode_cls, - mode_const): + def _register_cipher_adapter(self, cipher_cls, cipher_const, mode_cls, + mode_const): if (cipher_cls, mode_cls) in self._cipher_registry: raise ValueError("Duplicate registration for: {0} {1}".format( cipher_cls, mode_cls) @@ -135,7 +135,7 @@ class Backend(object): (CFB, self._lib.kCCModeCFB), (OFB, self._lib.kCCModeOFB), (CTR, self._lib.kCCModeCTR) ]: - self.register_cipher_adapter( + self._register_cipher_adapter( AES, self._lib.kCCAlgorithmAES128, mode_cls, @@ -145,7 +145,7 @@ class Backend(object): (CBC, self._lib.kCCModeCBC), (CFB, self._lib.kCCModeCFB), (OFB, self._lib.kCCModeOFB), ]: - self.register_cipher_adapter( + self._register_cipher_adapter( TripleDES, self._lib.kCCAlgorithm3DES, mode_cls, @@ -155,13 +155,13 @@ class Backend(object): (CBC, self._lib.kCCModeCBC), (ECB, self._lib.kCCModeECB), (CFB, self._lib.kCCModeCFB), (OFB, self._lib.kCCModeOFB), ]: - self.register_cipher_adapter( + self._register_cipher_adapter( Blowfish, self._lib.kCCAlgorithmBlowfish, mode_cls, mode_const ) - self.register_cipher_adapter( + self._register_cipher_adapter( ARC4, self._lib.kCCAlgorithmRC4, type(None), @@ -189,8 +189,10 @@ def _release_cipher_ctx(ctx): Called by the garbage collector and used to safely dereference and release the context. """ - res = backend._lib.CCCryptorRelease(ctx[0]) - backend._check_response(res) + if ctx[0] != backend._ffi.NULL: + res = backend._lib.CCCryptorRelease(ctx[0]) + backend._check_response(res) + ctx[0] = backend._ffi.NULL @utils.register_interface(interfaces.CipherContext) @@ -278,8 +280,7 @@ class _CipherContext(object): res = self._backend._lib.CCCryptorFinal( self._ctx[0], buf, len(buf), outlen) self._backend._check_response(res) - # TODO: how do we release this here without causing a crash when - # the GC also releases it? + _release_cipher_ctx(self._ctx) return self._backend._ffi.buffer(buf)[:outlen[0]] diff --git a/tests/hazmat/backends/test_commoncrypto.py b/tests/hazmat/backends/test_commoncrypto.py index 8022863c..68ab6bc1 100644 --- a/tests/hazmat/backends/test_commoncrypto.py +++ b/tests/hazmat/backends/test_commoncrypto.py @@ -28,7 +28,7 @@ class TestCommonCrypto(object): def test_register_duplicate_cipher_adapter(self): from cryptography.hazmat.backends.commoncrypto.backend import backend with pytest.raises(ValueError): - backend.register_cipher_adapter( + backend._register_cipher_adapter( AES, backend._lib.kCCAlgorithmAES128, CBC, backend._lib.kCCModeCBC ) -- cgit v1.2.3 From b20689fc9b1841e8e190b80087c9857440dcc10a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 20 Jan 2014 17:00:37 -0600 Subject: style nit fix --- cryptography/hazmat/backends/commoncrypto/backend.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py index 8b9fe084..ed5376c8 100644 --- a/cryptography/hazmat/backends/commoncrypto/backend.py +++ b/cryptography/hazmat/backends/commoncrypto/backend.py @@ -133,8 +133,10 @@ class Backend(object): def _register_default_ciphers(self): for mode_cls, mode_const in [ - (CBC, self._lib.kCCModeCBC), (ECB, self._lib.kCCModeECB), - (CFB, self._lib.kCCModeCFB), (OFB, self._lib.kCCModeOFB), + (CBC, self._lib.kCCModeCBC), + (ECB, self._lib.kCCModeECB), + (CFB, self._lib.kCCModeCFB), + (OFB, self._lib.kCCModeOFB), (CTR, self._lib.kCCModeCTR) ]: self._register_cipher_adapter( @@ -154,8 +156,10 @@ class Backend(object): mode_const ) for mode_cls, mode_const in [ - (CBC, self._lib.kCCModeCBC), (ECB, self._lib.kCCModeECB), - (CFB, self._lib.kCCModeCFB), (OFB, self._lib.kCCModeOFB), + (CBC, self._lib.kCCModeCBC), + (ECB, self._lib.kCCModeECB), + (CFB, self._lib.kCCModeCFB), + (OFB, self._lib.kCCModeOFB) ]: self._register_cipher_adapter( Blowfish, -- cgit v1.2.3 From 8d7b96e8a4fb5766e72e45668dae9369f0070f35 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 20 Jan 2014 20:42:55 -0600 Subject: missed one. of course. --- cryptography/hazmat/backends/commoncrypto/backend.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py index ed5376c8..2d142569 100644 --- a/cryptography/hazmat/backends/commoncrypto/backend.py +++ b/cryptography/hazmat/backends/commoncrypto/backend.py @@ -146,7 +146,8 @@ class Backend(object): mode_const ) for mode_cls, mode_const in [ - (CBC, self._lib.kCCModeCBC), (CFB, self._lib.kCCModeCFB), + (CBC, self._lib.kCCModeCBC), + (CFB, self._lib.kCCModeCFB), (OFB, self._lib.kCCModeOFB), ]: self._register_cipher_adapter( -- cgit v1.2.3