Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/hashes.py: 27%
45 statements
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
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.
5import typing
7from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
8from cryptography.hazmat.primitives import hashes
11if typing.TYPE_CHECKING:
12 from cryptography.hazmat.backends.openssl.backend import Backend
15class _HashContext(hashes.HashContext):
16 def __init__(
17 self, backend: "Backend", algorithm: hashes.HashAlgorithm, ctx=None
18 ) -> None:
19 self._algorithm = algorithm
21 self._backend = backend
23 if ctx is None:
24 ctx = self._backend._lib.EVP_MD_CTX_new()
25 ctx = self._backend._ffi.gc(
26 ctx, self._backend._lib.EVP_MD_CTX_free
27 )
28 evp_md = self._backend._evp_md_from_algorithm(algorithm)
29 if evp_md == self._backend._ffi.NULL:
30 raise UnsupportedAlgorithm(
31 "{} is not a supported hash on this backend.".format(
32 algorithm.name
33 ),
34 _Reasons.UNSUPPORTED_HASH,
35 )
36 res = self._backend._lib.EVP_DigestInit_ex(
37 ctx, evp_md, self._backend._ffi.NULL
38 )
39 self._backend.openssl_assert(res != 0)
41 self._ctx = ctx
43 @property
44 def algorithm(self) -> hashes.HashAlgorithm:
45 return self._algorithm
47 def copy(self) -> "_HashContext":
48 copied_ctx = self._backend._lib.EVP_MD_CTX_new()
49 copied_ctx = self._backend._ffi.gc(
50 copied_ctx, self._backend._lib.EVP_MD_CTX_free
51 )
52 res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx)
53 self._backend.openssl_assert(res != 0)
54 return _HashContext(self._backend, self.algorithm, ctx=copied_ctx)
56 def update(self, data: bytes) -> None:
57 data_ptr = self._backend._ffi.from_buffer(data)
58 res = self._backend._lib.EVP_DigestUpdate(
59 self._ctx, data_ptr, len(data)
60 )
61 self._backend.openssl_assert(res != 0)
63 def finalize(self) -> bytes:
64 if isinstance(self.algorithm, hashes.ExtendableOutputFunction):
65 # extendable output functions use a different finalize
66 return self._finalize_xof()
67 else:
68 buf = self._backend._ffi.new(
69 "unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE
70 )
71 outlen = self._backend._ffi.new("unsigned int *")
72 res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf, outlen)
73 self._backend.openssl_assert(res != 0)
74 self._backend.openssl_assert(
75 outlen[0] == self.algorithm.digest_size
76 )
77 return self._backend._ffi.buffer(buf)[: outlen[0]]
79 def _finalize_xof(self) -> bytes:
80 buf = self._backend._ffi.new(
81 "unsigned char[]", self.algorithm.digest_size
82 )
83 res = self._backend._lib.EVP_DigestFinalXOF(
84 self._ctx, buf, self.algorithm.digest_size
85 )
86 self._backend.openssl_assert(res != 0)
87 return self._backend._ffi.buffer(buf)[: self.algorithm.digest_size]