Implement AES using TBoxes

This commit is contained in:
Manuel Thalmann 2023-12-19 04:13:07 +01:00
parent dc87ee563e
commit eada851807

View file

@ -1,5 +1,7 @@
#include <chrono>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdint.h>
#include <stdlib.h>
@ -14,7 +16,7 @@ http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
#define WORD(byte0, byte1, byte2, byte3) ((((((uint16_t)(byte3 << 8) | byte2) << 8) | byte1) << 8) | byte0)
#define WBYTE(value, position) ((value >> (position * 8)) & 0xFF)
#define WBYTE(value, position) (((uint32_t)value >> (position * 8)) & 0xFF)
/* AES Constants */
// AES polynomial
@ -40,6 +42,12 @@ const uint8_t SBOX[256] = {
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
// T-boxes
uint32_t T0[256];
uint32_t T1[256];
uint32_t T2[256];
uint32_t T3[256];
const uint8_t rCon[12] = {
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
};
@ -93,26 +101,6 @@ uint8_t xtime(uint8_t a) {
return ((a << 1) ^ mask) & 0xFF;
}
// not mandatory - mix a single column
uint32_t mixColumn(uint32_t c) {
uint32_t result = c;
uint8_t *source = (uint8_t*)(&c);
uint8_t *target = (uint8_t*)(&result);
uint8_t base = *source ^ *(source + 1) ^ *(source + 2) ^ *(source + 3);
*target ^= base ^ xtime(*source ^ *(source + 1));
*(target + 1) ^= base ^ xtime(*(source + 1) ^ *(source + 2));
*(target + 2) ^= base ^ xtime(*(source + 2) ^ *(source + 3));
*(target + 3) ^= base ^ xtime(*(source + 3) ^ *source);
return result;
}
void mixColumns(t_state s) {
for (uint8_t i = 0; i < 4; i++) {
s[i] = mixColumn(s[i]);
}
}
/*
* Key expansion from 128bits (4*32b)
* to 11 round keys (11*4*32b)
@ -159,21 +147,27 @@ void aes(uint8_t *in, uint8_t *out, uint8_t *skey)
uint32_t expKey[11 * 4];
expandKey(skey, expKey);
addRoundKey(state, expKey, 0);
for (int i = 1; i <= 10; i++) {
subBytes(state);
for (int i = 1; i < 10; i++) {
t_state tmp;
shiftRows(state);
if (i < 10) {
mixColumns(state);
for (int j = 0; j < 4; j++) {
tmp[j] =
T0[WBYTE(state[j], 0)] ^
T1[WBYTE(state[(j + 1) % 4], 1)] ^
T2[WBYTE(state[(j + 2) % 4], 2)] ^
T3[WBYTE(state[(j + 3) % 4], 3)];
}
memcpy(state, tmp, sizeof(t_state));
addRoundKey(state, expKey, 4 * i);
}
subBytes(state);
shiftRows(state);
addRoundKey(state, expKey, 40);
for (int i = 0; i < 16; i++) {
if (i < 4) out[i] = WBYTE(state[0], i % 4);
else if (i < 8) out[i] = WBYTE(state[1], i % 4);
@ -198,6 +192,16 @@ int main(int argc, char* argv[])
cycles = std::atoi(argv[1]);
}
for (int i = 0; i <= 0xFF; i++) {
uint8_t a1 = SBOX[i];
uint8_t a2 = xtime(a1);
uint8_t a3 = a2 ^ a1;
T0[i] = WORD(a2, a1, a1, a3);
T1[i] = WORD(a3, a2, a1, a1);
T2[i] = WORD(a1, a3, a2, a1);
T3[i] = WORD(a1, a1, a3, a2);
}
const auto start{std::chrono::steady_clock::now()};
{
for (int i = 0; i < cycles; i++) {