1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#include <stdio.h>
#include <string.h>
#include <sodium.h>
#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) {
}
}
|