_mode_ofb.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. # -*- coding: utf-8 -*-
  2. #
  3. # Cipher/mode_ofb.py : OFB mode
  4. #
  5. # ===================================================================
  6. # The contents of this file are dedicated to the public domain. To
  7. # the extent that dedication to the public domain is not available,
  8. # everyone is granted a worldwide, perpetual, royalty-free,
  9. # non-exclusive license to exercise all rights associated with the
  10. # contents of this file for any purpose whatsoever.
  11. # No rights are reserved.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  17. # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  18. # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. # SOFTWARE.
  21. # ===================================================================
  22. """
  23. Output Feedback (CFB) mode.
  24. """
  25. __all__ = ['OfbMode']
  26. from tls.Crypto.Util.py3compat import _copy_bytes
  27. from tls.Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
  28. create_string_buffer, get_raw_buffer,
  29. SmartPointer, c_size_t, c_uint8_ptr,
  30. is_writeable_buffer)
  31. from tls.Crypto.Random import get_random_bytes
  32. raw_ofb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ofb", """
  33. int OFB_start_operation(void *cipher,
  34. const uint8_t iv[],
  35. size_t iv_len,
  36. void **pResult);
  37. int OFB_encrypt(void *ofbState,
  38. const uint8_t *in,
  39. uint8_t *out,
  40. size_t data_len);
  41. int OFB_decrypt(void *ofbState,
  42. const uint8_t *in,
  43. uint8_t *out,
  44. size_t data_len);
  45. int OFB_stop_operation(void *state);
  46. """
  47. )
  48. class OfbMode(object):
  49. """*Output FeedBack (OFB)*.
  50. This mode is very similar to CBC, but it
  51. transforms the underlying block cipher into a stream cipher.
  52. The keystream is the iterated block encryption of the
  53. previous ciphertext block.
  54. An Initialization Vector (*IV*) is required.
  55. See `NIST SP800-38A`_ , Section 6.4.
  56. .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
  57. :undocumented: __init__
  58. """
  59. def __init__(self, block_cipher, iv):
  60. """Create a new block cipher, configured in OFB mode.
  61. :Parameters:
  62. block_cipher : C pointer
  63. A smart pointer to the low-level block cipher instance.
  64. iv : bytes/bytearray/memoryview
  65. The initialization vector to use for encryption or decryption.
  66. It is as long as the cipher block.
  67. **The IV must be a nonce, to to be reused for any other
  68. message**. It shall be a nonce or a random value.
  69. Reusing the *IV* for encryptions performed with the same key
  70. compromises confidentiality.
  71. """
  72. self._state = VoidPointer()
  73. result = raw_ofb_lib.OFB_start_operation(block_cipher.get(),
  74. c_uint8_ptr(iv),
  75. c_size_t(len(iv)),
  76. self._state.address_of())
  77. if result:
  78. raise ValueError("Error %d while instantiating the OFB mode"
  79. % result)
  80. # Ensure that object disposal of this Python object will (eventually)
  81. # free the memory allocated by the raw library for the cipher mode
  82. self._state = SmartPointer(self._state.get(),
  83. raw_ofb_lib.OFB_stop_operation)
  84. # Memory allocated for the underlying block cipher is now owed
  85. # by the cipher mode
  86. block_cipher.release()
  87. self.block_size = len(iv)
  88. """The block size of the underlying cipher, in bytes."""
  89. self.iv = _copy_bytes(None, None, iv)
  90. """The Initialization Vector originally used to create the object.
  91. The value does not change."""
  92. self.IV = self.iv
  93. """Alias for `iv`"""
  94. self._next = [ self.encrypt, self.decrypt ]
  95. def encrypt(self, plaintext, output=None):
  96. """Encrypt data with the key and the parameters set at initialization.
  97. A cipher object is stateful: once you have encrypted a message
  98. you cannot encrypt (or decrypt) another message using the same
  99. object.
  100. The data to encrypt can be broken up in two or
  101. more pieces and `encrypt` can be called multiple times.
  102. That is, the statement:
  103. >>> c.encrypt(a) + c.encrypt(b)
  104. is equivalent to:
  105. >>> c.encrypt(a+b)
  106. This function does not add any padding to the plaintext.
  107. :Parameters:
  108. plaintext : bytes/bytearray/memoryview
  109. The piece of data to encrypt.
  110. It can be of any length.
  111. :Keywords:
  112. output : bytearray/memoryview
  113. The location where the ciphertext must be written to.
  114. If ``None``, the ciphertext is returned.
  115. :Return:
  116. If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
  117. Otherwise, ``None``.
  118. """
  119. if self.encrypt not in self._next:
  120. raise TypeError("encrypt() cannot be called after decrypt()")
  121. self._next = [ self.encrypt ]
  122. if output is None:
  123. ciphertext = create_string_buffer(len(plaintext))
  124. else:
  125. ciphertext = output
  126. if not is_writeable_buffer(output):
  127. raise TypeError("output must be a bytearray or a writeable memoryview")
  128. if len(plaintext) != len(output):
  129. raise ValueError("output must have the same length as the input"
  130. " (%d bytes)" % len(plaintext))
  131. result = raw_ofb_lib.OFB_encrypt(self._state.get(),
  132. c_uint8_ptr(plaintext),
  133. c_uint8_ptr(ciphertext),
  134. c_size_t(len(plaintext)))
  135. if result:
  136. raise ValueError("Error %d while encrypting in OFB mode" % result)
  137. if output is None:
  138. return get_raw_buffer(ciphertext)
  139. else:
  140. return None
  141. def decrypt(self, ciphertext, output=None):
  142. """Decrypt data with the key and the parameters set at initialization.
  143. A cipher object is stateful: once you have decrypted a message
  144. you cannot decrypt (or encrypt) another message with the same
  145. object.
  146. The data to decrypt can be broken up in two or
  147. more pieces and `decrypt` can be called multiple times.
  148. That is, the statement:
  149. >>> c.decrypt(a) + c.decrypt(b)
  150. is equivalent to:
  151. >>> c.decrypt(a+b)
  152. This function does not remove any padding from the plaintext.
  153. :Parameters:
  154. ciphertext : bytes/bytearray/memoryview
  155. The piece of data to decrypt.
  156. It can be of any length.
  157. :Keywords:
  158. output : bytearray/memoryview
  159. The location where the plaintext is written to.
  160. If ``None``, the plaintext is returned.
  161. :Return:
  162. If ``output`` is ``None``, the plaintext is returned as ``bytes``.
  163. Otherwise, ``None``.
  164. """
  165. if self.decrypt not in self._next:
  166. raise TypeError("decrypt() cannot be called after encrypt()")
  167. self._next = [ self.decrypt ]
  168. if output is None:
  169. plaintext = create_string_buffer(len(ciphertext))
  170. else:
  171. plaintext = output
  172. if not is_writeable_buffer(output):
  173. raise TypeError("output must be a bytearray or a writeable memoryview")
  174. if len(ciphertext) != len(output):
  175. raise ValueError("output must have the same length as the input"
  176. " (%d bytes)" % len(plaintext))
  177. result = raw_ofb_lib.OFB_decrypt(self._state.get(),
  178. c_uint8_ptr(ciphertext),
  179. c_uint8_ptr(plaintext),
  180. c_size_t(len(ciphertext)))
  181. if result:
  182. raise ValueError("Error %d while decrypting in OFB mode" % result)
  183. if output is None:
  184. return get_raw_buffer(plaintext)
  185. else:
  186. return None
  187. def _create_ofb_cipher(factory, **kwargs):
  188. """Instantiate a cipher object that performs OFB encryption/decryption.
  189. :Parameters:
  190. factory : module
  191. The underlying block cipher, a module from ``Crypto.Cipher``.
  192. :Keywords:
  193. iv : bytes/bytearray/memoryview
  194. The IV to use for OFB.
  195. IV : bytes/bytearray/memoryview
  196. Alias for ``iv``.
  197. Any other keyword will be passed to the underlying block cipher.
  198. See the relevant documentation for details (at least ``key`` will need
  199. to be present).
  200. """
  201. cipher_state = factory._create_base_cipher(kwargs)
  202. iv = kwargs.pop("IV", None)
  203. IV = kwargs.pop("iv", None)
  204. if (None, None) == (iv, IV):
  205. iv = get_random_bytes(factory.block_size)
  206. if iv is not None:
  207. if IV is not None:
  208. raise TypeError("You must either use 'iv' or 'IV', not both")
  209. else:
  210. iv = IV
  211. if len(iv) != factory.block_size:
  212. raise ValueError("Incorrect IV length (it must be %d bytes long)" %
  213. factory.block_size)
  214. if kwargs:
  215. raise TypeError("Unknown parameters for OFB: %s" % str(kwargs))
  216. return OfbMode(cipher_state, iv)