Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/cmac.py: 26%
47 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:50 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:50 +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.
5from __future__ import annotations
7import typing
9from cryptography.exceptions import (
10 InvalidSignature,
11 UnsupportedAlgorithm,
12 _Reasons,
13)
14from cryptography.hazmat.primitives import constant_time
15from cryptography.hazmat.primitives.ciphers.modes import CBC
17if typing.TYPE_CHECKING:
18 from cryptography.hazmat.backends.openssl.backend import Backend
19 from cryptography.hazmat.primitives import ciphers
22class _CMACContext:
23 def __init__(
24 self,
25 backend: Backend,
26 algorithm: ciphers.BlockCipherAlgorithm,
27 ctx=None,
28 ) -> None:
29 if not backend.cmac_algorithm_supported(algorithm):
30 raise UnsupportedAlgorithm(
31 "This backend does not support CMAC.",
32 _Reasons.UNSUPPORTED_CIPHER,
33 )
35 self._backend = backend
36 self._key = algorithm.key
37 self._algorithm = algorithm
38 self._output_length = algorithm.block_size // 8
40 if ctx is None:
41 registry = self._backend._cipher_registry
42 adapter = registry[type(algorithm), CBC]
44 evp_cipher = adapter(self._backend, algorithm, CBC)
46 ctx = self._backend._lib.CMAC_CTX_new()
48 self._backend.openssl_assert(ctx != self._backend._ffi.NULL)
49 ctx = self._backend._ffi.gc(ctx, self._backend._lib.CMAC_CTX_free)
51 key_ptr = self._backend._ffi.from_buffer(self._key)
52 res = self._backend._lib.CMAC_Init(
53 ctx,
54 key_ptr,
55 len(self._key),
56 evp_cipher,
57 self._backend._ffi.NULL,
58 )
59 self._backend.openssl_assert(res == 1)
61 self._ctx = ctx
63 def update(self, data: bytes) -> None:
64 res = self._backend._lib.CMAC_Update(self._ctx, data, len(data))
65 self._backend.openssl_assert(res == 1)
67 def finalize(self) -> bytes:
68 buf = self._backend._ffi.new("unsigned char[]", self._output_length)
69 length = self._backend._ffi.new("size_t *", self._output_length)
70 res = self._backend._lib.CMAC_Final(self._ctx, buf, length)
71 self._backend.openssl_assert(res == 1)
73 self._ctx = None
75 return self._backend._ffi.buffer(buf)[:]
77 def copy(self) -> _CMACContext:
78 copied_ctx = self._backend._lib.CMAC_CTX_new()
79 copied_ctx = self._backend._ffi.gc(
80 copied_ctx, self._backend._lib.CMAC_CTX_free
81 )
82 res = self._backend._lib.CMAC_CTX_copy(copied_ctx, self._ctx)
83 self._backend.openssl_assert(res == 1)
84 return _CMACContext(self._backend, self._algorithm, ctx=copied_ctx)
86 def verify(self, signature: bytes) -> None:
87 digest = self.finalize()
88 if not constant_time.bytes_eq(digest, signature):
89 raise InvalidSignature("Signature did not match digest.")