base.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. from __future__ import annotations
  5. import abc
  6. import typing
  7. from cryptography.hazmat.bindings._rust import openssl as rust_openssl
  8. from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm
  9. from cryptography.hazmat.primitives.ciphers import modes
  10. from cryptography.utils import Buffer
  11. class CipherContext(metaclass=abc.ABCMeta):
  12. @abc.abstractmethod
  13. def update(self, data: Buffer) -> bytes:
  14. """
  15. Processes the provided bytes through the cipher and returns the results
  16. as bytes.
  17. """
  18. @abc.abstractmethod
  19. def update_into(self, data: Buffer, buf: Buffer) -> int:
  20. """
  21. Processes the provided bytes and writes the resulting data into the
  22. provided buffer. Returns the number of bytes written.
  23. """
  24. @abc.abstractmethod
  25. def finalize(self) -> bytes:
  26. """
  27. Returns the results of processing the final block as bytes.
  28. """
  29. @abc.abstractmethod
  30. def reset_nonce(self, nonce: bytes) -> None:
  31. """
  32. Resets the nonce for the cipher context to the provided value.
  33. Raises an exception if it does not support reset or if the
  34. provided nonce does not have a valid length.
  35. """
  36. class AEADCipherContext(CipherContext, metaclass=abc.ABCMeta):
  37. @abc.abstractmethod
  38. def authenticate_additional_data(self, data: Buffer) -> None:
  39. """
  40. Authenticates the provided bytes.
  41. """
  42. class AEADDecryptionContext(AEADCipherContext, metaclass=abc.ABCMeta):
  43. @abc.abstractmethod
  44. def finalize_with_tag(self, tag: bytes) -> bytes:
  45. """
  46. Returns the results of processing the final block as bytes and allows
  47. delayed passing of the authentication tag.
  48. """
  49. class AEADEncryptionContext(AEADCipherContext, metaclass=abc.ABCMeta):
  50. @property
  51. @abc.abstractmethod
  52. def tag(self) -> bytes:
  53. """
  54. Returns tag bytes. This is only available after encryption is
  55. finalized.
  56. """
  57. Mode = typing.TypeVar(
  58. "Mode", bound=typing.Optional[modes.Mode], covariant=True
  59. )
  60. class Cipher(typing.Generic[Mode]):
  61. def __init__(
  62. self,
  63. algorithm: CipherAlgorithm,
  64. mode: Mode,
  65. backend: typing.Any = None,
  66. ) -> None:
  67. if not isinstance(algorithm, CipherAlgorithm):
  68. raise TypeError("Expected interface of CipherAlgorithm.")
  69. if mode is not None:
  70. # mypy needs this assert to narrow the type from our generic
  71. # type. Maybe it won't some time in the future.
  72. assert isinstance(mode, modes.Mode)
  73. mode.validate_for_algorithm(algorithm)
  74. self.algorithm = algorithm
  75. self.mode = mode
  76. @typing.overload
  77. def encryptor(
  78. self: Cipher[modes.ModeWithAuthenticationTag],
  79. ) -> AEADEncryptionContext: ...
  80. @typing.overload
  81. def encryptor(
  82. self: _CIPHER_TYPE,
  83. ) -> CipherContext: ...
  84. def encryptor(self):
  85. if isinstance(self.mode, modes.ModeWithAuthenticationTag):
  86. if self.mode.tag is not None:
  87. raise ValueError(
  88. "Authentication tag must be None when encrypting."
  89. )
  90. return rust_openssl.ciphers.create_encryption_ctx(
  91. self.algorithm, self.mode
  92. )
  93. @typing.overload
  94. def decryptor(
  95. self: Cipher[modes.ModeWithAuthenticationTag],
  96. ) -> AEADDecryptionContext: ...
  97. @typing.overload
  98. def decryptor(
  99. self: _CIPHER_TYPE,
  100. ) -> CipherContext: ...
  101. def decryptor(self):
  102. return rust_openssl.ciphers.create_decryption_ctx(
  103. self.algorithm, self.mode
  104. )
  105. _CIPHER_TYPE = Cipher[
  106. typing.Union[
  107. modes.ModeWithNonce,
  108. modes.ModeWithTweak,
  109. modes.ECB,
  110. modes.ModeWithInitializationVector,
  111. None,
  112. ]
  113. ]
  114. CipherContext.register(rust_openssl.ciphers.CipherContext)
  115. AEADEncryptionContext.register(rust_openssl.ciphers.AEADEncryptionContext)
  116. AEADDecryptionContext.register(rust_openssl.ciphers.AEADDecryptionContext)