summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2013-11-28 04:31:25 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2013-11-28 04:31:25 +0100
commitac55a91fe94b78bde373169264e6b7a180c39f04 (patch)
tree33f9a38de1e7056d02ca61c82a41e604dabdf232
parentca49096f5d02e351b928b2fd584bd7ca0d5fcf1f (diff)
downloadfastd-ac55a91fe94b78bde373169264e6b7a180c39f04.tar
fastd-ac55a91fe94b78bde373169264e6b7a180c39f04.zip
Add a pclmulqdq ghash implementation
-rw-r--r--CMakeLists.txt1
-rw-r--r--cmake/arch.cmake17
-rw-r--r--cmake/fastd_module.cmake8
-rw-r--r--src/crypto/mac/CMakeLists.txt4
-rw-r--r--src/crypto/mac/ghash/CMakeLists.txt1
-rw-r--r--src/crypto/mac/ghash/pclmulqdq/CMakeLists.txt7
-rw-r--r--src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.c61
-rw-r--r--src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.h45
-rw-r--r--src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq_impl.c106
9 files changed, 250 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2420488..4e06cff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,6 +4,7 @@ project(FASTD C)
set(CMAKE_MODULE_PATH ${FASTD_SOURCE_DIR}/cmake)
set(FASTD_VERSION "v10+")
+include(arch)
include(config)
include(deps)
include(checks)
diff --git a/cmake/arch.cmake b/cmake/arch.cmake
new file mode 100644
index 0000000..fe488c2
--- /dev/null
+++ b/cmake/arch.cmake
@@ -0,0 +1,17 @@
+include(CheckCSourceCompiles)
+
+check_c_source_compiles("
+#ifndef __i386__
+#error not x86
+#endif
+
+int main() {return 0;}
+" ARCH_X86)
+
+check_c_source_compiles("
+#ifndef __x86_64__
+#error not x86_64
+#endif
+
+int main() {return 0;}
+" ARCH_X86_64)
diff --git a/cmake/fastd_module.cmake b/cmake/fastd_module.cmake
index 26285ae..093e28b 100644
--- a/cmake/fastd_module.cmake
+++ b/cmake/fastd_module.cmake
@@ -49,3 +49,11 @@ function(fastd_module_require type name)
endforeach(req)
endif(WITH_${TYPE}_${NAME})
endfunction(fastd_module_require)
+
+function(fastd_module_compile_flags type name source)
+ _fastd_module_handle_name()
+
+ if(WITH_${TYPE}_${NAME})
+ set_property(SOURCE ${source} APPEND PROPERTY COMPILE_FLAGS ${ARGN})
+ endif(WITH_${TYPE}_${NAME})
+endfunction(fastd_module_compile_flags)
diff --git a/src/crypto/mac/CMakeLists.txt b/src/crypto/mac/CMakeLists.txt
index 22bc95e..355416f 100644
--- a/src/crypto/mac/CMakeLists.txt
+++ b/src/crypto/mac/CMakeLists.txt
@@ -34,6 +34,10 @@ macro(fastd_mac_impl_require mac name)
fastd_module_require(mac "${mac} ${name}" ${ARGN})
endmacro(fastd_mac_impl_require)
+macro(fastd_mac_impl_compile_flags mac name source)
+ fastd_module_compile_flags(mac "${mac} ${name}" ${source} ${ARGN})
+endmacro(fastd_mac_impl_compile_flags)
+
add_subdirectory(ghash)
diff --git a/src/crypto/mac/ghash/CMakeLists.txt b/src/crypto/mac/ghash/CMakeLists.txt
index 1fd04a4..d5ce150 100644
--- a/src/crypto/mac/ghash/CMakeLists.txt
+++ b/src/crypto/mac/ghash/CMakeLists.txt
@@ -1,2 +1,3 @@
fastd_mac(ghash ghash.c)
+add_subdirectory(pclmulqdq)
add_subdirectory(builtin)
diff --git a/src/crypto/mac/ghash/pclmulqdq/CMakeLists.txt b/src/crypto/mac/ghash/pclmulqdq/CMakeLists.txt
new file mode 100644
index 0000000..a11ad02
--- /dev/null
+++ b/src/crypto/mac/ghash/pclmulqdq/CMakeLists.txt
@@ -0,0 +1,7 @@
+if(ARCH_X86 OR ARCH_X86_64)
+ fastd_mac_impl(ghash pclmulqdq
+ ghash_pclmulqdq.c
+ ghash_pclmulqdq_impl.c
+ )
+ fastd_mac_impl_compile_flags(ghash pclmulqdq ghash_pclmulqdq_impl.c "-mssse3 -mpclmul")
+endif(ARCH_X86 OR ARCH_X86_64)
diff --git a/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.c b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.c
new file mode 100644
index 0000000..11073a5
--- /dev/null
+++ b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.c
@@ -0,0 +1,61 @@
+/*
+ Copyright (c) 2012-2013, Matthias Schiffer <mschiffer@universe-factory.net>
+ 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 "ghash_pclmulqdq.h"
+#include "../../../../cpuid.h"
+
+
+static bool ghash_available(void) {
+ static const uint64_t REQ = CPUID_FXSR|CPUID_SSSE3|CPUID_PCLMULQDQ;
+
+ return ((fastd_cpuid()&REQ) == REQ);
+}
+
+static fastd_mac_context_t* ghash_initialize(fastd_context_t *ctx UNUSED) {
+ return NULL;
+}
+
+static void ghash_free_state(fastd_context_t *ctx UNUSED, fastd_mac_state_t *state) {
+ if (state) {
+ secure_memzero(state, sizeof(*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_pclmulqdq = {
+ .available = ghash_available,
+
+ .initialize = ghash_initialize,
+ .init_state = fastd_ghash_pclmulqdq_init_state,
+
+ .hash = fastd_ghash_pclmulqdq_hash,
+
+ .free_state = ghash_free_state,
+ .free = ghash_free,
+};
diff --git a/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.h b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.h
new file mode 100644
index 0000000..f2bc916
--- /dev/null
+++ b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.h
@@ -0,0 +1,45 @@
+/*
+ Copyright (c) 2012-2013, Matthias Schiffer <mschiffer@universe-factory.net>
+ 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 "../../../../crypto.h"
+
+
+typedef union _v2di {
+ uint64_t v __attribute__((vector_size(16)));
+ char v16 __attribute__((vector_size(16)));
+ long long int vll __attribute__((vector_size(16)));
+ uint64_t e[2];
+ fastd_block128_t block;
+} v2di;
+
+
+struct fastd_mac_state {
+ v2di H;
+};
+
+
+fastd_mac_state_t* fastd_ghash_pclmulqdq_init_state(fastd_context_t *ctx, const fastd_mac_context_t *mctx, const uint8_t *key);
+bool fastd_ghash_pclmulqdq_hash(fastd_context_t *ctx, const fastd_mac_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t n_blocks);
diff --git a/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq_impl.c b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq_impl.c
new file mode 100644
index 0000000..e797d3c
--- /dev/null
+++ b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq_impl.c
@@ -0,0 +1,106 @@
+/*
+ Copyright (c) 2012-2013, Matthias Schiffer <mschiffer@universe-factory.net>
+ 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 "ghash_pclmulqdq.h"
+
+
+static inline v2di shl(v2di v, int a) {
+ v2di tmph, tmpl;
+ tmph.v = v.v << ((v2di){{a, a}}).v;
+ tmpl.v = v.v >> ((v2di){{64-a, 64-a}}).v;
+
+ return (v2di){{tmph.e[0], tmph.e[1]|tmpl.e[0]}};
+}
+
+static inline v2di shr(v2di v, int a) {
+ v2di tmph, tmpl;
+ tmph.v = v.v >> ((v2di){{a, a}}).v;
+ tmpl.v = v.v << ((v2di){{64-a, 64-a}}).v;
+
+ return (v2di){{tmph.e[0]|tmpl.e[1], tmph.e[1]}};
+}
+
+static inline v2di byteswap(v2di v) {
+ const v2di shuffle = { .v16 = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}};
+ v.v16 = __builtin_ia32_pshufb128(v.v16, shuffle.v16);
+ return v;
+}
+
+fastd_mac_state_t* fastd_ghash_pclmulqdq_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));
+
+ memcpy(&state->H, key, sizeof(v2di));
+ state->H = byteswap(state->H);
+
+ return state;
+}
+
+static inline v2di gmul(v2di v, v2di h) {
+ /* multiply */
+ v2di tmp00, tmp10, tmp01, tmp11;
+ tmp00.vll = __builtin_ia32_pclmulqdq128(v.vll, h.vll, 0x00);
+ tmp01.vll = __builtin_ia32_pclmulqdq128(v.vll, h.vll, 0x01);
+ tmp10.vll = __builtin_ia32_pclmulqdq128(v.vll, h.vll, 0x10);
+ tmp11.vll = __builtin_ia32_pclmulqdq128(v.vll, h.vll, 0x11);
+
+ v2di pl = {{tmp11.e[0] ^ tmp01.e[1] ^ tmp10.e[1], tmp11.e[1]}};
+ v2di ph = {{tmp00.e[0], tmp00.e[1] ^ tmp01.e[0] ^ tmp10.e[0]}};
+
+ pl = shl(pl, 1);
+ pl.e[0] |= ph.e[1] >> 63;
+
+ ph = shl(ph, 1);
+
+ /* reduce */
+ uint64_t b = ph.e[0] << 62;
+ uint64_t c = ph.e[0] << 57;
+
+ v2di d = {{ph.e[0], ph.e[1] ^ b ^ c}};
+
+ v2di e = shr(d, 1);
+ v2di f = shr(d, 2);
+ v2di g = shr(d, 7);
+
+ pl.v ^= d.v ^ e.v ^ f.v ^ g.v;
+
+ return pl;
+}
+
+
+bool fastd_ghash_pclmulqdq_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) {
+ const v2di *inv = (const v2di*)in;
+ v2di v = {{0, 0}};
+
+ size_t i;
+ for (i = 0; i < n_blocks; i++) {
+ v.v ^= byteswap(inv[i]).v;
+ v = gmul(v, state->H);
+ }
+
+ *out = byteswap(v).block;
+
+ return true;
+}