support byteslike in ConcatKDF{HMAC,Hash}, Scrypt, and X963KDF (#4709)

* byteslike concatkdf

* byteslike scrypt

* byteslike x963kdf
diff --git a/docs/hazmat/primitives/key-derivation-functions.rst b/docs/hazmat/primitives/key-derivation-functions.rst
index 373fdbf..64a22c0 100644
--- a/docs/hazmat/primitives/key-derivation-functions.rst
+++ b/docs/hazmat/primitives/key-derivation-functions.rst
@@ -377,7 +377,8 @@
 
     .. method:: derive(key_material)
 
-        :param bytes key_material: The input key material.
+        :param key_material: The input key material.
+        :type key_material: :term:`bytes-like`
         :return bytes: The derived key.
         :raises TypeError: This exception is raised if ``key_material`` is
                             not ``bytes``.
@@ -562,7 +563,8 @@
 
     .. method:: derive(key_material)
 
-        :param bytes key_material: The input key material.
+        :param key_material: The input key material.
+        :type key_material: :term:`bytes-like`
         :return bytes: The derived key.
         :raises TypeError: This exception is raised if ``key_material`` is
                             not ``bytes``.
@@ -813,7 +815,8 @@
 
     .. method:: derive(key_material)
 
-        :param bytes key_material: The input key material.
+        :param key_material: The input key material.
+        :type key_material: :term:`bytes-like`
         :return bytes: the derived key.
         :raises TypeError: This exception is raised if ``key_material`` is not
                            ``bytes``.
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index f74c955..ab0daa2 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -2181,8 +2181,9 @@
 
     def derive_scrypt(self, key_material, salt, length, n, r, p):
         buf = self._ffi.new("unsigned char[]", length)
+        key_material_ptr = self._ffi.from_buffer(key_material)
         res = self._lib.EVP_PBE_scrypt(
-            key_material, len(key_material), salt, len(salt), n, r, p,
+            key_material_ptr, len(key_material), salt, len(salt), n, r, p,
             scrypt._MEM_LIMIT, buf, length
         )
         if res != 1:
diff --git a/src/cryptography/hazmat/primitives/kdf/concatkdf.py b/src/cryptography/hazmat/primitives/kdf/concatkdf.py
index 89c3b28..65b25cd 100644
--- a/src/cryptography/hazmat/primitives/kdf/concatkdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/concatkdf.py
@@ -32,7 +32,7 @@
 
 
 def _concatkdf_derive(key_material, length, auxfn, otherinfo):
-    utils._check_bytes("key_material", key_material)
+    utils._check_byteslike("key_material", key_material)
     output = [b""]
     outlen = 0
     counter = 1
diff --git a/src/cryptography/hazmat/primitives/kdf/scrypt.py b/src/cryptography/hazmat/primitives/kdf/scrypt.py
index 44e369f..df9745e 100644
--- a/src/cryptography/hazmat/primitives/kdf/scrypt.py
+++ b/src/cryptography/hazmat/primitives/kdf/scrypt.py
@@ -52,7 +52,7 @@
             raise AlreadyFinalized("Scrypt instances can only be used once.")
         self._used = True
 
-        utils._check_bytes("key_material", key_material)
+        utils._check_byteslike("key_material", key_material)
         return self._backend.derive_scrypt(
             key_material, self._salt, self._length, self._n, self._r, self._p
         )
diff --git a/src/cryptography/hazmat/primitives/kdf/x963kdf.py b/src/cryptography/hazmat/primitives/kdf/x963kdf.py
index a8c0775..fd9d125 100644
--- a/src/cryptography/hazmat/primitives/kdf/x963kdf.py
+++ b/src/cryptography/hazmat/primitives/kdf/x963kdf.py
@@ -46,7 +46,7 @@
         if self._used:
             raise AlreadyFinalized
         self._used = True
-        utils._check_bytes("key_material", key_material)
+        utils._check_byteslike("key_material", key_material)
         output = [b""]
         outlen = 0
         counter = 1
diff --git a/tests/hazmat/primitives/test_concatkdf.py b/tests/hazmat/primitives/test_concatkdf.py
index aa568c1..6731509 100644
--- a/tests/hazmat/primitives/test_concatkdf.py
+++ b/tests/hazmat/primitives/test_concatkdf.py
@@ -52,6 +52,22 @@
 
         assert ckdf.derive(prk) == okm
 
+    def test_buffer_protocol(self, backend):
+        prk = binascii.unhexlify(
+            b"52169af5c485dcc2321eb8d26d5efa21fb9b93c98e38412ee2484cf14f0d0d23"
+        )
+
+        okm = binascii.unhexlify(b"1c3bc9e7c4547c5191c0d478cccaed55")
+
+        oinfo = binascii.unhexlify(
+            b"a1b2c3d4e53728157e634612c12d6d5223e204aeea4341565369647bd184bcd2"
+            b"46f72971f292badaa2fe4124612cba"
+        )
+
+        ckdf = ConcatKDFHash(hashes.SHA256(), 16, oinfo, backend)
+
+        assert ckdf.derive(bytearray(prk)) == okm
+
     def test_verify(self, backend):
         prk = binascii.unhexlify(
             b"52169af5c485dcc2321eb8d26d5efa21fb9b93c98e38412ee2484cf14f0d0d23"
@@ -158,6 +174,25 @@
 
         assert ckdf.derive(prk) == okm
 
+    def test_buffer_protocol(self, backend):
+        prk = binascii.unhexlify(
+            b"013951627c1dea63ea2d7702dd24e963eef5faac6b4af7e4"
+            b"b831cde499dff1ce45f6179f741c728aa733583b02409208"
+            b"8f0af7fce1d045edbc5790931e8d5ca79c73"
+        )
+
+        okm = binascii.unhexlify(b"64ce901db10d558661f10b6836a122a7"
+                                 b"605323ce2f39bf27eaaac8b34cf89f2f")
+
+        oinfo = binascii.unhexlify(
+            b"a1b2c3d4e55e600be5f367e0e8a465f4bf2704db00c9325c"
+            b"9fbd216d12b49160b2ae5157650f43415653696421e68e"
+        )
+
+        ckdf = ConcatKDFHMAC(hashes.SHA512(), 32, None, oinfo, backend)
+
+        assert ckdf.derive(bytearray(prk)) == okm
+
     def test_derive_explicit_salt(self, backend):
         prk = binascii.unhexlify(
             b"013951627c1dea63ea2d7702dd24e963eef5faac6b4af7e4"
diff --git a/tests/hazmat/primitives/test_scrypt.py b/tests/hazmat/primitives/test_scrypt.py
index 25d2c61..8f3a14e 100644
--- a/tests/hazmat/primitives/test_scrypt.py
+++ b/tests/hazmat/primitives/test_scrypt.py
@@ -108,6 +108,19 @@
         with pytest.raises(TypeError):
             scrypt.derive(password)
 
+    def test_buffer_protocol(self, backend):
+        password = bytearray(b"password")
+        work_factor = 256
+        block_size = 8
+        parallelization_factor = 16
+        length = 10
+        salt = b"NaCl"
+
+        scrypt = Scrypt(salt, length, work_factor, block_size,
+                        parallelization_factor, backend)
+
+        assert scrypt.derive(password) == b'\xf4\x92\x86\xb2\x06\x0c\x848W\x87'
+
     @pytest.mark.parametrize("params", vectors)
     def test_verify(self, backend, params):
         _skip_if_memory_limited(_MEM_LIMIT, params)
diff --git a/tests/hazmat/primitives/test_x963kdf.py b/tests/hazmat/primitives/test_x963kdf.py
index d87a46b..c4dd892 100644
--- a/tests/hazmat/primitives/test_x963kdf.py
+++ b/tests/hazmat/primitives/test_x963kdf.py
@@ -45,6 +45,17 @@
 
         assert xkdf.derive(key) == derivedkey
 
+    def test_buffer_protocol(self, backend):
+        key = bytearray(binascii.unhexlify(
+            b"96c05619d56c328ab95fe84b18264b08725b85e33fd34f08"
+        ))
+
+        derivedkey = binascii.unhexlify(b"443024c3dae66b95e6f5670601558f71")
+
+        xkdf = X963KDF(hashes.SHA256(), 16, None, backend)
+
+        assert xkdf.derive(key) == derivedkey
+
     def test_verify(self, backend):
         key = binascii.unhexlify(
             b"22518b10e70f2a3f243810ae3254139efbee04aa57c7af7d"