Add a very simple encryption layer for testing
This commit is contained in:
1
Makefile
1
Makefile
@@ -1,6 +1,7 @@
|
|||||||
CC := gcc
|
CC := gcc
|
||||||
LDFLAGS := -Wl,-O1,--sort-common,--as-needed
|
LDFLAGS := -Wl,-O1,--sort-common,--as-needed
|
||||||
CFLAGS := -ffreestanding -Wall -Wextra
|
CFLAGS := -ffreestanding -Wall -Wextra
|
||||||
|
LDLIBS := -lsodium
|
||||||
|
|
||||||
prefix := /usr/local
|
prefix := /usr/local
|
||||||
|
|
||||||
|
|||||||
208
glorytun.c
208
glorytun.c
@@ -16,7 +16,9 @@
|
|||||||
# include <linux/if_tun.h>
|
# include <linux/if_tun.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GT_BUFFER_SIZE (32*1024)
|
#include <sodium.h>
|
||||||
|
|
||||||
|
#define GT_BUFFER_SIZE (4*1024*1024)
|
||||||
|
|
||||||
struct option {
|
struct option {
|
||||||
char *name;
|
char *name;
|
||||||
@@ -30,6 +32,12 @@ struct netio {
|
|||||||
buffer_t send; // TODO
|
buffer_t send; // TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct crypto_ctx {
|
||||||
|
crypto_aead_aes256gcm_state state;
|
||||||
|
uint8_t nonce_w[crypto_aead_aes256gcm_NPUBBYTES];
|
||||||
|
uint8_t nonce_r[crypto_aead_aes256gcm_NPUBBYTES];
|
||||||
|
};
|
||||||
|
|
||||||
volatile sig_atomic_t running;
|
volatile sig_atomic_t running;
|
||||||
|
|
||||||
static void fd_set_nonblock (int fd)
|
static void fd_set_nonblock (int fd)
|
||||||
@@ -251,25 +259,89 @@ static ssize_t fd_write (int fd, const void *data, size_t size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static ssize_t fd_read_all (int fd, void *data, size_t size)
|
||||||
static ssize_t fd_writev (int fd, const struct iovec *iov, int count)
|
|
||||||
{
|
{
|
||||||
if (!count)
|
size_t done = 0;
|
||||||
return -2;
|
|
||||||
|
|
||||||
ssize_t ret = writev(fd, iov, count);
|
while (done<size) {
|
||||||
|
ssize_t ret = fd_read(fd, data+done, size-done);
|
||||||
|
|
||||||
if (ret==-1) {
|
if (!ret)
|
||||||
if (errno==EAGAIN || errno==EINTR)
|
break;
|
||||||
return -1;
|
|
||||||
if (errno)
|
if (ret>0)
|
||||||
perror("write");
|
done += ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fd_write_all (int fd, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
size_t done = 0;
|
||||||
|
|
||||||
|
while (done<size) {
|
||||||
|
ssize_t ret = fd_write(fd, data+done, size-done);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (ret>0)
|
||||||
|
done += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int encrypt_packet (struct crypto_ctx *ctx, uint8_t *packet, size_t size, buffer_t *buffer)
|
||||||
|
{
|
||||||
|
const size_t ws = size + crypto_aead_aes256gcm_ABYTES;
|
||||||
|
|
||||||
|
if (buffer_write_size(buffer) < ws)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
const int hs = 4;
|
||||||
|
|
||||||
|
byte_cpy(buffer->write, packet, size);
|
||||||
|
|
||||||
|
crypto_aead_aes256gcm_encrypt_afternm(
|
||||||
|
buffer->write + hs, NULL,
|
||||||
|
packet + hs, size - hs,
|
||||||
|
packet, hs,
|
||||||
|
NULL, ctx->nonce_w,
|
||||||
|
(const crypto_aead_aes256gcm_state *)&ctx->state);
|
||||||
|
|
||||||
|
sodium_increment(ctx->nonce_w, crypto_aead_aes256gcm_NPUBBYTES);
|
||||||
|
buffer->write += ws;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int decrypt_packet (struct crypto_ctx *ctx, uint8_t *packet, size_t size, buffer_t *buffer)
|
||||||
|
{
|
||||||
|
const size_t rs = size + crypto_aead_aes256gcm_ABYTES;
|
||||||
|
|
||||||
|
if (buffer_read_size(buffer) < rs)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
const int hs = 4;
|
||||||
|
|
||||||
|
byte_cpy(packet, buffer->read, hs);
|
||||||
|
|
||||||
|
if (crypto_aead_aes256gcm_decrypt_afternm(
|
||||||
|
packet + hs, NULL,
|
||||||
|
NULL,
|
||||||
|
buffer->read + hs, rs - hs,
|
||||||
|
packet, hs,
|
||||||
|
ctx->nonce_r,
|
||||||
|
(const crypto_aead_aes256gcm_state *)&ctx->state))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sodium_increment(ctx->nonce_r, crypto_aead_aes256gcm_NPUBBYTES);
|
||||||
|
buffer->read += rs;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
static int option_flag (void *data, _unused_ int argc, _unused_ char **argv)
|
static int option_flag (void *data, _unused_ int argc, _unused_ char **argv)
|
||||||
{
|
{
|
||||||
@@ -291,6 +363,7 @@ static int option_str (void *data, int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_unused_
|
||||||
static int option_long (void *data, int argc, char **argv)
|
static int option_long (void *data, int argc, char **argv)
|
||||||
{
|
{
|
||||||
if (argc<2 || !argv[1]) {
|
if (argc<2 || !argv[1]) {
|
||||||
@@ -370,10 +443,54 @@ static ssize_t get_ip_size (const uint8_t *data, size_t size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gt_setup_crypto (struct crypto_ctx *ctx, int fd, int listener)
|
||||||
|
{
|
||||||
|
unsigned char secret[crypto_scalarmult_SCALARBYTES];
|
||||||
|
unsigned char shared[crypto_scalarmult_BYTES];
|
||||||
|
|
||||||
|
unsigned char public_w[crypto_scalarmult_SCALARBYTES];
|
||||||
|
unsigned char public_r[crypto_scalarmult_SCALARBYTES];
|
||||||
|
|
||||||
|
randombytes_buf(secret, sizeof(secret));
|
||||||
|
crypto_scalarmult_base(public_w, secret);
|
||||||
|
|
||||||
|
if (!listener)
|
||||||
|
fd_write_all(fd, public_w, sizeof(public_w));
|
||||||
|
|
||||||
|
fd_read_all(fd, public_r, sizeof(public_r));
|
||||||
|
|
||||||
|
if (listener)
|
||||||
|
fd_write_all(fd, public_w, sizeof(public_w));
|
||||||
|
|
||||||
|
crypto_scalarmult(shared, secret, public_r);
|
||||||
|
crypto_aead_aes256gcm_beforenm(&ctx->state, shared);
|
||||||
|
|
||||||
|
sodium_memzero(secret, sizeof(secret));
|
||||||
|
sodium_memzero(shared, sizeof(shared));
|
||||||
|
|
||||||
|
sodium_memzero(public_w, sizeof(public_w));
|
||||||
|
sodium_memzero(public_r, sizeof(public_r));
|
||||||
|
|
||||||
|
randombytes_buf(ctx->nonce_w, sizeof(ctx->nonce_w));
|
||||||
|
|
||||||
|
fd_write_all(fd, ctx->nonce_w, sizeof(ctx->nonce_w));
|
||||||
|
fd_read_all(fd, ctx->nonce_r, sizeof(ctx->nonce_r));
|
||||||
|
}
|
||||||
|
|
||||||
int main (int argc, char **argv)
|
int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
gt_set_signal();
|
gt_set_signal();
|
||||||
|
|
||||||
|
if (sodium_init()==-1) {
|
||||||
|
printf("libsodium initialization has failed!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!crypto_aead_aes256gcm_is_available()) {
|
||||||
|
printf("AES-256-GCM is not available on your platform!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
char *host = NULL;
|
char *host = NULL;
|
||||||
char *port = "5000";
|
char *port = "5000";
|
||||||
char *dev = "glorytun";
|
char *dev = "glorytun";
|
||||||
@@ -442,6 +559,9 @@ int main (int argc, char **argv)
|
|||||||
sk_set_nodelay(sock.fd);
|
sk_set_nodelay(sock.fd);
|
||||||
sk_set_congestion(sock.fd, congestion);
|
sk_set_congestion(sock.fd, congestion);
|
||||||
|
|
||||||
|
struct crypto_ctx ctx;
|
||||||
|
gt_setup_crypto(&ctx, sock.fd, listener);
|
||||||
|
|
||||||
printf("running...\n");
|
printf("running...\n");
|
||||||
|
|
||||||
struct pollfd fds[] = {
|
struct pollfd fds[] = {
|
||||||
@@ -449,6 +569,14 @@ int main (int argc, char **argv)
|
|||||||
{ .fd = sock.fd, .events = POLLIN },
|
{ .fd = sock.fd, .events = POLLIN },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8_t buf[2048];
|
||||||
|
size_t size;
|
||||||
|
} tunr, tunw;
|
||||||
|
|
||||||
|
tunr.size = 0;
|
||||||
|
tunw.size = 0;
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
if (poll(fds, COUNT(fds), -1)==-1 && errno!=EINTR) {
|
if (poll(fds, COUNT(fds), -1)==-1 && errno!=EINTR) {
|
||||||
perror("poll");
|
perror("poll");
|
||||||
@@ -459,8 +587,10 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
if (fds[0].revents & POLLIN) {
|
if (fds[0].revents & POLLIN) {
|
||||||
while (1) {
|
while (1) {
|
||||||
size_t size = buffer_write_size(&tun.recv);
|
if (buffer_write_size(&tun.recv)<sizeof(tunr.buf)+16)
|
||||||
ssize_t r = fd_read(fds[0].fd, tun.recv.write, size);
|
break;
|
||||||
|
|
||||||
|
ssize_t r = fd_read(fds[0].fd, tunr.buf, sizeof(tunr.buf));
|
||||||
|
|
||||||
if (!r)
|
if (!r)
|
||||||
return 2;
|
return 2;
|
||||||
@@ -468,18 +598,18 @@ int main (int argc, char **argv)
|
|||||||
if (r<0)
|
if (r<0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ssize_t ip_size = get_ip_size(tun.recv.write, size);
|
ssize_t ip_size = get_ip_size(tunr.buf, sizeof(tunr.buf));
|
||||||
|
|
||||||
if (ip_size<=0)
|
if (ip_size<=0)
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
if (r<ip_size)
|
if (r<ip_size)
|
||||||
set_ip_size(tun.recv.write, r);
|
set_ip_size(tunr.buf, r);
|
||||||
|
|
||||||
if (r>ip_size)
|
if (r>ip_size)
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
tun.recv.write += r;
|
encrypt_packet(&ctx, tunr.buf, r, &tun.recv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,27 +645,35 @@ int main (int argc, char **argv)
|
|||||||
fds[0].events = POLLIN;
|
fds[0].events = POLLIN;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
size_t size = buffer_read_size(&sock.recv);
|
if (!tunw.size) {
|
||||||
ssize_t ip_size = get_ip_size(sock.recv.read, size);
|
size_t size = buffer_read_size(&sock.recv);
|
||||||
|
ssize_t ip_size = get_ip_size(sock.recv.read, size);
|
||||||
|
|
||||||
if (!ip_size)
|
if (!ip_size)
|
||||||
goto restart;
|
goto restart;
|
||||||
|
|
||||||
if (ip_size<0 || (size_t)ip_size>size)
|
if (ip_size<0 || (size_t)ip_size+16>size)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ssize_t r = fd_write(fds[0].fd, sock.recv.read, ip_size);
|
if (decrypt_packet(&ctx, tunw.buf, ip_size, &sock.recv))
|
||||||
|
goto restart;
|
||||||
|
|
||||||
if (!r)
|
tunw.size = ip_size;
|
||||||
return 2;
|
}
|
||||||
|
if (tunw.size) {
|
||||||
|
ssize_t r = fd_write(fds[0].fd, tunw.buf, tunw.size);
|
||||||
|
|
||||||
if (r==-1)
|
if (!r)
|
||||||
fds[0].events = POLLIN|POLLOUT;
|
return 2;
|
||||||
|
|
||||||
if (r<0)
|
if (r==-1)
|
||||||
break;
|
fds[0].events = POLLIN|POLLOUT;
|
||||||
|
|
||||||
sock.recv.read += r;
|
if (r<0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
tunw.size = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user