diff --git a/src/encrypt.c b/src/encrypt.c index 6aab823d..301dfca4 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -1511,7 +1511,12 @@ int ss_check_hash(char **buf_ptr, ssize_t *buf_len, struct chunk *chunk, int buf if (cidx == chunk->len + AUTH_BYTES) { // Compare hash uint8_t *hash = (uint8_t *)malloc(chunk->len); - crypto_generichash(hash, HASH_BYTES, (uint8_t *)chunk->buf + AUTH_BYTES, chunk->len, NULL, 0); + uint8_t key[MAX_KEY_LENGTH + sizeof(uint32_t)]; + + memcpy(key, enc_key, enc_key_len); + memcpy(key + enc_key_len, &chunk->counter, sizeof(uint32_t)); + crypto_generichash(hash, HASH_BYTES, (uint8_t *)chunk->buf + AUTH_BYTES, chunk->len, + key, enc_key_len + sizeof(uint32_t)); if (memcmp(hash, chunk->buf + CLEN_BYTES, HASH_BYTES) != 0) return 0; @@ -1523,6 +1528,7 @@ int ss_check_hash(char **buf_ptr, ssize_t *buf_len, struct chunk *chunk, int buf j += chunk->len; k = j; cidx = 0; + chunk->counter++; } } @@ -1532,7 +1538,7 @@ int ss_check_hash(char **buf_ptr, ssize_t *buf_len, struct chunk *chunk, int buf return 1; } -char *ss_gen_hash(char *buf, ssize_t *buf_len, int buf_size) +char *ss_gen_hash(char *buf, ssize_t *buf_len, uint32_t *counter, int buf_size) { ssize_t blen = *buf_len; int size = max(AUTH_BYTES + blen, buf_size); @@ -1543,12 +1549,17 @@ char *ss_gen_hash(char *buf, ssize_t *buf_len, int buf_size) uint16_t chunk_len = htons((uint16_t)blen); uint8_t hash[HASH_BYTES]; - crypto_generichash(hash, HASH_BYTES, (uint8_t *)buf, blen, NULL, 0); + uint8_t key[MAX_KEY_LENGTH + sizeof(uint32_t)]; + + memcpy(key, enc_key, enc_key_len); + memcpy(key + enc_key_len, counter, sizeof(uint32_t)); + crypto_generichash(hash, HASH_BYTES, (uint8_t *)buf, blen, key, enc_key_len + sizeof(uint32_t)); memmove(buf + AUTH_BYTES, buf, blen); memcpy(buf + CLEN_BYTES, hash, HASH_BYTES); memcpy(buf, &chunk_len, CLEN_BYTES); *buf_len = blen + AUTH_BYTES; + *counter = *counter + 1; return buf; } diff --git a/src/encrypt.h b/src/encrypt.h index 43bc6552..df148af5 100644 --- a/src/encrypt.h +++ b/src/encrypt.h @@ -156,6 +156,7 @@ typedef struct { struct chunk { uint32_t idx; uint32_t len; + uint32_t counter; char *buf; }; @@ -181,6 +182,6 @@ int ss_onetimeauth(char *auth, char *msg, int msg_len, struct enc_ctx *ctx); int ss_onetimeauth_verify(char *auth, char *msg, int msg_len, struct enc_ctx *ctx); int ss_check_hash(char **buf_ptr, ssize_t *buf_len, struct chunk *chunk, int buf_size); -char *ss_gen_hash(char *buf, ssize_t *buf_len, int buf_size); +char *ss_gen_hash(char *buf, ssize_t *buf_len, uint32_t *counter, int buf_size); #endif // _ENCRYPT_H diff --git a/src/local.c b/src/local.c index 4bc6ee34..016356b9 100644 --- a/src/local.c +++ b/src/local.c @@ -245,7 +245,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) } if (!remote->direct && remote->send_ctx->connected && auth) { - remote->buf = ss_gen_hash(remote->buf, &r, BUF_SIZE); + remote->buf = ss_gen_hash(remote->buf, &r, &remote->counter, BUF_SIZE); } // insert shadowsocks header @@ -485,7 +485,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) if (r > 0) { if (auth) { - buf = ss_gen_hash(buf, &r, BUF_SIZE); + buf = ss_gen_hash(buf, &r, &remote->counter, BUF_SIZE); } memcpy(remote->buf + addr_len, buf, r); } diff --git a/src/local.h b/src/local.h index 27588910..edbfa9c5 100644 --- a/src/local.h +++ b/src/local.h @@ -81,6 +81,7 @@ struct remote { struct server *server; struct sockaddr_storage addr; int addr_len; + uint32_t counter; }; #endif // _LOCAL_H diff --git a/src/redir.c b/src/redir.c index 38b2ab01..8c4427ae 100644 --- a/src/redir.c +++ b/src/redir.c @@ -185,7 +185,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) } if (auth) { - remote->buf = ss_gen_hash(remote->buf, &r, BUF_SIZE); + remote->buf = ss_gen_hash(remote->buf, &r, &remote->counter, BUF_SIZE); } remote->buf = ss_encrypt(BUF_SIZE, remote->buf, &r, server->e_ctx); diff --git a/src/redir.h b/src/redir.h index 57a7f57c..398f5700 100644 --- a/src/redir.h +++ b/src/redir.h @@ -70,6 +70,7 @@ struct remote { struct remote_ctx *recv_ctx; struct remote_ctx *send_ctx; struct server *server; + uint32_t counter; }; #endif // _LOCAL_H diff --git a/src/server.c b/src/server.c index 72940335..11de6f99 100644 --- a/src/server.c +++ b/src/server.c @@ -547,6 +547,8 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) * +------+---------+-------------+------+ * | 2 | 4 | Variable | ... * +------+---------+-------------+------+ + * + * The key of BLAKE2b is (KEY + CHUNK ID) */ int offset = 0; diff --git a/src/tunnel.c b/src/tunnel.c index b2fff704..ef575355 100644 --- a/src/tunnel.c +++ b/src/tunnel.c @@ -197,7 +197,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) } if (auth) { - remote->buf = ss_gen_hash(remote->buf, &r, BUF_SIZE); + remote->buf = ss_gen_hash(remote->buf, &r, &remote->counter, BUF_SIZE); } remote->buf = ss_encrypt(BUF_SIZE, remote->buf, &r, server->e_ctx); diff --git a/src/tunnel.h b/src/tunnel.h index 3ac4317e..16f2b0b3 100644 --- a/src/tunnel.h +++ b/src/tunnel.h @@ -74,6 +74,7 @@ struct remote { struct remote_ctx *recv_ctx; struct remote_ctx *send_ctx; struct server *server; + uint32_t counter; }; #endif // _TUNNEL_H