diff options
Diffstat (limited to 'cryptography/hazmat')
| -rw-r--r-- | cryptography/hazmat/backends/openssl/backend.py | 11 | ||||
| -rw-r--r-- | cryptography/hazmat/bindings/commoncrypto/__init__.py | 12 | ||||
| -rw-r--r-- | cryptography/hazmat/bindings/commoncrypto/binding.py | 47 | ||||
| -rw-r--r-- | cryptography/hazmat/bindings/commoncrypto/common_digest.py | 67 | ||||
| -rw-r--r-- | cryptography/hazmat/bindings/commoncrypto/common_hmac.py | 46 | ||||
| -rw-r--r-- | cryptography/hazmat/bindings/openssl/binding.py | 81 | ||||
| -rw-r--r-- | cryptography/hazmat/bindings/openssl/err.py | 50 | ||||
| -rw-r--r-- | cryptography/hazmat/bindings/utils.py | 86 | ||||
| -rw-r--r-- | cryptography/hazmat/primitives/ciphers/algorithms.py | 15 | ||||
| -rw-r--r-- | cryptography/hazmat/primitives/ciphers/base.py | 3 | ||||
| -rw-r--r-- | cryptography/hazmat/primitives/ciphers/modes.py | 33 | ||||
| -rw-r--r-- | cryptography/hazmat/primitives/constant_time.py | 7 | ||||
| -rw-r--r-- | cryptography/hazmat/primitives/interfaces.py | 7 | ||||
| -rw-r--r-- | cryptography/hazmat/primitives/padding.py | 7 | 
14 files changed, 372 insertions, 100 deletions
| diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 089684ad..ec2824d1 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -22,7 +22,7 @@ from cryptography.hazmat.backends.interfaces import (  )  from cryptography.hazmat.primitives import interfaces  from cryptography.hazmat.primitives.ciphers.algorithms import ( -    AES, Blowfish, Camellia, CAST5, TripleDES, ARC4, +    AES, Blowfish, Camellia, TripleDES, ARC4,  )  from cryptography.hazmat.primitives.ciphers.modes import (      CBC, CTR, ECB, OFB, CFB, GCM, @@ -43,7 +43,11 @@ class Backend(object):          self._ffi = self._binding.ffi          self._lib = self._binding.lib +        # adds all ciphers/digests for EVP          self._lib.OpenSSL_add_all_algorithms() +        # registers available SSL/TLS ciphers and digests +        self._lib.SSL_library_init() +        # loads error strings for libcrypto and libssl functions          self._lib.SSL_load_error_strings()          self._cipher_registry = {} @@ -149,11 +153,6 @@ class Backend(object):                  GetCipherByName("bf-{mode.name}")              )          self.register_cipher_adapter( -            CAST5, -            ECB, -            GetCipherByName("cast5-ecb") -        ) -        self.register_cipher_adapter(              ARC4,              type(None),              GetCipherByName("rc4") diff --git a/cryptography/hazmat/bindings/commoncrypto/__init__.py b/cryptography/hazmat/bindings/commoncrypto/__init__.py new file mode 100644 index 00000000..55c925c6 --- /dev/null +++ b/cryptography/hazmat/bindings/commoncrypto/__init__.py @@ -0,0 +1,12 @@ +# 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. diff --git a/cryptography/hazmat/bindings/commoncrypto/binding.py b/cryptography/hazmat/bindings/commoncrypto/binding.py new file mode 100644 index 00000000..9c1af40a --- /dev/null +++ b/cryptography/hazmat/bindings/commoncrypto/binding.py @@ -0,0 +1,47 @@ +# 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 + +import sys + +from cryptography.hazmat.bindings.utils import build_ffi + + +class Binding(object): +    """ +    CommonCrypto API wrapper. +    """ +    _module_prefix = "cryptography.hazmat.bindings.commoncrypto." +    _modules = [ +        "common_digest", +        "common_hmac", +    ] + +    ffi = None +    lib = None + +    def __init__(self): +        self._ensure_ffi_initialized() + +    @classmethod +    def _ensure_ffi_initialized(cls): +        if cls.ffi is not None and cls.lib is not None: +            return + +        cls.ffi, cls.lib = build_ffi(cls._module_prefix, cls._modules, +                                     "", "", []) + +    @classmethod +    def is_available(cls): +        return sys.platform == "darwin" diff --git a/cryptography/hazmat/bindings/commoncrypto/common_digest.py b/cryptography/hazmat/bindings/commoncrypto/common_digest.py new file mode 100644 index 00000000..ec0fcc92 --- /dev/null +++ b/cryptography/hazmat/bindings/commoncrypto/common_digest.py @@ -0,0 +1,67 @@ +# 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. + +INCLUDES = """ +#include <CommonCrypto/CommonDigest.h> +""" + +TYPES = """ +typedef uint32_t CC_LONG; +typedef uint64_t CC_LONG64; +typedef struct CC_MD5state_st { +    ...; +} CC_MD5_CTX; +typedef struct CC_SHA1state_st { +    ...; +} CC_SHA1_CTX; +typedef struct CC_SHA256state_st { +    ...; +} CC_SHA256_CTX; +typedef struct CC_SHA512state_st { +    ...; +} CC_SHA512_CTX; +""" + +FUNCTIONS = """ +int CC_MD5_Init(CC_MD5_CTX *); +int CC_MD5_Update(CC_MD5_CTX *, const void *, CC_LONG); +int CC_MD5_Final(unsigned char *, CC_MD5_CTX *); + +int CC_SHA1_Init(CC_SHA1_CTX *); +int CC_SHA1_Update(CC_SHA1_CTX *, const void *, CC_LONG); +int CC_SHA1_Final(unsigned char *, CC_SHA1_CTX *); + +int CC_SHA224_Init(CC_SHA256_CTX *); +int CC_SHA224_Update(CC_SHA256_CTX *, const void *, CC_LONG); +int CC_SHA224_Final(unsigned char *, CC_SHA256_CTX *); + +int CC_SHA256_Init(CC_SHA256_CTX *); +int CC_SHA256_Update(CC_SHA256_CTX *, const void *, CC_LONG); +int CC_SHA256_Final(unsigned char *, CC_SHA256_CTX *); + +int CC_SHA384_Init(CC_SHA512_CTX *); +int CC_SHA384_Update(CC_SHA512_CTX *, const void *, CC_LONG); +int CC_SHA384_Final(unsigned char *, CC_SHA512_CTX *); + +int CC_SHA512_Init(CC_SHA512_CTX *); +int CC_SHA512_Update(CC_SHA512_CTX *, const void *, CC_LONG); +int CC_SHA512_Final(unsigned char *, CC_SHA512_CTX *); +""" + +MACROS = """ +""" + +CUSTOMIZATIONS = """ +""" + +CONDITIONAL_NAMES = {} diff --git a/cryptography/hazmat/bindings/commoncrypto/common_hmac.py b/cryptography/hazmat/bindings/commoncrypto/common_hmac.py new file mode 100644 index 00000000..a4bf9009 --- /dev/null +++ b/cryptography/hazmat/bindings/commoncrypto/common_hmac.py @@ -0,0 +1,46 @@ +# 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. + +INCLUDES = """ +#include <CommonCrypto/CommonHMAC.h> +""" + +TYPES = """ +typedef struct { +    ...; +} CCHmacContext; +enum { +    kCCHmacAlgSHA1, +    kCCHmacAlgMD5, +    kCCHmacAlgSHA256, +    kCCHmacAlgSHA384, +    kCCHmacAlgSHA512, +    kCCHmacAlgSHA224 +}; +typedef uint32_t CCHmacAlgorithm; +""" + +FUNCTIONS = """ +void CCHmacInit(CCHmacContext *, CCHmacAlgorithm, const void *, size_t); +void CCHmacUpdate(CCHmacContext *, const void *, size_t); +void CCHmacFinal(CCHmacContext *, void *); + +""" + +MACROS = """ +""" + +CUSTOMIZATIONS = """ +""" + +CONDITIONAL_NAMES = {} diff --git a/cryptography/hazmat/bindings/openssl/binding.py b/cryptography/hazmat/bindings/openssl/binding.py index 3b874466..2419044f 100644 --- a/cryptography/hazmat/bindings/openssl/binding.py +++ b/cryptography/hazmat/bindings/openssl/binding.py @@ -13,9 +13,8 @@  from __future__ import absolute_import, division, print_function -import sys +from cryptography.hazmat.bindings.utils import build_ffi -import cffi  _OSX_PRE_INCLUDE = """  #ifdef __APPLE__ @@ -39,20 +38,6 @@ _OSX_POST_INCLUDE = """  class Binding(object):      """      OpenSSL API wrapper. - -    Modules listed in the ``_modules`` listed should have the following -    attributes: - -    * ``INCLUDES``: A string containg C includes. -    * ``TYPES``: A string containing C declarations for types. -    * ``FUNCTIONS``: A string containing C declarations for functions. -    * ``MACROS``: A string containing C declarations for any macros. -    * ``CUSTOMIZATIONS``: A string containing arbitrary top-level C code, this -        can be used to do things like test for a define and provide an -        alternate implementation based on that. -    * ``CONDITIONAL_NAMES``: A dict mapping strings of condition names from the -        library to a list of names which will not be present without the -        condition.      """      _module_prefix = "cryptography.hazmat.bindings.openssl."      _modules = [ @@ -93,61 +78,13 @@ class Binding(object):          if cls.ffi is not None and cls.lib is not None:              return -        ffi = cffi.FFI() -        includes = [] -        functions = [] -        macros = [] -        customizations = [] -        for name in cls._modules: -            module_name = cls._module_prefix + name -            __import__(module_name) -            module = sys.modules[module_name] - -            ffi.cdef(module.TYPES) - -            macros.append(module.MACROS) -            functions.append(module.FUNCTIONS) -            includes.append(module.INCLUDES) -            customizations.append(module.CUSTOMIZATIONS) - -        # loop over the functions & macros after declaring all the types -        # so we can set interdependent types in different files and still -        # have them all defined before we parse the funcs & macros -        for func in functions: -            ffi.cdef(func) -        for macro in macros: -            ffi.cdef(macro) - -        # We include functions here so that if we got any of their definitions -        # wrong, the underlying C compiler will explode. In C you are allowed -        # to re-declare a function if it has the same signature. That is: -        #   int foo(int); -        #   int foo(int); -        # is legal, but the following will fail to compile: -        #   int foo(int); -        #   int foo(short); - -        lib = ffi.verify( -            source="\n".join( -                [_OSX_PRE_INCLUDE] + -                includes + -                [_OSX_POST_INCLUDE] + -                functions + -                customizations -            ), -            libraries=["crypto", "ssl"], -        ) - -        for name in cls._modules: -            module_name = cls._module_prefix + name -            module = sys.modules[module_name] -            for condition, names in module.CONDITIONAL_NAMES.items(): -                if not getattr(lib, condition): -                    for name in names: -                        delattr(lib, name) - -        res = lib.Cryptography_add_osrandom_engine() +        cls.ffi, cls.lib = build_ffi(cls._module_prefix, cls._modules, +                                     _OSX_PRE_INCLUDE, _OSX_POST_INCLUDE, +                                     ["crypto", "ssl"]) +        res = cls.lib.Cryptography_add_osrandom_engine()          assert res == 1 -        cls.ffi = ffi -        cls.lib = lib +    @classmethod +    def is_available(cls): +        # OpenSSL is the only binding so for now it must always be available +        return True diff --git a/cryptography/hazmat/bindings/openssl/err.py b/cryptography/hazmat/bindings/openssl/err.py index 6b2a77b1..1b66bd2a 100644 --- a/cryptography/hazmat/bindings/openssl/err.py +++ b/cryptography/hazmat/bindings/openssl/err.py @@ -22,23 +22,67 @@ struct ERR_string_data_st {  };  typedef struct ERR_string_data_st ERR_STRING_DATA; +static const int ASN1_R_BAD_PASSWORD_READ; +  static const int ERR_LIB_EVP;  static const int ERR_LIB_PEM; -static const int EVP_F_EVP_ENCRYPTFINAL_EX;  static const int EVP_F_EVP_DECRYPTFINAL_EX; +static const int EVP_F_EVP_ENCRYPTFINAL_EX;  static const int EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH; -static const int PEM_F_PEM_READ_BIO_PRIVATEKEY;  static const int PEM_F_D2I_PKCS8PRIVATEKEY_BIO; +static const int PEM_F_D2I_PKCS8PRIVATEKEY_BIO; +static const int PEM_F_D2I_PKCS8PRIVATEKEY_FP; +static const int PEM_F_DO_PK8PKEY; +static const int PEM_F_DO_PK8PKEY_FP; +static const int PEM_F_LOAD_IV; +static const int PEM_F_PEM_ASN1_READ; +static const int PEM_F_PEM_ASN1_READ_BIO; +static const int PEM_F_PEM_ASN1_WRITE; +static const int PEM_F_PEM_ASN1_WRITE_BIO; +static const int PEM_F_PEM_DEF_CALLBACK; +static const int PEM_F_PEM_DO_HEADER; +static const int PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY; +static const int PEM_F_PEM_GET_EVP_CIPHER_INFO; +static const int PEM_F_PEM_PK8PKEY; +static const int PEM_F_PEM_READ; +static const int PEM_F_PEM_READ_BIO; +static const int PEM_F_PEM_READ_BIO_PRIVATEKEY; +static const int PEM_F_PEM_READ_BIO_PRIVATEKEY; +static const int PEM_F_PEM_READ_PRIVATEKEY; +static const int PEM_F_PEM_SEALFINAL; +static const int PEM_F_PEM_SEALINIT; +static const int PEM_F_PEM_SIGNFINAL; +static const int PEM_F_PEM_WRITE; +static const int PEM_F_PEM_WRITE_BIO; +static const int PEM_F_PEM_X509_INFO_READ; +static const int PEM_F_PEM_X509_INFO_READ_BIO; +static const int PEM_F_PEM_X509_INFO_WRITE_BIO; +static const int PEM_R_BAD_BASE64_DECODE; +static const int PEM_R_BAD_DECRYPT; +static const int PEM_R_BAD_END_LINE; +static const int PEM_R_BAD_IV_CHARS;  static const int PEM_R_BAD_PASSWORD_READ; -static const int ASN1_R_BAD_PASSWORD_READ; +static const int PEM_R_BAD_PASSWORD_READ; +static const int PEM_R_ERROR_CONVERTING_PRIVATE_KEY; +static const int PEM_R_NOT_DEK_INFO; +static const int PEM_R_NOT_ENCRYPTED; +static const int PEM_R_NOT_PROC_TYPE; +static const int PEM_R_NO_START_LINE; +static const int PEM_R_PROBLEMS_GETTING_PASSWORD; +static const int PEM_R_PUBLIC_KEY_NO_RSA; +static const int PEM_R_READ_KEY; +static const int PEM_R_SHORT_HEADER; +static const int PEM_R_UNSUPPORTED_CIPHER; +static const int PEM_R_UNSUPPORTED_ENCRYPTION;  """  FUNCTIONS = """  void ERR_load_crypto_strings(void); +void ERR_load_SSL_strings(void);  void ERR_free_strings(void);  char* ERR_error_string(unsigned long, char *);  void ERR_error_string_n(unsigned long, char *, size_t); diff --git a/cryptography/hazmat/bindings/utils.py b/cryptography/hazmat/bindings/utils.py new file mode 100644 index 00000000..9cc05506 --- /dev/null +++ b/cryptography/hazmat/bindings/utils.py @@ -0,0 +1,86 @@ +# 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 + +import sys + +import cffi + + +def build_ffi(module_prefix, modules, pre_include, post_include, libraries): +    """ +    Modules listed in ``modules`` should have the following attributes: + +    * ``INCLUDES``: A string containing C includes. +    * ``TYPES``: A string containing C declarations for types. +    * ``FUNCTIONS``: A string containing C declarations for functions. +    * ``MACROS``: A string containing C declarations for any macros. +    * ``CUSTOMIZATIONS``: A string containing arbitrary top-level C code, this +        can be used to do things like test for a define and provide an +        alternate implementation based on that. +    * ``CONDITIONAL_NAMES``: A dict mapping strings of condition names from the +        library to a list of names which will not be present without the +        condition. +    """ +    ffi = cffi.FFI() +    types = [] +    includes = [] +    functions = [] +    macros = [] +    customizations = [] +    for name in modules: +        module_name = module_prefix + name +        __import__(module_name) +        module = sys.modules[module_name] + +        types.append(module.TYPES) +        macros.append(module.MACROS) +        functions.append(module.FUNCTIONS) +        includes.append(module.INCLUDES) +        customizations.append(module.CUSTOMIZATIONS) + +    # loop over the functions & macros after declaring all the types +    # so we can set interdependent types in different files and still +    # have them all defined before we parse the funcs & macros +    ffi.cdef("\n".join(types + functions + macros)) + +    # We include functions here so that if we got any of their definitions +    # wrong, the underlying C compiler will explode. In C you are allowed +    # to re-declare a function if it has the same signature. That is: +    #   int foo(int); +    #   int foo(int); +    # is legal, but the following will fail to compile: +    #   int foo(int); +    #   int foo(short); +    lib = ffi.verify( +        source="\n".join( +            [pre_include] + +            includes + +            [post_include] + +            functions + +            customizations +        ), +        libraries=libraries, +        ext_package="cryptography", +    ) + +    for name in modules: +        module_name = module_prefix + name +        module = sys.modules[module_name] +        for condition, names in module.CONDITIONAL_NAMES.items(): +            if not getattr(lib, condition): +                for name in names: +                    delattr(lib, name) + +    return ffi, lib diff --git a/cryptography/hazmat/primitives/ciphers/algorithms.py b/cryptography/hazmat/primitives/ciphers/algorithms.py index a5cfce92..19cf1920 100644 --- a/cryptography/hazmat/primitives/ciphers/algorithms.py +++ b/cryptography/hazmat/primitives/ciphers/algorithms.py @@ -90,21 +90,6 @@ class Blowfish(object):          return len(self.key) * 8 -@utils.register_interface(interfaces.BlockCipherAlgorithm) -@utils.register_interface(interfaces.CipherAlgorithm) -class CAST5(object): -    name = "CAST5" -    block_size = 64 -    key_sizes = frozenset(range(40, 129, 8)) - -    def __init__(self, key): -        self.key = _verify_key_size(self, key) - -    @property -    def key_size(self): -        return len(self.key) * 8 - -  @utils.register_interface(interfaces.CipherAlgorithm)  class ARC4(object):      name = "RC4" diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py index 1da0802c..d366e4cf 100644 --- a/cryptography/hazmat/primitives/ciphers/base.py +++ b/cryptography/hazmat/primitives/ciphers/base.py @@ -25,6 +25,9 @@ class Cipher(object):          if not isinstance(algorithm, interfaces.CipherAlgorithm):              raise TypeError("Expected interface of interfaces.CipherAlgorithm") +        if mode is not None: +            mode.validate_for_algorithm(algorithm) +          self.algorithm = algorithm          self.mode = mode          self._backend = backend diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py index ab8501c6..739f23dd 100644 --- a/cryptography/hazmat/primitives/ciphers/modes.py +++ b/cryptography/hazmat/primitives/ciphers/modes.py @@ -25,11 +25,20 @@ class CBC(object):      def __init__(self, initialization_vector):          self.initialization_vector = initialization_vector +    def validate_for_algorithm(self, algorithm): +        if len(self.initialization_vector) * 8 != algorithm.block_size: +            raise ValueError("Invalid iv size ({0}) for {1}".format( +                len(self.initialization_vector), self.name +            )) +  @utils.register_interface(interfaces.Mode)  class ECB(object):      name = "ECB" +    def validate_for_algorithm(self, algorithm): +        pass +  @utils.register_interface(interfaces.Mode)  @utils.register_interface(interfaces.ModeWithInitializationVector) @@ -39,6 +48,12 @@ class OFB(object):      def __init__(self, initialization_vector):          self.initialization_vector = initialization_vector +    def validate_for_algorithm(self, algorithm): +        if len(self.initialization_vector) * 8 != algorithm.block_size: +            raise ValueError("Invalid iv size ({0}) for {1}".format( +                len(self.initialization_vector), self.name +            )) +  @utils.register_interface(interfaces.Mode)  @utils.register_interface(interfaces.ModeWithInitializationVector) @@ -48,6 +63,12 @@ class CFB(object):      def __init__(self, initialization_vector):          self.initialization_vector = initialization_vector +    def validate_for_algorithm(self, algorithm): +        if len(self.initialization_vector) * 8 != algorithm.block_size: +            raise ValueError("Invalid iv size ({0}) for {1}".format( +                len(self.initialization_vector), self.name +            )) +  @utils.register_interface(interfaces.Mode)  @utils.register_interface(interfaces.ModeWithNonce) @@ -57,6 +78,12 @@ class CTR(object):      def __init__(self, nonce):          self.nonce = nonce +    def validate_for_algorithm(self, algorithm): +        if len(self.nonce) * 8 != algorithm.block_size: +            raise ValueError("Invalid nonce size ({0}) for {1}".format( +                len(self.nonce), self.name +            )) +  @utils.register_interface(interfaces.Mode)  @utils.register_interface(interfaces.ModeWithInitializationVector) @@ -65,6 +92,9 @@ class GCM(object):      name = "GCM"      def __init__(self, initialization_vector, tag=None): +        # len(initialization_vector) must in [1, 2 ** 64), but it's impossible +        # to actually construct a bytes object that large, so we don't check +        # for it          if tag is not None and len(tag) < 4:              raise ValueError(                  "Authentication tag must be 4 bytes or longer" @@ -72,3 +102,6 @@ class GCM(object):          self.initialization_vector = initialization_vector          self.tag = tag + +    def validate_for_algorithm(self, algorithm): +        pass diff --git a/cryptography/hazmat/primitives/constant_time.py b/cryptography/hazmat/primitives/constant_time.py index 6502803e..e88a0d95 100644 --- a/cryptography/hazmat/primitives/constant_time.py +++ b/cryptography/hazmat/primitives/constant_time.py @@ -23,7 +23,8 @@ _ffi.cdef("""  uint8_t Cryptography_constant_time_bytes_eq(uint8_t *, size_t, uint8_t *,                                              size_t);  """) -_lib = _ffi.verify(""" +_lib = _ffi.verify( +    """  uint8_t Cryptography_constant_time_bytes_eq(uint8_t *a, size_t len_a,                                              uint8_t *b, size_t len_b) {      size_t i = 0; @@ -42,7 +43,9 @@ uint8_t Cryptography_constant_time_bytes_eq(uint8_t *a, size_t len_a,      /* Now check the low bit to see if it's set */      return (mismatch & 1) == 0;  } -""") +""", +    ext_package="cryptography", +)  def bytes_eq(a, b): diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py index e87c9ca9..7a6bf3e2 100644 --- a/cryptography/hazmat/primitives/interfaces.py +++ b/cryptography/hazmat/primitives/interfaces.py @@ -47,6 +47,13 @@ class Mode(six.with_metaclass(abc.ABCMeta)):          A string naming this mode (e.g. "ECB", "CBC").          """ +    @abc.abstractmethod +    def validate_for_algorithm(self, algorithm): +        """ +        Checks that all the necessary invariants of this (mode, algorithm) +        combination are met. +        """ +  class ModeWithInitializationVector(six.with_metaclass(abc.ABCMeta)):      @abc.abstractproperty diff --git a/cryptography/hazmat/primitives/padding.py b/cryptography/hazmat/primitives/padding.py index e517dee0..ddb2c63c 100644 --- a/cryptography/hazmat/primitives/padding.py +++ b/cryptography/hazmat/primitives/padding.py @@ -23,7 +23,8 @@ _ffi = cffi.FFI()  _ffi.cdef("""  uint8_t Cryptography_check_pkcs7_padding(const uint8_t *, uint8_t);  """) -_lib = _ffi.verify(""" +_lib = _ffi.verify( +    """  /* Returns the value of the input with the most-significant-bit copied to all     of the bits. */  static uint8_t Cryptography_DUPLICATE_MSB_TO_ALL(uint8_t a) { @@ -59,7 +60,9 @@ 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;  } -""") +""", +    ext_package="cryptography", +)  class PKCS7(object): | 
