We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Make it harder to allow truncation on a GCM tag
`GCM()` should take a `min_tag_length` parameter, which defaults to `GCM.MAX_TAG_LENGTH`, then we can make it error out on truncated tags by default, while still allowing truncation for use cases that need it.

This is technically a backwards compatibility break, but I argue that it should be allowed as a security hardening measure. Thoughts?


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cryptography/__about__.py`
Content:
```
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 #    http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10 # implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13 from __future__ import absolute_import, division, print_function
14 
15 __all__ = [
16     "__title__", "__summary__", "__uri__", "__version__", "__author__",
17     "__email__", "__license__", "__copyright__",
18 ]
19 
20 __title__ = "cryptography"
21 __summary__ = ("cryptography is a package which provides cryptographic recipes"
22                " and primitives to Python developers.")
23 __uri__ = "https://github.com/pyca/cryptography"
24 
25 __version__ = "0.5.dev1"
26 
27 __author__ = "The cryptography developers"
28 __email__ = "cryptography-dev@python.org"
29 
30 __license__ = "Apache License, Version 2.0"
31 __copyright__ = "Copyright 2013-2014 %s" % __author__
32
```

Path: `cryptography/hazmat/primitives/ciphers/modes.py`
Content:
```
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 #    http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10 # implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13 
14 from __future__ import absolute_import, division, print_function
15 
16 from cryptography import utils
17 from cryptography.hazmat.primitives import interfaces
18 
19 
20 def _check_iv_length(mode, algorithm):
21     if len(mode.initialization_vector) * 8 != algorithm.block_size:
22         raise ValueError("Invalid IV size ({0}) for {1}.".format(
23             len(mode.initialization_vector), mode.name
24         ))
25 
26 
27 @utils.register_interface(interfaces.Mode)
28 @utils.register_interface(interfaces.ModeWithInitializationVector)
29 class CBC(object):
30     name = "CBC"
31 
32     def __init__(self, initialization_vector):
33         self.initialization_vector = initialization_vector
34 
35     validate_for_algorithm = _check_iv_length
36 
37 
38 @utils.register_interface(interfaces.Mode)
39 class ECB(object):
40     name = "ECB"
41 
42     def validate_for_algorithm(self, algorithm):
43         pass
44 
45 
46 @utils.register_interface(interfaces.Mode)
47 @utils.register_interface(interfaces.ModeWithInitializationVector)
48 class OFB(object):
49     name = "OFB"
50 
51     def __init__(self, initialization_vector):
52         self.initialization_vector = initialization_vector
53 
54     validate_for_algorithm = _check_iv_length
55 
56 
57 @utils.register_interface(interfaces.Mode)
58 @utils.register_interface(interfaces.ModeWithInitializationVector)
59 class CFB(object):
60     name = "CFB"
61 
62     def __init__(self, initialization_vector):
63         self.initialization_vector = initialization_vector
64 
65     validate_for_algorithm = _check_iv_length
66 
67 
68 @utils.register_interface(interfaces.Mode)
69 @utils.register_interface(interfaces.ModeWithInitializationVector)
70 class CFB8(object):
71     name = "CFB8"
72 
73     def __init__(self, initialization_vector):
74         self.initialization_vector = initialization_vector
75 
76     validate_for_algorithm = _check_iv_length
77 
78 
79 @utils.register_interface(interfaces.Mode)
80 @utils.register_interface(interfaces.ModeWithNonce)
81 class CTR(object):
82     name = "CTR"
83 
84     def __init__(self, nonce):
85         self.nonce = nonce
86 
87     def validate_for_algorithm(self, algorithm):
88         if len(self.nonce) * 8 != algorithm.block_size:
89             raise ValueError("Invalid nonce size ({0}) for {1}.".format(
90                 len(self.nonce), self.name
91             ))
92 
93 
94 @utils.register_interface(interfaces.Mode)
95 @utils.register_interface(interfaces.ModeWithInitializationVector)
96 @utils.register_interface(interfaces.ModeWithAuthenticationTag)
97 class GCM(object):
98     name = "GCM"
99 
100     def __init__(self, initialization_vector, tag=None):
101         # len(initialization_vector) must in [1, 2 ** 64), but it's impossible
102         # to actually construct a bytes object that large, so we don't check
103         # for it
104         if tag is not None and len(tag) < 4:
105             raise ValueError(
106                 "Authentication tag must be 4 bytes or longer."
107             )
108 
109         self.initialization_vector = initialization_vector
110         self.tag = tag
111 
112     def validate_for_algorithm(self, algorithm):
113         pass
114
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/cryptography/__about__.py b/cryptography/__about__.py
--- a/cryptography/__about__.py
+++ b/cryptography/__about__.py
@@ -28,4 +28,4 @@
 __email__ = "cryptography-dev@python.org"
 
 __license__ = "Apache License, Version 2.0"
-__copyright__ = "Copyright 2013-2014 %s" % __author__
+__copyright__ = "Copyright 2013-2014 {0}".format(__author__)
diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py
--- a/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/cryptography/hazmat/primitives/ciphers/modes.py
@@ -97,13 +97,16 @@
 class GCM(object):
     name = "GCM"
 
-    def __init__(self, initialization_vector, tag=None):
+    def __init__(self, initialization_vector, tag=None, min_tag_length=16):
         # len(initialization_vector) must in [1, 2 ** 64), but it's impossible
         # to actually construct a bytes object that large, so we don't check
         # for it
-        if tag is not None and len(tag) < 4:
+        if min_tag_length < 4:
+            raise ValueError("min_tag_length must be >= 4")
+        if tag is not None and len(tag) < min_tag_length:
             raise ValueError(
-                "Authentication tag must be 4 bytes or longer."
+                "Authentication tag must be {0} bytes or longer.".format(
+                    min_tag_length)
             )
 
         self.initialization_vector = initialization_vector

{"golden_diff": "diff --git a/cryptography/__about__.py b/cryptography/__about__.py\n--- a/cryptography/__about__.py\n+++ b/cryptography/__about__.py\n@@ -28,4 +28,4 @@\n __email__ = \"cryptography-dev@python.org\"\n \n __license__ = \"Apache License, Version 2.0\"\n-__copyright__ = \"Copyright 2013-2014 %s\" % __author__\n+__copyright__ = \"Copyright 2013-2014 {0}\".format(__author__)\ndiff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py\n--- a/cryptography/hazmat/primitives/ciphers/modes.py\n+++ b/cryptography/hazmat/primitives/ciphers/modes.py\n@@ -97,13 +97,16 @@\n class GCM(object):\n     name = \"GCM\"\n \n-    def __init__(self, initialization_vector, tag=None):\n+    def __init__(self, initialization_vector, tag=None, min_tag_length=16):\n         # len(initialization_vector) must in [1, 2 ** 64), but it's impossible\n         # to actually construct a bytes object that large, so we don't check\n         # for it\n-        if tag is not None and len(tag) < 4:\n+        if min_tag_length < 4:\n+            raise ValueError(\"min_tag_length must be >= 4\")\n+        if tag is not None and len(tag) < min_tag_length:\n             raise ValueError(\n-                \"Authentication tag must be 4 bytes or longer.\"\n+                \"Authentication tag must be {0} bytes or longer.\".format(\n+                    min_tag_length)\n             )\n \n         self.initialization_vector = initialization_vector\n", "issue": "Make it harder to allow truncation on a GCM tag\n`GCM()` should take a `min_tag_length` parameter, which defaults to `GCM.MAX_TAG_LENGTH`, then we can make it error out on truncated tags by default, while still allowing truncation for use cases that need it.\n\nThis is technically a backwards compatibility break, but I argue that it should be allowed as a security hardening measure. Thoughts?\n\n", "before_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n# implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom __future__ import absolute_import, division, print_function\n\n__all__ = [\n    \"__title__\", \"__summary__\", \"__uri__\", \"__version__\", \"__author__\",\n    \"__email__\", \"__license__\", \"__copyright__\",\n]\n\n__title__ = \"cryptography\"\n__summary__ = (\"cryptography is a package which provides cryptographic recipes\"\n               \" and primitives to Python developers.\")\n__uri__ = \"https://github.com/pyca/cryptography\"\n\n__version__ = \"0.5.dev1\"\n\n__author__ = \"The cryptography developers\"\n__email__ = \"cryptography-dev@python.org\"\n\n__license__ = \"Apache License, Version 2.0\"\n__copyright__ = \"Copyright 2013-2014 %s\" % __author__\n", "path": "cryptography/__about__.py"}, {"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n# implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import absolute_import, division, print_function\n\nfrom cryptography import utils\nfrom cryptography.hazmat.primitives import interfaces\n\n\ndef _check_iv_length(mode, algorithm):\n    if len(mode.initialization_vector) * 8 != algorithm.block_size:\n        raise ValueError(\"Invalid IV size ({0}) for {1}.\".format(\n            len(mode.initialization_vector), mode.name\n        ))\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass CBC(object):\n    name = \"CBC\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\nclass ECB(object):\n    name = \"ECB\"\n\n    def validate_for_algorithm(self, algorithm):\n        pass\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass OFB(object):\n    name = \"OFB\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass CFB(object):\n    name = \"CFB\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass CFB8(object):\n    name = \"CFB8\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithNonce)\nclass CTR(object):\n    name = \"CTR\"\n\n    def __init__(self, nonce):\n        self.nonce = nonce\n\n    def validate_for_algorithm(self, algorithm):\n        if len(self.nonce) * 8 != algorithm.block_size:\n            raise ValueError(\"Invalid nonce size ({0}) for {1}.\".format(\n                len(self.nonce), self.name\n            ))\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\n@utils.register_interface(interfaces.ModeWithAuthenticationTag)\nclass GCM(object):\n    name = \"GCM\"\n\n    def __init__(self, initialization_vector, tag=None):\n        # len(initialization_vector) must in [1, 2 ** 64), but it's impossible\n        # to actually construct a bytes object that large, so we don't check\n        # for it\n        if tag is not None and len(tag) < 4:\n            raise ValueError(\n                \"Authentication tag must be 4 bytes or longer.\"\n            )\n\n        self.initialization_vector = initialization_vector\n        self.tag = tag\n\n    def validate_for_algorithm(self, algorithm):\n        pass\n", "path": "cryptography/hazmat/primitives/ciphers/modes.py"}], "after_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n# implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom __future__ import absolute_import, division, print_function\n\n__all__ = [\n    \"__title__\", \"__summary__\", \"__uri__\", \"__version__\", \"__author__\",\n    \"__email__\", \"__license__\", \"__copyright__\",\n]\n\n__title__ = \"cryptography\"\n__summary__ = (\"cryptography is a package which provides cryptographic recipes\"\n               \" and primitives to Python developers.\")\n__uri__ = \"https://github.com/pyca/cryptography\"\n\n__version__ = \"0.5.dev1\"\n\n__author__ = \"The cryptography developers\"\n__email__ = \"cryptography-dev@python.org\"\n\n__license__ = \"Apache License, Version 2.0\"\n__copyright__ = \"Copyright 2013-2014 {0}\".format(__author__)\n", "path": "cryptography/__about__.py"}, {"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n# implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import absolute_import, division, print_function\n\nfrom cryptography import utils\nfrom cryptography.hazmat.primitives import interfaces\n\n\ndef _check_iv_length(mode, algorithm):\n    if len(mode.initialization_vector) * 8 != algorithm.block_size:\n        raise ValueError(\"Invalid IV size ({0}) for {1}.\".format(\n            len(mode.initialization_vector), mode.name\n        ))\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass CBC(object):\n    name = \"CBC\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\nclass ECB(object):\n    name = \"ECB\"\n\n    def validate_for_algorithm(self, algorithm):\n        pass\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass OFB(object):\n    name = \"OFB\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass CFB(object):\n    name = \"CFB\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\nclass CFB8(object):\n    name = \"CFB8\"\n\n    def __init__(self, initialization_vector):\n        self.initialization_vector = initialization_vector\n\n    validate_for_algorithm = _check_iv_length\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithNonce)\nclass CTR(object):\n    name = \"CTR\"\n\n    def __init__(self, nonce):\n        self.nonce = nonce\n\n    def validate_for_algorithm(self, algorithm):\n        if len(self.nonce) * 8 != algorithm.block_size:\n            raise ValueError(\"Invalid nonce size ({0}) for {1}.\".format(\n                len(self.nonce), self.name\n            ))\n\n\n@utils.register_interface(interfaces.Mode)\n@utils.register_interface(interfaces.ModeWithInitializationVector)\n@utils.register_interface(interfaces.ModeWithAuthenticationTag)\nclass GCM(object):\n    name = \"GCM\"\n\n    def __init__(self, initialization_vector, tag=None, min_tag_length=16):\n        # len(initialization_vector) must in [1, 2 ** 64), but it's impossible\n        # to actually construct a bytes object that large, so we don't check\n        # for it\n        if min_tag_length < 4:\n            raise ValueError(\"min_tag_length must be >= 4\")\n        if tag is not None and len(tag) < min_tag_length:\n            raise ValueError(\n                \"Authentication tag must be {0} bytes or longer.\".format(\n                    min_tag_length)\n            )\n\n        self.initialization_vector = initialization_vector\n        self.tag = tag\n\n    def validate_for_algorithm(self, algorithm):\n        pass\n", "path": "cryptography/hazmat/primitives/ciphers/modes.py"}]}