From 4b2a15fef3e9f0ca3809a54ae2a18109dae4ae01 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Mon, 28 Oct 2013 02:36:19 +0100 Subject: Be more consistent with spaces and tabs Signed-off-by: Sebastian Ramacher --- src/AESNI.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/AESNI.c b/src/AESNI.c index 750f719..5b388ef 100644 --- a/src/AESNI.c +++ b/src/AESNI.c @@ -29,9 +29,9 @@ #define BLOCK_SIZE 16 #define KEY_SIZE 0 -#define MAXKC (256/32) -#define MAXKB (256/8) -#define MAXNR 14 +#define MAXKC (256/32) +#define MAXKB (256/8) +#define MAXNR 14 typedef unsigned char u8; @@ -151,18 +151,18 @@ static void aes_key_setup_dec(__m128i dk[], const __m128i ek[], int rounds) static void block_init(block_state* self, unsigned char* key, int keylen) { - int nr = 0; - switch (keylen) { - case 16: nr = 10; break; - case 24: nr = 12; break; - case 32: nr = 14; break; + int nr = 0; + switch (keylen) { + case 16: nr = 10; break; + case 24: nr = 12; break; + case 32: nr = 14; break; default: PyErr_SetString(PyExc_ValueError, "AES key must be either 16, 24, or 32 bytes long"); - return; - } - self->rounds = nr; - aes_key_setup_enc(self->ek, key, keylen); + return; + } + self->rounds = nr; + aes_key_setup_enc(self->ek, key, keylen); aes_key_setup_dec(self->dk, self->ek, nr); } @@ -196,7 +196,7 @@ static void block_encrypt(block_state* self, const u8* in, u8* out) static void block_decrypt(block_state* self, const u8* in, u8* out) { - __m128i m = _mm_loadu_si128((const __m128i*) in); + __m128i m = _mm_loadu_si128((const __m128i*) in); /* first 9 rounds */ m = _mm_xor_si128(m, self->dk[0]); m = _mm_aesdec_si128(m, self->dk[1]); -- cgit v1.2.1 From 8cde8b9893819e9586bde2ce9be84f24689ff0d9 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Mon, 28 Oct 2013 02:47:48 +0100 Subject: Add block_finalize to clean up block_state from ALGdealloc This is the counterpart to block_init which is called from ALGnew. Signed-off-by: Sebastian Ramacher --- src/AES.c | 4 ++++ src/AESNI.c | 4 ++++ src/ARC2.c | 4 ++++ src/Blowfish.c | 4 ++++ src/CAST.c | 5 +++++ src/DES.c | 4 ++++ src/block_template.c | 1 + 7 files changed, 26 insertions(+) diff --git a/src/AES.c b/src/AES.c index 5da189f..1e705da 100644 --- a/src/AES.c +++ b/src/AES.c @@ -1446,6 +1446,10 @@ static void block_init(block_state *state, unsigned char *key, rijndaelKeySetupDec(state->dk, key, keylen*8); } +static void block_finalize(block_state* self) +{ +} + static void block_encrypt(block_state *self, u8 *in, u8 *out) { rijndaelEncrypt(self->ek, self->rounds, in, out); diff --git a/src/AESNI.c b/src/AESNI.c index 5b388ef..81c6e9c 100644 --- a/src/AESNI.c +++ b/src/AESNI.c @@ -166,6 +166,10 @@ static void block_init(block_state* self, unsigned char* key, int keylen) aes_key_setup_dec(self->dk, self->ek, nr); } +static void block_finalize(block_state* self) +{ +} + static void block_encrypt(block_state* self, const u8* in, u8* out) { __m128i m = _mm_loadu_si128((const __m128i*) in); diff --git a/src/ARC2.c b/src/ARC2.c index 255e77e..71858f6 100644 --- a/src/ARC2.c +++ b/src/ARC2.c @@ -216,5 +216,9 @@ block_init(block_state *self, U8 *key, int keylength) } while (i--); } +static void +block_finalize(block_state* self) +{ +} #include "block_template.c" diff --git a/src/Blowfish.c b/src/Blowfish.c index 96f8628..f1ab55a 100644 --- a/src/Blowfish.c +++ b/src/Blowfish.c @@ -231,6 +231,10 @@ static void Blowfish_init(Blowfish_state *self, const unsigned char *key, int ke #define block_encrypt Blowfish_encrypt #define block_decrypt Blowfish_decrypt +static void block_finalize(block_state *self) +{ +} + #include "block_template.c" /* vim:set ts=4 sw=4 sts=4 expandtab: */ diff --git a/src/CAST.c b/src/CAST.c index ca5d0f0..d7b00f3 100644 --- a/src/CAST.c +++ b/src/CAST.c @@ -434,6 +434,11 @@ block_init(block_state *self, unsigned char *key, int keylength) castschedulekeys(self, key, keylength); } +static void +block_finalize(block_state* self) +{ +} + static void block_encrypt(block_state *self, unsigned char *in, unsigned char *out) diff --git a/src/DES.c b/src/DES.c index 9cbda53..5187870 100644 --- a/src/DES.c +++ b/src/DES.c @@ -76,6 +76,10 @@ static void block_init(block_state *self, unsigned char *key, int keylen) } } +static void block_finalize(block_state *self) +{ +} + static void block_encrypt(block_state *self, unsigned char *in, unsigned char *out) { int rc; diff --git a/src/block_template.c b/src/block_template.c index f940e0e..eec03d3 100644 --- a/src/block_template.c +++ b/src/block_template.c @@ -84,6 +84,7 @@ static void ALGdealloc(PyObject *ptr) { ALGobject *self = (ALGobject *)ptr; + block_finalize(&self->st); /* Overwrite the contents of the object */ Py_XDECREF(self->counter); -- cgit v1.2.1 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 From 7d16bb41592155949a711815da2a39202052b423 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Mon, 28 Oct 2013 21:44:35 +0100 Subject: Add a wrapper for posix_memalign and friends This also fixes the order of arguments passed to _aligned_malloc. Signed-off-by: Sebastian Ramacher --- src/AESNI.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/AESNI.c b/src/AESNI.c index bd03cc8..6c27225 100644 --- a/src/AESNI.c +++ b/src/AESNI.c @@ -45,6 +45,26 @@ typedef struct { int rounds; } block_state; +/* Wrapper function for malloc with memory alignment */ + +static void* memalign_wrapper(size_t alignment, size_t size) +{ +#if defined(HAVE_POSIX_MEMALIGN) + /* posix_memalign is defined by POSIX */ + void* tmp = NULL; + posix_memalign(&tmp, alignment, size); + return tmp; +#elif defined(HAVE_ALIGNED_ALLOC) + /* aligned_alloc is defined by C11 */ + return aligned_alloc(alignment, size); +#elif defined(HAVE__ALIGNED_MALLOC) + /* _aligned_malloc is available on Windows */ + return _aligned_malloc(size, alignment); +#else +#error "No function to allocate aligned memory is available." +#endif +} + /* Helper functions to expand keys */ static __m128i aes128_keyexpand(__m128i key, __m128i keygened, int shuf) @@ -167,23 +187,8 @@ static void block_init(block_state* self, unsigned char* key, int keylen) } /* 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 + void* tek = memalign_wrapper(16, (nr + 1) * sizeof(__m128i)); + void* tdk = memalign_wrapper(16, (nr + 1) * sizeof(__m128i)); if (!tek || !tdk) { free(tek); free(tdk); -- cgit v1.2.1 From 694f536eb05c5dea85ad0488fedef122bb124237 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Sat, 22 Feb 2014 17:07:50 +0100 Subject: Add wrapper for free For _aligned_malloc calling free is illegal. We need to use_aligned_free instead. Signed-off-by: Sebastian Ramacher --- src/AESNI.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/AESNI.c b/src/AESNI.c index 6c27225..16119e0 100644 --- a/src/AESNI.c +++ b/src/AESNI.c @@ -45,7 +45,7 @@ typedef struct { int rounds; } block_state; -/* Wrapper function for malloc with memory alignment */ +/* Wrapper function for malloc and free with memory alignment */ static void* memalign_wrapper(size_t alignment, size_t size) { @@ -61,7 +61,20 @@ static void* memalign_wrapper(size_t alignment, size_t size) /* _aligned_malloc is available on Windows */ return _aligned_malloc(size, alignment); #else -#error "No function to allocate aligned memory is available." +#error "No function to allocate/free aligned memory is available." +#endif +} + +static void free_wrapper(void* ptr) +{ +#if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_ALIGNED_ALLOC) + /* free is fine for aligned_alloc and posix_memalign */ + free(ptr); +#elif defined(HAVE__ALIGNED_MALLOC) + /* _aligned_malloc requires _aligned_free */ + _aligned_free(ptr); +#else +#error "No function to allocate/free aligned memory is available." #endif } @@ -190,8 +203,8 @@ static void block_init(block_state* self, unsigned char* key, int keylen) void* tek = memalign_wrapper(16, (nr + 1) * sizeof(__m128i)); void* tdk = memalign_wrapper(16, (nr + 1) * sizeof(__m128i)); if (!tek || !tdk) { - free(tek); - free(tdk); + free_wrapper(tek); + free_wrapper(tdk); PyErr_SetString(PyExc_MemoryError, "failed to allocate memory for keys"); return; @@ -211,8 +224,8 @@ static void block_finalize(block_state* self) memset(self->ek, 0, (self->rounds + 1) * sizeof(__m128i)); memset(self->dk, 0, (self->rounds + 1) * sizeof(__m128i)); - free(self->ek); - free(self->dk); + free_wrapper(self->ek); + free_wrapper(self->dk); } static void block_encrypt(block_state* self, const u8* in, u8* out) -- cgit v1.2.1 From 85c2ac670937bbe5c369e6f205213453515e37c1 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Sat, 22 Feb 2014 17:08:13 +0100 Subject: Check return value of posix_memalign Signed-off-by: Sebastian Ramacher --- src/AESNI.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AESNI.c b/src/AESNI.c index 16119e0..b2daa81 100644 --- a/src/AESNI.c +++ b/src/AESNI.c @@ -52,7 +52,9 @@ static void* memalign_wrapper(size_t alignment, size_t size) #if defined(HAVE_POSIX_MEMALIGN) /* posix_memalign is defined by POSIX */ void* tmp = NULL; - posix_memalign(&tmp, alignment, size); + int result = posix_memalign(&tmp, alignment, size); + if (result != 0) + return NULL; return tmp; #elif defined(HAVE_ALIGNED_ALLOC) /* aligned_alloc is defined by C11 */ -- cgit v1.2.1 From 6a3bd8bef9522f0df7cb259cccc0fdec917e2da8 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Sat, 22 Feb 2014 17:08:47 +0100 Subject: Prefer C11's aligned_alloc if it is available Signed-off-by: Sebastian Ramacher --- src/AESNI.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AESNI.c b/src/AESNI.c index b2daa81..cbd1448 100644 --- a/src/AESNI.c +++ b/src/AESNI.c @@ -49,16 +49,16 @@ typedef struct { static void* memalign_wrapper(size_t alignment, size_t size) { -#if defined(HAVE_POSIX_MEMALIGN) +#if defined(HAVE_ALIGNED_ALLOC) + /* aligned_alloc is defined by C11 */ + return aligned_alloc(alignment, size); +#elif defined(HAVE_POSIX_MEMALIGN) /* posix_memalign is defined by POSIX */ void* tmp = NULL; int result = posix_memalign(&tmp, alignment, size); if (result != 0) return NULL; return tmp; -#elif defined(HAVE_ALIGNED_ALLOC) - /* aligned_alloc is defined by C11 */ - return aligned_alloc(alignment, size); #elif defined(HAVE__ALIGNED_MALLOC) /* _aligned_malloc is available on Windows */ return _aligned_malloc(size, alignment); -- cgit v1.2.1