1# SPDX-FileCopyrightText: 2014 Legrandin <helderijs@gmail.com>
2# SPDX-License-Identifier: BSD-2-Clause
3
4"""
5Ciphertext Block Chaining (CBC) mode.
6"""
7
8from __future__ import annotations
9
10from typing import Optional, Union, overload
11
12__all__ = ["CbcMode"]
13from Crypto.Cipher._state_machine import Method
14from Crypto.Random import get_random_bytes
15from Crypto.Util._raw_api import (
16 SmartPointer,
17 VoidPointer,
18 c_size_t,
19 c_uint8_ptr_len,
20 c_uint8_ptr_out,
21 create_output_buffer,
22 get_raw_buffer,
23 is_writeable_buffer,
24 load_pycryptodome_raw_lib,
25)
26
27Buffer = Union[bytes, bytearray, memoryview]
28
29raw_cbc_lib = load_pycryptodome_raw_lib(
30 "Crypto.Cipher._raw_cbc",
31 """
32 int CBC_start_operation(void *cipher,
33 const uint8_t iv[],
34 size_t iv_len,
35 void **pResult);
36 int CBC_encrypt(void *cbcState,
37 const uint8_t *in,
38 uint8_t *out,
39 size_t data_len);
40 int CBC_decrypt(void *cbcState,
41 const uint8_t *in,
42 uint8_t *out,
43 size_t data_len);
44 int CBC_stop_operation(void *state);
45 """,
46)
47
48
49class CbcMode:
50 """*Cipher-Block Chaining (CBC)*.
51
52 Each of the ciphertext blocks depends on the current
53 and all previous plaintext blocks.
54
55 An Initialization Vector (*IV*) is required.
56
57 See `NIST SP800-38A`_ , Section 6.2 .
58
59 .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
60
61 :undocumented: __init__
62 """
63
64 def __init__(self, block_cipher: SmartPointer, iv: Buffer) -> None:
65 """Create a new block cipher, configured in CBC mode.
66
67 :Parameters:
68 block_cipher : C pointer
69 A smart pointer to the low-level block cipher instance.
70
71 iv : bytes/bytearray/memoryview
72 The initialization vector to use for encryption or decryption.
73 It is as long as the cipher block.
74
75 **The IV must be unpredictable**. Ideally it is picked randomly.
76
77 Reusing the *IV* for encryptions performed with the same key
78 compromises confidentiality.
79 """
80
81 state = VoidPointer()
82 iv_ptr, iv_len = c_uint8_ptr_len(iv)
83 result = raw_cbc_lib.CBC_start_operation(
84 block_cipher.get(), iv_ptr, c_size_t(iv_len), state.address_of()
85 )
86 if result:
87 raise ValueError("Error %d while instantiating the CBC mode" % result)
88
89 # Ensure that object disposal of this Python object will (eventually)
90 # free the memory allocated by the raw library for the cipher mode
91 self._state = SmartPointer(state.get(), raw_cbc_lib.CBC_stop_operation)
92
93 # Memory allocated for the underlying block cipher is now owed
94 # by the cipher mode
95 block_cipher.release()
96
97 self.block_size = len(iv)
98 """The block size of the underlying cipher, in bytes."""
99
100 self.iv = bytes(iv)
101 """The Initialization Vector originally used to create the object.
102 The value does not change."""
103
104 self.IV = self.iv
105 """Alias for `iv`"""
106
107 self._next = [Method.ENCRYPT, Method.DECRYPT]
108
109 @overload
110 def encrypt(self, plaintext: Buffer) -> bytes: ...
111
112 @overload
113 def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
114
115 def encrypt(
116 self, plaintext: Buffer, output: Optional[Union[bytearray, memoryview]] = None
117 ) -> Optional[bytes]:
118 """Encrypt data with the key and the parameters set at initialization.
119
120 A cipher object is stateful: once you have encrypted a message
121 you cannot encrypt (or decrypt) another message using the same
122 object.
123
124 The data to encrypt can be broken up in two or
125 more pieces and `encrypt` can be called multiple times.
126
127 That is, the statement:
128
129 >>> c.encrypt(a) + c.encrypt(b)
130
131 is equivalent to:
132
133 >>> c.encrypt(a+b)
134
135 That also means that you cannot reuse an object for encrypting
136 or decrypting other data with the same key.
137
138 This function does not add any padding to the plaintext.
139
140 :Parameters:
141 plaintext : bytes/bytearray/memoryview
142 The piece of data to encrypt.
143 Its lenght must be multiple of the cipher block size.
144 :Keywords:
145 output : bytearray/memoryview
146 The location where the ciphertext must be written to.
147 If ``None``, the ciphertext is returned.
148 :Return:
149 If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
150 Otherwise, ``None``.
151 """
152
153 if Method.ENCRYPT not in self._next:
154 raise TypeError("encrypt() cannot be called after decrypt()")
155 self._next = [Method.ENCRYPT]
156
157 if output is None:
158 ciphertext = create_output_buffer(len(plaintext))
159 else:
160 ciphertext = output
161
162 if not is_writeable_buffer(output):
163 raise TypeError("output must be a bytearray or a writeable memoryview")
164
165 if len(plaintext) != len(output):
166 raise ValueError("output must have the same length as the input (%d bytes)" % len(plaintext))
167
168 with c_uint8_ptr_out(ciphertext) as ciphertext_ptr:
169 plaintext_ptr, plaintext_len = c_uint8_ptr_len(plaintext)
170 # Check the lengths of the buffers that C code gets
171 if len(ciphertext_ptr) != plaintext_len:
172 raise ValueError("output must have the same length as the input (%d bytes)" % plaintext_len)
173 result = raw_cbc_lib.CBC_encrypt(
174 self._state.get(), plaintext_ptr, ciphertext_ptr, c_size_t(plaintext_len)
175 )
176 if result:
177 if result == 3:
178 raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
179 raise ValueError("Error %d while encrypting in CBC mode" % result)
180
181 if output is None:
182 return get_raw_buffer(ciphertext)
183 else:
184 return None
185
186 @overload
187 def decrypt(self, ciphertext: Buffer) -> bytes: ...
188
189 @overload
190 def decrypt(self, ciphertext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
191
192 def decrypt(
193 self, ciphertext: Buffer, output: Optional[Union[bytearray, memoryview]] = None
194 ) -> Optional[bytes]:
195 """Decrypt data with the key and the parameters set at initialization.
196
197 A cipher object is stateful: once you have decrypted a message
198 you cannot decrypt (or encrypt) another message with the same
199 object.
200
201 The data to decrypt can be broken up in two or
202 more pieces and `decrypt` can be called multiple times.
203
204 That is, the statement:
205
206 >>> c.decrypt(a) + c.decrypt(b)
207
208 is equivalent to:
209
210 >>> c.decrypt(a+b)
211
212 This function does not remove any padding from the plaintext.
213
214 :Parameters:
215 ciphertext : bytes/bytearray/memoryview
216 The piece of data to decrypt.
217 Its length must be multiple of the cipher block size.
218 :Keywords:
219 output : bytearray/memoryview
220 The location where the plaintext must be written to.
221 If ``None``, the plaintext is returned.
222 :Return:
223 If ``output`` is ``None``, the plaintext is returned as ``bytes``.
224 Otherwise, ``None``.
225 """
226
227 if Method.DECRYPT not in self._next:
228 raise TypeError("decrypt() cannot be called after encrypt()")
229 self._next = [Method.DECRYPT]
230
231 if output is None:
232 plaintext = create_output_buffer(len(ciphertext))
233 else:
234 plaintext = output
235
236 if not is_writeable_buffer(output):
237 raise TypeError("output must be a bytearray or a writeable memoryview")
238
239 if len(ciphertext) != len(output):
240 raise ValueError("output must have the same length as the input (%d bytes)" % len(plaintext))
241
242 with c_uint8_ptr_out(plaintext) as plaintext_ptr:
243 ciphertext_ptr, ciphertext_len = c_uint8_ptr_len(ciphertext)
244 # Check the lengths of the buffers that C code gets
245 if len(plaintext_ptr) != ciphertext_len:
246 raise ValueError("output must have the same length as the input (%d bytes)" % ciphertext_len)
247 result = raw_cbc_lib.CBC_decrypt(
248 self._state.get(), ciphertext_ptr, plaintext_ptr, c_size_t(ciphertext_len)
249 )
250 if result:
251 if result == 3:
252 raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
253 raise ValueError("Error %d while decrypting in CBC mode" % result)
254
255 if output is None:
256 return get_raw_buffer(plaintext)
257 else:
258 return None
259
260
261def _create_cbc_cipher(factory, **kwargs):
262 """Instantiate a cipher object that performs CBC encryption/decryption.
263
264 :Parameters:
265 factory : module
266 The underlying block cipher, a module from ``Crypto.Cipher``.
267
268 :Keywords:
269 iv : bytes/bytearray/memoryview
270 The IV to use for CBC.
271
272 IV : bytes/bytearray/memoryview
273 Alias for ``iv``.
274
275 Any other keyword will be passed to the underlying block cipher.
276 See the relevant documentation for details (at least ``key`` will need
277 to be present).
278 """
279
280 cipher_state = factory._create_base_cipher(kwargs)
281 iv = kwargs.pop("IV", None)
282 IV = kwargs.pop("iv", None)
283
284 if (iv, IV) == (None, None):
285 iv = get_random_bytes(factory.block_size)
286 if iv is not None:
287 if IV is not None:
288 raise TypeError("You must either use 'iv' or 'IV', not both")
289 else:
290 iv = IV
291
292 if len(iv) != factory.block_size:
293 raise ValueError("Incorrect IV length (it must be %d bytes long)" % factory.block_size)
294
295 if kwargs:
296 raise TypeError("Unknown parameters for CBC: %s" % str(kwargs))
297
298 return CbcMode(cipher_state, iv)