From 7b880de63b01a75abd339308d0adf167e5d7729a Mon Sep 17 00:00:00 2001
From: mtu <maxence.tury@ssi.gouv.fr>
Date: Fri, 10 Feb 2017 13:51:16 +0100
Subject: [PATCH] Enable DES and EXP-DES for TLS

---
 scapy/layers/tls/__init__.py             |  2 --
 scapy/layers/tls/crypto/cipher_block.py  | 42 +++++++++++++-----------
 scapy/layers/tls/crypto/cipher_stream.py | 17 ++++++----
 test/tls.uts                             | 21 ++++++++++++
 4 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/scapy/layers/tls/__init__.py b/scapy/layers/tls/__init__.py
index 2c615919..cb6a6dd0 100644
--- a/scapy/layers/tls/__init__.py
+++ b/scapy/layers/tls/__init__.py
@@ -63,8 +63,6 @@ TODO list (may it be carved away by good souls):
 
         - the so-called 'tls' hash used with SSLv3 and TLS 1.0;
 
-        - the simple DES algorithm;
-
         - the compressed EC point format.
 
 
diff --git a/scapy/layers/tls/crypto/cipher_block.py b/scapy/layers/tls/crypto/cipher_block.py
index de750438..81dfb1da 100644
--- a/scapy/layers/tls/crypto/cipher_block.py
+++ b/scapy/layers/tls/crypto/cipher_block.py
@@ -39,7 +39,11 @@ class _BlockCipher(object):
         self.ready = {"key":True, "iv":True}
         if key is None:
             self.ready["key"] = False
-            key = "\0" * self.key_len
+            if hasattr(self, "expanded_key_len"):
+                l = self.expanded_key_len
+            else:
+                l = self.key_len
+            key = "\0" * l
         if iv is None or iv == "":
             self.ready["iv"] = False
             iv = "\0" * self.block_size
@@ -112,6 +116,24 @@ class Cipher_CAMELLIA_256_CBC(Cipher_CAMELLIA_128_CBC):
 
 ### Mostly deprecated ciphers
 
+class Cipher_DES_CBC(_BlockCipher):
+    pc_cls = algorithms.TripleDES
+    pc_cls_mode = modes.CBC
+    block_size = 8
+    key_len = 8
+
+class Cipher_DES40_CBC(Cipher_DES_CBC):
+    """
+    This is an export cipher example. The key length has been weakened to 5
+    random bytes (i.e. 5 bytes will be extracted from the master_secret).
+    Yet, we still need to know the original length which will actually be
+    fed into the encryption algorithm. This is what expanded_key_len
+    is for, and it gets used in PRF.postprocess_key_for_export().
+    We never define this attribute with non-export ciphers.
+    """
+    expanded_key_len = 8
+    key_len = 5
+
 class Cipher_3DES_EDE_CBC(_BlockCipher):
     pc_cls = algorithms.TripleDES
     pc_cls_mode = modes.CBC
@@ -130,24 +152,6 @@ class Cipher_SEED_CBC(_BlockCipher):
     block_size = 16
     key_len = 16
 
-#class Cipher_DES_CBC(_BlockCipher):
-#    pc_cls = algorithms.DES    # no support in the cryptography library
-#    pc_cls_mode = modes.CBC
-#    block_size = 8
-#    key_len = 8
-
-#class Cipher_DES40_CBC(Cipher_DES_CBC):
-#    """
-#    This is an export cipher example. The key length has been weakened to 5
-#    random bytes (i.e. 5 bytes will be extracted from the master_secret).
-#    Yet, we still need to know the original length which will actually be
-#    fed into the encryption algorithm. This is what expanded_key_len
-#    is for, and it gets used in PRF.postprocess_key_for_export().
-#    We never define this attribute with non-export ciphers.
-#    """
-#    key_len = 5
-#    expanded_key_len = 8
-
 #class Cipher_RC2_CBC_40(_BlockCipher): # RFC 2268
 #    pc_cls = ARC2              # no support in the cryptography library
 #    pc_cls_mode = modes.CBC
diff --git a/scapy/layers/tls/crypto/cipher_stream.py b/scapy/layers/tls/crypto/cipher_stream.py
index 7a403f3c..6bfd1a37 100644
--- a/scapy/layers/tls/crypto/cipher_stream.py
+++ b/scapy/layers/tls/crypto/cipher_stream.py
@@ -42,7 +42,11 @@ class _StreamCipher(object):
         self.ready = {"key":True}
         if key is None:
             self.ready["key"] = False
-            key = "\0" * self.key_len
+            if hasattr(self, "expanded_key_len"):
+                l = self.expanded_key_len
+            else:
+                l = self.key_len
+            key = "\0" * l
 
         # we use super() in order to avoid any deadlock with __setattr__
         super(_StreamCipher, self).__setattr__("key", key)
@@ -71,18 +75,17 @@ class _StreamCipher(object):
         return self.decryptor.update(data)
 
 
-class Cipher_RC4_40(_StreamCipher):
+class Cipher_RC4_128(_StreamCipher):
     pc_cls = algorithms.ARC4
-    key_len = 5
-    expanded_key_len = 16
-
-class Cipher_RC4_128(Cipher_RC4_40):
     key_len = 16
 
+class Cipher_RC4_40(Cipher_RC4_128):
+    expanded_key_len = 16
+    key_len = 5
+
 
 class Cipher_NULL(_StreamCipher):
     key_len = 0
-    expanded_key_len = 0
 
     def __init__(self, key=None):
         self.ready = {"key":True}
diff --git a/test/tls.uts b/test/tls.uts
index e24d203d..0604b17a 100644
--- a/test/tls.uts
+++ b/test/tls.uts
@@ -416,6 +416,27 @@ def _all_rc4_tests():
 _all_rc4_tests()
 
 
++ Test DES-CBC
+= Crypto - DES cipher in CBC mode, check from FIPS PUB 81
+import binascii
+class _descbc_test:
+    k= binascii.unhexlify("0123456789abcdef")
+    p= binascii.unhexlify("4e6f77206973207468652074696d6520666f7220616c6c20")
+    c= binascii.unhexlify("e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6")
+    iv=binascii.unhexlify("1234567890abcdef")
+
+def _all_aes_cbc_tests():
+    from scapy.layers.tls.crypto.cipher_block import Cipher_DES_CBC
+    res = True
+    t = _descbc_test
+    tmp = (Cipher_DES_CBC(t.k, t.iv).encrypt(t.p) == t.c and
+           Cipher_DES_CBC(t.k, t.iv).decrypt(t.c) == t.p)
+    res = res and tmp
+    return res
+
+_all_aes_cbc_tests()
+
+
 + Test AES-CBC
 = Crypto - AES cipher in CBC mode, checks from RFC 3602
 
-- 
GitLab