libtom / libtomcrypt

LibTomCrypt is a fairly comprehensive, modular and portable cryptographic toolkit that provides developers with a vast array of well known published block ciphers, one-way hash functions, chaining modes, pseudo-random number generators, public key cryptography and a plethora of other routines.

Home Page:https://www.libtom.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ctr_encrypt ctr->pad not aligned

mkj opened this issue · comments

Description

Running under ubsan catches undefined behaviour in ctr_encrypt. The problem is that ctr->pad isn't 16 byte aligned, but we have a cast to a ulong64. I'm not sure how important it is for portability, I guess x64 works fine? Unsure the best way to fix it, other than just disabling LTC_FAST for that section - maybe the compiler will unroll it anyway...

ctr_encrypt.c:63               *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ctr->pad + x));

Steps to Reproduce

make CC=clang CFLAGS="-fsanitize=undefined -fno-sanitize-recover=undefined -DUSE_LTM -DLTM_DESC" EXTRALIBS="-ltommath" LD=clang++ LDFLAGS=-fsanitize=undefined test

./test
...
store_test..........src/modes/ctr/ctr_encrypt.c:57:60: runtime error: load of misaligned address 0x000000eae01c for type 'LTC_FAST_TYPE' (aka 'unsigned long long'), which requires 8 byte alignment
0x000000eae01c: note: pointer points here
  00 00 00 00 9e 26 81 83  ff ee e7 0b 2e 07 2e 5c  68 ee e6 29 00 00 00 00  00 00 00 00 00 00 00 00
              ^ 
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior src/modes/ctr/ctr_encrypt.c:57:60 in 

Version

v1.18.2-595-gcfbd7f8d
Ubuntu 20.04, x64
clang 10.0.0-4ubuntu1

It seems to come from an issue with the symmetric_CTR definition, which defines 5 (32-bit) leading intergers, so the next 16-byte buffers end up aligned on a 32-bit boundary.

A quick & dirty workaround:

--- a/src/headers/tomcrypt_cipher.h
+++ b/src/headers/tomcrypt_cipher.h
@@ -290,6 +290,8 @@ typedef struct {
                        mode,
    /** counter width */
                        ctrlen;
+   /** fix alignment issues with pad & LTC_FAST mode on 64-bit hosts */
+   int                 dummy;
 
    /** The counter */
    unsigned char       ctr[MAXBLOCKSIZE],
@@ -306,7 +308,6 @@ typedef struct {
 typedef struct {
     /** The index of the cipher chosen (must be a 128-bit block cipher) */

but a proper fix would require to force the compiler to align the pad (and maybe other) buffers.

can you please check whether #560 solves this?

Ah, #560 fixes CTR->pad[] but now pt is also unaligned. You're right about "and maybe other buffers".

Failing as below where pt comes from buf+z

// tests/store_test.c:56
  for (z = 0; z < y; z++) {
     /* fill y bytes with random */
     yarrow_read(buf+z,   y, &yarrow_prng);
store_test..........src/modes/ctr/ctr_encrypt.c:56:66: runtime error: load of misaligned address 0x7ffdb93ce3c1 for type 'LTC_FAST_TYPE' (aka 'unsigned long long'), which requires 8 byte alignment
0x7ffdb93ce3c1: note: pointer points here
 00 00 00  13 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 5a cd 1c 49 51 5c ba  a0 bd c2 32 54
              ^ 
    #0 0x503e99 in s_ctr_encrypt /home/matt/src/libtomcrypt/src/modes/ctr/ctr_encrypt.c:56:66
    #1 0x4e6974 in yarrow_read /home/matt/src/libtomcrypt/src/prngs/yarrow.c:231:8
    #2 0x441685 in store_test /home/matt/src/libtomcrypt/tests/store_test.c:56:6
    #3 0x441e1b in main /home/matt/src/libtomcrypt/tests/test.c:408:11