#include "rivide/crypto/aes.h"
#include "rivide/rivide_config.h"
#include "rivide/utils/mem.h"
static const uint8_t aes_rcon[10] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
static inline uint32_t load32_be(const uint8_t *p) {
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
}
static inline uint8_t gf256_xtime(uint8_t x) {
return (uint8_t)((x << 1) ^ (((uint8_t)(0 - (x >> 7))) & 0x1B));
}
static inline uint8_t gf256_mul(uint8_t a, uint8_t b) {
uint8_t p = 0;
int i;
for (i = 0; i < 8; i++) {
uint8_t mask = (uint8_t)(0 - (b & 1));
p ^= (a & mask);
a = gf256_xtime(a);
b >>= 1;
}
return p;
}
static inline uint8_t gf256_sqr(uint8_t a) {
return gf256_mul(a, a);
}
static inline uint8_t gf256_inv(uint8_t a) {
uint8_t a2 = gf256_sqr(a);
uint8_t a3 = gf256_mul(a2, a);
uint8_t a6 = gf256_sqr(a3);
uint8_t a7 = gf256_mul(a6, a);
uint8_t a14 = gf256_sqr(a7);
uint8_t a15 = gf256_mul(a14, a);
uint8_t a30 = gf256_sqr(a15);
uint8_t a60 = gf256_sqr(a30);
uint8_t a63 = gf256_mul(a60, a3);
uint8_t a126 = gf256_sqr(a63);
uint8_t a127 = gf256_mul(a126, a);
return gf256_sqr(a127);
}
static inline uint8_t rotl8(uint8_t x, int n) {
return (uint8_t)((x << n) | (x >> (8 - n)));
}
static inline uint8_t aes_sbox_ct(uint8_t in) {
uint8_t inv = gf256_inv(in);
return (uint8_t)(inv ^ rotl8(inv, 1) ^ rotl8(inv, 2) ^ rotl8(inv, 3) ^ rotl8(inv, 4) ^ 0x63);
}
static uint32_t sub_word(uint32_t w) {
return ((uint32_t)aes_sbox_ct((uint8_t)(w >> 24)) << 24) |
((uint32_t)aes_sbox_ct((uint8_t)(w >> 16)) << 16) |
((uint32_t)aes_sbox_ct((uint8_t)(w >> 8)) << 8) | ((uint32_t)aes_sbox_ct((uint8_t)w));
}
static inline uint32_t rot_word(uint32_t w) {
return (w << 8) | (w >> 24);
}
void rivide_aes_encrypt_block(const rivide_aes_key_t *key_ctx, const uint8_t *in, uint8_t *out) {
uint8_t state[16];
int rounds = key_ctx->rounds;
const uint32_t *rk = key_ctx->round_keys;
int i, j, round;
uint8_t t, u, v;
for (i = 0; i < 16; i++) {
state[i] = in[i] ^ (uint8_t)(rk[i / 4] >> (24 - 8 * (i % 4)));
}
for (round = 1; round < rounds; round++) {
uint8_t tmp[16];
for (i = 0; i < 16; i++) {
tmp[i] = aes_sbox_ct(state[i]);
}
state[0] = tmp[0];
state[1] = tmp[5];
state[2] = tmp[10];
state[3] = tmp[15];
state[4] = tmp[4];
state[5] = tmp[9];
state[6] = tmp[14];
state[7] = tmp[3];
state[8] = tmp[8];
state[9] = tmp[13];
state[10] = tmp[2];
state[11] = tmp[7];
state[12] = tmp[12];
state[13] = tmp[1];
state[14] = tmp[6];
state[15] = tmp[11];
for (j = 0; j < 4; j++) {
int base = j * 4;
t = (uint8_t)(state[base] ^ state[base + 1] ^ state[base + 2] ^ state[base + 3]);
u = state[base];
v = (uint8_t)(state[base] ^ state[base + 1]);
v = gf256_xtime(v);
state[base] ^= (uint8_t)(v ^ t);
v = (uint8_t)(state[base + 1] ^ state[base + 2]);
v = gf256_xtime(v);
state[base + 1] ^= (uint8_t)(v ^ t);
v = (uint8_t)(state[base + 2] ^ state[base + 3]);
v = gf256_xtime(v);
state[base + 2] ^= (uint8_t)(v ^ t);
v = (uint8_t)(state[base + 3] ^ u);
v = gf256_xtime(v);
state[base + 3] ^= (uint8_t)(v ^ t);
}
for (i = 0; i < 16; i++) {
state[i] ^= (uint8_t)(rk[round * 4 + i / 4] >> (24 - 8 * (i % 4)));
}
}
{
uint8_t tmp[16];
for (i = 0; i < 16; i++) {
tmp[i] = aes_sbox_ct(state[i]);
}
state[0] = tmp[0];
state[1] = tmp[5];
state[2] = tmp[10];
state[3] = tmp[15];
state[4] = tmp[4];
state[5] = tmp[9];
state[6] = tmp[14];
state[7] = tmp[3];
state[8] = tmp[8];
state[9] = tmp[13];
state[10] = tmp[2];
state[11] = tmp[7];
state[12] = tmp[12];
state[13] = tmp[1];
state[14] = tmp[6];
state[15] = tmp[11];
for (i = 0; i < 16; i++) {
state[i] ^= (uint8_t)(rk[rounds * 4 + i / 4] >> (24 - 8 * (i % 4)));
}
}
for (i = 0; i < 16; i++) {
out[i] = state[i];
}
rivide_cleanse(state, sizeof(state));
}
void rivide_aes_key_cleanse(rivide_aes_key_t *ctx) {
if (ctx) {
rivide_cleanse(ctx->round_keys, sizeof(ctx->round_keys));
ctx->rounds = 0;
}
}
rivide_status_t rivide_aes128_key_expand(rivide_aes_key_t *ctx, const uint8_t *key) {
int i;
if (!ctx || !key) {
return RIVIDE_ERR_NULL_PTR;
}
ctx->rounds = 10;
for (i = 0; i < 4; i++) {
ctx->round_keys[i] = load32_be(key + 4 * i);
}
for (i = 4; i < 44; i++) {
uint32_t tmp = ctx->round_keys[i - 1];
if (i % 4 == 0) {
tmp = sub_word(rot_word(tmp)) ^ ((uint32_t)aes_rcon[i / 4 - 1] << 24);
}
ctx->round_keys[i] = ctx->round_keys[i - 4] ^ tmp;
}
return RIVIDE_SUCCESS;
}
rivide_status_t rivide_aes256_key_expand(rivide_aes_key_t *ctx, const uint8_t *key) {
int i;
if (!ctx || !key) {
return RIVIDE_ERR_NULL_PTR;
}
ctx->rounds = 14;
for (i = 0; i < 8; i++) {
ctx->round_keys[i] = load32_be(key + 4 * i);
}
for (i = 8; i < 60; i++) {
uint32_t tmp = ctx->round_keys[i - 1];
if (i % 8 == 0) {
tmp = sub_word(rot_word(tmp)) ^ ((uint32_t)aes_rcon[i / 8 - 1] << 24);
} else if (i % 8 == 4) {
tmp = sub_word(tmp);
}
ctx->round_keys[i] = ctx->round_keys[i - 8] ^ tmp;
}
return RIVIDE_SUCCESS;
}