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)