1## This file is part of Scapy 2## Copyright (C) 2007, 2008, 2009 Arnaud Ebalard 3## 2015, 2016, 2017 Maxence Tury 4## This program is published under a GPLv2 license 5 6""" 7Block ciphers. 8""" 9 10from __future__ import absolute_import 11from scapy.config import conf 12from scapy.utils import strxor 13from scapy.layers.tls.crypto.ciphers import CipherError 14import scapy.modules.six as six 15 16if conf.crypto_valid: 17 from cryptography.utils import register_interface 18 from cryptography.hazmat.primitives.ciphers import (Cipher, algorithms, modes, 19 BlockCipherAlgorithm, 20 CipherAlgorithm) 21 from cryptography.hazmat.backends.openssl.backend import (backend, 22 GetCipherByName) 23 24 25_tls_block_cipher_algs = {} 26 27class _BlockCipherMetaclass(type): 28 """ 29 Cipher classes are automatically registered through this metaclass. 30 Furthermore, their name attribute is extracted from their class name. 31 """ 32 def __new__(cls, ciph_name, bases, dct): 33 if ciph_name != "_BlockCipher": 34 dct["name"] = ciph_name[7:] # remove leading "Cipher_" 35 the_class = super(_BlockCipherMetaclass, cls).__new__(cls, ciph_name, 36 bases, dct) 37 if ciph_name != "_BlockCipher": 38 _tls_block_cipher_algs[ciph_name[7:]] = the_class 39 return the_class 40 41 42class _BlockCipher(six.with_metaclass(_BlockCipherMetaclass, object)): 43 type = "block" 44 45 def __init__(self, key=None, iv=None): 46 self.ready = {"key": True, "iv": True} 47 if key is None: 48 self.ready["key"] = False 49 if hasattr(self, "expanded_key_len"): 50 l = self.expanded_key_len 51 else: 52 l = self.key_len 53 key = b"\0" * l 54 if not iv: 55 self.ready["iv"] = False 56 iv = b"\0" * self.block_size 57 58 # we use super() in order to avoid any deadlock with __setattr__ 59 super(_BlockCipher, self).__setattr__("key", key) 60 super(_BlockCipher, self).__setattr__("iv", iv) 61 62 self._cipher = Cipher(self.pc_cls(key), 63 self.pc_cls_mode(iv), 64 backend=backend) 65 66 def __setattr__(self, name, val): 67 if name == "key": 68 if self._cipher is not None: 69 self._cipher.algorithm.key = val 70 self.ready["key"] = True 71 elif name == "iv": 72 if self._cipher is not None: 73 self._cipher.mode._initialization_vector = val 74 self.ready["iv"] = True 75 super(_BlockCipher, self).__setattr__(name, val) 76 77 78 def encrypt(self, data): 79 """ 80 Encrypt the data. Also, update the cipher iv. This is needed for SSLv3 81 and TLS 1.0. For TLS 1.1/1.2, it is overwritten in TLS.post_build(). 82 """ 83 if False in six.itervalues(self.ready): 84 raise CipherError(data) 85 encryptor = self._cipher.encryptor() 86 tmp = encryptor.update(data) + encryptor.finalize() 87 self.iv = tmp[-self.block_size:] 88 return tmp 89 90 def decrypt(self, data): 91 """ 92 Decrypt the data. Also, update the cipher iv. This is needed for SSLv3 93 and TLS 1.0. For TLS 1.1/1.2, it is overwritten in TLS.pre_dissect(). 94 If we lack the key, we raise a CipherError which contains the input. 95 """ 96 if False in six.itervalues(self.ready): 97 raise CipherError(data) 98 decryptor = self._cipher.decryptor() 99 tmp = decryptor.update(data) + decryptor.finalize() 100 self.iv = data[-self.block_size:] 101 return tmp 102 103 def snapshot(self): 104 c = self.__class__(self.key, self.iv) 105 c.ready = self.ready.copy() 106 return c 107 108 109if conf.crypto_valid: 110 class Cipher_AES_128_CBC(_BlockCipher): 111 pc_cls = algorithms.AES 112 pc_cls_mode = modes.CBC 113 block_size = 16 114 key_len = 16 115 116 class Cipher_AES_256_CBC(Cipher_AES_128_CBC): 117 key_len = 32 118 119 120 class Cipher_CAMELLIA_128_CBC(_BlockCipher): 121 pc_cls = algorithms.Camellia 122 pc_cls_mode = modes.CBC 123 block_size = 16 124 key_len = 16 125 126 class Cipher_CAMELLIA_256_CBC(Cipher_CAMELLIA_128_CBC): 127 key_len = 32 128 129 130### Mostly deprecated ciphers 131 132if conf.crypto_valid: 133 class Cipher_DES_CBC(_BlockCipher): 134 pc_cls = algorithms.TripleDES 135 pc_cls_mode = modes.CBC 136 block_size = 8 137 key_len = 8 138 139 class Cipher_DES40_CBC(Cipher_DES_CBC): 140 """ 141 This is an export cipher example. The key length has been weakened to 5 142 random bytes (i.e. 5 bytes will be extracted from the master_secret). 143 Yet, we still need to know the original length which will actually be 144 fed into the encryption algorithm. This is what expanded_key_len 145 is for, and it gets used in PRF.postprocess_key_for_export(). 146 We never define this attribute with non-export ciphers. 147 """ 148 expanded_key_len = 8 149 key_len = 5 150 151 class Cipher_3DES_EDE_CBC(_BlockCipher): 152 pc_cls = algorithms.TripleDES 153 pc_cls_mode = modes.CBC 154 block_size = 8 155 key_len = 24 156 157 class Cipher_IDEA_CBC(_BlockCipher): 158 pc_cls = algorithms.IDEA 159 pc_cls_mode = modes.CBC 160 block_size = 8 161 key_len = 16 162 163 class Cipher_SEED_CBC(_BlockCipher): 164 pc_cls = algorithms.SEED 165 pc_cls_mode = modes.CBC 166 block_size = 16 167 key_len = 16 168 169 170_sslv2_block_cipher_algs = {} 171 172if conf.crypto_valid: 173 _sslv2_block_cipher_algs.update({ 174 "IDEA_128_CBC": Cipher_IDEA_CBC, 175 "DES_64_CBC": Cipher_DES_CBC, 176 "DES_192_EDE3_CBC": Cipher_3DES_EDE_CBC 177 }) 178 179 180# We need some black magic for RC2, which is not registered by default 181# to the openssl backend of the cryptography library. 182# If the current version of openssl does not support rc2, the RC2 ciphers are 183# silently not declared, and the corresponding suites will have 'usable' False. 184 185if conf.crypto_valid: 186 @register_interface(BlockCipherAlgorithm) 187 @register_interface(CipherAlgorithm) 188 class _ARC2(object): 189 name = "RC2" 190 block_size = 64 191 key_sizes = frozenset([128]) 192 193 def __init__(self, key): 194 self.key = algorithms._verify_key_size(self, key) 195 196 @property 197 def key_size(self): 198 return len(self.key) * 8 199 200 201 _gcbn_format = "{cipher.name}-{mode.name}" 202 if GetCipherByName(_gcbn_format)(backend, _ARC2, modes.CBC) != \ 203 backend._ffi.NULL: 204 205 class Cipher_RC2_CBC(_BlockCipher): 206 pc_cls = _ARC2 207 pc_cls_mode = modes.CBC 208 block_size = 8 209 key_len = 16 210 211 class Cipher_RC2_CBC_40(Cipher_RC2_CBC): 212 expanded_key_len = 16 213 key_len = 5 214 215 backend.register_cipher_adapter(Cipher_RC2_CBC.pc_cls, 216 Cipher_RC2_CBC.pc_cls_mode, 217 GetCipherByName(_gcbn_format)) 218 219 _sslv2_block_cipher_algs["RC2_128_CBC"] = Cipher_RC2_CBC 220 221 222_tls_block_cipher_algs.update(_sslv2_block_cipher_algs) 223 224