Merge pull request #313 from dreid/block-cipher-algorithm

BlockCipherAlgorithm because we should document block_size and ARC4 shouldn't need block_size = 1.
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index bd092be..588a427 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -276,6 +276,11 @@
         self._operation = operation
         self._tag = None
 
+        if isinstance(self._cipher, interfaces.BlockCipherAlgorithm):
+            self._block_size = self._cipher.block_size
+        else:
+            self._block_size = 1
+
         ctx = self._backend.lib.EVP_CIPHER_CTX_new()
         ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_CIPHER_CTX_free)
 
@@ -341,7 +346,7 @@
 
     def update(self, data):
         buf = self._backend.ffi.new("unsigned char[]",
-                                    len(data) + self._cipher.block_size - 1)
+                                    len(data) + self._block_size - 1)
         outlen = self._backend.ffi.new("int *")
         res = self._backend.lib.EVP_CipherUpdate(self._ctx, buf, outlen, data,
                                                  len(data))
@@ -349,7 +354,7 @@
         return self._backend.ffi.buffer(buf)[:outlen[0]]
 
     def finalize(self):
-        buf = self._backend.ffi.new("unsigned char[]", self._cipher.block_size)
+        buf = self._backend.ffi.new("unsigned char[]", self._block_size)
         outlen = self._backend.ffi.new("int *")
         res = self._backend.lib.EVP_CipherFinal_ex(self._ctx, buf, outlen)
         if res == 0:
@@ -357,7 +362,7 @@
 
         if (isinstance(self._mode, GCM) and
            self._operation == self._ENCRYPT):
-            block_byte_size = self._cipher.block_size // 8
+            block_byte_size = self._block_size // 8
             tag_buf = self._backend.ffi.new("unsigned char[]", block_byte_size)
             res = self._backend.lib.EVP_CIPHER_CTX_ctrl(
                 self._ctx, self._backend.lib.Cryptography_EVP_CTRL_GCM_GET_TAG,
diff --git a/cryptography/hazmat/primitives/ciphers/algorithms.py b/cryptography/hazmat/primitives/ciphers/algorithms.py
index a206b27..a5cfce9 100644
--- a/cryptography/hazmat/primitives/ciphers/algorithms.py
+++ b/cryptography/hazmat/primitives/ciphers/algorithms.py
@@ -26,6 +26,7 @@
     return key
 
 
+@utils.register_interface(interfaces.BlockCipherAlgorithm)
 @utils.register_interface(interfaces.CipherAlgorithm)
 class AES(object):
     name = "AES"
@@ -40,6 +41,7 @@
         return len(self.key) * 8
 
 
+@utils.register_interface(interfaces.BlockCipherAlgorithm)
 @utils.register_interface(interfaces.CipherAlgorithm)
 class Camellia(object):
     name = "camellia"
@@ -54,6 +56,7 @@
         return len(self.key) * 8
 
 
+@utils.register_interface(interfaces.BlockCipherAlgorithm)
 @utils.register_interface(interfaces.CipherAlgorithm)
 class TripleDES(object):
     name = "3DES"
@@ -72,6 +75,7 @@
         return len(self.key) * 8
 
 
+@utils.register_interface(interfaces.BlockCipherAlgorithm)
 @utils.register_interface(interfaces.CipherAlgorithm)
 class Blowfish(object):
     name = "Blowfish"
@@ -86,6 +90,7 @@
         return len(self.key) * 8
 
 
+@utils.register_interface(interfaces.BlockCipherAlgorithm)
 @utils.register_interface(interfaces.CipherAlgorithm)
 class CAST5(object):
     name = "CAST5"
@@ -103,7 +108,6 @@
 @utils.register_interface(interfaces.CipherAlgorithm)
 class ARC4(object):
     name = "RC4"
-    block_size = 1
     key_sizes = frozenset([40, 56, 64, 80, 128, 192, 256])
 
     def __init__(self, key):
diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py
index e3f4f58..2a1a21b 100644
--- a/cryptography/hazmat/primitives/interfaces.py
+++ b/cryptography/hazmat/primitives/interfaces.py
@@ -32,6 +32,14 @@
         """
 
 
+class BlockCipherAlgorithm(six.with_metaclass(abc.ABCMeta)):
+    @abc.abstractproperty
+    def block_size(self):
+        """
+        The size of a block as an integer in bits.  (e.g. 64, 128)
+        """
+
+
 class Mode(six.with_metaclass(abc.ABCMeta)):
     @abc.abstractproperty
     def name(self):
diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index 11cff51..361b723 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -36,6 +36,17 @@
         The number of bits in the key being used.
 
 
+.. class:: BlockCipherAlgorithm
+
+    A block cipher algorithm.
+
+    .. attribute:: block_size
+
+        :type: int
+
+        The number of bits in a block.
+
+
 Cipher Modes
 ------------