Skip to content

Commit

Permalink
Merge pull request #653 from tomato42/connection-state
Browse files Browse the repository at this point in the history
Document connection state handling
  • Loading branch information
tomato42 committed Mar 11, 2020
2 parents c5727aa + f250d2c commit 55036db
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 9 deletions.
142 changes: 142 additions & 0 deletions docs/source/connection-state.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
================
Connection state
================

Processing of nodes like :py:class:`~tlsfuzzer.expect.ExpectServerHello`
or :py:class:`~tlsfuzzer.messages.ClientKeyExchangeGenerator` updates the
state of the connection: the encryption keys, handshake hashes, and so on.

To perform more complex handshakes, you need to take more direct control
of some of those variables.

Opening and closing the connection
==================================

To open a :term:`TCP`: connection use the
:py:class:`~tlsfuzzer.messages.Connect` node.
It provides also ability to control the record layer protocol version
using the ``version`` parameter and setting the amount of time runner waits
for messages from peer using the ``timeout`` parameter.

In contrast, the :py:class:`~tlsfuzzer.messages.Close` node closes the
:term:`TCP` connection and doesn't accept any parameters.

For example, to start session resumption, you need to close the old connection
and open a new one.

You can find a usage example of them in:
`test-tls13-session-resumption.py
<https://github.com/tomato42/tlsfuzzer/blob/master/scripts/scripts/test-tls13-session-resumption.py>`_.


Handshake hashes
================

:term:`TLS` uses a running hash of all exchanged messages to verify the
integrity of the handshake and to perform signatures in CertificateVerify
messages.

Before session resumption or renegotiation, you need to zero out, or reset,
those hashes.

The :py:class:`tlsfuzzer.messages.ResetHandshakeHashes` node allows to do that.

For example, to start renegotiation right after finishing a handshake use
the following code:

.. code:: python
node = node.add_child(ExpectChangeCipherSpec())
node = node.add_child(ExpectFinished())
node = node.add_child(ResetHandshakeHashes())
node = node.add_child(ClientHelloGenerator(ciphers,
session_id=bytearray(0),
extensions=ext))
You can find a usage example in:
`test-legacy-renegotiation.py
<https://github.com/tomato42/tlsfuzzer/blob/master/scripts/scripts/test-legacy-renegotiation.py>`_.

Renegotiation info
==================

During secure renegotiation peers send the value of last Finished message
in the ``renegotiation_info`` extension.
If you use automatic generators for processing this extension, you
need to reset the values from Finished before a new handshake
using :py:class:`~tlsfuzzer.messages.ResetRenegotiationInfo`.

For example, to start session resumption using session IDs use the following
code:

.. code:: python
...
node = node.add_child(ExpectClose())
node = node.add_child(Close())
node = node.add_child(Connect(host, port))
node = node.add_child(ResetHandshakeHashes())
node = node.add_child(ResetRenegotiationInfo())
node = node.add_child(ClientHelloGenerator(
ciphers,
extensions={ExtensionType.renegotiation_info:None}))
You can find a usage example in:
`test-sessionID-resumption.py
<https://github.com/tomato42/tlsfuzzer/blob/master/scripts/scripts/test-sessionID-resumption.py>`_.

.. _clearing-encryption-settings:

Clearing encryption settings
============================

Tlsfuzzer allows also disabling encryption for sent messages.
To reset the context for sending records, use the
:py:class:`~tlsfuzzer.messages.ResetWriteConnectionState`.

For example, to send an unencrypted Finished message use the following code:

.. code:: python
...
node = node.add_child(ExpectFinished())
node = node.add_child(ResetWriteConnectionState())
node = node.add_child(FinishedGenerator())
You can find a usage example in
`test-tls13-finished-plaintext.py
<https://github.com/tomato42/tlsfuzzer/blob/master/scripts/scripts/test-tls13-finished-plaintext.py>`_.

Clearing post-handshake authentication context
==============================================

A client associates its reply to the server's CertificateRequest message
by sending it with the same context.
To pass that association around
:py:class:`~tlsfuzzer.expect.ExpectCertificateRequest`,
:py:class:`~tlsfuzzer.messages.CertificateGenerator`,
:py:class:`~tlsfuzzer.messages.CertificateVerifyGenerator`,
and :py:class:`~tlsfuzzer.messages.FinishedGenerator` accept the ``context``
keyword argument.
If the runner executes the same conversation multiple times, as it does with
``sanity`` test cases, that context needs resetting between runs.
:py:class:`~tlsfuzzer.messages.ClearContext` provides this functionality.

For example, to handle a single post-handshake authentication use the
following code:

.. code:: python
...
context = []
node = node.add_child(ExpectCertificateRequest(context=context))
node = node.add_child(CertificateGenerator(
X509CertChain([cert]), context=context))
node = node.add_child(CertificateVerifyGenerator(
private_key, context=context))
node = node.add_child(FinishedGenerator(context=context))
node = node.add_child(ClearContext(context))
You can find a usage example in
`test-tls13-post-handshake-auth.py
<https://github.com/tomato42/tlsfuzzer/blob/master/scripts/scripts/test-tls13-post-handshake-auth.py>`_.
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ to see wanted, but not yet implemented features.
writing-tests
advanced-decision-graph
modifying-messages
connection-state
glossary
modules

Expand Down
4 changes: 4 additions & 0 deletions docs/source/modifying-messages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ For example, to send an empty ClientHello message, write:
You can find a usage example in:
`test-aesccm.py <https://github.com/tomato42/tlsfuzzer/blob/master/scripts/test-aesccm.py>`_.

.. tip::
If you want to send an otherwise valid message, only as plaintext, not
encrypted, see the :ref:`clearing-encryption-settings` section.

Creating arbitrary messages
---------------------------

Expand Down
3 changes: 1 addition & 2 deletions scripts/test-client-hello-max-size.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
from tlsfuzzer.runner import Runner
from tlsfuzzer.messages import Connect, ClientHelloGenerator, \
ClientKeyExchangeGenerator, ChangeCipherSpecGenerator, \
FinishedGenerator, ApplicationDataGenerator, AlertGenerator, \
ResetHandshakeHashes, Close, ResetRenegotiationInfo
FinishedGenerator, ApplicationDataGenerator, AlertGenerator
from tlsfuzzer.expect import ExpectServerHello, ExpectCertificate, \
ExpectServerHelloDone, ExpectChangeCipherSpec, ExpectFinished, \
ExpectAlert, ExpectApplicationData, ExpectClose, \
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-legacy-renegotiation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from tlsfuzzer.messages import Connect, ClientHelloGenerator, \
ClientKeyExchangeGenerator, ChangeCipherSpecGenerator, \
FinishedGenerator, ApplicationDataGenerator, AlertGenerator, \
ResetHandshakeHashes, Close
ResetHandshakeHashes
from tlsfuzzer.expect import ExpectServerHello, ExpectCertificate, \
ExpectServerHelloDone, ExpectChangeCipherSpec, ExpectFinished, \
ExpectAlert, ExpectApplicationData, ExpectClose, \
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-renegotiation-disabled-client-cert.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from tlsfuzzer.messages import Connect, ClientHelloGenerator, \
ClientKeyExchangeGenerator, ChangeCipherSpecGenerator, \
FinishedGenerator, ApplicationDataGenerator, AlertGenerator, \
fuzz_message, ResetHandshakeHashes, Close, ResetRenegotiationInfo, \
fuzz_message, ResetHandshakeHashes, \
CertificateGenerator, CertificateVerifyGenerator
from tlsfuzzer.expect import ExpectServerHello, ExpectCertificate, \
ExpectServerHelloDone, ExpectChangeCipherSpec, ExpectFinished, \
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-renegotiation-disabled.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from tlsfuzzer.messages import Connect, ClientHelloGenerator, \
ClientKeyExchangeGenerator, ChangeCipherSpecGenerator, \
FinishedGenerator, ApplicationDataGenerator, AlertGenerator, \
ResetHandshakeHashes, Close, ResetRenegotiationInfo
ResetHandshakeHashes
from tlsfuzzer.expect import ExpectServerHello, ExpectCertificate, \
ExpectServerHelloDone, ExpectChangeCipherSpec, ExpectFinished, \
ExpectAlert, ExpectApplicationData, ExpectClose
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-sslv2-force-cipher-3des.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from tlsfuzzer.messages import Connect, ClientHelloGenerator, \
ChangeCipherSpecGenerator, \
FinishedGenerator, ApplicationDataGenerator, AlertGenerator, \
ClientMasterKeyGenerator, Close
ClientMasterKeyGenerator
from tlsfuzzer.expect import ExpectServerHello, ExpectCertificate, \
ExpectServerHelloDone, ExpectChangeCipherSpec, \
ExpectAlert, ExpectClose, ExpectApplicationData, ExpectServerHello2, \
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-sslv2-force-cipher-non3des.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from tlsfuzzer.messages import Connect, ClientHelloGenerator, \
ChangeCipherSpecGenerator, \
FinishedGenerator, ApplicationDataGenerator, AlertGenerator, \
ClientMasterKeyGenerator, Close
ClientMasterKeyGenerator
from tlsfuzzer.expect import ExpectServerHello, ExpectCertificate, \
ExpectServerHelloDone, ExpectChangeCipherSpec, \
ExpectAlert, ExpectClose, ExpectApplicationData, ExpectServerHello2, \
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-sslv2-force-export-cipher.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from tlsfuzzer.messages import Connect, ClientHelloGenerator, \
ChangeCipherSpecGenerator, \
FinishedGenerator, ApplicationDataGenerator, AlertGenerator, \
ClientMasterKeyGenerator, Close
ClientMasterKeyGenerator
from tlsfuzzer.expect import ExpectServerHello, ExpectCertificate, \
ExpectServerHelloDone, ExpectChangeCipherSpec, \
ExpectAlert, ExpectClose, ExpectApplicationData, ExpectServerHello2, \
Expand Down
11 changes: 10 additions & 1 deletion tlsfuzzer/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,16 @@ class Connect(Command):
"""Object used to connect to a TCP server."""

def __init__(self, hostname, port, version=(3, 0), timeout=5):
"""Provide minimal settings needed to connect to other peer."""
"""
Provide minimal settings needed to connect to other peer.
:param str hostname: host name of the server to connect to
:param int port: :term:`TCP` port number to connect to
:param tuple(int,int) version: the protocol version used in the
record layer for the initial messages
:param float timeout: amount of time to wait while expecting a message
before aborting the connection, in seconds
"""
super(Connect, self).__init__()
self.hostname = hostname
self.port = port
Expand Down

0 comments on commit 55036db

Please sign in to comment.