From 4496be6e29732189769b78f63e491dacb23c961b Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 2 Nov 2013 16:01:16 +0100 Subject: Convert ghash to the new crypto algorithm scheme --- CMakeLists.txt | 19 +--- src/CMakeLists.txt | 1 - src/config.c | 27 +---- src/config.y | 9 -- src/crypto.c | 147 --------------------------- src/crypto.h | 56 ---------- src/crypto/CMakeLists.txt | 7 +- src/crypto/mac/CMakeLists.txt | 34 +++++++ src/crypto/mac/ghash/CMakeLists.txt | 18 ++++ src/crypto/mac/ghash/builtin/CMakeLists.txt | 6 ++ src/crypto/mac/ghash/builtin/ghash_builtin.c | 140 +++++++++++++++++++++++++ src/crypto/mac/macs.c.in | 117 +++++++++++++++++++++ src/fastd.c | 14 +-- src/fastd.h | 46 ++++++--- src/methods/generic_gcm/generic_gcm.c | 20 ++-- src/types.h | 11 +- 16 files changed, 378 insertions(+), 294 deletions(-) delete mode 100644 src/crypto.c delete mode 100644 src/crypto.h create mode 100644 src/crypto/mac/CMakeLists.txt create mode 100644 src/crypto/mac/ghash/CMakeLists.txt create mode 100644 src/crypto/mac/ghash/builtin/CMakeLists.txt create mode 100644 src/crypto/mac/ghash/builtin/ghash_builtin.c create mode 100644 src/crypto/mac/macs.c.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 12daafa..70a17c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,8 @@ set(WITH_CMDLINE_COMMANDS TRUE CACHE BOOL "Include support for setting handler s set(WITH_CIPHER_AES128_CTR TRUE CACHE BOOL "Include the AES128-CTR cipher algorithm") set(WITH_CIPHER_AES128_CTR_NACL TRUE CACHE BOOL "Include the AES128-CTR implementation from the NaCl library") -set(WITH_CRYPTO_GHASH_BUILTIN TRUE CACHE BOOL "Include the built-in GHASH implementation") +set(WITH_MAC_GHASH TRUE CACHE BOOL "Include the GHASH MAC algorithm") +set(WITH_MAC_GHASH_BUILTIN TRUE CACHE BOOL "Include the built-in GHASH implementation") set(WITH_METHOD_XSALSA20_POLY1305 TRUE CACHE BOOL "Include xsalsa20-poly1305 method") set(WITH_METHOD_GENERIC_GCM TRUE CACHE BOOL "Include generic gcm method") @@ -44,25 +45,9 @@ set(USE_LIBSODIUM FALSE CACHE BOOL "Use libsodium instead of NaCl") set(MAX_CONFIG_DEPTH 10 CACHE STRING "Maximum config include depth") -if(WITH_CRYPTO_GHASH_BUILTIN) - set(WITH_CRYPTO_GHASH TRUE) -endif(WITH_CRYPTO_GHASH_BUILTIN) - - # Ensure the value is numeric math(EXPR MAX_CONFIG_DEPTH_NUM ${MAX_CONFIG_DEPTH}) -set(USE_CRYPTO_GHASH FALSE) - -if(WITH_METHOD_AES128_GCM) - set(USE_CRYPTO_GHASH TRUE) -endif(WITH_METHOD_AES128_GCM) - - -if(USE_CRYPTO_GHASH AND NOT WITH_CRYPTO_GHASH) - MESSAGE(FATAL_ERROR "No GHASH implementation was selected, but a selected method needs it.") -endif(USE_CRYPTO_GHASH AND NOT WITH_CRYPTO_GHASH) - find_package(BISON 2.5 REQUIRED) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 68b077e..ebc6c37 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,7 +16,6 @@ add_executable(fastd fastd.c capabilities.c config.c - crypto.c handshake.c hkdf_sha256.c lex.c diff --git a/src/config.c b/src/config.c index 8cf0dcb..f9d2ae1 100644 --- a/src/config.c +++ b/src/config.c @@ -43,10 +43,6 @@ extern const fastd_protocol_t fastd_protocol_ec25519_fhmqvc; -#ifdef USE_CRYPTO_GHASH -extern const fastd_crypto_ghash_t fastd_crypto_ghash_builtin; -#endif - static void default_config(fastd_config_t *conf) { memset(conf, 0, sizeof(fastd_config_t)); @@ -74,15 +70,12 @@ static void default_config(fastd_config_t *conf) { conf->key_refresh = 3300; /* 55 minutes */ conf->key_refresh_splay = 300; /* 5 minutes */ -#ifdef USE_CRYPTO_GHASH - conf->crypto_ghash = &fastd_crypto_ghash_builtin; -#endif - conf->peer_group = calloc(1, sizeof(fastd_peer_group_config_t)); conf->peer_group->name = strdup("default"); conf->peer_group->max_connections = -1; conf->ciphers = fastd_cipher_config_alloc(); + conf->macs = fastd_mac_config_alloc(); } bool fastd_config_protocol(fastd_context_t *ctx UNUSED, fastd_config_t *conf, const char *name) { @@ -112,23 +105,6 @@ bool fastd_config_method(fastd_context_t *ctx, fastd_config_t *conf, const char return true; } -bool fastd_config_crypto(fastd_context_t *ctx UNUSED, fastd_config_t *conf UNUSED, const char *alg UNUSED, const char *impl UNUSED) { -#ifdef USE_CRYPTO_GHASH - if (!strcasecmp(alg, "ghash")) { - if (!strcasecmp(impl, "default")) - conf->crypto_ghash = &fastd_crypto_ghash_builtin; - else if (!strcasecmp(impl, "builtin")) - conf->crypto_ghash = &fastd_crypto_ghash_builtin; - else - return false; - - return true; - } - else -#endif - return false; -} - bool fastd_config_bind_address(fastd_context_t *ctx UNUSED, fastd_config_t *conf, const fastd_peer_address_t *address, const char *bindtodev, bool default_v4, bool default_v6) { #ifndef USE_BINDTODEVICE if (bindtodev) @@ -671,6 +647,7 @@ void fastd_config_release(fastd_context_t *ctx, fastd_config_t *conf) { fastd_string_stack_free(conf->methods); + fastd_mac_config_free(conf->macs); fastd_cipher_config_free(conf->ciphers); free(conf->user); diff --git a/src/config.y b/src/config.y index ffc719d..ca2d8de 100644 --- a/src/config.y +++ b/src/config.y @@ -177,7 +177,6 @@ statement: peer_group_statement | TOK_MODE mode ';' | TOK_PROTOCOL protocol ';' | TOK_METHOD method ';' - | TOK_CRYPTO crypto ';' | TOK_SECRET secret ';' | TOK_ON TOK_PRE_UP on_pre_up ';' | TOK_ON TOK_UP on_up ';' @@ -357,14 +356,6 @@ method: TOK_STRING { } ; -crypto: TOK_STRING TOK_USE TOK_STRING { - if (!fastd_config_crypto(ctx, conf, $1->str, $3->str)) { - fastd_config_error(&@$, ctx, conf, filename, depth, "invalid crypto algorithm/implementation"); - YYERROR; - } - } - ; - secret: TOK_STRING { free(conf->secret); conf->secret = strdup($1->str); } ; diff --git a/src/crypto.c b/src/crypto.c deleted file mode 100644 index 1583349..0000000 --- a/src/crypto.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - Copyright (c) 2012-2013, Matthias Schiffer - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "fastd.h" -#include "crypto.h" - - -#ifdef USE_CRYPTO_GHASH -#ifdef WITH_CRYPTO_GHASH_BUILTIN - -struct fastd_crypto_ghash_state { - fastd_block128_t H[32][16]; -}; - - -static const fastd_block128_t r = { .b = {0xe1} }; - - -static inline uint8_t shr(fastd_block128_t *out, const fastd_block128_t *in, int n) { - size_t i; - uint8_t c = 0; - - for (i = 0; i < sizeof(fastd_block128_t); i++) { - uint8_t c2 = in->b[i] << (8-n); - out->b[i] = (in->b[i] >> n) | c; - c = c2; - } - - return (c >> (8-n)); -} - -static inline void mulH_a(fastd_block128_t *x, const fastd_crypto_ghash_state_t *cstate) { - fastd_block128_t out = {}; - - int i; - for (i = 0; i < 16; i++) { - xor_a(&out, &cstate->H[2*i][x->b[i]>>4]); - xor_a(&out, &cstate->H[2*i+1][x->b[i]&0xf]); - } - - *x = out; -} - - -static fastd_crypto_ghash_context_t* ghash_init(fastd_context_t *ctx UNUSED) { - return (fastd_crypto_ghash_context_t*)1; -} - -static fastd_crypto_ghash_state_t* ghash_set_h(fastd_context_t *ctx UNUSED, const fastd_crypto_ghash_context_t *cctx UNUSED, const fastd_block128_t *h) { - fastd_crypto_ghash_state_t *cstate = malloc(sizeof(fastd_crypto_ghash_state_t)); - - fastd_block128_t Hbase[4]; - fastd_block128_t Rbase[4]; - - Hbase[0] = *h; - Rbase[0] = r; - - int i; - for (i = 1; i < 4; i++) { - uint8_t carry = shr(&Hbase[i], &Hbase[i-1], 1); - if (carry) - xor_a(&Hbase[i], &r); - - shr(&Rbase[i], &Rbase[i-1], 1); - } - - fastd_block128_t R[16]; - memset(cstate->H, 0, sizeof(cstate->H)); - memset(R, 0, sizeof(R)); - - for (i = 0; i < 16; i++) { - int j; - for (j = 0; j < 4; j++) { - if (i & (8 >> j)) { - xor_a(&cstate->H[0][i], &Hbase[j]); - xor_a(&R[i], &Rbase[j]); - } - } - } - - for (i = 1; i < 32; i++) { - int j; - - for (j = 0; j < 16; j++) { - uint8_t carry = shr(&cstate->H[i][j], &cstate->H[i-1][j], 4); - xor_a(&cstate->H[i][j], &R[carry]); - } - } - - return cstate; -} - -static bool ghash_hash(fastd_context_t *ctx UNUSED, const fastd_crypto_ghash_state_t *cstate, fastd_block128_t *out, const fastd_block128_t *in, size_t n_blocks) { - memset(out, 0, sizeof(fastd_block128_t)); - - size_t i; - for (i = 0; i < n_blocks; i++) { - xor_a(out, &in[i]); - mulH_a(out, cstate); - } - - return true; -} - -static void ghash_free_state(fastd_context_t *ctx UNUSED, fastd_crypto_ghash_state_t *cstate) { - free(cstate); -} - -static void ghash_free(fastd_context_t *ctx UNUSED, fastd_crypto_ghash_context_t *cctx UNUSED) { -} - -const fastd_crypto_ghash_t fastd_crypto_ghash_builtin = { - .name = "builtin", - - .init = ghash_init, - .set_h = ghash_set_h, - .hash = ghash_hash, - - .free_state = ghash_free_state, - .free = ghash_free, -}; - -#endif -#endif diff --git a/src/crypto.h b/src/crypto.h deleted file mode 100644 index b954651..0000000 --- a/src/crypto.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (c) 2012-2013, Matthias Schiffer - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef _FASTD_CRYPTO_H_ -#define _FASTD_CRYPTO_H_ - -#include "types.h" - - -#ifdef USE_CRYPTO_GHASH -struct fastd_crypto_ghash { - const char *name; - - fastd_crypto_ghash_context_t* (*init)(fastd_context_t *ctx); - fastd_crypto_ghash_state_t* (*set_h)(fastd_context_t *ctx, const fastd_crypto_ghash_context_t *cctx, const fastd_block128_t *h); - bool (*hash)(fastd_context_t *ctx, const fastd_crypto_ghash_state_t *cstate, fastd_block128_t *out, const fastd_block128_t *in, size_t n_blocks); - - void (*free_state)(fastd_context_t *ctx, fastd_crypto_ghash_state_t *cstate); - void (*free)(fastd_context_t *ctx, fastd_crypto_ghash_context_t *cctx); -}; -#endif - - -static inline void xor(fastd_block128_t *x, const fastd_block128_t *a, const fastd_block128_t *b) { - x->qw[0] = a->qw[0] ^ b->qw[0]; - x->qw[1] = a->qw[1] ^ b->qw[1]; -} - -static inline void xor_a(fastd_block128_t *x, const fastd_block128_t *a) { - xor(x, x, a); -} - -#endif /* _FASTD_CRYPTO_H_ */ diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index 1c78e03..94ff3b4 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -1,3 +1,8 @@ add_subdirectory(cipher) +add_subdirectory(mac) -set(CRYPTO_SOURCES "${CIPHER_SOURCES}" PARENT_SCOPE) +set(CRYPTO_SOURCES "") +list(APPEND CRYPTO_SOURCES ${CIPHER_SOURCES}) +list(APPEND CRYPTO_SOURCES ${MAC_SOURCES}) + +set(CRYPTO_SOURCES "${CRYPTO_SOURCES}" PARENT_SCOPE) diff --git a/src/crypto/mac/CMakeLists.txt b/src/crypto/mac/CMakeLists.txt new file mode 100644 index 0000000..7f8664c --- /dev/null +++ b/src/crypto/mac/CMakeLists.txt @@ -0,0 +1,34 @@ +set(MACS "") + +if(WITH_MAC_GHASH) + list(APPEND MACS ghash) +endif(WITH_MAC_GHASH) + +set(MAC_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/macs.c") + +set(MAC_DEFINITIONS "") +set(MAC_IMPLS "") +set(MAC_LIST "") + +foreach(mac ${MACS}) + add_subdirectory(${mac}) + + list(APPEND MAC_SOURCES ${IMPL_SOURCES}) + + set(MAC_LIST "${MAC_LIST}\n{\"${MAC_NAME}\", mac_${mac}_impls},") + set(MAC_IMPLS "${MAC_IMPLS}\nstatic const fastd_mac_t *const mac_${mac}_impls[] = {") + + foreach(impl ${IMPLS}) + set(MAC_DEFINITIONS "${MAC_DEFINITIONS}\nextern const fastd_mac_t fastd_mac_${mac}_${impl};") + set(MAC_IMPLS "${MAC_IMPLS}&fastd_mac_${mac}_${impl}, ") + endforeach(impl) + + set(MAC_IMPLS "${MAC_IMPLS}NULL};") + +endforeach(mac) + + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macs.c.in ${CMAKE_CURRENT_BINARY_DIR}/macs.c) + + +set(MAC_SOURCES "${MAC_SOURCES}" PARENT_SCOPE) diff --git a/src/crypto/mac/ghash/CMakeLists.txt b/src/crypto/mac/ghash/CMakeLists.txt new file mode 100644 index 0000000..7d697e8 --- /dev/null +++ b/src/crypto/mac/ghash/CMakeLists.txt @@ -0,0 +1,18 @@ +set(IMPLS "") + +if(WITH_MAC_GHASH_BUILTIN) + list(APPEND IMPLS builtin) +endif(WITH_MAC_GHASH_BUILTIN) + +set(IMPL_SOURCES "") + +foreach(impl ${IMPLS}) + add_subdirectory(${impl}) + + list(APPEND IMPL_SOURCES $) +endforeach(impl) + + +set(MAC_NAME "ghash" PARENT_SCOPE) +set(IMPLS "${IMPLS}" PARENT_SCOPE) +set(IMPL_SOURCES "${IMPL_SOURCES}" PARENT_SCOPE) diff --git a/src/crypto/mac/ghash/builtin/CMakeLists.txt b/src/crypto/mac/ghash/builtin/CMakeLists.txt new file mode 100644 index 0000000..7951d58 --- /dev/null +++ b/src/crypto/mac/ghash/builtin/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories(${FASTD_SOURCE_DIR}/src ${FASTD_BINARY_DIR}) + +add_library(mac_ghash_builtin OBJECT + ghash_builtin.c +) +set_property(TARGET mac_ghash_builtin PROPERTY COMPILE_FLAGS "${FASTD_CFLAGS}") diff --git a/src/crypto/mac/ghash/builtin/ghash_builtin.c b/src/crypto/mac/ghash/builtin/ghash_builtin.c new file mode 100644 index 0000000..2eb7fed --- /dev/null +++ b/src/crypto/mac/ghash/builtin/ghash_builtin.c @@ -0,0 +1,140 @@ +/* + Copyright (c) 2012-2013, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "../../../../fastd.h" + + +struct fastd_mac_state { + fastd_block128_t H[32][16]; +}; + + +static const fastd_block128_t r = { .b = {0xe1} }; + + +static inline uint8_t shr(fastd_block128_t *out, const fastd_block128_t *in, int n) { + size_t i; + uint8_t c = 0; + + for (i = 0; i < sizeof(fastd_block128_t); i++) { + uint8_t c2 = in->b[i] << (8-n); + out->b[i] = (in->b[i] >> n) | c; + c = c2; + } + + return (c >> (8-n)); +} + +static inline void mulH_a(fastd_block128_t *x, const fastd_mac_state_t *cstate) { + fastd_block128_t out = {}; + + int i; + for (i = 0; i < 16; i++) { + xor_a(&out, &cstate->H[2*i][x->b[i]>>4]); + xor_a(&out, &cstate->H[2*i+1][x->b[i]&0xf]); + } + + *x = out; +} + + +static fastd_mac_context_t* ghash_initialize(fastd_context_t *ctx UNUSED) { + return NULL; +} + +static fastd_mac_state_t* ghash_init_state(fastd_context_t *ctx UNUSED, const fastd_mac_context_t *mctx UNUSED, const uint8_t *key) { + fastd_mac_state_t *state = malloc(sizeof(fastd_mac_state_t)); + + fastd_block128_t Hbase[4]; + fastd_block128_t Rbase[4]; + + memcpy(&Hbase[0], key, sizeof(fastd_block128_t)); + Rbase[0] = r; + + int i; + for (i = 1; i < 4; i++) { + uint8_t carry = shr(&Hbase[i], &Hbase[i-1], 1); + if (carry) + xor_a(&Hbase[i], &r); + + shr(&Rbase[i], &Rbase[i-1], 1); + } + + fastd_block128_t R[16]; + memset(state->H, 0, sizeof(state->H)); + memset(R, 0, sizeof(R)); + + for (i = 0; i < 16; i++) { + int j; + for (j = 0; j < 4; j++) { + if (i & (8 >> j)) { + xor_a(&state->H[0][i], &Hbase[j]); + xor_a(&R[i], &Rbase[j]); + } + } + } + + for (i = 1; i < 32; i++) { + int j; + + for (j = 0; j < 16; j++) { + uint8_t carry = shr(&state->H[i][j], &state->H[i-1][j], 4); + xor_a(&state->H[i][j], &R[carry]); + } + } + + return state; +} + +static bool ghash_hash(fastd_context_t *ctx UNUSED, const fastd_mac_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t n_blocks) { + memset(out, 0, sizeof(fastd_block128_t)); + + size_t i; + for (i = 0; i < n_blocks; i++) { + xor_a(out, &in[i]); + mulH_a(out, state); + } + + return true; +} + +static void ghash_free_state(fastd_context_t *ctx UNUSED, fastd_mac_state_t *state) { + free(state); +} + +static void ghash_free(fastd_context_t *ctx UNUSED, fastd_mac_context_t *mctx UNUSED) { +} + +const fastd_mac_t fastd_mac_ghash_builtin = { + .name = "builtin", + + .initialize = ghash_initialize, + .init_state = ghash_init_state, + .hash = ghash_hash, + + .free_state = ghash_free_state, + .free = ghash_free, +}; diff --git a/src/crypto/mac/macs.c.in b/src/crypto/mac/macs.c.in new file mode 100644 index 0000000..e591935 --- /dev/null +++ b/src/crypto/mac/macs.c.in @@ -0,0 +1,117 @@ +/* + Copyright (c) 2012-2013, Matthias Schiffer + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + + +@MAC_DEFINITIONS@ + +typedef struct mac_impl_list { + const char *name; + const fastd_mac_t *const *impls; +} mac_impl_list_t; + +@MAC_IMPLS@ + +static const mac_impl_list_t macs[] = { @MAC_LIST@ +}; + + +const fastd_mac_t** fastd_mac_config_alloc(void) { + const fastd_mac_t **mac_conf = calloc(array_size(macs), sizeof(const fastd_mac_t*)); + + size_t i; + for (i = 0; i < array_size(macs); i++) + mac_conf[i] = macs[i].impls[0]; + + return mac_conf; +} + +void fastd_mac_config_free(const fastd_mac_t **mac_conf) { + free(mac_conf); +} + +bool fastd_mac_config(const fastd_mac_t **mac_conf, const char *name, const char *impl) { + size_t i; + for (i = 0; i < array_size(macs); i++) { + if (!strcmp(macs[i].name, name)) { + size_t j; + for (j = 0; macs[i].impls[j]; j++) { + if (!strcmp(macs[i].impls[j]->name, impl)) { + mac_conf[i] = macs[i].impls[j]; + return true; + } + } + + return false; + } + } + + return false; +} + +void fastd_mac_init(fastd_context_t *ctx) { + ctx->mac_contexts = calloc(array_size(macs), sizeof(fastd_mac_context_t*)); + + size_t i; + for (i = 0; i < array_size(macs); i++) { + if (ctx->conf->macs[i]) + ctx->mac_contexts[i] = ctx->conf->macs[i]->initialize(ctx); + } +} + +void fastd_mac_free(fastd_context_t *ctx) { + size_t i; + for (i = 0; i < array_size(macs); i++) + ctx->conf->macs[i]->free(ctx, ctx->mac_contexts[i]); + + free(ctx->mac_contexts); +} + +bool fastd_mac_available(const char *name) { + size_t i; + for (i = 0; i < array_size(macs); i++) { + if (!strcmp(macs[i].name, name)) { + return true; + } + } + + return false; +} + +const fastd_mac_t* fastd_mac_get_by_name(fastd_context_t *ctx, const char *name, fastd_mac_context_t **cctx) { + size_t i; + for (i = 0; i < array_size(macs); i++) { + if (!strcmp(macs[i].name, name)) { + if (cctx) + *cctx = ctx->mac_contexts[i]; + + return ctx->conf->macs[i]; + } + } + + return NULL; +} diff --git a/src/fastd.c b/src/fastd.c index 534a30e..175dc00 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -25,7 +25,6 @@ #include "fastd.h" -#include "crypto.h" #include "handshake.h" #include "peer.h" #include @@ -147,20 +146,11 @@ static void close_log(fastd_context_t *ctx) { static void crypto_init(fastd_context_t *ctx) { fastd_cipher_init(ctx); - -#ifdef USE_CRYPTO_GHASH - ctx->crypto_ghash = ctx->conf->crypto_ghash->init(ctx); - if (!ctx->crypto_ghash) - exit_error(ctx, "Unable to initialize GHASH implementation"); -#endif + fastd_mac_init(ctx); } static void crypto_free(fastd_context_t *ctx UNUSED) { -#ifdef USE_CRYPTO_GHASH - ctx->conf->crypto_ghash->free(ctx, ctx->crypto_ghash); - ctx->crypto_ghash = NULL; -#endif - + fastd_mac_free(ctx); fastd_cipher_free(ctx); } diff --git a/src/fastd.h b/src/fastd.h index 6f0bd19..573da1b 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -105,12 +105,23 @@ struct fastd_cipher { fastd_cipher_context_t* (*initialize)(fastd_context_t *ctx); fastd_cipher_state_t* (*init_state)(fastd_context_t *ctx, const fastd_cipher_context_t *cctx, const uint8_t *key); - bool (*crypt)(fastd_context_t *ctx, const fastd_cipher_state_t *cstate, fastd_block128_t *out, const fastd_block128_t *in, size_t len, const fastd_block128_t *iv); + bool (*crypt)(fastd_context_t *ctx, const fastd_cipher_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t len, const fastd_block128_t *iv); - void (*free_state)(fastd_context_t *ctx, fastd_cipher_state_t *cstate); + void (*free_state)(fastd_context_t *ctx, fastd_cipher_state_t *state); void (*free)(fastd_context_t *ctx, fastd_cipher_context_t *cctx); }; +struct fastd_mac { + const char *name; + + fastd_mac_context_t* (*initialize)(fastd_context_t *ctx); + fastd_mac_state_t* (*init_state)(fastd_context_t *ctx, const fastd_mac_context_t *mctx, const uint8_t *key); + bool (*hash)(fastd_context_t *ctx, const fastd_mac_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t n_blocks); + + void (*free_state)(fastd_context_t *ctx, fastd_mac_state_t *state); + void (*free)(fastd_context_t *ctx, fastd_mac_context_t *mctx); +}; + union fastd_peer_address { struct sockaddr sa; struct sockaddr_in in; @@ -237,10 +248,7 @@ struct fastd_config { unsigned key_refresh_splay; const fastd_cipher_t **ciphers; - -#ifdef USE_CRYPTO_GHASH - const fastd_crypto_ghash_t *crypto_ghash; -#endif + const fastd_mac_t **macs; fastd_peer_group_config_t *peer_group; fastd_peer_config_t *peers; @@ -316,10 +324,7 @@ struct fastd_context { fastd_stats_t tx_error; fastd_cipher_context_t **cipher_contexts; - -#ifdef USE_CRYPTO_GHASH - fastd_crypto_ghash_context_t *crypto_ghash; -#endif + fastd_mac_context_t **mac_contexts; size_t eth_addr_size; size_t n_eth_addr; @@ -359,7 +364,6 @@ void fastd_logf(const fastd_context_t *ctx, fastd_loglevel_t level, const char * void fastd_add_peer_dir(fastd_context_t *ctx, fastd_config_t *conf, const char *dir); bool fastd_read_config(fastd_context_t *ctx, fastd_config_t *conf, const char *filename, bool peer_config, int depth); -bool fastd_cipher_available(const char *name); const fastd_method_t* fastd_method_get_by_name(const char *name); const fastd_cipher_t** fastd_cipher_config_alloc(void); @@ -368,11 +372,20 @@ bool fastd_cipher_config(const fastd_cipher_t **cipher_conf, const char *name, c void fastd_cipher_init(fastd_context_t *ctx); void fastd_cipher_free(fastd_context_t *ctx); +bool fastd_cipher_available(const char *name); const fastd_cipher_t* fastd_cipher_get_by_name(fastd_context_t *ctx, const char *name, fastd_cipher_context_t **cctx); +const fastd_mac_t** fastd_mac_config_alloc(void); +void fastd_mac_config_free(const fastd_mac_t **mac_conf); +bool fastd_mac_config(const fastd_mac_t **mac_conf, const char *name, const char *impl); + +void fastd_mac_init(fastd_context_t *ctx); +void fastd_mac_free(fastd_context_t *ctx); +bool fastd_mac_available(const char *name); +const fastd_mac_t* fastd_mac_get_by_name(fastd_context_t *ctx, const char *name, fastd_mac_context_t **cctx); + bool fastd_config_protocol(fastd_context_t *ctx, fastd_config_t *conf, const char *name); bool fastd_config_method(fastd_context_t *ctx, fastd_config_t *conf, const char *name); -bool fastd_config_crypto(fastd_context_t *ctx, fastd_config_t *conf, const char *alg, const char *impl); bool fastd_config_add_log_file(fastd_context_t *ctx, fastd_config_t *conf, const char *name, fastd_loglevel_t level); bool fastd_config_bind_address(fastd_context_t *ctx, fastd_config_t *conf, const fastd_peer_address_t *address, const char *bindtodev, bool default_v4, bool default_v6); void fastd_config_peer_group_push(fastd_context_t *ctx, fastd_config_t *conf, const char *name); @@ -546,4 +559,13 @@ static inline void secure_memzero(void *s, size_t n) { asm volatile("" : : "m"(s)); } +static inline void xor(fastd_block128_t *x, const fastd_block128_t *a, const fastd_block128_t *b) { + x->qw[0] = a->qw[0] ^ b->qw[0]; + x->qw[1] = a->qw[1] ^ b->qw[1]; +} + +static inline void xor_a(fastd_block128_t *x, const fastd_block128_t *a) { + xor(x, x, a); +} + #endif /* _FASTD_FASTD_H_ */ diff --git a/src/methods/generic_gcm/generic_gcm.c b/src/methods/generic_gcm/generic_gcm.c index 479ea83..ba8729a 100644 --- a/src/methods/generic_gcm/generic_gcm.c +++ b/src/methods/generic_gcm/generic_gcm.c @@ -25,7 +25,6 @@ #include "../../fastd.h" -#include "../../crypto.h" #include "../common.h" @@ -36,11 +35,16 @@ struct fastd_method_session_state { fastd_cipher_context_t *cipher_ctx; fastd_cipher_state_t *cipher_state; - fastd_crypto_ghash_state_t *cstate_ghash; + const fastd_mac_t *ghash; + fastd_mac_context_t *ghash_ctx; + fastd_mac_state_t *ghash_state; }; static bool cipher_get(fastd_context_t *ctx, const char *name, const fastd_cipher_t **cipher, fastd_cipher_context_t **cctx) { + if (!fastd_mac_available("ghash")) + return false; + size_t len = strlen(name); if (len < 4) @@ -108,7 +112,11 @@ static fastd_method_session_state_t* method_session_init(fastd_context_t *ctx, c session->cipher->crypt(ctx, session->cipher_state, &H, &zeroblock, sizeof(fastd_block128_t), &zeroblock); - session->cstate_ghash = ctx->conf->crypto_ghash->set_h(ctx, ctx->crypto_ghash, &H); + session->ghash = fastd_mac_get_by_name(ctx, "ghash", &session->ghash_ctx); + if (!session->ghash) + exit_bug(ctx, "generic-gcm: can't instanciate ghash mac"); + + session->ghash_state = session->ghash->init_state(ctx, session->ghash_ctx, H.b); return session; } @@ -139,7 +147,7 @@ static void method_session_superseded(fastd_context_t *ctx, fastd_method_session static void method_session_free(fastd_context_t *ctx, fastd_method_session_state_t *session) { if (session) { session->cipher->free_state(ctx, session->cipher_state); - ctx->conf->crypto_ghash->free_state(ctx, session->cstate_ghash); + session->ghash->free_state(ctx, session->ghash_state); secure_memzero(session, sizeof(fastd_method_session_state_t)); free(session); @@ -184,7 +192,7 @@ static bool method_encrypt(fastd_context_t *ctx, fastd_peer_t *peer UNUSED, fast put_size(&outblocks[n_blocks], in.len-sizeof(fastd_block128_t)); - ok = ctx->conf->crypto_ghash->hash(ctx, session->cstate_ghash, &sig, outblocks+1, n_blocks); + ok = session->ghash->hash(ctx, session->ghash_state, &sig, outblocks+1, n_blocks); } if (!ok) { @@ -240,7 +248,7 @@ static bool method_decrypt(fastd_context_t *ctx, fastd_peer_t *peer, fastd_metho put_size(&inblocks[n_blocks], in.len-sizeof(fastd_block128_t)); - ok = ctx->conf->crypto_ghash->hash(ctx, session->cstate_ghash, &sig, inblocks+1, n_blocks); + ok = session->ghash->hash(ctx, session->ghash_state, &sig, inblocks+1, n_blocks); } if (!ok || memcmp(&sig, &outblocks[0], sizeof(fastd_block128_t)) != 0) { diff --git a/src/types.h b/src/types.h index 894b2af..352bf7c 100644 --- a/src/types.h +++ b/src/types.h @@ -115,6 +115,7 @@ typedef struct fastd_context fastd_context_t; typedef struct fastd_protocol fastd_protocol_t; typedef struct fastd_method fastd_method_t; typedef struct fastd_cipher fastd_cipher_t; +typedef struct fastd_mac fastd_mac_t; typedef struct fastd_handshake fastd_handshake_t; @@ -123,10 +124,6 @@ typedef struct fastd_string_stack fastd_string_stack_t; typedef struct fastd_resolve_return fastd_resolve_return_t; -#ifdef USE_CRYPTO_GHASH -typedef struct fastd_crypto_ghash fastd_crypto_ghash_t; -#endif - typedef union fastd_block128 { uint8_t b[16]; @@ -145,9 +142,7 @@ typedef struct fastd_method_session_state fastd_method_session_state_t; typedef struct fastd_cipher_context fastd_cipher_context_t; typedef struct fastd_cipher_state fastd_cipher_state_t; -#ifdef USE_CRYPTO_GHASH -typedef struct fastd_crypto_ghash_context fastd_crypto_ghash_context_t; -typedef struct fastd_crypto_ghash_state fastd_crypto_ghash_state_t; -#endif +typedef struct fastd_mac_context fastd_mac_context_t; +typedef struct fastd_mac_state fastd_mac_state_t; #endif /* _FASTD_TYPES_H_ */ -- cgit v1.2.3