summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-09-16 05:28:45 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-09-16 05:30:24 +0200
commitce1b13c5ea3ea0c7ba8b8250b2d91942ca0db065 (patch)
tree5259c1e3d3a51bb92ba64eab04a22ed66c84c497
parent7305c533516df296124d6b2415482d2febb7328a (diff)
downloadfastd-ce1b13c5ea3ea0c7ba8b8250b2d91942ca0db065.tar
fastd-ce1b13c5ea3ea0c7ba8b8250b2d91942ca0db065.zip
Make implementations used for AES128-CTR and GHASH configurable.
-rw-r--r--src/config.c29
-rw-r--r--src/config.l2
-rw-r--r--src/config.y11
-rw-r--r--src/fastd.h3
-rw-r--r--src/linux_alg.c137
-rw-r--r--src/types.h4
6 files changed, 128 insertions, 58 deletions
diff --git a/src/config.c b/src/config.c
index 8b19fd4..168a640 100644
--- a/src/config.c
+++ b/src/config.c
@@ -37,6 +37,7 @@
#include <dirent.h>
#include <libgen.h>
#include <stdarg.h>
+#include <strings.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -85,6 +86,8 @@ static void default_config(fastd_config *conf) {
conf->secret = NULL;
conf->key_valid = 3600; /* 60 minutes */
conf->key_refresh = 3300; /* 55 minutes */
+ conf->alg_impl_aes128ctr = ALG_IMPL_DEFAULT;
+ conf->alg_impl_ghash = ALG_IMPL_DEFAULT;
conf->peer_dirs = NULL;
conf->peers = NULL;
@@ -174,6 +177,32 @@ bool fastd_config_method(fastd_context *ctx, fastd_config *conf, const char *nam
exit_bug(ctx, "MAX_METHODS too low");
}
+bool fastd_config_algorithm(fastd_context *ctx, fastd_config *conf, const char *alg, const char *impl) {
+ if (!strcasecmp(alg, "aes128-ctr") || !strcasecmp(alg, "aes128") || !strcasecmp(alg, "aes-ctr") || !strcasecmp(alg, "aes")) {
+ if (!strcasecmp(impl, "default"))
+ conf->alg_impl_aes128ctr = ALG_IMPL_DEFAULT;
+ else if (!strcasecmp(impl, "algif"))
+ conf->alg_impl_aes128ctr = ALG_IMPL_ALGIF;
+ else
+ return false;
+
+ return true;
+ }
+ else if (!strcasecmp(alg, "ghash")) {
+ if (!strcasecmp(impl, "default"))
+ conf->alg_impl_ghash = ALG_IMPL_DEFAULT;
+ else if (!strcasecmp(impl, "algif"))
+ conf->alg_impl_ghash = ALG_IMPL_ALGIF;
+ else
+ return false;
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
bool fastd_config_add_log_file(fastd_context *ctx, fastd_config *conf, const char *name, int level) {
char *name2 = strdup(name);
char *name3 = strdup(name);
diff --git a/src/config.l b/src/config.l
index 5596484..b640426 100644
--- a/src/config.l
+++ b/src/config.l
@@ -97,6 +97,8 @@ yes { TOKEN(TOK_YES); }
no { TOKEN(TOK_NO); }
port { TOKEN(TOK_PORT); }
float { TOKEN(TOK_FLOAT); }
+algorithm { TOKEN(TOK_ALGORITHM); }
+use { TOKEN(TOK_USE); }
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} {
UPDATE_LOCATION;
diff --git a/src/config.y b/src/config.y
index 07774d1..8fea5a3 100644
--- a/src/config.y
+++ b/src/config.y
@@ -95,6 +95,8 @@
%token TOK_NO
%token TOK_PORT
%token TOK_FLOAT
+%token TOK_ALGORITHM
+%token TOK_USE
%token <addr> TOK_ADDR
%token <addr6> TOK_ADDR6
@@ -136,6 +138,7 @@ statement: TOK_LOG log ';'
| TOK_MODE mode ';'
| TOK_PROTOCOL protocol ';'
| TOK_METHOD method ';'
+ | TOK_ALGORITHM algorithm ';'
| TOK_SECRET secret ';'
| TOK_ON TOK_UP on_up ';'
| TOK_ON TOK_DOWN on_down ';'
@@ -226,6 +229,14 @@ method: TOK_STRING {
}
;
+algorithm: TOK_STRING TOK_USE TOK_STRING {
+ if (!fastd_config_algorithm(ctx, conf, $1->str, $3->str)) {
+ fastd_config_error(&@$, ctx, conf, filename, depth, "invalid algorithm/implementation");
+ YYERROR;
+ }
+ }
+ ;
+
secret: TOK_STRING { free(conf->secret); conf->secret = strdup($1->str); }
;
diff --git a/src/fastd.h b/src/fastd.h
index 023576b..7c3fe19 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -163,6 +163,8 @@ struct _fastd_config {
char *secret;
unsigned key_valid;
unsigned key_refresh;
+ fastd_alg_impl alg_impl_aes128ctr;
+ fastd_alg_impl alg_impl_ghash;
fastd_string_stack *peer_dirs;
fastd_peer_config *peers;
@@ -247,6 +249,7 @@ bool fastd_read_config(fastd_context *ctx, fastd_config *conf, const char *filen
bool fastd_config_protocol(fastd_context *ctx, fastd_config *conf, const char *name);
bool fastd_config_method(fastd_context *ctx, fastd_config *conf, const char *name);
+bool fastd_config_algorithm(fastd_context *ctx, fastd_config *conf, const char *alg, const char *impl);
bool fastd_config_add_log_file(fastd_context *ctx, fastd_config *conf, const char *name, int level);
void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *const argv[]);
void fastd_reconfigure(fastd_context *ctx, fastd_config *conf);
diff --git a/src/linux_alg.c b/src/linux_alg.c
index 9591ce8..ab08cab 100644
--- a/src/linux_alg.c
+++ b/src/linux_alg.c
@@ -36,83 +36,68 @@
#endif
-void fastd_linux_alg_init(fastd_context *ctx) {
- ctx->algfd_ghash = socket(AF_ALG, SOCK_SEQPACKET, 0);
- if (ctx->algfd_ghash < 0)
- goto ghash_done;
+static int init_aesctr(fastd_context *ctx) {
+ int fd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ if (fd < 0)
+ goto error;
struct sockaddr_alg sa = {};
sa.salg_family = AF_ALG;
- strcpy((char*)sa.salg_type, "hash");
- strcpy((char*)sa.salg_name, "ghash");
- if (bind(ctx->algfd_ghash, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
- close(ctx->algfd_ghash);
- ctx->algfd_ghash = -1;
- }
-
- ghash_done:
- if (ctx->algfd_ghash < 0)
- pr_info(ctx, "no kernel support for GHASH was found, falling back to userspace implementation");
-
- ctx->algfd_aesctr = socket(AF_ALG, SOCK_SEQPACKET, 0);
- if (ctx->algfd_aesctr < 0)
- goto aesctr_done;
-
strcpy((char*)sa.salg_type, "skcipher");
strcpy((char*)sa.salg_name, "ctr(aes)");
- if (bind(ctx->algfd_aesctr, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
- close(ctx->algfd_aesctr);
- ctx->algfd_aesctr = -1;
- }
+ if (bind(fd, (struct sockaddr*)&sa, sizeof(sa)) < 0)
+ goto error;
- aesctr_done:
- if (ctx->algfd_aesctr < 0)
- pr_info(ctx, "no kernel support for AES-CTR was found, falling back to userspace implementation");
-}
+ return fd;
-void fastd_linux_alg_close(fastd_context *ctx) {
- if (ctx->algfd_ghash >= 0)
- close(ctx->algfd_ghash);
+ error:
+ if (fd >= 0)
+ close(fd);
- if (ctx->algfd_aesctr >= 0)
- close(ctx->algfd_aesctr);
+ pr_info(ctx, "no kernel support for AES-CTR was found, falling back to userspace implementation");
+ return -1;
}
+static int init_ghash(fastd_context *ctx) {
+ int fd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ if (fd < 0)
+ goto error;
-int fastd_linux_alg_ghash_init(fastd_context *ctx, uint8_t key[16]) {
- if (ctx->algfd_ghash < 0)
- return -1;
-
- if (setsockopt(ctx->algfd_ghash, SOL_ALG, ALG_SET_KEY, key, 16) < 0) {
- pr_error_errno(ctx, "fastd_linux_alg_ghash_init: setsockopt");
- return -1;
- }
+ struct sockaddr_alg sa = {};
+ sa.salg_family = AF_ALG;
+ strcpy((char*)sa.salg_type, "hash");
+ strcpy((char*)sa.salg_name, "ghash");
+ if (bind(fd, (struct sockaddr*)&sa, sizeof(sa)) < 0)
+ goto error;
- int ret = accept(ctx->algfd_ghash, NULL, NULL);
+ return fd;
- if (ret < 0) {
- pr_error_errno(ctx, "fastd_linux_alg_ghash_init: accept");
- return -1;
- }
+ error:
+ if (fd >= 0)
+ close(fd);
- return ret;
+ pr_info(ctx, "no kernel support for GHASH was found, falling back to userspace implementation");
+ return -1;
}
-bool fastd_linux_alg_ghash(fastd_context *ctx, int fd, uint8_t out[16], const void *data, size_t len) {
- if (!len)
- return false;
+void fastd_linux_alg_init(fastd_context *ctx) {
+ if (ctx->conf->alg_impl_aes128ctr == ALG_IMPL_ALGIF)
+ ctx->algfd_aesctr = init_aesctr(ctx);
+ else
+ ctx->algfd_aesctr = -1;
- if (write(fd, data, len) < 0) {
- pr_error_errno(ctx, "fastd_linux_alg_ghash: write");
- return false;
- }
+ if (ctx->conf->alg_impl_ghash == ALG_IMPL_ALGIF)
+ ctx->algfd_ghash = init_ghash(ctx);
+ else
+ ctx->algfd_ghash = -1;
+}
- if (read(fd, out, 16) < 16) {
- pr_error_errno(ctx, "fastd_linux_alg_ghash: read");
- return false;
- }
+void fastd_linux_alg_close(fastd_context *ctx) {
+ if (ctx->algfd_ghash >= 0)
+ close(ctx->algfd_ghash);
- return true;
+ if (ctx->algfd_aesctr >= 0)
+ close(ctx->algfd_aesctr);
}
int fastd_linux_alg_aesctr_init(fastd_context *ctx, uint8_t *key, size_t keylen) {
@@ -173,3 +158,39 @@ bool fastd_linux_alg_aesctr(fastd_context *ctx, int fd, void *out, const void *i
return true;
}
+
+int fastd_linux_alg_ghash_init(fastd_context *ctx, uint8_t key[16]) {
+ if (ctx->algfd_ghash < 0)
+ return -1;
+
+ if (setsockopt(ctx->algfd_ghash, SOL_ALG, ALG_SET_KEY, key, 16) < 0) {
+ pr_error_errno(ctx, "fastd_linux_alg_ghash_init: setsockopt");
+ return -1;
+ }
+
+ int ret = accept(ctx->algfd_ghash, NULL, NULL);
+
+ if (ret < 0) {
+ pr_error_errno(ctx, "fastd_linux_alg_ghash_init: accept");
+ return -1;
+ }
+
+ return ret;
+}
+
+bool fastd_linux_alg_ghash(fastd_context *ctx, int fd, uint8_t out[16], const void *data, size_t len) {
+ if (!len)
+ return false;
+
+ if (write(fd, data, len) < 0) {
+ pr_error_errno(ctx, "fastd_linux_alg_ghash: write");
+ return false;
+ }
+
+ if (read(fd, out, 16) < 16) {
+ pr_error_errno(ctx, "fastd_linux_alg_ghash: read");
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/types.h b/src/types.h
index c213118..c27a99c 100644
--- a/src/types.h
+++ b/src/types.h
@@ -38,6 +38,10 @@ typedef enum _fastd_mode {
MODE_TUN,
} fastd_mode;
+typedef enum _fastd_alg_impl {
+ ALG_IMPL_DEFAULT,
+ ALG_IMPL_ALGIF,
+} fastd_alg_impl;
typedef struct _fastd_buffer fastd_buffer;