Use ChiakiKeyState to 32bit fix key state overflow (Fix #172) (#359)

This commit is contained in:
Sven Scharmentke 2020-11-04 11:45:05 +01:00 committed by GitHub
commit 59e6603256
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 272 additions and 108 deletions

View file

@ -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
}

View file

@ -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
}