Skip to content

Commit 34a2cb7

Browse files
committed
protocol: Make T_DATUM_PROTOCOL_HEADER serialisation explicit
Should improve portability
1 parent b453ce6 commit 34a2cb7

File tree

2 files changed

+46
-28
lines changed

2 files changed

+46
-28
lines changed

src/datum_protocol.c

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,6 @@ unsigned char datum_protocol_setup_new_job_idx(void *sx) {
150150
return a;
151151
}
152152

153-
static inline void datum_xor_header_key(void *h, uint32_t key) {
154-
*((uint32_t *)h) ^= key;
155-
}
156-
157153
uint32_t datum_header_xor_feedback(const uint32_t i) {
158154
uint32_t s = 0xb10cfeed;
159155
uint32_t h = s;
@@ -173,6 +169,32 @@ uint32_t datum_header_xor_feedback(const uint32_t i) {
173169
return h;
174170
}
175171

172+
static
173+
void datum_header_pk(uint8_t * const dst, const size_t offset, const T_DATUM_PROTOCOL_HEADER * const h, uint32_t * const xor_key) {
174+
uint32_t raw = (h->cmd_len & 0x3fffffUL) |
175+
((uint32_t)h->is_signed << 24) |
176+
((uint32_t)h->is_encrypted_pubkey << 25) |
177+
((uint32_t)h->is_encrypted_channel << 26) |
178+
((uint32_t)(h->proto_cmd & 0x1f) << 27);
179+
raw ^= *xor_key;
180+
*xor_key = datum_header_xor_feedback(*xor_key);
181+
182+
pk_u32le(dst, offset, raw);
183+
}
184+
185+
static
186+
void datum_header_upk(T_DATUM_PROTOCOL_HEADER * const h, const uint8_t * const src, const size_t offset, uint32_t * const xor_key) {
187+
uint32_t raw = upk_u32le(src, offset);
188+
raw ^= *xor_key;
189+
*xor_key = datum_header_xor_feedback(*xor_key);
190+
191+
h->cmd_len = raw & 0x003fffffUL;
192+
h->is_signed = raw & 0x01000000UL;
193+
h->is_encrypted_pubkey = raw & 0x02000000UL;
194+
h->is_encrypted_channel = raw & 0x04000000UL;
195+
h->proto_cmd = (raw >> 27) & 0x1f;
196+
}
197+
176198
// Take the hexidecimal public key string and store it in a DATUM_ENC_KEYS
177199
int datum_pubkey_to_struct(const char *input, DATUM_ENC_KEYS *key) {
178200
int i;
@@ -230,6 +252,7 @@ int datum_protocol_mining_cmd(void *data, int len) {
230252
// encypt and send a standard mining sub-command
231253
// this can be called from other threads so must be thread safe!
232254
T_DATUM_PROTOCOL_HEADER h;
255+
unsigned char wire_h[T_DATUM_PROTOCOL_HEADER_WIRE_BYTES];
233256
int i;
234257

235258
memset(&h, 0, sizeof(T_DATUM_PROTOCOL_HEADER));
@@ -245,11 +268,10 @@ int datum_protocol_mining_cmd(void *data, int len) {
245268

246269
crypto_box_easy_afternm(data, data, len, session_nonce_sender, session_precomp.precomp_remote);
247270
//DLOG_DEBUG("mining cmd 5--- len %d, send header key %8.8x, raw %8.8lx", h.cmd_len, sending_header_key, (unsigned long)upk_u32le(h, 0));
248-
datum_xor_header_key(&h, sending_header_key);
249-
sending_header_key = datum_header_xor_feedback(sending_header_key);
271+
datum_header_pk(wire_h, 0, &h, &sending_header_key);
250272
datum_increment_session_nonce(session_nonce_sender);
251273

252-
i = datum_protocol_chars_to_server((unsigned char *)&h, sizeof(T_DATUM_PROTOCOL_HEADER));
274+
i = datum_protocol_chars_to_server(wire_h, sizeof(wire_h));
253275
if (i < 1) {
254276
pthread_mutex_unlock(&datum_protocol_sender_stage1_lock);
255277
return -1;
@@ -1039,16 +1061,12 @@ int datum_protocol_send_hello(int sockfd) {
10391061
i+=crypto_sign_BYTES;
10401062

10411063
// seal it up
1042-
crypto_box_seal(&enc_hello_msg[sizeof(T_DATUM_PROTOCOL_HEADER)], hello_msg, i, pool_keys.pk_x25519);
1064+
crypto_box_seal(&enc_hello_msg[T_DATUM_PROTOCOL_HEADER_WIRE_BYTES], hello_msg, i, pool_keys.pk_x25519);
10431065
i+=crypto_box_SEALBYTES;
10441066

10451067
h.cmd_len = i;
10461068

1047-
memcpy(enc_hello_msg, &h, sizeof(T_DATUM_PROTOCOL_HEADER));
1048-
1049-
// apply our initial xor key to the header, just to obfuscate it a tiny bit
1050-
// kinda pointless, but ok
1051-
datum_xor_header_key(&enc_hello_msg[0], sending_header_key);
1069+
datum_header_pk(enc_hello_msg, 0, &h, &sending_header_key);
10521070

10531071
DLOG_DEBUG("Sending handshake init (%d bytes)", h.cmd_len);
10541072

@@ -1071,7 +1089,7 @@ int datum_protocol_send_hello(int sockfd) {
10711089
// FIXME: why is this mixed-endian?
10721090
//DLOG_DEBUG("Session Nonce: %8.8X%8.8X%8.8X%8.8X%8.8X%8.8X", upk_u32le(session_nonce_receiver, 0), upk_u32le(session_nonce_receiver, 4), upk_u32le(session_nonce_receiver, 8), upk_u32le(session_nonce_receiver, 12), upk_u32le(session_nonce_receiver, 16), upk_u32le(session_nonce_receiver, 20));
10731091

1074-
return datum_protocol_chars_to_server(enc_hello_msg, i+sizeof(T_DATUM_PROTOCOL_HEADER));
1092+
return datum_protocol_chars_to_server(enc_hello_msg, T_DATUM_PROTOCOL_HEADER_WIRE_BYTES + i);
10751093
}
10761094

10771095
int datum_protocol_decrypt_sealed(T_DATUM_PROTOCOL_HEADER *h, unsigned char *data) {
@@ -1478,6 +1496,7 @@ void *datum_protocol_client(void *args) {
14781496
bool break_again = false;
14791497
int sent = 0;
14801498
T_DATUM_PROTOCOL_HEADER s_header;
1499+
unsigned char wire_h[T_DATUM_PROTOCOL_HEADER_WIRE_BYTES];
14811500

14821501
pthread_rwlock_wrlock(&datum_jobs_rwlock);
14831502
for(i=0;i<MAX_DATUM_PROTOCOL_JOBS;i++) {
@@ -1724,7 +1743,7 @@ void *datum_protocol_client(void *args) {
17241743
case 1:
17251744
case 2:
17261745
case 3: {
1727-
n = recv(sockfd, ((unsigned char *)&s_header) + (sizeof(T_DATUM_PROTOCOL_HEADER) - protocol_state), protocol_state, MSG_DONTWAIT);
1746+
n = recv(sockfd, &wire_h[sizeof(wire_h) - protocol_state], protocol_state, MSG_DONTWAIT);
17281747
if (n <= 0) {
17291748
if ((n < 0) && ((errno == EAGAIN || errno == EWOULDBLOCK))) {
17301749
continue;
@@ -1733,34 +1752,34 @@ void *datum_protocol_client(void *args) {
17331752
break_again = true; break;
17341753
}
17351754

1736-
if ((n+(sizeof(T_DATUM_PROTOCOL_HEADER) - protocol_state)) != sizeof(T_DATUM_PROTOCOL_HEADER)) {
1755+
if ((n + (sizeof(wire_h) - protocol_state)) != sizeof(wire_h)) {
17371756
if ((n+protocol_state) > 4) {
17381757
DLOG_DEBUG("recv() issue. too many header bytes. protocol_state=%d, n=%d, errno=%d (%s)", protocol_state, n, errno, strerror(errno));
17391758
break_again = true; break;
17401759
}
17411760

1742-
protocol_state = sizeof(T_DATUM_PROTOCOL_HEADER) - n - (sizeof(T_DATUM_PROTOCOL_HEADER) - protocol_state); // should give us a state equal to the number of. consoluted to show the process. (compiler optimizes)
1761+
protocol_state = sizeof(wire_h) - n - (sizeof(wire_h) - protocol_state); // should give us a state equal to the number of. consoluted to show the process. (compiler optimizes)
17431762
continue;
17441763
}
17451764

17461765
protocol_state = 4;
17471766
continue; // cant fall through to 0, so loop around back to this to jump to 4
17481767
}
17491768
case 0: {
1750-
n = recv(sockfd, &s_header, sizeof(T_DATUM_PROTOCOL_HEADER), MSG_DONTWAIT);
1769+
n = recv(sockfd, &wire_h[0], sizeof(wire_h), MSG_DONTWAIT);
17511770
if (n <= 0) {
17521771
if ((n < 0) && ((errno == EAGAIN || errno == EWOULDBLOCK))) {
17531772
continue;
17541773
}
17551774
DLOG_DEBUG("recv() issue. protocol_state=%d, n=%d, errno=%d (%s)", protocol_state, n, errno, strerror(errno));
17561775
break_again = true; break;
17571776
}
1758-
if (n != sizeof(T_DATUM_PROTOCOL_HEADER)) {
1777+
if (n != sizeof(wire_h)) {
17591778
if (n > 4) {
17601779
DLOG_DEBUG("recv() issue. too many header bytes (B). protocol_state=%d, n=%d, errno=%d (%s)", protocol_state, n, errno, strerror(errno));
17611780
break_again = true; break;
17621781
}
1763-
protocol_state = sizeof(T_DATUM_PROTOCOL_HEADER)-n;
1782+
protocol_state = sizeof(wire_h) - n;
17641783
continue;
17651784
}
17661785

@@ -1770,9 +1789,8 @@ void *datum_protocol_client(void *args) {
17701789
}
17711790

17721791
case 4: {
1773-
datum_xor_header_key(&s_header, receiving_header_key);
1774-
//DLOG_DEBUG("Server CMD: cmd=%u, len=%u, raw = %8.8x ... rkey = %8.8x", s_header.proto_cmd, s_header.cmd_len, upk_u32le(s_header, 0), receiving_header_key);
1775-
receiving_header_key = datum_header_xor_feedback(receiving_header_key);
1792+
datum_header_upk(&s_header, wire_h, 0, &receiving_header_key);
1793+
//DLOG_DEBUG("Server CMD: cmd=%u, len=%u, raw = %8.8x ... rkey(after) = %8.8x", s_header.proto_cmd, s_header.cmd_len, upk_u32le(s_header, 0), receiving_header_key);
17761794
protocol_state = 5;
17771795
server_in_buf = 0;
17781796
if (!s_header.cmd_len) {

src/datum_protocol.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@
5858
// It's likely possible to brute force the XOR key to break packets down into individual commands, but the contents and nature of the
5959
// cmd is still obfuscated and unrecoverable without the session keys.
6060

61-
typedef struct __attribute__((packed)) T_DATUM_PROTOCOL_HEADER {
61+
typedef struct T_DATUM_PROTOCOL_HEADER {
6262
uint32_t cmd_len:22; // max cmd size is 2^22 (~4MB), which is roughly the max block size for a raw submission or a raw template validation
63-
uint8_t reserved:2; // save for later use
64-
bool is_signed:1;
65-
bool is_encrypted_pubkey:1;
66-
bool is_encrypted_channel:1;
63+
bool is_signed;
64+
bool is_encrypted_pubkey;
65+
bool is_encrypted_channel;
6766
uint8_t proto_cmd:5; // 32 protocol level commands
6867
} T_DATUM_PROTOCOL_HEADER;
68+
#define T_DATUM_PROTOCOL_HEADER_WIRE_BYTES 4
6969

7070
typedef struct {
7171
bool is_remote;

0 commit comments

Comments
 (0)