1#include "inv_cipher.h"2 3#define Nb 44#define Nr 105 6extern uint8_t inv_sbox[256];7 8#define get_sbox_invert(num) (inv_sbox[(num)])9 10uint8_t xtime(uint8_t x) { return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); }11 12#define multiply(x, y) \13 (((y & 1) * x) ^ ((y >> 1 & 1) * xtime(x)) ^ \14 ((y >> 2 & 1) * xtime(xtime(x))) ^ \15 ((y >> 3 & 1) * xtime(xtime(xtime(x)))) ^ \16 ((y >> 4 & 1) * xtime(xtime(xtime(xtime(x))))))17 18void inv_mix_columns(state_t* state) {19 int i;20 uint8_t a, b, c, d;21 for (i = 0; i < 4; ++i) {22 a = (*state)[i][0];23 b = (*state)[i][1];24 c = (*state)[i][2];25 d = (*state)[i][3];26 27 (*state)[i][0] = multiply(a, 0x0e) ^ multiply(b, 0x0b) ^28 multiply(c, 0x0d) ^ multiply(d, 0x09);29 (*state)[i][1] = multiply(a, 0x09) ^ multiply(b, 0x0e) ^30 multiply(c, 0x0b) ^ multiply(d, 0x0d);31 (*state)[i][2] = multiply(a, 0x0d) ^ multiply(b, 0x09) ^32 multiply(c, 0x0e) ^ multiply(d, 0x0b);33 (*state)[i][3] = multiply(a, 0x0b) ^ multiply(b, 0x0d) ^34 multiply(c, 0x09) ^ multiply(d, 0x0e);35 }36}37 38void inv_sub_bytes(state_t* state) {39 uint8_t i, j;40 for (i = 0; i < 4; ++i) {41 for (j = 0; j < 4; ++j) {42 (*state)[j][i] = get_sbox_invert((*state)[j][i]);43 }44 }45}46 47static void inv_shift_rows(state_t* state) {48 uint8_t temp;49 50 // Rotate first row 1 columns to right51 temp = (*state)[3][1];52 (*state)[3][1] = (*state)[2][1];53 (*state)[2][1] = (*state)[1][1];54 (*state)[1][1] = (*state)[0][1];55 (*state)[0][1] = temp;56 57 // Rotate second row 2 columns to right58 temp = (*state)[0][2];59 (*state)[0][2] = (*state)[2][2];60 (*state)[2][2] = temp;61 62 temp = (*state)[1][2];63 (*state)[1][2] = (*state)[3][2];64 (*state)[3][2] = temp;65 66 // Rotate third row 3 columns to right67 temp = (*state)[0][3];68 (*state)[0][3] = (*state)[1][3];69 (*state)[1][3] = (*state)[2][3];70 (*state)[2][3] = (*state)[3][3];71 (*state)[3][3] = temp;72}73 74void add_round_key(uint8_t round, state_t* state, const uint8_t* round_key) {75 uint8_t i, j;76 for (i = 0; i < 4; ++i) {77 for (j = 0; j < 4; ++j) {78 (*state)[i][j] ^= round_key[(round * Nb * 4) + (i * Nb) + j];79 }80 }81}82 83void inv_cipher(state_t* state, const uint8_t* round_key) {84 uint8_t round = 0;85 86 add_round_key(Nr, state, round_key);87 88 for (round = (Nr - 1);; --round) {89 inv_shift_rows(state);90 inv_sub_bytes(state);91 add_round_key(round, state, round_key);92 if (round == 0) {93 break;94 }95 inv_mix_columns(state);96 }97}
1#ifndef _INV_CIPHER_H_2#define _INV_CIPHER_H_3 4#include <stdint.h>5 6typedef uint8_t state_t[4][4];7void inv_cipher(state_t* state, const uint8_t* round_key);8 9#endif // _INV_CIPHER_H_
1#include <stdio.h>2#include <string.h>3 4#include "inv_cipher.h"5#include "key_expansion.h"6#include "rcon.h"7#include "sbox.h"8 9#define Nb 410#define Nk 411#define Nr 1012 13extern uint8_t sbox[256];14extern uint8_t inv_sbox[256];15extern int rcon[Nr + 1];16 17static int test_inv_cipher(void);18 19int main(void) {20 int exit;21 22 int num_rounds = Nr + 1;23 initialize_aes_sbox(sbox);24 initialize_inverse_aes_sbox(inv_sbox, sbox);25 calculate_rcon(num_rounds, rcon);26 27 exit = test_inv_cipher();28 29 return exit;30}31 32static int test_inv_cipher(void) {33 uint8_t round_key[176];34 uint8_t key[16] = {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,35 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C};36 37 key_expansion(round_key, key);38 39 uint8_t decrypted[] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,40 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A};41 uint8_t in[] = {0x3A, 0xD7, 0x7B, 0xB4, 0x0D, 0x7A, 0x36, 0x60,42 0xA8, 0x9E, 0xCA, 0xF3, 0x24, 0x66, 0xEF, 0x97};43 44 inv_cipher((state_t*)in, round_key);45 46 printf("AES Inverse Cipher test: ");47 48 if (0 == memcmp((char*)in, (char*)decrypted, sizeof decrypted)) {49 printf("SUCCESS!\n");50 return (0);51 } else {52 printf("FAILURE!\n");53 return (1);54 }55}
1#include "key_expansion.h"2 3#define Nb 44#define Nk 45#define Nr 106 7extern uint8_t sbox[256];8extern int rcon[Nr + 1];9 10#define get_sbox_value(num) (sbox[(num)])11 12void key_expansion(uint8_t* round_key, const uint8_t* key) {13 unsigned i, j, k;14 uint8_t tempa[4];15 16 for (i = 0; i < Nk; ++i) {17 round_key[(i * 4) + 0] = key[(i * 4) + 0];18 round_key[(i * 4) + 1] = key[(i * 4) + 1];19 round_key[(i * 4) + 2] = key[(i * 4) + 2];20 round_key[(i * 4) + 3] = key[(i * 4) + 3];21 }22 23 for (i = Nk; i < Nb * (Nr + 1); ++i) {24 {25 k = (i - 1) * 4;26 tempa[0] = round_key[k + 0];27 tempa[1] = round_key[k + 1];28 tempa[2] = round_key[k + 2];29 tempa[3] = round_key[k + 3];30 }31 32 if (i % Nk == 0) {33 // Function RotWord()34 {35 const uint8_t u8tmp = tempa[0];36 tempa[0] = tempa[1];37 tempa[1] = tempa[2];38 tempa[2] = tempa[3];39 tempa[3] = u8tmp;40 }41 42 // Function Subword()43 {44 tempa[0] = get_sbox_value(tempa[0]);45 tempa[1] = get_sbox_value(tempa[1]);46 tempa[2] = get_sbox_value(tempa[2]);47 tempa[3] = get_sbox_value(tempa[3]);48 }49 50 tempa[0] = tempa[0] ^ rcon[i / Nk];51 }52 53 j = i * 4;54 k = (i - Nk) * 4;55 round_key[j + 0] = round_key[k + 0] ^ tempa[0];56 round_key[j + 1] = round_key[k + 1] ^ tempa[1];57 round_key[j + 2] = round_key[k + 2] ^ tempa[2];58 round_key[j + 3] = round_key[k + 3] ^ tempa[3];59 }60}
1#ifndef _KEY_EXPANSION_H_2#define _KEY_EXPANSION_H_3 4#include <stdint.h>5 6void key_expansion(uint8_t* round_key, const uint8_t* key);7 8#endif // _KEY_EXPANSION_H_
1#include "sbox.h"2 3uint8_t sbox[256];4uint8_t inv_sbox[256];5 6#define ROTL8(x, shift) ((uint8_t)((x) << (shift)) | ((x) >> (8 - (shift))))7 8void initialize_aes_sbox(uint8_t sbox[256]) {9 uint8_t p = 1, q = 1;10 11 do {12 p = p ^ (p << 1) ^ (p & 0x80 ? 0x1B : 0);13 14 q ^= q << 1;15 q ^= q << 2;16 q ^= q << 4;17 q ^= q & 0x80 ? 0x09 : 0;18 19 uint8_t xformed =20 q ^ ROTL8(q, 1) ^ ROTL8(q, 2) ^ ROTL8(q, 3) ^ ROTL8(q, 4);21 22 sbox[p] = xformed ^ 0x63;23 } while (p != 1);24 25 sbox[0] = 0x63;26}27 28void initialize_inverse_aes_sbox(uint8_t inv_sbox[256],29 const uint8_t sbox[256]) {30 for (int i = 0; i < 256; i++) {31 inv_sbox[sbox[i]] = i;32 }33}
1#ifndef _SBOX_H_2#define _SBOX_H_3 4#include <stdint.h>5 6void initialize_aes_sbox(uint8_t sbox[256]);7void initialize_inverse_aes_sbox(uint8_t inv_sbox[256],8 const uint8_t sbox[256]);9 10#endif // _SBOX_H_
1#define Nr 102 3int rcon[Nr + 1];4 5void calculate_rcon(int num_rounds, int* rcon) {6 rcon[0] = 0x8d;7 for (int i = 1; i < num_rounds; ++i) {8 rcon[i] = rcon[i - 1] << 1;9 if (rcon[i] & 0x100) {10 rcon[i] ^= 0x11B;11 }12 }13}
1#ifndef _RCON_H_2#define _RCON_H_3 4void calculate_rcon(int num_rounds, int* rcon);5 6#endif // _RCON_H_
gcc inv_cipher.c test_inv_cipher.c key_expansion.c sbox.c rcon.c && ./a.out
AES Inverse Cipher test: SUCCESS!