diff options
author | Tom Smeding <tom.smeding@gmail.com> | 2020-06-21 22:32:27 +0200 |
---|---|---|
committer | Tom Smeding <tom.smeding@gmail.com> | 2020-06-25 17:22:19 +0200 |
commit | bbb8bc475593b9ff481ec214c4391fe6aff854f4 (patch) | |
tree | 4452579755867361fc5e6b7b395787f57e9fa2c7 /protocol_transport.md | |
parent | 46feba9a7b1e4ed023dcdc3c505b67f3eb8348f0 (diff) |
WIP secure transport using libsodium secretstreamlibsodium-transport
Diffstat (limited to 'protocol_transport.md')
-rw-r--r-- | protocol_transport.md | 128 |
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` |