1 |
2 |
vv_gulyaev |
/**
|
2 |
|
|
* AES-128-ECB Encoder module
|
3 |
|
|
*
|
4 |
|
|
* Copyright 2020 by Vyacheslav Gulyaev
|
5 |
|
|
*
|
6 |
|
|
* Licensed under GNU General Public License 3.0 or later.
|
7 |
|
|
* Some rights reserved. See COPYING, AUTHORS.
|
8 |
|
|
*
|
9 |
|
|
* @license GPL-3.0+
|
10 |
|
|
*/
|
11 |
|
|
|
12 |
|
|
module aes128_enc(
|
13 |
|
|
input clk_i,
|
14 |
|
|
input rstn_i,
|
15 |
|
|
|
16 |
|
|
input [127:0] data_i,
|
17 |
|
|
input [127:0] key_i,
|
18 |
|
|
input valid_i,
|
19 |
|
|
|
20 |
|
|
|
21 |
|
|
output logic [127:0] data_o,
|
22 |
|
|
output logic valid_o
|
23 |
|
|
|
24 |
|
|
);
|
25 |
|
|
|
26 |
|
|
//`define DEBUG_MODE
|
27 |
|
|
|
28 |
|
|
localparam logic [7:0] Sbox[0:15][0:15] = '{/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
29 |
|
|
/*0*/ '{8'h63, 8'h7c, 8'h77, 8'h7b, 8'hf2, 8'h6b, 8'h6f, 8'hc5, 8'h30, 8'h01, 8'h67, 8'h2b, 8'hfe, 8'hd7, 8'hab, 8'h76},
|
30 |
|
|
/*1*/ '{8'hca, 8'h82, 8'hc9, 8'h7d, 8'hfa, 8'h59, 8'h47, 8'hf0, 8'had, 8'hd4, 8'ha2, 8'haf, 8'h9c, 8'ha4, 8'h72, 8'hc0},
|
31 |
|
|
/*2*/ '{8'hb7, 8'hfd, 8'h93, 8'h26, 8'h36, 8'h3f, 8'hf7, 8'hcc, 8'h34, 8'ha5, 8'he5, 8'hf1, 8'h71, 8'hd8, 8'h31, 8'h15},
|
32 |
|
|
/*3*/ '{8'h04, 8'hc7, 8'h23, 8'hc3, 8'h18, 8'h96, 8'h05, 8'h9a, 8'h07, 8'h12, 8'h80, 8'he2, 8'heb, 8'h27, 8'hb2, 8'h75},
|
33 |
|
|
/*4*/ '{8'h09, 8'h83, 8'h2c, 8'h1a, 8'h1b, 8'h6e, 8'h5a, 8'ha0, 8'h52, 8'h3b, 8'hd6, 8'hb3, 8'h29, 8'he3, 8'h2f, 8'h84},
|
34 |
|
|
/*5*/ '{8'h53, 8'hd1, 8'h00, 8'hed, 8'h20, 8'hfc, 8'hb1, 8'h5b, 8'h6a, 8'hcb, 8'hbe, 8'h39, 8'h4a, 8'h4c, 8'h58, 8'hcf},
|
35 |
|
|
/*6*/ '{8'hd0, 8'hef, 8'haa, 8'hfb, 8'h43, 8'h4d, 8'h33, 8'h85, 8'h45, 8'hf9, 8'h02, 8'h7f, 8'h50, 8'h3c, 8'h9f, 8'ha8},
|
36 |
|
|
/*7*/ '{8'h51, 8'ha3, 8'h40, 8'h8f, 8'h92, 8'h9d, 8'h38, 8'hf5, 8'hbc, 8'hb6, 8'hda, 8'h21, 8'h10, 8'hff, 8'hf3, 8'hd2},
|
37 |
|
|
/*8*/ '{8'hcd, 8'h0c, 8'h13, 8'hec, 8'h5f, 8'h97, 8'h44, 8'h17, 8'hc4, 8'ha7, 8'h7e, 8'h3d, 8'h64, 8'h5d, 8'h19, 8'h73},
|
38 |
|
|
/*9*/ '{8'h60, 8'h81, 8'h4f, 8'hdc, 8'h22, 8'h2a, 8'h90, 8'h88, 8'h46, 8'hee, 8'hb8, 8'h14, 8'hde, 8'h5e, 8'h0b, 8'hdb},
|
39 |
|
|
/*A*/ '{8'he0, 8'h32, 8'h3a, 8'h0a, 8'h49, 8'h06, 8'h24, 8'h5c, 8'hc2, 8'hd3, 8'hac, 8'h62, 8'h91, 8'h95, 8'he4, 8'h79},
|
40 |
|
|
/*B*/ '{8'he7, 8'hc8, 8'h37, 8'h6d, 8'h8d, 8'hd5, 8'h4e, 8'ha9, 8'h6c, 8'h56, 8'hf4, 8'hea, 8'h65, 8'h7a, 8'hae, 8'h08},
|
41 |
|
|
/*C*/ '{8'hba, 8'h78, 8'h25, 8'h2e, 8'h1c, 8'ha6, 8'hb4, 8'hc6, 8'he8, 8'hdd, 8'h74, 8'h1f, 8'h4b, 8'hbd, 8'h8b, 8'h8a},
|
42 |
|
|
/*D*/ '{8'h70, 8'h3e, 8'hb5, 8'h66, 8'h48, 8'h03, 8'hf6, 8'h0e, 8'h61, 8'h35, 8'h57, 8'hb9, 8'h86, 8'hc1, 8'h1d, 8'h9e},
|
43 |
|
|
/*E*/ '{8'he1, 8'hf8, 8'h98, 8'h11, 8'h69, 8'hd9, 8'h8e, 8'h94, 8'h9b, 8'h1e, 8'h87, 8'he9, 8'hce, 8'h55, 8'h28, 8'hdf},
|
44 |
|
|
/*F*/ '{8'h8c, 8'ha1, 8'h89, 8'h0d, 8'hbf, 8'he6, 8'h42, 8'h68, 8'h41, 8'h99, 8'h2d, 8'h0f, 8'hb0, 8'h54, 8'hbb, 8'h16}
|
45 |
|
|
};
|
46 |
|
|
|
47 |
|
|
localparam logic [7:0] Rcon[0:3][0:9] = '{
|
48 |
|
|
'{8'h01, 8'h02, 8'h04, 8'h08, 8'h10, 8'h20, 8'h40, 8'h80, 8'h1b, 8'h36},
|
49 |
|
|
'{8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00},
|
50 |
|
|
'{8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00},
|
51 |
|
|
'{8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00}
|
52 |
|
|
};
|
53 |
|
|
|
54 |
|
|
typedef logic [7:0] state_t [0:3] [0:3];
|
55 |
|
|
state_t state;
|
56 |
|
|
state_t round_key;
|
57 |
|
|
|
58 |
|
|
logic [127:0] data_int;
|
59 |
|
|
logic [3:0] round;
|
60 |
|
|
logic busy;
|
61 |
|
|
|
62 |
|
|
////////////////////////////////////////
|
63 |
|
|
/*
|
64 |
|
|
* Implementation of functions area start
|
65 |
|
|
*/
|
66 |
|
|
|
67 |
|
|
/*Transform functions 128-bit(16byte) vector to byte state matrix 4x4 and back
|
68 |
|
|
*[15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0] <==> | 15 11 7 3 |
|
69 |
|
|
* | 14 10 6 2 |
|
70 |
|
|
* | 13 9 5 1 |
|
71 |
|
|
* | 12 8 4 0 |
|
72 |
|
|
*/
|
73 |
|
|
function state_t vect_to_matrix(input logic [127:0] data);
|
74 |
|
|
state_t state_o;
|
75 |
|
|
state_o ='{ '{data[127:120], data[95:88], data[63:56], data[31:24]},
|
76 |
|
|
'{data[119:112], data[87:80], data[55:48], data[23:16]},
|
77 |
|
|
'{data[111:104], data[79:72], data[47:40], data[15: 8]},
|
78 |
|
|
'{data[103: 96], data[71:64], data[39:32], data[ 7: 0]}
|
79 |
|
|
};
|
80 |
|
|
return state_o;
|
81 |
|
|
endfunction
|
82 |
|
|
|
83 |
|
|
function logic [127:0] matrix_to_vector(input state_t st);
|
84 |
|
|
logic [127:0] d_o;
|
85 |
|
|
d_o = { st[0][0], st[1][0], st[2][0], st[3][0],
|
86 |
|
|
st[0][1], st[1][1], st[2][1], st[3][1],
|
87 |
|
|
st[0][2], st[1][2], st[2][2], st[3][2],
|
88 |
|
|
st[0][3], st[1][3], st[2][3], st[3][3]
|
89 |
|
|
};
|
90 |
|
|
return d_o;
|
91 |
|
|
endfunction
|
92 |
|
|
|
93 |
|
|
/*
|
94 |
|
|
* Replase data in state matrix with data from Sbox(2^8) table
|
95 |
|
|
*/
|
96 |
|
|
function state_t sub_bytes(input state_t st);
|
97 |
|
|
logic [3:0] r_gf;
|
98 |
|
|
logic [3:0] c_gf;
|
99 |
|
|
state_t state_o;
|
100 |
|
|
for (int r=0; r<4; r=r+1) begin
|
101 |
|
|
for (int c=0; c<4; c=c+1) begin
|
102 |
|
|
r_gf = st[r][c][7:4];
|
103 |
|
|
c_gf = st[r][c][3:0];
|
104 |
|
|
state_o[r][c] = Sbox[r_gf][c_gf];
|
105 |
|
|
end
|
106 |
|
|
end
|
107 |
|
|
//void'(debug_output("After sub bytes", state_o));
|
108 |
|
|
return state_o;
|
109 |
|
|
endfunction
|
110 |
|
|
|
111 |
|
|
/*
|
112 |
|
|
* Cyclic shift bytes in state matrix rows
|
113 |
|
|
*/
|
114 |
|
|
function state_t shift_rows(input state_t st);
|
115 |
|
|
state_t state_o;
|
116 |
|
|
state_o = '{'{st[0][0], st[0][1], st[0][2], st[0][3]},
|
117 |
|
|
'{st[1][1], st[1][2], st[1][3], st[1][0]},
|
118 |
|
|
'{st[2][2], st[2][3], st[2][0], st[2][1]},
|
119 |
|
|
'{st[3][3], st[3][0], st[3][1], st[3][2]}
|
120 |
|
|
};
|
121 |
|
|
//void'(debug_output("After shift rows", state_o));
|
122 |
|
|
return state_o;
|
123 |
|
|
endfunction
|
124 |
|
|
|
125 |
|
|
/*
|
126 |
|
|
* Multiplication by 2: 1-bit shift left + xor 8'h1b (if val[7]==1)
|
127 |
|
|
*/
|
128 |
|
|
function logic [7:0] mul2(input logic [7:0] val);
|
129 |
|
|
return (({val[6:0], 1'b0}) ^ (val[7] ? 8'h1b : 8'h00));
|
130 |
|
|
endfunction
|
131 |
|
|
|
132 |
|
|
/*
|
133 |
|
|
* Multiplication by 3: mul2 + val ('+' is xor operation)
|
134 |
|
|
*/
|
135 |
|
|
function logic [7:0] mul3(input logic [7:0] val);
|
136 |
|
|
return (mul2(val) ^ val);
|
137 |
|
|
endfunction
|
138 |
|
|
|
139 |
|
|
/* Mix column algorithm is multiplication matrix on column vector
|
140 |
|
|
* | s'[0,c] | = | 02 03 01 01 | * | s[0,c] |
|
141 |
|
|
* | s'[1.c] | | 01 02 03 01 | | s[1,c] |
|
142 |
|
|
* | s'[2,c] | | 01 01 02 03 | | s[2,c] |
|
143 |
|
|
* | s'[3,c] | | 03 01 01 02 | | s[3,c] |
|
144 |
|
|
*/
|
145 |
|
|
function state_t mix_columns(input state_t st);
|
146 |
|
|
state_t state_o;
|
147 |
|
|
for (int c=0; c<4; c=c+1) begin
|
148 |
|
|
state_o[0][c] = mul2(st[0][c]) ^ mul3(st[1][c]) ^ st[2][c] ^ st[3][c]; //s'[0,c] = ({02}*s[0,c]) + ({03}*s[1,c]) + s[2,c] + s[3,c]
|
149 |
|
|
state_o[1][c] = st[0][c] ^ mul2(st[1][c]) ^ mul3(st[2][c]) ^ st[3][c]; //s'[1,c] = s[0,c] + ({02}*s[1,c]) + ({03}*s[2,c]) + s[3,c]
|
150 |
|
|
state_o[2][c] = st[0][c] ^ st[1][c] ^ mul2(st[2][c]) ^ mul3(st[3][c]); //s'[2,c] = s[0,c] + s[1,c] + ({02}*s[2,c]) + ({03}*s[3,c])
|
151 |
|
|
state_o[3][c] = mul3(st[0][c]) ^ st[1][c] ^ st[2][c] ^ mul2(st[3][c]); //s'[2,c] = ({02}*s[0,c]) + s[1,c] + s[2,c] + ({02}*s[3,c])
|
152 |
|
|
end
|
153 |
|
|
//void'(debug_output("After mix columns", state_o));
|
154 |
|
|
return state_o;
|
155 |
|
|
endfunction
|
156 |
|
|
|
157 |
|
|
/*
|
158 |
|
|
* Computing next round key for key schedule
|
159 |
|
|
* */
|
160 |
|
|
function state_t compute_next_round_key(input state_t key, input logic [3:0] cur_round);
|
161 |
|
|
state_t key_o;
|
162 |
|
|
logic [3:0] r_gf;
|
163 |
|
|
logic [3:0] c_gf;
|
164 |
|
|
|
165 |
|
|
for (int r=0; r<4; r=r+1) begin
|
166 |
|
|
//compute [0] column
|
167 |
|
|
//sub bytes from Sbox
|
168 |
|
|
if (r<3) begin
|
169 |
|
|
r_gf = key[r+1][3][7:4];
|
170 |
|
|
c_gf = key[r+1][3][3:0];
|
171 |
|
|
end else begin
|
172 |
|
|
r_gf = key[0][3][7:4];
|
173 |
|
|
c_gf = key[0][3][3:0];
|
174 |
|
|
end
|
175 |
|
|
key_o[r][0] = key[r][0] ^ Sbox[r_gf][c_gf] ^ Rcon[r][cur_round];
|
176 |
|
|
|
177 |
|
|
//compute [1:3] columns
|
178 |
|
|
for (int c=1; c<4; c=c+1) begin
|
179 |
|
|
key_o[r][c] = key_o[r][c-1] ^ key[r][c];
|
180 |
|
|
end
|
181 |
|
|
end
|
182 |
|
|
return key_o;
|
183 |
|
|
endfunction
|
184 |
|
|
|
185 |
|
|
/*
|
186 |
|
|
* Adding round key
|
187 |
|
|
* */
|
188 |
|
|
function state_t add_round_key(input state_t st, input state_t key);
|
189 |
|
|
state_t state_o;
|
190 |
|
|
for (int r=0; r<4; r=r+1) begin
|
191 |
|
|
for (int c=0; c<4; c=c+1) begin
|
192 |
|
|
state_o[r][c] = st[r][c] ^ key[r][c];
|
193 |
|
|
end
|
194 |
|
|
end
|
195 |
|
|
//void'(debug_output("After add round key", state_o));
|
196 |
|
|
return state_o;
|
197 |
|
|
endfunction
|
198 |
|
|
|
199 |
|
|
/*
|
200 |
|
|
* Debug output
|
201 |
|
|
* */
|
202 |
|
|
/*
|
203 |
|
|
function debug_output(string info, state_t state);
|
204 |
|
|
`ifdef DEBUG_MODE
|
205 |
|
|
for (int r=0; r<4; r=r+1) begin
|
206 |
|
|
$display("[%t]: %s: 0x%02H 0x%02H 0x%02H 0x%02H", $time, info, state[r][0], state[r][1], state[r][2], state[r][3]);
|
207 |
|
|
end
|
208 |
|
|
$display("");
|
209 |
|
|
`endif
|
210 |
|
|
endfunction
|
211 |
|
|
*/
|
212 |
|
|
/*
|
213 |
|
|
* Implementation of functions area end
|
214 |
|
|
*/
|
215 |
|
|
////////////////////////////////////////
|
216 |
|
|
|
217 |
|
|
|
218 |
|
|
//AES-128 encoder logic
|
219 |
|
|
assign data_int = data_i ^ key_i; // Initialization, i.e. adding round key before 1st round
|
220 |
|
|
|
221 |
|
|
always @(posedge clk_i or negedge rstn_i) begin
|
222 |
|
|
if (~rstn_i) begin
|
223 |
|
|
`ifdef DEBUG_MODE
|
224 |
|
|
$display("=====Reseting=====");
|
225 |
|
|
`endif
|
226 |
|
|
state = vect_to_matrix(127'h0);
|
227 |
|
|
round_key = vect_to_matrix(127'h0);
|
228 |
|
|
round = 4'h0;
|
229 |
|
|
busy = 1'b0;
|
230 |
|
|
data_o = 128'h0;
|
231 |
|
|
valid_o = 1'b0;
|
232 |
|
|
end else if (valid_i & ~busy) begin //1st round after valid data receiving
|
233 |
|
|
`ifdef DEBUG_MODE
|
234 |
|
|
$display("=====Received valid data, starting round 1=====");
|
235 |
|
|
`endif
|
236 |
|
|
round = 4'h0;
|
237 |
|
|
busy = 1'b1;
|
238 |
|
|
|
239 |
|
|
state = vect_to_matrix(data_int); //convert 128 bit data xored with key to byte matrix 4x4
|
240 |
|
|
state = sub_bytes(state); //change data bytes on bytes from Sbox field
|
241 |
|
|
state = shift_rows(state); //shift columns in rows
|
242 |
|
|
state = mix_columns(state);//mix columns algorithm
|
243 |
|
|
round_key = vect_to_matrix(key_i);//convert 128bit key to byte matrix 4x4
|
244 |
|
|
round_key = compute_next_round_key(round_key, round);//get next schedule key
|
245 |
|
|
state = add_round_key(state, round_key);
|
246 |
|
|
|
247 |
|
|
round = round + 1;
|
248 |
|
|
data_o = 128'h0;
|
249 |
|
|
valid_o = 1'b0;
|
250 |
|
|
end else if (busy) begin //rounds 2-10
|
251 |
|
|
`ifdef DEBUG_MODE
|
252 |
|
|
$display("=====Round %02d=====", (round+1));
|
253 |
|
|
`endif
|
254 |
|
|
state = sub_bytes(state); //change data bytes on bytes from Sbox field
|
255 |
|
|
|
256 |
|
|
state = shift_rows(state); //shift columns in rows
|
257 |
|
|
if (round!=4'h9) begin
|
258 |
|
|
state = mix_columns(state);//mix columns algorithm
|
259 |
|
|
end
|
260 |
|
|
round_key = compute_next_round_key(round_key, round);//get next schedule key
|
261 |
|
|
state = add_round_key(state, round_key);
|
262 |
|
|
if (round==9'h9) begin
|
263 |
|
|
round = 4'h0;
|
264 |
|
|
busy = 1'b0;
|
265 |
|
|
data_o = matrix_to_vector(state);
|
266 |
|
|
valid_o = 1'b1;
|
267 |
|
|
end else begin
|
268 |
|
|
round = round + 1;
|
269 |
|
|
busy = 1'b1;
|
270 |
|
|
data_o = 128'h0;
|
271 |
|
|
valid_o = 1'b0;
|
272 |
|
|
end
|
273 |
|
|
end else begin
|
274 |
|
|
`ifdef DEBUG_MODE
|
275 |
|
|
$display("=====IDLE=====");
|
276 |
|
|
`endif
|
277 |
|
|
state = vect_to_matrix(127'h0);
|
278 |
|
|
round_key = vect_to_matrix(127'h0);
|
279 |
|
|
round = 4'h0;
|
280 |
|
|
busy = 1'b0;
|
281 |
|
|
data_o = 128'h0;
|
282 |
|
|
valid_o = 1'b0;
|
283 |
|
|
end
|
284 |
|
|
end
|
285 |
|
|
|
286 |
|
|
endmodule
|