#include #include #include #include "transport.h" #include "net.h" #define STREAM_KEY_SIZE 32 #define STREAM_HEADER_SIZE 24 #define PARTY_PUBKEY_SIZE 32 #define PARTY_SECKEY_SIZE 32 __attribute__((warn_unused_result)) static bool check_libsodium_size_assumptions(void) { return crypto_secretstream_xchacha20poly1305_KEYBYTES == STREAM_KEY_SIZE && crypto_secretstream_xchacha20poly1305_HEADERBYTES == STREAM_HEADER_SIZE && crypto_kx_SESSIONKEYBYTES >= STREAM_KEY_SIZE && crypto_kx_PUBLICKEYBYTES == PARTY_PUBKEY_SIZE && crypto_kx_SECRETKEYBYTES == PARTY_SECKEY_SIZE; } static void send_clienthello( int fd, const unsigned char pubkey[PARTY_PUBKEY_SIZE] ) { char buffer[16 + PARTY_PUBKEY_SIZE]; memcpy(buffer, "tomsg v01 client", 16); memcpy(buffer + 16, pubkey, PARTY_PUBKEY_SIZE); net_send_raw_text(fd, buffer, sizeof buffer); } static void send_serverhello( int fd, const unsigned char pubkey[PARTY_PUBKEY_SIZE], const unsigned char server_tx_header[STREAM_HEADER_SIZE] ) { char buffer[16 + PARTY_PUBKEY_SIZE + STREAM_HEADER_SIZE]; memcpy(buffer, "tomsg v01 server", 16); memcpy(buffer + 16, pubkey, PARTY_PUBKEY_SIZE); memcpy(buffer + 16 + PARTY_PUBKEY_SIZE, server_tx_header, STREAM_HEADER_SIZE); net_send_raw_text(fd, buffer, sizeof buffer); } static void send_clienthello2( int fd, const unsigned char client_tx_header[STREAM_HEADER_SIZE] ) { char buffer[8 + STREAM_HEADER_SIZE]; memcpy(buffer, "cheader0", 8); memcpy(buffer + 8, client_tx_header, STREAM_HEADER_SIZE); net_send_raw_text(fd, buffer, sizeof buffer); } enum phase { WAITING_FOR_SERVERHELLO, WAITING_FOR_CLIENTHELLO, WAITING_FOR_CLIENTHELLO2, WAITING_FOR_DATA, // handshake finished }; struct transport { int fd; bool is_server; enum phase phase; unsigned char my_pubkey[PARTY_PUBKEY_SIZE]; unsigned char my_seckey[PARTY_SECKEY_SIZE]; unsigned char other_pubkey[PARTY_PUBKEY_SIZE]; crypto_secretstream_xchacha20poly1305_state pushstate; crypto_secretstream_xchacha20poly1305_state pullstate; }; struct transport* tsp_start(int fd, bool is_server) { if (!check_libsodium_size_assumptions()) { die("Transport protocol size assumptions do not hold!"); } struct transport *tsp = calloc(1, struct transport); tsp->fd = fd; tsp->is_server = is_server; crypto_kx_keypair(tsp->my_pubkey, tsp->my_seckey); if (is_server) { tsp->phase = WAITING_FOR_CLIENTHELLO; } else { send_clienthello(fd, tsp->my_pubkey); tsp->phase = WAITING_FOR_SERVERHELLO; } return tsp; } void tsp_close(struct transport *tsp) { if (tsp->phase == WAITING_FOR_DATA) { } }