Quickstart

Installing dependencies

To execute tlsfuzzer test scripts you need a python environment. This framework supports all versions of python since 2.6 except 3.0, 3.1, and 3.2. Check the Travis CI to see explicitly tested environments.

Python supports installing modules system-wide, to the user directory, or to a virtual environment. With tlsfuzzer dependencies you can use either option, though some work better than others.

Note

Execute all example commands in the root directory of tlsfuzzer repository checkout.

Hint

If you plan to develop, not just use tlsfuzzer, use the instructions in the Installation chapter. If you want to try several scripts before installing full development environment, for swift clean up, use the virtual environment installation method.

System wide installation

Installation of modules system-wide allows for easy execution of scripts later. This does “pollute” the system and conflicts with python modules managed by the OS package manager though. It also requires administrative privileges on the system. You should use this approach if you plan to keep using tlsfuzzer for a long time.

To install all dependencies execute as root:

pip install -r requirements.txt

Warning

Different versions of python keep their modules separate, as such, installing packages with pip from Python 2.7 doesn’t make them available for Python 3.7 and vice versa.

User directory installation

If you don’t have administrative privileges on the system, you can install python modules to your local home directory. This doesn’t make them usable for other users of the system. Unlike the virtual environment approach, it does make running with wrong python environment less probable.

To install all dependencies to user directory execute:

pip install --user -r requirements.txt

For Python 3.7 this places the modules to the ~/.local/lib/python3.7/site-packages/ directory. For Python 2.7 this places the modules to the ~/.local/lib/python2.7/site-packages/ directory.

Virtual environment installation

You can find detailed description of Python virtual environments in the official documentation. Deleting a virtual environment doesn’t influence anything outside of it, making it safe to do after you don’t need it.

To create a virtual environment in a new directory, for example ~/tlsfuzzer-env, execute:

python -m venv ~/tlsfuzzer-env

To install all dependencies in that virtual environment execute:

~/tlsfuzzer-env/bin/pip install -r requirements.txt

Note

When you use virtual environments you must specify the python executable from the virtual environment, not the system-wide one. Use ~/tlsfuzzer-env/bin/python instead of python to execute the test scripts in following examples. You can also “activate” an environment to make python and pip point to commands from the virtual environment, this modifies only the current session though. To do that execute source ~/tlsfuzzer-env/bin/activate.

Starting an OpenSSL server

To have a server to test against you can use OpenSSL. Example below shows how to setup a configuration with a self-signed certificate. You can execute the scripts against any network-accessible server, if you have one already running, you can skip this part.

Generate certificates

Most test cases require a server configured with a certificate (the ones that require more complex PKIX setup print it when executed).

To create a simple self-signed certificate and key, execute the following OpenSSL command:

openssl req -x509 -newkey rsa -keyout /tmp/localhost.key \
-out /tmp/localhost.crt -subj /CN=localhost -nodes -batch \
-days 3650

Start the server

Once you have a key and a certificate, you can use them to configure a test server with support for minimal subset of HTTP:

openssl s_server -key /tmp/localhost.key -cert /tmp/localhost.crt -www

Executing a test case

With a TLS server available, you can start executing test cases against it.

To verify that a server supports TLS 1.2 or earlier, you can use the test-conversation.py script.

To execute the script against a server running on localhost on port 4433, as it’s set-up in the preceding OpenSSL example, execute the following command in the checkout of tlsfuzzer repository:

PYTHONPATH=. python scripts/test-conversation.py

This command should provide the following output if everything went fine:

sanity ...
OK

sanity ...
OK

Basic conversation script; check basic communication with typical
cipher, TLS 1.2 or earlier and RSA key exchange (or (EC)DHE if
-d option is used)

Test end
====================
version: 8
====================
TOTAL: 2
SKIP: 0
PASS: 2
XFAIL: 0
FAIL: 0
XPASS: 0
====================

All the test scripts support at least --help option. For this script it will provide the following information:

Usage: <script-name> [-h hostname] [-p port] [[probe-name] ...]
 -h hostname    name of the host to run the test against
                localhost by default
 -p port        port number to use for connection, 4433 by default
 probe-name     if present, will run only the probes with given
                names and not all of them, e.g "sanity"
 -e probe-name  exclude the probe from the list of the ones run
                may be specified multiple times
 -x probe-name  expect the probe to fail. When such probe passes despite being marked like this
                it will be reported in the test summary and the whole script will fail.
                May be specified multiple times.
 -X message     expect the `message` substring in exception raised during
                execution of preceding expected failure probe
                usage: [-x probe-name] [-X exception], order is compulsory!
 -n num         run 'num' or all(if 0) tests instead of default(all)
                ("sanity" tests are always executed)
 -d             negotiate (EC)DHE instead of RSA key exchange, send
                additional extensions, usually used for (EC)DHE ciphers
 -C ciph        Use specified ciphersuite. Either numerical value or
                IETF name.
 --help         this message

Almost all scripts support this set of command line options.

Executing a test case to verify TLS 1.3 support works similar:

PYTHONPATH=. python scripts/test-tls13-conversation.py

This produces similar output:

sanity ...
OK

sanity ...
OK

Basic communication test with TLS 1.3 server
Check if communication with typical group and cipher works with
the TLS 1.3 server.

Test end
====================
version: 7
====================
TOTAL: 2
SKIP: 0
PASS: 2
XFAIL: 0
FAIL: 0
XPASS: 0
====================

Similarly to the TLS 1.2 script, this one supports a set of options:

Usage: <script-name> [-h hostname] [-p port] [[probe-name] ...]
 -h hostname    name of the host to run the test against
                localhost by default
 -p port        port number to use for connection, 4433 by default
 probe-name     if present, will run only the probes with given
                names and not all of them, e.g "sanity"
 -e probe-name  exclude the probe from the list of the ones run
                may be specified multiple times
 -x probe-name  expect the probe to fail. When such probe passes despite being marked like this
                it will be reported in the test summary and the whole script will fail.
                May be specified multiple times.
 -X message     expect the `message` substring in exception raised during
                execution of preceding expected failure probe
                usage: [-x probe-name] [-X exception], order is compulsory!
 -n num         run 'num' or all(if 0) tests instead of default(all)
                ("sanity" tests are always executed)
 -C ciph        Use specified ciphersuite. Either numerical value or
                IETF name.
 --help         this message

As cryptographic parameter negotiation happens differently in TLS 1.3 than it does in TLS 1.2, the TLS 1.3 scripts generally don’t support the -d option.

Note

When a particular test case in the script observes an expected behaviour it prints an “OK” status, if all test cases in a test script do that, the script passes. Expected behaviour doesn’t mean a successful connection. Negative test cases expect a failed TLS handshake or a particular kind of connection abortion.