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