hw/ip/aes/rtl/aes_key_expand.sv Cov: 100%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // AES KeyExpand
6:
7: module aes_key_expand #(
8: parameter bit AES192Enable = 1,
9: parameter SBoxImpl = "lut"
10: ) (
11: input logic clk_i,
12: input logic rst_ni,
13: input aes_pkg::mode_e mode_i,
14: input logic step_i,
15: input logic clear_i,
16: input logic [3:0] round_i,
17: input aes_pkg::key_len_e key_len_i,
18: input logic [7:0][31:0] key_i,
19: output logic [7:0][31:0] key_o
20: );
21:
22: import aes_pkg::*;
23:
24: logic [7:0] rcon_d, rcon_q;
25: logic rcon_we;
26: logic use_rcon;
27:
28: logic [3:0] rnd;
29: logic [3:0] rnd_type;
30:
31: logic [31:0] spec_in_128, spec_in_192;
32: logic [31:0] rot_word_in, rot_word_out;
33: logic use_rot_word;
34: logic [31:0] sub_word_in, sub_word_out;
35: logic [7:0] rcon_add_in, rcon_add_out;
36: logic [31:0] rcon_added;
37:
38: logic [31:0] irregular;
39: logic [7:0][31:0] regular;
40:
41: assign rnd = round_i;
42:
43: // For AES-192, there are four different types of rounds.
44: always_comb begin : get_rnd_type
45: if (AES192Enable) begin
46: rnd_type[0] = (rnd == 0);
47: rnd_type[1] = (rnd == 1 || rnd == 4 || rnd == 7 || rnd == 10);
48: rnd_type[2] = (rnd == 2 || rnd == 5 || rnd == 8 || rnd == 11);
49: rnd_type[3] = (rnd == 3 || rnd == 6 || rnd == 9 || rnd == 12);
50: end else begin
51: rnd_type = '0;
52: end
53: end
54:
55: //////////////////////////////////////////////////////
56: // Irregular part involving Rcon, RotWord & SubWord //
57: //////////////////////////////////////////////////////
58:
59: // Depending on key length and round, RotWord is not used
60: assign use_rot_word = (key_len_i == AES_256 && rnd[0] == 1'b0) ? 1'b0 : 1'b1;
61:
62: // Depending on mode, key length and round, Rcon is not used and thus must not be updated
63: always_comb begin : rcon_usage
64: use_rcon = 1'b1;
65:
66: if (AES192Enable) begin
67: if (key_len_i == AES_192 &&
68: ((mode_i == AES_ENC && rnd_type[1]) ||
69: (mode_i == AES_DEC && (rnd_type[0] || rnd_type[3])))) begin
70: use_rcon = 1'b0;
71: end
72: end
73:
74: if (key_len_i == AES_256 && rnd[0] == 1'b0) begin
75: use_rcon = 1'b0;
76: end
77: end
78:
79: // Generate Rcon
80: always_comb begin : rcon_update
81: rcon_d = rcon_q;
82:
83: if (clear_i) begin
84: rcon_d = (mode_i == AES_ENC) ? 8'h01 :
85: ((mode_i == AES_DEC) && (key_len_i == AES_128)) ? 8'h36 :
86: ((mode_i == AES_DEC) && (key_len_i == AES_192)) ? 8'h80 :
87: ((mode_i == AES_DEC) && (key_len_i == AES_256)) ? 8'h40 : 8'h01;
88: end else begin
89: rcon_d = (mode_i == AES_ENC) ? aes_mul2(rcon_q) :
90: (mode_i == AES_DEC) ? aes_div2(rcon_q) : 8'h01;
91: end
92: end
93:
94: assign rcon_we = clear_i | (step_i & use_rcon);
95:
96: // Rcon register
97: always_ff @(posedge clk_i or negedge rst_ni) begin : reg_rcon
98: if (!rst_ni) begin
99: rcon_q <= '0;
100: end else if (rcon_we) begin
101: rcon_q <= rcon_d;
102: end
103: end
104:
105: // Special input, equivalent to key_o[3] in the used cases
106: assign spec_in_128 = key_i[3] ^ key_i[2];
107: assign spec_in_192 = AES192Enable ? key_i[5] ^ key_i[1] ^ key_i[0] : '0;
108:
109: // Select input
110: always_comb begin : rot_word_in_mux
111: unique case (key_len_i)
112:
113: /////////////
114: // AES-128 //
115: /////////////
116: AES_128: begin
117: unique case (mode_i)
118: AES_ENC: rot_word_in = key_i[3];
119: AES_DEC: rot_word_in = spec_in_128;
120: default: rot_word_in = key_i[3];
121: endcase
122: end
123:
124: /////////////
125: // AES-192 //
126: /////////////
127: AES_192: begin
128: if (AES192Enable) begin
129: unique case (mode_i)
130: AES_ENC: begin
131: rot_word_in = rnd_type[0] ? key_i[5] :
132: rnd_type[2] ? key_i[5] :
133: rnd_type[3] ? spec_in_192 : key_i[3];
134: end
135: AES_DEC: begin
136: rot_word_in = rnd_type[1] ? key_i[3] :
137: rnd_type[2] ? key_i[1] : key_i[3];
138: end
139: default: rot_word_in = key_i[3];
140: endcase
141: end else begin
142: rot_word_in = key_i[3];
143: end
144: end
145:
146: /////////////
147: // AES-256 //
148: /////////////
149: AES_256: begin
150: unique case (mode_i)
151: AES_ENC: rot_word_in = key_i[7];
152: AES_DEC: rot_word_in = key_i[3];
153: default: rot_word_in = key_i[7];
154: endcase
155: end
156:
157: default: rot_word_in = key_i[3];
158: endcase
159: end
160:
161: // RotWord: cyclic byte shift
162: assign rot_word_out = aes_circ_byte_shift(rot_word_in, 3);
163:
164: // Mux input for SubWord
165: assign sub_word_in = use_rot_word ? rot_word_out : rot_word_in;
166:
167: // SubWord - individually substitute bytes
168: for (genvar i = 0; i < 4; i++) begin : gen_sbox
169: aes_sbox #(
170: .SBoxImpl ( SBoxImpl )
171: ) aes_sbox_i (
172: .mode_i ( AES_ENC ),
173: .data_i ( sub_word_in[8*i +: 8] ),
174: .data_o ( sub_word_out[8*i +: 8] )
175: );
176: end
177:
178: // Add Rcon
179: assign rcon_add_in = sub_word_out[7:0];
180: assign rcon_add_out = rcon_add_in ^ rcon_q;
181: assign rcon_added = {sub_word_out[31:8], rcon_add_out};
182:
183: // Mux output coming from Rcon & SubWord
184: assign irregular = use_rcon ? rcon_added : sub_word_out;
185:
186: ///////////////////////////
187: // The more regular part //
188: ///////////////////////////
189:
190: // To reduce muxing resources, we re-use existing
191: // connections for unused words and default cases.
192: always_comb begin : drive_regular
193: unique case (key_len_i)
194:
195: /////////////
196: // AES-128 //
197: /////////////
198: AES_128: begin
199: // key_o[7:4] not used
200: regular[7:4] = key_i[3:0];
201:
202: regular[0] = irregular ^ key_i[0];
203: unique case (mode_i)
204: AES_ENC: begin
205: for (int i=1; i<4; i++) begin
206: regular[i] = regular[i-1] ^ key_i[i];
207: end
208: end
209:
210: AES_DEC: begin
211: for (int i=1; i<4; i++) begin
212: regular[i] = key_i[i-1] ^ key_i[i];
213: end
214: end
215:
216: default: regular = {key_i[3:0], key_i[7:4]};
217: endcase
218: end
219:
220: /////////////
221: // AES-192 //
222: /////////////
223: AES_192: begin
224: // key_o[7:6] not used
225: regular[7:6] = key_i[3:2];
226:
227: if (AES192Enable) begin
228: unique case (mode_i)
229: AES_ENC: begin
230: if (rnd_type[0]) begin
231: // Shift down four upper most words
232: regular[3:0] = key_i[5:2];
233: // Generate Words 6 and 7
234: regular[4] = irregular ^ key_i[0];
235: regular[5] = regular[4] ^ key_i[1];
236: end else begin
237: // Shift down two upper most words
238: regular[1:0] = key_i[5:4];
239: // Generate new upper four words
240: for (int i=0; i<4; i++) begin
241: if ((i == 0 && rnd_type[2]) ||
242: (i == 2 && rnd_type[3])) begin
243: regular[i+2] = irregular ^ key_i[i];
244: end else begin
245: regular[i+2] = regular[i+1] ^ key_i[i];
246: end
247: end
248: end // rnd_type[0]
249: end
250:
251: AES_DEC: begin
252: if (rnd_type[0]) begin
253: // Shift up four lowest words
254: regular[5:2] = key_i[3:0];
255: // Generate Word 44 and 45
256: for (int i=0; i<2; i++) begin
257: regular[i] = key_i[3+i] ^ key_i[3+i+1];
258: end
259: end else begin
260: // Shift up two lowest words
261: regular[5:4] = key_i[1:0];
262: // Generate new lower four words
263: for (int i=0; i<4; i++) begin
264: if ((i == 2 && rnd_type[1]) ||
265: (i == 0 && rnd_type[2])) begin
266: regular[i] = irregular ^ key_i[i+2];
267: end else begin
268: regular[i] = key_i[i+1] ^ key_i[i+2];
269: end
270: end
271: end // rnd_type[0]
272: end
273:
274: default: regular = {key_i[3:0], key_i[7:4]};
275: endcase
276:
277: end else begin
278: regular = {key_i[3:0], key_i[7:4]};
279: end // AES192Enable
280: end
281:
282: /////////////
283: // AES-256 //
284: /////////////
285: AES_256: begin
286: unique case (mode_i)
287: AES_ENC: begin
288: if (rnd == 0) begin
289: // Round 0: Nothing to be done
290: // The Full Key registers are not updated
291: regular = {key_i[3:0], key_i[7:4]};
292: end else begin
293: // Shift down old upper half
294: regular[3:0] = key_i[7:4];
295: // Generate new upper half
296: regular[4] = irregular ^ key_i[0];
297: for (int i=1; i<4; i++) begin
298: regular[i+4] = regular[i+4-1] ^ key_i[i];
299: end
300: end // rnd == 0
301: end
302:
303: AES_DEC: begin
304: if (rnd == 0) begin
305: // Round 0: Nothing to be done
306: // The Full Key registers are not updated
307: regular = {key_i[3:0], key_i[7:4]};
308: end else begin
309: // Shift up old lower half
310: regular[7:4] = key_i[3:0];
311: // Generate new lower half
312: regular[0] = irregular ^ key_i[4];
313: for (int i=0; i<3; i++) begin
314: regular[i+1] = key_i[4+i] ^ key_i[4+i+1];
315: end
316: end // rnd == 0
317: end
318:
319: default: regular = {key_i[3:0], key_i[7:4]};
320: endcase
321: end
322:
323: default: regular = {key_i[3:0], key_i[7:4]};
324: endcase // key_len_i
325: end
326:
327: // Drive output
328: assign key_o = regular;
329:
330: // Selectors must be known/valid
331: `ASSERT_KNOWN(AesModeKnown, mode_i, clk_i, !rst_ni)
332: `ASSERT(AesKeyLenValid, key_len_i inside {
333: AES_128,
334: AES_192,
335: AES_256
336: }, clk_i, !rst_ni)
337:
338: endmodule
339: