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

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. 

4 

5from __future__ import annotations 

6 

7import typing 

8 

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 

16 

17if typing.TYPE_CHECKING: 

18 from cryptography.hazmat.backends.openssl.backend import Backend 

19 from cryptography.hazmat.primitives import ciphers 

20 

21 

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 ) 

34 

35 self._backend = backend 

36 self._key = algorithm.key 

37 self._algorithm = algorithm 

38 self._output_length = algorithm.block_size // 8 

39 

40 if ctx is None: 

41 registry = self._backend._cipher_registry 

42 adapter = registry[type(algorithm), CBC] 

43 

44 evp_cipher = adapter(self._backend, algorithm, CBC) 

45 

46 ctx = self._backend._lib.CMAC_CTX_new() 

47 

48 self._backend.openssl_assert(ctx != self._backend._ffi.NULL) 

49 ctx = self._backend._ffi.gc(ctx, self._backend._lib.CMAC_CTX_free) 

50 

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) 

60 

61 self._ctx = ctx 

62 

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) 

66 

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) 

72 

73 self._ctx = None 

74 

75 return self._backend._ffi.buffer(buf)[:] 

76 

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) 

85 

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.")