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