summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/handshake.c68
-rw-r--r--src/handshake.h65
-rw-r--r--src/protocols/ec25519_fhmqvc/handshake.c24
-rw-r--r--src/types.h1
4 files changed, 101 insertions, 57 deletions
diff --git a/src/handshake.c b/src/handshake.c
index a55844f..7dd5b44 100644
--- a/src/handshake.c
+++ b/src/handshake.c
@@ -78,8 +78,11 @@ static inline uint32_t as_uint32(const fastd_handshake_record_t *record) {
}
/** Reads a TLV record as a 16bit integer (little endian) */
-static inline uint16_t as_uint16_le(const fastd_handshake_record_t *record) {
- return as_uint8(record) | (uint16_t)record->data[1] << 8;
+static inline uint16_t as_uint16_endian(const fastd_handshake_record_t *record, bool little_endian) {
+ if (little_endian)
+ return as_uint8(record) | (uint16_t)record->data[1] << 8;
+ else
+ return as_uint16(record);
}
/** Reads a TLV record as a variable-length integer (little endian) */
@@ -157,7 +160,7 @@ static fastd_string_stack_t * parse_string_list(const uint8_t *data, size_t len)
}
/** Allocates and initializes a new handshake packet */
-static fastd_buffer_t new_handshake(uint8_t type, const fastd_method_info_t *method, bool with_method_list, size_t tail_space) {
+static fastd_handshake_buffer_t new_handshake(uint8_t type, bool little_endian, const fastd_method_info_t *method, bool with_method_list, size_t tail_space) {
size_t version_len = strlen(FASTD_VERSION);
size_t protocol_len = strlen(conf.protocol->name);
size_t method_len = method ? strlen(method->name) : 0;
@@ -168,22 +171,24 @@ static fastd_buffer_t new_handshake(uint8_t type, const fastd_method_info_t *met
if (with_method_list)
method_list = create_method_list(&method_list_len);
- fastd_buffer_t buffer = fastd_buffer_alloc(sizeof(fastd_handshake_packet_t), 1,
- 3*5 + /* handshake type, mode, reply code */
- 6 + /* MTU */
- 4+version_len + /* version name */
- 4+protocol_len + /* protocol name */
- 4+method_len + /* method name */
- 4+method_list_len + /* supported method name list */
- tail_space);
- fastd_handshake_packet_t *packet = buffer.data;
+ fastd_handshake_buffer_t buffer = {
+ .buffer = fastd_buffer_alloc(sizeof(fastd_handshake_packet_t), 1,
+ 3*5 + /* handshake type, mode, reply code */
+ 6 + /* MTU */
+ 4+version_len + /* version name */
+ 4+protocol_len + /* protocol name */
+ 4+method_len + /* method name */
+ 4+method_list_len + /* supported method name list */
+ tail_space),
+ .little_endian = little_endian};
+ fastd_handshake_packet_t *packet = buffer.buffer.data;
packet->rsv = 0;
packet->tlv_len = 0;
fastd_handshake_add_uint8(&buffer, RECORD_HANDSHAKE_TYPE, type);
fastd_handshake_add_uint8(&buffer, RECORD_MODE, conf.mode);
- fastd_handshake_add_uint16_le(&buffer, RECORD_MTU, conf.mtu);
+ fastd_handshake_add_uint16_endian(&buffer, RECORD_MTU, conf.mtu);
fastd_handshake_add(&buffer, RECORD_VERSION_NAME, version_len, FASTD_VERSION);
fastd_handshake_add(&buffer, RECORD_PROTOCOL_NAME, protocol_len, conf.protocol->name);
@@ -200,13 +205,13 @@ static fastd_buffer_t new_handshake(uint8_t type, const fastd_method_info_t *met
}
/** Allocates and initializes a new initial handshake packet */
-fastd_buffer_t fastd_handshake_new_init(size_t tail_space) {
- return new_handshake(1, NULL, !conf.secure_handshakes, tail_space);
+fastd_handshake_buffer_t fastd_handshake_new_init(size_t tail_space) {
+ return new_handshake(1, true, NULL, !conf.secure_handshakes, tail_space);
}
/** Allocates and initializes a new reply handshake packet */
-fastd_buffer_t fastd_handshake_new_reply(uint8_t type, const fastd_method_info_t *method, bool with_method_list, size_t tail_space) {
- fastd_buffer_t buffer = new_handshake(type, method, with_method_list, tail_space);
+fastd_handshake_buffer_t fastd_handshake_new_reply(uint8_t type, bool little_endian, const fastd_method_info_t *method, bool with_method_list, size_t tail_space) {
+ fastd_handshake_buffer_t buffer = new_handshake(type, little_endian, method, with_method_list, tail_space);
fastd_handshake_add_uint8(&buffer, RECORD_REPLY_CODE, 0);
return buffer;
}
@@ -258,8 +263,11 @@ static void print_error(const char *prefix, const fastd_peer_address_t *remote_a
static void send_error(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, uint8_t reply_code, uint16_t error_detail) {
print_error("sending", remote_addr, reply_code, error_detail);
- fastd_buffer_t buffer = fastd_buffer_alloc(sizeof(fastd_handshake_packet_t), 0, 3*5 /* enough space for handshake type, reply code and error detail */);
- fastd_handshake_packet_t *reply = buffer.data;
+ fastd_handshake_buffer_t buffer = {
+ .buffer = fastd_buffer_alloc(sizeof(fastd_handshake_packet_t), 0, 3*5 /* enough space for handshake type, reply code and error detail */),
+ .little_endian = handshake->little_endian
+ };
+ fastd_handshake_packet_t *reply = buffer.buffer.data;
reply->rsv = 0;
reply->tlv_len = 0;
@@ -268,7 +276,7 @@ static void send_error(fastd_socket_t *sock, const fastd_peer_address_t *local_a
fastd_handshake_add_uint8(&buffer, RECORD_REPLY_CODE, reply_code);
fastd_handshake_add_uint(&buffer, RECORD_ERROR_DETAIL, error_detail);
- fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer);
+ fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer.buffer);
}
/** Parses the TLV records of a handshake */
@@ -297,8 +305,20 @@ static inline fastd_handshake_t parse_tlvs(const fastd_buffer_t *buffer) {
if (ptr+4 > end)
break;
- uint16_t type = ptr[0] + (ptr[1] << 8);
- uint16_t len = ptr[2] + (ptr[3] << 8);
+ uint16_t type, len;
+
+ if (!handshake.little_endian) {
+ type = ptr[1] + (ptr[0] << 8);
+ len = ptr[3] + (ptr[2] << 8);
+
+ if (type > 0xff || (type == 0 && len > 0xff))
+ handshake.little_endian = true;
+ }
+
+ if (handshake.little_endian) {
+ type = ptr[0] + (ptr[1] << 8);
+ len = ptr[2] + (ptr[3] << 8);
+ }
if (ptr+4+len > end)
break;
@@ -343,9 +363,9 @@ static inline bool check_records(fastd_socket_t *sock, const fastd_peer_address_
if (!conf.secure_handshakes || handshake->type > 1) {
if (handshake->records[RECORD_MTU].length == 2) {
- if (as_uint16_le(&handshake->records[RECORD_MTU]) != conf.mtu) {
+ if (as_uint16_endian(&handshake->records[RECORD_MTU], handshake->little_endian) != conf.mtu) {
pr_warn("MTU configuration differs with peer %I: local MTU is %u, remote MTU is %u",
- remote_addr, conf.mtu, as_uint16_le(&handshake->records[RECORD_MTU]));
+ remote_addr, conf.mtu, as_uint16_endian(&handshake->records[RECORD_MTU], handshake->little_endian));
}
}
}
diff --git a/src/handshake.h b/src/handshake.h
index 760d21b..f5582e9 100644
--- a/src/handshake.h
+++ b/src/handshake.h
@@ -89,11 +89,18 @@ struct fastd_handshake {
fastd_handshake_record_t records[RECORD_MAX]; /**< The TLV records of the handshake */
uint16_t tlv_len; /**< The length of the TLV record data */
void *tlv_data; /**< TLV record data */
+ bool little_endian; /**< true if the old little-endian handshake format is used */
+};
+
+/** A buffer a handshake to send is prepared in */
+struct fastd_handshake_buffer {
+ fastd_buffer_t buffer;
+ bool little_endian;
};
-fastd_buffer_t fastd_handshake_new_init(size_t tail_space);
-fastd_buffer_t fastd_handshake_new_reply(uint8_t type, const fastd_method_info_t *method, bool with_method_list, size_t tail_space);
+fastd_handshake_buffer_t fastd_handshake_new_init(size_t tail_space);
+fastd_handshake_buffer_t fastd_handshake_new_reply(uint8_t type, bool little_endian, const fastd_method_info_t *method, bool with_method_list, size_t tail_space);
void fastd_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, fastd_buffer_t buffer);
@@ -111,34 +118,42 @@ static inline uint16_t fastd_handshake_tlv_len(const fastd_buffer_t *buffer) {
}
/** Adds an uninitialized TLV record of given type and length to a handshake buffer */
-static inline uint8_t * fastd_handshake_extend(fastd_buffer_t *buffer, fastd_handshake_record_type_t type, size_t len) {
- uint8_t *dst = buffer->data + buffer->len;
+static inline uint8_t * fastd_handshake_extend(fastd_handshake_buffer_t *buffer, fastd_handshake_record_type_t type, size_t len) {
+ uint8_t *dst = buffer->buffer.data + buffer->buffer.len;
- if (buffer->data + buffer->len + 4 + len > buffer->base + buffer->base_len)
+ if (buffer->buffer.data + buffer->buffer.len + 4 + len > buffer->buffer.base + buffer->buffer.base_len)
exit_bug("not enough buffer allocated for handshake");
- buffer->len += 4 + len;
+ buffer->buffer.len += 4 + len;
- fastd_handshake_packet_t *packet = buffer->data;
- packet->tlv_len = htons(fastd_handshake_tlv_len(buffer) + 4 + len);
+ fastd_handshake_packet_t *packet = buffer->buffer.data;
+ packet->tlv_len = htons(fastd_handshake_tlv_len(&buffer->buffer) + 4 + len);
- dst[0] = type;
- dst[1] = type >> 8;
- dst[2] = len;
- dst[3] = len >> 8;
+ if (buffer->little_endian) {
+ dst[0] = type;
+ dst[1] = type >> 8;
+ dst[2] = len;
+ dst[3] = len >> 8;
+ }
+ else {
+ dst[0] = type >> 8;
+ dst[1] = type;
+ dst[2] = len >> 8;
+ dst[3] = len;
+ }
return dst+4;
}
/** Adds an TLV record of given type and length initialized with arbitraty data to a handshake buffer */
-static inline void fastd_handshake_add(fastd_buffer_t *buffer, fastd_handshake_record_type_t type, size_t len, const void *data) {
+static inline void fastd_handshake_add(fastd_handshake_buffer_t *buffer, fastd_handshake_record_type_t type, size_t len, const void *data) {
uint8_t *dst = fastd_handshake_extend(buffer, type, len);
memcpy(dst, data, len);
}
/** Adds an TLV record of given type and length initialized with zeros to a handshake buffer */
-static inline uint8_t * fastd_handshake_add_zero(fastd_buffer_t *buffer, fastd_handshake_record_type_t type, size_t len) {
+static inline uint8_t * fastd_handshake_add_zero(fastd_handshake_buffer_t *buffer, fastd_handshake_record_type_t type, size_t len) {
uint8_t *dst = fastd_handshake_extend(buffer, type, len);
memset(dst, 0, len);
@@ -146,14 +161,14 @@ static inline uint8_t * fastd_handshake_add_zero(fastd_buffer_t *buffer, fastd_h
}
/** Adds an uint8 TLV record of given type and value to a handshake buffer */
-static inline void fastd_handshake_add_uint8(fastd_buffer_t *buffer, fastd_handshake_record_type_t type, uint8_t value) {
+static inline void fastd_handshake_add_uint8(fastd_handshake_buffer_t *buffer, fastd_handshake_record_type_t type, uint8_t value) {
uint8_t *dst = fastd_handshake_extend(buffer, type, 1);
dst[0] = value;
}
/** Adds an uint16 TLV record of given type and value to a handshake buffer */
-static inline void fastd_handshake_add_uint16(fastd_buffer_t *buffer, fastd_handshake_record_type_t type, uint16_t value) {
+static inline void fastd_handshake_add_uint16(fastd_handshake_buffer_t *buffer, fastd_handshake_record_type_t type, uint16_t value) {
uint8_t *dst = fastd_handshake_extend(buffer, type, 2);
dst[0] = value >> 8;
@@ -161,7 +176,7 @@ static inline void fastd_handshake_add_uint16(fastd_buffer_t *buffer, fastd_hand
}
/** Adds an uint24 TLV record of given type and value to a handshake buffer */
-static inline void fastd_handshake_add_uint24(fastd_buffer_t *buffer, fastd_handshake_record_type_t type, uint32_t value) {
+static inline void fastd_handshake_add_uint24(fastd_handshake_buffer_t *buffer, fastd_handshake_record_type_t type, uint32_t value) {
uint8_t *dst = fastd_handshake_extend(buffer, type, 3);
dst[0] = value >> 16;
@@ -170,7 +185,7 @@ static inline void fastd_handshake_add_uint24(fastd_buffer_t *buffer, fastd_hand
}
/** Adds an uint32 TLV record of given type and value to a handshake buffer */
-static inline void fastd_handshake_add_uint32(fastd_buffer_t *buffer, fastd_handshake_record_type_t type, uint32_t value) {
+static inline void fastd_handshake_add_uint32(fastd_handshake_buffer_t *buffer, fastd_handshake_record_type_t type, uint32_t value) {
uint8_t *dst = fastd_handshake_extend(buffer, type, 4);
dst[0] = value >> 24;
@@ -180,15 +195,21 @@ static inline void fastd_handshake_add_uint32(fastd_buffer_t *buffer, fastd_hand
}
/** Adds an uint16 TLV record of given type and value to a handshake buffer encoded as little endian */
-static inline void fastd_handshake_add_uint16_le(fastd_buffer_t *buffer, fastd_handshake_record_type_t type, uint16_t value) {
+static inline void fastd_handshake_add_uint16_endian(fastd_handshake_buffer_t *buffer, fastd_handshake_record_type_t type, uint16_t value) {
uint8_t *dst = fastd_handshake_extend(buffer, type, 2);
- dst[0] = value;
- dst[1] = value >> 8;
+ if (buffer->little_endian) {
+ dst[0] = value;
+ dst[1] = value >> 8;
+ }
+ else {
+ dst[0] = value >> 8;
+ dst[1] = value;
+ }
}
/** Adds an TLV record of given type and value to a handshake buffer, automatically using a 1- to 4-byte value */
-static inline void fastd_handshake_add_uint(fastd_buffer_t *buffer, fastd_handshake_record_type_t type, uint32_t value) {
+static inline void fastd_handshake_add_uint(fastd_handshake_buffer_t *buffer, fastd_handshake_record_type_t type, uint32_t value) {
if (value > 0xffffff)
fastd_handshake_add_uint32(buffer, type, value);
if (value > 0xffff)
diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c
index 5d3e57e..0b547f4 100644
--- a/src/protocols/ec25519_fhmqvc/handshake.c
+++ b/src/protocols/ec25519_fhmqvc/handshake.c
@@ -329,7 +329,7 @@ static void clear_shared_handshake_key(const fastd_peer_t *peer) {
/** Sends a reply to an initial handshake (type 1) */
static void respond_handshake(const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer,
- const aligned_int256_t *peer_handshake_key, const fastd_method_info_t *method) {
+ const aligned_int256_t *peer_handshake_key, const fastd_method_info_t *method, bool little_endian) {
pr_debug("responding handshake with %P[%I]...", peer, remote_addr);
const handshake_key_t *handshake_key = &ctx.protocol_state->handshake_key;
@@ -337,7 +337,7 @@ static void respond_handshake(const fastd_socket_t *sock, const fastd_peer_addre
if (!update_shared_handshake_key(peer, handshake_key, peer_handshake_key))
return;
- fastd_buffer_t buffer = fastd_handshake_new_reply(2, method, true, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
+ fastd_handshake_buffer_t buffer = fastd_handshake_new_reply(2, little_endian, method, true, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->key->key);
@@ -352,10 +352,10 @@ static void respond_handshake(const fastd_socket_t *sock, const fastd_peer_addre
}
uint8_t *mac = fastd_handshake_add_zero(&buffer, RECORD_TLV_MAC, HASHBYTES);
- fastd_hmacsha256(&hmacbuf, peer->protocol_state->shared_handshake_key.w, fastd_handshake_tlv_data(&buffer), fastd_handshake_tlv_len(&buffer));
+ fastd_hmacsha256(&hmacbuf, peer->protocol_state->shared_handshake_key.w, fastd_handshake_tlv_data(&buffer.buffer), fastd_handshake_tlv_len(&buffer.buffer));
memcpy(mac, hmacbuf.b, HASHBYTES);
- fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer);
+ fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer.buffer);
}
/** Sends a reply to a handshake response (type 2) */
@@ -398,7 +398,7 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l
&peer->key->key, &sigma, compat ? NULL : shared_handshake_key.w, handshake_key->serial))
return;
- fastd_buffer_t buffer = fastd_handshake_new_reply(3, method, false, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
+ fastd_handshake_buffer_t buffer = fastd_handshake_new_reply(3, handshake->little_endian, method, false, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->key->key);
@@ -408,7 +408,7 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l
if (!compat) {
fastd_sha256_t hmacbuf;
uint8_t *mac = fastd_handshake_add_zero(&buffer, RECORD_TLV_MAC, HASHBYTES);
- fastd_hmacsha256(&hmacbuf, shared_handshake_key.w, fastd_handshake_tlv_data(&buffer), fastd_handshake_tlv_len(&buffer));
+ fastd_hmacsha256(&hmacbuf, shared_handshake_key.w, fastd_handshake_tlv_data(&buffer.buffer), fastd_handshake_tlv_len(&buffer.buffer));
memcpy(mac, hmacbuf.b, HASHBYTES);
}
else {
@@ -417,7 +417,7 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l
fastd_handshake_add(&buffer, RECORD_T, HASHBYTES, hmacbuf.b);
}
- fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer);
+ fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer.buffer);
}
/** Handles a reply to a handshake response (type 3) */
@@ -521,7 +521,7 @@ static fastd_peer_t * match_sender_key(const fastd_socket_t *sock, const fastd_p
void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer) {
fastd_protocol_ec25519_fhmqvc_maintenance();
- fastd_buffer_t buffer = fastd_handshake_new_init(3*(4+PUBLICKEYBYTES) /* sender key, recipient key, handshake key */);
+ fastd_handshake_buffer_t buffer = fastd_handshake_new_init(3*(4+PUBLICKEYBYTES) /* sender key, recipient key, handshake key */);
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
@@ -539,7 +539,7 @@ void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fa
if (!peer || !fastd_peer_is_established(peer))
fastd_peer_exec_shell_command(&conf.on_connect, peer, (local_addr && local_addr->sa.sa_family) ? local_addr : sock->bound_addr, remote_addr);
- fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer);
+ fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer.buffer);
}
@@ -557,6 +557,7 @@ static inline void print_unknown_key(const fastd_peer_address_t *addr, const uns
/** Data attached to an asynchronous on-verify run */
typedef struct verify_data {
aligned_int256_t peer_handshake_key; /**< The public key of the peer being verified */
+ bool little_endian; /**< The handshake endianess */
} verify_data_t;
/** Adds a dynamic peer for an unknown key */
@@ -614,6 +615,7 @@ static bool handle_dynamic(fastd_socket_t *sock, const fastd_peer_address_t *loc
verify_data_t verify_data;
memset(&verify_data, 0, sizeof(verify_data));
memcpy(&verify_data.peer_handshake_key, handshake->records[RECORD_SENDER_HANDSHAKE_KEY].data, PUBLICKEYBYTES);
+ verify_data.little_endian = handshake->little_endian;
fastd_tristate_t verified = fastd_verify_peer(peer, sock, local_addr, remote_addr, method, &verify_data, sizeof(verify_data));
@@ -640,7 +642,7 @@ void fastd_protocol_ec25519_fhmqvc_handle_verify_return(fastd_peer_t *peer, fast
peer->last_handshake_response_timeout = ctx.now + MIN_HANDSHAKE_INTERVAL;
peer->last_handshake_response_address = *remote_addr;
- respond_handshake(sock, local_addr, remote_addr, peer, &data->peer_handshake_key, method);
+ respond_handshake(sock, local_addr, remote_addr, peer, &data->peer_handshake_key, method, data->little_endian);
}
#else
@@ -726,7 +728,7 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const
peer->last_handshake_response_timeout = ctx.now + MIN_HANDSHAKE_INTERVAL;
peer->last_handshake_response_address = *remote_addr;
- respond_handshake(sock, local_addr, remote_addr, peer, &peer_handshake_key, method);
+ respond_handshake(sock, local_addr, remote_addr, peer, &peer_handshake_key, method, handshake->little_endian);
return;
}
diff --git a/src/types.h b/src/types.h
index d0a0221..01b36f5 100644
--- a/src/types.h
+++ b/src/types.h
@@ -107,6 +107,7 @@ typedef struct fastd_mac_info fastd_mac_info_t;
typedef struct fastd_mac fastd_mac_t;
typedef struct fastd_handshake fastd_handshake_t;
+typedef struct fastd_handshake_buffer fastd_handshake_buffer_t;
typedef struct fastd_lex fastd_lex_t;
typedef struct fastd_parser_state fastd_parser_state_t;