Merge pull request #327 from reaperhulk/gcm-lower-limit-tag

Restrict GCM tag length to 4+ bytes
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index b9e8b89..bd3eee2 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -319,9 +319,9 @@
             )
             assert res != 0
             if operation == self._DECRYPT:
-                if not mode.tag:
-                    raise ValueError("Authentication tag must be supplied "
-                                     "when decrypting")
+                if not mode.tag or len(mode.tag) < 4:
+                    raise ValueError("Authentication tag must be provided and "
+                                     "be 4 bytes or longer when decrypting")
                 res = self._backend.lib.EVP_CIPHER_CTX_ctrl(
                     ctx, self._backend.lib.Cryptography_EVP_CTRL_GCM_SET_TAG,
                     len(mode.tag), mode.tag
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index f4d0457..6e3c102 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -352,6 +352,16 @@
                                         Do not reuse an ``initialization_vector``
                                         with a given ``key``.
 
+    .. note::
+
+        Cryptography will emit a 128-bit tag when finalizing encryption.
+        You can shorten a tag by truncating it to the desired length, but this
+        is **not recommended** as it lowers the security margins of the
+        authentication (`NIST SP-800-38D`_ recommends 96-bits or greater).
+        If you must shorten the tag the minimum allowed length is 4 bytes
+        (32-bits). Applications **must** verify the tag is the expected length
+        to guarantee the expected security margin.
+
     :param bytes tag: The tag bytes to verify during decryption. When encrypting
                       this must be None.
 
@@ -390,3 +400,4 @@
 
 .. _`described by Colin Percival`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
 .. _`recommends 96-bit IV length`: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
+.. _`NIST SP-800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py
index 227a405..b00d318 100644
--- a/tests/hazmat/primitives/utils.py
+++ b/tests/hazmat/primitives/utils.py
@@ -363,6 +363,13 @@
         cipher.decryptor()
     cipher = Cipher(
         cipher_factory(binascii.unhexlify(b"0" * 32)),
+        mode_factory(binascii.unhexlify(b"0" * 24), b"000"),
+        backend
+    )
+    with pytest.raises(ValueError):
+        cipher.decryptor()
+    cipher = Cipher(
+        cipher_factory(binascii.unhexlify(b"0" * 32)),
         mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
         backend
     )