Browse Source

add auth to udprelay

pull/405/head
Max Lv 9 years ago
parent
commit
0e79c93ad1
7 changed files with 50 additions and 32 deletions
  1. 58
      src/encrypt.c
  2. 8
      src/encrypt.h
  3. 2
      src/local.c
  4. 2
      src/redir.c
  5. 2
      src/server.c
  6. 2
      src/tunnel.c
  7. 8
      src/udprelay.c

58
src/encrypt.c

@ -790,6 +790,8 @@ void cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
return;
}
enc_iv_len = 0;
if (method >= SALSA20) {
enc_iv_len = supported_ciphers_iv_size[method];
return;
@ -1029,27 +1031,27 @@ static int cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, size_t *ole
#endif
}
int ss_onetimeauth(char *auth, char *msg, int msg_len, struct enc_ctx *ctx)
int ss_onetimeauth(char *auth, char *msg, int msg_len, uint8_t *iv)
{
uint8_t auth_key[MAX_IV_LENGTH + MAX_KEY_LENGTH];
memcpy(auth_key, ctx->evp.iv, enc_iv_len);
memcpy(auth_key, iv, enc_iv_len);
memcpy(auth_key + enc_iv_len, enc_key, enc_key_len);
sha1_hmac(auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)auth);
return 0;
}
int ss_onetimeauth_verify(char *auth, char *msg, int msg_len, struct enc_ctx *ctx)
int ss_onetimeauth_verify(char *auth, char *msg, int msg_len, uint8_t *iv)
{
uint8_t hash[ONETIMEAUTH_BYTES];
uint8_t auth_key[MAX_IV_LENGTH + MAX_KEY_LENGTH];
memcpy(auth_key, ctx->evp.iv, enc_iv_len);
memcpy(auth_key, iv, enc_iv_len);
memcpy(auth_key + enc_iv_len, enc_key, enc_key_len);
sha1_hmac(auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, hash);
return memcmp(auth, hash, ONETIMEAUTH_BYTES);
}
char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method)
char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method, int auth)
{
if (method > TABLE) {
cipher_ctx_t evp;
@ -1069,10 +1071,21 @@ char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method)
char *ciphertext = tmp_buf;
uint8_t iv[MAX_IV_LENGTH];
rand_bytes(iv, iv_len);
cipher_context_set_iv(&evp, iv, iv_len, 1);
memcpy(ciphertext, iv, iv_len);
if (auth) {
char hash[ONETIMEAUTH_BYTES];
ss_onetimeauth(hash, plaintext, p_len, iv);
if (buf_size < ONETIMEAUTH_BYTES + p_len) {
plaintext = realloc(plaintext, ONETIMEAUTH_BYTES + p_len);
memcpy(plaintext + p_len, hash, ONETIMEAUTH_BYTES);
p_len = c_len = p_len + ONETIMEAUTH_BYTES;
}
}
if (method >= SALSA20) {
crypto_stream_xor_ic((uint8_t *)(ciphertext + iv_len),
(const uint8_t *)plaintext, (uint64_t)(p_len),
@ -1097,8 +1110,8 @@ char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method)
cipher_context_release(&evp);
if (*len < iv_len + c_len) {
plaintext = realloc(plaintext, max(iv_len + c_len, buf_size));
if (buf_size < iv_len + c_len) {
plaintext = realloc(plaintext, iv_len + c_len);
}
*len = iv_len + c_len;
memcpy(plaintext, ciphertext, *len);
@ -1183,8 +1196,8 @@ char * ss_encrypt(int buf_size, char *plaintext, ssize_t *len,
dump("CIPHER", ciphertext + iv_len, c_len);
#endif
if (*len < iv_len + c_len) {
plaintext = realloc(plaintext, max(iv_len + c_len, buf_size));
if (buf_size < iv_len + c_len) {
plaintext = realloc(plaintext, iv_len + c_len);
}
*len = iv_len + c_len;
memcpy(plaintext, ciphertext, *len);
@ -1200,14 +1213,14 @@ char * ss_encrypt(int buf_size, char *plaintext, ssize_t *len,
}
}
char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method)
char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method, int auth)
{
if (method > TABLE) {
cipher_ctx_t evp;
cipher_context_init(&evp, method, 0);
size_t iv_len = enc_iv_len;
size_t c_len = *len, p_len = *len - iv_len;
int err = 1;
int ret = 1;
static int tmp_len = 0;
static char *tmp_buf = NULL;
@ -1228,12 +1241,18 @@ char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method)
(uint64_t)(c_len - iv_len),
(const uint8_t *)iv, 0, enc_key, method);
} else {
err = cipher_context_update(&evp, (uint8_t *)plaintext, &p_len,
ret = cipher_context_update(&evp, (uint8_t *)plaintext, &p_len,
(const uint8_t *)(ciphertext + iv_len),
c_len - iv_len);
}
if (!err) {
if (auth) {
char hash[ONETIMEAUTH_BYTES];
ret = !ss_onetimeauth_verify(hash, plaintext, p_len - ONETIMEAUTH_BYTES, iv);
if (ret) p_len -= ONETIMEAUTH_BYTES;
}
if (!ret) {
free(ciphertext);
cipher_context_release(&evp);
return NULL;
@ -1246,8 +1265,8 @@ char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method)
cipher_context_release(&evp);
if (*len < p_len) {
ciphertext = realloc(ciphertext, max(p_len, buf_size));
if (buf_size < p_len) {
ciphertext = realloc(ciphertext, p_len);
}
*len = p_len;
memcpy(ciphertext, plaintext, *len);
@ -1308,8 +1327,7 @@ char * ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *
tmp_buf = plaintext;
}
if (padding) {
ciphertext =
realloc(ciphertext, max(c_len + padding, buf_size));
ciphertext = realloc(ciphertext, max(c_len + padding, buf_size));
memmove(ciphertext + iv_len + padding, ciphertext + iv_len,
c_len - iv_len);
memset(ciphertext + iv_len, 0, padding);
@ -1340,8 +1358,8 @@ char * ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *
dump("CIPHER", ciphertext + iv_len, c_len - iv_len);
#endif
if (*len < p_len) {
ciphertext = realloc(ciphertext, max(p_len, buf_size));
if (buf_size < p_len) {
ciphertext = realloc(ciphertext, p_len);
}
*len = p_len;
memcpy(ciphertext, plaintext, *len);
@ -1501,7 +1519,7 @@ int ss_check_hash(char **buf_ptr, ssize_t *buf_len, struct chunk *chunk, struct
if (cidx == CLEN_BYTES) {
uint16_t clen = ntohs(*((uint16_t *)chunk->buf));
if (chunk->len < clen) {
if (buf_size < clen + AUTH_BYTES) {
chunk->buf = realloc(chunk->buf, clen + AUTH_BYTES);
}
chunk->len = clen;

8
src/encrypt.h

@ -164,8 +164,8 @@ struct enc_ctx {
cipher_ctx_t evp;
};
char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method);
char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method);
char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method, int auth);
char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method, int auth);
char * ss_encrypt(int buf_size, char *plaintext, ssize_t *len,
struct enc_ctx *ctx);
char * ss_decrypt(int buf_size, char *ciphertext, ssize_t *len,
@ -176,8 +176,8 @@ int enc_get_iv_len(void);
void cipher_context_release(cipher_ctx_t *evp);
unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md);
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_onetimeauth(char *auth, char *msg, int msg_len, uint8_t *iv);
int ss_onetimeauth_verify(char *auth, char *msg, int msg_len, uint8_t *iv);
int ss_check_hash(char **buf_ptr, ssize_t *buf_len, struct chunk *chunk, struct enc_ctx *ctx, int buf_size);
char *ss_gen_hash(char *buf, ssize_t *buf_len, uint32_t *counter, struct enc_ctx *ctx, int buf_size);

2
src/local.c

@ -477,7 +477,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
if (!remote->direct) {
if (auth) {
ss_addr_to_send[0] |= ONETIMEAUTH_FLAG;
ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len, server->e_ctx);
ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len, server->e_ctx->evp.iv);
addr_len += ONETIMEAUTH_BYTES;
}

2
src/redir.c

@ -377,7 +377,7 @@ static void remote_send_cb(EV_P_ ev_io *w, int revents)
if (auth) {
ss_addr_to_send[0] |= ONETIMEAUTH_FLAG;
ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len, server->e_ctx);
ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len, server->e_ctx->evp.iv);
addr_len += ONETIMEAUTH_BYTES;
}

2
src/server.c

@ -664,7 +664,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
offset += 2;
if (auth || (atyp & ONETIMEAUTH_FLAG)) {
if (ss_onetimeauth_verify(server->buf + offset, server->buf, offset, server->d_ctx)) {
if (ss_onetimeauth_verify(server->buf + offset, server->buf, offset, server->d_ctx->evp.iv)) {
LOGE("authentication error %d", atyp);
report_addr(server->fd);
close_and_free_server(EV_A_ server);

2
src/tunnel.c

@ -416,7 +416,7 @@ static void remote_send_cb(EV_P_ ev_io *w, int revents)
if (auth) {
ss_addr_to_send[0] |= ONETIMEAUTH_FLAG;
ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len, server->e_ctx);
ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len, server->e_ctx->evp.iv);
addr_len += ONETIMEAUTH_BYTES;
}

8
src/udprelay.c

@ -648,7 +648,7 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
}
#ifdef UDPRELAY_LOCAL
buf = ss_decrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method);
buf = ss_decrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method, 0);
if (buf == NULL) {
ERROR("[udp] server_ss_decrypt_all");
goto CLEAN_UP;
@ -708,7 +708,7 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
memcpy(buf, addr_header, addr_header_len);
buf_len += addr_header_len;
buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method);
buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method, 0);
#endif
size_t remote_src_addr_len = get_sockaddr_len((struct sockaddr *)&remote_ctx->src_addr);
@ -826,7 +826,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
tx += buf_len;
buf = ss_decrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method);
buf = ss_decrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method, 1);
if (buf == NULL) {
ERROR("[udp] server_ss_decrypt_all");
goto CLEAN_UP;
@ -1081,7 +1081,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
memmove(buf, buf + offset, buf_len);
}
buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method);
buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method, 1);
int s = sendto(remote_ctx->fd, buf, buf_len, 0, remote_addr, remote_addr_len);

Loading…
Cancel
Save