aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2014-10-22 10:12:07 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2014-10-22 10:12:07 -0700
commitd918580097506197e0aadaa60c4681536b5f4adf (patch)
tree2b58223f53302e0aa953c0fc203537dda879d1fc
parent633caacfe7e86f9098bb8cb64cfc12a9fe5cc35c (diff)
downloadcryptography-d918580097506197e0aadaa60c4681536b5f4adf.tar.gz
cryptography-d918580097506197e0aadaa60c4681536b5f4adf.tar.bz2
cryptography-d918580097506197e0aadaa60c4681536b5f4adf.zip
Statically verify interface implementations, and fix all the resulting bugs
-rw-r--r--cryptography/hazmat/backends/commoncrypto/hashes.py4
-rw-r--r--cryptography/hazmat/backends/commoncrypto/hmac.py4
-rw-r--r--cryptography/hazmat/backends/multibackend.py16
-rw-r--r--cryptography/hazmat/backends/openssl/cmac.py15
-rw-r--r--cryptography/hazmat/backends/openssl/dsa.py8
-rw-r--r--cryptography/hazmat/backends/openssl/hashes.py4
-rw-r--r--cryptography/hazmat/backends/openssl/hmac.py4
-rw-r--r--cryptography/hazmat/primitives/ciphers/modes.py29
-rw-r--r--cryptography/hazmat/primitives/cmac.py10
-rw-r--r--cryptography/hazmat/primitives/hashes.py4
-rw-r--r--cryptography/hazmat/primitives/hmac.py12
-rw-r--r--cryptography/utils.py1
-rw-r--r--tests/hazmat/backends/test_commoncrypto.py1
-rw-r--r--tests/hazmat/backends/test_openssl.py3
-rw-r--r--tests/hazmat/primitives/test_block.py1
-rw-r--r--tests/hazmat/primitives/test_ec.py11
-rw-r--r--tests/hazmat/primitives/test_hashes.py2
-rw-r--r--tests/hazmat/primitives/test_hmac.py4
-rw-r--r--tests/hazmat/primitives/test_pbkdf2hmac.py2
19 files changed, 92 insertions, 43 deletions
diff --git a/cryptography/hazmat/backends/commoncrypto/hashes.py b/cryptography/hazmat/backends/commoncrypto/hashes.py
index ebad7201..217f4e8c 100644
--- a/cryptography/hazmat/backends/commoncrypto/hashes.py
+++ b/cryptography/hazmat/backends/commoncrypto/hashes.py
@@ -21,7 +21,7 @@ from cryptography.hazmat.primitives import interfaces
@utils.register_interface(interfaces.HashContext)
class _HashContext(object):
def __init__(self, backend, algorithm, ctx=None):
- self.algorithm = algorithm
+ self._algorithm = algorithm
self._backend = backend
if ctx is None:
@@ -39,6 +39,8 @@ class _HashContext(object):
self._ctx = ctx
+ algorithm = utils.read_only_property("_algorithm")
+
def copy(self):
methods = self._backend._hash_mapping[self.algorithm.name]
new_ctx = self._backend._ffi.new(methods.ctx)
diff --git a/cryptography/hazmat/backends/commoncrypto/hmac.py b/cryptography/hazmat/backends/commoncrypto/hmac.py
index ec3a878b..404aac68 100644
--- a/cryptography/hazmat/backends/commoncrypto/hmac.py
+++ b/cryptography/hazmat/backends/commoncrypto/hmac.py
@@ -21,7 +21,7 @@ from cryptography.hazmat.primitives import interfaces
@utils.register_interface(interfaces.HashContext)
class _HMACContext(object):
def __init__(self, backend, key, algorithm, ctx=None):
- self.algorithm = algorithm
+ self._algorithm = algorithm
self._backend = backend
if ctx is None:
ctx = self._backend._ffi.new("CCHmacContext *")
@@ -39,6 +39,8 @@ class _HMACContext(object):
self._ctx = ctx
self._key = key
+ algorithm = utils.read_only_property("_algorithm")
+
def copy(self):
copied_ctx = self._backend._ffi.new("CCHmacContext *")
# CommonCrypto has no APIs for copying HMACs, so we have to copy the
diff --git a/cryptography/hazmat/backends/multibackend.py b/cryptography/hazmat/backends/multibackend.py
index e873f504..c62b790c 100644
--- a/cryptography/hazmat/backends/multibackend.py
+++ b/cryptography/hazmat/backends/multibackend.py
@@ -47,33 +47,33 @@ class MultiBackend(object):
if isinstance(b, interface):
yield b
- def cipher_supported(self, algorithm, mode):
+ def cipher_supported(self, cipher, mode):
return any(
- b.cipher_supported(algorithm, mode)
+ b.cipher_supported(cipher, mode)
for b in self._filtered_backends(CipherBackend)
)
- def create_symmetric_encryption_ctx(self, algorithm, mode):
+ def create_symmetric_encryption_ctx(self, cipher, mode):
for b in self._filtered_backends(CipherBackend):
try:
- return b.create_symmetric_encryption_ctx(algorithm, mode)
+ return b.create_symmetric_encryption_ctx(cipher, mode)
except UnsupportedAlgorithm:
pass
raise UnsupportedAlgorithm(
"cipher {0} in {1} mode is not supported by this backend.".format(
- algorithm.name, mode.name if mode else mode),
+ cipher.name, mode.name if mode else mode),
_Reasons.UNSUPPORTED_CIPHER
)
- def create_symmetric_decryption_ctx(self, algorithm, mode):
+ def create_symmetric_decryption_ctx(self, cipher, mode):
for b in self._filtered_backends(CipherBackend):
try:
- return b.create_symmetric_decryption_ctx(algorithm, mode)
+ return b.create_symmetric_decryption_ctx(cipher, mode)
except UnsupportedAlgorithm:
pass
raise UnsupportedAlgorithm(
"cipher {0} in {1} mode is not supported by this backend.".format(
- algorithm.name, mode.name if mode else mode),
+ cipher.name, mode.name if mode else mode),
_Reasons.UNSUPPORTED_CIPHER
)
diff --git a/cryptography/hazmat/backends/openssl/cmac.py b/cryptography/hazmat/backends/openssl/cmac.py
index da7b7484..113188ca 100644
--- a/cryptography/hazmat/backends/openssl/cmac.py
+++ b/cryptography/hazmat/backends/openssl/cmac.py
@@ -15,8 +15,10 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
-from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
-from cryptography.hazmat.primitives import interfaces
+from cryptography.exceptions import (
+ InvalidSignature, UnsupportedAlgorithm, _Reasons
+)
+from cryptography.hazmat.primitives import constant_time, interfaces
from cryptography.hazmat.primitives.ciphers.modes import CBC
@@ -50,6 +52,8 @@ class _CMACContext(object):
self._ctx = ctx
+ algorithm = utils.read_only_property("_algorithm")
+
def update(self, data):
res = self._backend._lib.CMAC_Update(self._ctx, data, len(data))
assert res == 1
@@ -78,3 +82,10 @@ class _CMACContext(object):
return _CMACContext(
self._backend, self._algorithm, ctx=copied_ctx
)
+
+ def verify(self, signature):
+ if not isinstance(signature, bytes):
+ raise TypeError("signature must be bytes.")
+ digest = self.finalize()
+ if not constant_time.bytes_eq(digest, signature):
+ raise InvalidSignature("Signature did not match digest.")
diff --git a/cryptography/hazmat/backends/openssl/dsa.py b/cryptography/hazmat/backends/openssl/dsa.py
index 2298e7d9..8652d50b 100644
--- a/cryptography/hazmat/backends/openssl/dsa.py
+++ b/cryptography/hazmat/backends/openssl/dsa.py
@@ -131,8 +131,8 @@ class _DSAPrivateKey(object):
key_size = utils.read_only_property("_key_size")
- def signer(self, algorithm):
- return _DSASignatureContext(self._backend, self, algorithm)
+ def signer(self, signature_algorithm):
+ return _DSASignatureContext(self._backend, self, signature_algorithm)
def private_numbers(self):
return dsa.DSAPrivateNumbers(
@@ -180,9 +180,9 @@ class _DSAPublicKey(object):
key_size = utils.read_only_property("_key_size")
- def verifier(self, signature, algorithm):
+ def verifier(self, signature, signature_algorithm):
return _DSAVerificationContext(
- self._backend, self, signature, algorithm
+ self._backend, self, signature, signature_algorithm
)
def public_numbers(self):
diff --git a/cryptography/hazmat/backends/openssl/hashes.py b/cryptography/hazmat/backends/openssl/hashes.py
index da91eef6..591c014a 100644
--- a/cryptography/hazmat/backends/openssl/hashes.py
+++ b/cryptography/hazmat/backends/openssl/hashes.py
@@ -22,7 +22,7 @@ from cryptography.hazmat.primitives import interfaces
@utils.register_interface(interfaces.HashContext)
class _HashContext(object):
def __init__(self, backend, algorithm, ctx=None):
- self.algorithm = algorithm
+ self._algorithm = algorithm
self._backend = backend
@@ -44,6 +44,8 @@ class _HashContext(object):
self._ctx = ctx
+ algorithm = utils.read_only_property("_algorithm")
+
def copy(self):
copied_ctx = self._backend._lib.EVP_MD_CTX_create()
copied_ctx = self._backend._ffi.gc(
diff --git a/cryptography/hazmat/backends/openssl/hmac.py b/cryptography/hazmat/backends/openssl/hmac.py
index 3f1576f5..f22b086f 100644
--- a/cryptography/hazmat/backends/openssl/hmac.py
+++ b/cryptography/hazmat/backends/openssl/hmac.py
@@ -22,7 +22,7 @@ from cryptography.hazmat.primitives import interfaces
@utils.register_interface(interfaces.HashContext)
class _HMACContext(object):
def __init__(self, backend, key, algorithm, ctx=None):
- self.algorithm = algorithm
+ self._algorithm = algorithm
self._backend = backend
if ctx is None:
@@ -47,6 +47,8 @@ class _HMACContext(object):
self._ctx = ctx
self._key = key
+ algorithm = utils.read_only_property("_algorithm")
+
def copy(self):
copied_ctx = self._backend._ffi.new("HMAC_CTX *")
self._backend._lib.HMAC_CTX_init(copied_ctx)
diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py
index 509b4de2..d995b876 100644
--- a/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/cryptography/hazmat/primitives/ciphers/modes.py
@@ -17,10 +17,10 @@ from cryptography import utils
from cryptography.hazmat.primitives import interfaces
-def _check_iv_length(mode, algorithm):
- if len(mode.initialization_vector) * 8 != algorithm.block_size:
+def _check_iv_length(self, algorithm):
+ if len(self.initialization_vector) * 8 != algorithm.block_size:
raise ValueError("Invalid IV size ({0}) for {1}.".format(
- len(mode.initialization_vector), mode.name
+ len(self.initialization_vector), self.name
))
@@ -30,8 +30,9 @@ class CBC(object):
name = "CBC"
def __init__(self, initialization_vector):
- self.initialization_vector = initialization_vector
+ self._initialization_vector = initialization_vector
+ initialization_vector = utils.read_only_property("_initialization_vector")
validate_for_algorithm = _check_iv_length
@@ -49,8 +50,9 @@ class OFB(object):
name = "OFB"
def __init__(self, initialization_vector):
- self.initialization_vector = initialization_vector
+ self._initialization_vector = initialization_vector
+ initialization_vector = utils.read_only_property("_initialization_vector")
validate_for_algorithm = _check_iv_length
@@ -60,8 +62,9 @@ class CFB(object):
name = "CFB"
def __init__(self, initialization_vector):
- self.initialization_vector = initialization_vector
+ self._initialization_vector = initialization_vector
+ initialization_vector = utils.read_only_property("_initialization_vector")
validate_for_algorithm = _check_iv_length
@@ -71,8 +74,9 @@ class CFB8(object):
name = "CFB8"
def __init__(self, initialization_vector):
- self.initialization_vector = initialization_vector
+ self._initialization_vector = initialization_vector
+ initialization_vector = utils.read_only_property("_initialization_vector")
validate_for_algorithm = _check_iv_length
@@ -82,7 +86,9 @@ class CTR(object):
name = "CTR"
def __init__(self, nonce):
- self.nonce = nonce
+ self._nonce = nonce
+
+ nonce = utils.read_only_property("_nonce")
def validate_for_algorithm(self, algorithm):
if len(self.nonce) * 8 != algorithm.block_size:
@@ -109,8 +115,11 @@ class GCM(object):
min_tag_length)
)
- self.initialization_vector = initialization_vector
- self.tag = tag
+ self._initialization_vector = initialization_vector
+ self._tag = tag
+
+ tag = utils.read_only_property("_tag")
+ initialization_vector = utils.read_only_property("_initialization_vector")
def validate_for_algorithm(self, algorithm):
pass
diff --git a/cryptography/hazmat/primitives/cmac.py b/cryptography/hazmat/primitives/cmac.py
index 7ae5c118..a70a9a42 100644
--- a/cryptography/hazmat/primitives/cmac.py
+++ b/cryptography/hazmat/primitives/cmac.py
@@ -15,10 +15,10 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, InvalidSignature, UnsupportedAlgorithm, _Reasons
+ AlreadyFinalized, UnsupportedAlgorithm, _Reasons
)
from cryptography.hazmat.backends.interfaces import CMACBackend
-from cryptography.hazmat.primitives import constant_time, interfaces
+from cryptography.hazmat.primitives import interfaces
@utils.register_interface(interfaces.MACContext)
@@ -57,11 +57,7 @@ class CMAC(object):
return digest
def verify(self, signature):
- if not isinstance(signature, bytes):
- raise TypeError("signature must be bytes.")
- digest = self.finalize()
- if not constant_time.bytes_eq(digest, signature):
- raise InvalidSignature("Signature did not match digest.")
+ self._ctx.verify(signature)
def copy(self):
if self._ctx is None:
diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py
index 04f7620a..8c2284e3 100644
--- a/cryptography/hazmat/primitives/hashes.py
+++ b/cryptography/hazmat/primitives/hashes.py
@@ -32,7 +32,7 @@ class Hash(object):
if not isinstance(algorithm, interfaces.HashAlgorithm):
raise TypeError("Expected instance of interfaces.HashAlgorithm.")
- self.algorithm = algorithm
+ self._algorithm = algorithm
self._backend = backend
@@ -41,6 +41,8 @@ class Hash(object):
else:
self._ctx = ctx
+ algorithm = utils.read_only_property("_algorithm")
+
def update(self, data):
if self._ctx is None:
raise AlreadyFinalized("Context was already finalized.")
diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py
index 23292432..22a31391 100644
--- a/cryptography/hazmat/primitives/hmac.py
+++ b/cryptography/hazmat/primitives/hmac.py
@@ -33,7 +33,7 @@ class HMAC(object):
if not isinstance(algorithm, interfaces.HashAlgorithm):
raise TypeError("Expected instance of interfaces.HashAlgorithm.")
- self.algorithm = algorithm
+ self._algorithm = algorithm
self._backend = backend
self._key = key
@@ -42,12 +42,14 @@ class HMAC(object):
else:
self._ctx = ctx
- def update(self, msg):
+ algorithm = utils.read_only_property("_algorithm")
+
+ def update(self, data):
if self._ctx is None:
raise AlreadyFinalized("Context was already finalized.")
- if not isinstance(msg, bytes):
- raise TypeError("msg must be bytes.")
- self._ctx.update(msg)
+ if not isinstance(data, bytes):
+ raise TypeError("data must be bytes.")
+ self._ctx.update(data)
def copy(self):
if self._ctx is None:
diff --git a/cryptography/utils.py b/cryptography/utils.py
index 8fbcabc5..03c8c0e8 100644
--- a/cryptography/utils.py
+++ b/cryptography/utils.py
@@ -23,6 +23,7 @@ DeprecatedIn06 = DeprecationWarning
def register_interface(iface):
def register_decorator(klass):
+ verify_interface(iface, klass)
iface.register(klass)
return klass
return register_decorator
diff --git a/tests/hazmat/backends/test_commoncrypto.py b/tests/hazmat/backends/test_commoncrypto.py
index 28d1a6ca..b79c02e0 100644
--- a/tests/hazmat/backends/test_commoncrypto.py
+++ b/tests/hazmat/backends/test_commoncrypto.py
@@ -30,6 +30,7 @@ from ...utils import raises_unsupported_algorithm
class DummyCipher(object):
name = "dummy-cipher"
block_size = 128
+ key_size = 128
@pytest.mark.skipif("commoncrypto" not in
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 3bea413a..83494d0d 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -51,6 +51,7 @@ class DummyMode(object):
@utils.register_interface(interfaces.CipherAlgorithm)
class DummyCipher(object):
name = "dummy-cipher"
+ key_size = 128
@utils.register_interface(interfaces.AsymmetricPadding)
@@ -61,6 +62,8 @@ class DummyPadding(object):
@utils.register_interface(interfaces.HashAlgorithm)
class DummyHash(object):
name = "dummy-hash"
+ block_size = 128
+ digest_size = 128
class DummyMGF(object):
diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py
index 022e3af7..0b90dd90 100644
--- a/tests/hazmat/primitives/test_block.py
+++ b/tests/hazmat/primitives/test_block.py
@@ -43,6 +43,7 @@ class DummyMode(object):
@utils.register_interface(interfaces.CipherAlgorithm)
class DummyCipher(object):
name = "dummy-cipher"
+ key_size = 128
@pytest.mark.cipher
diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py
index 1b3bb9b3..9ed762cb 100644
--- a/tests/hazmat/primitives/test_ec.py
+++ b/tests/hazmat/primitives/test_ec.py
@@ -68,11 +68,20 @@ class DummyCurve(object):
@utils.register_interface(interfaces.EllipticCurveSignatureAlgorithm)
class DummySignatureAlgorithm(object):
- pass
+ algorithm = None
@utils.register_interface(EllipticCurveBackend)
class DeprecatedDummyECBackend(object):
+ def _unimplemented(self):
+ raise NotImplementedError
+
+ elliptic_curve_signature_algorithm_supported = _unimplemented
+ load_elliptic_curve_private_numbers = _unimplemented
+ load_elliptic_curve_public_numbers = _unimplemented
+ elliptic_curve_supported = _unimplemented
+ generate_elliptic_curve_private_key = _unimplemented
+
def elliptic_curve_private_key_from_numbers(self, numbers):
return b"private_key"
diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py
index ffd65bde..2bf1f8ef 100644
--- a/tests/hazmat/primitives/test_hashes.py
+++ b/tests/hazmat/primitives/test_hashes.py
@@ -33,6 +33,8 @@ from ...utils import raises_unsupported_algorithm
@utils.register_interface(interfaces.HashAlgorithm)
class UnsupportedDummyHash(object):
name = "unsupported-dummy-hash"
+ block_size = 128
+ digest_size = 128
@pytest.mark.hash
diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py
index 77dfb6be..21be73a3 100644
--- a/tests/hazmat/primitives/test_hmac.py
+++ b/tests/hazmat/primitives/test_hmac.py
@@ -32,7 +32,9 @@ from ...utils import raises_unsupported_algorithm
@utils.register_interface(interfaces.HashAlgorithm)
class UnsupportedDummyHash(object):
- name = "unsupported-dummy-hash"
+ name = "unsupported-dummy-hash"
+ block_size = 128
+ digest_size = 128
@pytest.mark.supported(
diff --git a/tests/hazmat/primitives/test_pbkdf2hmac.py b/tests/hazmat/primitives/test_pbkdf2hmac.py
index e928fc6a..fa925877 100644
--- a/tests/hazmat/primitives/test_pbkdf2hmac.py
+++ b/tests/hazmat/primitives/test_pbkdf2hmac.py
@@ -31,6 +31,8 @@ from ...utils import raises_unsupported_algorithm
@utils.register_interface(interfaces.HashAlgorithm)
class DummyHash(object):
name = "dummy-hash"
+ block_size = 128
+ digest_size = 128
class TestPBKDF2HMAC(object):