Skip to content

Commit

Permalink
Ensure that AES key is always correctly aligned
Browse files Browse the repository at this point in the history
Aligning a `struct` member via `attribute(align(<n>))` is not guaranteed
to work.
Change the approach to use an opaque buffer and always manually align
the start pointers of the keys.

c.f. DCIT/perl-CryptX#95

Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
  • Loading branch information
sjaeckel committed Oct 4, 2023
1 parent b96e96c commit fcdb5c4
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 5 deletions.
6 changes: 5 additions & 1 deletion src/ciphers/aes/aes.c
Expand Up @@ -96,7 +96,7 @@ static ulong32 setup_mix2(ulong32 temp)
int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
int i;
ulong32 temp, *rk;
ulong32 temp, *rk, *K;
#ifndef ENCRYPT_ONLY
ulong32 *rrk;
#endif
Expand All @@ -112,6 +112,10 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
}

skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;
K = LTC_ALIGN_BUF(skey->rijndael.K, 16);
skey->rijndael.eK = K;
K += 60;
skey->rijndael.dK = K;

/* setup the forward key */
i = 0;
Expand Down
6 changes: 5 additions & 1 deletion src/ciphers/aes/aesni.c
Expand Up @@ -46,7 +46,7 @@ int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_
{
int i;
__m128i temp;
ulong32 *rk;
ulong32 *rk, *K;
ulong32 *rrk;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(skey != NULL);
Expand All @@ -60,6 +60,10 @@ int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_
}

skey->rijndael.Nr = keylen / 4 + 6;
K = LTC_ALIGN_BUF(skey->rijndael.K, 16);
skey->rijndael.eK = K;
K += 60;
skey->rijndael.dK = K;

/* setup the forward key */
i = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/headers/tomcrypt_cfg.h
Expand Up @@ -209,7 +209,7 @@ LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2);
typedef unsigned __int64 ulong64;
typedef __int64 long64;
#else
#define CONST64(n) n ## ULL
#define CONST64(n) n ## uLL
typedef unsigned long long ulong64;
typedef long long long64;
#endif
Expand Down
5 changes: 3 additions & 2 deletions src/headers/tomcrypt_cipher.h
Expand Up @@ -35,9 +35,10 @@ struct saferp_key {

#ifdef LTC_RIJNDAEL
struct rijndael_key {
ulong32 eK[60] LTC_ALIGN(16);
ulong32 dK[60] LTC_ALIGN(16);
ulong32 *eK;
ulong32 *dK;
int Nr;
unsigned char K[(60 + 60 + 4) * sizeof(ulong32)];
};
#endif

Expand Down
15 changes: 15 additions & 0 deletions src/headers/tomcrypt_private.h
Expand Up @@ -9,6 +9,21 @@

#define LTC_PAD_MASK (0xF000U)

#if defined(ENDIAN_64BITWORD)
#define CONSTPTR(n) CONST64(n)
#else
#define CONSTPTR(n) n ## uL
#endif

/* Poor-man's `uintptr_t` since we can't use stdint.h
* c.f. https://github.com/DCIT/perl-CryptX/issues/95#issuecomment-1745280962 */
typedef size_t ltc_uintptr;

/* Aligns a `unsigned char` buffer `buf` to `n` bytes and returns that aligned address.
* Make sure that the buffer that is passed is huge enough.
*/
#define LTC_ALIGN_BUF(buf, n) ((void*)((ltc_uintptr)&(buf)[n - 1] & (~(CONSTPTR(n) - CONSTPTR(1)))))

/* `NULL` as defined by the standard is not guaranteed to be of a pointer
* type. In order to make sure that in vararg API's a pointer type is used,
* define our own version and use that one internally.
Expand Down

0 comments on commit fcdb5c4

Please sign in to comment.