From 8b68505248a54477f7cb81b30e33520d9c5d1083 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Mon, 28 Oct 2013 02:52:39 +0100 Subject: Make sure that ek and dk are aligned at 16 byte boundaries ek and dk are used as operands in instructions that require 16 byte alignment. Thanks to Greg Price for finding this issue. Signed-off-by: Sebastian Ramacher --- configure.ac | 1 + setup.py | 4 ++++ src/AESNI.c | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index b62db5e..5f22d00 100644 --- a/configure.ac +++ b/configure.ac @@ -103,5 +103,6 @@ AC_TYPE_UINT8_T # Checks for library functions. AC_FUNC_MALLOC AC_CHECK_FUNCS([memmove memset]) +AC_CHECK_FUNCS([posix_memalign aligned_alloc _aligned_malloc]) AC_OUTPUT diff --git a/setup.py b/setup.py index 998122e..5269e9d 100644 --- a/setup.py +++ b/setup.py @@ -166,6 +166,10 @@ class PCTBuildExt (build_ext): if not ac.get("HAVE_WMMINTRIN_H"): # AES-NI instrincs not available self.__remove_extensions(["Crypto.Cipher._AESNI"]) + elif not (ac.get("HAVE_POSIX_MEMALIGN") or ac.get("HAVE_ALIGNED_ALLOC") + or ac.get("HAVE__ALIGNED_MALLOC")): + # no function to allocate aligned memory is available + self.__remove_extensions(["Crypto.Cipher._AESNI"]) elif ac.get("HAVE_MAES"): # -maes has to be passed to the compiler to use the AES-NI instrincs self.__add_extension_compile_option(["Crypto.Cipher._AESNI"], diff --git a/src/AESNI.c b/src/AESNI.c index 81c6e9c..bd03cc8 100644 --- a/src/AESNI.c +++ b/src/AESNI.c @@ -22,8 +22,12 @@ * =================================================================== */ -#include "Python.h" +#include "pycrypto_common.h" #include +#include +#if defined(HAVE__ALIGNED_MALLOC) +#include +#endif #define MODULE_NAME _AESNI #define BLOCK_SIZE 16 @@ -36,9 +40,9 @@ typedef unsigned char u8; typedef struct { - __m128i ek[MAXNR + 1]; - __m128i dk[MAXNR + 1]; - int rounds; + __m128i* ek; + __m128i* dk; + int rounds; } block_state; /* Helper functions to expand keys */ @@ -161,6 +165,36 @@ static void block_init(block_state* self, unsigned char* key, int keylen) "AES key must be either 16, 24, or 32 bytes long"); return; } + + /* ensure that self->ek and self->dk are aligned to 16 byte boundaries */ + void* tek = NULL; + void* tdk = NULL; +#if defined(HAVE_POSIX_MEMALIGN) + /* posix_memalign is defined by POSIX */ + posix_memalign(&tek, 16, (nr + 1) * sizeof(__m128i)); + posix_memalign(&tdk, 16, (nr + 1) * sizeof(__m128i)); +#elif defined(HAVE_ALIGNED_ALLOC) + /* aligned_alloc is defined by C11 */ + tek = aligned_alloc(16, (nr + 1) * sizeof(__m128i)); + tdk = aligned_alloc(16, (nr + 1) * sizeof(__m128i)); +#elif defined(HAVE__ALIGNED_MALLOC) + /* _aligned_malloc is available on Windows */ + tek = _aligned_malloc(16, (nr + 1) * sizeof(__m128i)); + tdk = _aligned_malloc(16, (nr + 1) * sizeof(__m128i)); +#else +#error "No function to allocate aligned memory is available." +#endif + if (!tek || !tdk) { + free(tek); + free(tdk); + PyErr_SetString(PyExc_MemoryError, + "failed to allocate memory for keys"); + return; + } + + self->ek = tek; + self->dk = tdk; + self->rounds = nr; aes_key_setup_enc(self->ek, key, keylen); aes_key_setup_dec(self->dk, self->ek, nr); @@ -168,6 +202,12 @@ static void block_init(block_state* self, unsigned char* key, int keylen) static void block_finalize(block_state* self) { + /* overwrite contents of ek and dk */ + memset(self->ek, 0, (self->rounds + 1) * sizeof(__m128i)); + memset(self->dk, 0, (self->rounds + 1) * sizeof(__m128i)); + + free(self->ek); + free(self->dk); } static void block_encrypt(block_state* self, const u8* in, u8* out) -- cgit v1.2.1