mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-21 14:03:11 -07:00
parent
163fa81c03
commit
59e6603256
10 changed files with 272 additions and 108 deletions
|
@ -20,15 +20,20 @@ extern "C" {
|
|||
#define CHIAKI_GKCRYPT_GMAC_KEY_REFRESH_KEY_POS 45000
|
||||
#define CHIAKI_GKCRYPT_GMAC_KEY_REFRESH_IV_OFFSET 44910
|
||||
|
||||
typedef struct chiaki_key_state_t
|
||||
{
|
||||
uint64_t prev;
|
||||
} ChiakiKeyState;
|
||||
|
||||
typedef struct chiaki_gkcrypt_t {
|
||||
uint8_t index;
|
||||
|
||||
uint8_t *key_buf; // circular buffer of the ctr mode key stream
|
||||
size_t key_buf_size;
|
||||
size_t key_buf_populated; // size of key_buf that is already populated (on startup)
|
||||
size_t key_buf_key_pos_min; // minimal key pos currently in key_buf
|
||||
uint64_t key_buf_key_pos_min; // minimal key pos currently in key_buf
|
||||
size_t key_buf_start_offset; // offset in key_buf of the minimal key pos
|
||||
size_t last_key_pos; // last key pos that has been requested
|
||||
uint64_t last_key_pos; // last key pos that has been requested
|
||||
bool key_buf_thread_stop;
|
||||
ChiakiMutex key_buf_mutex;
|
||||
ChiakiCond key_buf_cond;
|
||||
|
@ -50,14 +55,14 @@ struct chiaki_session_t;
|
|||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_init(ChiakiGKCrypt *gkcrypt, ChiakiLog *log, size_t key_buf_chunks, uint8_t index, const uint8_t *handshake_key, const uint8_t *ecdh_secret);
|
||||
|
||||
CHIAKI_EXPORT void chiaki_gkcrypt_fini(ChiakiGKCrypt *gkcrypt);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_get_key_stream(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_decrypt(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size);
|
||||
static inline ChiakiErrorCode chiaki_gkcrypt_encrypt(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size) { return chiaki_gkcrypt_decrypt(gkcrypt, key_pos, buf, buf_size); }
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcrypt, uint64_t key_pos, uint8_t *buf, size_t buf_size);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_get_key_stream(ChiakiGKCrypt *gkcrypt, uint64_t key_pos, uint8_t *buf, size_t buf_size);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_decrypt(ChiakiGKCrypt *gkcrypt, uint64_t key_pos, uint8_t *buf, size_t buf_size);
|
||||
static inline ChiakiErrorCode chiaki_gkcrypt_encrypt(ChiakiGKCrypt *gkcrypt, uint64_t key_pos, uint8_t *buf, size_t buf_size) { return chiaki_gkcrypt_decrypt(gkcrypt, key_pos, buf, buf_size); }
|
||||
CHIAKI_EXPORT void chiaki_gkcrypt_gen_gmac_key(uint64_t index, const uint8_t *key_base, const uint8_t *iv, uint8_t *key_out);
|
||||
CHIAKI_EXPORT void chiaki_gkcrypt_gen_new_gmac_key(ChiakiGKCrypt *gkcrypt, uint64_t index);
|
||||
CHIAKI_EXPORT void chiaki_gkcrypt_gen_tmp_gmac_key(ChiakiGKCrypt *gkcrypt, uint64_t index, uint8_t *key_out);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gmac(ChiakiGKCrypt *gkcrypt, size_t key_pos, const uint8_t *buf, size_t buf_size, uint8_t *gmac_out);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gmac(ChiakiGKCrypt *gkcrypt, uint64_t key_pos, const uint8_t *buf, size_t buf_size, uint8_t *gmac_out);
|
||||
|
||||
static inline ChiakiGKCrypt *chiaki_gkcrypt_new(ChiakiLog *log, size_t key_buf_chunks, uint8_t index, const uint8_t *handshake_key, const uint8_t *ecdh_secret)
|
||||
{
|
||||
|
@ -81,12 +86,17 @@ static inline void chiaki_gkcrypt_free(ChiakiGKCrypt *gkcrypt)
|
|||
free(gkcrypt);
|
||||
}
|
||||
|
||||
typedef struct chiaki_key_state_t {
|
||||
uint64_t prev;
|
||||
} ChiakiKeyState;
|
||||
|
||||
CHIAKI_EXPORT void chiaki_key_state_init(ChiakiKeyState *state);
|
||||
CHIAKI_EXPORT uint64_t chiaki_key_state_request_pos(ChiakiKeyState *state, uint32_t low);
|
||||
|
||||
/**
|
||||
* @param commit whether to remember this key_pos to update the state. Should only be true after authentication to avoid DoS.
|
||||
*/
|
||||
CHIAKI_EXPORT uint64_t chiaki_key_state_request_pos(ChiakiKeyState *state, uint32_t low, bool commit);
|
||||
|
||||
/**
|
||||
* Update the internal state after knowing that this key_pos is authentic.
|
||||
*/
|
||||
CHIAKI_EXPORT void chiaki_key_state_commit(ChiakiKeyState *state, uint64_t prev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint32_t ChiakiTakionPacketKeyPos;
|
||||
|
||||
typedef enum chiaki_takion_message_data_type_t {
|
||||
CHIAKI_TAKION_MESSAGE_DATA_TYPE_PROTOBUF = 0,
|
||||
CHIAKI_TAKION_MESSAGE_DATA_TYPE_9 = 9
|
||||
|
@ -45,7 +43,7 @@ typedef struct chiaki_takion_av_packet_t
|
|||
uint8_t adaptive_stream_index;
|
||||
uint8_t byte_at_0x2c;
|
||||
|
||||
uint32_t key_pos;
|
||||
uint64_t key_pos;
|
||||
|
||||
uint8_t *data; // not owned
|
||||
size_t data_size;
|
||||
|
@ -55,7 +53,7 @@ static inline uint8_t chiaki_takion_av_packet_audio_unit_size(ChiakiTakionAVPack
|
|||
static inline uint8_t chiaki_takion_av_packet_audio_source_units_count(ChiakiTakionAVPacket *packet) { return packet->units_in_frame_fec & 0xf; }
|
||||
static inline uint8_t chiaki_takion_av_packet_audio_fec_units_count(ChiakiTakionAVPacket *packet) { return (packet->units_in_frame_fec >> 4) & 0xf; }
|
||||
|
||||
typedef ChiakiErrorCode (*ChiakiTakionAVPacketParse)(ChiakiTakionAVPacket *packet, uint8_t *buf, size_t buf_size);
|
||||
typedef ChiakiErrorCode (*ChiakiTakionAVPacketParse)(ChiakiTakionAVPacket *packet, ChiakiKeyState *key_state, uint8_t *buf, size_t buf_size);
|
||||
|
||||
typedef struct chiaki_takion_congestion_packet_t
|
||||
{
|
||||
|
@ -133,7 +131,7 @@ typedef struct chiaki_takion_t
|
|||
size_t postponed_packets_count;
|
||||
|
||||
ChiakiGKCrypt *gkcrypt_local; // if NULL (default), no gmac is calculated and nothing is encrypted
|
||||
size_t key_pos_local;
|
||||
uint64_t key_pos_local;
|
||||
ChiakiMutex gkcrypt_local_mutex;
|
||||
|
||||
ChiakiGKCrypt *gkcrypt_remote; // if NULL (default), remote gmacs are IGNORED (!) and everything is expected to be unencrypted
|
||||
|
@ -158,6 +156,8 @@ typedef struct chiaki_takion_t
|
|||
uint32_t a_rwnd;
|
||||
|
||||
ChiakiTakionAVPacketParse av_packet_parse;
|
||||
|
||||
ChiakiKeyState key_state;
|
||||
} ChiakiTakion;
|
||||
|
||||
|
||||
|
@ -178,7 +178,7 @@ static inline void chiaki_takion_set_crypt(ChiakiTakion *takion, ChiakiGKCrypt *
|
|||
* Thread-safe while Takion is running.
|
||||
* @param key_pos pointer to write the new key pos to. will be 0 if encryption is disabled. Contents undefined on failure.
|
||||
*/
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_crypt_advance_key_pos(ChiakiTakion *takion, size_t data_size, size_t *key_pos);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_crypt_advance_key_pos(ChiakiTakion *takion, size_t data_size, uint64_t *key_pos);
|
||||
|
||||
/**
|
||||
* Send a datagram directly on the socket.
|
||||
|
@ -193,7 +193,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_raw(ChiakiTakion *takion, const
|
|||
*
|
||||
* If encryption is disabled, the MAC will be set to 0.
|
||||
*/
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send(ChiakiTakion *takion, uint8_t *buf, size_t buf_size);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send(ChiakiTakion *takion, uint8_t *buf, size_t buf_size, uint64_t key_pos);
|
||||
|
||||
/**
|
||||
* Thread-safe while Takion is running.
|
||||
|
@ -220,7 +220,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_feedback_history(ChiakiTakion *
|
|||
#define CHIAKI_TAKION_V9_AV_HEADER_SIZE_VIDEO 0x17
|
||||
#define CHIAKI_TAKION_V9_AV_HEADER_SIZE_AUDIO 0x12
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v9_av_packet_parse(ChiakiTakionAVPacket *packet, uint8_t *buf, size_t buf_size);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v9_av_packet_parse(ChiakiTakionAVPacket *packet, ChiakiKeyState *key_state, uint8_t *buf, size_t buf_size);
|
||||
|
||||
#define CHIAKI_TAKION_V7_AV_HEADER_SIZE_BASE 0x12
|
||||
#define CHIAKI_TAKION_V7_AV_HEADER_SIZE_VIDEO_ADD 0x3
|
||||
|
@ -228,7 +228,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v9_av_packet_parse(ChiakiTakionAVPac
|
|||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v7_av_packet_format_header(uint8_t *buf, size_t buf_size, size_t *header_size_out, ChiakiTakionAVPacket *packet);
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v7_av_packet_parse(ChiakiTakionAVPacket *packet, uint8_t *buf, size_t buf_size);
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v7_av_packet_parse(ChiakiTakionAVPacket *packet, ChiakiKeyState *key_state, uint8_t *buf, size_t buf_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -79,7 +79,6 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_ctrl_init(ChiakiCtrl *ctrl, ChiakiSession *
|
|||
goto error_notif_pipe;
|
||||
|
||||
return err;
|
||||
error_notif_mutex:
|
||||
chiaki_mutex_fini(&ctrl->notif_mutex);
|
||||
error_notif_pipe:
|
||||
chiaki_stop_pipe_fini(&ctrl->notif_pipe);
|
||||
|
|
|
@ -210,7 +210,7 @@ CHIAKI_EXPORT void chiaki_gkcrypt_gen_tmp_gmac_key(ChiakiGKCrypt *gkcrypt, uint6
|
|||
memcpy(key_out, gkcrypt->key_gmac_base, sizeof(gkcrypt->key_gmac_base));
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size)
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gen_key_stream(ChiakiGKCrypt *gkcrypt, uint64_t key_pos, uint8_t *buf, size_t buf_size)
|
||||
{
|
||||
assert(key_pos % CHIAKI_GKCRYPT_BLOCK_SIZE == 0);
|
||||
assert(buf_size % CHIAKI_GKCRYPT_BLOCK_SIZE == 0);
|
||||
|
@ -276,7 +276,7 @@ static bool gkcrypt_key_buf_should_generate(ChiakiGKCrypt *gkcrypt)
|
|||
return gkcrypt->last_key_pos > gkcrypt->key_buf_key_pos_min + gkcrypt->key_buf_populated / 2;
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_get_key_stream(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size)
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_get_key_stream(ChiakiGKCrypt *gkcrypt, uint64_t key_pos, uint8_t *buf, size_t buf_size)
|
||||
{
|
||||
if(!gkcrypt->key_buf)
|
||||
return chiaki_gkcrypt_gen_key_stream(gkcrypt, key_pos, buf, buf_size);
|
||||
|
@ -291,7 +291,15 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_get_key_stream(ChiakiGKCrypt *gkcry
|
|||
if(key_pos < gkcrypt->key_buf_key_pos_min
|
||||
|| key_pos + buf_size >= gkcrypt->key_buf_key_pos_min + gkcrypt->key_buf_populated)
|
||||
{
|
||||
CHIAKI_LOGW(gkcrypt->log, "Requested key stream for key pos %#llx on GKCrypt %d, but it's not in the buffer", (int)key_pos, gkcrypt->index);
|
||||
CHIAKI_LOGW(gkcrypt->log, "Requested key stream for key pos %#llx on GKCrypt %d, but it's not in the buffer:"
|
||||
" key buf size %#llx, start offset: %#llx, populated: %#llx, min key pos: %#llx, last key pos: %#llx",
|
||||
(unsigned long long)key_pos,
|
||||
gkcrypt->index,
|
||||
(unsigned long long)gkcrypt->key_buf_size,
|
||||
(unsigned long long)gkcrypt->key_buf_start_offset,
|
||||
(unsigned long long)gkcrypt->key_buf_populated,
|
||||
(unsigned long long)gkcrypt->key_buf_key_pos_min,
|
||||
(unsigned long long)gkcrypt->last_key_pos);
|
||||
chiaki_mutex_unlock(&gkcrypt->key_buf_mutex);
|
||||
err = chiaki_gkcrypt_gen_key_stream(gkcrypt, key_pos, buf, buf_size);
|
||||
}
|
||||
|
@ -318,9 +326,9 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_get_key_stream(ChiakiGKCrypt *gkcry
|
|||
return err;
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_decrypt(ChiakiGKCrypt *gkcrypt, size_t key_pos, uint8_t *buf, size_t buf_size)
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_decrypt(ChiakiGKCrypt *gkcrypt, uint64_t key_pos, uint8_t *buf, size_t buf_size)
|
||||
{
|
||||
size_t padding_pre = key_pos % CHIAKI_GKCRYPT_BLOCK_SIZE;
|
||||
uint64_t padding_pre = key_pos % CHIAKI_GKCRYPT_BLOCK_SIZE;
|
||||
size_t full_size = ((padding_pre + buf_size + CHIAKI_GKCRYPT_BLOCK_SIZE - 1) / CHIAKI_GKCRYPT_BLOCK_SIZE) * CHIAKI_GKCRYPT_BLOCK_SIZE;
|
||||
|
||||
uint8_t *key_stream = malloc(full_size);
|
||||
|
@ -340,7 +348,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_decrypt(ChiakiGKCrypt *gkcrypt, siz
|
|||
return CHIAKI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gmac(ChiakiGKCrypt *gkcrypt, size_t key_pos, const uint8_t *buf, size_t buf_size, uint8_t *gmac_out)
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_gkcrypt_gmac(ChiakiGKCrypt *gkcrypt, uint64_t key_pos, const uint8_t *buf, size_t buf_size, uint8_t *gmac_out)
|
||||
{
|
||||
uint8_t iv[CHIAKI_GKCRYPT_BLOCK_SIZE];
|
||||
counter_add(iv, gkcrypt->iv, key_pos / 0x10);
|
||||
|
@ -463,7 +471,7 @@ static ChiakiErrorCode gkcrypt_generate_next_chunk(ChiakiGKCrypt *gkcrypt)
|
|||
{
|
||||
assert(gkcrypt->key_buf_populated + KEY_BUF_CHUNK_SIZE <= gkcrypt->key_buf_size);
|
||||
size_t buf_offset = (gkcrypt->key_buf_start_offset + gkcrypt->key_buf_populated) % gkcrypt->key_buf_size;
|
||||
size_t key_pos = gkcrypt->key_buf_key_pos_min + gkcrypt->key_buf_populated;
|
||||
uint64_t key_pos = gkcrypt->key_buf_key_pos_min + gkcrypt->key_buf_populated;
|
||||
uint8_t *buf_start = gkcrypt->key_buf + buf_offset;
|
||||
|
||||
chiaki_mutex_unlock(&gkcrypt->key_buf_mutex);
|
||||
|
@ -505,7 +513,7 @@ static void *gkcrypt_thread_func(void *user)
|
|||
if(gkcrypt->last_key_pos > gkcrypt->key_buf_key_pos_min + gkcrypt->key_buf_populated)
|
||||
{
|
||||
// skip ahead if the last key pos is already beyond our buffer
|
||||
size_t key_pos = (gkcrypt->last_key_pos / KEY_BUF_CHUNK_SIZE) * KEY_BUF_CHUNK_SIZE;
|
||||
uint64_t key_pos = (gkcrypt->last_key_pos / KEY_BUF_CHUNK_SIZE) * KEY_BUF_CHUNK_SIZE;
|
||||
CHIAKI_LOGW(gkcrypt->log, "Already requested a higher key pos than in the buffer, skipping ahead from min %#llx to %#llx",
|
||||
(unsigned long long)gkcrypt->key_buf_key_pos_min,
|
||||
(unsigned long long)key_pos);
|
||||
|
@ -533,7 +541,7 @@ CHIAKI_EXPORT void chiaki_key_state_init(ChiakiKeyState *state)
|
|||
state->prev = 0;
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT uint64_t chiaki_key_state_request_pos(ChiakiKeyState *state, uint32_t low)
|
||||
CHIAKI_EXPORT uint64_t chiaki_key_state_request_pos(ChiakiKeyState *state, uint32_t low, bool commit)
|
||||
{
|
||||
uint32_t prev_low = (uint32_t)state->prev;
|
||||
uint32_t high = (uint32_t)(state->prev >> 32);
|
||||
|
@ -541,5 +549,13 @@ CHIAKI_EXPORT uint64_t chiaki_key_state_request_pos(ChiakiKeyState *state, uint3
|
|||
high++;
|
||||
else if(chiaki_seq_num_32_lt(low, prev_low) && low > prev_low && high)
|
||||
high--;
|
||||
return state->prev = (((uint64_t)high) << 32) | ((uint64_t)low);
|
||||
uint64_t res = (((uint64_t)high) << 32) | ((uint64_t)low);
|
||||
if(commit)
|
||||
state->prev = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT void chiaki_key_state_commit(ChiakiKeyState *state, uint64_t prev)
|
||||
{
|
||||
state->prev = prev;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <pb_decode.h>
|
||||
#include <pb.h>
|
||||
#include <chiaki/takion.h>
|
||||
#include <chiaki/gkcrypt.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h>
|
||||
|
@ -85,6 +86,8 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_senkusha_init(ChiakiSenkusha *senkusha, Chi
|
|||
senkusha->ping_tag = 0;
|
||||
senkusha->pong_time_us = 0;
|
||||
|
||||
chiaki_key_state_init(&senkusha->takion.key_state);
|
||||
|
||||
return CHIAKI_ERR_SUCCESS;
|
||||
|
||||
error_state_mutex:
|
||||
|
|
104
lib/src/takion.c
104
lib/src/takion.c
|
@ -3,6 +3,7 @@
|
|||
#include <chiaki/takion.h>
|
||||
#include <chiaki/congestioncontrol.h>
|
||||
#include <chiaki/random.h>
|
||||
#include <chiaki/gkcrypt.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -71,6 +72,8 @@ int takion_packet_type_mac_offset(TakionPacketType type)
|
|||
case TAKION_PACKET_TYPE_VIDEO:
|
||||
case TAKION_PACKET_TYPE_AUDIO:
|
||||
return 0xa;
|
||||
case TAKION_PACKET_TYPE_CONGESTION:
|
||||
return 7;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -88,6 +91,8 @@ int takion_packet_type_key_pos_offset(TakionPacketType type)
|
|||
case TAKION_PACKET_TYPE_VIDEO:
|
||||
case TAKION_PACKET_TYPE_AUDIO:
|
||||
return 0xe;
|
||||
case TAKION_PACKET_TYPE_CONGESTION:
|
||||
return 0xb;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -107,7 +112,7 @@ typedef struct takion_message_t
|
|||
{
|
||||
uint32_t tag;
|
||||
//uint8_t zero[4];
|
||||
uint32_t key_pos;
|
||||
uint64_t key_pos;
|
||||
|
||||
uint8_t chunk_type;
|
||||
uint8_t chunk_flags;
|
||||
|
@ -162,7 +167,7 @@ static void takion_handle_packet_message(ChiakiTakion *takion, uint8_t *buf, siz
|
|||
static void takion_handle_packet_message_data(ChiakiTakion *takion, uint8_t *packet_buf, size_t packet_buf_size, uint8_t type_b, uint8_t *payload, size_t payload_size);
|
||||
static void takion_handle_packet_message_data_ack(ChiakiTakion *takion, uint8_t flags, uint8_t *buf, size_t buf_size);
|
||||
static ChiakiErrorCode takion_parse_message(ChiakiTakion *takion, uint8_t *buf, size_t buf_size, TakionMessage *msg);
|
||||
static void takion_write_message_header(uint8_t *buf, uint32_t tag, uint32_t key_pos, uint8_t chunk_type, uint8_t chunk_flags, size_t payload_data_size);
|
||||
static void takion_write_message_header(uint8_t *buf, uint32_t tag, uint64_t key_pos, uint8_t chunk_type, uint8_t chunk_flags, size_t payload_data_size);
|
||||
static ChiakiErrorCode takion_send_message_init(ChiakiTakion *takion, TakionMessagePayloadInit *payload);
|
||||
static ChiakiErrorCode takion_send_message_cookie(ChiakiTakion *takion, uint8_t *cookie);
|
||||
static ChiakiErrorCode takion_recv(ChiakiTakion *takion, uint8_t *buf, size_t *buf_size, uint64_t timeout_ms);
|
||||
|
@ -304,7 +309,7 @@ CHIAKI_EXPORT void chiaki_takion_close(ChiakiTakion *takion)
|
|||
chiaki_mutex_fini(&takion->gkcrypt_local_mutex);
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_crypt_advance_key_pos(ChiakiTakion *takion, size_t data_size, size_t *key_pos)
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_crypt_advance_key_pos(ChiakiTakion *takion, size_t data_size, uint64_t *key_pos)
|
||||
{
|
||||
ChiakiErrorCode err = chiaki_mutex_lock(&takion->gkcrypt_local_mutex);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
|
@ -312,7 +317,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_crypt_advance_key_pos(ChiakiTakion *
|
|||
|
||||
if(takion->gkcrypt_local)
|
||||
{
|
||||
size_t cur = takion->key_pos_local;
|
||||
uint64_t cur = takion->key_pos_local;
|
||||
if(SIZE_MAX - cur < data_size)
|
||||
{
|
||||
chiaki_mutex_unlock(&takion->gkcrypt_local_mutex);
|
||||
|
@ -337,8 +342,26 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_raw(ChiakiTakion *takion, const
|
|||
return CHIAKI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static ChiakiErrorCode chiaki_takion_packet_read_key_pos(ChiakiTakion *takion, uint8_t *buf, size_t buf_size, uint64_t *key_pos_out)
|
||||
{
|
||||
if(buf_size < 1)
|
||||
return CHIAKI_ERR_BUF_TOO_SMALL;
|
||||
|
||||
static ChiakiErrorCode chiaki_takion_packet_mac(ChiakiGKCrypt *crypt, uint8_t *buf, size_t buf_size, uint8_t *mac_out, uint8_t *mac_old_out, ChiakiTakionPacketKeyPos *key_pos_out)
|
||||
TakionPacketType base_type = buf[0] & TAKION_PACKET_BASE_TYPE_MASK;
|
||||
int key_pos_offset = takion_packet_type_key_pos_offset(base_type);
|
||||
if(key_pos_offset < 0)
|
||||
return CHIAKI_ERR_INVALID_DATA;
|
||||
|
||||
if(buf_size < key_pos_offset + sizeof(uint32_t))
|
||||
return CHIAKI_ERR_BUF_TOO_SMALL;
|
||||
|
||||
uint32_t key_pos_low = ntohl(*((chiaki_unaligned_uint32_t *)(buf + key_pos_offset)));
|
||||
*key_pos_out = chiaki_key_state_request_pos(&takion->key_state, key_pos_low, false);
|
||||
|
||||
return CHIAKI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static ChiakiErrorCode chiaki_takion_packet_mac(ChiakiGKCrypt *crypt, uint8_t *buf, size_t buf_size, uint64_t key_pos, uint8_t *mac_out, uint8_t *mac_old_out)
|
||||
{
|
||||
if(buf_size < 1)
|
||||
return CHIAKI_ERR_BUF_TOO_SMALL;
|
||||
|
@ -349,7 +372,7 @@ static ChiakiErrorCode chiaki_takion_packet_mac(ChiakiGKCrypt *crypt, uint8_t *b
|
|||
if(mac_offset < 0 || key_pos_offset < 0)
|
||||
return CHIAKI_ERR_INVALID_DATA;
|
||||
|
||||
if(buf_size < mac_offset + CHIAKI_GKCRYPT_GMAC_SIZE || buf_size < key_pos_offset + sizeof(ChiakiTakionPacketKeyPos))
|
||||
if(buf_size < mac_offset + CHIAKI_GKCRYPT_GMAC_SIZE || buf_size < key_pos_offset + sizeof(uint32_t))
|
||||
return CHIAKI_ERR_BUF_TOO_SMALL;
|
||||
|
||||
if(mac_old_out)
|
||||
|
@ -357,31 +380,31 @@ static ChiakiErrorCode chiaki_takion_packet_mac(ChiakiGKCrypt *crypt, uint8_t *b
|
|||
|
||||
memset(buf + mac_offset, 0, CHIAKI_GKCRYPT_GMAC_SIZE);
|
||||
|
||||
ChiakiTakionPacketKeyPos key_pos = ntohl(*((ChiakiTakionPacketKeyPos *)(buf + key_pos_offset)));
|
||||
|
||||
if(crypt)
|
||||
{
|
||||
uint8_t key_pos_tmp[sizeof(uint32_t)];
|
||||
if(base_type == TAKION_PACKET_TYPE_CONTROL)
|
||||
memset(buf + key_pos_offset, 0, sizeof(ChiakiTakionPacketKeyPos));
|
||||
{
|
||||
memcpy(key_pos_tmp, buf + key_pos_offset, sizeof(uint32_t));
|
||||
memset(buf + key_pos_offset, 0, sizeof(uint32_t));
|
||||
}
|
||||
chiaki_gkcrypt_gmac(crypt, key_pos, buf, buf_size, buf + mac_offset);
|
||||
*((ChiakiTakionPacketKeyPos *)(buf + key_pos_offset)) = htonl(key_pos);
|
||||
if(base_type == TAKION_PACKET_TYPE_CONTROL)
|
||||
memcpy(buf + key_pos_offset, key_pos_tmp, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
if(key_pos_out)
|
||||
*key_pos_out = key_pos;
|
||||
|
||||
memcpy(mac_out, buf + mac_offset, CHIAKI_GKCRYPT_GMAC_SIZE);
|
||||
|
||||
return CHIAKI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send(ChiakiTakion *takion, uint8_t *buf, size_t buf_size)
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send(ChiakiTakion *takion, uint8_t *buf, size_t buf_size, uint64_t key_pos)
|
||||
{
|
||||
ChiakiErrorCode err = chiaki_mutex_lock(&takion->gkcrypt_local_mutex);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
return err;
|
||||
uint8_t mac[CHIAKI_GKCRYPT_GMAC_SIZE];
|
||||
err = chiaki_takion_packet_mac(takion->gkcrypt_local, buf, buf_size, mac, NULL, NULL);
|
||||
err = chiaki_takion_packet_mac(takion->gkcrypt_local, buf, buf_size, key_pos, mac, NULL);
|
||||
chiaki_mutex_unlock(&takion->gkcrypt_local_mutex);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
return err;
|
||||
|
@ -397,7 +420,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_message_data(ChiakiTakion *taki
|
|||
// TODO: can we make this more memory-efficient?
|
||||
// TODO: split packet if necessary?
|
||||
|
||||
size_t key_pos;
|
||||
uint64_t key_pos;
|
||||
ChiakiErrorCode err = chiaki_takion_crypt_advance_key_pos(takion, buf_size, &key_pos);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
return err;
|
||||
|
@ -424,7 +447,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_message_data(ChiakiTakion *taki
|
|||
*(msg_payload + 8) = 0;
|
||||
memcpy(msg_payload + 9, buf, buf_size);
|
||||
|
||||
err = chiaki_takion_send(takion, packet_buf, packet_size); // will alter packet_buf with gmac
|
||||
err = chiaki_takion_send(takion, packet_buf, packet_size, key_pos); // will alter packet_buf with gmac
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
CHIAKI_LOGE(takion->log, "Takion failed to send data packet: %s", chiaki_error_string(err));
|
||||
|
@ -445,7 +468,7 @@ static ChiakiErrorCode chiaki_takion_send_message_data_ack(ChiakiTakion *takion,
|
|||
uint8_t buf[1 + TAKION_MESSAGE_HEADER_SIZE + 0xc];
|
||||
buf[0] = TAKION_PACKET_TYPE_CONTROL;
|
||||
|
||||
size_t key_pos;
|
||||
uint64_t key_pos;
|
||||
ChiakiErrorCode err = chiaki_takion_crypt_advance_key_pos(takion, sizeof(buf), &key_pos);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
return err;
|
||||
|
@ -458,7 +481,7 @@ static ChiakiErrorCode chiaki_takion_send_message_data_ack(ChiakiTakion *takion,
|
|||
*((chiaki_unaligned_uint16_t *)(data_ack + 8)) = 0;
|
||||
*((chiaki_unaligned_uint16_t *)(data_ack + 0xa)) = 0;
|
||||
|
||||
return chiaki_takion_send(takion, buf, sizeof(buf));
|
||||
return chiaki_takion_send(takion, buf, sizeof(buf), key_pos);
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_congestion(ChiakiTakion *takion, ChiakiTakionCongestionPacket *packet)
|
||||
|
@ -470,19 +493,15 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_congestion(ChiakiTakion *takion
|
|||
*((chiaki_unaligned_uint16_t *)(buf + 3)) = htons(packet->word_1);
|
||||
*((chiaki_unaligned_uint16_t *)(buf + 5)) = htons(packet->word_2);
|
||||
|
||||
ChiakiErrorCode err = chiaki_mutex_lock(&takion->gkcrypt_local_mutex);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
return err;
|
||||
*((chiaki_unaligned_uint32_t *)(buf + 0xb)) = htonl((uint32_t)takion->key_pos_local); // TODO: is this correct? shouldn't key_pos be 0 for mac calculation?
|
||||
err = chiaki_gkcrypt_gmac(takion->gkcrypt_local, takion->key_pos_local, buf, sizeof(buf), buf + 7);
|
||||
takion->key_pos_local += sizeof(buf);
|
||||
chiaki_mutex_unlock(&takion->gkcrypt_local_mutex);
|
||||
uint64_t key_pos;
|
||||
ChiakiErrorCode err = chiaki_takion_crypt_advance_key_pos(takion, sizeof(buf), &key_pos);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
return err;
|
||||
*((chiaki_unaligned_uint32_t *)(buf + 0xb)) = htonl((uint32_t)key_pos); // TODO: is this correct? shouldn't key_pos be 0 for mac calculation?
|
||||
|
||||
//chiaki_log_hexdump(takion->log, CHIAKI_LOG_DEBUG, buf, sizeof(buf));
|
||||
|
||||
return chiaki_takion_send_raw(takion, buf, sizeof(buf));
|
||||
return chiaki_takion_send(takion, buf, sizeof(buf), key_pos);
|
||||
}
|
||||
|
||||
static ChiakiErrorCode takion_send_feedback_packet(ChiakiTakion *takion, uint8_t *buf, size_t buf_size)
|
||||
|
@ -495,7 +514,7 @@ static ChiakiErrorCode takion_send_feedback_packet(ChiakiTakion *takion, uint8_t
|
|||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
return err;
|
||||
|
||||
size_t key_pos;
|
||||
uint64_t key_pos;
|
||||
err = chiaki_takion_crypt_advance_key_pos(takion, payload_size + CHIAKI_GKCRYPT_BLOCK_SIZE, &key_pos);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
goto beach;
|
||||
|
@ -780,8 +799,14 @@ static ChiakiErrorCode takion_handle_packet_mac(ChiakiTakion *takion, uint8_t ba
|
|||
|
||||
uint8_t mac[CHIAKI_GKCRYPT_GMAC_SIZE];
|
||||
uint8_t mac_expected[CHIAKI_GKCRYPT_GMAC_SIZE];
|
||||
ChiakiTakionPacketKeyPos key_pos;
|
||||
ChiakiErrorCode err = chiaki_takion_packet_mac(takion->gkcrypt_remote, buf, buf_size, mac_expected, mac, &key_pos);
|
||||
uint64_t key_pos;
|
||||
ChiakiErrorCode err = chiaki_takion_packet_read_key_pos(takion, buf, buf_size, &key_pos);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
CHIAKI_LOGE(takion->log, "Takion failed to pull key_pos out of received packet");
|
||||
return err;
|
||||
}
|
||||
err = chiaki_takion_packet_mac(takion->gkcrypt_remote, buf, buf_size, key_pos, mac_expected, mac);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
CHIAKI_LOGE(takion->log, "Takion failed to calculate mac for received packet");
|
||||
|
@ -799,6 +824,8 @@ static ChiakiErrorCode takion_handle_packet_mac(ChiakiTakion *takion, uint8_t ba
|
|||
return CHIAKI_ERR_INVALID_MAC;
|
||||
}
|
||||
|
||||
chiaki_key_state_commit(&takion->key_state, key_pos);
|
||||
|
||||
return CHIAKI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1014,7 +1041,7 @@ static void takion_handle_packet_message_data_ack(ChiakiTakion *takion, uint8_t
|
|||
*
|
||||
* @param raw_payload_size size of the actual data of the payload excluding type_a, type_b and payload_size
|
||||
*/
|
||||
static void takion_write_message_header(uint8_t *buf, uint32_t tag, uint32_t key_pos, uint8_t chunk_type, uint8_t chunk_flags, size_t payload_data_size)
|
||||
static void takion_write_message_header(uint8_t *buf, uint32_t tag, uint64_t key_pos, uint8_t chunk_type, uint8_t chunk_flags, size_t payload_data_size)
|
||||
{
|
||||
*((chiaki_unaligned_uint32_t *)(buf + 0)) = htonl(tag);
|
||||
memset(buf + 4, 0, CHIAKI_GKCRYPT_GMAC_SIZE);
|
||||
|
@ -1033,7 +1060,8 @@ static ChiakiErrorCode takion_parse_message(ChiakiTakion *takion, uint8_t *buf,
|
|||
}
|
||||
|
||||
msg->tag = ntohl(*((chiaki_unaligned_uint32_t *)buf));
|
||||
msg->key_pos = ntohl(*((chiaki_unaligned_uint32_t *)(buf + 0x8)));
|
||||
uint32_t key_pos_low = ntohl(*((chiaki_unaligned_uint32_t *)(buf + 0x8)));
|
||||
msg->key_pos = chiaki_key_state_request_pos(&takion->key_state, key_pos_low, true);
|
||||
msg->chunk_type = buf[0xc];
|
||||
msg->chunk_flags = buf[0xd];
|
||||
msg->payload_size = ntohs(*((chiaki_unaligned_uint16_t *)(buf + 0xe)));
|
||||
|
@ -1185,7 +1213,7 @@ static void takion_handle_packet_av(ChiakiTakion *takion, uint8_t base_type, uin
|
|||
assert(base_type == TAKION_PACKET_TYPE_VIDEO || base_type == TAKION_PACKET_TYPE_AUDIO);
|
||||
|
||||
ChiakiTakionAVPacket packet;
|
||||
ChiakiErrorCode err = takion->av_packet_parse(&packet, buf, buf_size);
|
||||
ChiakiErrorCode err = takion->av_packet_parse(&packet, &takion->key_state, buf, buf_size);
|
||||
if(err != CHIAKI_ERR_SUCCESS)
|
||||
{
|
||||
if(err == CHIAKI_ERR_BUF_TOO_SMALL)
|
||||
|
@ -1202,7 +1230,7 @@ static void takion_handle_packet_av(ChiakiTakion *takion, uint8_t base_type, uin
|
|||
}
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v9_av_packet_parse(ChiakiTakionAVPacket *packet, uint8_t *buf, size_t buf_size)
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v9_av_packet_parse(ChiakiTakionAVPacket *packet, ChiakiKeyState *key_state, uint8_t *buf, size_t buf_size)
|
||||
{
|
||||
memset(packet, 0, sizeof(ChiakiTakionAVPacket));
|
||||
|
||||
|
@ -1242,8 +1270,8 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v9_av_packet_parse(ChiakiTakionAVPac
|
|||
}
|
||||
|
||||
packet->codec = av[8];
|
||||
|
||||
packet->key_pos = ntohl(*((chiaki_unaligned_uint32_t *)(av + 0xd)));
|
||||
uint32_t key_pos_low = ntohl(*((chiaki_unaligned_uint32_t *)(av + 0xd)));
|
||||
packet->key_pos = chiaki_key_state_request_pos(key_state, key_pos_low, true);
|
||||
|
||||
uint8_t unknown_1 = av[0x11];
|
||||
|
||||
|
@ -1313,7 +1341,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v7_av_packet_format_header(uint8_t *
|
|||
|
||||
*(chiaki_unaligned_uint32_t *)(buf + 0xa) = 0; // unknown
|
||||
|
||||
*(chiaki_unaligned_uint32_t *)(buf + 0xe) = packet->key_pos;
|
||||
*(chiaki_unaligned_uint32_t *)(buf + 0xe) = (uint32_t)packet->key_pos;
|
||||
|
||||
uint8_t *cur = buf + 0x12;
|
||||
if(packet->is_video)
|
||||
|
@ -1332,7 +1360,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v7_av_packet_format_header(uint8_t *
|
|||
return CHIAKI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v7_av_packet_parse(ChiakiTakionAVPacket *packet, uint8_t *buf, size_t buf_size)
|
||||
CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_v7_av_packet_parse(ChiakiTakionAVPacket *packet, ChiakiKeyState *key_state, uint8_t *buf, size_t buf_size)
|
||||
{
|
||||
memset(packet, 0, sizeof(ChiakiTakionAVPacket));
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue