We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Implement One Shot AESGCM
Much like our ChaCha20Poly1305 and AESCCM classes we should do AESGCM. Then we can update our streaming GCM docs to point at the one shot as a better option if you aren't dealing with large volumes of data.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/cryptography/hazmat/backends/openssl/aead.py`
Content:
```
1 # This file is dual licensed under the terms of the Apache License, Version
2 # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3 # for complete details.
4 
5 from __future__ import absolute_import, division, print_function
6 
7 from cryptography.exceptions import InvalidTag
8 
9 
10 _ENCRYPT = 1
11 _DECRYPT = 0
12 
13 
14 def _aead_cipher_name(cipher):
15     from cryptography.hazmat.primitives.ciphers.aead import (
16         AESCCM, ChaCha20Poly1305
17     )
18     if isinstance(cipher, ChaCha20Poly1305):
19         return b"chacha20-poly1305"
20     else:
21         assert isinstance(cipher, AESCCM)
22         return "aes-{0}-ccm".format(len(cipher._key) * 8).encode("ascii")
23 
24 
25 def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):
26     evp_cipher = backend._lib.EVP_get_cipherbyname(cipher_name)
27     backend.openssl_assert(evp_cipher != backend._ffi.NULL)
28     ctx = backend._lib.EVP_CIPHER_CTX_new()
29     ctx = backend._ffi.gc(ctx, backend._lib.EVP_CIPHER_CTX_free)
30     res = backend._lib.EVP_CipherInit_ex(
31         ctx, evp_cipher,
32         backend._ffi.NULL,
33         backend._ffi.NULL,
34         backend._ffi.NULL,
35         int(operation == _ENCRYPT)
36     )
37     backend.openssl_assert(res != 0)
38     res = backend._lib.EVP_CIPHER_CTX_set_key_length(ctx, len(key))
39     backend.openssl_assert(res != 0)
40     res = backend._lib.EVP_CIPHER_CTX_ctrl(
41         ctx, backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(nonce),
42         backend._ffi.NULL
43     )
44     backend.openssl_assert(res != 0)
45     if operation == _DECRYPT:
46         res = backend._lib.EVP_CIPHER_CTX_ctrl(
47             ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag
48         )
49         backend.openssl_assert(res != 0)
50     else:
51         res = backend._lib.EVP_CIPHER_CTX_ctrl(
52             ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, tag_len, backend._ffi.NULL
53         )
54 
55     res = backend._lib.EVP_CipherInit_ex(
56         ctx,
57         backend._ffi.NULL,
58         backend._ffi.NULL,
59         key,
60         nonce,
61         int(operation == _ENCRYPT)
62     )
63     backend.openssl_assert(res != 0)
64     return ctx
65 
66 
67 def _set_length(backend, ctx, data_len):
68     intptr = backend._ffi.new("int *")
69     res = backend._lib.EVP_CipherUpdate(
70         ctx,
71         backend._ffi.NULL,
72         intptr,
73         backend._ffi.NULL,
74         data_len
75     )
76     backend.openssl_assert(res != 0)
77 
78 
79 def _process_aad(backend, ctx, associated_data):
80     outlen = backend._ffi.new("int *")
81     res = backend._lib.EVP_CipherUpdate(
82         ctx, backend._ffi.NULL, outlen, associated_data, len(associated_data)
83     )
84     backend.openssl_assert(res != 0)
85 
86 
87 def _process_data(backend, ctx, data):
88     outlen = backend._ffi.new("int *")
89     buf = backend._ffi.new("unsigned char[]", len(data))
90     res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data))
91     backend.openssl_assert(res != 0)
92     return backend._ffi.buffer(buf, outlen[0])[:]
93 
94 
95 def _encrypt(backend, cipher, nonce, data, associated_data, tag_length):
96     from cryptography.hazmat.primitives.ciphers.aead import AESCCM
97     cipher_name = _aead_cipher_name(cipher)
98     ctx = _aead_setup(
99         backend, cipher_name, cipher._key, nonce, None, tag_length, _ENCRYPT
100     )
101     # CCM requires us to pass the length of the data before processing anything
102     # However calling this with any other AEAD results in an error
103     if isinstance(cipher, AESCCM):
104         _set_length(backend, ctx, len(data))
105 
106     _process_aad(backend, ctx, associated_data)
107     processed_data = _process_data(backend, ctx, data)
108     outlen = backend._ffi.new("int *")
109     res = backend._lib.EVP_CipherFinal_ex(ctx, backend._ffi.NULL, outlen)
110     backend.openssl_assert(res != 0)
111     backend.openssl_assert(outlen[0] == 0)
112     tag_buf = backend._ffi.new("unsigned char[]", tag_length)
113     res = backend._lib.EVP_CIPHER_CTX_ctrl(
114         ctx, backend._lib.EVP_CTRL_AEAD_GET_TAG, tag_length, tag_buf
115     )
116     backend.openssl_assert(res != 0)
117     tag = backend._ffi.buffer(tag_buf)[:]
118 
119     return processed_data + tag
120 
121 
122 def _decrypt(backend, cipher, nonce, data, associated_data, tag_length):
123     from cryptography.hazmat.primitives.ciphers.aead import AESCCM
124     if len(data) < tag_length:
125         raise InvalidTag
126     tag = data[-tag_length:]
127     data = data[:-tag_length]
128     cipher_name = _aead_cipher_name(cipher)
129     ctx = _aead_setup(
130         backend, cipher_name, cipher._key, nonce, tag, tag_length, _DECRYPT
131     )
132     # CCM requires us to pass the length of the data before processing anything
133     # However calling this with any other AEAD results in an error
134     if isinstance(cipher, AESCCM):
135         _set_length(backend, ctx, len(data))
136 
137     _process_aad(backend, ctx, associated_data)
138     # CCM has a different error path if the tag doesn't match. Errors are
139     # raised in Update and Final is irrelevant.
140     if isinstance(cipher, AESCCM):
141         outlen = backend._ffi.new("int *")
142         buf = backend._ffi.new("unsigned char[]", len(data))
143         res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data))
144         if res != 1:
145             backend._consume_errors()
146             raise InvalidTag
147 
148         processed_data = backend._ffi.buffer(buf, outlen[0])[:]
149     else:
150         processed_data = _process_data(backend, ctx, data)
151         outlen = backend._ffi.new("int *")
152         res = backend._lib.EVP_CipherFinal_ex(ctx, backend._ffi.NULL, outlen)
153         if res == 0:
154             backend._consume_errors()
155             raise InvalidTag
156 
157     return processed_data
158
```

Path: `src/cryptography/hazmat/primitives/ciphers/aead.py`
Content:
```
1 # This file is dual licensed under the terms of the Apache License, Version
2 # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3 # for complete details.
4 
5 from __future__ import absolute_import, division, print_function
6 
7 import os
8 
9 from cryptography import exceptions, utils
10 from cryptography.hazmat.backends.openssl import aead
11 from cryptography.hazmat.backends.openssl.backend import backend
12 
13 
14 class ChaCha20Poly1305(object):
15     def __init__(self, key):
16         if not backend.aead_cipher_supported(self):
17             raise exceptions.UnsupportedAlgorithm(
18                 "ChaCha20Poly1305 is not supported by this version of OpenSSL",
19                 exceptions._Reasons.UNSUPPORTED_CIPHER
20             )
21         utils._check_bytes("key", key)
22 
23         if len(key) != 32:
24             raise ValueError("ChaCha20Poly1305 key must be 32 bytes.")
25 
26         self._key = key
27 
28     @classmethod
29     def generate_key(cls):
30         return os.urandom(32)
31 
32     def encrypt(self, nonce, data, associated_data):
33         if associated_data is None:
34             associated_data = b""
35 
36         self._check_params(nonce, data, associated_data)
37         return aead._encrypt(
38             backend, self, nonce, data, associated_data, 16
39         )
40 
41     def decrypt(self, nonce, data, associated_data):
42         if associated_data is None:
43             associated_data = b""
44 
45         self._check_params(nonce, data, associated_data)
46         return aead._decrypt(
47             backend, self, nonce, data, associated_data, 16
48         )
49 
50     def _check_params(self, nonce, data, associated_data):
51         utils._check_bytes("nonce", nonce)
52         utils._check_bytes("data", data)
53         utils._check_bytes("associated_data", associated_data)
54         if len(nonce) != 12:
55             raise ValueError("Nonce must be 12 bytes")
56 
57 
58 class AESCCM(object):
59     def __init__(self, key, tag_length=16):
60         utils._check_bytes("key", key)
61         if len(key) not in (16, 24, 32):
62             raise ValueError("AESCCM key must be 128, 192, or 256 bits.")
63 
64         self._key = key
65         if not isinstance(tag_length, int):
66             raise TypeError("tag_length must be an integer")
67 
68         if tag_length not in (4, 6, 8, 12, 14, 16):
69             raise ValueError("Invalid tag_length")
70 
71         self._tag_length = tag_length
72 
73         if not backend.aead_cipher_supported(self):
74             raise exceptions.UnsupportedAlgorithm(
75                 "AESCCM is not supported by this version of OpenSSL",
76                 exceptions._Reasons.UNSUPPORTED_CIPHER
77             )
78 
79     @classmethod
80     def generate_key(cls, bit_length):
81         if not isinstance(bit_length, int):
82             raise TypeError("bit_length must be an integer")
83 
84         if bit_length not in (128, 192, 256):
85             raise ValueError("bit_length must be 128, 192, or 256")
86 
87         return os.urandom(bit_length // 8)
88 
89     def encrypt(self, nonce, data, associated_data):
90         if associated_data is None:
91             associated_data = b""
92 
93         self._check_params(nonce, data, associated_data)
94         self._validate_lengths(nonce, len(data))
95         return aead._encrypt(
96             backend, self, nonce, data, associated_data, self._tag_length
97         )
98 
99     def decrypt(self, nonce, data, associated_data):
100         if associated_data is None:
101             associated_data = b""
102 
103         self._check_params(nonce, data, associated_data)
104         return aead._decrypt(
105             backend, self, nonce, data, associated_data, self._tag_length
106         )
107 
108     def _validate_lengths(self, nonce, data_len):
109         # For information about computing this, see
110         # https://tools.ietf.org/html/rfc3610#section-2.1
111         l = 15 - len(nonce)
112         if 2 ** (8 * l) < data_len:
113             raise ValueError("Nonce too long for data")
114 
115     def _check_params(self, nonce, data, associated_data):
116         utils._check_bytes("nonce", nonce)
117         utils._check_bytes("data", data)
118         utils._check_bytes("associated_data", associated_data)
119         if not 7 <= len(nonce) <= 13:
120             raise ValueError("Nonce must be between 7 and 13 bytes")
121
```
--- 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/src/cryptography/hazmat/backends/openssl/aead.py b/src/cryptography/hazmat/backends/openssl/aead.py
--- a/src/cryptography/hazmat/backends/openssl/aead.py
+++ b/src/cryptography/hazmat/backends/openssl/aead.py
@@ -13,13 +13,15 @@
 
 def _aead_cipher_name(cipher):
     from cryptography.hazmat.primitives.ciphers.aead import (
-        AESCCM, ChaCha20Poly1305
+        AESCCM, AESGCM, ChaCha20Poly1305
     )
     if isinstance(cipher, ChaCha20Poly1305):
         return b"chacha20-poly1305"
-    else:
-        assert isinstance(cipher, AESCCM)
+    elif isinstance(cipher, AESCCM):
         return "aes-{0}-ccm".format(len(cipher._key) * 8).encode("ascii")
+    else:
+        assert isinstance(cipher, AESGCM)
+        return "aes-{0}-gcm".format(len(cipher._key) * 8).encode("ascii")
 
 
 def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):
diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py
--- a/src/cryptography/hazmat/primitives/ciphers/aead.py
+++ b/src/cryptography/hazmat/primitives/ciphers/aead.py
@@ -118,3 +118,45 @@
         utils._check_bytes("associated_data", associated_data)
         if not 7 <= len(nonce) <= 13:
             raise ValueError("Nonce must be between 7 and 13 bytes")
+
+
+class AESGCM(object):
+    def __init__(self, key):
+        utils._check_bytes("key", key)
+        if len(key) not in (16, 24, 32):
+            raise ValueError("AESGCM key must be 128, 192, or 256 bits.")
+
+        self._key = key
+
+    @classmethod
+    def generate_key(cls, bit_length):
+        if not isinstance(bit_length, int):
+            raise TypeError("bit_length must be an integer")
+
+        if bit_length not in (128, 192, 256):
+            raise ValueError("bit_length must be 128, 192, or 256")
+
+        return os.urandom(bit_length // 8)
+
+    def encrypt(self, nonce, data, associated_data):
+        if associated_data is None:
+            associated_data = b""
+
+        self._check_params(nonce, data, associated_data)
+        return aead._encrypt(
+            backend, self, nonce, data, associated_data, 16
+        )
+
+    def decrypt(self, nonce, data, associated_data):
+        if associated_data is None:
+            associated_data = b""
+
+        self._check_params(nonce, data, associated_data)
+        return aead._decrypt(
+            backend, self, nonce, data, associated_data, 16
+        )
+
+    def _check_params(self, nonce, data, associated_data):
+        utils._check_bytes("nonce", nonce)
+        utils._check_bytes("data", data)
+        utils._check_bytes("associated_data", associated_data)

{"golden_diff": "diff --git a/src/cryptography/hazmat/backends/openssl/aead.py b/src/cryptography/hazmat/backends/openssl/aead.py\n--- a/src/cryptography/hazmat/backends/openssl/aead.py\n+++ b/src/cryptography/hazmat/backends/openssl/aead.py\n@@ -13,13 +13,15 @@\n \n def _aead_cipher_name(cipher):\n     from cryptography.hazmat.primitives.ciphers.aead import (\n-        AESCCM, ChaCha20Poly1305\n+        AESCCM, AESGCM, ChaCha20Poly1305\n     )\n     if isinstance(cipher, ChaCha20Poly1305):\n         return b\"chacha20-poly1305\"\n-    else:\n-        assert isinstance(cipher, AESCCM)\n+    elif isinstance(cipher, AESCCM):\n         return \"aes-{0}-ccm\".format(len(cipher._key) * 8).encode(\"ascii\")\n+    else:\n+        assert isinstance(cipher, AESGCM)\n+        return \"aes-{0}-gcm\".format(len(cipher._key) * 8).encode(\"ascii\")\n \n \n def _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):\ndiff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py\n--- a/src/cryptography/hazmat/primitives/ciphers/aead.py\n+++ b/src/cryptography/hazmat/primitives/ciphers/aead.py\n@@ -118,3 +118,45 @@\n         utils._check_bytes(\"associated_data\", associated_data)\n         if not 7 <= len(nonce) <= 13:\n             raise ValueError(\"Nonce must be between 7 and 13 bytes\")\n+\n+\n+class AESGCM(object):\n+    def __init__(self, key):\n+        utils._check_bytes(\"key\", key)\n+        if len(key) not in (16, 24, 32):\n+            raise ValueError(\"AESGCM key must be 128, 192, or 256 bits.\")\n+\n+        self._key = key\n+\n+    @classmethod\n+    def generate_key(cls, bit_length):\n+        if not isinstance(bit_length, int):\n+            raise TypeError(\"bit_length must be an integer\")\n+\n+        if bit_length not in (128, 192, 256):\n+            raise ValueError(\"bit_length must be 128, 192, or 256\")\n+\n+        return os.urandom(bit_length // 8)\n+\n+    def encrypt(self, nonce, data, associated_data):\n+        if associated_data is None:\n+            associated_data = b\"\"\n+\n+        self._check_params(nonce, data, associated_data)\n+        return aead._encrypt(\n+            backend, self, nonce, data, associated_data, 16\n+        )\n+\n+    def decrypt(self, nonce, data, associated_data):\n+        if associated_data is None:\n+            associated_data = b\"\"\n+\n+        self._check_params(nonce, data, associated_data)\n+        return aead._decrypt(\n+            backend, self, nonce, data, associated_data, 16\n+        )\n+\n+    def _check_params(self, nonce, data, associated_data):\n+        utils._check_bytes(\"nonce\", nonce)\n+        utils._check_bytes(\"data\", data)\n+        utils._check_bytes(\"associated_data\", associated_data)\n", "issue": "Implement One Shot AESGCM\nMuch like our ChaCha20Poly1305 and AESCCM classes we should do AESGCM. Then we can update our streaming GCM docs to point at the one shot as a better option if you aren't dealing with large volumes of data.\n", "before_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nfrom cryptography.exceptions import InvalidTag\n\n\n_ENCRYPT = 1\n_DECRYPT = 0\n\n\ndef _aead_cipher_name(cipher):\n    from cryptography.hazmat.primitives.ciphers.aead import (\n        AESCCM, ChaCha20Poly1305\n    )\n    if isinstance(cipher, ChaCha20Poly1305):\n        return b\"chacha20-poly1305\"\n    else:\n        assert isinstance(cipher, AESCCM)\n        return \"aes-{0}-ccm\".format(len(cipher._key) * 8).encode(\"ascii\")\n\n\ndef _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):\n    evp_cipher = backend._lib.EVP_get_cipherbyname(cipher_name)\n    backend.openssl_assert(evp_cipher != backend._ffi.NULL)\n    ctx = backend._lib.EVP_CIPHER_CTX_new()\n    ctx = backend._ffi.gc(ctx, backend._lib.EVP_CIPHER_CTX_free)\n    res = backend._lib.EVP_CipherInit_ex(\n        ctx, evp_cipher,\n        backend._ffi.NULL,\n        backend._ffi.NULL,\n        backend._ffi.NULL,\n        int(operation == _ENCRYPT)\n    )\n    backend.openssl_assert(res != 0)\n    res = backend._lib.EVP_CIPHER_CTX_set_key_length(ctx, len(key))\n    backend.openssl_assert(res != 0)\n    res = backend._lib.EVP_CIPHER_CTX_ctrl(\n        ctx, backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(nonce),\n        backend._ffi.NULL\n    )\n    backend.openssl_assert(res != 0)\n    if operation == _DECRYPT:\n        res = backend._lib.EVP_CIPHER_CTX_ctrl(\n            ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag\n        )\n        backend.openssl_assert(res != 0)\n    else:\n        res = backend._lib.EVP_CIPHER_CTX_ctrl(\n            ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, tag_len, backend._ffi.NULL\n        )\n\n    res = backend._lib.EVP_CipherInit_ex(\n        ctx,\n        backend._ffi.NULL,\n        backend._ffi.NULL,\n        key,\n        nonce,\n        int(operation == _ENCRYPT)\n    )\n    backend.openssl_assert(res != 0)\n    return ctx\n\n\ndef _set_length(backend, ctx, data_len):\n    intptr = backend._ffi.new(\"int *\")\n    res = backend._lib.EVP_CipherUpdate(\n        ctx,\n        backend._ffi.NULL,\n        intptr,\n        backend._ffi.NULL,\n        data_len\n    )\n    backend.openssl_assert(res != 0)\n\n\ndef _process_aad(backend, ctx, associated_data):\n    outlen = backend._ffi.new(\"int *\")\n    res = backend._lib.EVP_CipherUpdate(\n        ctx, backend._ffi.NULL, outlen, associated_data, len(associated_data)\n    )\n    backend.openssl_assert(res != 0)\n\n\ndef _process_data(backend, ctx, data):\n    outlen = backend._ffi.new(\"int *\")\n    buf = backend._ffi.new(\"unsigned char[]\", len(data))\n    res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data))\n    backend.openssl_assert(res != 0)\n    return backend._ffi.buffer(buf, outlen[0])[:]\n\n\ndef _encrypt(backend, cipher, nonce, data, associated_data, tag_length):\n    from cryptography.hazmat.primitives.ciphers.aead import AESCCM\n    cipher_name = _aead_cipher_name(cipher)\n    ctx = _aead_setup(\n        backend, cipher_name, cipher._key, nonce, None, tag_length, _ENCRYPT\n    )\n    # CCM requires us to pass the length of the data before processing anything\n    # However calling this with any other AEAD results in an error\n    if isinstance(cipher, AESCCM):\n        _set_length(backend, ctx, len(data))\n\n    _process_aad(backend, ctx, associated_data)\n    processed_data = _process_data(backend, ctx, data)\n    outlen = backend._ffi.new(\"int *\")\n    res = backend._lib.EVP_CipherFinal_ex(ctx, backend._ffi.NULL, outlen)\n    backend.openssl_assert(res != 0)\n    backend.openssl_assert(outlen[0] == 0)\n    tag_buf = backend._ffi.new(\"unsigned char[]\", tag_length)\n    res = backend._lib.EVP_CIPHER_CTX_ctrl(\n        ctx, backend._lib.EVP_CTRL_AEAD_GET_TAG, tag_length, tag_buf\n    )\n    backend.openssl_assert(res != 0)\n    tag = backend._ffi.buffer(tag_buf)[:]\n\n    return processed_data + tag\n\n\ndef _decrypt(backend, cipher, nonce, data, associated_data, tag_length):\n    from cryptography.hazmat.primitives.ciphers.aead import AESCCM\n    if len(data) < tag_length:\n        raise InvalidTag\n    tag = data[-tag_length:]\n    data = data[:-tag_length]\n    cipher_name = _aead_cipher_name(cipher)\n    ctx = _aead_setup(\n        backend, cipher_name, cipher._key, nonce, tag, tag_length, _DECRYPT\n    )\n    # CCM requires us to pass the length of the data before processing anything\n    # However calling this with any other AEAD results in an error\n    if isinstance(cipher, AESCCM):\n        _set_length(backend, ctx, len(data))\n\n    _process_aad(backend, ctx, associated_data)\n    # CCM has a different error path if the tag doesn't match. Errors are\n    # raised in Update and Final is irrelevant.\n    if isinstance(cipher, AESCCM):\n        outlen = backend._ffi.new(\"int *\")\n        buf = backend._ffi.new(\"unsigned char[]\", len(data))\n        res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data))\n        if res != 1:\n            backend._consume_errors()\n            raise InvalidTag\n\n        processed_data = backend._ffi.buffer(buf, outlen[0])[:]\n    else:\n        processed_data = _process_data(backend, ctx, data)\n        outlen = backend._ffi.new(\"int *\")\n        res = backend._lib.EVP_CipherFinal_ex(ctx, backend._ffi.NULL, outlen)\n        if res == 0:\n            backend._consume_errors()\n            raise InvalidTag\n\n    return processed_data\n", "path": "src/cryptography/hazmat/backends/openssl/aead.py"}, {"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nimport os\n\nfrom cryptography import exceptions, utils\nfrom cryptography.hazmat.backends.openssl import aead\nfrom cryptography.hazmat.backends.openssl.backend import backend\n\n\nclass ChaCha20Poly1305(object):\n    def __init__(self, key):\n        if not backend.aead_cipher_supported(self):\n            raise exceptions.UnsupportedAlgorithm(\n                \"ChaCha20Poly1305 is not supported by this version of OpenSSL\",\n                exceptions._Reasons.UNSUPPORTED_CIPHER\n            )\n        utils._check_bytes(\"key\", key)\n\n        if len(key) != 32:\n            raise ValueError(\"ChaCha20Poly1305 key must be 32 bytes.\")\n\n        self._key = key\n\n    @classmethod\n    def generate_key(cls):\n        return os.urandom(32)\n\n    def encrypt(self, nonce, data, associated_data):\n        if associated_data is None:\n            associated_data = b\"\"\n\n        self._check_params(nonce, data, associated_data)\n        return aead._encrypt(\n            backend, self, nonce, data, associated_data, 16\n        )\n\n    def decrypt(self, nonce, data, associated_data):\n        if associated_data is None:\n            associated_data = b\"\"\n\n        self._check_params(nonce, data, associated_data)\n        return aead._decrypt(\n            backend, self, nonce, data, associated_data, 16\n        )\n\n    def _check_params(self, nonce, data, associated_data):\n        utils._check_bytes(\"nonce\", nonce)\n        utils._check_bytes(\"data\", data)\n        utils._check_bytes(\"associated_data\", associated_data)\n        if len(nonce) != 12:\n            raise ValueError(\"Nonce must be 12 bytes\")\n\n\nclass AESCCM(object):\n    def __init__(self, key, tag_length=16):\n        utils._check_bytes(\"key\", key)\n        if len(key) not in (16, 24, 32):\n            raise ValueError(\"AESCCM key must be 128, 192, or 256 bits.\")\n\n        self._key = key\n        if not isinstance(tag_length, int):\n            raise TypeError(\"tag_length must be an integer\")\n\n        if tag_length not in (4, 6, 8, 12, 14, 16):\n            raise ValueError(\"Invalid tag_length\")\n\n        self._tag_length = tag_length\n\n        if not backend.aead_cipher_supported(self):\n            raise exceptions.UnsupportedAlgorithm(\n                \"AESCCM is not supported by this version of OpenSSL\",\n                exceptions._Reasons.UNSUPPORTED_CIPHER\n            )\n\n    @classmethod\n    def generate_key(cls, bit_length):\n        if not isinstance(bit_length, int):\n            raise TypeError(\"bit_length must be an integer\")\n\n        if bit_length not in (128, 192, 256):\n            raise ValueError(\"bit_length must be 128, 192, or 256\")\n\n        return os.urandom(bit_length // 8)\n\n    def encrypt(self, nonce, data, associated_data):\n        if associated_data is None:\n            associated_data = b\"\"\n\n        self._check_params(nonce, data, associated_data)\n        self._validate_lengths(nonce, len(data))\n        return aead._encrypt(\n            backend, self, nonce, data, associated_data, self._tag_length\n        )\n\n    def decrypt(self, nonce, data, associated_data):\n        if associated_data is None:\n            associated_data = b\"\"\n\n        self._check_params(nonce, data, associated_data)\n        return aead._decrypt(\n            backend, self, nonce, data, associated_data, self._tag_length\n        )\n\n    def _validate_lengths(self, nonce, data_len):\n        # For information about computing this, see\n        # https://tools.ietf.org/html/rfc3610#section-2.1\n        l = 15 - len(nonce)\n        if 2 ** (8 * l) < data_len:\n            raise ValueError(\"Nonce too long for data\")\n\n    def _check_params(self, nonce, data, associated_data):\n        utils._check_bytes(\"nonce\", nonce)\n        utils._check_bytes(\"data\", data)\n        utils._check_bytes(\"associated_data\", associated_data)\n        if not 7 <= len(nonce) <= 13:\n            raise ValueError(\"Nonce must be between 7 and 13 bytes\")\n", "path": "src/cryptography/hazmat/primitives/ciphers/aead.py"}], "after_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nfrom cryptography.exceptions import InvalidTag\n\n\n_ENCRYPT = 1\n_DECRYPT = 0\n\n\ndef _aead_cipher_name(cipher):\n    from cryptography.hazmat.primitives.ciphers.aead import (\n        AESCCM, AESGCM, ChaCha20Poly1305\n    )\n    if isinstance(cipher, ChaCha20Poly1305):\n        return b\"chacha20-poly1305\"\n    elif isinstance(cipher, AESCCM):\n        return \"aes-{0}-ccm\".format(len(cipher._key) * 8).encode(\"ascii\")\n    else:\n        assert isinstance(cipher, AESGCM)\n        return \"aes-{0}-gcm\".format(len(cipher._key) * 8).encode(\"ascii\")\n\n\ndef _aead_setup(backend, cipher_name, key, nonce, tag, tag_len, operation):\n    evp_cipher = backend._lib.EVP_get_cipherbyname(cipher_name)\n    backend.openssl_assert(evp_cipher != backend._ffi.NULL)\n    ctx = backend._lib.EVP_CIPHER_CTX_new()\n    ctx = backend._ffi.gc(ctx, backend._lib.EVP_CIPHER_CTX_free)\n    res = backend._lib.EVP_CipherInit_ex(\n        ctx, evp_cipher,\n        backend._ffi.NULL,\n        backend._ffi.NULL,\n        backend._ffi.NULL,\n        int(operation == _ENCRYPT)\n    )\n    backend.openssl_assert(res != 0)\n    res = backend._lib.EVP_CIPHER_CTX_set_key_length(ctx, len(key))\n    backend.openssl_assert(res != 0)\n    res = backend._lib.EVP_CIPHER_CTX_ctrl(\n        ctx, backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(nonce),\n        backend._ffi.NULL\n    )\n    backend.openssl_assert(res != 0)\n    if operation == _DECRYPT:\n        res = backend._lib.EVP_CIPHER_CTX_ctrl(\n            ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag\n        )\n        backend.openssl_assert(res != 0)\n    else:\n        res = backend._lib.EVP_CIPHER_CTX_ctrl(\n            ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, tag_len, backend._ffi.NULL\n        )\n\n    res = backend._lib.EVP_CipherInit_ex(\n        ctx,\n        backend._ffi.NULL,\n        backend._ffi.NULL,\n        key,\n        nonce,\n        int(operation == _ENCRYPT)\n    )\n    backend.openssl_assert(res != 0)\n    return ctx\n\n\ndef _set_length(backend, ctx, data_len):\n    intptr = backend._ffi.new(\"int *\")\n    res = backend._lib.EVP_CipherUpdate(\n        ctx,\n        backend._ffi.NULL,\n        intptr,\n        backend._ffi.NULL,\n        data_len\n    )\n    backend.openssl_assert(res != 0)\n\n\ndef _process_aad(backend, ctx, associated_data):\n    outlen = backend._ffi.new(\"int *\")\n    res = backend._lib.EVP_CipherUpdate(\n        ctx, backend._ffi.NULL, outlen, associated_data, len(associated_data)\n    )\n    backend.openssl_assert(res != 0)\n\n\ndef _process_data(backend, ctx, data):\n    outlen = backend._ffi.new(\"int *\")\n    buf = backend._ffi.new(\"unsigned char[]\", len(data))\n    res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data))\n    backend.openssl_assert(res != 0)\n    return backend._ffi.buffer(buf, outlen[0])[:]\n\n\ndef _encrypt(backend, cipher, nonce, data, associated_data, tag_length):\n    from cryptography.hazmat.primitives.ciphers.aead import AESCCM\n    cipher_name = _aead_cipher_name(cipher)\n    ctx = _aead_setup(\n        backend, cipher_name, cipher._key, nonce, None, tag_length, _ENCRYPT\n    )\n    # CCM requires us to pass the length of the data before processing anything\n    # However calling this with any other AEAD results in an error\n    if isinstance(cipher, AESCCM):\n        _set_length(backend, ctx, len(data))\n\n    _process_aad(backend, ctx, associated_data)\n    processed_data = _process_data(backend, ctx, data)\n    outlen = backend._ffi.new(\"int *\")\n    res = backend._lib.EVP_CipherFinal_ex(ctx, backend._ffi.NULL, outlen)\n    backend.openssl_assert(res != 0)\n    backend.openssl_assert(outlen[0] == 0)\n    tag_buf = backend._ffi.new(\"unsigned char[]\", tag_length)\n    res = backend._lib.EVP_CIPHER_CTX_ctrl(\n        ctx, backend._lib.EVP_CTRL_AEAD_GET_TAG, tag_length, tag_buf\n    )\n    backend.openssl_assert(res != 0)\n    tag = backend._ffi.buffer(tag_buf)[:]\n\n    return processed_data + tag\n\n\ndef _decrypt(backend, cipher, nonce, data, associated_data, tag_length):\n    from cryptography.hazmat.primitives.ciphers.aead import AESCCM\n    if len(data) < tag_length:\n        raise InvalidTag\n    tag = data[-tag_length:]\n    data = data[:-tag_length]\n    cipher_name = _aead_cipher_name(cipher)\n    ctx = _aead_setup(\n        backend, cipher_name, cipher._key, nonce, tag, tag_length, _DECRYPT\n    )\n    # CCM requires us to pass the length of the data before processing anything\n    # However calling this with any other AEAD results in an error\n    if isinstance(cipher, AESCCM):\n        _set_length(backend, ctx, len(data))\n\n    _process_aad(backend, ctx, associated_data)\n    # CCM has a different error path if the tag doesn't match. Errors are\n    # raised in Update and Final is irrelevant.\n    if isinstance(cipher, AESCCM):\n        outlen = backend._ffi.new(\"int *\")\n        buf = backend._ffi.new(\"unsigned char[]\", len(data))\n        res = backend._lib.EVP_CipherUpdate(ctx, buf, outlen, data, len(data))\n        if res != 1:\n            backend._consume_errors()\n            raise InvalidTag\n\n        processed_data = backend._ffi.buffer(buf, outlen[0])[:]\n    else:\n        processed_data = _process_data(backend, ctx, data)\n        outlen = backend._ffi.new(\"int *\")\n        res = backend._lib.EVP_CipherFinal_ex(ctx, backend._ffi.NULL, outlen)\n        if res == 0:\n            backend._consume_errors()\n            raise InvalidTag\n\n    return processed_data\n", "path": "src/cryptography/hazmat/backends/openssl/aead.py"}, {"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nimport os\n\nfrom cryptography import exceptions, utils\nfrom cryptography.hazmat.backends.openssl import aead\nfrom cryptography.hazmat.backends.openssl.backend import backend\n\n\nclass ChaCha20Poly1305(object):\n    def __init__(self, key):\n        if not backend.aead_cipher_supported(self):\n            raise exceptions.UnsupportedAlgorithm(\n                \"ChaCha20Poly1305 is not supported by this version of OpenSSL\",\n                exceptions._Reasons.UNSUPPORTED_CIPHER\n            )\n        utils._check_bytes(\"key\", key)\n\n        if len(key) != 32:\n            raise ValueError(\"ChaCha20Poly1305 key must be 32 bytes.\")\n\n        self._key = key\n\n    @classmethod\n    def generate_key(cls):\n        return os.urandom(32)\n\n    def encrypt(self, nonce, data, associated_data):\n        if associated_data is None:\n            associated_data = b\"\"\n\n        self._check_params(nonce, data, associated_data)\n        return aead._encrypt(\n            backend, self, nonce, data, associated_data, 16\n        )\n\n    def decrypt(self, nonce, data, associated_data):\n        if associated_data is None:\n            associated_data = b\"\"\n\n        self._check_params(nonce, data, associated_data)\n        return aead._decrypt(\n            backend, self, nonce, data, associated_data, 16\n        )\n\n    def _check_params(self, nonce, data, associated_data):\n        utils._check_bytes(\"nonce\", nonce)\n        utils._check_bytes(\"data\", data)\n        utils._check_bytes(\"associated_data\", associated_data)\n        if len(nonce) != 12:\n            raise ValueError(\"Nonce must be 12 bytes\")\n\n\nclass AESCCM(object):\n    def __init__(self, key, tag_length=16):\n        utils._check_bytes(\"key\", key)\n        if len(key) not in (16, 24, 32):\n            raise ValueError(\"AESCCM key must be 128, 192, or 256 bits.\")\n\n        self._key = key\n        if not isinstance(tag_length, int):\n            raise TypeError(\"tag_length must be an integer\")\n\n        if tag_length not in (4, 6, 8, 12, 14, 16):\n            raise ValueError(\"Invalid tag_length\")\n\n        self._tag_length = tag_length\n\n        if not backend.aead_cipher_supported(self):\n            raise exceptions.UnsupportedAlgorithm(\n                \"AESCCM is not supported by this version of OpenSSL\",\n                exceptions._Reasons.UNSUPPORTED_CIPHER\n            )\n\n    @classmethod\n    def generate_key(cls, bit_length):\n        if not isinstance(bit_length, int):\n            raise TypeError(\"bit_length must be an integer\")\n\n        if bit_length not in (128, 192, 256):\n            raise ValueError(\"bit_length must be 128, 192, or 256\")\n\n        return os.urandom(bit_length // 8)\n\n    def encrypt(self, nonce, data, associated_data):\n        if associated_data is None:\n            associated_data = b\"\"\n\n        self._check_params(nonce, data, associated_data)\n        self._validate_lengths(nonce, len(data))\n        return aead._encrypt(\n            backend, self, nonce, data, associated_data, self._tag_length\n        )\n\n    def decrypt(self, nonce, data, associated_data):\n        if associated_data is None:\n            associated_data = b\"\"\n\n        self._check_params(nonce, data, associated_data)\n        return aead._decrypt(\n            backend, self, nonce, data, associated_data, self._tag_length\n        )\n\n    def _validate_lengths(self, nonce, data_len):\n        # For information about computing this, see\n        # https://tools.ietf.org/html/rfc3610#section-2.1\n        l = 15 - len(nonce)\n        if 2 ** (8 * l) < data_len:\n            raise ValueError(\"Nonce too long for data\")\n\n    def _check_params(self, nonce, data, associated_data):\n        utils._check_bytes(\"nonce\", nonce)\n        utils._check_bytes(\"data\", data)\n        utils._check_bytes(\"associated_data\", associated_data)\n        if not 7 <= len(nonce) <= 13:\n            raise ValueError(\"Nonce must be between 7 and 13 bytes\")\n\n\nclass AESGCM(object):\n    def __init__(self, key):\n        utils._check_bytes(\"key\", key)\n        if len(key) not in (16, 24, 32):\n            raise ValueError(\"AESGCM key must be 128, 192, or 256 bits.\")\n\n        self._key = key\n\n    @classmethod\n    def generate_key(cls, bit_length):\n        if not isinstance(bit_length, int):\n            raise TypeError(\"bit_length must be an integer\")\n\n        if bit_length not in (128, 192, 256):\n            raise ValueError(\"bit_length must be 128, 192, or 256\")\n\n        return os.urandom(bit_length // 8)\n\n    def encrypt(self, nonce, data, associated_data):\n        if associated_data is None:\n            associated_data = b\"\"\n\n        self._check_params(nonce, data, associated_data)\n        return aead._encrypt(\n            backend, self, nonce, data, associated_data, 16\n        )\n\n    def decrypt(self, nonce, data, associated_data):\n        if associated_data is None:\n            associated_data = b\"\"\n\n        self._check_params(nonce, data, associated_data)\n        return aead._decrypt(\n            backend, self, nonce, data, associated_data, 16\n        )\n\n    def _check_params(self, nonce, data, associated_data):\n        utils._check_bytes(\"nonce\", nonce)\n        utils._check_bytes(\"data\", data)\n        utils._check_bytes(\"associated_data\", associated_data)\n", "path": "src/cryptography/hazmat/primitives/ciphers/aead.py"}]}