diff options
| -rw-r--r-- | cryptography/hazmat/backends/__init__.py | 10 | ||||
| -rw-r--r-- | cryptography/hazmat/backends/commoncrypto/__init__.py | 17 | ||||
| -rw-r--r-- | cryptography/hazmat/backends/commoncrypto/backend.py | 125 | ||||
| -rw-r--r-- | docs/changelog.rst | 1 | ||||
| -rw-r--r-- | docs/hazmat/backends/common-crypto.rst | 20 | ||||
| -rw-r--r-- | docs/hazmat/backends/index.rst | 1 | ||||
| -rw-r--r-- | docs/spelling_wordlist.txt | 1 | 
7 files changed, 172 insertions, 3 deletions
| diff --git a/cryptography/hazmat/backends/__init__.py b/cryptography/hazmat/backends/__init__.py index 215aa4d3..cb1fee90 100644 --- a/cryptography/hazmat/backends/__init__.py +++ b/cryptography/hazmat/backends/__init__.py @@ -12,11 +12,15 @@  # limitations under the License.  from cryptography.hazmat.backends import openssl +from cryptography.hazmat.bindings.commoncrypto.binding import ( +    Binding as CCBinding +) +_ALL_BACKENDS = [openssl.backend] -_ALL_BACKENDS = [ -    openssl.backend -] +if CCBinding.is_available(): +    from cryptography.hazmat.backends import commoncrypto +    _ALL_BACKENDS.append(commoncrypto.backend)  def default_backend(): diff --git a/cryptography/hazmat/backends/commoncrypto/__init__.py b/cryptography/hazmat/backends/commoncrypto/__init__.py new file mode 100644 index 00000000..64a1c01c --- /dev/null +++ b/cryptography/hazmat/backends/commoncrypto/__init__.py @@ -0,0 +1,17 @@ +# 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. + +from cryptography.hazmat.backends.commoncrypto.backend import backend + + +__all__ = ["backend"] diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py new file mode 100644 index 00000000..3d98bf6b --- /dev/null +++ b/cryptography/hazmat/backends/commoncrypto/backend.py @@ -0,0 +1,125 @@ +# 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. + +from __future__ import absolute_import, division, print_function + +from collections import namedtuple + +from cryptography import utils +from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.backends.interfaces import ( +    HashBackend, +) +from cryptography.hazmat.bindings.commoncrypto.binding import Binding +from cryptography.hazmat.primitives import interfaces + + +HashMethods = namedtuple( +    "HashMethods", ["ctx", "hash_init", "hash_update", "hash_final"] +) + + +@utils.register_interface(HashBackend) +class Backend(object): +    """ +    CommonCrypto API wrapper. +    """ +    name = "commoncrypto" + +    def __init__(self): +        self._binding = Binding() +        self._ffi = self._binding.ffi +        self._lib = self._binding.lib + +        self._hash_mapping = { +            "md5": HashMethods( +                "CC_MD5_CTX *", self._lib.CC_MD5_Init, +                self._lib.CC_MD5_Update, self._lib.CC_MD5_Final +            ), +            "sha1": HashMethods( +                "CC_SHA1_CTX *", self._lib.CC_SHA1_Init, +                self._lib.CC_SHA1_Update, self._lib.CC_SHA1_Final +            ), +            "sha224": HashMethods( +                "CC_SHA256_CTX *", self._lib.CC_SHA224_Init, +                self._lib.CC_SHA224_Update, self._lib.CC_SHA224_Final +            ), +            "sha256": HashMethods( +                "CC_SHA256_CTX *", self._lib.CC_SHA256_Init, +                self._lib.CC_SHA256_Update, self._lib.CC_SHA256_Final +            ), +            "sha384": HashMethods( +                "CC_SHA512_CTX *", self._lib.CC_SHA384_Init, +                self._lib.CC_SHA384_Update, self._lib.CC_SHA384_Final +            ), +            "sha512": HashMethods( +                "CC_SHA512_CTX *", self._lib.CC_SHA512_Init, +                self._lib.CC_SHA512_Update, self._lib.CC_SHA512_Final +            ), +        } + +    def hash_supported(self, algorithm): +        try: +            self._hash_mapping[algorithm.name] +            return True +        except KeyError: +            return False + +    def create_hash_ctx(self, algorithm): +        return _HashContext(self, algorithm) + + +@utils.register_interface(interfaces.HashContext) +class _HashContext(object): +    def __init__(self, backend, algorithm, ctx=None): +        self.algorithm = algorithm +        self._backend = backend + +        if ctx is None: +            try: +                methods = self._backend._hash_mapping[self.algorithm.name] +            except KeyError: +                raise UnsupportedAlgorithm( +                    "{0} is not a supported hash on this backend".format( +                        algorithm.name) +                ) +            ctx = self._backend._ffi.new(methods.ctx) +            res = methods.hash_init(ctx) +            assert res == 1 + +        self._ctx = ctx + +    def copy(self): +        methods = self._backend._hash_mapping[self.algorithm.name] +        new_ctx = self._backend._ffi.new(methods.ctx) +        # CommonCrypto has no APIs for copying hashes, so we have to copy the +        # underlying struct. +        new_ctx[0] = self._ctx[0] + +        return _HashContext(self._backend, self.algorithm, ctx=new_ctx) + +    def update(self, data): +        methods = self._backend._hash_mapping[self.algorithm.name] +        res = methods.hash_update(self._ctx, data, len(data)) +        assert res == 1 + +    def finalize(self): +        methods = self._backend._hash_mapping[self.algorithm.name] +        buf = self._backend._ffi.new("unsigned char[]", +                                     self.algorithm.digest_size) +        res = methods.hash_final(buf, self._ctx) +        assert res == 1 +        return self._backend._ffi.buffer(buf)[:] + + +backend = Backend() diff --git a/docs/changelog.rst b/docs/changelog.rst index 289992f4..b0baf912 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -6,6 +6,7 @@ Changelog  **In development** +* Added CommonCrypto backend with hash support.  * Added initial CommonCrypto bindings.  0.1 - 2014-01-08 diff --git a/docs/hazmat/backends/common-crypto.rst b/docs/hazmat/backends/common-crypto.rst new file mode 100644 index 00000000..af2032b6 --- /dev/null +++ b/docs/hazmat/backends/common-crypto.rst @@ -0,0 +1,20 @@ +.. hazmat:: + +CommonCrypto Backend +==================== + +The `CommonCrypto`_ C library provided by Apple on OS X and iOS. + +.. currentmodule:: cryptography.hazmat.backends.commoncrypto.backend + +.. versionadded:: 0.2 + +.. data:: cryptography.hazmat.backends.commoncrypto.backend + +    This is the exposed API for the CommonCrypto backend. It has one public attribute. + +    .. attribute:: name + +        The string name of this backend: ``"commoncrypto"`` + +.. _`CommonCrypto`: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/Common%20Crypto.3cc.html diff --git a/docs/hazmat/backends/index.rst b/docs/hazmat/backends/index.rst index 06951281..22354f69 100644 --- a/docs/hazmat/backends/index.rst +++ b/docs/hazmat/backends/index.rst @@ -31,4 +31,5 @@ Individual Backends      :maxdepth: 1      openssl +    common-crypto      interfaces diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index 97356c24..75628ba5 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -14,6 +14,7 @@ hazmat  indistinguishability  introspectability  invariants +iOS  pickleable  plaintext  testability | 
