diff --git a/.travis.yml b/.travis.yml
index f4cd9a21150b9136eddb5fd2b171f76f2b1dd090..b94ac0364757ed0ede87f9be732074f97ea9cc33 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -36,13 +36,6 @@ matrix:
           env:
             - SCAPY_SUDO=sudo SCAPY_USE_PCAPDNET=yes SCAPY_COVERAGE=yes 
 
-        - os: linux
-          sudo: required
-          python: 2.7
-          env:
-            - TRAVIS_SUDO=sudo
-            - TEST_COMBINED_MODES=yes
-
         - os: osx
           language: generic
           env:
diff --git a/.travis/test.sh b/.travis/test.sh
index 18917fcfb4c560ca597acfba81f3de39875b6d3d..64ba5b1fad648301e00673297a4fc27b346afe06 100644
--- a/.travis/test.sh
+++ b/.travis/test.sh
@@ -77,8 +77,8 @@ do
 done
 
 # Run unit tests with openssl if we have root privileges
-if [ "$TRAVIS_OS_NAME" = "linux" ] && [ ! -z $SCAPY_USE_PCAPDNET ] && [ ! -z $TRAVIS_SUDO ]
+if [ "$TRAVIS_OS_NAME" = "linux" ] && [ ! -z $SCAPY_USE_PCAPDNET ] && [ ! -z $SCAPY_SUDO ]
 then
-  $TRAVIS_SUDO ./run_tests_tls_netaccess || exit $?
+  $SCAPY_SUDO tls/run_tests_tls_netaccess || exit $?
 fi
 
diff --git a/scapy/config.py b/scapy/config.py
index 2a2bbc07dcaa56eacab68414284a63b85593cc16..e46ffeadc2f0dc97eaaf05426445cc471bae8839 100755
--- a/scapy/config.py
+++ b/scapy/config.py
@@ -308,69 +308,37 @@ def _prompt_changer(attr,val):
     sys.ps1 = prompt
 
 class Conf(ConfClass):
-    """
-    This object contains the configuration of scapy.
-    _session
-        Filename where the session will be saved.
-    _interactive_shell
-        If "ipython", use IPython as shell. Default is Python.
-    _stealth
-        If 1, prevent any unwanted packet to go out (ARP, DNS, ...).
-    _checkIPID
-        If 0, don't check that IPID matches between IP sent and ICMP IP
-        citation received. If 1, check that they either are equal or byte
-        swapped equals (bug in some IP stacks). If 2, strictly check that
-        they are equals.
-    _checkIPinIP
-        If True, check that IP-in-IP layers match. If False, do not check IP
-        layers that encapsulates another IP layer.
-    _checkIPsrc
-        If 1, check IP src in IP and ICMP IP citation match (bug in some NAT
-        stacks).
-    _check_TCPerror_seqack
-        If 1, also check that TCP seq and ack match the ones in ICMP citation.
-    _iff
-        Select the output interface for srp() and sendp(). Default is "eth0".
-    _verb
-        Level of verbosity, from 0 (almost mute) to 3 (verbose).
-    _promisc
-        Default mode for listening socket (to get answers if you spoof on a
-        lan).
-    _sniff_promisc
-        Default mode for sniff().
-    _filter
-        BPF filter added to every sniffing socket to exclude traffic from
-        analysis.
-    _histfile
-        History file.
-    _padding
-        Include padding in desassembled packets.
-    _except_filter
-        BPF filter for packets to ignore.
-    _debug_match
-        If 1, store received packet that are not matched into debug.recv.
-    _route
-        Holds the Scapy routing table and provides methods to manipulate it.
-    _warning_threshold
-        Set the time threshold between warnings from the same place.
-    _ASN1_default_codec
-        Codec used by default for ASN1 objects.
-    _mib
-        Holds MIB direct access dictionary.
-    _resolve
-        Holds a list of fields for which resolution should be done.
-    _noenum
-        Holds a list of enum fields for which conversion to string should NOT
-        be done.
-    _AS_resolver
-        Choose the AS resolver class to use.
-    _extensions_paths
-        Path or list of paths where extensions are to be looked for.
-    _contribs
-        A dict which can be used by contrib layers to store local configuration.
-    _debug_tls
-        When 1, print some TLS session secrets when they are computed.
-    """
+    """This object contains the configuration of Scapy.
+session  : filename where the session will be saved
+interactive_shell : If set to "ipython", use IPython as shell. Default: Python
+stealth  : if 1, prevents any unwanted packet to go out (ARP, DNS, ...)
+checkIPID: if 0, doesn't check that IPID matches between IP sent and ICMP IP citation received
+           if 1, checks that they either are equal or byte swapped equals (bug in some IP stacks)
+           if 2, strictly checks that they are equals
+checkIPsrc: if 1, checks IP src in IP and ICMP IP citation match (bug in some NAT stacks)
+checkIPinIP: if True, checks that IP-in-IP layers match. If False, do not
+             check IP layers that encapsulates another IP layer
+check_TCPerror_seqack: if 1, also check that TCP seq and ack match the ones in ICMP citation
+iff      : selects the default output interface for srp() and sendp(). default:"eth0")
+verb     : level of verbosity, from 0 (almost mute) to 3 (verbose)
+promisc  : default mode for listening socket (to get answers if you spoof on a lan)
+sniff_promisc : default mode for sniff()
+filter   : bpf filter added to every sniffing socket to exclude traffic from analysis
+histfile : history file
+padding  : includes padding in disassembled packets
+except_filter : BPF filter for packets to ignore
+debug_match : when 1, store received packet that are not matched into debug.recv
+route    : holds the Scapy routing table and provides methods to manipulate it
+warning_threshold : how much time between warnings from the same place
+ASN1_default_codec: Codec used by default for ASN1 objects
+mib      : holds MIB direct access dictionary
+resolve  : holds list of fields for which resolution should be done
+noenum   : holds list of enum fields for which conversion to string should NOT be done
+AS_resolver: choose the AS resolver class to use
+extensions_paths: path or list of paths where extensions are to be looked for
+contribs : a dict which can be used by contrib layers to store local configuration
+debug_tls:When 1, print some TLS session secrets when they are computed.
+"""
     version = VERSION
     session = ""
     interactive = False
diff --git a/scapy/layers/tls/__init__.py b/scapy/layers/tls/__init__.py
index bcc292ba4fe4040c67ed12dbe07531adafdadd23..5bc6d76b89e9920c763d7b1959ee9900c1a5df4c 100644
--- a/scapy/layers/tls/__init__.py
+++ b/scapy/layers/tls/__init__.py
@@ -8,15 +8,7 @@ Tools for handling TLS sessions and digital certificates.
 
 Prerequisites:
 
-    - You need to 'pip install ecdsa' for the module to be loaded.
-
-    - We rely on pycrypto for several computations, however the last packaged
-    version does not provide AEAD support. If you don't need it, just do
-    'pip install pycrypto'. If however you need GCM & CCM support, do
-    curl -sL https://github.com/dlitz/pycrypto/archive/v2.7a1.tar.gz | tar xz
-    cd pycrypto-2.7a1
-    python setup.py build
-    sudo python setup.py install
+    - You may need to 'pip install cryptography' for the module to be loaded.
 
 
 Main features:
@@ -26,22 +18,23 @@ Main features:
     - RSA & ECDSA keys sign/verify methods.
 
     - TLS records and sublayers (handshake...) parsing/building. Works with
-    versions TLS 1.0, 1.1 and 1.2. SSLv3 should be mostly ok. This may be
-    enhanced by a TLS context. For instance, if scapy reads a ServerHello
-    with version TLS 1.2 and a cipher suite using AES, it will assume the
-    presence of IVs prepending the data. See test/tls.uts for real examples.
+      versions SSLv3, TLS 1.0, 1.1 and 1.2. This may be enhanced by a TLS
+      context. For instance, if scapy reads a ServerHello with version TLS 1.2
+      and a cipher suite using AES, it will assume the presence of IVs
+      prepending the data. See test/tls.uts for real examples.
 
     - TLS encryption/decryption capabilities with the usual ciphersuites. Once
-    again, the TLS context enables scapy to transparently send/receive
-    protected data if it learnt the session secrets. Note that if scapy acts as
-    one side of the handshake (e.g. reads all server-related packets and builds
-    all client-related packets), it will indeed compute the session secrets.
+      again, the TLS context enables scapy to transparently send/receive
+      protected data if it learnt the session secrets. Note that if scapy acts
+      as one side of the handshake (e.g. reads all server-related packets and
+      builds all client-related packets), it will indeed compute the session
+      secrets.
 
     - TLS client & server basic automatons, provided for testing and tweaking
-    purposes. These make for a very primitive TLS stack.
+      purposes. These make for a very primitive TLS stack.
 
     - Additionally, a basic test PKI (key + certificate for a CA, a client and
-    a server) is provided in tls/examples/pki_test.
+      a server) is provided in tls/examples/pki_test.
 
 
 Unit tests:
@@ -57,46 +50,67 @@ Unit tests:
 
 TODO list (may it be carved away by good souls):
 
-    - Enrich the automatons. The client should be able to receive data at any
-    time, and to send as much data as wanted from stdin (for now, only one
-    predefined data message may be sent following the handshake). The server
-    should stay online even after the first client leaves. Then we could look
-    at more complicated behaviours like renegotiation and resumption.
-    We might get some help from tintinweb/scapy-ssl_tls.
+    - Features to add (or wait for) in the cryptography library:
+
+        - no limitation on FFDH generator size;
+          (remove line 88 in cryptography/hazmat/primitives/asymmetric/dh.py)
+
+        - CCM and CHACHA20-POLY1305 ciphers;
+
+        - ECDH curves (x25519 and x448) from RFC 7748;
+
+        - FFDH groups from RFC 7919;
+
+        - the so-called 'tls' hash used with SSLv3 and TLS 1.0;
+
+        - the simple DES algorithm;
+
+        - the compressed EC point format.
+
+
+    - About the automatons:
+
+        - Enrich the automatons. The client should be able to receive data at
+          any time, and to send as much data as wanted from stdin (for now,
+          only one predefined data message may be sent following the
+          handshake). The server should stay online even after the first client
+          leaves. Then we could look at more complicated behaviours like
+          renegotiation and resumption. We might get some help from
+          tintinweb/scapy-ssl_tls.
+
+        - Add some examples which illustrate how the automatons could be used.
+          Typically, we could showcase this with Heartbleed.
 
-    - Add some examples which illustrate how the automatons could be used.
-    Typically, we could showcase this with Heartbleed.
+        - Split up parts of the automaton, e.g. when our server builds the
+          ServerHello, Certificate, ServerKeyExchange and ServerHelloDone in
+          the same should_REPLY_TO_CH method.
 
-    - Split up parts of the automaton, e.g. when our server builds the
-    ServerHello, Certificate, ServerKeyExchange and ServerHelloDone in the
-    same should_REPLY_TO_CH method.
+        - Make the automatons tests more robust and less consuming.
 
-    - Make the automatons tests more robust and less consuming.
+        - Allow the server to store both one RSA key and one ECDSA key, and
+          select the right one to use according to the ClientHello suites.
 
-    - Allow for the server to store simultaneously one RSA key and one ECDSA
-    key, and select the right one to use according to the ClientHello suites.
+        - Find a way to shutdown the automatons sockets properly without
+          simultaneously breaking the unit tests.
 
-    - Find a way to shutdown the automatons sockets properly without
-    simultaneously breaking the unit tests.
 
-    - Switch from pycrypto to python-cryptography, once it provides proper
-    AEAD support. See if we could get CHACHA20-POLY1305 in the process.
+    - Miscellaneous:
 
-    - Check FFDH and ECDH parameters at SKE/CKE reception.
+        - Implement TLS 1.3 structures and automatons. :D
 
-    - Go through the kx_algs and see what may be commented out without risk.
+        - Implement SSLv2 structures and automatons. xD
 
-    - Define the OCSPStatus packet.
+        - Mostly unused features : DSS, fixed DH, SRP, IDEA, char2 curves...
 
-    - Define several Certificate Transparency objects.
+        - Check FFDH and ECDH parameters at SKE/CKE reception.
 
-    - Enhance PSK support.
+        - Go through the kx_algs and see what may be commented out.
 
-    - Mostly unused features : DSS, fixed DH, SRP, IDEA, KRB5, char2 curves...
+        - Define the OCSPStatus packet.
 
-    - Implement SSLv2 structures and automatons. xD
+        - Define several Certificate Transparency objects.
 
-    - Implement TLS 1.3 structures and automatons. :D
+        - Enhance PSK and session ticket support.
 """
 
 from scapy.config import conf
diff --git a/scapy/layers/tls/automaton.py b/scapy/layers/tls/automaton.py
index 9c1ce68896b39e75ce6d91388e8e620e91bd8ebc..f31c1f1b03c7358ba8671823a1e71d74acc21caf 100644
--- a/scapy/layers/tls/automaton.py
+++ b/scapy/layers/tls/automaton.py
@@ -829,9 +829,10 @@ class TLSServerAutomaton(Automaton):
         if self.cur_pkt.comp and 1 in self.cur_pkt.comp:
             comp = 1
 
-        # Should do more than that to decide which version to return
         self.cur_session.advertised_tls_version = self.cur_pkt.version
-        v = self.cur_session.advertised_tls_version
+        self.cur_session.tls_version = self.cur_pkt.version
+        #XXX there should be some checks on this version from the ClientHello
+        v = self.cur_session.tls_version
         print "\nVersion: " + _tls_version[v]
         print "Cipher suite: " + _tls_cipher_suites[c]
 
diff --git a/scapy/layers/tls/basefields.py b/scapy/layers/tls/basefields.py
index c480d8869813d6ce8ccc94723b64e5cbaad85e1e..cfa98d6e832cccfaf93e7197898fca4d0bc5b1fa 100644
--- a/scapy/layers/tls/basefields.py
+++ b/scapy/layers/tls/basefields.py
@@ -155,10 +155,11 @@ class _TLSPadField(StrField):
 
     def getfield(self, pkt, s):
         if pkt.tls_session.consider_read_padding():
-            # We get the length from the first byte of s which
+            # We get the length from the last byte of s which
             # is either the first byte of padding or the padding
-            # length field itself is padding length is 0
-            l = ord(s[0])
+            # length field itself is padding length is 0.
+            # This should work with SSLv3 and also TLS versions.
+            l = ord(s[-1])
             return s[l:], self.m2i(pkt, s[:l])
         return s, None
 
diff --git a/scapy/layers/tls/cert.py b/scapy/layers/tls/cert.py
index eea1cbc1d51ebfb41b5d73fec848da6f2931c0a1..a3eed47e4d57d8fadabd75197dafe9b9c9a6498c 100644
--- a/scapy/layers/tls/cert.py
+++ b/scapy/layers/tls/cert.py
@@ -8,8 +8,6 @@
 High-level methods for PKI objects (X.509 certificates, CRLs, asymmetric keys).
 Supports both RSA and ECDSA objects.
 
-This module relies on python-crypto and python-ecdsa.
-
 The classes below are wrappers for the ASN.1 objects defined in x509.py.
 By collecting their attributes, we bypass the ASN.1 structure, hence
 there is no direct method for exporting a new full DER-encoded version
@@ -107,6 +105,7 @@ class _PKIObj(object):
     def __init__(self, frmt, der, pem):
         # Note that changing attributes of the _PKIObj does not update these
         # values (e.g. modifying k.modulus does not change k.der).
+        #XXX use __setattr__ for this
         self.frmt = frmt
         self.der = der
         self.pem = pem
@@ -174,18 +173,16 @@ class _PubKeyFactory(_PKIObjMaker):
     """
     Metaclass for PubKey creation.
     It casts the appropriate class on the fly, then fills in
-    the appropriate attributes with updateWith() submethod.
+    the appropriate attributes with import_from_asn1pkt() submethod.
     """
     def __call__(cls, key_path):
 
-        # First, we deal with the exceptional RSA KEA call.
+        # First, we deal with the exceptional RSA 'kx export' call.
         if type(key_path) is tuple:
-            e, m, mLen = key_path
             obj = type.__call__(cls)
+            obj.__class__ = PubKeyRSA
             obj.frmt = "tuple"
-            obj.modulus = m
-            obj.modulusLen = mLen
-            obj.pubExp = e
+            obj.import_from_tuple(key_path)
             return obj
 
         # Now for the usual calls, key_path may be the path to either:
@@ -198,11 +195,11 @@ class _PubKeyFactory(_PKIObjMaker):
             pubkey = spki.subjectPublicKey
             if isinstance(pubkey, RSAPublicKey):
                 obj.__class__ = PubKeyRSA
-                obj.updateWith(pubkey)
+                obj.import_from_asn1pkt(pubkey)
             elif isinstance(pubkey, ECDSAPublicKey):
                 obj.__class__ = PubKeyECDSA
                 try:
-                    obj.updateWith(spki)
+                    obj.import_from_asn1pkt(obj.der)
                 except ImportError:
                     pass
             else:
@@ -212,7 +209,7 @@ class _PubKeyFactory(_PKIObjMaker):
             try:
                 pubkey = RSAPublicKey(obj.der)
                 obj.__class__ = PubKeyRSA
-                obj.updateWith(pubkey)
+                obj.import_from_asn1pkt(pubkey)
                 marker = "RSA PUBLIC KEY"
             except:
                 # We cannot import an ECDSA public key without curve knowledge
@@ -236,12 +233,7 @@ class PubKey(object):
         sigAlg = tbsCert.signature
         h = hash_by_oid[sigAlg.algorithm.val]
         sigVal = str(cert.signatureValue)
-        sigdec = None
-        if ecdsa_support:
-            sigdec = ecdsa.util.sigdecode_der
-        return self.verify(str(tbsCert), sigVal, h=h,
-                           t='pkcs',
-                           sigdecode=sigdec)
+        return self.verify(str(tbsCert), sigVal, h=h, t='pkcs')
 
 
 class PubKeyRSA(_PKIObj, PubKey, _EncryptAndVerifyRSA):
@@ -250,60 +242,59 @@ class PubKeyRSA(_PKIObj, PubKey, _EncryptAndVerifyRSA):
     Use the 'key' attribute to access original object.
     """
     @crypto_validator
-    def updateWith(self, pubkey):
+    def import_from_tuple(self, tup):
+        # this is rarely used
+        e, m, mLen = tup
+        if isinstance(m, str):
+            self.modulus = pkcs_os2ip(m)
+        else:
+            self.modulus = m
+        self.modulusLen = mLen
+        if isinstance(e, str):
+            self.pubExp = pkcs_os2ip(e)
+        else:
+            self.pubExp = e
+        pubNum = rsa.RSAPublicNumbers(n=self.modulus, e=self.pubExp)
+        self.pubkey = pubNum.public_key(default_backend())
+        self.pem = self.pubkey.public_bytes(
+                        encoding=serialization.Encoding.PEM,
+                        format=serialization.PublicFormat.SubjectPublicKeyInfo)
+        self.der = pem2der(self.pem)
+
+    @crypto_validator
+    def import_from_asn1pkt(self, pubkey):
         self.modulus    = pubkey.modulus.val
         self.modulusLen = len(binrepr(pubkey.modulus.val))
         self.pubExp     = pubkey.publicExponent.val
-        self.key = rsa.RSAPublicNumbers(
-            n=self.modulus,
-            e=self.pubExp
-        ).public_key(default_backend())
+        pubNum = rsa.RSAPublicNumbers(n=self.modulus, e=self.pubExp)
+        self.pubkey = pubNum.public_key(default_backend())
     def encrypt(self, msg, t=None, h=None, mgf=None, L=None):
         # no ECDSA encryption support, hence no ECDSA specific keywords here
         return _EncryptAndVerifyRSA.encrypt(self, msg, t=t, h=h, mgf=mgf, L=L)
     def verify(self, msg, sig, h=None,
-               t=None, mgf=None, sLen=None,
-               sigdecode=None):
+               t=None, mgf=None, sLen=None):
         return _EncryptAndVerifyRSA.verify(self, msg, sig, h=h,
                                            t=t, mgf=mgf, sLen=sLen)
 
 class PubKeyECDSA(_PKIObj, PubKey):
     """
-    Wrapper for ECDSA keys based on VerifyingKey from ecdsa library.
+    Wrapper for ECDSA keys based on the cryptography library.
     Use the 'key' attribute to access original object.
     """
-    @ecdsa_exception
-    def updateWith(self, spki):
-        # For now we use from_der() or from_string() methods,
-        # which do not offer support for compressed points.
-        #XXX Try using the from_public_point() method.
-        try:
-            self.key = ecdsa.VerifyingKey.from_der(str(spki))
-            # from_der() raises an exception on explicit curves
-        except:
-            s = spki.subjectPublicKey.val_readable[1:]
-            p = spki.signatureAlgorithm.parameters
-            c = import_curve(p.fieldID.prime.val,
-                             p.curve.a.val,
-                             p.curve.b.val,
-                             p.base.val,
-                             p.order.val)
-            self.key = ecdsa.VerifyingKey.from_string(s, c)
-    @ecdsa_exception
+    def import_from_asn1pkt(self, pubkey):
+        # XXX does the cryptography lib support explicit curves?
+        # check also for compressed points
+        self.pubkey = serialization.load_der_public_key(pubkey,
+                                                    backend=default_backend())
     def encrypt(self, msg, t=None, h=None, mgf=None, L=None):
-        # python-ecdsa does not support encryption
+        # cryptography lib does not support ECDSA encryption
         raise Exception("No ECDSA encryption support")
-    @ecdsa_exception
     def verify(self, msg, sig, h=None,
-               t=None, mgf=None, sLen=None,
-               sigdecode=None):
-        if sigdecode is None:
-            sigdecode = ecdsa.util.sigdecode_string
-        try:
-            return self.key.verify(sig, msg, hashfunc=mapHashFunc(h),
-                                   sigdecode=sigdecode)
-        except ecdsa.keys.BadSignatureError:
-            return False
+               t=None, mgf=None, sLen=None):
+        # 'sig' should be a DER-encoded signature, as per RFC 3279
+        verifier = self.pubkey.verifier(sig, ec.ECDSA(mapHashFunc(h)))
+        verifier.update(msg)
+        return verifier.verify()
 
 
 ################
@@ -314,7 +305,7 @@ class _PrivKeyFactory(_PKIObjMaker):
     """
     Metaclass for PrivKey creation.
     It casts the appropriate class on the fly, then fills in
-    the appropriate attributes with updateWith() submethod.
+    the appropriate attributes with import_from_asn1pkt() submethod.
     """
     def __call__(cls, key_path):
         """
@@ -351,7 +342,7 @@ class _PrivKeyFactory(_PKIObjMaker):
                     except:
                         raise Exception("Unable to import private key")
         try:
-            obj.updateWith(privkey)
+            obj.import_from_asn1pkt(privkey)
         except ImportError:
             pass
 
@@ -383,17 +374,11 @@ class PrivKey(object):
         to both PrivKeyRSA and PrivKeyECDSA, the sign() methods of the
         subclasses accept any argument, be it from the RSA or ECDSA world,
         and then they keep the ones they're interested in.
-        Here, t will be passed eventually to pkcs1._DecryptAndSignRSA.sign(),
-        while sigencode will be passed to ecdsa.keys.SigningKey.sign().
+        Here, t will be passed eventually to pkcs1._DecryptAndSignRSA.sign().
         """
         sigAlg = tbsCert.signature
         h = h or hash_by_oid[sigAlg.algorithm.val]
-        sigenc = None
-        if ECDSA_SUPPORT:
-            sigenc = ecdsa.util.sigencode_der
-        sigVal = self.sign(str(tbsCert), h=h,
-                           t='pkcs',
-                           sigencode=sigenc)
+        sigVal = self.sign(str(tbsCert), h=h, t='pkcs')
         c = X509_Cert()
         c.tbsCertificate = tbsCert
         c.signatureAlgorithm = sigAlg
@@ -410,13 +395,7 @@ class PrivKey(object):
         sigAlg = tbsCert.signature
         h = hash_by_oid[sigAlg.algorithm.val]
         sigVal = str(cert.signatureValue)
-        if not ecdsa_support:
-            print "No ecdsa support. Signature could not be verified."
-            return False
-        else:
-            return self.verify(str(tbsCert), sigVal, h=h,
-                               t='pkcs',
-                               sigdecode=ecdsa.util.sigdecode_der)
+        return self.verify(str(tbsCert), sigVal, h=h, t='pkcs')
 
 
 class PrivKeyRSA(_PKIObj, PrivKey, _EncryptAndVerifyRSA, _DecryptAndSignRSA):
@@ -425,7 +404,7 @@ class PrivKeyRSA(_PKIObj, PrivKey, _EncryptAndVerifyRSA, _DecryptAndSignRSA):
     Use the 'key' attribute to access original object.
     """
     @crypto_validator
-    def updateWith(self, privkey):
+    def import_from_asn1pkt(self, privkey):
         self.modulus     = privkey.modulus.val
         self.modulusLen  = len(binrepr(privkey.modulus.val))
         self.pubExp      = privkey.publicExponent.val
@@ -440,15 +419,14 @@ class PrivKeyRSA(_PKIObj, PrivKey, _EncryptAndVerifyRSA, _DecryptAndSignRSA):
             dmq1=self.exponent2, iqmp=self.coefficient,
             public_numbers=rsa.RSAPublicNumbers(n=self.modulus, e=self.pubExp),
         ).private_key(default_backend())
+        self.pubkey = self.key.public_key()
     def verify(self, msg, sig, h=None,
-               t=None, mgf=None, sLen=None,
-               sigdecode=None):
+               t=None, mgf=None, sLen=None):
         # Let's copy this from PubKeyRSA instead of adding another baseclass :)
         return _EncryptAndVerifyRSA.verify(self, msg, sig, h=h,
                                            t=t, mgf=mgf, sLen=sLen)
     def sign(self, data, h=None,
-             t=None, mgf=None, sLen=None,
-             k=None, entropy=None, sigencode=None):
+             t=None, mgf=None, sLen=None):
         return _DecryptAndSignRSA.sign(self, data, h=h,
                                        t=t, mgf=mgf, sLen=sLen)
 
@@ -458,25 +436,20 @@ class PrivKeyECDSA(_PKIObj, PrivKey):
     Wrapper for ECDSA keys based on SigningKey from ecdsa library.
     Use the 'key' attribute to access original object.
     """
-    @ecdsa_exception
-    def updateWith(self, privkey):
-        self.privKey = pkcs_os2ip(privkey.privateKey.val)
-        self.key = ecdsa.SigningKey.from_der(str(privkey))
-        self.vkey = self.key.get_verifying_key()
-    @ecdsa_exception
-    def verify(self, msg, sig, h=None,
-               t=None, mgf=None, sLen=None,
-               sigdecode=None):
-        return self.vkey.verify(sig, msg, hashfunc=mapHashFunc(h),
-                                sigdecode=sigdecode)
-    @ecdsa_exception
-    def sign(self, data, h=None,
-             t=None, mgf=None, sLen=None,
-             k=None, entropy=None, sigencode=None):
-        if sigencode is None:
-            sigencode = ecdsa.util.sigencode_string
-        return self.key.sign(data, hashfunc=mapHashFunc(h),
-                             k=k, entropy=entropy, sigencode=sigencode)
+    def import_from_asn1pkt(self, privkey):
+        self.key = serialization.load_der_private_key(str(privkey),
+                                                      None,
+                                                      backend=default_backend())
+        self.pubkey = self.key.public_key()
+    def verify(self, msg, sig, h=None, **kwargs):
+        # 'sig' should be a DER-encoded signature, as per RFC 3279
+        verifier = self.pubkey.verifier(sig, ec.ECDSA(mapHashFunc(h)))
+        verifier.update(msg)
+        return verifier.verify()
+    def sign(self, data, h=None, **kwargs):
+        signer = self.key.signer(ec.ECDSA(mapHashFunc(h)))
+        signer.update(data)
+        return signer.finalize()
 
 
 ################
@@ -496,7 +469,7 @@ class _CertMaker(_PKIObjMaker):
             cert = X509_Cert(obj.der)
         except:
             raise Exception("Unable to import certificate")
-        obj.updateWith(cert)
+        obj.import_from_asn1pkt(cert)
         return obj
 
 
@@ -507,7 +480,7 @@ class Cert(_PKIObj):
     """
     __metaclass__ = _CertMaker
 
-    def updateWith(self, cert):
+    def import_from_asn1pkt(self, cert):
         error_msg = "Unable to import certificate"
 
         self.x509Cert = cert
@@ -591,11 +564,9 @@ class Cert(_PKIObj):
         return self.pubKey.encrypt(msg, t=t, h=h, mgf=mgf, L=L)
 
     def verify(self, msg, sig, h=None,
-               t=None, mgf=None, sLen=None,
-               sigdecode=None):
+               t=None, mgf=None, sLen=None):
         return self.pubKey.verify(msg, sig, h=h,
-                                  t=t, mgf=mgf, sLen=sLen,
-                                  sigdecode=sigdecode)
+                                  t=t, mgf=mgf, sLen=sLen)
 
     def remainingDays(self, now=None):
         """
@@ -698,7 +669,7 @@ class _CRLMaker(_PKIObjMaker):
             crl = X509_CRL(obj.der)
         except:
             raise Exception("Unable to import CRL")
-        obj.updateWith(crl)
+        obj.import_from_asn1pkt(crl)
         return obj
 
 
@@ -709,7 +680,7 @@ class CRL(_PKIObj):
     """
     __metaclass__ = _CRLMaker
 
-    def updateWith(self, crl):
+    def import_from_asn1pkt(self, crl):
         error_msg = "Unable to import CRL"
 
         self.x509CRL = crl
diff --git a/scapy/layers/tls/crypto/all.py b/scapy/layers/tls/crypto/all.py
index 18c1bba54d9de2bbe7240c89de1a8c281075680f..e8192a55dcec9a67aa4c0b027f6fa16a5b40c2c7 100644
--- a/scapy/layers/tls/crypto/all.py
+++ b/scapy/layers/tls/crypto/all.py
@@ -7,7 +7,9 @@
 Aggregate some TLS crypto objects.
 """
 
-from scapy.layers.tls.crypto.ecdh import *
+# XXX This line should be removed once standard FFDH groups have been
+# registered in the cryptography library.
 from scapy.layers.tls.crypto.ffdh import *
+
 from scapy.layers.tls.crypto.suites import *
 
diff --git a/scapy/layers/tls/crypto/camellia.py b/scapy/layers/tls/crypto/camellia.py
deleted file mode 100644
index c9f70a5ccb7b411ab9b270f1a01825fb38a2ce49..0000000000000000000000000000000000000000
--- a/scapy/layers/tls/crypto/camellia.py
+++ /dev/null
@@ -1,376 +0,0 @@
-## This file is part of Scapy
-## Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
-##                     2015, 2016 Maxence Tury
-## This program is published under a GPLv2 license
-
-"""
-Pure Python implementation of Camellia based on RFC 3713.
-"""
-
-# Note: the only rationales for this implementation are that Camellia is
-#       not yet available in python-crypto at the time of writing and
-#       the fact that the module is not expected to be used on huge
-#       volume of traffic, but mainly for TLS handshakes --arno
-
-from scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp, pkcs_os2ip
-
-
-def _left_rot_op(x, xbitlen, bitrot): # left rotation operation, i.e. '<<<'
-    """
-    Performs left rotation operation of 'xbitrot' bit on 'x' of bit length
-    'xbitlen', i.e. if x is taken as 32 bit value, _left_rot_op(x, 32, 12)
-    is basically w <<< 12 in the notation of
-    """
-    bitrot %= xbitlen
-    mask = (1 << xbitlen) - 1
-    x &= mask
-    return ((x << bitrot) |  (x >> (xbitlen - bitrot))) & mask
-
-_MASK8   = 0xff
-_MASK32  = 0xffffffff
-_MASK64  = 0xffffffffffffffff
-_MASK128 = 0xffffffffffffffffffffffffffffffff
-
-_Sigma1 = 0xA09E667F3BCC908B
-_Sigma2 = 0xB67AE8584CAA73B2
-_Sigma3 = 0xC6EF372FE94F82BE
-_Sigma4 = 0x54FF53A5F1D36F1C
-_Sigma5 = 0x10E527FADE682D1D
-_Sigma6 = 0xB05688C2B3E6C1FD
-
-_SBOX1 = [112, 130,  44, 236, 179,  39, 192, 229,
-          228, 133,  87,  53, 234,  12, 174,  65,
-           35, 239, 107, 147,  69,  25, 165,  33,
-          237,  14,  79,  78,  29, 101, 146, 189,
-          134, 184, 175, 143, 124, 235,  31, 206,
-           62,  48, 220,  95,  94, 197,  11,  26,
-          166, 225,  57, 202, 213,  71,  93,  61,
-          217,   1,  90, 214,  81,  86, 108,  77,
-          139,  13, 154, 102, 251, 204, 176,  45,
-          116,  18,  43,  32, 240, 177, 132, 153,
-          223,  76, 203, 194,  52, 126, 118,   5,
-          109, 183, 169,  49, 209,  23,   4, 215,
-           20,  88,  58,  97, 222,  27,  17,  28,
-           50,  15, 156,  22,  83,  24, 242,  34,
-          254,  68, 207, 178, 195, 181, 122, 145,
-           36,   8, 232, 168,  96, 252, 105,  80,
-          170, 208, 160, 125, 161, 137,  98, 151,
-           84,  91,  30, 149, 224, 255, 100, 210,
-           16, 196,   0,  72, 163, 247, 117, 219,
-          138,   3, 230, 218,   9,  63, 221, 148,
-          135,  92, 131,   2, 205,  74, 144,  51,
-          115, 103, 246, 243, 157, 127, 191, 226,
-           82, 155, 216,  38, 200,  55, 198,  59,
-          129, 150, 111,  75,  19, 190,  99,  46,
-          233, 121, 167, 140, 159, 110, 188, 142,
-           41, 245, 249, 182,  47, 253, 180,  89,
-          120, 152,   6, 106, 231,  70, 113, 186,
-          212,  37, 171,  66, 136, 162, 141, 250,
-          114,   7, 185,  85, 248, 238, 172,  10,
-           54,  73,  42, 104,  60,  56, 241, 164,
-           64,  40, 211, 123, 187, 201,  67, 193,
-           21, 227, 173, 244, 119, 199, 128, 158]
-
-_SBOX2 = map(lambda x: _left_rot_op(x,8,1), _SBOX1)
-
-_SBOX3 = map(lambda x: _left_rot_op(x,8,7), _SBOX1)
-
-_SBOX4 = []
-for k in range(len(_SBOX1)):
-    _SBOX4.append(_SBOX1[_left_rot_op(k,8,1)])
-
-def _F(F_IN, KE): # Section 2.4.1 of RFC 3713
-       x  = (F_IN ^ KE) & _MASK64
-       t1 =  x >> 56  & _MASK8
-       t2 = (x >> 48) & _MASK8
-       t3 = (x >> 40) & _MASK8
-       t4 = (x >> 32) & _MASK8
-       t5 = (x >> 24) & _MASK8
-       t6 = (x >> 16) & _MASK8
-       t7 = (x >>  8) & _MASK8
-       t8 =  x        & _MASK8
-       t1 = _SBOX1[t1]
-       t2 = _SBOX2[t2]
-       t3 = _SBOX3[t3]
-       t4 = _SBOX4[t4]
-       t5 = _SBOX2[t5]
-       t6 = _SBOX3[t6]
-       t7 = _SBOX4[t7]
-       t8 = _SBOX1[t8]
-       y1 = t1 ^ t3 ^ t4 ^ t6 ^ t7 ^ t8
-       y2 = t1 ^ t2 ^ t4 ^ t5 ^ t7 ^ t8
-       y3 = t1 ^ t2 ^ t3 ^ t5 ^ t6 ^ t8
-       y4 = t2 ^ t3 ^ t4 ^ t5 ^ t6 ^ t7
-       y5 = t1 ^ t2 ^ t6 ^ t7 ^ t8
-       y6 = t2 ^ t3 ^ t5 ^ t7 ^ t8
-       y7 = t3 ^ t4 ^ t5 ^ t6 ^ t8
-       y8 = t1 ^ t4 ^ t5 ^ t6 ^ t7
-       F_OUT = ((y1 << 56) | (y2 << 48) | (y3 << 40) | (y4 << 32) |
-                (y5 << 24) | (y6 << 16) | (y7 <<  8) | y8)
-       return F_OUT;
-
-
-def _FL(FL_IN, KE): # Section 2.4.2 of RFC 3713
-    x1 = (FL_IN >> 32) & _MASK32
-    x2 = FL_IN & _MASK32
-    k1 = KE >> 32
-    k2 = KE & _MASK32
-    x2 = x2 ^ _left_rot_op((x1 & k1), 32, 1)
-    x1 = x1 ^ (x2 | k2)
-    FL_OUT = (x1 << 32) | x2
-    return FL_OUT
-
-def _FLINV(FLINV_IN, KE): # Section 2.4.3 of RFC 3713
-    y1 = FLINV_IN >> 32
-    y2 = FLINV_IN & _MASK32
-    k1 = KE >> 32
-    k2 = KE & _MASK32
-    y1 = y1 ^ (y2 | k2)
-    y2 = y2 ^ _left_rot_op((y1 & k1), 32, 1)
-    FLINV_OUT = (y1 << 32) | y2
-    return FLINV_OUT
-
-# Key Scheduling Part as described in section 2.2 of RFC 3713
-def _scheduling(K): #eats the key as a 16, 24 or 32 bytes string
-    l = len(K)
-    K = pkcs_os2ip(K)
-
-    if l == 16:
-        KL = K
-        KR = 0
-    elif l == 24:
-        KL = K >> 64
-        KR = ((K & _MASK64) << 64) | ((~(K & _MASK64)) % (_MASK64+1))
-    elif l == 32:
-        KL = K >> 128
-        KR = K & _MASK128
-    else:
-        return None
-
-    D1 = (KL ^ KR) >> 64
-    D2 = (KL ^ KR) & _MASK64
-    D2 = D2 ^ _F(D1, _Sigma1)
-    D1 = D1 ^ _F(D2, _Sigma2)
-    D1 = D1 ^ (KL >> 64)
-    D2 = D2 ^ (KL & _MASK64)
-    D2 = D2 ^ _F(D1, _Sigma3)
-    D1 = D1 ^ _F(D2, _Sigma4)
-    KA = (D1 << 64) | D2
-    D1 = (KA ^ KR) >> 64
-    D2 = (KA ^ KR) & _MASK64
-    D2 = D2 ^ _F(D1, _Sigma5)
-    D1 = D1 ^ _F(D2, _Sigma6)
-
-    if l != 16:
-        KB = (D1 << 64) | D2
-
-    if l == 16:
-        kw1 = _left_rot_op(KL, 128,   0) >> 64
-        kw2 = _left_rot_op(KL, 128,   0) & _MASK64
-        k1  = _left_rot_op(KA, 128,   0) >> 64
-        k2  = _left_rot_op(KA, 128,   0) & _MASK64
-        k3  = _left_rot_op(KL, 128,  15) >> 64
-        k4  = _left_rot_op(KL, 128,  15) & _MASK64
-        k5  = _left_rot_op(KA, 128,  15) >> 64
-        k6  = _left_rot_op(KA, 128,  15) & _MASK64
-        ke1 = _left_rot_op(KA, 128,  30) >> 64
-        ke2 = _left_rot_op(KA, 128,  30) & _MASK64
-        k7  = _left_rot_op(KL, 128,  45) >> 64
-        k8  = _left_rot_op(KL, 128,  45) & _MASK64
-        k9  = _left_rot_op(KA, 128,  45) >> 64
-        k10 = _left_rot_op(KL, 128,  60) & _MASK64
-        k11 = _left_rot_op(KA, 128,  60) >> 64
-        k12 = _left_rot_op(KA, 128,  60) & _MASK64
-        ke3 = _left_rot_op(KL, 128,  77) >> 64
-        ke4 = _left_rot_op(KL, 128,  77) & _MASK64
-        k13 = _left_rot_op(KL, 128,  94) >> 64
-        k14 = _left_rot_op(KL, 128,  94) & _MASK64
-        k15 = _left_rot_op(KA, 128,  94) >> 64
-        k16 = _left_rot_op(KA, 128,  94) & _MASK64
-        k17 = _left_rot_op(KL, 128, 111) >> 64
-        k18 = _left_rot_op(KL, 128, 111) & _MASK64
-        kw3 = _left_rot_op(KA, 128, 111) >> 64
-        kw4 = _left_rot_op(KA, 128, 111) & _MASK64
-        return [ kw1, kw2, kw3, kw4,
-                 k1 ,  k2,  k3,  k4,  k5,  k6,  k7,  k8,  k9,
-                 k10, k11, k12, k13, k14, k15, k16, k17, k18,
-                 ke1, ke2, ke3, ke4 ]
-    else:
-        kw1 = _left_rot_op(KL, 128,   0) >> 64
-        kw2 = _left_rot_op(KL, 128,   0) & _MASK64
-        k1  = _left_rot_op(KB, 128,   0) >> 64
-        k2  = _left_rot_op(KB, 128,   0) & _MASK64
-        k3  = _left_rot_op(KR, 128,  15) >> 64
-        k4  = _left_rot_op(KR, 128,  15) & _MASK64
-        k5  = _left_rot_op(KA, 128,  15) >> 64
-        k6  = _left_rot_op(KA, 128,  15) & _MASK64
-        ke1 = _left_rot_op(KR, 128,  30) >> 64
-        ke2 = _left_rot_op(KR, 128,  30) & _MASK64
-        k7  = _left_rot_op(KB, 128,  30) >> 64
-        k8  = _left_rot_op(KB, 128,  30) & _MASK64
-        k9  = _left_rot_op(KL, 128,  45) >> 64
-        k10 = _left_rot_op(KL, 128,  45) & _MASK64
-        k11 = _left_rot_op(KA, 128,  45) >> 64
-        k12 = _left_rot_op(KA, 128,  45) & _MASK64
-        ke3 = _left_rot_op(KL, 128,  60) >> 64
-        ke4 = _left_rot_op(KL, 128,  60) & _MASK64
-        k13 = _left_rot_op(KR, 128,  60) >> 64
-        k14 = _left_rot_op(KR, 128,  60) & _MASK64
-        k15 = _left_rot_op(KB, 128,  60) >> 64
-        k16 = _left_rot_op(KB, 128,  60) & _MASK64
-        k17 = _left_rot_op(KL, 128,  77) >> 64
-        k18 = _left_rot_op(KL, 128,  77) & _MASK64
-        ke5 = _left_rot_op(KA, 128,  77) >> 64
-        ke6 = _left_rot_op(KA, 128,  77) & _MASK64
-        k19 = _left_rot_op(KR, 128,  94) >> 64
-        k20 = _left_rot_op(KR, 128,  94) & _MASK64
-        k21 = _left_rot_op(KA, 128,  94) >> 64
-        k22 = _left_rot_op(KA, 128,  94) & _MASK64
-        k23 = _left_rot_op(KL, 128, 111) >> 64
-        k24 = _left_rot_op(KL, 128, 111) & _MASK64
-        kw3 = _left_rot_op(KB, 128, 111) >> 64
-        kw4 = _left_rot_op(KB, 128, 111) & _MASK64
-        return [ kw1, kw2, kw3, kw4,
-                 k1 ,  k2,  k3,  k4,  k5,  k6,  k7,  k8,
-                 k9 , k10, k11, k12, k13, k14, k15, k16,
-                 k17, k18, k19, k20, k21, k22, k23, k24,
-                 ke1, ke2, ke3, ke4, ke5, ke6 ]
-
-def _decrypt_encrypt_128(M, K, decrypt=False):
-    M = pkcs_os2ip(M)
-    D1 = M >> 64
-    D2 = M & _MASK64
-
-    l = _scheduling(K)
-    (kw1,kw2,kw3,kw4,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,
-     k11,k12,k13,k14,k15,k16,k17,k18,ke1,ke2,ke3,ke4) = l
-    if decrypt: # Reversing the order of subkeys: See 2.3.3 of RFC 3713
-        tmp = kw1; kw1 = kw3; kw3 = tmp
-        tmp = kw2; kw2 = kw4; kw4 = tmp
-        tmp = k1; k1  = k18; k18 = tmp
-        tmp = k2; k2  = k17; k17 = tmp
-        tmp = k3; k3  = k16; k16 = tmp
-        tmp = k4; k4  = k15; k15 = tmp
-        tmp = k5; k5  = k14; k14 = tmp
-        tmp = k6; k6  = k13; k13 = tmp
-        tmp = k7; k7  = k12; k12 = tmp
-        tmp = k8; k8  = k11; k11 = tmp
-        tmp = k9; k9  = k10; k10 = tmp
-        tmp = ke1; ke1 = ke4; ke4 = tmp
-        tmp = ke2; ke2 = ke3; ke3 = tmp
-
-    D1 = D1 ^ kw1           # Prewhitening
-    D2 = D2 ^ kw2
-    D2 = D2 ^ _F(D1, k1)     # Round 1
-    D1 = D1 ^ _F(D2, k2)     # Round 2
-    D2 = D2 ^ _F(D1, k3)     # Round 3
-    D1 = D1 ^ _F(D2, k4)     # Round 4
-    D2 = D2 ^ _F(D1, k5)     # Round 5
-    D1 = D1 ^ _F(D2, k6)     # Round 6
-    D1 = _FL(D1, ke1)        # FL
-    D2 = _FLINV(D2, ke2)     # FLINV
-    D2 = D2 ^ _F(D1, k7)     # Round 7
-    D1 = D1 ^ _F(D2, k8)     # Round 8
-    D2 = D2 ^ _F(D1, k9)     # Round 9
-    D1 = D1 ^ _F(D2, k10)    # Round 10
-    D2 = D2 ^ _F(D1, k11)    # Round 11
-    D1 = D1 ^ _F(D2, k12)    # Round 12
-    D1 = _FL(D1, ke3)        # FL
-    D2 = _FLINV(D2, ke4)     # FLINV
-    D2 = D2 ^ _F(D1, k13)    # Round 13
-    D1 = D1 ^ _F(D2, k14)    # Round 14
-    D2 = D2 ^ _F(D1, k15)    # Round 15
-    D1 = D1 ^ _F(D2, k16)    # Round 16
-    D2 = D2 ^ _F(D1, k17)    # Round 17
-    D1 = D1 ^ _F(D2, k18)    # Round 18
-    D2 = D2 ^ kw3           # Postwhitening
-    D1 = D1 ^ kw4
-
-    C = (D2 << 64) | D1
-    return pkcs_i2osp(C, 16)
-
-def _decrypt_encrypt_192_256(M, K, decrypt=False):
-    M = pkcs_os2ip(M)
-    D1 = M >> 64
-    D2 = M & _MASK64
-
-    l = _scheduling(K)
-    (kw1,kw2,kw3,kw4,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,
-     k12,k13,k14,k15,k16,k17,k18,k19,k20,k21,k22,k23,
-     k24,ke1,ke2,ke3,ke4,ke5,ke6) = l
-    if decrypt: # Reversing the order of subkeys: See 2.3.3 of RFC 3713
-        tmp = kw1; kw1 = kw3; kw3 = tmp
-        tmp = kw2; kw2 = kw4; kw4 = tmp
-        tmp = k1; k1  = k24; k24 = tmp
-        tmp = k2; k2  = k23; k23 = tmp
-        tmp = k3; k3  = k22; k22 = tmp
-        tmp = k4; k4  = k21; k21 = tmp
-        tmp = k5; k5  = k20; k20 = tmp
-        tmp = k6; k6  = k19; k19 = tmp
-        tmp = k7; k7  = k18; k18 = tmp
-        tmp = k8; k8  = k17; k17 = tmp
-        tmp = k9; k9  = k16; k16 = tmp
-        tmp = k10; k10 = k15; k15 = tmp
-        tmp = k11; k11 = k14; k14 = tmp
-        tmp = k12; k12 = k13; k13 = tmp
-        tmp = ke1; ke1 = ke6; ke6 = tmp
-        tmp = ke2; ke2 = ke5; ke5 = tmp
-        tmp = ke3; ke3 = ke4; ke4 = tmp
-
-    D1 = D1 ^ kw1            # Prewhitening
-    D2 = D2 ^ kw2
-    D2 = D2 ^ _F(D1, k1)     # Round 1
-    D1 = D1 ^ _F(D2, k2)     # Round 2
-    D2 = D2 ^ _F(D1, k3)     # Round 3
-    D1 = D1 ^ _F(D2, k4)     # Round 4
-    D2 = D2 ^ _F(D1, k5)     # Round 5
-    D1 = D1 ^ _F(D2, k6)     # Round 6
-    D1 = _FL   (D1, ke1)     # _FL
-    D2 = _FLINV(D2, ke2)     # _FLINV
-    D2 = D2 ^ _F(D1, k7)     # Round 7
-    D1 = D1 ^ _F(D2, k8)     # Round 8
-    D2 = D2 ^ _F(D1, k9)     # Round 9
-    D1 = D1 ^ _F(D2, k10)    # Round 10
-    D2 = D2 ^ _F(D1, k11)    # Round 11
-    D1 = D1 ^ _F(D2, k12)    # Round 12
-    D1 = _FL   (D1, ke3)     # _FL
-    D2 = _FLINV(D2, ke4)     # _FLINV
-    D2 = D2 ^ _F(D1, k13)    # Round 13
-    D1 = D1 ^ _F(D2, k14)    # Round 14
-    D2 = D2 ^ _F(D1, k15)    # Round 15
-    D1 = D1 ^ _F(D2, k16)    # Round 16
-    D2 = D2 ^ _F(D1, k17)    # Round 17
-    D1 = D1 ^ _F(D2, k18)    # Round 18
-    D1 = _FL   (D1, ke5)     # _FL
-    D2 = _FLINV(D2, ke6)     # _FLINV
-    D2 = D2 ^ _F(D1, k19)    # Round 19
-    D1 = D1 ^ _F(D2, k20)    # Round 20
-    D2 = D2 ^ _F(D1, k21)    # Round 21
-    D1 = D1 ^ _F(D2, k22)    # Round 22
-    D2 = D2 ^ _F(D1, k23)    # Round 23
-    D1 = D1 ^ _F(D2, k24)    # Round 24
-    D2 = D2 ^ kw3            # Postwhitening
-    D1 = D1 ^ kw4
-    C = (D2 << 64) | D1
-
-    return pkcs_i2osp(C, 16)
-
-
-class Camellia(object):
-    def _decrypt_encrypt(self, M, K, dec):
-        if len(M) != 16:
-            raise AttributeError("Camellia has a block size of 128 bits")
-        l = len(K)
-        if l == 16:
-            return _decrypt_encrypt_128(M, K, decrypt=dec)
-        elif l == 24 or l == 32:
-            return _decrypt_encrypt_192_256(M, K, decrypt=dec)
-        else:
-            raise AttributeError("Camellia supports only 128, 192 and 256 bits keys")
-
-    def encrypt(self, M, K):
-        return self._decrypt_encrypt(M, K, False)
-
-    def decrypt(self, C, K):
-        return self._decrypt_encrypt(C, K, True)
-
diff --git a/scapy/layers/tls/crypto/cipher_aead.py b/scapy/layers/tls/crypto/cipher_aead.py
index 7ef30ca6385c2e39d3436218a66718189bc968a4..3b9d84a095bce3b6b1a25cc5d10af8f1e0d78ee6 100644
--- a/scapy/layers/tls/crypto/cipher_aead.py
+++ b/scapy/layers/tls/crypto/cipher_aead.py
@@ -10,20 +10,16 @@ RFC 5288 introduces new ciphersuites for TLS 1.2 which are based on AES in
 Galois/Counter Mode (GCM). RFC 6655 in turn introduces AES_CCM ciphersuites.
 The related AEAD algorithms are defined in RFC 5116.
 
-For now, we use AES.MODE_GCM and AES.MODE_CCM from the pycrypto library.
-Note that, even though they are supported in the last version 2.7a,
-they are not supported by the last commonly packaged version 2.6.
-
-For the installation of pycrypto 2.7a, see doc/scapy/installation.rst
-If you keep pycrypto 2.6, the suites supposed to use the ciphers below
-will be tagged with 'usable' False.
+For now the cryptography library only supports GCM mode.
+Their interface might (and should) be changed in the future.
 """
 
 import struct
 
-from Crypto.Cipher import AES
+from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
+from cryptography.hazmat.backends import default_backend
+from cryptography.exceptions import InvalidTag
 
-from scapy.error import warning
 from scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp, pkcs_os2ip
 from scapy.layers.tls.crypto.ciphers import CipherError
 
@@ -56,25 +52,53 @@ class _AEADCipher(object):
     __metaclass__ = _AEADCipherMetaclass
     type = "aead"
 
-    pc_cls = AES
-    block_size = 16
-    key_len = 16
-
-    salt_len = 4
-    nonce_explicit_len = 8
-    tag_len = 16
-
-    def __init__(self, key=None, salt=None, nonce_explicit_init=None):
+    def __init__(self, key=None, salt=None, nonce_explicit=None):
         """
         'key' and 'salt' are to be provided as strings, whereas the internal
         'nonce_explicit' is an integer (it is simpler for incrementation).
         """
-        self.key = key
-        self.salt = salt
-
-        if type(nonce_explicit_init) is str:
-            nonce_explicit_init = pkcs_os2ip(nonce_explicit_init)
-        self.nonce_explicit = nonce_explicit_init
+        self.ready = {"key":True, "salt":True, "nonce_explicit":True}
+        if key is None:
+            self.ready["key"] = False
+            key = "\0" * self.key_len
+        if salt is None:
+            self.ready["salt"] = False
+            salt = "\0" * self.salt_len
+        if nonce_explicit is None:
+            self.ready["nonce_explicit"] = False
+            nonce_explicit = 0
+
+        if type(nonce_explicit) is str:
+            nonce_explicit = pkcs_os2ip(nonce_explicit)
+
+        # we use super() in order to avoid any deadlock with __setattr__
+        super(_AEADCipher, self).__setattr__("key", key)
+        super(_AEADCipher, self).__setattr__("salt", salt)
+        super(_AEADCipher, self).__setattr__("nonce_explicit", nonce_explicit)
+
+        iv = salt + pkcs_i2osp(nonce_explicit, self.nonce_explicit_len)
+        self._cipher = Cipher(self.pc_cls(key),
+                              self.pc_cls_mode(iv),
+                              backend=default_backend())
+
+    def __setattr__(self, name, val):
+        if name == "key":
+            if self._cipher is not None:
+                self._cipher.algorithm.key = val
+            self.ready["key"] = True
+        elif name == "salt":
+            iv = val + pkcs_i2osp(self.nonce_explicit, self.nonce_explicit_len)
+            if self._cipher is not None:
+                self._cipher.mode._initialization_vector = iv
+            self.ready["salt"] = True
+        elif name == "nonce_explicit":
+            if type(val) is str:
+                val = pkcs_os2ip(val)
+            iv = self.salt + pkcs_i2osp(val, self.nonce_explicit_len)
+            if self._cipher is not None:
+                self._cipher.mode._initialization_vector = iv
+            self.ready["nonce_explicit"] = True
+        super(_AEADCipher, self).__setattr__(name, val)
 
     def _update_nonce(self):
         """
@@ -88,25 +112,27 @@ class _AEADCipher(object):
         Encrypt the data, prepend the explicit part of the nonce,
         and append the computed authentication code.
         Additional data may be authenticated without encryption (as A).
+
+        Note that the cipher's authentication tag must be None when encrypting.
         """
-        if self.pc_cls_mode is None:
-            warning("No AEAD support! Please install pycrypto 2.7a or later.")
-            raise CipherError
+        if False in self.ready.itervalues():
+            raise CipherError, (P, A)
+        self._cipher.mode._tag = None
+        encryptor = self._cipher.encryptor()
+        encryptor.authenticate_additional_data(A)
+        res = encryptor.update(P) + encryptor.finalize()
+        res += encryptor.tag
 
         nonce_explicit = pkcs_i2osp(self.nonce_explicit,
                                     self.nonce_explicit_len)
-        K = self.key
-        N = self.salt + nonce_explicit
-        ciph = self.pc_cls.new(K, self.pc_cls_mode, N, mac_len=self.tag_len)
-        ciph.update(A)
         self._update_nonce()
-        return nonce_explicit + ciph.encrypt(P) + ciph.digest()
+        return nonce_explicit + res
 
     def auth_decrypt(self, A, C, add_length=True):
         """
         Decrypt the data and verify the authentication code (in this order).
         When additional data was authenticated, it has to be passed (as A).
-        If the verification fails, a ValueError is raised. It is the user's
+        If the verification fails, an AEADTagError is raised. It is the user's
         responsibility to catch it if deemed useful. If we lack the key, we
         raise a CipherError which contains the encrypted input.
 
@@ -121,43 +147,48 @@ class _AEADCipher(object):
                                       C[self.nonce_explicit_len:-self.tag_len],
                                       C[-self.tag_len:])
 
-        if self.pc_cls_mode is None:
-            warning("No AEAD support! Please install pycrypto 2.7a or later.")
+        if False in self.ready.itervalues():
             raise CipherError, (nonce_explicit_str, C, mac)
 
-        if self.key is None:
-            raise CipherError, (nonce_explicit_str, C, mac)
+        self.nonce_explicit = pkcs_os2ip(nonce_explicit_str)
+        self._cipher.mode._tag = mac
 
-        K = self.key
-        N = self.salt + nonce_explicit_str
-        ciph = self.pc_cls.new(K, self.pc_cls_mode, N, mac_len=self.tag_len)
+        decryptor = self._cipher.decryptor()
         if add_length:
             A += struct.pack("!H", len(C))
-        ciph.update(A)
-        P = ciph.decrypt(C)
+        decryptor.authenticate_additional_data(A)
+
+        P = decryptor.update(C)
         try:
-            ciph.verify(mac)
-        except ValueError:
+            decryptor.finalize()
+        except InvalidTag:
             raise AEADTagError, (nonce_explicit_str, P, mac)
         return nonce_explicit_str, P, mac
 
 
 class Cipher_AES_128_GCM(_AEADCipher):
-    pc_cls_mode = AES.MODE_GCM if hasattr(AES, "MODE_GCM") else None
+    pc_cls = algorithms.AES
+    pc_cls_mode = modes.GCM
+    block_size = 16
+    key_len = 16
+    salt_len = 4
+    nonce_explicit_len = 8
+    tag_len = 16
 
 class Cipher_AES_256_GCM(Cipher_AES_128_GCM):
     key_len = 32
 
 
-class Cipher_AES_128_CCM(_AEADCipher):
-    pc_cls_mode = AES.MODE_CCM if hasattr(AES, "MODE_CCM") else None
-
-class Cipher_AES_256_CCM(Cipher_AES_128_CCM):
-    key_len = 32
-
-class Cipher_AES_128_CCM_8(Cipher_AES_128_CCM):
-    tag_len = 8
-
-class Cipher_AES_256_CCM_8(Cipher_AES_128_CCM_8):
-    key_len = 32
+# no support for now in the cryptography library
+#class Cipher_AES_128_CCM(_AEADCipher):
+#    pc_cls_mode = modes.CCM
+#
+#class Cipher_AES_256_CCM(Cipher_AES_128_CCM):
+#    key_len = 32
+#
+#class Cipher_AES_128_CCM_8(Cipher_AES_128_CCM):
+#    tag_len = 8
+#
+#class Cipher_AES_256_CCM_8(Cipher_AES_128_CCM_8):
+#    key_len = 32
 
diff --git a/scapy/layers/tls/crypto/cipher_block.py b/scapy/layers/tls/crypto/cipher_block.py
index 6f38ae7988f03977195b1e1fc065659283d59e4f..de750438863f0adb8f3f4f8129c20a9a70351fa9 100644
--- a/scapy/layers/tls/crypto/cipher_block.py
+++ b/scapy/layers/tls/crypto/cipher_block.py
@@ -7,10 +7,10 @@
 Block ciphers.
 """
 
-from Crypto.Cipher import AES, DES3, DES, ARC2
+from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
+from cryptography.hazmat.backends import default_backend
 
 from scapy.utils import strxor
-from scapy.layers.tls.crypto.camellia import Camellia
 from scapy.layers.tls.crypto.ciphers import CipherError
 
 
@@ -36,15 +36,43 @@ class _BlockCipher(object):
     type = "block"
 
     def __init__(self, key=None, iv=None):
-        self.key = key
-        self.iv = iv
+        self.ready = {"key":True, "iv":True}
+        if key is None:
+            self.ready["key"] = False
+            key = "\0" * self.key_len
+        if iv is None or iv == "":
+            self.ready["iv"] = False
+            iv = "\0" * self.block_size
+
+        # we use super() in order to avoid any deadlock with __setattr__
+        super(_BlockCipher, self).__setattr__("key", key)
+        super(_BlockCipher, self).__setattr__("iv", iv)
+
+        self._cipher = Cipher(self.pc_cls(key),
+                              self.pc_cls_mode(iv),
+                              backend=default_backend())
+
+    def __setattr__(self, name, val):
+        if name == "key":
+            if self._cipher is not None:
+                self._cipher.algorithm.key = val
+            self.ready["key"] = True
+        elif name == "iv":
+            if self._cipher is not None:
+                self._cipher.mode._initialization_vector = val
+            self.ready["iv"] = True
+        super(_BlockCipher, self).__setattr__(name, val)
+
 
     def encrypt(self, data):
         """
         Encrypt the data. Also, update the cipher iv. This is needed for SSLv3
         and TLS 1.0. For TLS 1.1/1.2, it is overwritten in TLS.post_build().
         """
-        tmp = self.pc_cls.new(self.key, self.pc_cls_mode, self.iv).encrypt(data)
+        if False in self.ready.itervalues():
+            raise CipherError, data
+        encryptor = self._cipher.encryptor()
+        tmp = encryptor.update(data) + encryptor.finalize()
         self.iv = tmp[-self.block_size:]
         return tmp
 
@@ -54,18 +82,17 @@ class _BlockCipher(object):
         and TLS 1.0. For TLS 1.1/1.2, it is overwritten in TLS.pre_dissect().
         If we lack the key, we raise a CipherError which contains the input.
         """
-        if self.key is None:
+        if False in self.ready.itervalues():
             raise CipherError, data
-        tmp = self.pc_cls.new(self.key, self.pc_cls_mode, self.iv).decrypt(data)
+        decryptor = self._cipher.decryptor()
+        tmp = decryptor.update(data) + decryptor.finalize()
         self.iv = data[-self.block_size:]
         return tmp
 
 
-### Standard AES
-
 class Cipher_AES_128_CBC(_BlockCipher):
-    pc_cls = AES
-    pc_cls_mode = AES.MODE_CBC
+    pc_cls = algorithms.AES
+    pc_cls_mode = modes.CBC
     block_size = 16
     key_len = 16
 
@@ -73,119 +100,58 @@ class Cipher_AES_256_CBC(Cipher_AES_128_CBC):
     key_len = 32
 
 
-### Camellia
-
 class Cipher_CAMELLIA_128_CBC(_BlockCipher):
-    """
-    As Camellia is not supported in pycrypto, we rely on our camellia.py.
-    Don't expect speed, it's more for completeness than anything else.
-    """
-    type = "block"
+    pc_cls = algorithms.Camellia
+    pc_cls_mode = modes.CBC
     block_size = 16
     key_len = 16
 
-    def __init__(self, key=None, iv=None):
-        self.key = key
-        self.iv = iv
-        self.c = Camellia()
-
-    def encrypt(self, data):
-        l = len(data)/16
-        p = 0
-        res = []
-        tmp = self.iv
-        while p != l:
-            tmp = strxor(tmp, data[p*16:(p+1)*16])
-            tmp = self.c.encrypt(tmp, self.key)
-            res.append(tmp)
-            p += 1
-        self.iv = tmp
-        return "".join(res)
-
-    def decrypt(self, data):
-        if self.key is None:
-            raise Exception, data
-        l = len(data)/16
-        p = 0
-        res = []
-        while p != l:
-            s = data[p*16:(p+1)*16]
-            tmp = self.c.decrypt(s, self.key)
-            tmp = strxor(tmp, self.iv)
-            self.iv = s
-            res.append(tmp)
-            p += 1
-        return "".join(res)
-
 class Cipher_CAMELLIA_256_CBC(Cipher_CAMELLIA_128_CBC):
-    name = "CAMELLIA_256_CBC"
     key_len = 32
 
 
 ### Mostly deprecated ciphers
 
-class Cipher_RC2_CBC_40(_BlockCipher): # RFC 2268
-    pc_cls = ARC2
-    pc_cls_mode = ARC2.MODE_CBC
-    block_size = 8
-    key_len = 5
-    expanded_key_len = 16
-
-class Cipher_DES_CBC(_BlockCipher):
-    pc_cls = DES
-    pc_cls_mode = DES.MODE_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_3DES_EDE_CBC(_BlockCipher):
-    pc_cls = DES3
-    pc_cls_mode = DES.MODE_CBC
+    pc_cls = algorithms.TripleDES
+    pc_cls_mode = modes.CBC
     block_size = 8
     key_len = 24
 
+class Cipher_IDEA_CBC(_BlockCipher):
+    pc_cls = algorithms.IDEA
+    pc_cls_mode = modes.CBC
+    block_size = 8
+    key_len = 16
+
+class Cipher_SEED_CBC(_BlockCipher):
+    pc_cls = algorithms.SEED
+    pc_cls_mode = modes.CBC
+    block_size = 16
+    key_len = 16
 
-### IDEA & SEED (XXX no support for now)
-
-# http://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
-# IPR claim on IDEA : http://www.ietf.org/ietf/IPR/ASCOM-IDEA
-# class Cipher_IDEA_CBC(_BlockCipher):
-#     key_len = 16
-#     block_size = 8
-#
-#     def encrypt(self, data):
-#         print "IDEA is unavailable"
-#         return data
-#
-#     def decrypt(self, data):
-#         print "IDEA is unavailable"
-#         return data
-
-# SEED is a symmetric encryption algorithm that was developed by Korea
-# Information Security Agency (KISA) and a group of experts.
-# Specif: http://www.kisa.or.kr/kisa/seed/data/Document_pdf/SEED_Specification_english.pdf
-#         http://tools.ietf.org/rfc/rfc4269.txt
-# RFC 4162 : Addition of SEED Cipher Suites to TLS
-# class Cipher_SEED_CBC(_BlockCipher):
-#     key_len = 16
-#     block_size = 16
-#
-#     def encrypt(self, data):
-#         print "SEED is unavailable"
-#         return data
-#
-#     def decrypt(self, data):
-#         print "SEED is unavailable"
-#         return data
+#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
+#    block_size = 8
+#    key_len = 5
+#    expanded_key_len = 16
 
diff --git a/scapy/layers/tls/crypto/cipher_stream.py b/scapy/layers/tls/crypto/cipher_stream.py
index 0c05e2dd3d5db703a858e999356da5a1a95c8aea..7a403f3cad91da287bf25d508c16249533e125cc 100644
--- a/scapy/layers/tls/crypto/cipher_stream.py
+++ b/scapy/layers/tls/crypto/cipher_stream.py
@@ -7,7 +7,8 @@
 Stream ciphers.
 """
 
-from Crypto.Cipher import ARC4
+from cryptography.hazmat.primitives.ciphers import Cipher, algorithms
+from cryptography.hazmat.backends import default_backend
 
 from scapy.layers.tls.crypto.ciphers import CipherError
 
@@ -33,41 +34,65 @@ class _StreamCipher(object):
     __metaclass__ = _StreamCipherMetaclass
     type = "stream"
 
-
-class Cipher_NULL(_StreamCipher):
-    key_len = 0
-    expanded_key_len = 0
-
     def __init__(self, key=None):
-        self.key = key
+        """
+        Note that we have to keep the encryption/decryption state in unique
+        encryptor and decryptor objects. This differs from _BlockCipher.
+        """
+        self.ready = {"key":True}
+        if key is None:
+            self.ready["key"] = False
+            key = "\0" * self.key_len
+
+        # we use super() in order to avoid any deadlock with __setattr__
+        super(_StreamCipher, self).__setattr__("key", key)
+
+        self._cipher = Cipher(self.pc_cls(key),
+                              mode=None,
+                              backend=default_backend())
+        self.encryptor = self._cipher.encryptor()
+        self.decryptor = self._cipher.decryptor()
+
+    def __setattr__(self, name, val):
+        if name == "key":
+            if self._cipher is not None:
+                self._cipher.algorithm.key = val
+            self.ready["key"] = True
+        super(_StreamCipher, self).__setattr__(name, val)
 
     def encrypt(self, data):
-        return data
+        if False in self.ready.itervalues():
+            raise CipherError, data
+        return self.encryptor.update(data)
 
     def decrypt(self, data):
-        return data
+        if False in self.ready.itervalues():
+            raise CipherError, data
+        return self.decryptor.update(data)
+
 
 class Cipher_RC4_40(_StreamCipher):
+    pc_cls = algorithms.ARC4
     key_len = 5
     expanded_key_len = 16
 
-    def __init__(self, key=None):
-        self.alg_state = None
-        self.key = key
+class Cipher_RC4_128(Cipher_RC4_40):
+    key_len = 16
 
-    def __setattr__(self, name, value):
-        super(Cipher_RC4_40, self).__setattr__(name, value)
-        if name == "key" and value is not None:
-            self.alg_state = ARC4.new(value)
+
+class Cipher_NULL(_StreamCipher):
+    key_len = 0
+    expanded_key_len = 0
+
+    def __init__(self, key=None):
+        self.ready = {"key":True}
+        # we use super() in order to avoid any deadlock with __setattr__
+        super(_StreamCipher, self).__setattr__("key", key)
+        self._cipher = None
 
     def encrypt(self, data):
-        return self.alg_state.encrypt(data)
+        return data
 
     def decrypt(self, data):
-        if self.key is None:
-            raise CipherError, data
-        return self.alg_state.decrypt(data)
-
-class Cipher_RC4_128(Cipher_RC4_40):
-    key_len = 16
+        return data
 
diff --git a/scapy/layers/tls/crypto/curves.py b/scapy/layers/tls/crypto/curves.py
index 94f2e3839b1c16978688b67d5efb3d95e5887317..9a1d875e6930631e36693050da797891d431424b 100644
--- a/scapy/layers/tls/crypto/curves.py
+++ b/scapy/layers/tls/crypto/curves.py
@@ -8,410 +8,262 @@ Implicit elliptic curves.
 
 Recommended curve parameters from www.secg.org/SEC2-Ver-1.0.pdf
 and www.ecc-brainpool.org/download/Domain-parameters.pdf
-Note that this module will overwrite curves from python-ecdsa.
-"""
-
-import math
-
-from scapy.utils import long_converter, binrepr
-from scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp, pkcs_os2ip
-
-
-def encode_point(point, point_format=0):
-    """
-    Return a string representation of the Point p, according to point_format.
-    """
-    pLen = len(binrepr(point.curve().p()))
-    x = pkcs_i2osp(point.x(), math.ceil(pLen/8))
-    y = pkcs_i2osp(point.y(), math.ceil(pLen/8))
-    if point_format == 0:
-        frmt = '\x04'
-    elif point_format == 1:
-        frmt = chr(2 + y%2)
-        y = ''
-    else:
-        raise Exception("No support for point_format %d" % point_format)
-    return frmt + x + y
-
-
-ecdsa_support = False
-try:
-    import ecdsa
-    ecdsa_support = True
-except ImportError:
-    import logging
-    log_loading = logging.getLogger("scapy.loading")
-    log_loading.info("Can't import python ecdsa lib. No curves.")
-
 
-if ecdsa_support:
-
-    from ecdsa.ellipticcurve import CurveFp, Point
-    from ecdsa.curves import Curve
-    from ecdsa.numbertheory import square_root_mod_prime
-
-
-    def extract_coordinates(g, curve):
-        """
-        Return the coordinates x and y as integers,
-        regardless of the point format of string g.
-        Second expected parameter is a CurveFp.
-        """
-        p = curve.p()
-        point_format = g[0]
-        point = g[1:]
-        if point_format == '\x04':
-            point_len = len(point)
-            if point_len % 2 != 0:
-                raise Exception("Point length is not even.")
-            x_bytes = point[:point_len>>1]
-            x = pkcs_os2ip(x_bytes) % p
-            y_bytes = point[point_len>>1:]
-            y = pkcs_os2ip(y_bytes) % p
-        elif point_format in ['\x02', '\x03']:
-            x_bytes = point
-            x = pkcs_os2ip(x_bytes) % p
-            # perform the y coordinate computation with self.tls_ec
-            y_square = (x*x*x + curve.a()*x + curve.b()) % p
-            y = square_root_mod_prime(y_square, p)
-            y_parity = ord(point_format) % 2    # \x02 means even, \x03 means odd
-            if y % 2 != y_parity:
-                y = -y % p
-        else:
-            raise Exception("Point starts with %s. This encoding "
-                            "is not recognized." % repr(point_format))
-        if not curve.contains_point(x, y):
-            raise Exception("The point we extracted does not belong on the curve!")
-        return x, y
+This is a ghost file since the shift from 'ecdsa' to 'cryptography' lib.
+Part of the code has been kept, but commented out, in case anyone would like
+to improve ECC support in 'cryptography' (namely for the compressed point
+format and additional curves).
+"""
 
-    def import_curve(p, a, b, g, r, name="dummyName", oid=(1, 3, 132, 0, 0xff)):
-        """
-        Create an ecdsa.curves.Curve from the usual parameters.
-        Arguments may be either octet strings or integers,
-        except g which we expect to be an octet string.
-        """
-        if isinstance(p, str):
-            p = pkcs_os2ip(p)
-        if isinstance(a, str):
-            a = pkcs_os2ip(a)
-        if isinstance(b, str):
-            b = pkcs_os2ip(b)
-        if isinstance(r, str):
-            r = pkcs_os2ip(r)
-        curve = CurveFp(p, a, b)
-        x, y = extract_coordinates(g, curve)
-        generator = Point(curve, x, y, r)
-        return Curve(name, curve, generator, oid)
+#import math
+#
+#from scapy.utils import long_converter, binrepr
+#from scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp, pkcs_os2ip
+#
+#
+#def encode_point(point, point_format=0):
+#    """
+#    Return a string representation of the Point p, according to point_format.
+#    """
+#    pLen = len(binrepr(point.curve().p()))
+#    x = pkcs_i2osp(point.x(), math.ceil(pLen/8))
+#    y = pkcs_i2osp(point.y(), math.ceil(pLen/8))
+#    if point_format == 0:
+#        frmt = '\x04'
+#    elif point_format == 1:
+#        frmt = chr(2 + y%2)
+#        y = ''
+#    else:
+#        raise Exception("No support for point_format %d" % point_format)
+#    return frmt + x + y
+#
+#
+#try:
+#    import ecdsa
+#    ecdsa_support = True
+#except ImportError:
+#    import logging
+#    log_loading = logging.getLogger("scapy.loading")
+#    log_loading.info("Can't import python ecdsa lib. No curves.")
+#
+#
+#if ecdsa_support:
+#
+#    from ecdsa.ellipticcurve import CurveFp, Point
+#    from ecdsa.curves import Curve
+#    from ecdsa.numbertheory import square_root_mod_prime
+#
+#
+#    def extract_coordinates(g, curve):
+#        """
+#        Return the coordinates x and y as integers,
+#        regardless of the point format of string g.
+#        Second expected parameter is a CurveFp.
+#        """
+#        p = curve.p()
+#        point_format = g[0]
+#        point = g[1:]
+#        if point_format == '\x04':
+#            point_len = len(point)
+#            if point_len % 2 != 0:
+#                raise Exception("Point length is not even.")
+#            x_bytes = point[:point_len>>1]
+#            x = pkcs_os2ip(x_bytes) % p
+#            y_bytes = point[point_len>>1:]
+#            y = pkcs_os2ip(y_bytes) % p
+#        elif point_format in ['\x02', '\x03']:
+#            x_bytes = point
+#            x = pkcs_os2ip(x_bytes) % p
+#            # perform the y coordinate computation with self.tls_ec
+#            y_square = (x*x*x + curve.a()*x + curve.b()) % p
+#            y = square_root_mod_prime(y_square, p)
+#            y_parity = ord(point_format) % 2    # \x02 means even, \x03 means odd
+#            if y % 2 != y_parity:
+#                y = -y % p
+#        else:
+#            raise Exception("Point starts with %s. This encoding "
+#                            "is not recognized." % repr(point_format))
+#        if not curve.contains_point(x, y):
+#            raise Exception("The point we extracted does not belong on the curve!")
+#        return x, y
+#
+#    def import_curve(p, a, b, g, r, name="dummyName", oid=(1, 3, 132, 0, 0xff)):
+#        """
+#        Create an ecdsa.curves.Curve from the usual parameters.
+#        Arguments may be either octet strings or integers,
+#        except g which we expect to be an octet string.
+#        """
+#        if isinstance(p, str):
+#            p = pkcs_os2ip(p)
+#        if isinstance(a, str):
+#            a = pkcs_os2ip(a)
+#        if isinstance(b, str):
+#            b = pkcs_os2ip(b)
+#        if isinstance(r, str):
+#            r = pkcs_os2ip(r)
+#        curve = CurveFp(p, a, b)
+#        x, y = extract_coordinates(g, curve)
+#        generator = Point(curve, x, y, r)
+#        return Curve(name, curve, generator, oid)
 
 
     ### Named curves
 
     # We always provide _a as a positive integer.
 
-    _p          = long_converter("""
-                  ffffffff ffffffff ffffffff fffffffe ffffac73""")
-    _a          = 0
-    _b          = 7
-    _Gx         = long_converter("""
-                  3b4c382c e37aa192 a4019e76 3036f4f5 dd4d7ebb""")
-    _Gy         = long_converter("""
-                  938cf935 318fdced 6bc28286 531733c3 f03c4fee""")
-    _r          = long_converter("""01
-                  00000000 00000000 0001b8fa 16dfab9a ca16b6b3""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP160k1   = Curve("SECP160k1", curve, generator,
-                        (1, 3, 132, 0, 9), "secp160k1")
-
-    _p          = long_converter("""
-                  ffffffff ffffffff ffffffff ffffffff 7fffffff""")
-    _a          = -3 % _p
-    _b          = long_converter("""
-                  1c97befc 54bd7a8b 65acf89f 81d4d4ad c565fa45""")
-    _Gx         = long_converter("""
-                  4a96b568 8ef57328 46646989 68c38bb9 13cbfc82""")
-    _Gy         = long_converter("""
-                  23a62855 3168947d 59dcc912 04235137 7ac5fb32""")
-    _r          = long_converter("""01
-                  00000000 00000000 0001f4c8 f927aed3 ca752257""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP160r1   = Curve("SECP160r1", curve, generator,
-                        (1, 3, 132, 0, 8), "secp160r1")
-
-    _p          = long_converter("""
-                  ffffffff ffffffff ffffffff fffffffe ffffac73""")
-    _a          = -3 % _p
-    _b          = long_converter("""
-                  b4e134d3 fb59eb8b ab572749 04664d5a f50388ba""")
-    _Gx         = long_converter("""
-                  52dcb034 293a117e 1f4ff11b 30f7199d 3144ce6d""")
-    _Gy         = long_converter("""
-                  feaffef2 e331f296 e071fa0d f9982cfe a7d43f2e""")
-    _r          = long_converter("""01
-                  00000000 00000000 0000351e e786a818 f3a1a16b""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP160r2   = Curve("SECP160r2", curve, generator,
-                        (1, 3, 132, 0, 30), "secp160r2")
-
-    _p          = long_converter("""
-                  ffffffff ffffffff ffffffff ffffffff fffffffe ffffee37""")
-    _a          = 0
-    _b          = 3
-    _Gx         = long_converter("""
-                  db4ff10e c057e9ae 26b07d02 80b7f434 1da5d1b1 eae06c7d""")
-    _Gy         = long_converter("""
-                  9b2f2f6d 9c5628a7 844163d0 15be8634 4082aa88 d95e2f9d""")
-    _r          = long_converter("""
-                  ffffffff ffffffff fffffffe 26f2fc17 0f69466a 74defd8d""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP192k1   = Curve("SECP192k1", curve, generator,
-                        (1, 3, 132, 0, 31), "secp192k1")
-
-    _p          = long_converter("""
-                  ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff""")
-    _a          = -3 % _p
-    _b          = long_converter("""
-                  64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1""")
-    _Gx         = long_converter("""
-                  188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012""")
-    _Gy         = long_converter("""
-                  07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811""")
-    _r          = long_converter("""
-                  ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP192r1   = Curve("SECP192r1", curve, generator,
-                        (1, 2, 840, 10045, 3, 1, 1), "prime192v1")
-
-    _p          = long_converter("""
-                  ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe
-                  ffffe56d""")
-    _a          = 0
-    _b          = 5
-    _Gx         = long_converter("""
-                  a1455b33 4df099df 30fc28a1 69a467e9 e47075a9 0f7e650e
-                  b6b7a45c""")
-    _Gy         = long_converter("""
-                  7e089fed 7fba3442 82cafbd6 f7e319f7 c0b0bd59 e2ca4bdb
-                  556d61a5""")
-    _r          = long_converter("""01
-                  00000000 00000000 00000000 0001dce8 d2ec6184 caf0a971
-                  769fb1f7""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP224k1   = Curve("SECP224k1", curve, generator,
-                        (1, 3, 132, 0, 32), "secp224k1")
-
-    _p          = long_converter("""
-                  ffffffff ffffffff ffffffff ffffffff 00000000 00000000
-                  00000001""")
-    _a          = -3 % _p
-    _b          = long_converter("""
-                  b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943
-                  2355ffb4""")
-    _Gx         = long_converter("""
-                  b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6
-                  115c1d21""")
-    _Gy         = long_converter("""
-                  bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199
-                  85007e34""")
-    _r          = long_converter("""
-                  ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945
-                  5c5c2a3d""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP224r1   = Curve("SECP224r1", curve, generator,
-                        (1, 3, 132, 0, 33), "secp224r1")
-
-    # (already defined as SECP256k1 by python-ecdsa)
-    _p          = long_converter("""
-                  ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
-                  fffffffe fffffc2f""")
-    _a          = 0
-    _b          = 7
-    _Gx         = long_converter("""
-                  79be667e f9dcbbac 55a06295 ce870b07 029bfcdb 2dce28d9
-                  59f2815b 16f81798""")
-    _Gy         = long_converter("""
-                  483ada77 26a3c465 5da4fbfc 0e1108a8 fd17b448 a6855419
-                  9c47d08f fb10d4b8""")
-    _r          = long_converter("""
-                  ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b
-                  bfd25e8c d0364141""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP256k1   = Curve("SECP256k1", curve, generator,
-                        (1, 3, 132, 0, 10), "secp256k1")
-
-    _p          = long_converter("""
-                  ffffffff 00000001 00000000 00000000 00000000 ffffffff
-                  ffffffff ffffffff""")
-    _a          = -3 % _p
-    _b          = long_converter("""
-                  5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6
-                  3bce3c3e 27d2604b""")
-    _Gx         = long_converter("""
-                  6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0
-                  f4a13945 d898c296""")
-    _Gy         = long_converter("""
-                  4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece
-                  cbb64068 37bf51f5""")
-    _r          = long_converter("""
-                  ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84
-                  f3b9cac2 fc632551""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP256r1   = Curve("SECP256r1", curve, generator,
-                        (1, 2, 840, 10045, 3, 1, 7), "prime256v1")
-
-    _p          = long_converter("""
-                  ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
-                  ffffffff fffffffe ffffffff 00000000 00000000 ffffffff""")
-    _a          = -3 % _p
-    _b          = long_converter("""
-                  b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112
-                  0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef""")
-    _Gx         = long_converter("""
-                  aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98
-                  59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7""")
-    _Gy         = long_converter("""
-                  3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c
-                  e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f""")
-    _r          = long_converter("""
-                  ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
-                  c7634d81 f4372ddf 581a0db2 48b0a77a ecec196a ccc52973""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP384r1   = Curve("SECP384r1", curve, generator,
-                        (1, 3, 132, 0, 34), "secp384r1")
-
-    _p          = long_converter("""
-                      01ff ffffffff ffffffff ffffffff ffffffff ffffffff
-                  ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
-                  ffffffff ffffffff ffffffff ffffffff ffffffff""")
-    _a          = -3 % _p
-    _b          = long_converter("""
-                      0051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b
-                  99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd
-                  3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00""")
-    _Gx         = long_converter("""
-                      00c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139
-                  053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127
-                  a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66""")
-    _Gy         = long_converter("""
-                      0118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449
-                  579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901
-                  3fad0761 353c7086 a272c240 88be9476 9fd16650""")
-    _r          = long_converter("""
-                      01ff ffffffff ffffffff ffffffff ffffffff ffffffff
-                  ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148
-                  f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    SECP521r1   = Curve("SECP521r1", curve, generator,
-                        (1, 3, 132, 0, 35), "secp521r1")
-
-    _p          = long_converter("""
-                  A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028
-                  2013481D 1F6E5377""")
-    _a          = long_converter("""
-                  7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C
-                  E94A4B44 F330B5D9""")
-    _b          = long_converter("""
-                  26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE
-                  6BCCDC18 FF8C07B6""")
-    _Gx         = long_converter("""
-                  8BD2AEB9 CB7E57CB 2C4B482F FC81B7AF B9DE27E1 E3BD23C2
-                  3A4453BD 9ACE3262""")
-    _Gy         = long_converter("""
-                  547EF835 C3DAC4FD 97F8461A 14611DC9 C2774513 2DED8E54
-                  5C1D54C7 2F046997""")
-    _r          = long_converter("""
-                  A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7
-                  901E0E82 974856A7""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    BRNP256r1   = Curve("BRNP256r1", curve, generator,
-                        (1, 3, 36, 3, 3, 2, 8, 1, 1, 7), "brainpoolP256r1")
-
-    _p          = long_converter("""
-                  8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4
-                  12B1DA19 7FB71123 ACD3A729 901D1A71 87470013 3107EC53""")
-    _a          = long_converter("""
-                  7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787
-                  139165EF BA91F90F 8AA5814A 503AD4EB 04A8C7DD 22CE2826""")
-    _b          = long_converter("""
-                  04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6
-                  2E880EA5 3EEB62D5 7CB43902 95DBC994 3AB78696 FA504C11""")
-    _Gx         = long_converter("""
-                  1D1C64F0 68CF45FF A2A63A81 B7C13F6B 8847A3E7 7EF14FE3
-                  DB7FCAFE 0CBD10E8 E826E034 36D646AA EF87B2E2 47D4AF1E""")
-    _Gy         = long_converter("""
-                  8ABE1D75 20F9C2A4 5CB1EB8E 95CFD552 62B70B29 FEEC5864
-                  E19C054F F9912928 0E464621 77918111 42820341 263C5315""")
-    _r          = long_converter("""
-                  8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3
-                  1F166E6C AC0425A7 CF3AB6AF 6B7FC310 3B883202 E9046565""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    BRNP384r1   = Curve("BRNP384r1", curve, generator,
-                        (1, 3, 36, 3, 3, 2, 8, 1, 1, 11), "brainpoolP384r1")
-
-    _p          = long_converter("""
-                  AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E
-                  D6639CCA 70330871 7D4D9B00 9BC66842 AECDA12A E6A380E6
-                  2881FF2F 2D82C685 28AA6056 583A48F3""")
-    _a          = long_converter("""
-                  7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610
-                  A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5
-                  7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA""")
-    _b          = long_converter("""
-                  3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9
-                  8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA DC083E67
-                  984050B7 5EBAE5DD 2809BD63 8016F723""")
-    _Gx         = long_converter("""
-                  81AEE4BD D82ED964 5A21322E 9C4C6A93 85ED9F70 B5D916C1
-                  B43B62EE F4D0098E FF3B1F78 E2D0D48D 50D1687B 93B97D5F
-                  7C6D5047 406A5E68 8B352209 BCB9F822""")
-    _Gy         = long_converter("""
-                  7DDE385D 566332EC C0EABFA9 CF7822FD F209F700 24A57B1A
-                  A000C55B 881F8111 B2DCDE49 4A5F485E 5BCA4BD8 8A2763AE
-                  D1CA2B2F A8F05406 78CD1E0F 3AD80892""")
-    _r          = long_converter("""
-                  AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E
-                  D6639CCA 70330870 553E5C41 4CA92619 41866119 7FAC1047
-                  1DB1D381 085DDADD B5879682 9CA90069""")
-    curve       = CurveFp(_p, _a, _b)
-    generator   = Point(curve, _Gx, _Gy, _r)
-    BRNP512r1   = Curve("BRNP512r1", curve, generator,
-                        (1, 3, 36, 3, 3, 2, 8, 1, 1, 13), "brainpoolP512r1")
-
-
-    # IANA identifiers
-    named_curves = { 15: SECP160k1,
-                     16: SECP160r1,
-                     17: SECP160r2,
-                     18: SECP192k1,
-                     19: SECP192r1,
-                     20: SECP224k1,
-                     21: SECP224r1,
-                     22: SECP256k1,
-                     23: SECP256r1,
-                     24: SECP384r1,
-                     25: SECP521r1,
-                     26: BRNP256r1,
-                     27: BRNP384r1,
-                     28: BRNP512r1
-                   }
-
-    for cid, c in named_curves.iteritems():
-        c.curve_id = cid
-
-    # We replace/fill the previous named curves.
-    import ecdsa.curves
-    ecdsa.curves.curves = named_curves.values()
-
+#    _p          = long_converter("""
+#                  ffffffff ffffffff ffffffff fffffffe ffffac73""")
+#    _a          = 0
+#    _b          = 7
+#    _Gx         = long_converter("""
+#                  3b4c382c e37aa192 a4019e76 3036f4f5 dd4d7ebb""")
+#    _Gy         = long_converter("""
+#                  938cf935 318fdced 6bc28286 531733c3 f03c4fee""")
+#    _r          = long_converter("""01
+#                  00000000 00000000 0001b8fa 16dfab9a ca16b6b3""")
+#    curve       = CurveFp(_p, _a, _b)
+#    generator   = Point(curve, _Gx, _Gy, _r)
+#    SECP160k1   = Curve("SECP160k1", curve, generator,
+#                        (1, 3, 132, 0, 9), "secp160k1")
+
+#    _p          = long_converter("""
+#                  ffffffff ffffffff ffffffff ffffffff 7fffffff""")
+#    _a          = -3 % _p
+#    _b          = long_converter("""
+#                  1c97befc 54bd7a8b 65acf89f 81d4d4ad c565fa45""")
+#    _Gx         = long_converter("""
+#                  4a96b568 8ef57328 46646989 68c38bb9 13cbfc82""")
+#    _Gy         = long_converter("""
+#                  23a62855 3168947d 59dcc912 04235137 7ac5fb32""")
+#    _r          = long_converter("""01
+#                  00000000 00000000 0001f4c8 f927aed3 ca752257""")
+#    curve       = CurveFp(_p, _a, _b)
+#    generator   = Point(curve, _Gx, _Gy, _r)
+#    SECP160r1   = Curve("SECP160r1", curve, generator,
+#                        (1, 3, 132, 0, 8), "secp160r1")
+
+#    _p          = long_converter("""
+#                  ffffffff ffffffff ffffffff fffffffe ffffac73""")
+#    _a          = -3 % _p
+#    _b          = long_converter("""
+#                  b4e134d3 fb59eb8b ab572749 04664d5a f50388ba""")
+#    _Gx         = long_converter("""
+#                  52dcb034 293a117e 1f4ff11b 30f7199d 3144ce6d""")
+#    _Gy         = long_converter("""
+#                  feaffef2 e331f296 e071fa0d f9982cfe a7d43f2e""")
+#    _r          = long_converter("""01
+#                  00000000 00000000 0000351e e786a818 f3a1a16b""")
+#    curve       = CurveFp(_p, _a, _b)
+#    generator   = Point(curve, _Gx, _Gy, _r)
+#    SECP160r2   = Curve("SECP160r2", curve, generator,
+#                        (1, 3, 132, 0, 30), "secp160r2")
+
+#    _p          = long_converter("""
+#                  ffffffff ffffffff ffffffff ffffffff fffffffe ffffee37""")
+#    _a          = 0
+#    _b          = 3
+#    _Gx         = long_converter("""
+#                  db4ff10e c057e9ae 26b07d02 80b7f434 1da5d1b1 eae06c7d""")
+#    _Gy         = long_converter("""
+#                  9b2f2f6d 9c5628a7 844163d0 15be8634 4082aa88 d95e2f9d""")
+#    _r          = long_converter("""
+#                  ffffffff ffffffff fffffffe 26f2fc17 0f69466a 74defd8d""")
+#    curve       = CurveFp(_p, _a, _b)
+#    generator   = Point(curve, _Gx, _Gy, _r)
+#    SECP192k1   = Curve("SECP192k1", curve, generator,
+#                        (1, 3, 132, 0, 31), "secp192k1")
+
+#    _p          = long_converter("""
+#                  ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe
+#                  ffffe56d""")
+#    _a          = 0
+#    _b          = 5
+#    _Gx         = long_converter("""
+#                  a1455b33 4df099df 30fc28a1 69a467e9 e47075a9 0f7e650e
+#                  b6b7a45c""")
+#    _Gy         = long_converter("""
+#                  7e089fed 7fba3442 82cafbd6 f7e319f7 c0b0bd59 e2ca4bdb
+#                  556d61a5""")
+#    _r          = long_converter("""01
+#                  00000000 00000000 00000000 0001dce8 d2ec6184 caf0a971
+#                  769fb1f7""")
+#    curve       = CurveFp(_p, _a, _b)
+#    generator   = Point(curve, _Gx, _Gy, _r)
+#    SECP224k1   = Curve("SECP224k1", curve, generator,
+#                        (1, 3, 132, 0, 32), "secp224k1")
+
+#    _p          = long_converter("""
+#                  A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028
+#                  2013481D 1F6E5377""")
+#    _a          = long_converter("""
+#                  7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C
+#                  E94A4B44 F330B5D9""")
+#    _b          = long_converter("""
+#                  26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE
+#                  6BCCDC18 FF8C07B6""")
+#    _Gx         = long_converter("""
+#                  8BD2AEB9 CB7E57CB 2C4B482F FC81B7AF B9DE27E1 E3BD23C2
+#                  3A4453BD 9ACE3262""")
+#    _Gy         = long_converter("""
+#                  547EF835 C3DAC4FD 97F8461A 14611DC9 C2774513 2DED8E54
+#                  5C1D54C7 2F046997""")
+#    _r          = long_converter("""
+#                  A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7
+#                  901E0E82 974856A7""")
+#    curve       = CurveFp(_p, _a, _b)
+#    generator   = Point(curve, _Gx, _Gy, _r)
+#    BRNP256r1   = Curve("BRNP256r1", curve, generator,
+#                        (1, 3, 36, 3, 3, 2, 8, 1, 1, 7), "brainpoolP256r1")
+
+#    _p          = long_converter("""
+#                  8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4
+#                  12B1DA19 7FB71123 ACD3A729 901D1A71 87470013 3107EC53""")
+#    _a          = long_converter("""
+#                  7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787
+#                  139165EF BA91F90F 8AA5814A 503AD4EB 04A8C7DD 22CE2826""")
+#    _b          = long_converter("""
+#                  04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6
+#                  2E880EA5 3EEB62D5 7CB43902 95DBC994 3AB78696 FA504C11""")
+#    _Gx         = long_converter("""
+#                  1D1C64F0 68CF45FF A2A63A81 B7C13F6B 8847A3E7 7EF14FE3
+#                  DB7FCAFE 0CBD10E8 E826E034 36D646AA EF87B2E2 47D4AF1E""")
+#    _Gy         = long_converter("""
+#                  8ABE1D75 20F9C2A4 5CB1EB8E 95CFD552 62B70B29 FEEC5864
+#                  E19C054F F9912928 0E464621 77918111 42820341 263C5315""")
+#    _r          = long_converter("""
+#                  8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3
+#                  1F166E6C AC0425A7 CF3AB6AF 6B7FC310 3B883202 E9046565""")
+#    curve       = CurveFp(_p, _a, _b)
+#    generator   = Point(curve, _Gx, _Gy, _r)
+#    BRNP384r1   = Curve("BRNP384r1", curve, generator,
+#                        (1, 3, 36, 3, 3, 2, 8, 1, 1, 11), "brainpoolP384r1")
+
+#    _p          = long_converter("""
+#                  AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E
+#                  D6639CCA 70330871 7D4D9B00 9BC66842 AECDA12A E6A380E6
+#                  2881FF2F 2D82C685 28AA6056 583A48F3""")
+#    _a          = long_converter("""
+#                  7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610
+#                  A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5
+#                  7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA""")
+#    _b          = long_converter("""
+#                  3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9
+#                  8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA DC083E67
+#                  984050B7 5EBAE5DD 2809BD63 8016F723""")
+#    _Gx         = long_converter("""
+#                  81AEE4BD D82ED964 5A21322E 9C4C6A93 85ED9F70 B5D916C1
+#                  B43B62EE F4D0098E FF3B1F78 E2D0D48D 50D1687B 93B97D5F
+#                  7C6D5047 406A5E68 8B352209 BCB9F822""")
+#    _Gy         = long_converter("""
+#                  7DDE385D 566332EC C0EABFA9 CF7822FD F209F700 24A57B1A
+#                  A000C55B 881F8111 B2DCDE49 4A5F485E 5BCA4BD8 8A2763AE
+#                  D1CA2B2F A8F05406 78CD1E0F 3AD80892""")
+#    _r          = long_converter("""
+#                  AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E
+#                  D6639CCA 70330870 553E5C41 4CA92619 41866119 7FAC1047
+#                  1DB1D381 085DDADD B5879682 9CA90069""")
+#    curve       = CurveFp(_p, _a, _b)
+#    generator   = Point(curve, _Gx, _Gy, _r)
+#    BRNP512r1   = Curve("BRNP512r1", curve, generator,
+#                        (1, 3, 36, 3, 3, 2, 8, 1, 1, 13), "brainpoolP512r1")
 
diff --git a/scapy/layers/tls/crypto/ecdh.py b/scapy/layers/tls/crypto/ecdh.py
deleted file mode 100644
index 56765ca79e405e6e92bb22a5feb0aa888cd54b5b..0000000000000000000000000000000000000000
--- a/scapy/layers/tls/crypto/ecdh.py
+++ /dev/null
@@ -1,181 +0,0 @@
-## This file is part of Scapy
-## Copyright (C) 2016 Pascal Delaunay, Maxence Tury
-## This program is published under a GPLv2 license
-
-"""
-Primitive Elliptic Curve Diffie-Hellman module.
-"""
-
-ecdsa_support = False
-try:
-    import ecdsa
-    ecdsa_support = True
-except ImportError:
-    import logging
-    log_loading = logging.getLogger("scapy.loading")
-    log_loading.info("Can't import python ecdsa lib. No ECDH.")
-
-
-if ecdsa_support:
-
-    import random
-
-    from scapy.layers.tls.crypto.curves import (Point,
-                                                named_curves,
-                                                import_curve,
-                                                encode_point,
-                                                extract_coordinates)
-    from scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp
-
-
-    class ECParams(object):
-        def __init__(self, curve_type):
-            """
-            RFC 3279: ec_type = 1 for prime-fields
-                              = 2 for char-two-fields (no real support for now)
-            As to self.curve, it stores an ecdsa.curves.Curve.
-            """
-            self.ec_type = None
-            self.curve = None
-
-        def set_named_curve(self, curve_tls_id):
-            """
-            Identify and store the named curve we're working with.
-            We always set self.ec_type to 1 because, for now at least,
-            there are no char2 curves among the named_curves.
-            """
-            if curve_tls_id not in named_curves:
-                raise Exception("Unsupported named curve id %d" % curve_tls_id)
-            self.curve = named_curves[curve_tls_id]
-            self.ec_type = 1
-
-        def set_explicit_char2_curve(self, basetype, base, a, b, g, r):
-            self.ec_type = 2
-            raise Exception("No char2 support for now")
-
-        def set_explicit_prime_curve(self, p, a, b, g, r):
-            """
-            Create and store the explicit curve we're working with.
-            """
-            self.ec_type = 1
-            self.curve = import_curve(p, a, b, g, r)
-
-
-    class ECDHParams(object):
-        """
-        Elliptic Curve Diffie-Hellman parameters.
-        Holds an instance of ECParams and some attributes of the DH algorithm.
-        These are used in ServerECDH*Params for the TLS key exchange.
-
-        self.priv is an integer. Its value may remain unknown.
-
-        self.pub and self.other_pub values (the public value we generated and the
-        one we received) are encoded as octet strings according to point_format.
-
-        self.secret is the shared secret, also encoded as an octet string.
-
-        Default ec_parameters relate to the SECP256r1 curve.
-        """
-        def __init__(self, ec_parameters=None, point_format=0):
-            """
-            RFC 4492: point_format = 0 for uncompressed
-                                   = 1 for compressed_prime
-                                   = 2 for compressed_char2
-            """
-            if ec_parameters is None:
-                ec_parameters = ECParams(1)
-                ec_parameters.set_named_curve(23)
-            self.ec_parameters = ec_parameters
-
-            if point_format not in [0, 1]:
-                if point_format == 2:
-                    raise Exception("No support for ansiX962_compressed_char2")
-                else:
-                    raise Exception("Unknown point format")
-            self.point_format   = point_format
-
-            self.priv           = None
-            self.pub            = None
-            self.other_pub      = None
-            self.secret         = None
-
-        def gen_public_params(self):
-            """
-            Generate ECDH public parameter, by choosing a random private value
-            in ] 0, self.ec_parameters.generator.order() [ and then multiplying
-            the generator of the group self.ec_parameters.base with the
-            private value. The public point is returned as a bitstring.
-            The private parameter is internally available for further
-            secret generation (using .gen_secret()).
-
-            Note that 'secret', 'secret_point', 'other_pub' and 'other_pub_point'
-            attributes of the instance are reset by the call.
-            """
-            self.other_pub      = None
-            self.secret         = None
-
-            params = self.ec_parameters
-            if params.ec_type == 1:
-                # Variables, for readability
-                order   = params.curve.order
-                base    = params.curve.generator
-
-                # Ephemeral private key generation : self.priv in [1..order-1]
-                self.priv = random.randint(1, order-1)
-
-                # Scalar multiplication of priv and base point in pub_point
-                pub_point = self.priv * base
-
-                # Encode the public key to be sent according to our point_format
-                self.pub = encode_point(pub_point, point_format=self.point_format)
-            else:
-                raise Exception("No support for ec_type %d" % params.ec_type)
-
-            return self.pub
-
-        def gen_secret(self, other_pub):
-            """
-            Given the peer's public point 'other_pub' as an octet string,
-            the shared secret is computed by multiplying the value with
-            self.priv which was generated with .gen_public_params()
-            """
-            if type(other_pub) is not str:
-                blen = self.ec_parameters.curve.baselen
-                if self.point_format == 1:
-                    other_pub = pkcs_i2osp(other_pub, blen)
-                else:
-                    other_pub = pkcs_i2osp(other_pub, 2*blen+1)
-
-            self.other_pub = other_pub
-
-            z = ""
-            params = self.ec_parameters
-            if params.ec_type == 1:
-                # Get underlying variables for readability
-                ec = params.curve
-                curveFp = ec.curve
-                order = ec.order
-
-                x, y = extract_coordinates(self.other_pub, curveFp)
-
-                # Construct the other_pub_point with integers (mod p) x and y
-                other_pub_point = Point(curveFp, x, y, order)
-
-                # Scalar multiplication with ephemeral private key
-                secret_point = self.priv * other_pub_point
-
-                # Shared secret is x-coordinate of secret_point as an octet string
-                secret_long = secret_point.x()
-
-                # Note that this string never depends on point_format
-                z = pkcs_i2osp(secret_long, ec.baselen)
-                self.secret = z
-            else:
-                raise Exception("No support for ec_type %d" % params.ec_type)
-
-            return z
-
-        def check_params(self):
-            #XXX Do me, maybe
-            pass
-
diff --git a/scapy/layers/tls/crypto/ffdh.py b/scapy/layers/tls/crypto/ffdh.py
index fd250d45391e5c2f97118d21cdc55084b0ebb122..7451c96e52788284fc101ecf1b149038a66d9657 100644
--- a/scapy/layers/tls/crypto/ffdh.py
+++ b/scapy/layers/tls/crypto/ffdh.py
@@ -4,57 +4,15 @@
 ## This program is published under a GPLv2 license
 
 """
-Primitive Finite Field Diffie-Hellman module.
-
-
-We prefer using 'FFDH' rather than 'DH' so as to differentiate it from 'ECDH'.
-
-This module provides:
-
-- a set of modp* classes providing verified DH groups parameters
-  (generator, modulus, modulus length). They are extracted from various
-  IKE-related RFC (RFC 4306, RFC 3526). Those group parameter classes
-  are keyed by modulus length in dh_params dictionary. For instance,
-  to get access to 1024 bits modulus length DH parameters, you can simply
-  do dh_params[1024]
-
-- a function dh_import_params() that converts PKCS#3-encoded DH parameters
-  into a 3-tuple (g, m, mLen). The PKCS#3-encoded parameters can be
-  provided in PEM or DER format, directly or by providing a filename.
-  The function directly reuses openssl command line utility
-
-- a FFDHParams() class, which should be instantiated with some group
-  parameters and provide access to methods for generating DH public values
-  and DH shared secret
-
-------- Example of use:
-
-In this example, we will use internally available group params
-
-a = ffdh_params[2048]              # get 2048 bit modulus FFDH group params
-p = FFDHParams(a.g, a.m, a.mLen)   # instantiate our params
-myPub = p.gen_public_params()      # generate public params (private part
-                                   # is stored internally)
-
-   --> send myPub to the peer
-  <--  get other_pub from the peer
-
-z = p.gen_secret(other_pub)        # Compute shared secret from peer's
-                                   # public value.
-
-This implementation is based on information provided by RSA Data Security
-PKCS#3 document available from their FTP site at the following address:
-
-       ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-3.asc
+This is a register for DH groups from RFC 3526 and RFC 4306.
+XXX These groups (and the ones from RFC 7919) should be registered to
+the cryptography library. And this file should eventually be removed.
 """
 
-
-import popen2
-import random
-import struct
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives.asymmetric import dh
 
 from scapy.utils import long_converter
-from scapy.layers.tls.crypto.pkcs1 import pkcs_os2ip, pkcs_i2osp
 
 
 class modp768: # From RFC 4306
@@ -234,99 +192,108 @@ class modp8192: # From RFC 3526
     60C980DD 98EDD3DF FFFFFFFF FFFFFFFF""")
     mLen = 8192
 
-ffdh_params = {   768: modp768 ,
-                 1024: modp1024,
-                 1536: modp1536,
-                 2048: modp2048,
-                 3072: modp3072,
-                 4096: modp4096,
-                 6144: modp6144,
-                 8192: modp8192  }
-
-
-class FFDHParams(object):
-    """
-    Finite-Field Diffie-Hellman parameters.
-    self.priv is an integer. Its value may remain unknown.
-    self.pub, self.other_pub, and finally self.secret, are also integers.
-    Default group parameters relate to the 2048-bit group from RFC 3526.
-    """
-    def __init__(self, g=ffdh_params[2048].g,
-                       m=ffdh_params[2048].m,
-                       mLen=ffdh_params[2048].mLen):
-        """
-           g: group (2, 5, ...). Can be provided as a string or long.
-           m: prime modulus. Can be provided as a string or long.
-        mLen: prime modulus length in bits.
-        """
-        if type(g) is str:
-            g = pkcs_os2ip(g)
-        if type(m) is str:
-            m = pkcs_os2ip(m)
-
-        self.g = long(g)
-        self.m = long(m)
-        self.mLen = mLen
-
-        self.priv       = None
-        self.pub        = None
-        self.other_pub  = None
-        self.secret     = None
-
-    def gen_public_params(self):
-        """
-        Generate FFDH public parameter, by choosing a random private
-        value in ] 0, p-1 [ and then exponentiating the generator of
-        the group with the private value. The public parameter is
-        returned as an octet string. The private parameter is internally
-        available for further secret generation (using .gen_secret()).
-
-        Note that 'secret' and 'other_pub' attribute of the instance
-        are reset by the call.
-        """
-        self.other_pub  = None
-        self.secret     = None
-
-        # Private key generation : 0 < x < p-1
-        x = random.randint(1, self.m-2)
-        self.priv = x
-
-        # Exponentiation
-        y = pow(self.g, self.priv, self.m)
-        self.pub = y
-
-        # Integer-to-octet-string conversion
-        y = pkcs_i2osp(y, self.mLen/8)
-
-        return y
-
-    def gen_secret(self, other_pub):
-        """
-        Given the peer's public value 'other_pub' provided as an octet string,
-        the shared secret is computed by exponentiating the value using
-        internally stored private value (self.priv, generated during
-        public_parameter generation using .gen_public_params()).
-
-        Computed secret is returned as a bitstring and stored internally.
-
-        No specific check is done on 'other_pub' before exponentiation.
-        """
-        if type(other_pub) is str:
-            other_pub = pkcs_os2ip(other_pub)
-
-        # Octet-string-to-integer conversion
-        self.other_pub = other_pub
-
-        # Exponentiation
-        z = pow(other_pub, self.priv, self.m)
-
-        # Integer-to-octet-string conversion
-        z = pkcs_i2osp(z, self.mLen/8)
-        self.secret = z
-
-        return z
-
-    def check_params(self):
-        #XXX Do me, maybe
-        pass
+_ffdh_raw_params = { 'modp768' : modp768,
+                     'modp1024': modp1024,
+                     'modp1536': modp1536,
+                     'modp2048': modp2048,
+                     'modp3072': modp3072,
+                     'modp4096': modp4096,
+                     'modp6144': modp6144,
+                     'modp8192': modp8192  }
+
+FFDH_GROUPS = {}
+for name, group in _ffdh_raw_params.iteritems():
+    pn = dh.DHParameterNumbers(group.m, group.g)
+    params = pn.parameters(default_backend())
+    FFDH_GROUPS[name] = [params, group.mLen]
+
+
+#from scapy.layers.tls.crypto.pkcs1 import pkcs_os2ip, pkcs_i2osp
+#
+#
+#class FFDHParams(object):
+#    """
+#    Finite-Field Diffie-Hellman parameters.
+#    self.priv is an integer. Its value may remain unknown.
+#    self.pub, self.other_pub, and finally self.secret, are also integers.
+#    Default group parameters relate to the 2048-bit group from RFC 3526.
+#    """
+#    def __init__(self, g=ffdh_params[2048].g,
+#                       m=ffdh_params[2048].m,
+#                       mLen=ffdh_params[2048].mLen):
+#        """
+#           g: group (2, 5, ...). Can be provided as a string or long.
+#           m: prime modulus. Can be provided as a string or long.
+#        mLen: prime modulus length in bits.
+#        """
+#        if type(g) is str:
+#            g = pkcs_os2ip(g)
+#        if type(m) is str:
+#            m = pkcs_os2ip(m)
+#
+#        self.g = long(g)
+#        self.m = long(m)
+#        self.mLen = mLen
+#
+#        self.priv       = None
+#        self.pub        = None
+#        self.other_pub  = None
+#        self.secret     = None
+#
+#    def gen_public_params(self):
+#        """
+#        Generate FFDH public parameter, by choosing a random private
+#        value in ] 0, p-1 [ and then exponentiating the generator of
+#        the group with the private value. The public parameter is
+#        returned as an octet string. The private parameter is internally
+#        available for further secret generation (using .gen_secret()).
+#
+#        Note that 'secret' and 'other_pub' attribute of the instance
+#        are reset by the call.
+#        """
+#        self.other_pub  = None
+#        self.secret     = None
+#
+#        # Private key generation : 0 < x < p-1
+#        x = random.randint(1, self.m-2)
+#        self.priv = x
+#
+#        # Exponentiation
+#        y = pow(self.g, self.priv, self.m)
+#        self.pub = y
+#
+#        # Integer-to-octet-string conversion
+#        y = pkcs_i2osp(y, self.mLen/8)
+#
+#        return y
+#
+#    def gen_secret(self, other_pub):
+#        """
+#        Given the peer's public value 'other_pub' provided as an octet string,
+#        the shared secret is computed by exponentiating the value using
+#        internally stored private value (self.priv, generated during
+#        public_parameter generation using .gen_public_params()).
+#
+#        Computed secret is returned as a bitstring and stored internally.
+#
+#        No specific check is done on 'other_pub' before exponentiation.
+#        """
+#        if type(other_pub) is str:
+#            other_pub = pkcs_os2ip(other_pub)
+#
+#        # Octet-string-to-integer conversion
+#        self.other_pub = other_pub
+#
+#        # Exponentiation
+#        z = pow(other_pub, self.priv, self.m)
+#
+#        # Integer-to-octet-string conversion
+#        z = pkcs_i2osp(z, self.mLen/8)
+#        self.secret = z
+#
+#        return z
+#
+#    def check_params(self):
+#        #XXX Do me, maybe
+#        pass
 
diff --git a/scapy/layers/tls/crypto/h_mac.py b/scapy/layers/tls/crypto/h_mac.py
index b399f56232528f2ca4ed3c0769cd7d2cf03edf48..6be3803b9c41b80050d7a2f5561d0415deddf6dd 100644
--- a/scapy/layers/tls/crypto/h_mac.py
+++ b/scapy/layers/tls/crypto/h_mac.py
@@ -12,6 +12,11 @@ import hmac
 from scapy.layers.tls.crypto.hash import tls_hash_algs
 
 
+SSLv3_PAD1_MD5  = "\x36"*48
+SSLv3_PAD1_SHA1 = "\x36"*40
+SSLv3_PAD2_MD5  = "\x5c"*48
+SSLv3_PAD2_SHA1 = "\x5c"*40
+
 tls_hmac_algs = {}
 
 class _GenericHMACMetaclass(type):
@@ -54,6 +59,23 @@ class _GenericHMAC(object):
             raise HMACError
         return hmac.new(self.key, tbd, self.hash_alg.hash_cls).digest()
 
+    def digest_sslv3(self, tbd):
+        if self.key is None:
+            raise HMACError
+
+        h = self.hash_alg()
+        if h.name == "SHA":
+            pad1 = SSLv3_PAD1_SHA1
+            pad2 = SSLv3_PAD2_SHA1
+        elif h.name == "MD5":
+            pad1 = SSLv3_PAD1_MD5
+            pad2 = SSLv3_PAD2_MD5
+        else:
+            raise HMACError("Provided hash does not work with SSLv3.")
+
+        return h.digest(self.key + pad2 +
+                        h.digest(self.key + pad1 + tbd))
+
 
 class Hmac_NULL(_GenericHMAC):
     hmac_len = 0
@@ -62,6 +84,9 @@ class Hmac_NULL(_GenericHMAC):
     def digest(self, tbd):
         return ""
 
+    def digest_sslv3(self, tbd):
+        return ""
+
 class Hmac_MD5(_GenericHMAC):
     pass
 
diff --git a/scapy/layers/tls/crypto/kx_algs.py b/scapy/layers/tls/crypto/kx_algs.py
index 4cf908d256185466151d916864434c5c935397a6..501e22ff1aad865d5a085b1eb8cd8ad507059946 100644
--- a/scapy/layers/tls/crypto/kx_algs.py
+++ b/scapy/layers/tls/crypto/kx_algs.py
@@ -33,6 +33,7 @@ class _GenericKXMetaclass(type):
             the_class.export = kx_name.endswith("_EXPORT")
             the_class.anonymous = "_anon_" in kx_name
             the_class.no_ske = not ("DHE" in kx_name or "_anon_" in kx_name)
+            the_class.no_ske &= not the_class.export
             tls_kx_algs[kx_name[3:]] = the_class
         return the_class
 
diff --git a/scapy/layers/tls/crypto/pkcs1.py b/scapy/layers/tls/crypto/pkcs1.py
index 7e3a64bbff3e209c484645ee1eeb6780b80b81ec..7da7182d30ca4a20c282f25f20b103791470eef7 100644
--- a/scapy/layers/tls/crypto/pkcs1.py
+++ b/scapy/layers/tls/crypto/pkcs1.py
@@ -1,10 +1,14 @@
 ## This file is part of Scapy
-## Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
-##                     2015, 2016 Maxence Tury
+## Copyright (C) 2008 Arnaud Ebalard <arno@natisbad.org>
+##         2015, 2016 Maxence Tury <maxence.tury@ssi.gouv.fr>
 ## This program is published under a GPLv2 license
 
 """
 PKCS #1 methods as defined in RFC 3447.
+
+XXX We cannot rely solely on the cryptography library, because it does not
+support our "tls" hash used with TLS 1.0. Once it is added to (or from) the
+library, most of the present module should be removed.
 """
 
 import os, popen2, tempfile
@@ -72,18 +76,20 @@ def pkcs_ilen(n):
         i += 1
     return i
 
-# for every hash function a tuple is provided, giving access to
+
+#####################################################################
+# Hash functions
+#####################################################################
+
+# For every hash function a tuple is provided, giving access to
 # - hash output length in byte
 # - associated hash function that take data to be hashed as parameter
 #   XXX I do not provide update() at the moment.
 # - DER encoding of the leading bits of digestInfo (the hash value
 #   will be concatenated to create the complete digestInfo).
 #
-# Notes:
-# - MD4 asn.1 value should be verified. Also, as stated in
-#   PKCS#1 v2.1, MD4 should not be used.
-# - 'tls' one is the concatenation of both md5 and sha1 hashes used
-#   by SSL/TLS when signing/verifying things
+# Note that 'tls' is the concatenation of both md5 and sha1 hashes used by
+# SSL/TLS 1.0 when signing/verifying things.
 
 _hashFuncParams = {}
 if conf.crypto_valid:
@@ -124,12 +130,18 @@ if conf.crypto_valid:
         }
 
 def mapHashFunc(hashStr):
+    if hashStr == "tls":
+        raise Exception("mapHashFunc is not supposed to be called on 'tls'")
     try:
-        return _hashFuncParams[hashStr][1]
+        return _hashFuncParams[hashStr][1]()
     except:
         raise Exception("Unknown hash function %s" % hashStr)
 
 
+#####################################################################
+# Some more PKCS helpers
+#####################################################################
+
 def pkcs_mgf1(mgfSeed, maskLen, h):
     """
     Implements generic MGF1 Mask Generation function as described in
@@ -308,165 +320,166 @@ def pkcs_emsa_pkcs1_v1_5_encode(M, emLen, h): # section 9.2 of RFC 3447
     return EM                                                # 6)
 
 
-# XXX should add other pgf1 instance in a better fashion.
+#####################################################################
+# Asymmetric Cryptography wrappers
+#####################################################################
 
-def create_ca_file(anchor_list, filename):
-    """
-    Concatenate all the certificates (PEM format for the export) in
-    'anchor_list' and write the result to file 'filename'. On success
-    'filename' is returned, None otherwise.
+class _EncryptAndVerifyRSA(object):
 
-    If you are used to OpenSSL tools, this function builds a CAfile
-    that can be used for certificate and CRL check.
+    def _rsaep(self, m):
+        """
+        Internal method providing raw RSA encryption, i.e. simple modular
+        exponentiation of the given message representative 'm', a long
+        between 0 and n-1.
 
-    Also see create_temporary_ca_file().
-    """
-    try:
-        f = open(filename, "w")
-        for a in anchor_list:
-            s = a.output(fmt="PEM")
-            f.write(s)
-        f.close()
-    except:
-        return None
-    return filename
+        This is the encryption primitive RSAEP described in PKCS#1 v2.1,
+        i.e. RFC 3447 Sect. 5.1.1.
 
-def create_temporary_ca_file(anchor_list):
-    """
-    Concatenate all the certificates (PEM format for the export) in
-    'anchor_list' and write the result to file to a temporary file
-    using mkstemp() from tempfile module. On success 'filename' is
-    returned, None otherwise.
+        Input:
+           m: message representative, a long between 0 and n-1, where
+              n is the key modulus.
 
-    If you are used to OpenSSL tools, this function builds a CAfile
-    that can be used for certificate and CRL check.
-    """
-    try:
-        f, fname = tempfile.mkstemp()
-        for a in anchor_list:
-            s = a.output(fmt="PEM")
-            l = os.write(f, s)
-        os.close(f)
-    except:
-        return None
-    return fname
+        Output:
+           ciphertext representative, a long between 0 and n-1
 
-def create_temporary_ca_path(anchor_list, folder):
-    """
-    Create a CA path folder as defined in OpenSSL terminology, by
-    storing all certificates in 'anchor_list' list in PEM format
-    under provided 'folder' and then creating the associated links
-    using the hash as usually done by c_rehash.
+        Not intended to be used directly. Please, see encrypt() method.
+        """
 
-    Note that you can also include CRL in 'anchor_list'. In that
-    case, they will also be stored under 'folder' and associated
-    links will be created.
+        n = self.modulus
+        if isinstance(m, int):
+            m = long(m)
+        if (not isinstance(m, long)) or m > n-1:
+            warning("Key._rsaep() expects a long between 0 and n-1")
+            return None
 
-    In folder, the files are created with names of the form
-    0...ZZ.pem. If you provide an empty list, folder will be created
-    if it does not already exist, but that's all.
+        return pow(m, self.pubExp, n)
 
-    The number of certificates written to folder is returned on
-    success, None on error.
-    """
-    # We should probably avoid writing duplicate anchors and also
-    # check if they are all certs.
-    try:
-        if not os.path.isdir(folder):
-            os.makedirs(folder)
-    except:
-        return None
 
-    l = len(anchor_list)
-    if l == 0:
-        return None
-    fmtstr = "%%0%sd.pem" % math.ceil(math.log(l, 10))
-    i = 0
-    try:
-        for a in anchor_list:
-            fname = os.path.join(folder, fmtstr % i)
-            f = open(fname, "w")
-            s = a.output(fmt="PEM")
-            f.write(s)
-            f.close()
-            i += 1
-    except:
-        return None
+    @crypto_validator
+    def encrypt(self, m, t="pkcs", h=None, mgf=None, L=None):
+        if h == "tls" or t is None:
+            #return self.encrypt_legacy(m, t=t, h=h, mgf=mgf, L=L)
+            warning("Cannot call encrypt_legacy anymore.")
+            return None
 
-    r,w=popen2.popen2("c_rehash %s" % folder)
-    r.close(); w.close()
+        if h is not None:
+            h = mapHashFunc(h)
 
-    return l
+        if t == "pkcs":
+            pad = padding.PKCS1v15()
+        elif t == "oaep":
+            pad = padding.OAEP(mgf=mgf(h), algorithm=h, label=L)
+        else:
+            warning("Key.encrypt(): Unknown encryption type (%s) provided" % t)
+            return None
+        return self.pubkey.encrypt(m, pad)
 
 
-#####################################################################
-# Public Key Cryptography related stuff
-#####################################################################
+    ### Below are verification related methods
 
-class _EncryptAndVerifyRSA(object):
-    @crypto_validator
-    def encrypt(self, m, t=None, h=None, mgf=None, L=None):
+    def _rsavp1(self, s):
         """
-        Encrypt message 'm' using 't' encryption scheme where 't' can be:
+        Internal method providing raw RSA verification, i.e. simple modular
+        exponentiation of the given signature representative 'c', an integer
+        between 0 and n-1.
 
-        - None: the message 'm' is directly applied the RSAEP encryption
-                primitive, as described in PKCS#1 v2.1, i.e. RFC 3447
-                Sect 5.1.1. Simply put, the message undergo a modular
-                exponentiation using the public key. Additionnal method
-                parameters are just ignored.
+        This is the signature verification primitive RSAVP1 described in
+        PKCS#1 v2.1, i.e. RFC 3447 Sect. 5.2.2.
 
-        -'pkcs': the message 'm' is applied RSAES-PKCS1-V1_5-ENCRYPT encryption
-                scheme as described in section 7.2.1 of RFC 3447. In that
-                context, other parameters ('h', 'mgf', 'l') are not used.
+        Input:
+          s: signature representative, an integer between 0 and n-1,
+             where n is the key modulus.
 
-        -'oaep': the message 'm' is applied the RSAES-OAEP-ENCRYPT encryption
-                scheme, as described in PKCS#1 v2.1, i.e. RFC 3447 Sect
-                7.1.1. In that context,
+        Output:
+           message representative, an integer between 0 and n-1
 
-                o 'h' parameter provides the name of the hash method to use.
-                  Possible values are "md2", "md4", "md5", "sha1", "tls",
-                  "sha224", "sha256", "sha384" and "sha512". If none is
-                  provided, sha1 is used.
+        Not intended to be used directly. Please, see verify() method.
+        """
+        return self._rsaep(s)
 
-                o 'mgf' is the mask generation function. By default, mgf
-                  is derived from the provided hash function using the
-                  generic MGF1 (see pkcs_mgf1() for details).
-
-                o 'L' is the optional label to be associated with the message.
-                  If not provided, the default value is used, i.e the empty
-                  string. No check is done on the input limitation of the hash
-                  function regarding the size of 'L' (for instance, 2^61 - 1
-                  for SHA-1). You have been warned.
+    def _rsassa_pss_verify(self, M, S, h=None, mgf=None, sLen=None):
         """
-        if h is not None:
-            h = mapHashFunc(h)
-        if t is None: # Raw encryption
-            return self.key.encrypt(
-                m,
-                padding.AsymmetricPadding(),
-            )
-        elif t == "pkcs":
-            return self.key.encrypt(
-                m,
-                padding.PKCS1v15(),
-            )
+        Implements RSASSA-PSS-VERIFY() function described in Sect 8.1.2
+        of RFC 3447
 
-        elif t == "oaep":
-            return self.key.encrypt(
-                m,
-                padding.OAEP(
-                    mgf=mgf(h()),
-                    algorithm=h(),
-                    label=L,
-                ),
-            )
+        Input:
+           M: message whose signature is to be verified
+           S: signature to be verified, an octet string of length k, where k
+              is the length in octets of the RSA modulus n.
 
-        else:
-            warning("Key.encrypt(): Unknown encryption type (%s) provided" % t)
-            return None
+        Output:
+           True is the signature is valid. False otherwise.
+        """
 
-    @crypto_validator
-    def verify(self, M, S, t=None, h=None, mgf=None, sLen=None):
+        # Set default parameters if not provided
+        if h is None: # By default, sha1
+            h = "sha1"
+        if not _hashFuncParams.has_key(h):
+            warning("Key._rsassa_pss_verify(): unknown hash function "
+                    "provided (%s)" % h)
+            return False
+        if mgf is None: # use mgf1 with underlying hash function
+            mgf = lambda x,y: pkcs_mgf1(x, y, h)
+        if sLen is None: # use Hash output length (A.2.3 of RFC 3447)
+            hLen = _hashFuncParams[h][0]
+            sLen = hLen
+
+        # 1) Length checking
+        modBits = self.modulusLen
+        k = modBits / 8
+        if len(S) != k:
+            return False
+
+        # 2) RSA verification
+        s = pkcs_os2ip(S)                           # 2.a)
+        m = self._rsavp1(s)                         # 2.b)
+        emLen = math.ceil((modBits - 1) / 8.)       # 2.c)
+        EM = pkcs_i2osp(m, emLen)
+
+        # 3) EMSA-PSS verification
+        result = pkcs_emsa_pss_verify(M, EM, modBits - 1, h, mgf, sLen)
+
+        return result                               # 4)
+
+
+    def _rsassa_pkcs1_v1_5_verify(self, M, S, h):
+        """
+        Implements RSASSA-PKCS1-v1_5-VERIFY() function as described in
+        Sect. 8.2.2 of RFC 3447.
+
+        Input:
+           M: message whose signature is to be verified, an octet string
+           S: signature to be verified, an octet string of length k, where
+              k is the length in octets of the RSA modulus n
+           h: hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls',
+                'sha256', 'sha384').
+
+        Output:
+           True if the signature is valid. False otherwise.
+        """
+
+        # 1) Length checking
+        k = self.modulusLen / 8
+        if len(S) != k:
+            warning("invalid signature (len(S) != k)")
+            return False
+
+        # 2) RSA verification
+        s = pkcs_os2ip(S)                           # 2.a)
+        m = self._rsavp1(s)                         # 2.b)
+        EM = pkcs_i2osp(m, k)                       # 2.c)
+
+        # 3) EMSA-PKCS1-v1_5 encoding
+        EMPrime = pkcs_emsa_pkcs1_v1_5_encode(M, k, h)
+        if EMPrime is None:
+            warning("Key._rsassa_pkcs1_v1_5_verify(): unable to encode.")
+            return False
+
+        # 4) Comparison
+        return EM == EMPrime
+
+
+    def verify_legacy(self, M, S, t=None, h=None, mgf=None, sLen=None):
         """
         Verify alleged signature 'S' is indeed the signature of message 'M'
         using 't' signature scheme where 't' can be:
@@ -503,33 +516,51 @@ class _EncryptAndVerifyRSA(object):
                   default value (the byte length of the hash value for provided
                   algorithm) by providing another one with that parameter.
         """
-        if h is not None:
-            h = mapHashFunc(h)
-
         if t is None: # RSAVP1
-            pad_inst = padding.AsymmetricPadding()
+            S = pkcs_os2ip(S)
+            n = self.modulus
+            if S > n-1:
+                warning("Signature to be verified is too long for key modulus")
+                return False
+            m = self._rsavp1(S)
+            if m is None:
+                return False
+            l = int(math.ceil(math.log(m, 2) / 8.)) # Hack
+            m = pkcs_i2osp(m, l)
+            return M == m
         elif t == "pkcs": # RSASSA-PKCS1-v1_5-VERIFY
             if h is None:
-                h = hashes.SHA1
-            pad_inst = padding.PKCS1v15()
+                h = "sha1"
+            return self._rsassa_pkcs1_v1_5_verify(M, S, h)
         elif t == "pss": # RSASSA-PSS-VERIFY
-            pad_inst = padding.PSS(mgf=mgf, salt_length=sLen)
+            return self._rsassa_pss_verify(M, S, h, mgf, sLen)
+        else:
+            warning("Key.verify(): Unknown signature type (%s) provided" % t)
+            return None
+
+    @crypto_validator
+    def verify(self, M, S, t="pkcs", h=None, mgf=None, sLen=None):
+        if h == "tls" or t is None:
+            return self.verify_legacy(M, S, t=t, h=h, mgf=mgf, sLen=sLen)
 
+        if h is not None:
+            h = mapHashFunc(h)
+
+        if t == "pkcs": # RSASSA-PKCS1-v1_5-VERIFY
+            pad = padding.PKCS1v15()
+        elif t == "pss": # RSASSA-PSS-VERIFY
+            pad = padding.PSS(mgf=mgf(h), salt_length=sLen)
         else:
             warning("Key.verify(): Unknown signature type (%s) provided" % t)
             return None
 
         try:
-            self.key.verify(
-                signature=S,
-                data=M,
-                padding=pad_inst,
-                algorithm=h(),
-            )
+            self.pubkey.verify(signature=S, data=M, padding=pad, algorithm=h)
             return True
         except InvalidSignature:
             return False
 
+
 class _DecryptAndSignRSA(object):
     ### Below are decryption related methods. Encryption ones are inherited
     ### from PubKey
@@ -557,210 +588,30 @@ class _DecryptAndSignRSA(object):
         if isinstance(c, int):
             c = long(c)
         if (not isinstance(c, long)) or c > n-1:
-            warning("Key._rsadp() expects a long between 0 and n-1")
-            return None
-
-        return self.key.decrypt(c)
-
-
-    def _rsaes_pkcs1_v1_5_decrypt(self, C):
-        """
-        Implements RSAES-PKCS1-V1_5-DECRYPT() function described in section
-        7.2.2 of RFC 3447.
-
-        Input:
-           C: ciphertext to be decrypted, an octet string of length k, where
-              k is the length in octets of the RSA modulus n.
-
-        Output:
-           an octet string of length k at most k - 11
-
-        on error, None is returned.
-        """
-
-        # 1) Length checking
-        cLen = len(C)
-        k = self.modulusLen / 8
-        if cLen != k or k < 11:
-            warning("Key._rsaes_pkcs1_v1_5_decrypt() decryption error "
-                    "(cLen != k or k < 11)")
+            warning("Key._rsaep() expects a long between 0 and n-1")
             return None
 
-        # 2) RSA decryption
-        c = pkcs_os2ip(C)                           # 2.a)
-        m = self._rsadp(c)                          # 2.b)
-        EM = pkcs_i2osp(m, k)                       # 2.c)
-
-        # 3) EME-PKCS1-v1_5 decoding
-
-        # I am aware of the note at the end of 7.2.2 regarding error
-        # conditions reporting but the one provided below are for _local_
-        # debugging purposes. --arno
-
-        if EM[0] != '\x00':
-            warning("Key._rsaes_pkcs1_v1_5_decrypt(): decryption error "
-                    "(first byte is not 0x00)")
-            return None
-
-        if EM[1] != '\x02':
-            warning("Key._rsaes_pkcs1_v1_5_decrypt(): decryption error "
-                    "(second byte is not 0x02)")
-            return None
-
-        tmp = EM[2:].split('\x00', 1)
-        if len(tmp) != 2:
-            warning("Key._rsaes_pkcs1_v1_5_decrypt(): decryption error "
-                    "(no 0x00 to separate PS from M)")
-            return None
-
-        PS, M = tmp
-        if len(PS) < 8:
-            warning("Key._rsaes_pkcs1_v1_5_decrypt(): decryption error "
-                    "(PS is less than 8 byte long)")
-            return None
-
-        return M                                    # 4)
-
-
-    def _rsaes_oaep_decrypt(self, C, h=None, mgf=None, L=None):
-        """
-        Internal method providing RSAES-OAEP-DECRYPT as defined in Sect.
-        7.1.2 of RFC 3447. Not intended to be used directly. Please, see
-        encrypt() method for type "OAEP".
-
-
-        Input:
-           C  : ciphertext to be decrypted, an octet string of length k, where
-                k = 2*hLen + 2 (k denotes the byte length of the RSA modulus
-                and hLen the byte length of the hash function output)
-           h  : hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls',
-                'sha256', 'sha384'). 'sha1' is used if none is provided.
-           mgf: the mask generation function f : seed, maskLen -> mask
-           L  : optional label whose association with the message is to be
-                verified; the default value for L, if not provided is the empty
-                string.
-
-        Output:
-           message, an octet string of length k mLen, where mLen <= k-2*hLen-2
-
-        On error, None is returned.
-        """
-        # The steps below are the one described in Sect. 7.1.2 of RFC 3447.
-
-        # 1) Length Checking
-                                                    # 1.a) is not done
-        if h is None:
-            h = "sha1"
-        if not _hashFuncParams.has_key(h):
-            warning("Key._rsaes_oaep_decrypt(): unknown hash function %s." % h)
-            return None
-        hLen = _hashFuncParams[h][0]
-        hFun = _hashFuncParams[h][2]
-        k = self.modulusLen / 8
-        cLen = len(C)
-        if cLen != k:                               # 1.b)
-            warning("Key._rsaes_oaep_decrypt(): decryption error. "
-                    "(cLen != k)")
-            return None
-        if k < 2*hLen + 2:
-            warning("Key._rsaes_oaep_decrypt(): decryption error. "
-                    "(k < 2*hLen + 2)")
-            return None
+        return pow(c, self.privExp, n)
 
-        # 2) RSA decryption
-        c = pkcs_os2ip(C)                           # 2.a)
-        m = self._rsadp(c)                          # 2.b)
-        EM = pkcs_i2osp(m, k)                       # 2.c)
 
-        # 3) EME-OAEP decoding
-        if L is None:                               # 3.a)
-            L = ""
-        lHash = hFun(L)
-        Y = EM[:1]                                  # 3.b)
-        if Y != '\x00':
-            warning("Key._rsaes_oaep_decrypt(): decryption error. "
-                    "(Y is not zero)")
-            return None
-        maskedSeed = EM[1:1+hLen]
-        maskedDB = EM[1+hLen:]
-        if mgf is None:
-            mgf = lambda x,y: pkcs_mgf1(x, y, h)
-        seedMask = mgf(maskedDB, hLen)              # 3.c)
-        seed = strxor(maskedSeed, seedMask)         # 3.d)
-        dbMask = mgf(seed, k - hLen - 1)            # 3.e)
-        DB = strxor(maskedDB, dbMask)               # 3.f)
-
-        # I am aware of the note at the end of 7.1.2 regarding error
-        # conditions reporting but the one provided below are for _local_
-        # debugging purposes. --arno
-
-        lHashPrime = DB[:hLen]                      # 3.g)
-        tmp = DB[hLen:].split('\x01', 1)
-        if len(tmp) != 2:
-            warning("Key._rsaes_oaep_decrypt(): decryption error. "
-                    "(0x01 separator not found)")
-            return None
-        PS, M = tmp
-        if PS != '\x00'*len(PS):
-            warning("Key._rsaes_oaep_decrypt(): decryption error. "
-                    "(invalid padding string)")
-            return None
-        if lHash != lHashPrime:
-            warning("Key._rsaes_oaep_decrypt(): decryption error. "
-                    "(invalid hash)")
+    def decrypt(self, C, t="pkcs", h=None, mgf=None, L=None):
+        if h == "tls" or t is None:
+            #return self.decrypt_legacy(C, t=t, h=h, mgf=mgf, L=L)
+            warning("Cannot call decrypt_legacy anymore.")
             return None
-        return M                                    # 4)
-
-
-    def decrypt(self, C, t=None, h=None, mgf=None, L=None):
-        """
-        Decrypt ciphertext 'C' using 't' decryption scheme where 't' can be:
-
-        - None: the ciphertext 'C' is directly applied the RSADP decryption
-                primitive, as described in PKCS#1 v2.1, i.e. RFC 3447
-                Sect 5.1.2. Simply, put the message undergo a modular
-                exponentiation using the private key. Additionnal method
-                parameters are just ignored.
-
-        - 'pkcs': the ciphertext 'C' is applied RSAES-PKCS1-V1_5-DECRYPT
-                decryption scheme as described in section 7.2.2 of RFC 3447.
-                In that context, other parameters ('h', 'mgf', 'l') are not
-                used.
-
-        - 'oaep': the ciphertext 'C' is applied the RSAES-OAEP-DECRYPT
-                decryption scheme, as described in PKCS#1 v2.1, i.e. RFC 3447
-                Sect 7.1.2. In that context,
-
-                o 'h' parameter provides the name of the hash method to use.
-                  Possible values are "md2", "md4", "md5", "sha1", "tls",
-                  "sha224", "sha256", "sha384" and "sha512". If None is
-                  provided, sha1 is used by default.
-
-                o 'mgf' is the mask generation function. By default, mgf
-                  is derived from the provided hash function using the
-                  generic MGF1 (see pkcs_mgf1() for details).
-
-                o 'L' is the optional label to be associated with the
-                  message. If not provided, the default value is used, i.e
-                  the empty string. No check is done on the input limitation
-                  of the hash function regarding the size of 'L' (for
-                  instance, 2^61 - 1 for SHA-1). You have been warned.
-        """
-        if t is None:
-            C = pkcs_os2ip(C)
-            c = self._rsadp(C)
-            l = int(math.ceil(math.log(c, 2) / 8.)) # Hack
-            return pkcs_i2osp(c, l)
 
-        elif t == "pkcs":
-            return self._rsaes_pkcs1_v1_5_decrypt(C)
+        if h is not None:
+            h = mapHashFunc(h)
 
+        if t == "pkcs":
+            pad = padding.PKCS1v15()
         elif t == "oaep":
-            return self._rsaes_oaep_decrypt(C, h, mgf, L)
-
+            pad = padding.OAEP(mgf=mgf(h), algorithm=h, label=L)
         else:
             warning("Key.decrypt(): Unknown decryption type (%s) provided" % t)
             return None
+        return self.key.decrypt(C, pad)
+
 
     ### Below are signature related methods.
     ### Verification methods are inherited from PubKey.
@@ -859,7 +710,7 @@ class _DecryptAndSignRSA(object):
         return S                                    # 3)
 
 
-    def sign(self, M, t=None, h=None, mgf=None, sLen=None):
+    def sign_legacy(self, M, t=None, h=None, mgf=None, sLen=None):
         """
         Sign message 'M' using 't' signature scheme where 't' can be:
 
@@ -892,7 +743,6 @@ class _DecryptAndSignRSA(object):
                   default value (the byte length of the hash value for provided
                   algorithm) by providing another one with that parameter.
         """
-
         if t is None: # RSASP1
             M = pkcs_os2ip(M)
             n = self.modulus
@@ -903,17 +753,123 @@ class _DecryptAndSignRSA(object):
             if s is None:
                 return None
             return pkcs_i2osp(s, self.modulusLen/8)
-
         elif t == "pkcs": # RSASSA-PKCS1-v1_5-SIGN
             if h is None:
                 h = "sha1"
             return self._rsassa_pkcs1_v1_5_sign(M, h)
-
         elif t == "pss": # RSASSA-PSS-SIGN
             return self._rsassa_pss_sign(M, h, mgf, sLen)
+        else:
+            warning("Key.sign(): Unknown signature type (%s) provided" % t)
+            return None
+
+    def sign(self, M, t="pkcs", h=None, mgf=None, sLen=None):
+        if h == "tls" or t is None:
+            return self.sign_legacy(M, t=t, h=h, mgf=mgf, sLen=sLen)
 
+        if h is not None:
+            h = mapHashFunc(h)
+
+        if t == "pkcs": # RSASSA-PKCS1-v1_5-SIGN
+            pad = padding.PKCS1v15()
+        elif t == "pss": # RSASSA-PSS-SIGN
+            pad = padding.PSS(mgf=mgf(h), salt_length=sLen)
         else:
             warning("Key.sign(): Unknown signature type (%s) provided" % t)
             return None
+        return self.key.sign(M, pad, h)
+
+
+
+#####################################################################
+# CA files helpers
+#####################################################################
+
+def create_ca_file(anchor_list, filename):
+    """
+    Concatenate all the certificates (PEM format for the export) in
+    'anchor_list' and write the result to file 'filename'. On success
+    'filename' is returned, None otherwise.
+
+    If you are used to OpenSSL tools, this function builds a CAfile
+    that can be used for certificate and CRL check.
+
+    Also see create_temporary_ca_file().
+    """
+    try:
+        f = open(filename, "w")
+        for a in anchor_list:
+            s = a.output(fmt="PEM")
+            f.write(s)
+        f.close()
+    except:
+        return None
+    return filename
+
+def create_temporary_ca_file(anchor_list):
+    """
+    Concatenate all the certificates (PEM format for the export) in
+    'anchor_list' and write the result to file to a temporary file
+    using mkstemp() from tempfile module. On success 'filename' is
+    returned, None otherwise.
+
+    If you are used to OpenSSL tools, this function builds a CAfile
+    that can be used for certificate and CRL check.
+    """
+    try:
+        f, fname = tempfile.mkstemp()
+        for a in anchor_list:
+            s = a.output(fmt="PEM")
+            l = os.write(f, s)
+        os.close(f)
+    except:
+        return None
+    return fname
+
+def create_temporary_ca_path(anchor_list, folder):
+    """
+    Create a CA path folder as defined in OpenSSL terminology, by
+    storing all certificates in 'anchor_list' list in PEM format
+    under provided 'folder' and then creating the associated links
+    using the hash as usually done by c_rehash.
+
+    Note that you can also include CRL in 'anchor_list'. In that
+    case, they will also be stored under 'folder' and associated
+    links will be created.
+
+    In folder, the files are created with names of the form
+    0...ZZ.pem. If you provide an empty list, folder will be created
+    if it does not already exist, but that's all.
 
+    The number of certificates written to folder is returned on
+    success, None on error.
+    """
+    # We should probably avoid writing duplicate anchors and also
+    # check if they are all certs.
+    try:
+        if not os.path.isdir(folder):
+            os.makedirs(folder)
+    except:
+        return None
+
+    l = len(anchor_list)
+    if l == 0:
+        return None
+    fmtstr = "%%0%sd.pem" % math.ceil(math.log(l, 10))
+    i = 0
+    try:
+        for a in anchor_list:
+            fname = os.path.join(folder, fmtstr % i)
+            f = open(fname, "w")
+            s = a.output(fmt="PEM")
+            f.write(s)
+            f.close()
+            i += 1
+    except:
+        return None
+
+    r,w=popen2.popen2("c_rehash %s" % folder)
+    r.close(); w.close()
+
+    return l
 
diff --git a/scapy/layers/tls/crypto/prf.py b/scapy/layers/tls/crypto/prf.py
index 94a2aa97330175e7fc10438f59ca7e6eec7d5a2f..1f93f92569074352bfb156160ec3518e16b9e70c 100644
--- a/scapy/layers/tls/crypto/prf.py
+++ b/scapy/layers/tls/crypto/prf.py
@@ -215,25 +215,50 @@ class PRF(object):
          prior to this document when TLS 1.2 is negotiated."
         Cipher suites using SHA-384 were defined later on.
         """
+        if self.tls_version <= 0x0300:
 
-        if read_or_write == "write":
-            d = {"client": "client", "server": "server"}
-        else:
-            d = {"client": "server", "server": "client"}
-        finished_label = d[con_end] + " finished"
+            if read_or_write == "write":
+                d = {"client": "CLNT", "server": "SRVR"}
+            else:
+                d = {"client": "SRVR", "server": "CLNT"}
+            label = d[con_end]
+
+            sslv3_md5_pad1 = "\x36"*48
+            sslv3_md5_pad2 = "\x5c"*48
+            sslv3_sha1_pad1 = "\x36"*40
+            sslv3_sha1_pad2 = "\x5c"*40
+
+            md5 = tls_hash_algs["MD5"]()
+            sha1 = tls_hash_algs["SHA"]()
 
-        if self.tls_version <= 0x0302:
-            s1 = tls_hash_algs["MD5"]().digest(handshake_msg)
-            s2 = tls_hash_algs["SHA"]().digest(handshake_msg)
+            md5_hash = md5.digest(master_secret + sslv3_md5_pad2 +
+                                  md5.digest(handshake_msg + label +
+                                             master_secret + sslv3_md5_pad1))
+            sha1_hash = sha1.digest(master_secret + sslv3_sha1_pad2 +
+                                    sha1.digest(handshake_msg + label +
+                                                master_secret + sslv3_sha1_pad1))
+            verify_data = md5_hash + sha1_hash
 
-            verify_data = self.prf(master_secret, finished_label, s1 + s2, 12)
         else:
-            if self.hash_name in ["MD5", "SHA"]:
-                h = tls_hash_algs["SHA256"]()
+
+            if read_or_write == "write":
+                d = {"client": "client", "server": "server"}
+            else:
+                d = {"client": "server", "server": "client"}
+            label = d[con_end] + " finished"
+
+            if self.tls_version <= 0x0302:
+                s1 = tls_hash_algs["MD5"]().digest(handshake_msg)
+                s2 = tls_hash_algs["SHA"]().digest(handshake_msg)
+                verify_data = self.prf(master_secret, label, s1 + s2, 12)
             else:
-                h = tls_hash_algs[self.hash_name]()
-            s = h.digest(handshake_msg)
-            verify_data = self.prf(master_secret, finished_label, s, 12)
+                if self.hash_name in ["MD5", "SHA"]:
+                    h = tls_hash_algs["SHA256"]()
+                else:
+                    h = tls_hash_algs[self.hash_name]()
+                s = h.digest(handshake_msg)
+                verify_data = self.prf(master_secret, label, s, 12)
+
         return verify_data
 
     def postprocess_key_for_export(self, key, client_random, server_random,
diff --git a/scapy/layers/tls/handshake.py b/scapy/layers/tls/handshake.py
index 316c4e1f74447e7aed06ead0825bd99c687d42ca..5a6ae985afb229accd7cbafd489becffb542634a 100644
--- a/scapy/layers/tls/handshake.py
+++ b/scapy/layers/tls/handshake.py
@@ -21,6 +21,7 @@ from scapy.layers.tls.basefields import _tls_version, _TLSVersionField
 from scapy.layers.tls.keyexchange import (_tls_named_curves, _TLSServerParamsField,
                                           _TLSSignature, _TLSSignatureField,
                                           _tls_hash_sig, SigAndHashAlgsField,
+                                          ServerRSAParams,
                                           SigAndHashAlgsLenField)
 from scapy.layers.tls.session import (_GenericTLSSessionInheritance,
                                       writeConnState,
@@ -1031,8 +1032,11 @@ class TLSServerKeyExchange(_TLSHandshake):
         if fval is None:
             s = self.tls_session
             if s.pwcs:
-                cls = s.pwcs.key_exchange.server_kx_msg_cls("\x03")
-                cls = cls(tls_session=s)
+                if s.pwcs.key_exchange.export:
+                    cls = ServerRSAParams(tls_session=s)
+                else:
+                    cls = s.pwcs.key_exchange.server_kx_msg_cls("\x03")
+                    cls = cls(tls_session=s)
                 try:
                     cls.fill_missing()
                 except:
@@ -1255,11 +1259,19 @@ class TLSClientKeyExchange(_TLSHandshake):
 ### Finished                                                                ###
 ###############################################################################
 
+class _VerifyDataField(StrLenField):
+    def getfield(self, pkt, s):
+        if pkt.tls_session.tls_version == 0x300:
+            sep = 36
+        else:
+            sep = 12
+        return s[sep:], s[:sep]
+
 class TLSFinished(_TLSHandshake):
     name = "TLS Handshake - Finished"
     fields_desc = [ ByteEnumField("msgtype", 20, _tls_handshake_type),
                     ThreeBytesField("msglen", None),
-                    StrFixedLenField("vdata", None, 12) ]
+                    _VerifyDataField("vdata", None) ]
 
     def build(self, *args, **kargs):
         fval = self.getfieldval("vdata")
diff --git a/scapy/layers/tls/keyexchange.py b/scapy/layers/tls/keyexchange.py
index 1a8abd1ee529fd67550f430487edc39f1bf75587..faf69bfa80ff54a2fe06b451ffbf114743173306 100644
--- a/scapy/layers/tls/keyexchange.py
+++ b/scapy/layers/tls/keyexchange.py
@@ -9,33 +9,19 @@ TLS key exchange logic.
 
 import math
 
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric import dh, ec, rsa
+
 from scapy.config import conf
 from scapy.error import warning
 from scapy.fields import *
 from scapy.packet import Packet, Raw, Padding
-from scapy.layers.tls.cert import PubKey
+from scapy.layers.tls.cert import PubKey, PrivKey
 from scapy.layers.tls.session import _GenericTLSSessionInheritance
 from scapy.layers.tls.basefields import _tls_version, _TLSClientVersionField
 from scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp, pkcs_os2ip
-from scapy.layers.tls.crypto.ffdh import FFDHParams
-from scapy.layers.tls.crypto.curves import encode_point
-
-ecdsa_support = False
-try:
-    from ecdsa.util import sigencode_der, sigdecode_der
-    from scapy.layers.tls.crypto.ecdh import ECParams, ECDHParams
-    ecdsa_support = True
-except ImportError:
-    import logging
-    log_loading = logging.getLogger("scapy.loading")
-    log_loading.info("Can't import python ecdsa lib. No EC-based kx.")
-    sigencode_der = sigdecode_der = None
-
-def ecdsa_warning(func):
-    def func_in(*args, **kwargs):
-        if ecdsa_support:
-            return func(*args, **kwargs)
-    return func_in
+from scapy.layers.tls.crypto.ffdh import FFDH_GROUPS
 
 
 ###############################################################################
@@ -149,7 +135,7 @@ class _TLSSignature(_GenericTLSSessionInheritance):
             self.sig_val = key.sign(m, t='pkcs', h='tls')
         else:
             h = _tls_hash_sig[self.sig_alg].split('+')[0]
-            self.sig_val = key.sign(m, t='pkcs', h=h, sigencode=sigencode_der)
+            self.sig_val = key.sign(m, t='pkcs', h=h)
 
     def _verify_sig(self, m, cert):
         """
@@ -159,8 +145,7 @@ class _TLSSignature(_GenericTLSSessionInheritance):
         if self.sig_val:
             if self.sig_alg:
                 h = _tls_hash_sig[self.sig_alg].split('+')[0]
-                return cert.verify(m, self.sig_val, t='pkcs', h=h,
-                                   sigdecode=sigdecode_der)
+                return cert.verify(m, self.sig_val, t='pkcs', h=h)
             else:
                 return cert.verify(m, self.sig_val, t='pkcs', h='tls')
         return False
@@ -214,8 +199,7 @@ class _TLSServerParamsField(PacketField):
                 p = ServerDHParams(m, tls_session=s)
                 if pkcs_os2ip(p.load[:2]) not in _tls_hash_sig:
                     raise Exception
-                else:
-                    return p
+                return p
             except:
                 cls = _tls_server_ecdh_cls_guess(m)
                 p = cls(m, tls_session=s)
@@ -262,47 +246,53 @@ class ServerDHParams(_GenericTLSSessionInheritance):
         Note that we do not expect dh_params_def.g to be more than 0xff.
         """
         s = self.tls_session
-        dh_params_def = s.default_ffdh_params
-        dh_Ys = dh_params_def.gen_public_params()
 
-        if self.dh_plen is None:
-            self.dh_plen = dh_params_def.mLen/8
+        default_params = FFDH_GROUPS['modp2048'][0].parameter_numbers()
+        default_mLen = FFDH_GROUPS['modp2048'][1]
+
         if self.dh_p is "":
-            self.dh_p = pkcs_i2osp(dh_params_def.m, dh_params_def.mLen/8)
+            self.dh_p = pkcs_i2osp(default_params.p, default_mLen/8)
+        if self.dh_plen is None:
+            self.dh_plen = len(self.dh_p)
+
+        if self.dh_g is "":
+            self.dh_g = pkcs_i2osp(default_params.g, 1)
         if self.dh_glen is None:
             self.dh_glen = 1
-        if self.dh_g is "":
-            self.dh_g = pkcs_i2osp(dh_params_def.g, 1)
-        if self.dh_Yslen is None:
-            self.dh_Yslen = len(dh_Ys)
-        if self.dh_Ys is "":
-            self.dh_Ys = dh_Ys
 
-        s.server_kx_params = FFDHParams(self.dh_g,
-                                        self.dh_p,
-                                        self.dh_plen*8)
-        s.server_kx_params.priv = dh_params_def.priv
-        s.server_kx_params.pub = pkcs_os2ip(self.dh_Ys)
+        p = pkcs_os2ip(self.dh_p)
+        g = pkcs_os2ip(self.dh_g)
+        real_params = dh.DHParameterNumbers(p, g).parameters(default_backend())
+
+        if self.dh_Ys is "":
+            s.server_kx_privkey = real_params.generate_private_key()
+            pubkey = s.server_kx_privkey.public_key()
+            y = pubkey.public_numbers().y
+            self.dh_Ys = pkcs_i2osp(y, pubkey.key_size/8)
+        # else, we assume that the user wrote the server_kx_privkey by himself
+        if self.dh_Yslen is None:
+            self.dh_Yslen = len(self.dh_Ys)
 
-        s.client_kx_params = FFDHParams(self.dh_g,
-                                        self.dh_p,
-                                        self.dh_plen*8)
-        s.client_kx_params.other_pub = pkcs_os2ip(self.dh_Ys)
+        if not s.client_kx_ffdh_params:
+            s.client_kx_ffdh_params = real_params
 
     def post_dissection(self, r):
         """
-        XXX Do a check_params() once it has been implemented in crypto/ffdh.py.
+        XXX Check that the pubkey received is in the group.
         """
-        if self.dh_g and self.dh_p and self.dh_plen:
-            s = self.tls_session
+        #if self.dh_g and self.dh_p and self.dh_Ys: #XXX remove this, probably
+        p = pkcs_os2ip(self.dh_p)
+        g = pkcs_os2ip(self.dh_g)
+        pn = dh.DHParameterNumbers(p, g)
 
-            dh_params_s = FFDHParams(self.dh_g, self.dh_p, self.dh_plen*8)
-            s.server_kx_params = dh_params_s
-            s.server_kx_params.pub = pkcs_os2ip(self.dh_Ys)
+        y = pkcs_os2ip(self.dh_Ys)
+        public_numbers = dh.DHPublicNumbers(y, pn)
 
-            dh_params_c = FFDHParams(self.dh_g, self.dh_p, self.dh_plen*8)
-            s.client_kx_params = dh_params_c
-            s.client_kx_params.other_pub = pkcs_os2ip(self.dh_Ys)
+        s = self.tls_session
+        s.server_kx_pubkey = public_numbers.public_key(default_backend())
+
+        if not s.client_kx_ffdh_params:
+            s.client_kx_ffdh_params = pn.parameters(default_backend())
 
     def guess_payload_class(self, p):
         """
@@ -409,6 +399,10 @@ class _ECBasisField(PacketField):
 ## The most frequent encounter of the 3 is (by far) ServerECDHNamedCurveParams.
 
 class ServerECDHExplicitPrimeParams(_GenericTLSSessionInheritance):
+    """
+    XXX We provide parsing abilities for ExplicitPrimeParams, but there is no
+    'cryptography' support, hence no context operations.
+    """
     name = "Server ECDH parameters - Explicit Prime"
     fields_desc = [ ByteEnumField("curve_type", 1, _tls_ec_curve_types),
 		    FieldLenField("plen", None, length_of="p", fmt="B"),
@@ -430,7 +424,6 @@ class ServerECDHExplicitPrimeParams(_GenericTLSSessionInheritance):
                     StrLenField("point", "",
                                 length_from=lambda pkt: pkt.pointlen) ]
 
-    @ecdsa_warning
     def fill_missing(self):
         """
         We do not want TLSServerKeyExchange.build() to overload and recompute
@@ -439,89 +432,18 @@ class ServerECDHExplicitPrimeParams(_GenericTLSSessionInheritance):
 
         XXX Note that if it is not set by the user, the cofactor will always
         be 1. It is true for most, but not all, TLS elliptic curves.
-        """
-        s = self.tls_session
-        dh_params_def = s.default_ecdh_params[0]
-        c = dh_params_def.ec_parameters.curve
-        point = dh_params_def.gen_public_params()
 
+        XXX Try and create a curve with the 'cryptography' lib somehow,
+        extract the missing fields for filling, then set s.server_kx_privkey.
+        """
         if self.curve_type is None:
-            self.curve_type = 1
-        if self.plen is None:
-            p = c.curve.p()
-            self.plen = len(pkcs_i2osp(p, c.baselen))
-        if self.p is "":
-            p = c.curve.p()
-            self.p = pkcs_i2osp(p, c.baselen)
-        if self.curve is None:
-            a = c.curve.a()
-            b = c.curve.b()
-            a_str = pkcs_i2osp(a, c.baselen)
-            b_str = pkcs_i2osp(b, c.baselen)
-            self.curve = ECCurvePkt(a=a_str, b=b_str)
-        if self.baselen is None:
-            self.baselen = c.baselen
-        if self.base is "":
-            self.base = encode_point(c.generator, dh_params_def.point_format)
-        if self.orderlen is None:
-            order = c.generator.order()
-            self.orderlen = len(pkcs_i2osp(order, c.baselen))
-        if self.order is "":
-            order = c.generator.order()
-            self.order = pkcs_i2osp(order, c.baselen)
-        if self.cofactorlen is None:
-            self.cofactorlen = 1
-        if self.cofactor is "":
-            self.cofactor = "\x01"
-        if self.pointlen is None:
-            self.pointlen = len(point)
-        if self.point is "":
-            self.point = point
-
-        ec_params_s = ECParams(self.curve_type)
-        ec_params_s.set_explicit_prime_curve(self.p,
-                                             self.curve.a, self.curve.b,
-                                             self.base, self.order)
-        dh_params_s = ECDHParams(ec_params_s, dh_params_def.point_format)
-        s.server_kx_params = dh_params_s
-        s.server_kx_params.priv = dh_params_def.priv
-        s.server_kx_params.pub = self.point
-
-        ec_params_c = ECParams(self.curve_type)
-        ec_params_c.set_explicit_prime_curve(self.p,
-                                             self.curve.a, self.curve.b,
-                                             self.base, self.order)
-        dh_params_c = ECDHParams(ec_params_c, dh_params_def.point_format)
-        s.client_kx_params = dh_params_c
-        s.client_kx_params.other_pub = self.point
-
-    @ecdsa_warning
+            self.curve_type = _tls_ec_curve_types["explicit_prime"]
+
     def post_dissection(self, pkt):
         """
-        XXX Do a check_params() once it has been implemented in crypto/ecdh.py.
+        XXX Store the server_kx_pubkey.
+        XXX Check that the pubkey received is on the curve.
         """
-        s = self.tls_session
-
-        point_format = 0
-        if self.point[0] in ["\x02", "\x03"]:
-            point_format = 1
-
-        ec_params_s = ECParams(self.curve_type)
-        ec_params_s.set_explicit_prime_curve(self.p,
-                                             self.curve.a, self.curve.b,
-                                             self.base, self.order)
-        dh_params_s = ECDHParams(ec_params_s, point_format)
-        s.server_kx_params = dh_params_s
-        s.server_kx_params.priv = dh_params_def.priv
-        s.server_kx_params.pub = self.point
-
-        ec_params_c = ECParams(self.curve_type)
-        ec_params_c.set_explicit_prime_curve(self.p,
-                                             self.curve.a, self.curve.b,
-                                             self.base, self.order)
-        dh_params_c = ECDHParams(ec_params_c, point_format)
-        s.client_kx_params = dh_params_c
-        s.client_kx_params.other_pub = self.point
 
     def guess_payload_class(self, p):
         return Padding
@@ -529,8 +451,8 @@ class ServerECDHExplicitPrimeParams(_GenericTLSSessionInheritance):
 
 class ServerECDHExplicitChar2Params(_GenericTLSSessionInheritance):
     """
-    XXX We provide parsing abilities for Char2Params, but the context
-    operations have not been implemented yet.
+    XXX We provide parsing abilities for Char2Params, but there is no
+    'cryptography' support, hence no context operations.
     """
     name = "Server ECDH parameters - Explicit Char2"
     fields_desc = [ ByteEnumField("curve_type", 2, _tls_ec_curve_types),
@@ -551,19 +473,19 @@ class ServerECDHExplicitChar2Params(_GenericTLSSessionInheritance):
                     StrLenField("point", "",
                                 length_from = lambda pkt: pkt.pointlen) ]
 
-    @ecdsa_warning
     def fill_missing(self):
         """
         We do not want TLSServerKeyExchange.build() to overload and recompute
         things everytime it is called. This method can be called specifically
         to have things filled in a smart fashion.
         """
-        pass
+        if self.curve_type is None:
+            self.curve_type = _tls_ec_curve_types["explicit_char2"]
 
-    @ecdsa_warning
     def post_dissection(self, pkt):
         """
-        XXX Do a check_params() once it has been implemented in crypto/ecdh.py.
+        XXX Store the server_kx_pubkey.
+        XXX Check that the pubkey received is in the group.
         """
         pass
 
@@ -580,62 +502,72 @@ class ServerECDHNamedCurveParams(_GenericTLSSessionInheritance):
                     StrLenField("point", None,
                                 length_from = lambda pkt: pkt.pointlen) ]
 
-    @ecdsa_warning
     def fill_missing(self):
         """
         We do not want TLSServerKeyExchange.build() to overload and recompute
         things everytime it is called. This method can be called specifically
         to have things filled in a smart fashion.
-        XXX We should check our point_format before 'point' filling.
+        XXX We should account for the point_format (before 'point' filling).
         """
         s = self.tls_session
-        dh_params_def = s.default_ecdh_params[0]
-        point = dh_params_def.gen_public_params()
 
         if self.curve_type is None:
-            self.curve_type = 3
+            self.curve_type = _tls_ec_curve_types["named_curve"]
+
         if self.named_curve is None:
-            self.named_curve = dh_params_def.ec_parameters.curve.curve_id
-        if self.pointlen is None:
-            self.pointlen = len(point)
+            curve = ec.SECP256R1()
+            s.server_kx_privkey = ec.generate_private_key(curve,
+                                                          default_backend())
+            curve_id = 0
+            for cid, name in _tls_named_curves.iteritems():
+                if name == curve.name:
+                    curve_id = cid
+                    break
+            self.named_curve = curve_id
+        else:
+            curve_name = _tls_named_curves.get(self.named_curve)
+            if curve_name is None:
+                # this fallback is arguable
+                curve = ec.SECP256R1()
+            else:
+                curve_cls = ec._CURVE_TYPES.get(curve_name)
+                if curve_cls is None:
+                    # this fallback is arguable
+                    curve = ec.SECP256R1()
+                else:
+                    curve = curve_cls()
+            s.server_kx_privkey = ec.generate_private_key(curve,
+                                                          default_backend())
+
         if self.point is None:
-            self.point = point
-
-        ec_params_s = ECParams(self.curve_type)
-        ec_params_s.set_named_curve(self.named_curve)
-        dh_params_s = ECDHParams(ec_params_s, dh_params_def.point_format)
-        s.server_kx_params = dh_params_s
-        s.server_kx_params.priv = dh_params_def.priv
-        s.server_kx_params.pub = self.point
-
-        ec_params_c = ECParams(self.curve_type)
-        ec_params_c.set_named_curve(self.named_curve)
-        dh_params_c = ECDHParams(ec_params_c, dh_params_def.point_format)
-        s.client_kx_params = dh_params_c
-        s.client_kx_params.other_pub = self.point
-
-    @ecdsa_warning
+            pubkey = s.server_kx_privkey.public_key()
+            self.point = pubkey.public_numbers().encode_point()
+        # else, we assume that the user wrote the server_kx_privkey by himself
+        if self.pointlen is None:
+            self.pointlen = len(self.point)
+
+        if not s.client_kx_ecdh_params:
+            s.client_kx_ecdh_params = curve
+
     def post_dissection(self, r):
         """
-        XXX Do a check_params() once it has been implemented in crypto/ecdh.py.
+        XXX Support compressed point format.
+        XXX Check that the pubkey received is on the curve.
         """
+        #point_format = 0
+        #if self.point[0] in ['\x02', '\x03']:
+        #    point_format = 1
+
+        #if self.named_curve and self.point: #XXX remove this, probably
+        curve_name = _tls_named_curves[self.named_curve]
+        curve = ec._CURVE_TYPES[curve_name]()
+        import_point = ec.EllipticCurvePublicNumbers.from_encoded_point
+        pubnum = import_point(curve, self.point)
         s = self.tls_session
+        s.server_kx_pubkey = pubnum.public_key(default_backend())
 
-        point_format = 0
-        if self.point[0] in ['\x02', '\x03']:
-            point_format = 1
-
-        ec_params_s = ECParams(self.curve_type)
-        ec_params_s.set_named_curve(self.named_curve)
-        dh_params_s = ECDHParams(ec_params_s, point_format)
-        s.server_kx_params = dh_params_s
-        s.server_kx_params.pub = self.point
-
-        ec_params_c = ECParams(self.curve_type)
-        ec_params_c.set_named_curve(self.named_curve)
-        dh_params_c = ECDHParams(ec_params_c, point_format)
-        s.client_kx_params = dh_params_c
-        s.client_kx_params.other_pub = self.point
+        if not s.client_kx_ecdh_params:
+            s.client_kx_ecdh_params = curve
 
     def guess_payload_class(self, p):
         return Padding
@@ -657,7 +589,7 @@ def _tls_server_ecdh_cls_guess(m):
 class ServerRSAParams(_GenericTLSSessionInheritance):
     """
     Defined for RSA_EXPORT kx : it enables servers to share RSA keys shorter
-    than their principal {>512}-bit key, when is not allowed for kx.
+    than their principal {>512}-bit key, when it is not allowed for kx.
 
     This should not appear in standard RSA kx negotiation, as the key
     has already been advertised in the Certificate message.
@@ -671,16 +603,24 @@ class ServerRSAParams(_GenericTLSSessionInheritance):
                                 length_from = lambda pkt: pkt.rsaexplen) ]
 
     def fill_missing(self):
-        k = self.tls_session.server_rsa_key
+        ext_k = rsa.generate_private_key(public_exponent=0x10001,
+                                         key_size=512,
+                                         backend=default_backend())
+        pem_k = ext_k.private_bytes(
+                        encoding=serialization.Encoding.PEM,
+                        format=serialization.PrivateFormat.TraditionalOpenSSL,
+                        encryption_algorithm=serialization.NoEncryption())
+        k = PrivKey(pem_k)
+        self.tls_session.server_tmp_rsa_key = k
 
         modlen = k.modulusLen / 8
-        if self.rsamod is None:
+        if self.rsamod is "":
             self.rsamod = pkcs_i2osp(k.modulus, modlen)
         if self.rsamodlen is None:
             self.rsamodlen = len(self.rsamod)
 
         rsaexplen = math.ceil(math.log(k.pubExp)/math.log(2)/8.)
-        if self.rsaexp is None:
+        if self.rsaexp is "":
             self.rsaexp = pkcs_i2osp(k.pubExp, rsaexplen)
         if self.rsaexplen is None:
             self.rsaexplen = len(self.rsaexp)
@@ -719,9 +659,6 @@ class ServerPSKParams(Packet):
         pass
 
     def post_dissection(self, pkt):
-        """
-        XXX Do a check_params() once it has been implemented in crypto/ecdh.py.
-        """
         pass
 
     def guess_payload_class(self, p):
@@ -752,24 +689,21 @@ class ClientDiffieHellmanPublic(_GenericTLSSessionInheritance):
         s = self.tls_session
 
         if self.dh_Yc == "":
-            dh_Yc = s.client_kx_params.gen_public_params()
-            dh_Yclen = len(dh_Yc)
-            self.dh_Yc = dh_Yc
+            params = s.client_kx_ffdh_params
+            s.client_kx_privkey = params.generate_private_key()
+            pubkey = s.client_kx_privkey.public_key()
+            y = pubkey.public_numbers().y
+            self.dh_Yc = pkcs_i2osp(y, pubkey.key_size/8)
+        # else, we assume that the user wrote the client_kx_privkey by himself
         if self.dh_Yclen is None:
-            self.dh_Yclen = dh_Yclen
-            # small hack so that ClientECDiffieHellmanPublic also works
-            l = struct.pack(self.fields_desc[0].fmt, self.dh_Yclen)
-            pkt = l + self.dh_Yc
-
-        if s.server_kx_params:
-            s.server_kx_params.other_pub = pkcs_os2ip(self.dh_Yc)
+            self.dh_Yclen = len(self.dh_Yc)
 
-        if s.client_kx_params.priv is not None:
-            pms = s.client_kx_params.gen_secret(s.server_kx_params.pub)
+        if s.client_kx_privkey and s.server_kx_pubkey:
+            pms = s.client_kx_privkey.exchange(s.server_kx_pubkey)
             s.pre_master_secret = pms
             s.compute_ms_and_derive_keys()
 
-        return pkt + pay
+        return pkcs_i2osp(self.dh_Yclen, 2) + self.dh_Yc + pay
 
     def post_dissection(self, m):
         """
@@ -779,37 +713,66 @@ class ClientDiffieHellmanPublic(_GenericTLSSessionInheritance):
         """
         s = self.tls_session
 
-        if s.client_kx_params:
-            s.client_kx_params.pub = pkcs_os2ip(self.dh_Yc)
+        if s.client_kx_ffdh_params:
+            y = pkcs_os2ip(self.dh_Yc)
+            param_numbers = s.client_kx_ffdh_params.parameter_numbers()
+            public_numbers = dh.DHPublicNumbers(y, param_numbers)
+            s.client_kx_pubkey = public_numbers.public_key(default_backend())
 
-        if s.server_kx_params:
-            s.server_kx_params.other_pub = pkcs_os2ip(self.dh_Yc)
-            if s.server_kx_params.priv:
-                ZZ = s.server_kx_params.gen_secret(self.dh_Yc)
-                s.pre_master_secret = ZZ
-                s.compute_ms_and_derive_keys()
+        if s.server_kx_privkey and s.client_kx_pubkey:
+            ZZ = s.server_kx_privkey.exchange(s.client_kx_pubkey)
+            s.pre_master_secret = ZZ
+            s.compute_ms_and_derive_keys()
 
     def guess_payload_class(self, p):
         return Padding
 
-class ClientECDiffieHellmanPublic(ClientDiffieHellmanPublic):
+class ClientECDiffieHellmanPublic(_GenericTLSSessionInheritance):
     """
-    We need an EC-dedicated subclass because the 'len' field is 1 byte longer.
+    Note that the 'len' field is 1 byte longer than with the previous class.
     """
     name = "Client ECDH Public Value"
-    fields_desc = [ FieldLenField("dh_Yclen", None, length_of="dh_Yc", fmt="B"),
-                    StrLenField("dh_Yc", "",
-                                length_from=lambda pkt: pkt.dh_Yclen)]
+    fields_desc = [ FieldLenField("ecdh_Yclen", None,
+                                  length_of="ecdh_Yc", fmt="B"),
+                    StrLenField("ecdh_Yc", "",
+                                length_from=lambda pkt: pkt.ecdh_Yclen)]
 
     def post_build(self, pkt, pay):
-        if ecdsa_support:
-            return super(ClientECDiffieHellmanPublic, self).post_build(pkt, pay)
-        else:
-            return pkt + pay
+        s = self.tls_session
+
+        if self.ecdh_Yc == "":
+            params = s.client_kx_ecdh_params
+            s.client_kx_privkey = ec.generate_private_key(params,
+                                                          default_backend())
+            pubkey = s.client_kx_privkey.public_key()
+            x = pubkey.public_numbers().x
+            y = pubkey.public_numbers().y
+            self.ecdh_Yc = ("\x04" +
+                            pkcs_i2osp(x, params.key_size/8) +
+                            pkcs_i2osp(y, params.key_size/8))
+        # else, we assume that the user wrote the client_kx_privkey by himself
+        if self.ecdh_Yclen is None:
+            self.ecdh_Yclen = len(self.ecdh_Yc)
+
+        if s.client_kx_privkey and s.server_kx_pubkey:
+            pms = s.client_kx_privkey.exchange(ec.ECDH(), s.server_kx_pubkey)
+            s.pre_master_secret = pms
+            s.compute_ms_and_derive_keys()
+
+        return pkcs_i2osp(self.ecdh_Yclen, 1) + self.ecdh_Yc + pay
 
-    @ecdsa_warning
     def post_dissection(self, m):
-        return super(ClientECDiffieHellmanPublic, self).post_dissection(m)
+        s = self.tls_session
+
+        if s.client_kx_ecdh_params:
+            import_point = ec.EllipticCurvePublicNumbers.from_encoded_point
+            pub_num = import_point(s.client_kx_ecdh_params, self.ecdh_Yc)
+            s.client_kx_pubkey = pub_num.public_key(default_backend())
+
+        if s.server_kx_privkey and s.client_kx_pubkey:
+            ZZ = s.server_kx_privkey.exchange(ec.ECDH(), s.client_kx_pubkey)
+            s.pre_master_secret = ZZ
+            s.compute_ms_and_derive_keys()
 
 
 ### RSA Encryption (standard & export)
@@ -835,7 +798,11 @@ class EncryptedPreMasterSecret(_GenericTLSSessionInheritance):
                 warning(err)
             else:
                 tbd = m[2:]
-        if s.server_rsa_key is not None:
+        if s.server_tmp_rsa_key is not None:
+            # priority is given to the tmp_key, if there is one
+            decrypted = s.server_tmp_rsa_key.decrypt(tbd)
+            pms = decrypted[-48:]
+        elif s.server_rsa_key is not None:
             decrypted = s.server_rsa_key.decrypt(tbd)
             pms = decrypted[-48:]
         else:
@@ -850,7 +817,7 @@ class EncryptedPreMasterSecret(_GenericTLSSessionInheritance):
 
     def post_build(self, pkt, pay):
         """
-        We encrypt premaster secret (the 48 bytes) with either the server
+        We encrypt the premaster secret (the 48 bytes) with either the server
         certificate or the temporary RSA key provided in a server key exchange
         message. After that step, we add the 2 bytes to provide the length, as
         described in implementation notes at the end of section 7.4.7.1.
@@ -861,10 +828,10 @@ class EncryptedPreMasterSecret(_GenericTLSSessionInheritance):
         s.pre_master_secret = enc
         s.compute_ms_and_derive_keys()
 
-        if s.server_certs:
-            enc = s.server_certs[0].encrypt(pkt, "pkcs")
-        elif self.tls_session.server_tmp_rsa_key is not None:
+        if s.server_tmp_rsa_key is not None:
             enc = s.server_tmp_rsa_key.encrypt(pkt, "pkcs")
+        elif s.server_certs is not None and len(s.server_certs) > 0:
+            enc = s.server_certs[0].encrypt(pkt, "pkcs")
         else:
             warning("No material to encrypt Pre Master Secret")
 
diff --git a/scapy/layers/tls/record.py b/scapy/layers/tls/record.py
index 160d322b6167e725e9031b7f0a31a58a1e055106..cebe3c21d38d551bb22d23268cc385a098946a3e 100644
--- a/scapy/layers/tls/record.py
+++ b/scapy/layers/tls/record.py
@@ -19,8 +19,7 @@ from scapy.fields import *
 from scapy.packet import *
 from scapy.layers.inet import TCP
 from scapy.layers.tls.session import _GenericTLSSessionInheritance
-from scapy.layers.tls.handshake import (_tls_handshake_cls, _TLSHandshake,
-                                        TLSClientHello)
+from scapy.layers.tls.handshake import _tls_handshake_cls, _TLSHandshake
 from scapy.layers.tls.basefields import (_TLSVersionField, _tls_version,
                                          _TLSIVField, _TLSMACField,
                                          _TLSPadField, _TLSPadLenField,
@@ -103,6 +102,8 @@ class _TLSMsgListField(PacketListField):
             remain, ret = s[:l], s[l:]
 
         if pkt.decipherable:
+            if remain == "":
+                return ret, [TLSApplicationData(data="")]
             while remain:
                 raw_msg = remain
                 p = self.m2i(pkt, remain)
@@ -286,8 +287,15 @@ class TLS(_GenericTLSSessionInheritance):
         read_seq_num = struct.pack("!Q", self.tls_session.rcs.seq_num)
         self.tls_session.rcs.seq_num += 1
         alg = self.tls_session.rcs.hmac
+
+        version = struct.unpack("!H", hdr[1:3])[0]
         try:
-            h = alg.digest(read_seq_num + hdr + msg)
+            if version > 0x300:
+                h = alg.digest(read_seq_num + hdr + msg)
+            elif version == 0x300:
+                h = alg.digest_sslv3(read_seq_num + hdr[0] + hdr[3:5] + msg)
+            else:
+                raise Exception("Unrecognized version.")
         except HMACError:
             h = mac
         return h == mac
@@ -308,6 +316,9 @@ class TLS(_GenericTLSSessionInheritance):
         TLSPlaintext.fragment. Else, it should be the length of the
         _TLSEncryptedContent.
         """
+        if len(s) < 5:
+            raise Exception("Invalid record: header is too short.")
+
         msglen = struct.unpack('!H', s[3:5])[0]
         hdr, efrag, r = s[:5], s[5:5+msglen], s[msglen+5:]
 
@@ -316,8 +327,7 @@ class TLS(_GenericTLSSessionInheritance):
         cipher_type = self.tls_session.rcs.cipher.type
 
         if cipher_type == 'block':
-            if len(s) >= 3:
-                version = struct.unpack("!H", s[1:3])[0]
+            version = struct.unpack("!H", s[1:3])[0]
 
             # Decrypt
             if version >= 0x0302:
@@ -462,7 +472,14 @@ class TLS(_GenericTLSSessionInheritance):
         write_seq_num = struct.pack("!Q", self.tls_session.wcs.seq_num)
         self.tls_session.wcs.seq_num += 1
         alg = self.tls_session.wcs.hmac
-        h = alg.digest(write_seq_num + hdr + msg)
+
+        version = struct.unpack("!H", hdr[1:3])[0]
+        if version > 0x300:
+            h = alg.digest(write_seq_num + hdr + msg)
+        elif version == 0x300:
+            h = alg.digest_sslv3(write_seq_num + hdr[0] + hdr[3:5] + msg)
+        else:
+            raise Exception("Unrecognized version.")
         return msg + h
 
     def _tls_pad(self, s):
diff --git a/scapy/layers/tls/session.py b/scapy/layers/tls/session.py
index 7af0c305d7feb6ad61faf1b74f0fd4c9903a2e63..0c781552ccf1ef65e86f5465250331a4ca1c4019 100644
--- a/scapy/layers/tls/session.py
+++ b/scapy/layers/tls/session.py
@@ -16,18 +16,8 @@ from scapy.error import warning
 from scapy.packet import Packet
 from scapy.utils import repr_hex
 from scapy.layers.tls.crypto.compression import Comp_NULL
-from scapy.layers.tls.crypto.ffdh import FFDHParams
 from scapy.layers.tls.crypto.prf import PRF
 
-ecdsa_support = False
-try:
-    from scapy.layers.tls.crypto.ecdh import ECDHParams
-    ecdsa_support = True
-except ImportError:
-    import logging
-    log_loading = logging.getLogger("scapy.loading")
-    log_loading.info("Can't import python ecdsa lib. No default ECDH params.")
-
 # Note the following import may happen inside connState.__init__()
 # in order to avoid to avoid cyclical dependancies.
 # from scapy.layers.tls.crypto.suites import TLS_NULL_WITH_NULL_NULL
@@ -326,25 +316,24 @@ class tlsSession(object):
 
         ### Ephemeral key exchange parameters
 
-        # Default FFDH/ECDH parameters when acting as server.
-        # They are used for building Server(EC)DHParams, via .fill_missing().
-        # Note that there are two types of curves, Fp and char2.
-        # We use the same defaults for explicit and named Fp curves,
-        # but for now there is no support for char2 curves.
-        self.default_ffdh_params = FFDHParams()
-        if ecdsa_support:
-            self.default_ecdh_params = [ECDHParams(), None]
-        else:
-            self.default_ecdh_params = [None, None]
-
-        # Either an instance of FFDHParams or ECDHParams.
-        # Depending on which side of the connection we operate,
-        # one of these params will not hold 'priv' and 'secret' attributes.
-        # We did not use these intermediaries for RSAkx, as the 'priv' would
-        # equate the PrivKey, and the 'secret' the pre_master_secret.
-        # (It could have been useful for RSAkx export, though...)
-        self.server_kx_params = None
-        self.client_kx_params = None
+        ## XXX Explain why we need pubkey (which should be contained in privkey)
+        # also, params is used to hold params between the SKE and the CKE
+        self.server_kx_privkey = None
+        self.server_kx_pubkey = None
+        self.client_kx_privkey = None
+        self.client_kx_pubkey = None
+
+        self.client_kx_ffdh_params = None
+        self.client_kx_ecdh_params = None
+
+        ## Either an instance of FFDHParams or ECDHParams.
+        ## Depending on which side of the connection we operate,
+        ## one of these params will not hold 'priv' and 'secret' attributes.
+        ## We did not use these intermediaries for RSAkx, as the 'priv' would
+        ## equate the PrivKey, and the 'secret' the pre_master_secret.
+        ## (It could have been useful for RSAkx export, though...)
+        #self.server_kx_params = None
+        #self.client_kx_params = None
 
 
         ### Negotiated session parameters
diff --git a/test/cert.uts b/test/cert.uts
index 876286d26b414b9c59bb317fb0c2ac67a3b6e21e..69b981b5deff396dad3f7b69de8c1d31cb2db952 100644
--- a/test/cert.uts
+++ b/test/cert.uts
@@ -60,10 +60,10 @@ Jd5qtmDF2Zu+xrwrBRT0HBnPweDU+RsFxcyU/QxD9WYORzYarqxbcA==
 type(z) is PubKeyECDSA
 
 = PubKey class : checking curve
-z.key.curve.name == "SECP256k1"
+z.pubkey.curve.name == "secp256k1"
 
 = PubKey class : checking point value
-z.key.pubkey.point.x() == 104748656174769496952370005421566518252704263000192720134585149244759951661467L
+z.pubkey.public_numbers().x == 104748656174769496952370005421566518252704263000192720134585149244759951661467L
 
 
 ########### PrivKey class ###############################################
@@ -124,11 +124,24 @@ weDU+RsFxcyU/QxD9WYORzYarqxbcA==
 type(y) is PrivKeyECDSA
 
 = PrivKey class : checking public attributes
-assert(y.key.curve.name == "SECP256k1")
-y.key.privkey.public_key.point.y() == 86290575637772818452062569410092503179882738810918951913926481113065456425840L
+assert(y.key.curve.name == "secp256k1")
+y.key.public_key().public_numbers().y == 86290575637772818452062569410092503179882738810918951913926481113065456425840L
 
 = PrivKey class : checking private attributes
-y.key.privkey.secret_multiplier == 90719786431263082134670936670180839782031078050773732489701961692235185651857L
+y.key.private_numbers().private_value == 90719786431263082134670936670180839782031078050773732489701961692235185651857L
+
+
+########### PKCS crypto #############################################
+# these are legacy tests which should be removed eventually (see our pkcs1.py)
+
++ PKCS legacy tests
+
+= PKCS legacy : RSA signature & verification
+m = "Testing our PKCS legacy methods"
+s = x.sign_legacy(m, t="pkcs", h="tls")
+assert(s == "Zp\xd7`\x80\x97\x18\xc5t\xf1\xc2ZZ\x1e'\xee\xf1\x8d\xc2\xfat#Z\xde\xa5gnZ\xb5\xad\xc0?\xe0\xb5\xef\xe4\xc3Z\xe1>\x04@'<\xda\x8dtd\xd1Y\xdfm\x93\x88Sg\x9d\xc42\x87\x01\xd1\xfd\x03$C\x07A\x89\x86\xf4\x87*\x96\xd7\xf0\x0c\x19\x12\xf5\xa5\xa6\x07\x8b\xe6\x04c\x1a8\x18B\xfb\\t\xdf\x9f:\xdc\xa8\x0eg],I\xdc\xcc\x99\xa8\x93rl\xb3\xad\x91Kd\x92H\xf4\xfc\xc2\xf9\xf0\xe0`7\xb0\xf7E\x97\\k\xec\xfb\xff\xcff\xb3\xbf\xf6\xdf(\xae]\x01\x85\x06\xdd\x91\x91(\xf1,\x15c\x8b\x0b,\x1f \xc2\x1aN/\xeeJ$Qz\x9a\xc0\x8c\x99\x80\xe2\xba\xfdpu\x15p\x18;3\xff\x90\xbb$\xf1-VT\xe5'F\xed*0\xadXd9T!\x8au]\xc1\xe8\xf0\xb3\x04\x0f6b\xf2\x7f\xa8\x06}\x97*\xec\x97X\x94g\xd1\xc3a\x11\x1a4\xd0\x01\xb3yp\xdc\xdf5{\xb7\x9d\x97y`\xa6\xde\x03\xe9\xa6\x14s\x0fa")
+x_pub = PubKey((x.pubExp, x.modulus, x.modulusLen))
+x_pub.verify_legacy(m, s, t="pkcs", h="tls")
 
 
 ########### Cert class ##############################################
@@ -223,8 +236,9 @@ JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
 
 = Cert class : Checking ECDSA public key
 assert(type(y.pubKey) is PubKeyECDSA)
-assert(y.pubKey.key.curve.name == 'SECP384r1')
-y.pubKey.key.pubkey.point.x() == 3987178688175281746349180015490646948656137448666005327832107126183726641822596270780616285891030558662603987311874L
+pubkey = y.pubKey.pubkey
+assert(pubkey.curve.name == 'secp384r1')
+pubkey.public_numbers().x == 3987178688175281746349180015490646948656137448666005327832107126183726641822596270780616285891030558662603987311874L
 
 = Cert class : Checking ECDSA signature
 y.signatureValue == '0d\x020%\xa4\x81E\x02k\x12KutO\xc8#\xe3p\xf2ur\xde|\x89\xf0\xcf\x91ra\x9e^\x10\x92YV\xb9\x83\xc7\x10\xe78\xe9X&6}\xd5\xe44\x869\x020|6S\xf00\xe5bc:\x99\xe2\xb6\xa3;\x9b4\xfa\x1e\xda\x10\x92q^\x91\x13\xa7\xdd\xa4n\x92\xcc2\xd6\xf5!f\xc7/\xea\x96cjeE\x92\x95\x01\xb4'
diff --git a/test/tls.uts b/test/tls.uts
index 82513014f31cc95b003fd3a96fa3a653da154fcd..32af086dee88685a520f3b42b2171041659175b3 100644
--- a/test/tls.uts
+++ b/test/tls.uts
@@ -3,6 +3,7 @@
 # Try me with :
 # bash test/run_tests -t test/tls.uts -F
 
+~ crypto
 
 ###############################################################################
 ################################### Crypto ####################################
@@ -536,7 +537,7 @@ def _all_aes_gcm_tests():
     ciphers = []
     for t in [_aes128gcm_test_1, _aes128gcm_test_2]:
         c = Cipher_AES_128_GCM(key=t.k, salt=t.n[:4],
-                               nonce_explicit_init=pkcs_os2ip(t.n[4:]))
+                               nonce_explicit=pkcs_os2ip(t.n[4:]))
         ne = t.n[-c.nonce_explicit_len:]
         tup = ne, t.p, t.ct[-c.tag_len:]
         tmp1 = c.auth_decrypt(t.a, ne + t.ct, add_length=False) == tup
@@ -544,7 +545,7 @@ def _all_aes_gcm_tests():
         res = res and tmp1 and tmp2
     for t in [_aes256gcm_test_1, _aes256gcm_test_2]:
         c = Cipher_AES_256_GCM(key=t.k, salt=t.n[:4],
-                               nonce_explicit_init=pkcs_os2ip(t.n[4:]))
+                               nonce_explicit=pkcs_os2ip(t.n[4:]))
         ne = t.n[-c.nonce_explicit_len:]
         tup = ne, t.p, t.ct[-c.tag_len:]
         tmp1 = c.auth_decrypt(t.a, ne + t.ct, add_length=False) == tup
@@ -555,63 +556,64 @@ def _all_aes_gcm_tests():
 _all_aes_gcm_tests()
 
 
-+ Test AES-CCM
-= Crypto - AES cipher in CCM mode, checks from IEEE P1619.1
-~ combined_modes
-
-class _aes256ccm_test_1:
-    k= "\0"*32
-    n= "\0"*12
-    p= "\0"*16
-    a= ""
-    ct=("\xc1\x94\x40\x44\xc8\xe7\xaa\x95\xd2\xde\x95\x13\xc7\xf3\xdd\x8c" +
-       "\x4b\x0a\x3e\x5e\x51\xf1\x51\xeb\x0f\xfa\xe7\xc4\x3d\x01\x0f\xdb")
-
-class _aes256ccm_test_2:
-    k=("\xfb\x76\x15\xb2\x3d\x80\x89\x1d\xd4\x70\x98\x0b\xc7\x95\x84\xc8" +
-       "\xb2\xfb\x64\xce\x60\x97\x87\x8d\x17\xfc\xe4\x5a\x49\xe8\x30\xb7")
-    n= "\xdb\xd1\xa3\x63\x60\x24\xb7\xb4\x02\xda\x7d\x6f"
-    p= "\xa9"
-    a= "\x36"
-    ct="\x9d\x32\x61\xb1\xcf\x93\x14\x31\xe9\x9a\x32\x80\x67\x38\xec\xbd\x2a"
-
-class _aes256ccm_test_3:
-    k=("\xfb\x76\x15\xb2\x3d\x80\x89\x1d\xd4\x70\x98\x0b\xc7\x95\x84\xc8" +
-       "\xb2\xfb\x64\xce\x60\x97\x8f\x4d\x17\xfc\xe4\x5a\x49\xe8\x30\xb7")
-    n= "\xdb\xd1\xa3\x63\x60\x24\xb7\xb4\x02\xda\x7d\x6f"
-    p= "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e"
-    a= ""
-    ct=("\xcc\x88\x12\x61\xc6\xa7\xfa\x72\xb9\x6a\x17\x39\x17\x6b\x27\x7f" +
-       "\x34\x72\xe1\x14\x5f\x2c\x0c\xbe\x14\x63\x49\x06\x2c\xf0\xe4\x23")
-
-class _aes256ccm_test_4:
-    k=("\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" +
-       "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f")
-    n= "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b"
-    p=("\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +
-       "\x30\x31\x32\x33\x34\x35\x36\x37")
-    a=("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
-       "\x10\x11\x12\x13")
-    ct=("\x04\xf8\x83\xae\xb3\xbd\x07\x30\xea\xf5\x0b\xb6\xde\x4f\xa2\x21" +
-       "\x20\x34\xe4\xe4\x1b\x0e\x75\xe5\x9b\xba\x3f\x3a\x10\x7f\x32\x39" +
-       "\xbd\x63\x90\x29\x23\xf8\x03\x71")
-
-def _all_aes_ccm_tests():
-    from scapy.layers.tls.crypto.cipher_aead import Cipher_AES_256_CCM
-    res = True
-    ciphers = []
-    for t in [_aes256ccm_test_1, _aes256ccm_test_2,
-              _aes256ccm_test_3, _aes256ccm_test_4]:
-        c = Cipher_AES_256_CCM(key=t.k, salt=t.n[:4],
-                               nonce_explicit_init=pkcs_os2ip(t.n[4:]))
-        ne = t.n[-c.nonce_explicit_len:]
-        tup = ne, t.p, t.ct[-c.tag_len:]
-        tmp1 = c.auth_decrypt(t.a, ne + t.ct, add_length=False) == tup
-        tmp2 = c.auth_encrypt(t.p, t.a) == (ne + t.ct)
-        res = res and tmp1 and tmp2
-    return res
-
-_all_aes_ccm_tests()
+#XXX CCM remains to be added to the cryptography library
+#+ Test AES-CCM
+#= Crypto - AES cipher in CCM mode, checks from IEEE P1619.1
+#~ combined_modes
+#
+#class _aes256ccm_test_1:
+#    k= "\0"*32
+#    n= "\0"*12
+#    p= "\0"*16
+#    a= ""
+#    ct=("\xc1\x94\x40\x44\xc8\xe7\xaa\x95\xd2\xde\x95\x13\xc7\xf3\xdd\x8c" +
+#       "\x4b\x0a\x3e\x5e\x51\xf1\x51\xeb\x0f\xfa\xe7\xc4\x3d\x01\x0f\xdb")
+#
+#class _aes256ccm_test_2:
+#    k=("\xfb\x76\x15\xb2\x3d\x80\x89\x1d\xd4\x70\x98\x0b\xc7\x95\x84\xc8" +
+#       "\xb2\xfb\x64\xce\x60\x97\x87\x8d\x17\xfc\xe4\x5a\x49\xe8\x30\xb7")
+#    n= "\xdb\xd1\xa3\x63\x60\x24\xb7\xb4\x02\xda\x7d\x6f"
+#    p= "\xa9"
+#    a= "\x36"
+#    ct="\x9d\x32\x61\xb1\xcf\x93\x14\x31\xe9\x9a\x32\x80\x67\x38\xec\xbd\x2a"
+#
+#class _aes256ccm_test_3:
+#    k=("\xfb\x76\x15\xb2\x3d\x80\x89\x1d\xd4\x70\x98\x0b\xc7\x95\x84\xc8" +
+#       "\xb2\xfb\x64\xce\x60\x97\x8f\x4d\x17\xfc\xe4\x5a\x49\xe8\x30\xb7")
+#    n= "\xdb\xd1\xa3\x63\x60\x24\xb7\xb4\x02\xda\x7d\x6f"
+#    p= "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e"
+#    a= ""
+#    ct=("\xcc\x88\x12\x61\xc6\xa7\xfa\x72\xb9\x6a\x17\x39\x17\x6b\x27\x7f" +
+#       "\x34\x72\xe1\x14\x5f\x2c\x0c\xbe\x14\x63\x49\x06\x2c\xf0\xe4\x23")
+#
+#class _aes256ccm_test_4:
+#    k=("\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" +
+#       "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f")
+#    n= "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b"
+#    p=("\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +
+#       "\x30\x31\x32\x33\x34\x35\x36\x37")
+#    a=("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
+#       "\x10\x11\x12\x13")
+#    ct=("\x04\xf8\x83\xae\xb3\xbd\x07\x30\xea\xf5\x0b\xb6\xde\x4f\xa2\x21" +
+#       "\x20\x34\xe4\xe4\x1b\x0e\x75\xe5\x9b\xba\x3f\x3a\x10\x7f\x32\x39" +
+#       "\xbd\x63\x90\x29\x23\xf8\x03\x71")
+#
+#def _all_aes_ccm_tests():
+#    from scapy.layers.tls.crypto.cipher_aead import Cipher_AES_256_CCM
+#    res = True
+#    ciphers = []
+#    for t in [_aes256ccm_test_1, _aes256ccm_test_2,
+#              _aes256ccm_test_3, _aes256ccm_test_4]:
+#        c = Cipher_AES_256_CCM(key=t.k, salt=t.n[:4],
+#                               nonce_explicit_init=pkcs_os2ip(t.n[4:]))
+#        ne = t.n[-c.nonce_explicit_len:]
+#        tup = ne, t.p, t.ct[-c.tag_len:]
+#        tmp1 = c.auth_decrypt(t.a, ne + t.ct, add_length=False) == tup
+#        tmp2 = c.auth_encrypt(t.p, t.a) == (ne + t.ct)
+#        res = res and tmp1 and tmp2
+#    return res
+#
+#_all_aes_ccm_tests()
 
 
 + Test camellia
@@ -621,27 +623,27 @@ class _Camellia128_test:
     k= "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10"
     p= "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10"
     c= "\x67\x67\x31\x38\x54\x96\x69\x73\x08\x57\x06\x56\x48\xea\xbe\x43"
-
-class _Camellia192_test:
-    k=("\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10" +
-       "\x00\x11\x22\x33\x44\x55\x66\x77")
-    p= "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10"
-    c= "\xb4\x99\x34\x01\xb3\xe9\x96\xf8\x4e\xe5\xce\xe7\xd7\x9b\x09\xb9"
+    iv="\0"*16
 
 class _Camellia256_test:
     k=("\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10" +
        "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff")
     p= "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10"
     c= "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c\x20\xef\x7c\x91\x9e\x3a\x75\x09"
+    iv="\0"*16
 
 def _all_camellia_tests():
-    from scapy.layers.tls.crypto.camellia import Camellia
-    cam = Camellia()
+    from scapy.layers.tls.crypto.cipher_block import (Cipher_CAMELLIA_128_CBC,
+                                                      Cipher_CAMELLIA_256_CBC)
     res = True
-    for t in [_Camellia128_test, _Camellia192_test, _Camellia256_test]:
-        tmp = ((cam.encrypt(t.p, t.k) == t.c) and
-               (cam.decrypt(t.c, t.k) == t.p))
-        res = res and tmp
+    t = _Camellia128_test
+    tmp = (Cipher_CAMELLIA_128_CBC(t.k, t.iv).encrypt(t.p) == t.c and
+           Cipher_CAMELLIA_128_CBC(t.k, t.iv).decrypt(t.c) == t.p)
+    res = res and tmp
+    t = _Camellia256_test
+    tmp = (Cipher_CAMELLIA_256_CBC(t.k, t.iv).encrypt(t.p) == t.c and
+           Cipher_CAMELLIA_256_CBC(t.k, t.iv).decrypt(t.c) == t.p)
+    res = res and tmp
     return res
 
 _all_camellia_tests()
@@ -785,7 +787,7 @@ assert(isinstance(ske, TLSServerKeyExchange))
 p = ske.params
 assert(isinstance(p, ServerECDHNamedCurveParams))
 assert(p.named_curve == 0x0017)
-assert(p.point[:4] == '\x04\xc3\x9d\x1c' and p.point[-4:] == 'X\x19\x03u')
+assert(p.point[0] == '\x04' and p.point[1:5] == '\xc3\x9d\x1cD' and p.point[-4:] == 'X\x19\x03u')
 assert(ske.sig.sig_alg == 0x0601)
 ske.sig.sig_val[:4] == 'y\x8aQ\x11' and ske.sig.sig_val[-4:] == '`15\xef'
 
@@ -801,12 +803,12 @@ t = shd.tls_session
 assert(len(t.handshake_messages) == 6)
 assert(t.handshake_messages_parsed[-1] is shd)
 assert(t.tls_version == 0x0303)
-assert(isinstance(t.server_kx_params, ECDHParams))
-p = t.server_kx_params.pub
-assert(p[:4] == '\x04\xc3\x9d\x1c' and p[-4:] == 'X\x19\x03u')
-assert(isinstance(t.client_kx_params, ECDHParams))
-p = t.client_kx_params.other_pub
-assert(p[:4] == '\x04\xc3\x9d\x1c' and p[-4:] == 'X\x19\x03u')
+assert(t.client_kx_ffdh_params is None)
+assert(t.client_kx_ecdh_params is not None)
+pn = t.server_kx_pubkey.public_numbers()
+x = pkcs_i2osp(pn.x, pn.curve.key_size/8)
+y = pkcs_i2osp(pn.y, pn.curve.key_size/8)
+assert(x[:4] == '\xc3\x9d\x1cD' and y[-4:] == 'X\x19\x03u')
 assert(t.rcs.row == "read")
 assert(t.wcs.row == "write")
 t.rcs.ciphersuite.val == 0
@@ -829,9 +831,8 @@ isinstance(t5.payload.payload.payload, NoPayload)
 assert(isinstance(cke, TLSClientKeyExchange))
 k = cke.exchkeys
 assert(isinstance(k, ClientECDiffieHellmanPublic))
-assert(k.dh_Yclen == 65)
-assert(k.dh_Yc[:4] == '\x04\xd2\x07\xce' and k.dh_Yc[-4:] == '\xdc\x86[\xe7')
-t.server_kx_params.other_pub == pkcs_os2ip(k.dh_Yc)
+assert(k.ecdh_Yclen == 65)
+assert(k.ecdh_Yc[:4] == '\x04\xd2\x07\xce' and k.ecdh_Yc[-4:] == '\xdc\x86[\xe7')
 
 
 + Test TLS ChangeCipherSpec
diff --git a/scapy/layers/tls/examples/__init__.py b/test/tls/__init__.py
similarity index 100%
rename from scapy/layers/tls/examples/__init__.py
rename to test/tls/__init__.py
diff --git a/scapy/layers/tls/examples/client_simple.py b/test/tls/example_client.py
similarity index 83%
rename from scapy/layers/tls/examples/client_simple.py
rename to test/tls/example_client.py
index c1f4f9d00ac715ecfac9cd9f56aac8f545ebc734..3ed4256203a246ef25c6001efca50859ad329f56 100755
--- a/scapy/layers/tls/examples/client_simple.py
+++ b/test/tls/example_client.py
@@ -10,10 +10,16 @@ For instance, "sudo ./client_simple.py c014" will try to connect to any TLS
 server at 127.0.0.1:4433, with suite TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA.
 """
 
+import os
 import sys
+
 from scapy.layers.tls.automaton import TLSClientAutomaton
 from scapy.layers.tls.handshake import TLSClientHello
 
+basedir = os.path.abspath(os.path.join(os.path.dirname(__file__),"../../"))
+sys.path=[basedir]+sys.path
+
+
 if len(sys.argv) == 2:
     ch = TLSClientHello(ciphers=int(sys.argv[1], 16))
 else:
diff --git a/scapy/layers/tls/examples/server_simple.py b/test/tls/example_server.py
similarity index 70%
rename from scapy/layers/tls/examples/server_simple.py
rename to test/tls/example_server.py
index f89aa4f99edb77e260f7598282c0d791ca909cad..30ffd2748bfe3451a8dbd199d978f5c3395e3512 100755
--- a/scapy/layers/tls/examples/server_simple.py
+++ b/test/tls/example_server.py
@@ -11,17 +11,22 @@ any TLS client connection. If provided, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
 will be preferred to any other suite the client might propose.
 """
 
+import os
 import sys
 
 from scapy.layers.tls.automaton import TLSServerAutomaton
 
+basedir = os.path.abspath(os.path.join(os.path.dirname(__file__),"../../"))
+sys.path=[basedir]+sys.path
+
+
 if len(sys.argv) == 2:
     pcs = int(sys.argv[1], 16)
 else:
     pcs = None
 
-t = TLSServerAutomaton(mycert='pki_test/srv_cert.pem',
-                       mykey='pki_test/srv_key.pem',
+t = TLSServerAutomaton(mycert=basedir+'/test/tls/pki/srv_cert.pem',
+                       mykey=basedir+'/test/tls/pki/srv_key.pem',
                        preferred_ciphersuite=pcs)
 t.run()
 
diff --git a/scapy/layers/tls/examples/pki_test/ca_cert.pem b/test/tls/pki/ca_cert.pem
similarity index 100%
rename from scapy/layers/tls/examples/pki_test/ca_cert.pem
rename to test/tls/pki/ca_cert.pem
diff --git a/scapy/layers/tls/examples/pki_test/ca_key.pem b/test/tls/pki/ca_key.pem
similarity index 100%
rename from scapy/layers/tls/examples/pki_test/ca_key.pem
rename to test/tls/pki/ca_key.pem
diff --git a/scapy/layers/tls/examples/pki_test/cli_cert.pem b/test/tls/pki/cli_cert.pem
similarity index 100%
rename from scapy/layers/tls/examples/pki_test/cli_cert.pem
rename to test/tls/pki/cli_cert.pem
diff --git a/scapy/layers/tls/examples/pki_test/cli_key.pem b/test/tls/pki/cli_key.pem
similarity index 100%
rename from scapy/layers/tls/examples/pki_test/cli_key.pem
rename to test/tls/pki/cli_key.pem
diff --git a/scapy/layers/tls/examples/pki_test/srv_cert.pem b/test/tls/pki/srv_cert.pem
similarity index 100%
rename from scapy/layers/tls/examples/pki_test/srv_cert.pem
rename to test/tls/pki/srv_cert.pem
diff --git a/scapy/layers/tls/examples/pki_test/srv_key.pem b/test/tls/pki/srv_key.pem
similarity index 100%
rename from scapy/layers/tls/examples/pki_test/srv_key.pem
rename to test/tls/pki/srv_key.pem
diff --git a/test/run_tests_tls_netaccess b/test/tls/run_tests_tls_netaccess
similarity index 69%
rename from test/run_tests_tls_netaccess
rename to test/tls/run_tests_tls_netaccess
index 7c11798b3ec050e3256ef8ea51f1bc3503f5bf0e..0d6a87d24b7c744c578ea901cf0d4901f8f3702a 100755
--- a/test/run_tests_tls_netaccess
+++ b/test/tls/run_tests_tls_netaccess
@@ -4,32 +4,32 @@
 function test_tls_server {
   msg=$1
   suite=$2
-  exclude_versions=$3
+  version=$3
   EXIT_CODE=test_tls_server_tmp_code
   OSSL_STDO=test_tls_server_tmp_openssl_stdout
   OSSL_STDE=test_tls_server_tmp_openssl_stderr
   SCAPY_STDE=test_tls_server_tmp_scapy_stderr
 
   echo "1" > $EXIT_CODE
-  ($TRAVIS_SUDO ./tls_test_server.py "$msg" 2>$SCAPY_STDE; echo $? > $EXIT_CODE) &
-  sleep 1         # wait for the server to start
+  ($TRAVIS_SUDO python travis_test_server.py "$msg" 2>$SCAPY_STDE; echo $? > $EXIT_CODE) &
+  sleep 2         # wait for the server to start
 
-  echo -n "$msg" | openssl s_client -cipher $suite $exclude_versions 1>$OSSL_STDO 2>$OSSL_STDE
+  echo -n "$msg" | sudo openssl s_client -cipher $suite $version 1>$OSSL_STDO 2>$OSSL_STDE
   sleep 0.5       # wait for the connection to be established, then torn down
 
-  if [[ -z $exclude_versions ]];
+  if [[ -z $version ]];
   then
-    versions=""
+    version=""
   else
-    versions="and option $exclude_versions"
+    version="and option $version"
   fi
 
   if [ $(<$EXIT_CODE) == "0" ];
   then
-    echo "PASSED - TLS server test with cipher suite $suite $versions"
+    echo "PASSED - TLS server test with cipher suite $suite $version"
     rm -f $EXIT_CODE $OSSL_STDO $OSSL_STDE $SCAPY_STDE
   else
-    echo "FAILED - TLS server test with cipher suite $suite $versions"
+    echo "FAILED - TLS server test with cipher suite $suite $version"
     echo -e "\n###\nHere are scapy writings to stderr:\n"
     cat $SCAPY_STDE
     echo -e "\nHere are openssl writings to stdout & stderr:\n"
@@ -55,10 +55,10 @@ function test_tls_client {
   CLI_STDO=test_tls_client_tmp_client_stdout
   CLI_STDE=test_tls_client_tmp_client_stderr
 
-  ($TRAVIS_SUDO ./tls_test_server.py "$msg" 1>$SRV_STDO 2>$SRV_STDE; echo $? > $EXIT_CODE) &
+  ($TRAVIS_SUDO python travis_test_server.py "$msg" 1>$SRV_STDO 2>$SRV_STDE; echo $? > $EXIT_CODE) &
   sleep 1         # wait for the server to start
 
-  $TRAVIS_SUDO ./tls_test_client.py "$msg" $suite $version 1>$CLI_STDO 2>$CLI_STDE
+  $TRAVIS_SUDO python travis_test_client.py "$msg" $suite $version 1>$CLI_STDO 2>$CLI_STDE
   sleep 0.5
 
   if [[ -z $version ]];
@@ -88,19 +88,16 @@ function test_tls_client {
 
 
 echo "TLS server automaton tests"
-test_tls_server "Testing TLS server with TLS 1.0 and TLS_RSA_WITH_RC4_128_SHA" "RC4-SHA" "-no_tls1_2 -no_tls1_1"
-test_tls_server "Testing TLS server with TLS 1.2 and TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" "DHE-RSA-AES128-SHA256"
-if [ "$TEST_COMBINED_MODES" == "yes" ]; then
-  test_tls_server "Testing TLS server with TLS 1.2 and TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" "ECDHE-RSA-AES256-GCM-SHA384"
-fi
+test_tls_server "Testing TLS server with TLS 1.0 and TLS_RSA_WITH_RC4_128_SHA" "RC4-SHA" "-tls1"
+test_tls_server "Testing TLS server with TLS 1.2 and TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" "DHE-RSA-AES128-SHA256" "-tls1_2"
+test_tls_server "Testing TLS server with TLS 1.2 and TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" "ECDHE-RSA-AES256-GCM-SHA384" "-tls1_2"
 echo
 sleep 1
 
 echo "TLS client automaton tests"
-test_tls_client "Testing TLS client with TLS 1.0 and TLS_RSA_WITH_RC4_128_SHA" "0005" "0301"
+test_tls_client "Testing TLS client with TLS 1.0 and TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA" "0088" "0301"
 test_tls_client "Testing TLS client with TLS 1.1 and TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" "c013" "0302"
-if [ "$TEST_COMBINED_MODES" == "yes" ]; then
-  test_tls_client "Testing TLS server with TLS 1.2 and TLS_DHE_RSA_WITH_AES_256_CCM" "c09f" "0303"
-fi
+test_tls_client "Testing TLS server with TLS 1.2 and TLS_DHE_RSA_WITH_AES_128_GCM_SHA256" "009e" "0303"
+test_tls_client "Testing TLS server with SSLv3 and TLS_RSA_EXPORT_WITH_RC4_40_MD5" "0003" "0300"
 
 
diff --git a/test/tls_test_client.py b/test/tls/travis_test_client.py
similarity index 98%
rename from test/tls_test_client.py
rename to test/tls/travis_test_client.py
index f4a16c37320c5963152c7bce65d25eae411d8d42..edfa5a5bf962c2eadfba09c2d670ab70f35e16a6 100755
--- a/test/tls_test_client.py
+++ b/test/tls/travis_test_client.py
@@ -16,12 +16,13 @@ Reception of the exact send_data on the server is to be checked externally.
 import os
 import sys
 
-basedir = os.path.abspath(os.path.join(os.path.dirname(__file__),"../"))
-sys.path=[basedir]+sys.path
-
 from scapy.layers.tls.automaton import TLSClientAutomaton
 from scapy.layers.tls.handshake import TLSClientHello
 
+basedir = os.path.abspath(os.path.join(os.path.dirname(__file__),"../../"))
+sys.path=[basedir]+sys.path
+
+
 send_data = cipher_suite_code = version = None
 
 if len(sys.argv) >= 2:
diff --git a/test/tls_test_server.py b/test/tls/travis_test_server.py
similarity index 89%
rename from test/tls_test_server.py
rename to test/tls/travis_test_server.py
index bb9f4e669007d6f31ea14048a020c6dba58fd89e..4db52f20df8300de51d1c100355ae49d87199fe9 100755
--- a/test/tls_test_server.py
+++ b/test/tls/travis_test_server.py
@@ -18,11 +18,11 @@ import sys
 from contextlib import contextmanager
 from StringIO import StringIO
 
-basedir = os.path.abspath(os.path.join(os.path.dirname(__file__),"../"))
-sys.path=[basedir]+sys.path
-
 from scapy.layers.tls.automaton import TLSServerAutomaton
 
+basedir = os.path.abspath(os.path.join(os.path.dirname(__file__),"../../"))
+sys.path=[basedir]+sys.path
+
 
 @contextmanager
 def captured_output():
@@ -56,10 +56,9 @@ else:
     expected_data = None
 
 with captured_output() as (out, err):
-    t = TLSServerAutomaton(mycert=basedir+'/scapy/layers/tls/examples/pki_test/srv_cert.pem',
-                           mykey=basedir+'/scapy/layers/tls/examples/pki_test/srv_key.pem')
+    t = TLSServerAutomaton(mycert=basedir+'/test/tls/pki/srv_cert.pem',
+                           mykey=basedir+'/test/tls/pki/srv_key.pem')
     t.run()
 
 check_output_for_data(out, err, expected_data)
 
-