Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/cmac.py: 24%
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
13from cryptography.hazmat.primitives.ciphers.modes import CBC
15if typing.TYPE_CHECKING:
16 from cryptography.hazmat.primitives import ciphers
17 from cryptography.hazmat.backends.openssl.backend import Backend
20class _CMACContext:
21 def __init__(
22 self,
23 backend: "Backend",
24 algorithm: "ciphers.BlockCipherAlgorithm",
25 ctx=None,
26 ) -> None:
27 if not backend.cmac_algorithm_supported(algorithm):
28 raise UnsupportedAlgorithm(
29 "This backend does not support CMAC.",
30 _Reasons.UNSUPPORTED_CIPHER,
31 )
33 self._backend = backend
34 self._key = algorithm.key
35 self._algorithm = algorithm
36 self._output_length = algorithm.block_size // 8
38 if ctx is None:
39 registry = self._backend._cipher_registry
40 adapter = registry[type(algorithm), CBC]
42 evp_cipher = adapter(self._backend, algorithm, CBC)
44 ctx = self._backend._lib.CMAC_CTX_new()
46 self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
47 ctx = self._backend._ffi.gc(ctx, self._backend._lib.CMAC_CTX_free)
49 key_ptr = self._backend._ffi.from_buffer(self._key)
50 res = self._backend._lib.CMAC_Init(
51 ctx,
52 key_ptr,
53 len(self._key),
54 evp_cipher,
55 self._backend._ffi.NULL,
56 )
57 self._backend.openssl_assert(res == 1)
59 self._ctx = ctx
61 def update(self, data: bytes) -> None:
62 res = self._backend._lib.CMAC_Update(self._ctx, data, len(data))
63 self._backend.openssl_assert(res == 1)
65 def finalize(self) -> bytes:
66 buf = self._backend._ffi.new("unsigned char[]", self._output_length)
67 length = self._backend._ffi.new("size_t *", self._output_length)
68 res = self._backend._lib.CMAC_Final(self._ctx, buf, length)
69 self._backend.openssl_assert(res == 1)
71 self._ctx = None
73 return self._backend._ffi.buffer(buf)[:]
75 def copy(self) -> "_CMACContext":
76 copied_ctx = self._backend._lib.CMAC_CTX_new()
77 copied_ctx = self._backend._ffi.gc(
78 copied_ctx, self._backend._lib.CMAC_CTX_free
79 )
80 res = self._backend._lib.CMAC_CTX_copy(copied_ctx, self._ctx)
81 self._backend.openssl_assert(res == 1)
82 return _CMACContext(self._backend, self._algorithm, ctx=copied_ctx)
84 def verify(self, signature: bytes) -> None:
85 digest = self.finalize()
86 if not constant_time.bytes_eq(digest, signature):
87 raise InvalidSignature("Signature did not match digest.")