| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  | # -*- coding: utf-8 -*- | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  Cipher/mode_ctr.py : CTR mode | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # =================================================================== | 
					
						
							|  |  |  | # The contents of this file are dedicated to the public domain.  To | 
					
						
							|  |  |  | # the extent that dedication to the public domain is not available, | 
					
						
							|  |  |  | # everyone is granted a worldwide, perpetual, royalty-free, | 
					
						
							|  |  |  | # non-exclusive license to exercise all rights associated with the | 
					
						
							|  |  |  | # contents of this file for any purpose whatsoever. | 
					
						
							|  |  |  | # No rights are reserved. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
					
						
							|  |  |  | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
					
						
							|  |  |  | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
					
						
							|  |  |  | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | 
					
						
							|  |  |  | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | 
					
						
							|  |  |  | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 
					
						
							|  |  |  | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
					
						
							|  |  |  | # SOFTWARE. | 
					
						
							|  |  |  | # =================================================================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | Counter (CTR) mode. | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-09 21:43:24 +01:00
										 |  |  | __all__ = ['CtrMode'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  | from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, | 
					
						
							|  |  |  |                                   create_string_buffer, get_raw_buffer, | 
					
						
							| 
									
										
										
										
											2015-02-10 22:29:40 +01:00
										 |  |  |                                   SmartPointer, c_size_t, expect_byte_string) | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  | from Crypto.Util.py3compat import * | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  | raw_ctr_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ctr", """
 | 
					
						
							|  |  |  |                     int CTR_start_operation(void *cipher, | 
					
						
							|  |  |  |                                             uint8_t   initialCounterBlock[], | 
					
						
							|  |  |  |                                             size_t    initialCounterBlock_len, | 
					
						
							|  |  |  |                                             size_t    prefix_len, | 
					
						
							|  |  |  |                                             unsigned  counter_len, | 
					
						
							|  |  |  |                                             unsigned  littleEndian, | 
					
						
							|  |  |  |                                             void **pResult); | 
					
						
							|  |  |  |                     int CTR_encrypt(void *ctrState, | 
					
						
							|  |  |  |                                     const uint8_t *in, | 
					
						
							|  |  |  |                                     uint8_t *out, | 
					
						
							|  |  |  |                                     size_t data_len); | 
					
						
							|  |  |  |                     int CTR_decrypt(void *ctrState, | 
					
						
							|  |  |  |                                     const uint8_t *in, | 
					
						
							|  |  |  |                                     uint8_t *out, | 
					
						
							|  |  |  |                                     size_t data_len); | 
					
						
							|  |  |  |                     int CTR_stop_operation(void *ctrState);"""
 | 
					
						
							|  |  |  |                                         ) | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-09 21:43:24 +01:00
										 |  |  | class CtrMode(object): | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  |     """*CounTeR (CTR)* mode.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This mode is very similar to ECB, in that | 
					
						
							|  |  |  |     encryption of one block is done independently of all other blocks. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Unlike ECB, the block *position* contributes to the encryption | 
					
						
							|  |  |  |     and no information leaks about symbol frequency. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Each message block is associated to a *counter* which | 
					
						
							|  |  |  |     must be unique across all messages that get encrypted | 
					
						
							|  |  |  |     with the same key (not just within the same message). | 
					
						
							|  |  |  |     The counter is as big as the block size. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Counters can be generated in several ways. The most | 
					
						
							|  |  |  |     straightword one is to choose an *initial counter block* | 
					
						
							|  |  |  |     (which can be made public, similarly to the *IV* for the | 
					
						
							|  |  |  |     other modes) and increment its lowest **m** bits by one | 
					
						
							|  |  |  |     (modulo *2^m*) for each block. In most cases, **m** is | 
					
						
							|  |  |  |     chosen to be half the block size. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-09 21:43:24 +01:00
										 |  |  |     See `NIST SP800-38A`_, Section 6.5 (for the mode) and | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  |     Appendix B (for how to manage the *initial counter block*). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |     def __init__(self, block_cipher, initial_counter_block, | 
					
						
							|  |  |  |                  prefix_len, counter_len, little_endian): | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  |         """Create a new block cipher, configured in CTR mode.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :Parameters: | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |           block_cipher : C pointer | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |             A smart pointer to the low-level block cipher instance. | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |           initial_counter_block : byte string | 
					
						
							|  |  |  |             The initial plaintext to use to generate the key stream. | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |             It is as large as the cipher block, and it embeds | 
					
						
							|  |  |  |             the initial value of the counter. | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |             This value must not be reused. | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  |             It shall contain a nonce or a random component. | 
					
						
							|  |  |  |             Reusing the *initial counter block* for encryptions | 
					
						
							|  |  |  |             performed with the same key compromises confidentiality. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |           prefix_len : integer | 
					
						
							|  |  |  |             The amount of bytes at the beginning of the counter block | 
					
						
							|  |  |  |             that never change. | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |           counter_len : integer | 
					
						
							|  |  |  |             The length in bytes of the counter embedded in the counter | 
					
						
							|  |  |  |             block. | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |           little_endian : boolean | 
					
						
							|  |  |  |             True if the counter in the counter block is an integer encoded | 
					
						
							|  |  |  |             in little endian mode. If False, it is big endian. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-10 22:29:40 +01:00
										 |  |  |         expect_byte_string(initial_counter_block) | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |         self._state = VoidPointer() | 
					
						
							|  |  |  |         result = raw_ctr_lib.CTR_start_operation(block_cipher.get(), | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |                                                  initial_counter_block, | 
					
						
							| 
									
										
										
										
											2015-02-10 16:45:25 +01:00
										 |  |  |                                                  c_size_t(len(initial_counter_block)), | 
					
						
							|  |  |  |                                                  c_size_t(prefix_len), | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |                                                  counter_len, | 
					
						
							|  |  |  |                                                  little_endian, | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |                                                  self._state.address_of()) | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |         if result: | 
					
						
							|  |  |  |             raise ValueError("Error %X while instatiating the CTR mode" | 
					
						
							|  |  |  |                              % result) | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Ensure that object disposal of this Python object will (eventually) | 
					
						
							|  |  |  |         # free the memory allocated by the raw library for the cipher mode | 
					
						
							|  |  |  |         self._state = SmartPointer(self._state.get(), | 
					
						
							|  |  |  |                                    raw_ctr_lib.CTR_stop_operation) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Memory allocated for the underlying block cipher is now owed | 
					
						
							|  |  |  |         # by the cipher mode | 
					
						
							|  |  |  |         block_cipher.release() | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #: The block size of the underlying cipher, in bytes. | 
					
						
							|  |  |  |         self.block_size = len(initial_counter_block) | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def encrypt(self, plaintext): | 
					
						
							|  |  |  |         """Encrypt data with the key and the parameters set at initialization.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         A cipher object is stateful: once you have encrypted a message | 
					
						
							|  |  |  |         you cannot encrypt (or decrypt) another message using the same | 
					
						
							|  |  |  |         object. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The data to encrypt can be broken up in two or | 
					
						
							|  |  |  |         more pieces and `encrypt` can be called multiple times. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         That is, the statement: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             >>> c.encrypt(a) + c.encrypt(b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         is equivalent to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              >>> c.encrypt(a+b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         This function does not add any padding to the plaintext. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :Parameters: | 
					
						
							|  |  |  |           plaintext : byte string | 
					
						
							|  |  |  |             The piece of data to encrypt. | 
					
						
							|  |  |  |             It can be of any length. | 
					
						
							|  |  |  |         :Return: | 
					
						
							|  |  |  |             the encrypted data, as a byte string. | 
					
						
							|  |  |  |             It is as long as *plaintext*. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-10 22:29:40 +01:00
										 |  |  |         expect_byte_string(plaintext) | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |         ciphertext = create_string_buffer(len(plaintext)) | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |         result = raw_ctr_lib.CTR_encrypt(self._state.get(), | 
					
						
							|  |  |  |                                          plaintext, | 
					
						
							|  |  |  |                                          ciphertext, | 
					
						
							| 
									
										
										
										
											2015-02-10 16:45:25 +01:00
										 |  |  |                                          c_size_t(len(plaintext))) | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |         if result: | 
					
						
							|  |  |  |             raise ValueError("Error %X while encrypting in CTR mode" % result) | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |         return get_raw_buffer(ciphertext) | 
					
						
							| 
									
										
										
										
											2014-12-10 21:40:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def decrypt(self, ciphertext): | 
					
						
							|  |  |  |         """Decrypt data with the key and the parameters set at initialization.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         A cipher object is stateful: once you have decrypted a message | 
					
						
							|  |  |  |         you cannot decrypt (or encrypt) another message with the same | 
					
						
							|  |  |  |         object. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The data to decrypt can be broken up in two or | 
					
						
							|  |  |  |         more pieces and `decrypt` can be called multiple times. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         That is, the statement: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             >>> c.decrypt(a) + c.decrypt(b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         is equivalent to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              >>> c.decrypt(a+b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         This function does not remove any padding from the plaintext. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :Parameters: | 
					
						
							|  |  |  |           ciphertext : byte string | 
					
						
							|  |  |  |             The piece of data to decrypt. | 
					
						
							|  |  |  |             It can be of any length. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :Return: the decrypted data (byte string). | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-10 22:29:40 +01:00
										 |  |  |         expect_byte_string(ciphertext) | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |         plaintext = create_string_buffer(len(ciphertext)) | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |         result = raw_ctr_lib.CTR_decrypt(self._state.get(), | 
					
						
							|  |  |  |                                          ciphertext, | 
					
						
							|  |  |  |                                          plaintext, | 
					
						
							| 
									
										
										
										
											2015-02-10 16:45:25 +01:00
										 |  |  |                                          c_size_t(len(ciphertext))) | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  |         if result: | 
					
						
							|  |  |  |             raise ValueError("Error %X while decrypting in CTR mode" % result) | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |         return get_raw_buffer(plaintext) | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _create_ctr_cipher(factory, **kwargs): | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |     """Instantiate a cipher object that performs CTR encryption/decryption.
 | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |     :Parameters: | 
					
						
							|  |  |  |       factory : module | 
					
						
							|  |  |  |         The underlying block cipher, a module from ``Crypto.Cipher``. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     :Keywords: | 
					
						
							|  |  |  |       iv : byte string | 
					
						
							|  |  |  |         The IV to use for CBC. | 
					
						
							| 
									
										
										
										
											2014-12-16 07:50:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |       IV : byte string | 
					
						
							|  |  |  |         Alias for ``iv``. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       counter : object | 
					
						
							|  |  |  |         Instance of ``Crypto.Util.Counter``. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Any other keyword will be passed to the underlying block cipher. | 
					
						
							|  |  |  |     See the relevant documentation for details (at least ``key`` will need | 
					
						
							|  |  |  |     to be present). | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cipher_state = factory._create_base_cipher(kwargs) | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         counter = kwargs.pop("counter") | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         # Required by unit test | 
					
						
							|  |  |  |         raise TypeError("Missing 'counter' parameter for CTR mode") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # 'counter' used to be a callable object, but now it is | 
					
						
							|  |  |  |     # just a dictionary for backward compatibility. | 
					
						
							|  |  |  |     counter_len = counter.pop("counter_len") | 
					
						
							|  |  |  |     prefix = counter.pop("prefix") | 
					
						
							|  |  |  |     suffix = counter.pop("suffix") | 
					
						
							|  |  |  |     initial_value = counter.pop("initial_value") | 
					
						
							|  |  |  |     little_endian = counter.pop("little_endian") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Compute initial counter block | 
					
						
							|  |  |  |     words = [] | 
					
						
							|  |  |  |     while initial_value > 0: | 
					
						
							|  |  |  |         words.append(bchr(initial_value & 255)) | 
					
						
							|  |  |  |         initial_value >>= 8 | 
					
						
							|  |  |  |     words += [bchr(0)] * max(0, counter_len - len(words)) | 
					
						
							|  |  |  |     if not little_endian: | 
					
						
							|  |  |  |         words.reverse() | 
					
						
							|  |  |  |     initial_counter_block = prefix + b("").join(words) + suffix | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if kwargs: | 
					
						
							|  |  |  |         raise ValueError("Unknown parameters for CTR mode: %s" | 
					
						
							|  |  |  |                          % str(kwargs)) | 
					
						
							| 
									
										
										
										
											2015-03-09 21:43:24 +01:00
										 |  |  |     return CtrMode(cipher_state, initial_counter_block, | 
					
						
							| 
									
										
										
										
											2015-01-19 14:00:35 +01:00
										 |  |  |                       len(prefix), counter_len, little_endian) |