From e758a218ea1a4017ff4070186da63e1bbb25e710 Mon Sep 17 00:00:00 2001 From: mtu Date: Thu, 26 Jan 2017 16:26:59 +0100 Subject: [PATCH] Ask for python-cryptography v1.7+ in warnings and documentation --- appveyor.yml | 2 +- doc/scapy/installation.rst | 26 ++++++---- scapy/config.py | 27 +++++++++- scapy/layers/dot11.py | 70 +++++++++++++------------- scapy/layers/ipsec.py | 47 ++++++++---------- scapy/layers/tls/__init__.py | 8 +-- scapy/layers/tls/cert.py | 14 ++++-- scapy/layers/tls/crypto/pkcs1.py | 84 ++++++++++++++++++-------------- test/ipsec.uts | 3 +- 9 files changed, 161 insertions(+), 120 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c8300abac..351cf4ef9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -29,7 +29,7 @@ test_script: # Secondary unit tests - 'del test\bpf.uts' # Don't bother with BPF regression tests - - "for %%t in (test\\*.uts) do (%PYTHON%\\python -m coverage run -a bin\\UTscapy -f text -t %%t -F -K combined_modes || exit /b 42)" + - "for %%t in (test\\*.uts) do (%PYTHON%\\python -m coverage run -a bin\\UTscapy -f text -t %%t -F -K combined_modes_ccm || exit /b 42)" # Contrib unit tests - "for %%t in (scapy\\contrib\\*.uts) do (%PYTHON%\\python -m coverage run -a bin\\UTscapy -f text -t %%t -F -P \"load_contrib(\'%%~nt\')\" || exit /b 42)" diff --git a/doc/scapy/installation.rst b/doc/scapy/installation.rst index 9272bd470..ac5ab68bf 100644 --- a/doc/scapy/installation.rst +++ b/doc/scapy/installation.rst @@ -166,11 +166,13 @@ Here are the topics involved and some examples that you can use to try if your i >>> enc=rdpcap("weplab-64bit-AA-managed.pcap") >>> enc.show() >>> enc[0] - >>> conf.wepkey="AA\x00\x00\x00" - >>> dec=Dot11PacketList(enc).toEthernet() - >>> dec.show() - >>> dec[0] + >>> conf.wepkey="AA\x00\x00\x00" + >>> dec=Dot11PacketList(enc).toEthernet() + >>> dec.show() + >>> dec[0] +* PKI operations and TLS decryption. `cryptography ` is also needed. + * Fingerprinting. ``nmap_fp()`` needs `Nmap `_. You need an `old version `_ (before v4.23) that still supports first generation fingerprinting. .. code-block:: python @@ -187,8 +189,6 @@ Here are the topics involved and some examples that you can use to try if your i * VOIP. ``voip_play()`` needs `SoX `_. -* IPsec Crypto Support. ``SecurityAssociation()`` needs `Pycrypto 2.7a1 `_. Combined AEAD modes such as GCM and CCM are not available yet because of cryptography restrictions. - Platform-specific instructions ============================== @@ -207,7 +207,13 @@ Debian/Ubuntu Just use the standard packages:: -$ sudo apt-get install tcpdump graphviz imagemagick python-gnuplot python-crypto python-pyx +$ sudo apt-get install tcpdump graphviz imagemagick python-gnuplot python-cryptography python-pyx + +Scapy optionally uses python-cryptography v1.7 or later. It has not been packaged for ``apt`` in less recent OS versions (e.g. Debian Jessie). If you need the cryptography-related methods, you may install the library with: + +.. code-block:: text + + # pip install cryptography Fedora ------ @@ -226,7 +232,7 @@ Some optional packages: .. code-block:: text - # yum install graphviz python-crypto sox PyX gnuplot numpy + # yum install graphviz python-cryptography sox PyX gnuplot numpy # cd /tmp # wget http://heanet.dl.sourceforge.net/sourceforge/gnuplot-py/gnuplot-py-1.8.tar.gz # tar xvfz gnuplot-py-1.8.tar.gz @@ -288,11 +294,11 @@ Here's how to install Scapy on OpenBSD 5.9+ Optional packages (OpenBSD only) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -py-crypto +py-cryptography .. code-block:: text - # pkg_add py-crypto + # pkg_add py-cryptography gnuplot and its Python binding: diff --git a/scapy/config.py b/scapy/config.py index fe541ed57..ffd0844b6 100755 --- a/scapy/config.py +++ b/scapy/config.py @@ -4,7 +4,7 @@ ## This program is published under a GPLv2 license """ -Implementation for of the configuration object. +Implementation of the configuration object. """ import os,time,socket,sys @@ -279,6 +279,14 @@ class LogLevel(object): obj._logLevel = val +def isCryptographyValid(): + try: + import cryptography + except ImportError: + return False + from distutils.version import LooseVersion + return LooseVersion(cryptography.__version__) >= LooseVersion("1.7") + def _prompt_changer(attr,val): prompt = conf.prompt @@ -396,6 +404,7 @@ contribs: a dict which can be used by contrib layers to store local configuratio "tftp", "x509", "bluetooth", "dhcp6", "llmnr", "sctp", "vrrp", "ipsec", "lltd", "vxlan"] contribs = dict() + crypto_valid = isCryptographyValid() if not Conf.ipv6_enabled: @@ -404,7 +413,23 @@ if not Conf.ipv6_enabled: if m in Conf.load_layers: Conf.load_layers.remove(m) +if not Conf.crypto_valid: + log_scapy.warning("Crypto-related methods disabled for IPsec, Dot11 " + "and TLS layers (needs python-cryptography v1.7+).") conf=Conf() conf.logLevel=30 # 30=Warning + +def crypto_validator(func): + """ + This a decorator to be used for any method relying on the cryptography library. + Its behaviour depends on the 'crypto_valid' attribute of the global 'conf'. + """ + def func_in(*args, **kwargs): + if not conf.crypto_valid: + raise ImportError("Cannot execute crypto-related method! " + "Please install python-cryptography v1.7 or later.") + return func(*args, **kwargs) + return func_in + diff --git a/scapy/layers/dot11.py b/scapy/layers/dot11.py index f6f92b773..8474412e4 100644 --- a/scapy/layers/dot11.py +++ b/scapy/layers/dot11.py @@ -10,7 +10,7 @@ Wireless LAN according to IEEE 802.11. import re,struct from zlib import crc32 -from scapy.config import conf +from scapy.config import conf, crypto_validator from scapy.data import * from scapy.packet import * from scapy.fields import * @@ -20,14 +20,12 @@ from scapy.layers.l2 import * from scapy.layers.inet import IP, TCP -try: +if conf.crypto_valid: from cryptography.hazmat.backends import default_backend - from cryptography.hazmat.primitives.ciphers import ( - Cipher, - algorithms, - ) -except ImportError: - log_loading.info("Can't import python cryptography lib. Won't be able to decrypt WEP.") + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms +else: + default_backend = Ciphers = algorithms = None + log_loading.info("Can't import python-cryptography v1.7+. Disabled WEP decryption/encryption.") ### Fields @@ -324,6 +322,18 @@ class Dot11WEP(Packet): StrField("wepdata",None,remain=4), IntField("icv",None) ] + @crypto_validator + def decrypt(self, key=None): + if key is None: + key = conf.wepkey + if key: + d = Cipher( + algorithms.ARC4(self.iv + key), + None, + default_backend(), + ).decryptor() + self.add_payload(LLC(d.update(self.wepdata) + d.finalize())) + def post_dissect(self, s): self.decrypt() @@ -332,36 +342,30 @@ class Dot11WEP(Packet): return Packet.build_payload(self) return "" - def post_build(self, p, pay): - if self.wepdata is None: - key = conf.wepkey - if key: - if self.icv is None: - pay += struct.pack("