prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Bug in HKDF?
  I think the computation of [`max_length`](https://github.com/pyca/cryptography/blob/66460d8f62b3f27a009bb61be6ce7675c8451b6e/src/cryptography/hazmat/primitives/kdf/hkdf.py#L70) in `src/cryptography/hazmat/primitives/kdf/hkdf.py` is wrong.
  
  [RFC5869](https://tools.ietf.org/html/rfc5869) states on page 3 that the input `L` of the HKDF-Expand function describes the "length of output keying material in octets (<= 255*HashLen)".
  An octet consists of 8 bit. 
  
  Currently, `max_length` is computed as:
  
  ```
  max_length = 255 * (algorithm.digest_size // 8)
  ```
  
  The problem is, that `algorithm.digest_size` returns the size of the digest in bytes. (There are 8 bits per byte). Therefore, the division by 8 is wrong, and thus, `max_length` is unnecessarily small.
  
  (same applies for the computation of `salt` as well ([line 33](https://github.com/pyca/cryptography/blob/66460d8f62b3f27a009bb61be6ce7675c8451b6e/src/cryptography/hazmat/primitives/kdf/hkdf.py#L33)), in the case where `salt is None`)
  
  --- 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/kdf/hkdf.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 six
  8 
  9 from cryptography import utils
  10 from cryptography.exceptions import (
  11     AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
  12 )
  13 from cryptography.hazmat.backends.interfaces import HMACBackend
  14 from cryptography.hazmat.primitives import constant_time, hmac
  15 from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
  16 
  17 
  18 @utils.register_interface(KeyDerivationFunction)
  19 class HKDF(object):
  20     def __init__(self, algorithm, length, salt, info, backend):
  21         if not isinstance(backend, HMACBackend):
  22             raise UnsupportedAlgorithm(
  23                 "Backend object does not implement HMACBackend.",
  24                 _Reasons.BACKEND_MISSING_INTERFACE
  25             )
  26 
  27         self._algorithm = algorithm
  28 
  29         if not (salt is None or isinstance(salt, bytes)):
  30             raise TypeError("salt must be bytes.")
  31 
  32         if salt is None:
  33             salt = b"\x00" * self._algorithm.digest_size
  34 
  35         self._salt = salt
  36 
  37         self._backend = backend
  38 
  39         self._hkdf_expand = HKDFExpand(self._algorithm, length, info, backend)
  40 
  41     def _extract(self, key_material):
  42         h = hmac.HMAC(self._salt, self._algorithm, backend=self._backend)
  43         h.update(key_material)
  44         return h.finalize()
  45 
  46     def derive(self, key_material):
  47         if not isinstance(key_material, bytes):
  48             raise TypeError("key_material must be bytes.")
  49 
  50         return self._hkdf_expand.derive(self._extract(key_material))
  51 
  52     def verify(self, key_material, expected_key):
  53         if not constant_time.bytes_eq(self.derive(key_material), expected_key):
  54             raise InvalidKey
  55 
  56 
  57 @utils.register_interface(KeyDerivationFunction)
  58 class HKDFExpand(object):
  59     def __init__(self, algorithm, length, info, backend):
  60         if not isinstance(backend, HMACBackend):
  61             raise UnsupportedAlgorithm(
  62                 "Backend object does not implement HMACBackend.",
  63                 _Reasons.BACKEND_MISSING_INTERFACE
  64             )
  65 
  66         self._algorithm = algorithm
  67 
  68         self._backend = backend
  69 
  70         max_length = 255 * (algorithm.digest_size // 8)
  71 
  72         if length > max_length:
  73             raise ValueError(
  74                 "Can not derive keys larger than {0} octets.".format(
  75                     max_length
  76                 ))
  77 
  78         self._length = length
  79 
  80         if not (info is None or isinstance(info, bytes)):
  81             raise TypeError("info must be bytes.")
  82 
  83         if info is None:
  84             info = b""
  85 
  86         self._info = info
  87 
  88         self._used = False
  89 
  90     def _expand(self, key_material):
  91         output = [b""]
  92         counter = 1
  93 
  94         while self._algorithm.digest_size * (len(output) - 1) < self._length:
  95             h = hmac.HMAC(key_material, self._algorithm, backend=self._backend)
  96             h.update(output[-1])
  97             h.update(self._info)
  98             h.update(six.int2byte(counter))
  99             output.append(h.finalize())
  100             counter += 1
  101 
  102         return b"".join(output)[:self._length]
  103 
  104     def derive(self, key_material):
  105         if not isinstance(key_material, bytes):
  106             raise TypeError("key_material must be bytes.")
  107 
  108         if self._used:
  109             raise AlreadyFinalized
  110 
  111         self._used = True
  112         return self._expand(key_material)
  113 
  114     def verify(self, key_material, expected_key):
  115         if not constant_time.bytes_eq(self.derive(key_material), expected_key):
  116             raise InvalidKey
  117
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py
  --- a/src/cryptography/hazmat/primitives/kdf/hkdf.py
  +++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py
  @@ -67,7 +67,7 @@
   
           self._backend = backend
   
  -        max_length = 255 * (algorithm.digest_size // 8)
  +        max_length = 255 * algorithm.digest_size
   
           if length > max_length:
               raise ValueError(
  
verification_info: {"golden_diff": "diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py\n--- a/src/cryptography/hazmat/primitives/kdf/hkdf.py\n+++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py\n@@ -67,7 +67,7 @@\n \n         self._backend = backend\n \n-        max_length = 255 * (algorithm.digest_size // 8)\n+        max_length = 255 * algorithm.digest_size\n \n         if length > max_length:\n             raise ValueError(\n", "issue": "Bug in HKDF?\nI think the computation of [`max_length`](https://github.com/pyca/cryptography/blob/66460d8f62b3f27a009bb61be6ce7675c8451b6e/src/cryptography/hazmat/primitives/kdf/hkdf.py#L70) in `src/cryptography/hazmat/primitives/kdf/hkdf.py` is wrong.\r\n\r\n[RFC5869](https://tools.ietf.org/html/rfc5869) states on page 3 that the input `L` of the HKDF-Expand function describes the \"length of output keying material in octets (<= 255*HashLen)\".\r\nAn octet consists of 8 bit. \r\n\r\nCurrently, `max_length` is computed as:\r\n\r\n```\r\nmax_length = 255 * (algorithm.digest_size // 8)\r\n```\r\n\r\nThe problem is, that `algorithm.digest_size` returns the size of the digest in bytes. (There are 8 bits per byte). Therefore, the division by 8 is wrong, and thus, `max_length` is unnecessarily small.\r\n\r\n(same applies for the computation of `salt` as well ([line 33](https://github.com/pyca/cryptography/blob/66460d8f62b3f27a009bb61be6ce7675c8451b6e/src/cryptography/hazmat/primitives/kdf/hkdf.py#L33)), in the case where `salt is None`)\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 six\n\nfrom cryptography import utils\nfrom cryptography.exceptions import (\n    AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons\n)\nfrom cryptography.hazmat.backends.interfaces import HMACBackend\nfrom cryptography.hazmat.primitives import constant_time, hmac\nfrom cryptography.hazmat.primitives.kdf import KeyDerivationFunction\n\n\n@utils.register_interface(KeyDerivationFunction)\nclass HKDF(object):\n    def __init__(self, algorithm, length, salt, info, backend):\n        if not isinstance(backend, HMACBackend):\n            raise UnsupportedAlgorithm(\n                \"Backend object does not implement HMACBackend.\",\n                _Reasons.BACKEND_MISSING_INTERFACE\n            )\n\n        self._algorithm = algorithm\n\n        if not (salt is None or isinstance(salt, bytes)):\n            raise TypeError(\"salt must be bytes.\")\n\n        if salt is None:\n            salt = b\"\\x00\" * self._algorithm.digest_size\n\n        self._salt = salt\n\n        self._backend = backend\n\n        self._hkdf_expand = HKDFExpand(self._algorithm, length, info, backend)\n\n    def _extract(self, key_material):\n        h = hmac.HMAC(self._salt, self._algorithm, backend=self._backend)\n        h.update(key_material)\n        return h.finalize()\n\n    def derive(self, key_material):\n        if not isinstance(key_material, bytes):\n            raise TypeError(\"key_material must be bytes.\")\n\n        return self._hkdf_expand.derive(self._extract(key_material))\n\n    def verify(self, key_material, expected_key):\n        if not constant_time.bytes_eq(self.derive(key_material), expected_key):\n            raise InvalidKey\n\n\n@utils.register_interface(KeyDerivationFunction)\nclass HKDFExpand(object):\n    def __init__(self, algorithm, length, info, backend):\n        if not isinstance(backend, HMACBackend):\n            raise UnsupportedAlgorithm(\n                \"Backend object does not implement HMACBackend.\",\n                _Reasons.BACKEND_MISSING_INTERFACE\n            )\n\n        self._algorithm = algorithm\n\n        self._backend = backend\n\n        max_length = 255 * (algorithm.digest_size // 8)\n\n        if length > max_length:\n            raise ValueError(\n                \"Can not derive keys larger than {0} octets.\".format(\n                    max_length\n                ))\n\n        self._length = length\n\n        if not (info is None or isinstance(info, bytes)):\n            raise TypeError(\"info must be bytes.\")\n\n        if info is None:\n            info = b\"\"\n\n        self._info = info\n\n        self._used = False\n\n    def _expand(self, key_material):\n        output = [b\"\"]\n        counter = 1\n\n        while self._algorithm.digest_size * (len(output) - 1) < self._length:\n            h = hmac.HMAC(key_material, self._algorithm, backend=self._backend)\n            h.update(output[-1])\n            h.update(self._info)\n            h.update(six.int2byte(counter))\n            output.append(h.finalize())\n            counter += 1\n\n        return b\"\".join(output)[:self._length]\n\n    def derive(self, key_material):\n        if not isinstance(key_material, bytes):\n            raise TypeError(\"key_material must be bytes.\")\n\n        if self._used:\n            raise AlreadyFinalized\n\n        self._used = True\n        return self._expand(key_material)\n\n    def verify(self, key_material, expected_key):\n        if not constant_time.bytes_eq(self.derive(key_material), expected_key):\n            raise InvalidKey\n", "path": "src/cryptography/hazmat/primitives/kdf/hkdf.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 six\n\nfrom cryptography import utils\nfrom cryptography.exceptions import (\n    AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons\n)\nfrom cryptography.hazmat.backends.interfaces import HMACBackend\nfrom cryptography.hazmat.primitives import constant_time, hmac\nfrom cryptography.hazmat.primitives.kdf import KeyDerivationFunction\n\n\n@utils.register_interface(KeyDerivationFunction)\nclass HKDF(object):\n    def __init__(self, algorithm, length, salt, info, backend):\n        if not isinstance(backend, HMACBackend):\n            raise UnsupportedAlgorithm(\n                \"Backend object does not implement HMACBackend.\",\n                _Reasons.BACKEND_MISSING_INTERFACE\n            )\n\n        self._algorithm = algorithm\n\n        if not (salt is None or isinstance(salt, bytes)):\n            raise TypeError(\"salt must be bytes.\")\n\n        if salt is None:\n            salt = b\"\\x00\" * self._algorithm.digest_size\n\n        self._salt = salt\n\n        self._backend = backend\n\n        self._hkdf_expand = HKDFExpand(self._algorithm, length, info, backend)\n\n    def _extract(self, key_material):\n        h = hmac.HMAC(self._salt, self._algorithm, backend=self._backend)\n        h.update(key_material)\n        return h.finalize()\n\n    def derive(self, key_material):\n        if not isinstance(key_material, bytes):\n            raise TypeError(\"key_material must be bytes.\")\n\n        return self._hkdf_expand.derive(self._extract(key_material))\n\n    def verify(self, key_material, expected_key):\n        if not constant_time.bytes_eq(self.derive(key_material), expected_key):\n            raise InvalidKey\n\n\n@utils.register_interface(KeyDerivationFunction)\nclass HKDFExpand(object):\n    def __init__(self, algorithm, length, info, backend):\n        if not isinstance(backend, HMACBackend):\n            raise UnsupportedAlgorithm(\n                \"Backend object does not implement HMACBackend.\",\n                _Reasons.BACKEND_MISSING_INTERFACE\n            )\n\n        self._algorithm = algorithm\n\n        self._backend = backend\n\n        max_length = 255 * algorithm.digest_size\n\n        if length > max_length:\n            raise ValueError(\n                \"Can not derive keys larger than {0} octets.\".format(\n                    max_length\n                ))\n\n        self._length = length\n\n        if not (info is None or isinstance(info, bytes)):\n            raise TypeError(\"info must be bytes.\")\n\n        if info is None:\n            info = b\"\"\n\n        self._info = info\n\n        self._used = False\n\n    def _expand(self, key_material):\n        output = [b\"\"]\n        counter = 1\n\n        while self._algorithm.digest_size * (len(output) - 1) < self._length:\n            h = hmac.HMAC(key_material, self._algorithm, backend=self._backend)\n            h.update(output[-1])\n            h.update(self._info)\n            h.update(six.int2byte(counter))\n            output.append(h.finalize())\n            counter += 1\n\n        return b\"\".join(output)[:self._length]\n\n    def derive(self, key_material):\n        if not isinstance(key_material, bytes):\n            raise TypeError(\"key_material must be bytes.\")\n\n        if self._used:\n            raise AlreadyFinalized\n\n        self._used = True\n        return self._expand(key_material)\n\n    def verify(self, key_material, expected_key):\n        if not constant_time.bytes_eq(self.derive(key_material), expected_key):\n            raise InvalidKey\n", "path": "src/cryptography/hazmat/primitives/kdf/hkdf.py"}]}