We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
aes keywrap with padding does properly handle key to wrap length % 8 == 0
@SalusaSecondus and I found a bug in the new `aes_key_unwrap_with_padding` for wrapped keys where the plaintext is multiples of 8 bytes. Strangely, it looks like the NIST test vectors used do include cases like this, but they are passing.

The problem appears to be with the padding check[1], where if `mli` is a multiple of 8, `b` is 0, making the final check `not bytes_eq(data[-b:], b"\x00" * b)` becomes `not bytes_eq(data, b"")`

[1] https://github.com/pyca/cryptography/blob/master/src/cryptography/hazmat/primitives/keywrap.py#L120-L121

## Results of testing on Amazon Linux 2017.09.1

https://gist.github.com/mattsb42-aws/0f535c5827b96022879bc169897cf3cf

## To duplicate
```
#Amazon Linux does not have 3.6 by default
#sudo yum install python36

virtualenv test_keywrap -p python3.6
source test_keywrap/bin/activate
pip install cryptography==2.2 pytest

echo "
import os

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import keywrap
import pytest

def test_unpadded():
    key = os.urandom(32)
    key_to_wrap = os.urandom(32)

    wrapped_key = keywrap.aes_key_wrap(wrapping_key=key, key_to_wrap=key_to_wrap, backend=default_backend())
    assert keywrap.aes_key_unwrap(wrapping_key=key, wrapped_key=wrapped_key, backend=default_backend()) == key_to_wrap

@pytest.mark.parametrize('key_to_wrap_length', (11, 16, 32, 72, 99))
def test_padded_with_padding(key_to_wrap_length):
    key = os.urandom(32)
    key_to_wrap = os.urandom(key_to_wrap_length)

    wrapped_key_with_padding = keywrap.aes_key_wrap_with_padding(wrapping_key=key, key_to_wrap=key_to_wrap, backend=default_backend())
    print(wrapped_key_with_padding)
    assert keywrap.aes_key_unwrap_with_padding(wrapping_key=key, wrapped_key=wrapped_key_with_padding, backend=default_backend()) == key_to_wrap

" > test_this.py

pytest test_this.py -l -vv

pip freeze

deactivate
```



--- 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/primitives/keywrap.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 struct
8 
9 from cryptography.hazmat.primitives.ciphers import Cipher
10 from cryptography.hazmat.primitives.ciphers.algorithms import AES
11 from cryptography.hazmat.primitives.ciphers.modes import ECB
12 from cryptography.hazmat.primitives.constant_time import bytes_eq
13 
14 
15 def _wrap_core(wrapping_key, a, r, backend):
16     # RFC 3394 Key Wrap - 2.2.1 (index method)
17     encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor()
18     n = len(r)
19     for j in range(6):
20         for i in range(n):
21             # every encryption operation is a discrete 16 byte chunk (because
22             # AES has a 128-bit block size) and since we're using ECB it is
23             # safe to reuse the encryptor for the entire operation
24             b = encryptor.update(a + r[i])
25             # pack/unpack are safe as these are always 64-bit chunks
26             a = struct.pack(
27                 ">Q", struct.unpack(">Q", b[:8])[0] ^ ((n * j) + i + 1)
28             )
29             r[i] = b[-8:]
30 
31     assert encryptor.finalize() == b""
32 
33     return a + b"".join(r)
34 
35 
36 def aes_key_wrap(wrapping_key, key_to_wrap, backend):
37     if len(wrapping_key) not in [16, 24, 32]:
38         raise ValueError("The wrapping key must be a valid AES key length")
39 
40     if len(key_to_wrap) < 16:
41         raise ValueError("The key to wrap must be at least 16 bytes")
42 
43     if len(key_to_wrap) % 8 != 0:
44         raise ValueError("The key to wrap must be a multiple of 8 bytes")
45 
46     a = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6"
47     r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]
48     return _wrap_core(wrapping_key, a, r, backend)
49 
50 
51 def _unwrap_core(wrapping_key, a, r, backend):
52     # Implement RFC 3394 Key Unwrap - 2.2.2 (index method)
53     decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor()
54     n = len(r)
55     for j in reversed(range(6)):
56         for i in reversed(range(n)):
57             # pack/unpack are safe as these are always 64-bit chunks
58             atr = struct.pack(
59                 ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1)
60             ) + r[i]
61             # every decryption operation is a discrete 16 byte chunk so
62             # it is safe to reuse the decryptor for the entire operation
63             b = decryptor.update(atr)
64             a = b[:8]
65             r[i] = b[-8:]
66 
67     assert decryptor.finalize() == b""
68     return a, r
69 
70 
71 def aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend):
72     if len(wrapping_key) not in [16, 24, 32]:
73         raise ValueError("The wrapping key must be a valid AES key length")
74 
75     aiv = b"\xA6\x59\x59\xA6" + struct.pack(">i", len(key_to_wrap))
76     # pad the key to wrap if necessary
77     pad = (8 - (len(key_to_wrap) % 8)) % 8
78     key_to_wrap = key_to_wrap + b"\x00" * pad
79     if len(key_to_wrap) == 8:
80         # RFC 5649 - 4.1 - exactly 8 octets after padding
81         encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor()
82         b = encryptor.update(aiv + key_to_wrap)
83         assert encryptor.finalize() == b""
84         return b
85     else:
86         r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]
87         return _wrap_core(wrapping_key, aiv, r, backend)
88 
89 
90 def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend):
91     if len(wrapped_key) < 16:
92         raise ValueError("Must be at least 16 bytes")
93 
94     if len(wrapping_key) not in [16, 24, 32]:
95         raise ValueError("The wrapping key must be a valid AES key length")
96 
97     if len(wrapped_key) == 16:
98         # RFC 5649 - 4.2 - exactly two 64-bit blocks
99         decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor()
100         b = decryptor.update(wrapped_key)
101         assert decryptor.finalize() == b""
102         a = b[:8]
103         data = b[8:]
104         n = 1
105     else:
106         r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]
107         encrypted_aiv = r.pop(0)
108         n = len(r)
109         a, r = _unwrap_core(wrapping_key, encrypted_aiv, r, backend)
110         data = b"".join(r)
111 
112     # 1) Check that MSB(32,A) = A65959A6.
113     # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n.  If so, let
114     #    MLI = LSB(32,A).
115     # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of
116     #    the output data are zero.
117     (mli,) = struct.unpack(">I", a[4:])
118     b = (8 * n) - mli
119     if (
120         not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") or not
121         8 * (n - 1) < mli <= 8 * n or not bytes_eq(data[-b:], b"\x00" * b)
122     ):
123         raise InvalidUnwrap()
124 
125     return data[:-b]
126 
127 
128 def aes_key_unwrap(wrapping_key, wrapped_key, backend):
129     if len(wrapped_key) < 24:
130         raise ValueError("Must be at least 24 bytes")
131 
132     if len(wrapped_key) % 8 != 0:
133         raise ValueError("The wrapped key must be a multiple of 8 bytes")
134 
135     if len(wrapping_key) not in [16, 24, 32]:
136         raise ValueError("The wrapping key must be a valid AES key length")
137 
138     aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6"
139     r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]
140     a = r.pop(0)
141     a, r = _unwrap_core(wrapping_key, a, r, backend)
142     if not bytes_eq(a, aiv):
143         raise InvalidUnwrap()
144 
145     return b"".join(r)
146 
147 
148 class InvalidUnwrap(Exception):
149     pass
150
```
--- 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/primitives/keywrap.py b/src/cryptography/hazmat/primitives/keywrap.py
--- a/src/cryptography/hazmat/primitives/keywrap.py
+++ b/src/cryptography/hazmat/primitives/keywrap.py
@@ -118,11 +118,16 @@
     b = (8 * n) - mli
     if (
         not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") or not
-        8 * (n - 1) < mli <= 8 * n or not bytes_eq(data[-b:], b"\x00" * b)
+        8 * (n - 1) < mli <= 8 * n or (
+            b != 0 and not bytes_eq(data[-b:], b"\x00" * b)
+        )
     ):
         raise InvalidUnwrap()
 
-    return data[:-b]
+    if b == 0:
+        return data
+    else:
+        return data[:-b]
 
 
 def aes_key_unwrap(wrapping_key, wrapped_key, backend):

{"golden_diff": "diff --git a/src/cryptography/hazmat/primitives/keywrap.py b/src/cryptography/hazmat/primitives/keywrap.py\n--- a/src/cryptography/hazmat/primitives/keywrap.py\n+++ b/src/cryptography/hazmat/primitives/keywrap.py\n@@ -118,11 +118,16 @@\n     b = (8 * n) - mli\n     if (\n         not bytes_eq(a[:4], b\"\\xa6\\x59\\x59\\xa6\") or not\n-        8 * (n - 1) < mli <= 8 * n or not bytes_eq(data[-b:], b\"\\x00\" * b)\n+        8 * (n - 1) < mli <= 8 * n or (\n+            b != 0 and not bytes_eq(data[-b:], b\"\\x00\" * b)\n+        )\n     ):\n         raise InvalidUnwrap()\n \n-    return data[:-b]\n+    if b == 0:\n+        return data\n+    else:\n+        return data[:-b]\n \n \n def aes_key_unwrap(wrapping_key, wrapped_key, backend):\n", "issue": "aes keywrap with padding does properly handle key to wrap length % 8 == 0\n@SalusaSecondus and I found a bug in the new `aes_key_unwrap_with_padding` for wrapped keys where the plaintext is multiples of 8 bytes. Strangely, it looks like the NIST test vectors used do include cases like this, but they are passing.\r\n\r\nThe problem appears to be with the padding check[1], where if `mli` is a multiple of 8, `b` is 0, making the final check `not bytes_eq(data[-b:], b\"\\x00\" * b)` becomes `not bytes_eq(data, b\"\")`\r\n\r\n[1] https://github.com/pyca/cryptography/blob/master/src/cryptography/hazmat/primitives/keywrap.py#L120-L121\r\n\r\n## Results of testing on Amazon Linux 2017.09.1\r\n\r\nhttps://gist.github.com/mattsb42-aws/0f535c5827b96022879bc169897cf3cf\r\n\r\n## To duplicate\r\n```\r\n#Amazon Linux does not have 3.6 by default\r\n#sudo yum install python36\r\n\r\nvirtualenv test_keywrap -p python3.6\r\nsource test_keywrap/bin/activate\r\npip install cryptography==2.2 pytest\r\n\r\necho \"\r\nimport os\r\n\r\nfrom cryptography.hazmat.backends import default_backend\r\nfrom cryptography.hazmat.primitives import keywrap\r\nimport pytest\r\n\r\ndef test_unpadded():\r\n    key = os.urandom(32)\r\n    key_to_wrap = os.urandom(32)\r\n\r\n    wrapped_key = keywrap.aes_key_wrap(wrapping_key=key, key_to_wrap=key_to_wrap, backend=default_backend())\r\n    assert keywrap.aes_key_unwrap(wrapping_key=key, wrapped_key=wrapped_key, backend=default_backend()) == key_to_wrap\r\n\r\n@pytest.mark.parametrize('key_to_wrap_length', (11, 16, 32, 72, 99))\r\ndef test_padded_with_padding(key_to_wrap_length):\r\n    key = os.urandom(32)\r\n    key_to_wrap = os.urandom(key_to_wrap_length)\r\n\r\n    wrapped_key_with_padding = keywrap.aes_key_wrap_with_padding(wrapping_key=key, key_to_wrap=key_to_wrap, backend=default_backend())\r\n    print(wrapped_key_with_padding)\r\n    assert keywrap.aes_key_unwrap_with_padding(wrapping_key=key, wrapped_key=wrapped_key_with_padding, backend=default_backend()) == key_to_wrap\r\n\r\n\" > test_this.py\r\n\r\npytest test_this.py -l -vv\r\n\r\npip freeze\r\n\r\ndeactivate\r\n```\r\n\r\n\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\nimport struct\n\nfrom cryptography.hazmat.primitives.ciphers import Cipher\nfrom cryptography.hazmat.primitives.ciphers.algorithms import AES\nfrom cryptography.hazmat.primitives.ciphers.modes import ECB\nfrom cryptography.hazmat.primitives.constant_time import bytes_eq\n\n\ndef _wrap_core(wrapping_key, a, r, backend):\n    # RFC 3394 Key Wrap - 2.2.1 (index method)\n    encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor()\n    n = len(r)\n    for j in range(6):\n        for i in range(n):\n            # every encryption operation is a discrete 16 byte chunk (because\n            # AES has a 128-bit block size) and since we're using ECB it is\n            # safe to reuse the encryptor for the entire operation\n            b = encryptor.update(a + r[i])\n            # pack/unpack are safe as these are always 64-bit chunks\n            a = struct.pack(\n                \">Q\", struct.unpack(\">Q\", b[:8])[0] ^ ((n * j) + i + 1)\n            )\n            r[i] = b[-8:]\n\n    assert encryptor.finalize() == b\"\"\n\n    return a + b\"\".join(r)\n\n\ndef aes_key_wrap(wrapping_key, key_to_wrap, backend):\n    if len(wrapping_key) not in [16, 24, 32]:\n        raise ValueError(\"The wrapping key must be a valid AES key length\")\n\n    if len(key_to_wrap) < 16:\n        raise ValueError(\"The key to wrap must be at least 16 bytes\")\n\n    if len(key_to_wrap) % 8 != 0:\n        raise ValueError(\"The key to wrap must be a multiple of 8 bytes\")\n\n    a = b\"\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\"\n    r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]\n    return _wrap_core(wrapping_key, a, r, backend)\n\n\ndef _unwrap_core(wrapping_key, a, r, backend):\n    # Implement RFC 3394 Key Unwrap - 2.2.2 (index method)\n    decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor()\n    n = len(r)\n    for j in reversed(range(6)):\n        for i in reversed(range(n)):\n            # pack/unpack are safe as these are always 64-bit chunks\n            atr = struct.pack(\n                \">Q\", struct.unpack(\">Q\", a)[0] ^ ((n * j) + i + 1)\n            ) + r[i]\n            # every decryption operation is a discrete 16 byte chunk so\n            # it is safe to reuse the decryptor for the entire operation\n            b = decryptor.update(atr)\n            a = b[:8]\n            r[i] = b[-8:]\n\n    assert decryptor.finalize() == b\"\"\n    return a, r\n\n\ndef aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend):\n    if len(wrapping_key) not in [16, 24, 32]:\n        raise ValueError(\"The wrapping key must be a valid AES key length\")\n\n    aiv = b\"\\xA6\\x59\\x59\\xA6\" + struct.pack(\">i\", len(key_to_wrap))\n    # pad the key to wrap if necessary\n    pad = (8 - (len(key_to_wrap) % 8)) % 8\n    key_to_wrap = key_to_wrap + b\"\\x00\" * pad\n    if len(key_to_wrap) == 8:\n        # RFC 5649 - 4.1 - exactly 8 octets after padding\n        encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor()\n        b = encryptor.update(aiv + key_to_wrap)\n        assert encryptor.finalize() == b\"\"\n        return b\n    else:\n        r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]\n        return _wrap_core(wrapping_key, aiv, r, backend)\n\n\ndef aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend):\n    if len(wrapped_key) < 16:\n        raise ValueError(\"Must be at least 16 bytes\")\n\n    if len(wrapping_key) not in [16, 24, 32]:\n        raise ValueError(\"The wrapping key must be a valid AES key length\")\n\n    if len(wrapped_key) == 16:\n        # RFC 5649 - 4.2 - exactly two 64-bit blocks\n        decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor()\n        b = decryptor.update(wrapped_key)\n        assert decryptor.finalize() == b\"\"\n        a = b[:8]\n        data = b[8:]\n        n = 1\n    else:\n        r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]\n        encrypted_aiv = r.pop(0)\n        n = len(r)\n        a, r = _unwrap_core(wrapping_key, encrypted_aiv, r, backend)\n        data = b\"\".join(r)\n\n    # 1) Check that MSB(32,A) = A65959A6.\n    # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n.  If so, let\n    #    MLI = LSB(32,A).\n    # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of\n    #    the output data are zero.\n    (mli,) = struct.unpack(\">I\", a[4:])\n    b = (8 * n) - mli\n    if (\n        not bytes_eq(a[:4], b\"\\xa6\\x59\\x59\\xa6\") or not\n        8 * (n - 1) < mli <= 8 * n or not bytes_eq(data[-b:], b\"\\x00\" * b)\n    ):\n        raise InvalidUnwrap()\n\n    return data[:-b]\n\n\ndef aes_key_unwrap(wrapping_key, wrapped_key, backend):\n    if len(wrapped_key) < 24:\n        raise ValueError(\"Must be at least 24 bytes\")\n\n    if len(wrapped_key) % 8 != 0:\n        raise ValueError(\"The wrapped key must be a multiple of 8 bytes\")\n\n    if len(wrapping_key) not in [16, 24, 32]:\n        raise ValueError(\"The wrapping key must be a valid AES key length\")\n\n    aiv = b\"\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\"\n    r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]\n    a = r.pop(0)\n    a, r = _unwrap_core(wrapping_key, a, r, backend)\n    if not bytes_eq(a, aiv):\n        raise InvalidUnwrap()\n\n    return b\"\".join(r)\n\n\nclass InvalidUnwrap(Exception):\n    pass\n", "path": "src/cryptography/hazmat/primitives/keywrap.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\nimport struct\n\nfrom cryptography.hazmat.primitives.ciphers import Cipher\nfrom cryptography.hazmat.primitives.ciphers.algorithms import AES\nfrom cryptography.hazmat.primitives.ciphers.modes import ECB\nfrom cryptography.hazmat.primitives.constant_time import bytes_eq\n\n\ndef _wrap_core(wrapping_key, a, r, backend):\n    # RFC 3394 Key Wrap - 2.2.1 (index method)\n    encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor()\n    n = len(r)\n    for j in range(6):\n        for i in range(n):\n            # every encryption operation is a discrete 16 byte chunk (because\n            # AES has a 128-bit block size) and since we're using ECB it is\n            # safe to reuse the encryptor for the entire operation\n            b = encryptor.update(a + r[i])\n            # pack/unpack are safe as these are always 64-bit chunks\n            a = struct.pack(\n                \">Q\", struct.unpack(\">Q\", b[:8])[0] ^ ((n * j) + i + 1)\n            )\n            r[i] = b[-8:]\n\n    assert encryptor.finalize() == b\"\"\n\n    return a + b\"\".join(r)\n\n\ndef aes_key_wrap(wrapping_key, key_to_wrap, backend):\n    if len(wrapping_key) not in [16, 24, 32]:\n        raise ValueError(\"The wrapping key must be a valid AES key length\")\n\n    if len(key_to_wrap) < 16:\n        raise ValueError(\"The key to wrap must be at least 16 bytes\")\n\n    if len(key_to_wrap) % 8 != 0:\n        raise ValueError(\"The key to wrap must be a multiple of 8 bytes\")\n\n    a = b\"\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\"\n    r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]\n    return _wrap_core(wrapping_key, a, r, backend)\n\n\ndef _unwrap_core(wrapping_key, a, r, backend):\n    # Implement RFC 3394 Key Unwrap - 2.2.2 (index method)\n    decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor()\n    n = len(r)\n    for j in reversed(range(6)):\n        for i in reversed(range(n)):\n            # pack/unpack are safe as these are always 64-bit chunks\n            atr = struct.pack(\n                \">Q\", struct.unpack(\">Q\", a)[0] ^ ((n * j) + i + 1)\n            ) + r[i]\n            # every decryption operation is a discrete 16 byte chunk so\n            # it is safe to reuse the decryptor for the entire operation\n            b = decryptor.update(atr)\n            a = b[:8]\n            r[i] = b[-8:]\n\n    assert decryptor.finalize() == b\"\"\n    return a, r\n\n\ndef aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend):\n    if len(wrapping_key) not in [16, 24, 32]:\n        raise ValueError(\"The wrapping key must be a valid AES key length\")\n\n    aiv = b\"\\xA6\\x59\\x59\\xA6\" + struct.pack(\">i\", len(key_to_wrap))\n    # pad the key to wrap if necessary\n    pad = (8 - (len(key_to_wrap) % 8)) % 8\n    key_to_wrap = key_to_wrap + b\"\\x00\" * pad\n    if len(key_to_wrap) == 8:\n        # RFC 5649 - 4.1 - exactly 8 octets after padding\n        encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor()\n        b = encryptor.update(aiv + key_to_wrap)\n        assert encryptor.finalize() == b\"\"\n        return b\n    else:\n        r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]\n        return _wrap_core(wrapping_key, aiv, r, backend)\n\n\ndef aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend):\n    if len(wrapped_key) < 16:\n        raise ValueError(\"Must be at least 16 bytes\")\n\n    if len(wrapping_key) not in [16, 24, 32]:\n        raise ValueError(\"The wrapping key must be a valid AES key length\")\n\n    if len(wrapped_key) == 16:\n        # RFC 5649 - 4.2 - exactly two 64-bit blocks\n        decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor()\n        b = decryptor.update(wrapped_key)\n        assert decryptor.finalize() == b\"\"\n        a = b[:8]\n        data = b[8:]\n        n = 1\n    else:\n        r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]\n        encrypted_aiv = r.pop(0)\n        n = len(r)\n        a, r = _unwrap_core(wrapping_key, encrypted_aiv, r, backend)\n        data = b\"\".join(r)\n\n    # 1) Check that MSB(32,A) = A65959A6.\n    # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n.  If so, let\n    #    MLI = LSB(32,A).\n    # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of\n    #    the output data are zero.\n    (mli,) = struct.unpack(\">I\", a[4:])\n    b = (8 * n) - mli\n    if (\n        not bytes_eq(a[:4], b\"\\xa6\\x59\\x59\\xa6\") or not\n        8 * (n - 1) < mli <= 8 * n or (\n            b != 0 and not bytes_eq(data[-b:], b\"\\x00\" * b)\n        )\n    ):\n        raise InvalidUnwrap()\n\n    if b == 0:\n        return data\n    else:\n        return data[:-b]\n\n\ndef aes_key_unwrap(wrapping_key, wrapped_key, backend):\n    if len(wrapped_key) < 24:\n        raise ValueError(\"Must be at least 24 bytes\")\n\n    if len(wrapped_key) % 8 != 0:\n        raise ValueError(\"The wrapped key must be a multiple of 8 bytes\")\n\n    if len(wrapping_key) not in [16, 24, 32]:\n        raise ValueError(\"The wrapping key must be a valid AES key length\")\n\n    aiv = b\"\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\\xa6\"\n    r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]\n    a = r.pop(0)\n    a, r = _unwrap_core(wrapping_key, a, r, backend)\n    if not bytes_eq(a, aiv):\n        raise InvalidUnwrap()\n\n    return b\"\".join(r)\n\n\nclass InvalidUnwrap(Exception):\n    pass\n", "path": "src/cryptography/hazmat/primitives/keywrap.py"}]}