Merge pull request #1341 from michael-hart/ec_vectors

Test Vector changes
diff --git a/cryptography/hazmat/backends/commoncrypto/ciphers.py b/cryptography/hazmat/backends/commoncrypto/ciphers.py
index 525500c..6d3ba86 100644
--- a/cryptography/hazmat/backends/commoncrypto/ciphers.py
+++ b/cryptography/hazmat/backends/commoncrypto/ciphers.py
@@ -151,6 +151,12 @@
             len(mode.initialization_vector)
         )
         self._backend._check_cipher_response(res)
+        # CommonCrypto has a bug where calling update without at least one
+        # call to authenticate_additional_data will result in null byte output
+        # for ciphertext. The following empty byte string call prevents the
+        # issue, which is present in at least 10.8 and 10.9.
+        # Filed as rdar://18314544
+        self.authenticate_additional_data(b"")
 
     def update(self, data):
         buf = self._backend._ffi.new("unsigned char[]", len(data))
@@ -164,6 +170,12 @@
         return self._backend._ffi.buffer(buf)[:]
 
     def finalize(self):
+        # CommonCrypto has a yet another bug where you must make at least one
+        # call to update. If you pass just AAD and call finalize without a call
+        # to update you'll get null bytes for tag. The following update call
+        # prevents this issue, which is present in at least 10.8 and 10.9.
+        # Filed as rdar://18314580
+        self.update(b"")
         tag_size = self._cipher.block_size // 8
         tag_buf = self._backend._ffi.new("unsigned char[]", tag_size)
         tag_len = self._backend._ffi.new("size_t *", tag_size)
diff --git a/cryptography/hazmat/backends/openssl/ciphers.py b/cryptography/hazmat/backends/openssl/ciphers.py
index c3a5499..d37bb01 100644
--- a/cryptography/hazmat/backends/openssl/ciphers.py
+++ b/cryptography/hazmat/backends/openssl/ciphers.py
@@ -128,6 +128,14 @@
         return self._backend._ffi.buffer(buf)[:outlen[0]]
 
     def finalize(self):
+        # OpenSSL 1.0.1 on Ubuntu 12.04 (and possibly other distributions)
+        # appears to have a bug where you must make at least one call to update
+        # even if you are only using authenticate_additional_data or the
+        # GCM tag will be wrong. An (empty) call to update resolves this
+        # and is harmless for all other versions of OpenSSL.
+        if isinstance(self._mode, GCM):
+            self.update(b"")
+
         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)
diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py
index 5bde7d3..e8e0eee 100644
--- a/tests/hazmat/primitives/test_aes.py
+++ b/tests/hazmat/primitives/test_aes.py
@@ -18,7 +18,7 @@
 
 import pytest
 
-from cryptography.hazmat.primitives.ciphers import algorithms, modes
+from cryptography.hazmat.primitives.ciphers import algorithms, base, modes
 
 from .utils import generate_aead_test, generate_encrypt_test
 from ...utils import load_nist_vectors
@@ -228,3 +228,36 @@
         algorithms.AES,
         modes.GCM,
     )
+
+    def test_gcm_tag_with_only_aad(self, backend):
+        key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3")
+        iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d")
+        aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193")
+        tag = binascii.unhexlify(b"0f247e7f9c2505de374006738018493b")
+
+        cipher = base.Cipher(
+            algorithms.AES(key),
+            modes.GCM(iv),
+            backend=backend
+        )
+        encryptor = cipher.encryptor()
+        encryptor.authenticate_additional_data(aad)
+        encryptor.finalize()
+        assert encryptor.tag == tag
+
+    def test_gcm_ciphertext_with_no_aad(self, backend):
+        key = binascii.unhexlify(b"e98b72a9881a84ca6b76e0f43e68647a")
+        iv = binascii.unhexlify(b"8b23299fde174053f3d652ba")
+        ct = binascii.unhexlify(b"5a3c1cf1985dbb8bed818036fdd5ab42")
+        tag = binascii.unhexlify(b"23c7ab0f952b7091cd324835043b5eb5")
+        pt = binascii.unhexlify(b"28286a321293253c3e0aa2704a278032")
+
+        cipher = base.Cipher(
+            algorithms.AES(key),
+            modes.GCM(iv),
+            backend=backend
+        )
+        encryptor = cipher.encryptor()
+        computed_ct = encryptor.update(pt) + encryptor.finalize()
+        assert computed_ct == ct
+        assert encryptor.tag == tag