aboutsummaryrefslogtreecommitdiff
path: root/protocol_transport.md
diff options
context:
space:
mode:
Diffstat (limited to 'protocol_transport.md')
-rw-r--r--protocol_transport.md128
1 files changed, 128 insertions, 0 deletions
diff --git a/protocol_transport.md b/protocol_transport.md
new file mode 100644
index 0000000..7915e29
--- /dev/null
+++ b/protocol_transport.md
@@ -0,0 +1,128 @@
+# tomsg transport protocol
+
+This is the specification for the lower-level transport protocol that underlies
+the application-level protocol described in `protocol.md`. This transport is
+used for communication between a client and the server.
+
+If at any point one of the parties breaks the protocol, the socket and transport
+should be closed.
+
+## Size assumptions
+
+The protocol makes a few assumptions about lengths of certain values in the
+libsodium API. An implementation of the protocol should verify that these
+assumptions still hold when the application is finally run.
+
+- `crypto_secretstream_xchacha20poly1305_KEYBYTES` = 32
+- `crypto_secretstream_xchacha20poly1305_HEADERBYTES` = 24
+- `crypto_kx_SESSIONKEYBYTES` >= 32
+- `crypto_kx_PUBLICKEYBYTES` = 32
+- `crypto_kx_SECRETKEYBYTES` = 32
+
+## Message types
+
+- ClientHello:
+ - 16 bytes magic: `tomsg v01 client`
+ - 32 bytes client public key
+- ServerHello:
+ - 16 bytes magic: `tomsg v01 server`
+ - 32 bytes server public key
+ - 24 bytes server->client libsodium secretstream header
+- ClientHello2:
+ - 8 bytes magic: `cheader0`
+ - 24 bytes client->server libsodium secretstream header
+- DataMessage:
+ - 8 bytes magic: `datamsg0`
+ - 8 bytes (unsigned little-endian) message length = N
+ - N bytes data
+
+## Initialisation sequence
+
+### Client initialisation sequence
+
+The following handshake is performed in order to set up two libsodium
+secretstreams, one for client->server communication (a push stream) and one for
+server->client communication (a pull stream).
+
+1. Generate a keypair using `crypto_kx_keypair`. These keys are referred to as
+ the client public and secret keys.
+2. Send a ClientHello message.
+3. Receive a ServerHello message.
+ - Check that the magic is correct for this version of the transport protocol.
+ - Use `crypto_kx_client_session_keys` to compute the client->server and
+ server->client encryption keys.
+ - Use `crypto_secretstream_xchacha20poly1305_init_push` to create the
+ client->server libsodium push secretstream using the client->server
+ encryption key.
+ - Use `crypto_secretstream_xchacha20poly1305_init_pull` to create the
+ server->client libsodium pull secretstream using the server->client
+ encryption key and header.
+4. Send a ClientHello2 message.
+
+### Server initialisation sequence
+
+The following handshake is performed in order to set up two libsodium
+secretstreams, one for server->client communication (a push stream) and one for
+client->server communication (a pull stream).
+
+1. Generate a keypair using `crypto_kx_keypair`. These keys are referred to as
+ the server public and secret keys.
+2. Receive a ClientHello message.
+ - Check that the magic is correct for this version of the transport protocol.
+ - Use `crypto_kx_server_session_keys` to compute the client->server and
+ server->client symmetric keys.
+ - Use `crypto_secretstream_xchacha20poly1305_init_push` to create the
+ server->client libsodium push secretstream using the server->client
+ encryption key.
+3. Send a ServerHello message.
+4. Receive a ClientHello2 message.
+ - Check that the magic is correct for this version of the transport protocol.
+ - Use `crypto_secretstream_xchacha20poly1305_init_pull` to create the
+ client->server libsodium pull secretstream using the client->server
+ encryption key and header.
+
+## Data exchange
+
+At this point, we can reconcile the two halves of the protocol: both parties now
+have a push secretstream for transmission to the other party, and a pull
+secretstream for reception from the other party.
+
+### Receiving a message
+
+At all times, the current party can receive a DataMessage message. To handle the
+message, use `crypto_secretstream_xchacha20poly1305_pull` to decrypt the
+encrypted data in the message, and observe the tag.
+- If the tag is 0:
+ - Return the decrypted data to the application.
+- If the tag is `crypto_secretstream_xchacha20poly1305_TAG_FINAL`:
+ - Close the socket and consider the transport closed. Report this to the
+ application.
+
+### Sending a message
+
+When the current party wants to send a message, use
+`crypto_secretstream_xchacha20poly1305_push`, with no additional data and
+`tag` = 0, to encrypt the message in the push secretstream. Then send the
+encrypted result in a DataMessage message to the other party.
+
+### Ending the transport
+
+When the current party wants to end the transport and close the socket, one has
+a choice between a graceful shutdown and an improper shutdown (just closing the
+socket and forgetting about the connection). Sometimes an improper shutdown
+cannot be avoided, e.g. if the application is killed by the operating system,
+but a graceful shutdown is always preferred.
+
+To perform a graceful shutdown, use `crypto_secretstream_xchacha20poly1305_push`
+on the push secretstream to encrypt the empty string with no additional data and
+`tag` = `crypto_secretstream_xchacha20poly1305_TAG_FINAL`. Then send the
+encrypted result in a DataMessage message to the other party.
+
+After the DataMessage message is successfully sent, the socket can be closed and
+the transport considered ended.
+
+
+# SSH notes
+
+- Use libssh, not libssh2
+- `ssh_message.type` has type `enum ssh_requests_e`, not `int`