Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/hmac.py: 50%
46 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:36 +0000
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:36 +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 (
8 InvalidSignature,
9 UnsupportedAlgorithm,
10 _Reasons,
11)
12from cryptography.hazmat.primitives import constant_time, hashes
14if typing.TYPE_CHECKING:
15 from cryptography.hazmat.backends.openssl.backend import Backend
18class _HMACContext(hashes.HashContext):
19 def __init__(
20 self,
21 backend: "Backend",
22 key: bytes,
23 algorithm: hashes.HashAlgorithm,
24 ctx=None,
25 ):
26 self._algorithm = algorithm
27 self._backend = backend
29 if ctx is None:
30 ctx = self._backend._lib.HMAC_CTX_new()
31 self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
32 ctx = self._backend._ffi.gc(ctx, self._backend._lib.HMAC_CTX_free)
33 evp_md = self._backend._evp_md_from_algorithm(algorithm)
34 if evp_md == self._backend._ffi.NULL:
35 raise UnsupportedAlgorithm(
36 "{} is not a supported hash on this backend".format(
37 algorithm.name
38 ),
39 _Reasons.UNSUPPORTED_HASH,
40 )
41 key_ptr = self._backend._ffi.from_buffer(key)
42 res = self._backend._lib.HMAC_Init_ex(
43 ctx, key_ptr, len(key), evp_md, self._backend._ffi.NULL
44 )
45 self._backend.openssl_assert(res != 0)
47 self._ctx = ctx
48 self._key = key
50 @property
51 def algorithm(self) -> hashes.HashAlgorithm:
52 return self._algorithm
54 def copy(self) -> "_HMACContext":
55 copied_ctx = self._backend._lib.HMAC_CTX_new()
56 self._backend.openssl_assert(copied_ctx != self._backend._ffi.NULL)
57 copied_ctx = self._backend._ffi.gc(
58 copied_ctx, self._backend._lib.HMAC_CTX_free
59 )
60 res = self._backend._lib.HMAC_CTX_copy(copied_ctx, self._ctx)
61 self._backend.openssl_assert(res != 0)
62 return _HMACContext(
63 self._backend, self._key, self.algorithm, ctx=copied_ctx
64 )
66 def update(self, data: bytes) -> None:
67 data_ptr = self._backend._ffi.from_buffer(data)
68 res = self._backend._lib.HMAC_Update(self._ctx, data_ptr, len(data))
69 self._backend.openssl_assert(res != 0)
71 def finalize(self) -> bytes:
72 buf = self._backend._ffi.new(
73 "unsigned char[]", self._backend._lib.EVP_MAX_MD_SIZE
74 )
75 outlen = self._backend._ffi.new("unsigned int *")
76 res = self._backend._lib.HMAC_Final(self._ctx, buf, outlen)
77 self._backend.openssl_assert(res != 0)
78 self._backend.openssl_assert(outlen[0] == self.algorithm.digest_size)
79 return self._backend._ffi.buffer(buf)[: outlen[0]]
81 def verify(self, signature: bytes) -> None:
82 digest = self.finalize()
83 if not constant_time.bytes_eq(digest, signature):
84 raise InvalidSignature("Signature did not match digest.")