InvCipher
コード
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!