def __init__(self, factory, key, nonce, kwargs): self.block_size = factory.block_size self._factory = factory self._nonce = nonce self._cipher_params = kwargs if len(key) not in (32, 48, 64): raise ValueError("Incorrect key length (%d bytes)" % len(key)) if nonce is not None: if not byte_string(nonce): raise TypeError("When provided, the nonce must be a byte string") if len(nonce) == 0: raise ValueError("When provided, the nonce must be non-empty") #: Public attribute is only available in case of non-deterministic #: encryption self.nonce = nonce subkey_size = len(key) // 2 self._mac_tag = None # Cache for MAC tag self._kdf = _S2V(key[:subkey_size], ciphermod=factory, cipher_params=self._cipher_params) self._subkey_cipher = key[subkey_size:] # Purely for the purpose of verifying that cipher_params are OK factory.new(key[:subkey_size], factory.MODE_ECB, **kwargs) # Allowed transitions after initialization self._next = [self.update, self.encrypt, self.decrypt, self.digest, self.verify]
def _update(self, assoc_data_pt=b("")): """Update the MAC with associated data or plaintext (without FSM checks)""" if self._mac_status == MacStatus.NOT_STARTED: self._cache.append(assoc_data_pt) return assert(byte_string(self._cache)) assert(len(self._cache) < self.block_size) if len(self._cache) > 0: filler = min(self.block_size - len(self._cache), len(assoc_data_pt)) self._cache += assoc_data_pt[:filler] assoc_data_pt = assoc_data_pt[filler:] if len(self._cache) < self.block_size: return # The cache is exactly one block self._t = self._mac.encrypt(self._cache) self._cache = b("") update_len = len(assoc_data_pt) // self.block_size * self.block_size self._cache = assoc_data_pt[update_len:] if update_len > 0: self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:]
def _update(self, assoc_data_pt=b("")): """Update the MAC with associated data or plaintext (without FSM checks)""" if self._mac_status == MacStatus.NOT_STARTED: self._cache.append(assoc_data_pt) return assert (byte_string(self._cache)) assert (len(self._cache) < self.block_size) if len(self._cache) > 0: filler = min(self.block_size - len(self._cache), len(assoc_data_pt)) self._cache += assoc_data_pt[:filler] assoc_data_pt = assoc_data_pt[filler:] if len(self._cache) < self.block_size: return # The cache is exactly one block self._t = self._mac.encrypt(self._cache) self._cache = b("") update_len = len(assoc_data_pt) // self.block_size * self.block_size self._cache = assoc_data_pt[update_len:] if update_len > 0: self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:]
def c_uint8_ptr(data): if isinstance(data, _buffer_type): # This only works for cffi >= 1.7 return ffi.cast(uint8_t_type, ffi.from_buffer(data)) elif byte_string(data) or isinstance(data, _Array): return data else: raise TypeError("Object type %s cannot be passed to C code" % type(data))
def c_uint8_ptr(data): if byte_string(data) or isinstance(data, Array): return data elif isinstance(data, bytearray): local_type = c_ubyte * len(data) return local_type.from_buffer(data) else: raise TypeError("Object type %s cannot be passed to C code" % type(data))
def c_uint8_ptr(data): if byte_string(data) or isinstance(data, _Array): return data elif isinstance(data, _buffer_type): obj = _py_object(data) buf = _Py_buffer() _PyObject_GetBuffer(obj, byref(buf), _PyBUF_SIMPLE) buffer_type = c_ubyte * buf.len return buffer_type.from_address(buf.buf) else: raise TypeError("Object type %s cannot be passed to C code" % type(data))
def _pad_cache_and_update(self): assert(self._mac_status != MacStatus.NOT_STARTED) assert(byte_string(self._cache)) assert(len(self._cache) < self.block_size) # Associated data is concatenated with the least number # of zero bytes (possibly none) to reach alignment to # the 16 byte boundary (A.2.3) len_cache = len(self._cache) if len_cache > 0: self._update(bchr(0) * (self.block_size - len_cache))
def _pad_cache_and_update(self): assert (self._mac_status != MacStatus.NOT_STARTED) assert (byte_string(self._cache)) assert (len(self._cache) < self.block_size) # Associated data is concatenated with the least number # of zero bytes (possibly none) to reach alignment to # the 16 byte boundary (A.2.3) len_cache = len(self._cache) if len_cache > 0: self._update(bchr(0) * (self.block_size - len_cache))
def encode(self): """Return this DER SEQUENCE, fully encoded as a binary string. Raises: ValueError: if some elements in the sequence are neither integers nor byte strings. """ self.payload = b('') for item in self._seq: if byte_string(item): self.payload += item elif _is_number(item): self.payload += DerInteger(item).encode() else: self.payload += item.encode() return DerObject.encode(self)
def __init__(self, factory, key, nonce, mac_len, cipher_params): """EAX cipher mode""" self.block_size = factory.block_size """The block size of the underlying cipher, in bytes.""" self.nonce = nonce """The nonce originally used to create the object.""" self._mac_len = mac_len self._mac_tag = None # Cache for MAC tag # Allowed transitions after initialization self._next = [ self.update, self.encrypt, self.decrypt, self.digest, self.verify ] # MAC tag length if not (4 <= self._mac_len <= self.block_size): raise ValueError("Parameter 'mac_len' must not be larger than %d" % self.block_size) # Nonce cannot be empty and must be a byte string if len(nonce) == 0: raise ValueError("Nonce cannot be empty in EAX mode") if not byte_string(nonce): raise TypeError("Nonce must be a byte string") self._omac = [ CMAC.new(key, bchr(0) * (self.block_size - 1) + bchr(i), ciphermod=factory, cipher_params=cipher_params) for i in xrange(0, 3) ] # Compute MAC of nonce self._omac[0].update(nonce) self._signer = self._omac[1] # MAC of the nonce is also the initial counter for CTR encryption counter_int = bytes_to_long(self._omac[0].digest()) self._cipher = factory.new(key, factory.MODE_CTR, initial_value=counter_int, nonce=b(""), **cipher_params)
def encode(self): """Return this DER SEQUENCE, fully encoded as a binary string. Raises: ValueError: if some elements in the sequence are neither integers nor byte strings. """ self.payload = b'' for item in self._seq: if byte_string(item): self.payload += item elif _is_number(item): self.payload += DerInteger(item).encode() else: self.payload += item.encode() return DerObject.encode(self)
def __init__(self, factory, key, nonce, mac_len, cipher_params): """EAX cipher mode""" self.block_size = factory.block_size """The block size of the underlying cipher, in bytes.""" self.nonce = nonce """The nonce originally used to create the object.""" self._mac_len = mac_len self._mac_tag = None # Cache for MAC tag # Allowed transitions after initialization self._next = [self.update, self.encrypt, self.decrypt, self.digest, self.verify] # MAC tag length if not (4 <= self._mac_len <= self.block_size): raise ValueError("Parameter 'mac_len' must not be larger than %d" % self.block_size) # Nonce cannot be empty and must be a byte string if len(nonce) == 0: raise ValueError("Nonce cannot be empty in EAX mode") if not byte_string(nonce): raise TypeError("Nonce must be a byte string") self._omac = [ CMAC.new(key, bchr(0) * (self.block_size - 1) + bchr(i), ciphermod=factory, cipher_params=cipher_params) for i in range(0, 3) ] # Compute MAC of nonce self._omac[0].update(nonce) self._signer = self._omac[1] # MAC of the nonce is also the initial counter for CTR encryption counter_int = bytes_to_long(self._omac[0].digest()) self._cipher = factory.new(key, factory.MODE_CTR, initial_value=counter_int, nonce=b(""), **cipher_params)
def __init__(self, factory, key, nonce, kwargs): self.block_size = factory.block_size """The block size of the underlying cipher, in bytes.""" self._factory = factory self._nonce = nonce self._cipher_params = kwargs if len(key) not in (32, 48, 64): raise ValueError("Incorrect key length (%d bytes)" % len(key)) if nonce is not None: if not byte_string(nonce): raise TypeError( "When provided, the nonce must be a byte string") if len(nonce) == 0: raise ValueError("When provided, the nonce must be non-empty") self.nonce = nonce """Public attribute is only available in case of non-deterministic encryption.""" subkey_size = len(key) // 2 self._mac_tag = None # Cache for MAC tag self._kdf = _S2V(key[:subkey_size], ciphermod=factory, cipher_params=self._cipher_params) self._subkey_cipher = key[subkey_size:] # Purely for the purpose of verifying that cipher_params are OK factory.new(key[:subkey_size], factory.MODE_ECB, **kwargs) # Allowed transitions after initialization self._next = [ self.update, self.encrypt, self.decrypt, self.digest, self.verify ]
def decode(self, der_encoded, strict=False): """Decode a complete DER element, and re-initializes this object with it. Args: der_encoded (byte string): A complete DER element. Raises: ValueError: in case of parsing errors. """ if not byte_string(der_encoded): raise ValueError("Input is not a byte string") s = BytesIO_EOF(der_encoded) self._decodeFromStream(s, strict) # There shouldn't be other bytes left if s.remaining_data() > 0: raise ValueError("Unexpected extra data after the DER structure") return self
def decode(self, derEle): """Decode a complete DER element, and re-initializes this object with it. :Parameters: derEle : byte string A complete DER element. :Raise ValueError: In case of parsing errors. """ if not byte_string(derEle): raise ValueError("Input is not a byte string") s = BytesIO_EOF(derEle) self._decodeFromStream(s) # There shouldn't be other bytes left if s.remaining_data() > 0: raise ValueError("Unexpected extra data after the DER structure") return self
def __init__(self, factory, key, nonce, mac_len, cipher_params): self.block_size = factory.block_size if self.block_size != 16: raise ValueError("GCM mode is only available for ciphers" " that operate on 128 bits blocks") if len(nonce) == 0: raise ValueError("Nonce cannot be empty") if not byte_string(nonce): raise TypeError("Nonce must be a byte string") self.nonce = nonce """Nonce""" self._factory = factory self._key = key self._tag = None # Cache for MAC tag self._mac_len = mac_len if not (4 <= mac_len <= 16): raise ValueError("Parameter 'mac_len' must be in the range 4..16") # Allowed transitions after initialization self._next = [self.update, self.encrypt, self.decrypt, self.digest, self.verify] self._no_more_assoc_data = False # Length of associated data self._auth_len = 0 # Length of the ciphertext or plaintext self._msg_len = 0 # Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H # See also Algorithm 5 (decryption) hash_subkey = factory.new(key, self._factory.MODE_ECB, **cipher_params ).encrypt(bchr(0) * 16) # Step 2 - Compute J0 (integer, not byte string!) if len(nonce) == 12: self._j0 = bytes_to_long(nonce + b("\x00\x00\x00\x01")) else: fill = (16 - (len(nonce) % 16)) % 16 + 8 ghash_in = (nonce + bchr(0) * fill + long_to_bytes(8 * len(nonce), 8)) self._j0 = bytes_to_long(_GHASH(hash_subkey) .update(ghash_in) .digest()) # Step 3 - Prepare GCTR cipher for encryption/decryption self._cipher = factory.new(key, self._factory.MODE_CTR, initial_value=self._j0 + 1, nonce=b(""), **cipher_params) # Step 5 - Bootstrat GHASH self._signer = _GHASH(hash_subkey) # Step 6 - Prepare GCTR cipher for GMAC self._tag_cipher = factory.new(key, self._factory.MODE_CTR, initial_value=self._j0, nonce=b(""), **cipher_params) # Cache for data to authenticate self._cache = b("") self._status = MacStatus.PROCESSING_AUTH_DATA
def _create_ctr_cipher(factory, **kwargs): """Instantiate a cipher object that performs CTR encryption/decryption. :Parameters: factory : module The underlying block cipher, a module from ``Crypto.Cipher``. :Keywords: nonce : binary string The fixed part at the beginning of the counter block - the rest is the counter number that gets increased when processing the next block. The nonce must be such that no two messages are encrypted under the same key and the same nonce. The nonce must be shorter than the block size (it can have zero length; the counter is then as long as the block). If this parameter is not present, a random nonce will be created with length equal to half the block size. No random nonce shorter than 64 bits will be created though - you must really think through all security consequences of using such a short block size. initial_value : posive integer or byte string The initial value for the counter. If not present, the cipher will start counting from 0. The value is incremented by one for each block. The counter number is encoded in big endian mode. counter : object Instance of ``Crypto.Util.Counter``, which allows full customization of the counter block. This parameter is incompatible to both ``nonce`` and ``initial_value``. 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) counter = kwargs.pop("counter", None) nonce = kwargs.pop("nonce", None) initial_value = kwargs.pop("initial_value", None) if kwargs: raise TypeError("Invalid parameters for CTR mode: %s" % str(kwargs)) if counter is not None and (nonce, initial_value) != (None, None): raise TypeError("'counter' and 'nonce'/'initial_value'" " are mutually exclusive") if counter is None: # Crypto.Util.Counter is not used if nonce is None: if factory.block_size < 16: raise TypeError("Impossible to create a safe nonce for short" " block sizes") nonce = get_random_bytes(factory.block_size // 2) else: if len(nonce) >= factory.block_size: raise ValueError("Nonce is too long") # What is not nonce is counter counter_len = factory.block_size - len(nonce) if initial_value is None: initial_value = 0 if byte_string(initial_value): if len(initial_value) != counter_len: raise ValueError( "Incorrect length for counter byte string (%d bytes, expected %d)" % (len(initial_value), counter_len)) initial_counter_block = nonce + initial_value else: if (1 << (counter_len * 8)) - 1 < initial_value: raise ValueError("Initial counter value is too large") initial_counter_block = nonce + long_to_bytes( initial_value, counter_len) return CtrMode( cipher_state, initial_counter_block, len(nonce), # prefix counter_len, False) # little_endian # Crypto.Util.Counter is used # 'counter' used to be a callable object, but now it is # just a dictionary for backward compatibility. _counter = dict(counter) try: 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") except KeyError: raise TypeError("Incorrect counter object" " (use Crypto.Util.Counter.new)") # 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 len(initial_counter_block) != factory.block_size: raise ValueError("Size of the counter block (%d bytes) must match" " block size (%d)" % (len(initial_counter_block), factory.block_size)) return CtrMode(cipher_state, initial_counter_block, len(prefix), counter_len, little_endian)
def expect_byte_string(data): if not byte_string(data) and not isinstance(data, Array): raise TypeError("Only byte strings can be passed to C code")