Using fork of mbed-tls AES implementation I've looked at a bit: https://github.com/newaetech/chipwhisperer/blob/develop/hardware/victims/firmware/crypto/mbedtls/library/aes.c
Important chunks:
One round of AES works like this with T-Tables:
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
{ \
X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y3 >> 24 ) & 0xFF ]; \
\
X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y0 >> 24 ) & 0xFF ]; \
\
X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y1 >> 24 ) & 0xFF ]; \
\
X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y2 >> 24 ) & 0xFF ]; \
}
When it goes to encrypt something, it runs this before calling the FROUND() function above:
NB: Watch carefully Xn vs Yn - I've changed X to Y below to match the above function, in MBED-TLS AES it swaps the two around, the code works fine but it's confusing as X0 in the encryption function becomes Y0 in the macro above for example
GET_UINT32_LE( Y0, input, 0 ); Y0 ^= *RK++;
GET_UINT32_LE( Y1, input, 4 ); Y1 ^= *RK++;
GET_UINT32_LE( Y2, input, 8 ); Y2 ^= *RK++;
GET_UINT32_LE( Y3, input, 12 ); Y3 ^= *RK++;
If you run through a single round for example, we can make the previous FROUND function reference
a new INPUT[N]
variable, which is the input ^ RK
from above, but referencing byte N
. This makes it easier to see
the byte collisions than before (I think anyway):
X0 = *RK++ ^ FT0[ ( INPUT[0] ) ] ^ \
FT1[ ( INPUT[5] ) ] ^ \
FT2[ ( INPUT[10]) ] ^ \
FT3[ ( INPUT[15]) ]; \
\
X1 = *RK++ ^ FT0[ ( INPUT[4] ) ] ^ \
FT1[ ( INPUT[9] ) ] ^ \
FT2[ ( INPUT[14]) ] ^ \
FT3[ ( INPUT[3] ) ]; \
\
X2 = *RK++ ^ FT0[ ( INPUT[8] ) ] ^ \
FT1[ ( INPUT[13]) ] ^ \
FT2[ ( INPUT[2] ) ] ^ \
FT3[ ( INPUT[7] ) ]; \
\
X3 = *RK++ ^ FT0[ ( INPUT[12]) ] ^ \
FT1[ ( INPUT[1] ) ] ^ \
FT2[ ( INPUT[6] ) ] ^ \
FT3[ ( INPUT[11]) ]; \
This has the expected collisions on the FT
tables (FT = Forward T-Table).
If we write out the order of access to elements, we see the following:
X0: 0 5 10 15
X1: 4 9 14 3
X2: 8 13 2 7
X3: 12 1 6 11
There also appears to be collisions from 5-->12, 10-->1, 15-->6 (wrapping around).
The next call to AES_FROUND is for 2nd round effectively, so seems unlikely it's providing additional leakage?