From ce1b13c5ea3ea0c7ba8b8250b2d91942ca0db065 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 16 Sep 2012 05:28:45 +0200 Subject: Make implementations used for AES128-CTR and GHASH configurable. --- src/config.c | 29 ++++++++++++ src/config.l | 2 + src/config.y | 11 +++++ src/fastd.h | 3 ++ src/linux_alg.c | 137 ++++++++++++++++++++++++++++++++------------------------ src/types.h | 4 ++ 6 files changed, 128 insertions(+), 58 deletions(-) (limited to 'src') 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 #include #include +#include #include #include @@ -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 TOK_ADDR %token 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; -- cgit v1.2.3