aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2014-05-15 16:59:15 -0400
committerPaul Kehrer <paul.l.kehrer@gmail.com>2014-05-15 16:59:15 -0400
commite2876f2051e9f6e7c535e8c3aca4bbd51caa3545 (patch)
tree1d5387d36b13f8e7a42ef9b380346fa4706fb0c8
parentd1c0fb8bbe0984d54ba0f4b7a8861bca0e446e19 (diff)
downloadcryptography-e2876f2051e9f6e7c535e8c3aca4bbd51caa3545.tar.gz
cryptography-e2876f2051e9f6e7c535e8c3aca4bbd51caa3545.tar.bz2
cryptography-e2876f2051e9f6e7c535e8c3aca4bbd51caa3545.zip
add CFB8 support for AES/3DES on CommonCrypto and OpenSSL backends
-rw-r--r--cryptography/hazmat/backends/commoncrypto/backend.py6
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py17
-rw-r--r--cryptography/hazmat/primitives/ciphers/modes.py19
-rw-r--r--tests/hazmat/primitives/test_3des.py37
-rw-r--r--tests/hazmat/primitives/test_aes.py33
5 files changed, 102 insertions, 10 deletions
diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py
index 4faca73e..91c0721d 100644
--- a/cryptography/hazmat/backends/commoncrypto/backend.py
+++ b/cryptography/hazmat/backends/commoncrypto/backend.py
@@ -28,7 +28,7 @@ from cryptography.hazmat.primitives.ciphers.algorithms import (
AES, ARC4, Blowfish, CAST5, TripleDES
)
from cryptography.hazmat.primitives.ciphers.modes import (
- CBC, CFB, CTR, ECB, GCM, OFB
+ CBC, CFB, CFB8, CTR, ECB, GCM, OFB
)
@@ -165,6 +165,7 @@ class Backend(object):
(CBC, self._lib.kCCModeCBC),
(ECB, self._lib.kCCModeECB),
(CFB, self._lib.kCCModeCFB),
+ (CFB8, self._lib.kCCModeCFB8),
(OFB, self._lib.kCCModeOFB),
(CTR, self._lib.kCCModeCTR),
(GCM, self._lib.kCCModeGCM),
@@ -178,6 +179,7 @@ class Backend(object):
for mode_cls, mode_const in [
(CBC, self._lib.kCCModeCBC),
(CFB, self._lib.kCCModeCFB),
+ (CFB8, self._lib.kCCModeCFB8),
(OFB, self._lib.kCCModeOFB),
]:
self._register_cipher_adapter(
@@ -264,7 +266,7 @@ class _CipherContext(object):
# This bug has been filed as rdar://15589470
self._bytes_processed = 0
if (isinstance(cipher, interfaces.BlockCipherAlgorithm) and not
- isinstance(mode, (OFB, CFB, CTR))):
+ isinstance(mode, (OFB, CFB, CFB8, CTR))):
self._byte_block_size = cipher.block_size // 8
else:
self._byte_block_size = 1
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index e00be92f..af8fc751 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -38,7 +38,7 @@ from cryptography.hazmat.primitives.ciphers.algorithms import (
AES, ARC4, Blowfish, CAST5, Camellia, IDEA, SEED, TripleDES
)
from cryptography.hazmat.primitives.ciphers.modes import (
- CBC, CFB, CTR, ECB, GCM, OFB
+ CBC, CFB, CFB8, CTR, ECB, GCM, OFB
)
@@ -147,16 +147,19 @@ class Backend(object):
self._cipher_registry[cipher_cls, mode_cls] = adapter
def _register_default_ciphers(self):
- for cipher_cls, mode_cls in itertools.product(
- [AES, Camellia],
- [CBC, CTR, ECB, OFB, CFB],
- ):
+ for mode_cls in [CBC, CTR, ECB, OFB, CFB, CFB8]:
self.register_cipher_adapter(
- cipher_cls,
+ AES,
+ mode_cls,
+ GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}")
+ )
+ for mode_cls in [CBC, CTR, ECB, OFB, CFB]:
+ self.register_cipher_adapter(
+ Camellia,
mode_cls,
GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}")
)
- for mode_cls in [CBC, CFB, OFB]:
+ for mode_cls in [CBC, CFB, CFB8, OFB]:
self.register_cipher_adapter(
TripleDES,
mode_cls,
diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py
index 739f23dd..dee80fb3 100644
--- a/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/cryptography/hazmat/primitives/ciphers/modes.py
@@ -59,8 +59,25 @@ class OFB(object):
@utils.register_interface(interfaces.ModeWithInitializationVector)
class CFB(object):
name = "CFB"
+ NATIVE_SIZE = object()
- def __init__(self, initialization_vector):
+ def __init__(self, initialization_vector, something=NATIVE_SIZE):
+ 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)
+class CFB8(object):
+ name = "CFB8"
+ NATIVE_SIZE = object()
+
+ def __init__(self, initialization_vector, something=NATIVE_SIZE):
self.initialization_vector = initialization_vector
def validate_for_algorithm(self, algorithm):
diff --git a/tests/hazmat/primitives/test_3des.py b/tests/hazmat/primitives/test_3des.py
index a4d696c9..b9354f0e 100644
--- a/tests/hazmat/primitives/test_3des.py
+++ b/tests/hazmat/primitives/test_3des.py
@@ -137,3 +137,40 @@ class TestTripleDESModeCFB(object):
),
lambda iv, **kwargs: modes.CFB(binascii.unhexlify(iv)),
)
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.cipher_supported(
+ algorithms.TripleDES("\x00" * 8), modes.CFB8("\x00" * 8)
+ ),
+ skip_message="Does not support TripleDES CFB8",
+)
+@pytest.mark.cipher
+class TestTripleDESModeCFB8(object):
+ test_KAT = generate_encrypt_test(
+ load_nist_vectors,
+ os.path.join("ciphers", "3DES", "CFB"),
+ [
+ "TCFB8invperm.rsp",
+ "TCFB8permop.rsp",
+ "TCFB8subtab.rsp",
+ "TCFB8varkey.rsp",
+ "TCFB8vartext.rsp",
+ ],
+ lambda keys, **kwargs: algorithms.TripleDES(binascii.unhexlify(keys)),
+ lambda iv, **kwargs: modes.CFB8(binascii.unhexlify(iv)),
+ )
+
+ test_MMT = generate_encrypt_test(
+ load_nist_vectors,
+ os.path.join("ciphers", "3DES", "CFB"),
+ [
+ "TCFB8MMT1.rsp",
+ "TCFB8MMT2.rsp",
+ "TCFB8MMT3.rsp",
+ ],
+ lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
+ binascii.unhexlify(key1 + key2 + key3)
+ ),
+ lambda iv, **kwargs: modes.CFB8(binascii.unhexlify(iv)),
+ )
diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py
index 03be268d..173075d6 100644
--- a/tests/hazmat/primitives/test_aes.py
+++ b/tests/hazmat/primitives/test_aes.py
@@ -158,6 +158,39 @@ class TestAESModeCFB(object):
@pytest.mark.supported(
only_if=lambda backend: backend.cipher_supported(
+ algorithms.AES("\x00" * 16), modes.CFB8("\x00" * 16)
+ ),
+ skip_message="Does not support AES CFB8",
+)
+@pytest.mark.cipher
+class TestAESModeCFB8(object):
+ test_CFB8 = generate_encrypt_test(
+ load_nist_vectors,
+ os.path.join("ciphers", "AES", "CFB"),
+ [
+ "CFB8GFSbox128.rsp",
+ "CFB8GFSbox192.rsp",
+ "CFB8GFSbox256.rsp",
+ "CFB8KeySbox128.rsp",
+ "CFB8KeySbox192.rsp",
+ "CFB8KeySbox256.rsp",
+ "CFB8VarKey128.rsp",
+ "CFB8VarKey192.rsp",
+ "CFB8VarKey256.rsp",
+ "CFB8VarTxt128.rsp",
+ "CFB8VarTxt192.rsp",
+ "CFB8VarTxt256.rsp",
+ "CFB8MMT128.rsp",
+ "CFB8MMT192.rsp",
+ "CFB8MMT256.rsp",
+ ],
+ lambda key, **kwargs: algorithms.AES(binascii.unhexlify(key)),
+ lambda iv, **kwargs: modes.CFB8(binascii.unhexlify(iv)),
+ )
+
+
+@pytest.mark.supported(
+ only_if=lambda backend: backend.cipher_supported(
algorithms.AES("\x00" * 16), modes.CTR("\x00" * 16)
),
skip_message="Does not support AES CTR",