aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography/hazmat
diff options
context:
space:
mode:
Diffstat (limited to 'cryptography/hazmat')
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py11
-rw-r--r--cryptography/hazmat/bindings/commoncrypto/__init__.py12
-rw-r--r--cryptography/hazmat/bindings/commoncrypto/binding.py47
-rw-r--r--cryptography/hazmat/bindings/commoncrypto/common_digest.py67
-rw-r--r--cryptography/hazmat/bindings/commoncrypto/common_hmac.py46
-rw-r--r--cryptography/hazmat/bindings/openssl/binding.py81
-rw-r--r--cryptography/hazmat/bindings/openssl/err.py50
-rw-r--r--cryptography/hazmat/bindings/utils.py86
-rw-r--r--cryptography/hazmat/primitives/ciphers/algorithms.py15
-rw-r--r--cryptography/hazmat/primitives/ciphers/base.py3
-rw-r--r--cryptography/hazmat/primitives/ciphers/modes.py33
-rw-r--r--cryptography/hazmat/primitives/constant_time.py7
-rw-r--r--cryptography/hazmat/primitives/interfaces.py7
-rw-r--r--cryptography/hazmat/primitives/padding.py7
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):