コンテンツにスキップ

InvCipher

コード

inv_cipher.c
1
#include "inv_cipher.h"
2
3
#define Nb 4
4
#define Nr 10
5
6
extern uint8_t inv_sbox[256];
7
8
#define get_sbox_invert(num) (inv_sbox[(num)])
9
10
uint8_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
18
void 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
38
void 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
47
static void inv_shift_rows(state_t* state) {
48
uint8_t temp;
49
50
// Rotate first row 1 columns to right
51
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 right
58
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 right
67
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
74
void 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
83
void 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
}
inv_cipher.h
1
#ifndef _INV_CIPHER_H_
2
#define _INV_CIPHER_H_
3
4
#include <stdint.h>
5
6
typedef uint8_t state_t[4][4];
7
void inv_cipher(state_t* state, const uint8_t* round_key);
8
9
#endif // _INV_CIPHER_H_
test_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 4
10
#define Nk 4
11
#define Nr 10
12
13
extern uint8_t sbox[256];
14
extern uint8_t inv_sbox[256];
15
extern int rcon[Nr + 1];
16
17
static int test_inv_cipher(void);
18
19
int 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
32
static 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
}
その他のソースコード
key_expansion.c
1
#include "key_expansion.h"
2
3
#define Nb 4
4
#define Nk 4
5
#define Nr 10
6
7
extern uint8_t sbox[256];
8
extern int rcon[Nr + 1];
9
10
#define get_sbox_value(num) (sbox[(num)])
11
12
void 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
}
key_expansion.h
1
#ifndef _KEY_EXPANSION_H_
2
#define _KEY_EXPANSION_H_
3
4
#include <stdint.h>
5
6
void key_expansion(uint8_t* round_key, const uint8_t* key);
7
8
#endif // _KEY_EXPANSION_H_
sbox.c
1
#include "sbox.h"
2
3
uint8_t sbox[256];
4
uint8_t inv_sbox[256];
5
6
#define ROTL8(x, shift) ((uint8_t)((x) << (shift)) | ((x) >> (8 - (shift))))
7
8
void 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
28
void 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
}
sbox.h
1
#ifndef _SBOX_H_
2
#define _SBOX_H_
3
4
#include <stdint.h>
5
6
void initialize_aes_sbox(uint8_t sbox[256]);
7
void initialize_inverse_aes_sbox(uint8_t inv_sbox[256],
8
const uint8_t sbox[256]);
9
10
#endif // _SBOX_H_
rcon.c
1
#define Nr 10
2
3
int rcon[Nr + 1];
4
5
void 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
}
rcon.h
1
#ifndef _RCON_H_
2
#define _RCON_H_
3
4
void calculate_rcon(int num_rounds, int* rcon);
5
6
#endif // _RCON_H_

実行

Terminal window
gcc inv_cipher.c test_inv_cipher.c key_expansion.c sbox.c rcon.c && ./a.out
実行結果
AES Inverse Cipher test: SUCCESS!