Merge branch 'master' into hmac-context-from-backend

Conflicts:
	cryptography/hazmat/bindings/openssl/backend.py
	cryptography/hazmat/primitives/hmac.py
diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py
index 4d1be3b..4760f9b 100644
--- a/cryptography/hazmat/bindings/openssl/backend.py
+++ b/cryptography/hazmat/bindings/openssl/backend.py
@@ -140,6 +140,7 @@
 
     def __init__(self, backend, cipher, mode, operation):
         self._backend = backend
+        self._cipher = cipher
 
         ctx = self._backend.lib.EVP_CIPHER_CTX_new()
         ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_CIPHER_CTX_free)
@@ -185,9 +186,8 @@
         self._ctx = ctx
 
     def update(self, data):
-        block_size = self._backend.lib.EVP_CIPHER_CTX_block_size(self._ctx)
         buf = self._backend.ffi.new("unsigned char[]",
-                                    len(data) + block_size - 1)
+                                    len(data) + self._cipher.block_size - 1)
         outlen = self._backend.ffi.new("int *")
         res = self._backend.lib.EVP_CipherUpdate(self._ctx, buf, outlen, data,
                                                  len(data))
@@ -195,8 +195,7 @@
         return self._backend.ffi.buffer(buf)[:outlen[0]]
 
     def finalize(self):
-        block_size = self._backend.lib.EVP_CIPHER_CTX_block_size(self._ctx)
-        buf = self._backend.ffi.new("unsigned char[]", block_size)
+        buf = self._backend.ffi.new("unsigned char[]", self._cipher.block_size)
         outlen = self._backend.ffi.new("int *")
         res = self._backend.lib.EVP_CipherFinal_ex(self._ctx, buf, outlen)
         assert res != 0
@@ -207,7 +206,6 @@
 
 class Ciphers(object):
     def __init__(self, backend):
-        super(Ciphers, self).__init__()
         self._backend = backend
         self._cipher_registry = {}
         self._register_default_ciphers()
@@ -269,54 +267,67 @@
                               _CipherContext._DECRYPT)
 
 
-class Hashes(object):
-    def __init__(self, backend):
-        super(Hashes, self).__init__()
+@interfaces.register(interfaces.HashContext)
+class _HashContext(object):
+    def __init__(self, backend, algorithm, ctx=None):
+        self.algorithm = algorithm
+
         self._backend = backend
 
-    def supported(self, hash_cls):
-        return (self._backend.ffi.NULL !=
-                self._backend.lib.EVP_get_digestbyname(
-                    hash_cls.name.encode("ascii")))
+        if ctx is None:
+            ctx = self._backend.lib.EVP_MD_CTX_create()
+            ctx = self._backend.ffi.gc(ctx,
+                                       self._backend.lib.EVP_MD_CTX_destroy)
+            evp_md = self._backend.lib.EVP_get_digestbyname(
+                algorithm.name.encode("ascii"))
+            assert evp_md != self._backend.ffi.NULL
+            res = self._backend.lib.EVP_DigestInit_ex(ctx, evp_md,
+                                                      self._backend.ffi.NULL)
+            assert res != 0
 
-    def create_ctx(self, hashobject):
-        ctx = self._backend.lib.EVP_MD_CTX_create()
-        ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_MD_CTX_destroy)
-        evp_md = self._backend.lib.EVP_get_digestbyname(
-            hashobject.name.encode("ascii"))
-        assert evp_md != self._backend.ffi.NULL
-        res = self._backend.lib.EVP_DigestInit_ex(ctx, evp_md,
-                                                  self._backend.ffi.NULL)
-        assert res != 0
-        return ctx
+        self._ctx = ctx
 
-    def update_ctx(self, ctx, data):
-        res = self._backend.lib.EVP_DigestUpdate(ctx, data, len(data))
-        assert res != 0
-
-    def finalize_ctx(self, ctx, digest_size):
-        buf = self._backend.ffi.new("unsigned char[]", digest_size)
-        res = self._backend.lib.EVP_DigestFinal_ex(ctx, buf,
-                                                   self._backend.ffi.NULL)
-        assert res != 0
-        res = self._backend.lib.EVP_MD_CTX_cleanup(ctx)
-        assert res == 1
-        return self._backend.ffi.buffer(buf)[:digest_size]
-
-    def copy_ctx(self, ctx):
+    def copy(self):
         copied_ctx = self._backend.lib.EVP_MD_CTX_create()
         copied_ctx = self._backend.ffi.gc(copied_ctx,
                                           self._backend.lib.EVP_MD_CTX_destroy)
-        res = self._backend.lib.EVP_MD_CTX_copy_ex(copied_ctx, ctx)
+        res = self._backend.lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx)
         assert res != 0
-        return copied_ctx
+        return _HashContext(self._backend, self.algorithm, ctx=copied_ctx)
+
+    def update(self, data):
+        res = self._backend.lib.EVP_DigestUpdate(self._ctx, data, len(data))
+        assert res != 0
+
+    def finalize(self):
+        buf = self._backend.ffi.new("unsigned char[]",
+                                    self.algorithm.digest_size)
+        res = self._backend.lib.EVP_DigestFinal_ex(self._ctx, buf,
+                                                   self._backend.ffi.NULL)
+        assert res != 0
+        res = self._backend.lib.EVP_MD_CTX_cleanup(self._ctx)
+        assert res == 1
+        return self._backend.ffi.buffer(buf)[:self.algorithm.digest_size]
+
+
+class Hashes(object):
+    def __init__(self, backend):
+        self._backend = backend
+
+    def supported(self, algorithm):
+        digest = self._backend.lib.EVP_get_digestbyname(
+            algorithm.name.encode("ascii")
+        )
+        return digest != self._backend.ffi.NULL
+
+    def create_ctx(self, algorithm):
+        return _HashContext(self._backend, algorithm)
 
 
 @interfaces.register(interfaces.HashContext)
 class _HMACContext(object):
     def __init__(self, backend, key, algorithm, ctx=None):
         self.algorithm = algorithm
-
         self._backend = backend
 
         if ctx is None:
@@ -367,7 +378,6 @@
 
 class HMACs(object):
     def __init__(self, backend):
-        super(HMACs, self).__init__()
         self._backend = backend
 
     def create_ctx(self, key, algorithm):
diff --git a/cryptography/hazmat/primitives/ciphers/algorithms.py b/cryptography/hazmat/primitives/ciphers/algorithms.py
index cbfaceb..c135f56 100644
--- a/cryptography/hazmat/primitives/ciphers/algorithms.py
+++ b/cryptography/hazmat/primitives/ciphers/algorithms.py
@@ -20,7 +20,6 @@
     key_sizes = frozenset([128, 192, 256])
 
     def __init__(self, key):
-        super(AES, self).__init__()
         self.key = key
 
         # Verify that the key size matches the expected key size
@@ -40,7 +39,6 @@
     key_sizes = frozenset([128, 192, 256])
 
     def __init__(self, key):
-        super(Camellia, self).__init__()
         self.key = key
 
         # Verify that the key size matches the expected key size
@@ -60,7 +58,6 @@
     key_sizes = frozenset([64, 128, 192])
 
     def __init__(self, key):
-        super(TripleDES, self).__init__()
         if len(key) == 8:
             key += key + key
         elif len(key) == 16:
@@ -84,7 +81,6 @@
     key_sizes = frozenset(range(32, 449, 8))
 
     def __init__(self, key):
-        super(Blowfish, self).__init__()
         self.key = key
 
         # Verify that the key size matches the expected key size
@@ -104,7 +100,6 @@
     key_sizes = frozenset([40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128])
 
     def __init__(self, key):
-        super(CAST5, self).__init__()
         self.key = key
 
         # Verify that the key size matches the expected key size
@@ -120,10 +115,10 @@
 
 class ARC4(object):
     name = "RC4"
+    block_size = 1
     key_sizes = frozenset([40, 56, 64, 80, 128, 192, 256])
 
     def __init__(self, key):
-        super(ARC4, self).__init__()
         self.key = key
 
         # Verify that the key size matches the expected key size
diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py
index 1599308..d48f9cc 100644
--- a/cryptography/hazmat/primitives/ciphers/base.py
+++ b/cryptography/hazmat/primitives/ciphers/base.py
@@ -18,8 +18,6 @@
 
 class Cipher(object):
     def __init__(self, algorithm, mode, backend=None):
-        super(Cipher, self).__init__()
-
         if backend is None:
             from cryptography.hazmat.bindings import (
                 _default_backend as backend,
diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py
index e54872a..915fd83 100644
--- a/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/cryptography/hazmat/primitives/ciphers/modes.py
@@ -22,7 +22,6 @@
     name = "CBC"
 
     def __init__(self, initialization_vector):
-        super(CBC, self).__init__()
         self.initialization_vector = initialization_vector
 
 
@@ -37,7 +36,6 @@
     name = "OFB"
 
     def __init__(self, initialization_vector):
-        super(OFB, self).__init__()
         self.initialization_vector = initialization_vector
 
 
@@ -47,7 +45,6 @@
     name = "CFB"
 
     def __init__(self, initialization_vector):
-        super(CFB, self).__init__()
         self.initialization_vector = initialization_vector
 
 
@@ -57,5 +54,4 @@
     name = "CTR"
 
     def __init__(self, nonce):
-        super(CTR, self).__init__()
         self.nonce = nonce
diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py
index c774811..6ae622c 100644
--- a/cryptography/hazmat/primitives/hashes.py
+++ b/cryptography/hazmat/primitives/hashes.py
@@ -39,15 +39,15 @@
     def update(self, data):
         if isinstance(data, six.text_type):
             raise TypeError("Unicode-objects must be encoded before hashing")
-        self._backend.hashes.update_ctx(self._ctx, data)
+        self._ctx.update(data)
 
     def copy(self):
-        return self.__class__(self.algorithm, backend=self._backend,
-                              ctx=self._backend.hashes.copy_ctx(self._ctx))
+        return Hash(
+            self.algorithm, backend=self._backend, ctx=self._ctx.copy()
+        )
 
     def finalize(self):
-        return self._backend.hashes.finalize_ctx(self._ctx,
-                                                 self.algorithm.digest_size)
+        return self._ctx.finalize()
 
 
 @interfaces.register(interfaces.HashAlgorithm)
diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py
index 57a908c..0f1b4fa 100644
--- a/cryptography/hazmat/primitives/hmac.py
+++ b/cryptography/hazmat/primitives/hmac.py
@@ -21,7 +21,6 @@
 @interfaces.register(interfaces.HashContext)
 class HMAC(object):
     def __init__(self, key, algorithm, ctx=None, backend=None):
-        super(HMAC, self).__init__()
         if not isinstance(algorithm, interfaces.HashAlgorithm):
             raise TypeError("Expected instance of interfaces.HashAlgorithm.")
         self.algorithm = algorithm
@@ -44,8 +43,10 @@
 
     def copy(self):
         return HMAC(
-            self._key, self.algorithm, ctx=self._ctx.copy(),
-            backend=self._backend
+            self._key,
+            self.algorithm,
+            backend=self._backend,
+            ctx=self._ctx.copy()
         )
 
     def finalize(self):
diff --git a/cryptography/hazmat/primitives/padding.py b/cryptography/hazmat/primitives/padding.py
index eac18c2..f41c62c 100644
--- a/cryptography/hazmat/primitives/padding.py
+++ b/cryptography/hazmat/primitives/padding.py
@@ -18,7 +18,6 @@
 
 class PKCS7(object):
     def __init__(self, block_size):
-        super(PKCS7, self).__init__()
         if not (0 <= block_size < 256):
             raise ValueError("block_size must be in range(0, 256)")
 
@@ -37,7 +36,6 @@
 @interfaces.register(interfaces.PaddingContext)
 class _PKCS7PaddingContext(object):
     def __init__(self, block_size):
-        super(_PKCS7PaddingContext, self).__init__()
         self.block_size = block_size
         # TODO: O(n ** 2) complexity for repeated concatentation, we should use
         # zero-buffer (#193)
@@ -72,7 +70,6 @@
 @interfaces.register(interfaces.PaddingContext)
 class _PKCS7UnpaddingContext(object):
     def __init__(self, block_size):
-        super(_PKCS7UnpaddingContext, self).__init__()
         self.block_size = block_size
         # TODO: O(n ** 2) complexity for repeated concatentation, we should use
         # zero-buffer (#193)
diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py
index 07ab248..6cdb0a0 100644
--- a/tests/hazmat/primitives/test_hashes.py
+++ b/tests/hazmat/primitives/test_hashes.py
@@ -32,9 +32,9 @@
             m.update(six.u("\u00FC"))
 
     def test_copy_backend_object(self):
-        pretend_hashes = pretend.stub(copy_ctx=lambda a: "copiedctx")
-        pretend_backend = pretend.stub(hashes=pretend_hashes)
-        pretend_ctx = pretend.stub()
+        pretend_backend = pretend.stub()
+        copied_ctx = pretend.stub()
+        pretend_ctx = pretend.stub(copy=lambda: copied_ctx)
         h = hashes.Hash(hashes.SHA1(), backend=pretend_backend,
                         ctx=pretend_ctx)
         assert h._backend is pretend_backend
diff --git a/tests/test_utils.py b/tests/test_utils.py
index af575b3..4dede2e 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -268,3 +268,133 @@
             ),
         }
     ]
+
+
+def test_load_nist_gcm_vectors():
+    vector_data = textwrap.dedent("""
+        [Keylen = 128]
+        [IVlen = 96]
+        [PTlen = 0]
+        [AADlen = 0]
+        [Taglen = 128]
+
+        Count = 0
+        Key = 11754cd72aec309bf52f7687212e8957
+        IV = 3c819d9a9bed087615030b65
+        PT =
+        AAD =
+        CT =
+        Tag = 250327c674aaf477aef2675748cf6971
+
+        Count = 1
+        Key = 272f16edb81a7abbea887357a58c1917
+        IV = 794ec588176c703d3d2a7a07
+        PT =
+        AAD =
+        CT =
+        Tag = b6e6f197168f5049aeda32dafbdaeb
+
+        Count = 2
+        Key = a49a5e26a2f8cb63d05546c2a62f5343
+        IV = 907763b19b9b4ab6bd4f0281
+        CT =
+        AAD =
+        Tag = a2be08210d8c470a8df6e8fbd79ec5cf
+        FAIL
+
+        Count = 3
+        Key = 5c1155084cc0ede76b3bc22e9f7574ef
+        IV = 9549e4ba69a61cad7856efc1
+        PT = d1448fa852b84408e2dad8381f363de7
+        AAD = e98e9d9c618e46fef32660976f854ee3
+        CT = f78b60ca125218493bea1c50a2e12ef4
+        Tag = d72da7f5c6cf0bca7242c71835809449
+
+        [Keylen = 128]
+        [IVlen = 96]
+        [PTlen = 0]
+        [AADlen = 0]
+        [Taglen = 120]
+
+        Count = 0
+        Key = eac258e99c55e6ae8ef1da26640613d7
+        IV = 4e8df20faaf2c8eebe922902
+        CT =
+        AAD =
+        Tag = e39aeaebe86aa309a4d062d6274339
+        PT =
+
+        Count = 1
+        Key = 3726cf02fcc6b8639a5497652c94350d
+        IV = 55fef82cde693ce76efcc193
+        CT =
+        AAD =
+        Tag = 3d68111a81ed22d2ef5bccac4fc27f
+        FAIL
+
+        Count = 2
+        Key = f202299d5fd74f03b12d2119a6c4c038
+        IV = eec51e7958c3f20a1bb71815
+        CT =
+        AAD =
+        Tag = a81886b3fb26e51fca87b267e1e157
+        FAIL
+
+        Count = 3
+        Key = fd52925f39546b4c55ffb6b20c59898c
+        IV = f5cf3227444afd905a5f6dba
+        CT =
+        AAD =
+        Tag = 1665b0f1a0b456e1664cfd3de08ccd
+        PT =
+    """).splitlines()
+    assert load_nist_vectors(vector_data) == [
+        {'aad': b'',
+         'pt': b'',
+         'iv': b'4e8df20faaf2c8eebe922902',
+         'tag': b'e39aeaebe86aa309a4d062d6274339',
+         'key': b'eac258e99c55e6ae8ef1da26640613d7',
+         'ct': b''},
+        {'aad': b'',
+         'iv': b'55fef82cde693ce76efcc193',
+         'tag': b'3d68111a81ed22d2ef5bccac4fc27f',
+         'key': b'3726cf02fcc6b8639a5497652c94350d',
+         'ct': b'',
+         'fail': True},
+        {'aad': b'',
+         'iv': b'eec51e7958c3f20a1bb71815',
+         'tag': b'a81886b3fb26e51fca87b267e1e157',
+         'key': b'f202299d5fd74f03b12d2119a6c4c038',
+         'ct': b'',
+         'fail': True},
+        {'aad': b'',
+         'pt': b'',
+         'iv': b'f5cf3227444afd905a5f6dba',
+         'tag': b'1665b0f1a0b456e1664cfd3de08ccd',
+         'key': b'fd52925f39546b4c55ffb6b20c59898c',
+         'ct': b''},
+        {'aad': b'',
+         'pt': b'',
+         'iv': b'3c819d9a9bed087615030b65',
+         'tag': b'250327c674aaf477aef2675748cf6971',
+         'key': b'11754cd72aec309bf52f7687212e8957',
+         'ct': b''},
+        {'aad': b'',
+         'pt': b'',
+         'iv': b'794ec588176c703d3d2a7a07',
+         'tag': b'b6e6f197168f5049aeda32dafbdaeb',
+         'key': b'272f16edb81a7abbea887357a58c1917',
+         'ct': b''},
+        {'aad': b'',
+         'iv': b'907763b19b9b4ab6bd4f0281',
+         'tag': b'a2be08210d8c470a8df6e8fbd79ec5cf',
+         'key': b'a49a5e26a2f8cb63d05546c2a62f5343',
+         'ct': b'',
+         'fail': True},
+        {'aad': b'e98e9d9c618e46fef32660976f854ee3',
+         'pt': b'd1448fa852b84408e2dad8381f363de7',
+         'iv': b'9549e4ba69a61cad7856efc1',
+         'tag': b'd72da7f5c6cf0bca7242c71835809449',
+         'key': b'5c1155084cc0ede76b3bc22e9f7574ef',
+         'ct': b'f78b60ca125218493bea1c50a2e12ef4'},
+    ]
diff --git a/tests/utils.py b/tests/utils.py
index df9232d..8fa9af9 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -43,8 +43,12 @@
             section = line[1:-1]
             continue
 
+        if line.strip() == "FAIL":
+            data[section, count]["fail"] = True
+            continue
+
         # Build our data using a simple Key = Value format
-        name, value = line.split(" = ")
+        name, value = [c.strip() for c in line.split("=")]
 
         # COUNT is a special token that indicates a new block of data
         if name.upper() == "COUNT":