FONT SIZE : AAA
In 1997, the U.S. National Institute of Standards and Technology (NIST) published a request for information regarding the creation of a new Advanced Encryption Standard (AES) for nonclassified government documents. The call also stipulated that the AES would specify an unclassified, publicly disclosed encryption algorithm(s), available royalty-free, worldwide.
In addition, the algorithm(s) must implement symmetric key cryptography as a block cipher and (at a minimum) support block sizes of 128 bits and key sizes of 128, 192, and 256 bits. After an open competition, the Rijndael algorithm was chosen as the winner and implemented as the AES standard. Rijndael allows key and block sizes to be 128, 192, or 256 bits.
AES allows the same key sizes, but operates using a block size of 128 bits. The algorithm operates in a similar way to DES, with 10 rounds of confusion and diffusion operators (shuffling and mixing) blocks at a time. Each round has a separate key, generated from the overall key. The round structure is shown in Figure 10.7.
The overall AES structure is given in Figure 10.8.
Figure 10.7
AES round structure.
Figure 10.8
AES structure.
Each block consists of 128 bits, and these are divided into 16 8-bit bytes. Each of the operations acts upon these 8-bit bytes in a 4 × 4 matrix:
Note that each element (ai,j) is an 8-bit byte, viewed as elements of GF(28). The arithmetic operators take advantage of the Galois Field (GF) rules defined in the Rijndael algorithm; an example is that of addition that is implemented by XOR.
Multiplication is more complicated, but each byte has the multiplicative inverse such that b.b = 00000001 (apart from 00000000, whose multiplicative inverse is 00000000). The model of the finite field GF(28) depends on the choice of an irreducible polynomial of degree 8, which for Rijndael is:
X8 + X4 + X3 + 1 (10.2)
Each of the round operations requires a specific mathematical exploration. Taking each in turn we can establish the requirements for each one.
Taking the original matrix:
each element can be replaced byte-by-byte to generate a new matrix:
Byte substitution requires that for each input data block a(3, 3), we look up a table of substitutions and replace the bytes to produce a new matrix b(3, 3). The way it works is that for each input byte abcdefgh, we look up row abcd and column efgh and use the byte at that location in the output.
The complete byte substitution table is defined as shown in Figure 10.9.
For example: If the input data byte was 7A, then this in binary terms is:
0111 1010
So the row required is 7 (0111) and the column required is A (1010). From this we can read off the resulting number from the table:
218 = 1101 1010 = DA
This is illustrated in the byte substitution table in Figure 10.9.
We can see that this is a bit shuffling operation that is simply moving bytes around in a publicly defined manner that does not have anything to do with a key.
Also note that the individual bits within the byte are not changed as such. This is a bytewise operation. The Shift Row function is essentially a set of cyclic shifts to the left with offsets of 0, 1, 2, 3, respectively.
Figure 10.9
AES byte substitution table.
The Mix Columns function is a series of specific multiplications:
where 01 = 00000001, 02 = 00000010, 03 = 00000011.
All multiplications are GF(28) and this transformation is invertible.
The final operation in each round is to add the key using the following function:
The round keys are generated using the following method. The original key of 128 bits is represented as a 4 × 4 matrix of bytes (of 8 bits). This can be thought of as four columns W(0), W(1), W(2), W(3). Adjoin 40 columns W(4), . , W(43). The round key for round i consists of i columns. If i is a multiple of 4:
W(i) = W(i − 4) ⊕ T(W(i − 1)) (10.3)
where T is a transformation of a, b, c, d in column W(i − 1) using the following procedure:
• Shift cyclically to get b, c, d, a.
• Replace each byte with S-box entry using ByteSub, to get e, f, g, h.
• Compute round constant r(i) = 00000010(i − 4)/4 in GF(28).
• T(W(i − 1)) = (e ⊕ r(i), f , g, h)
• If i is not a multiple of 4, W(i) = W(i − 4) ⊕ W(i − 1)
We have two options for implementing block cipher operations in VHDL. We can use the structural approach (shown in the DES example previously in this chapter), or sometimes it makes sense to define a library of functions and use those to make much simpler models.
In the example of AES, we can define a top level entity and architecture that has the bare minimum of structure and is completely defined using functions. This can be especially useful when working with behavioral synthesis software as this allows complete flexibility for architectural optimization.
1 library ieee;
2 use ieee.std_logic_1164.all; 3 entity AES is
4 port( 5 plaintext : in std_logic_vector(127 downto 0);
6 keytext : in std_logic_vector(127 downto 0);
7 encrypt : in std_logic;
8 go : in std_logic;
9 ciphertext : out std_logic_vector(127 downto 0);
10 done : out std_logic := ’0’
11 );
12 end;
13
14 use work.aes_functions.all;
15 architecture behavior of AES is
16 begin
17 process
18 begin
19 wait until go = ’1’;
20 done <= ’0’;
21 ciphertext <= aes_core(plaintext, keytext, encrypt);
22 done <= ’1’;
23 end process;
24 end;
In this example, we have the plaintext and keytext inputs defined as 128-bit-wide vectors and the ciphertext output is also defined as 128 bits wide. The go flag initiates the encryption and the done flag shows when this has been completed.
Notice that we have a work library defined called aes_functions which encapsulates all the relevant functions for the AES algorithm. The set of functions is defined in a package (aes_functions) and the VHDL is given:
1 library ieee;
2 use ieee.std_logic_1164.all; 3 use ieee.numeric_std.all; 4 package aes_functions is
56 constant nr : integer := 10;
7 constant nb : integer := 4;
8 constant nk : integer := 4;
9
10 subtype vec1408 is std_logic_vector(1407 downto 0);
11 subtype vec128 is std_logic_vector(127 downto 0);
12 subtype vec64 is std_logic_vector(63 downto 0);
13 subtype vec32 is std_logic_vector(31 downto 0);
14 subtype vec16 is std_logic_vector(15 downto 0);
15 subtype vec8 is std_logic_vector(7 downto 0);
16
17 subtype int9 is integer range 0 to 9;
18
19 function input_output (input : vec128) return vec128;
20 function sbox (pt : vec8) return vec8;
21 function subbytes (plaintext : vec128) return vec128;
22 function shiftrows (plaintext : vec128) return vec128;
23 function ffmul(pt : vec8; mul : vec8) return vec8;
24 function mixcl( l0 : vec8; l1 : vec8; l2 : vec8; l3 : vec8) return vec8;
25 function mixcolumns(pt : vec128) return vec128;
26 function rcon (input : int9) return vec8;
27 function aes_keyexpansion(key : vec128) return vec1408;
28 function aes_core (signal plaintext : vec128; signal keytext : vec128;
signal encrypt : std_logic) return vec128;
29
30
31
32 end;
33
34 library ieee;
35 use ieee.std_logic_1164.all;
36 use ieee.numeric_std.all;
37 package body aes_functions is
38
39 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
40 function subbytes (plaintext : vec128)
41 −− moods inline
42 return vec128 is
43 variable ciphertext : vec128;
44 begin
45 ciphertext := sbox(plaintext(127 downto 120)) &
46 sbox(plaintext(119 downto 112)) &
47 sbox(plaintext(111 downto 104)) &
48 sbox(plaintext(103 downto 96)) &
49 sbox(plaintext(95 downto 88)) &
50 sbox(plaintext(87 downto 80)) &
51 sbox(plaintext(79 downto 72)) &
52 sbox(plaintext(71 downto 64)) &
53 sbox(plaintext(63 downto 56)) &
54 sbox(plaintext(55 downto 48)) &
55 sbox(plaintext(47 downto 40)) &
56 sbox(plaintext(39 downto 32)) &
57 sbox(plaintext(31 downto 24)) &
58 sbox(plaintext(23 downto 16)) &
59 sbox(plaintext(15 downto 8)) &
60 sbox(plaintext(7 downto 0));
61 return ciphertext;
62 end;
63
64 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
65 function shiftrows (plaintext : vec128)
66 −− moods inline
67 return vec128 is
68 variable ciphertext : vec128;
69 begin
70 −−line 0 (the first): no shift
71 ciphertext := plaintext(31 downto 24) &
72 plaintext(55 downto 48) &
73 plaintext(79 downto 72) &
74 plaintext(103 downto 96) &
75 plaintext(127 downto 120) &
76 plaintext(23 downto 16) &
77 plaintext(47 downto 40) &
78 plaintext(71 downto 64) &
79 plaintext(95 downto 88) &
80 plaintext(119 downto 112) &
81 plaintext(15 downto 8) &
82 plaintext(39 downto 32) &
83 plaintext(63 downto 56) &
84 plaintext(87 downto 80) &
85 plaintext(111 downto 104) &
86 plaintext(7 downto 0);
87 return ciphertext;
88 end;
89
90 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
91
92 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
93 function tablelog (input : vec8)
94 −− moods inline
95 return vec8 is
96 variable output : vec8;
97 type table256 is array(0 to 255) of vec8;
98 constant pt_256 : table256 := (
99 −− moods rom
100 x"00", x"00", x"19", x"01", x"32",
101 x"02", x"1a", x"c6", x"4b",
102 x"c7", x"1b", x"68", x"33",
103 x"ee", x"df", x"03", x"64",
104
105 x"04", x"e0", x"0e", x"34",
106 x"8d", x"81", x"ef", x"4c",
107 x"71", x"08", x"c8", x"f8",
108 x"69", x"1c", x"c1", x"7d",
109
110 x"c2", x"1d", x"b5", x"f9",
111 x"b9", x"27", x"6a", x"4d",
112 x"e4", x"a6", x"72", x"9a",
113 x"c9", x"09", x"78", x"65",
114
115 x"2f", x"8a", x"05", x"21",
116 x"0f", x"e1", x"24", x"12",
117 x"f0", x"82", x"45", x"35",
118 x"93", x"da", x"8e", x"96",
119
120 x"8f", x"db", x"bd", x"36",
121 x"d0", x"ce", x"94", x"13",
122 x"5c", x"d2", x"f1", x"40",
123 x"46", x"83", x"38", x"66",
124 x"dd", x"fd", x"30", x"bf",
125 x"06", x"8b", x"62", x"b3",
126 x"25", x"e2", x"98", x"22",
127 x"88", x"91", x"10", x"7e",
128
129 x"6e", x"48", x"c3", x"a3",
130 x"b6", x"1e", x"42", x"3a",
131 x"6b", x"28", x"54", x"fa",
132 x"85", x"3d", x"ba", x"2b",
133
134 x"79", x"0a", x"15", x"9b",
135 x"9f", x"5e", x"ca", x"4e",
136 x"d4", x"ac", x"e5", x"f3",
137 x"73", x"a7", x"57", x"af",
138
139 x"58", x"a8", x"50", x"f4",
140 x"ea", x"d6", x"74", x"4f",
141 x"ae", x"e9", x"d5", x"e7",
142 x"e6", x"ad", x"e8", x"2c",
143
144 x"d7", x"75", x"7a", x"eb",
145 x"16", x"0b", x"f5", x"59",
146 x"cb", x"5f", x"b0", x"9c",
147 x"a9", x"51", x"a0", x"7f",
148
149 x"0c", x"f6", x"6f", x"17",
150 x"c4", x"49", x"ec", x"d8",
151 x"43", x"1f", x"2d", x"a4",
152 x"76", x"7b", x"b7", x"cc",
153
154 x"bb", x"3e", x"5a", x"fb",
155 x"60", x"b1", x"86", x"3b",
156 x"52", x"a1", x"6c", x"aa",
157 x"55", x"29", x"9d", x"97",
158
159 x"b2", x"87", x"90", x"61",
160 x"be", x"dc", x"fc", x"bc",
161 x"95", x"cf", x"cd", x"37",
162 x"3f", x"5b", x"d1", x"53",
163
164 x"39", x"84", x"3c", x"41",
165 x"a2", x"6d", x"47", x"14",
166 x"2a", x"9e", x"5d", x"56",
167 x"f2", x"d3", x"ab", x"44",
168
169 x"11", x"92", x"d9", x"23",
170 x"20", x"2e", x"89", x"b4",
171 x"7c", x"b8", x"26", x"77",
172 x"99", x"e3", x"a5", x"67",
173
174 x"4a", x"ed", x"de", x"c5",
175 x"31", x"fe", x"18", x"0d",
176 x"63", x"8c", x"80", x"c0",
177 x"f7", x"70", x"07" );
178 begin
179 output := pt_256(to_integer(unsigned(input)));
180 return output;
181 end;
182
183 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
184 function tableexp (input : vec8)
185 −− moods inline
186 return vec8 is
187 variable output : vec8;
188 type table256 is array(0 to 255) of vec8;
189 constant pt_256 : table256 := (
190 −− moods rom
191 x"01", x"03", x"05", x"0f",
192 x"11", x"33", x"55", x"ff",
193 x"1a", x"2e", x"72", x"96",
194 x"a1", x"f8", x"13", x"35",
195
196 x"5f", x"e1", x"38", x"48",
197 x"d8", x"73", x"95", x"a4",
198 x"f7", x"02", x"06", x"0a",
199 x"1e", x"22", x"66", x"aa",
200
201 x"e5", x"34", x"5c", x"e4",
202 x"37", x"59", x"eb", x"26",
203 x"6a", x"be", x"d9", x"70",
204 x"90", x"ab", x"e6", x"31",
205
206 x"53", x"f5", x"04", x"0c",
207 x"14", x"3c", x"44", x"cc",
208 x"4f", x"d1", x"68", x"b8",
209 x"d3", x"6e", x"b2", x"cd",
210
211 x"4c", x"d4", x"67", x"a9",
212 x"e0", x"3b", x"4d", x"d7",
213 x"62", x"a6", x"f1", x"08",
214 x"18", x"28", x"78", x"88",
215
216 x"83", x"9e", x"b9", x"d0",
217 x"6b", x"bd", x"dc", x"7f",
218 x"81", x"98", x"b3", x"ce",
219 x"49", x"db", x"76", x"9a",
220
221 x"b5", x"c4", x"57", x"f9",
222 x"10", x"30", x"50", x"f0",
223 x"0b", x"1d", x"27", x"69",
224 x"bb", x"d6", x"61", x"a3",
225
226 x"fe", x"19", x"2b", x"7d",
227 x"87", x"92", x"ad", x"ec",
228 x"2f", x"71", x"93", x"ae",
229 x"e9", x"20", x"60", x"a0",
230
231 x"fb", x"16", x"3a", x"4e",
232 x"d2", x"6d", x"b7", x"c2",
233 x"5d", x"e7", x"32", x"56",
234 x"fa", x"15", x"3f", x"41",
235
236 x"c3", x"5e", x"e2", x"3d",
237 x"47", x"c9", x"40", x"c0",
238 x"5b", x"ed", x"2c", x"74",
239 x"9c", x"bf", x"da", x"75",
Secure Systems 159
240
241 x"9f", x"ba", x"d5", x"64",
242 x"ac", x"ef", x"2a", x"7e",
243 x"82", x"9d", x"bc", x"df",
244 x"7a", x"8e", x"89", x"80",
245
246 x"9b", x"b6", x"c1", x"58",
247 x"e8", x"23", x"65", x"af",
248 x"ea", x"25", x"6f", x"b1",
249 x"c8", x"43", x"c5", x"54",
250
251 x"fc", x"1f", x"21", x"63",
252 x"a5", x"f4", x"07", x"09",
253 x"1b", x"2d", x"77", x"99",
254 x"b0", x"cb", x"46", x"ca",
255
256 x"45", x"cf", x"4a", x"de",
257 x"79", x"8b", x"86", x"91",
258 x"a8", x"e3", x"3e", x"42",
259 x"c6", x"51", x"f3", x"0e",
260
261 x"12", x"36", x"5a", x"ee",
262 x"29", x"7b", x"8d", x"8c",
263 x"8f", x"8a", x"85", x"94",
264 x"a7", x"f2", x"0d", x"17",
265
266 x"39", x"4b", x"dd", x"7c",
267 x"84", x"97", x"a2", x"fd",
268 x"1c", x"24", x"6c", x"b4",
269 x"c7", x"52", x"f6", x"01");
270 begin
271 output := pt_256(to_integer(unsigned(input)));
272 return output;
273 end;
274
275 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
276 function ffmul(pt : vec8; mul : vec8)
277 −− moods inline
278 return vec8 is
279 −−variable res : vec8;
280 variable tablogpt : vec8;
281 variable tablogmul : vec8;
282 variable tablogpt8 : unsigned(8 downto 0);
283 variable tablogmul8 : unsigned(8 downto 0);
284 variable carrie : std_logic_vector(8 downto 0);
285 variable power : vec8;
286 variable result: vec8;
287 begin
288 tablogpt := tablelog(pt);
289 tablogmul := tablelog(mul);
290
291 tablogpt8 := unsigned("0" & tablogpt);
292 tablogmul8 := unsigned("0" & tablogmul);
293
294 carrie := std_logic_vector(tablogmul8 + tablogpt8);
160 Chapter 10
295
296 if pt = x"00" or mul = x"00" then
297 result := x"00";
298 elsif carrie(8) = ’1’ or carrie(7 downto 0) = x"ff" then −− mod 255
299 power := std_logic_vector(unsigned(carrie(7 downto 0)) + 1); −− power =
power − 255
300 result := tableexp(power);
301 else
302 power := carrie(7 downto 0);
303 result := tableexp(power);
304 end if;
305 return result;
306 end;
307
308 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
309 function mixcl( l0 : vec8; l1 : vec8; l2 : vec8; l3 : vec8)
310 −− moods inline
311 return vec8 is
312 variable ct : vec8;
313 begin
314
315 ct := ffmul(l0, x"02") xor ffmul(l1, x"01") xor ffmul(l2, x"01") xor ffmul
(l3, x"03");
316
317 return ct;
318 end;
319
320 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
321 function mixcolumns(pt : vec128)
322 −− moods inline
323 return vec128 is
324 variable ct : vec128;
325 begin
326
327 ct := mixcl(pt(127 downto 120), pt(119 downto 112), pt(111 downto 104), pt
(103 downto 96)) &
328 mixcl(pt(119 downto 112), pt(111 downto 104), pt(103 downto 96), pt
(127 downto 120)) &
329 mixcl(pt(111 downto 104), pt(103 downto 96), pt(127 downto 120), pt
(119 downto 112)) &
330 mixcl(pt(103 downto 96), pt(127 downto 120), pt(119 downto 112), pt
(111 downto 104)) &
331
332 mixcl(pt(95 downto 88), pt(87 downto 80), pt(79 downto 72), pt(71
downto 64)) &
333 mixcl(pt(87 downto 80), pt(79 downto 72), pt(71 downto 64), pt(95
downto 88)) &
334 mixcl(pt(79 downto 72), pt(71 downto 64), pt(95 downto 88), pt(87
downto 80)) &
335 mixcl(pt(71 downto 64), pt(95 downto 88), pt(87 downto 80), pt(79
downto 72)) &
336
337 mixcl(pt(63 downto 56), pt(55 downto 48), pt(47 downto 40), pt(39
downto 32)) &
338 mixcl(pt(55 downto 48), pt(47 downto 40), pt(39 downto 32), pt(63
downto 56)) &
339 mixcl(pt(47 downto 40), pt(39 downto 32), pt(63 downto 56), pt(55
downto 48)) &
340 mixcl(pt(39 downto 32), pt(63 downto 56), pt(55 downto 48), pt(47
downto 40)) &
341
342 mixcl(pt(31 downto 24), pt(23 downto 16), pt(15 downto 8), pt(7 downto
0)) &
343 mixcl(pt(23 downto 16), pt(15 downto 8), pt(7 downto 0), pt(31 downto
24)) &
344 mixcl(pt(15 downto 8), pt(7 downto 0), pt(31 downto 24), pt(23 downto
16)) &
345 mixcl(pt(7 downto 0), pt(31 downto 24), pt(23 downto 16), pt(15 downto
8));
346
347 return ct;
348 end;
349
350 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
351 function input_output (input : vec128)
352 −− moods inline
353 return vec128 is
354 variable output : vec128;
355 function flip(input:vec32) return vec32 is
356 −− moods inline
357 begin
358 return input(7 downto 0) & input(15 downto 8)
359 & input(23 downto 16) & input(31 downto 24);
360 end;
361 begin
362 return flip(input(127 downto 96)) & flip(input(95 downto 64))
363 & flip(input(63 downto 32)) & flip(input(31 downto 0));
364 end;
365
366 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
367 function aes_keyexpansion(key : vec128)
368 −− moods inline
369 return vec1408 is
370 variable iok : vec128;
371 variable er0,er1,er2,er3,er4,er5,er6,er7,er8,er9:vec128;
372 −−variable zero: vec128;
373 −−variable expandedkeys: vec1408;
374
375 function exp_round(input : vec128; round: int9) return vec128 is
376 −− moods inline
377 variable r1,r2,r3,r4,r5: vec32;
378 begin
379 r1 := sbox(input(7 downto 0)) &
380 sbox(input(31 downto 24)) &
381 sbox(input(23 downto 16)) &
382 (sbox(input(15 downto 8)) xor rcon(round));
383
384 r2 := input(127 downto 96) xor r1;
385 r3 := input(95 downto 64) xor r2;
pter 10
386 r4 := input(63 downto 32) xor r3;
387 r5 := input(31 downto 0) xor r4;
388 return r2 & r3 & r4 & r5;
389 end;
390
391 begin
392 −− first round
393 iok := input_output(key);
394 −− other rounds
395 er9 := exp_round(iok,9);
396 er8 := exp_round(er9,8);
397 er7 := exp_round(er8,7);
398 er6 := exp_round(er7,6);
399 er5 := exp_round(er6,5);
400 er4 := exp_round(er5,4);
401 er3 := exp_round(er4,3);
402 er2 := exp_round(er3,2);
403 er1 := exp_round(er2,1);
404 er0 := exp_round(er1,0);
405
406 return (iok & er9 & er8 & er7 & er6 & er5 & er4 & er3 & er2 & er1 & er0);
407 end;
408
409 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
410
411 function aes_core (signal plaintext : vec128; signal keytext : vec128;
signal encrypt : std_logic)
412 −− moods inline
413 return vec128 is
414 variable rk0 : vec128;
415 variable ciphertext, expkey : vec128;
416 variable ct1, ct2,ct3,ct4,ct5,ct6,ct7,ct8: vec128;
417 variable expandedkeys : vec1408;
418 begin
419 −− expanded key schedule
420 expandedkeys := aes_keyexpansion(keytext);
421
422 −− round 0
423 ct1 := input_output(plaintext) xor expandedkeys(1407 downto 1280);
424
425 −− round 1 to nr−1
426 −−for i in 1 to nr−1 loop
427 for i in 1 to 9 loop
428 ct2 := subbytes(ct1);
429 ct3 := shiftrows(ct2);
430 ct4 := mixcolumns(ct3);
431 case(i) is
432 when 1 => expkey := expandedkeys(1279 downto 1152);
433 when 2 => expkey := expandedkeys(1151 downto 1024);
434 when 3 => expkey := expandedkeys(1023 downto 896);
435 when 4 => expkey := expandedkeys(895 downto 768);
436 when 5 => expkey := expandedkeys(767 downto 640);
437 when 6 => expkey := expandedkeys(639 downto 512);
438 when 7 => expkey := expandedkeys(511 downto 384);
439 when 8 => expkey := expandedkeys(383 downto 256);
63
440 when 9 => expkey := expandedkeys(255 downto 128);
441 when others => null;
442 end case;
443 ct1 := ct4 xor expkey;
444 end loop;
445
446 −− final round nr=10
447 ct5 := subbytes(ct1);
448 ct6 := shiftrows(ct5);
449 ct7 := ct6 xor expandedkeys(1407−128∗nr downto 1280−128∗nr);
450
451 ciphertext := input_output(ct7);
452
453 return ciphertext;
454 end;
455
456
457
458 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
459 function rcon (input : int9)
460 −− moods inline
461 return vec8 is
462 type rcont_t is array(0 to 9) of vec8;
463 constant table_rcon: rcont_t := (
464 −− moods rom
465 x"36", x"1b", x"80", x"40", x"20", x"10", x"08", x"04", x"02", x"01");
466 begin
467 return table_rcon(input);
468 end;
469
470 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
471 function sbox (pt : vec8)
472 −− moods inline
473 return vec8 is
474 variable ct : vec8;
475 type table256 is array(0 to 255) of vec8;
476 constant pt_256 : table256 := (
477 −− moods rom
478 x"63", x"7c", x"77", x"7b", x"f2", x"6b", x"6f", x"c5",
479 x"30", x"01", x"67", x"2b", x"fe", x"d7", x"ab", x"76",
480 x"ca", x"82", x"c9", x"7d", x"fa", x"59", x"47", x"f0",
481 x"ad", x"d4", x"a2", x"af", x"9c", x"a4", x"72", x"c0",
482 x"b7", x"fd", x"93", x"26", x"36", x"3f", x"f7", x"cc",
483 x"34", x"a5", x"e5", x"f1", x"71", x"d8", x"31", x"15",
484 x"04", x"c7", x"23", x"c3", x"18", x"96", x"05", x"9a",
485 x"07", x"12", x"80", x"e2", x"eb", x"27", x"b2", x"75",
486 x"09", x"83", x"2c", x"1a", x"1b", x"6e", x"5a", x"a0",
487 x"52", x"3b", x"d6", x"b3", x"29", x"e3", x"2f", x"84",
488 x"53", x"d1", x"00", x"ed", x"20", x"fc", x"b1", x"5b",
489 x"6a", x"cb", x"be", x"39", x"4a", x"4c", x"58", x"cf",
490 x"d0", x"ef", x"aa", x"fb", x"43", x"4d", x"33", x"85",
491 x"45", x"f9", x"02", x"7f", x"50", x"3c", x"9f", x"a8",
492 x"51", x"a3", x"40", x"8f", x"92", x"9d", x"38", x"f5",
493 x"bc", x"b6", x"da", x"21", x"10", x"ff", x"f3", x"d2",
494 x"cd", x"0c", x"13", x"ec", x"5f", x"97", x"44", x"17",
495 x"c4", x"a7", x"7e", x"3d", x"64", x"5d", x"19", x"73",
496 x"60", x"81", x"4f", x"dc", x"22", x"2a", x"90", x"88",
497 x"46", x"ee", x"b8", x"14", x"de", x"5e", x"0b", x"db",
498 x"e0", x"32", x"3a", x"0a", x"49", x"06", x"24", x"5c",
499 x"c2", x"d3", x"ac", x"62", x"91", x"95", x"e4", x"79",
500 x"e7", x"c8", x"37", x"6d", x"8d", x"d5", x"4e", x"a9",
501 x"6c", x"56", x"f4", x"ea", x"65", x"7a", x"ae", x"08",
502 x"ba", x"78", x"25", x"2e", x"1c", x"a6", x"b4", x"c6",
503 x"e8", x"dd", x"74", x"1f", x"4b", x"bd", x"8b", x"8a",
504 x"70", x"3e", x"b5", x"66", x"48", x"03", x"f6", x"0e",
505 x"61", x"35", x"57", x"b9", x"86", x"c1", x"1d", x"9e",
506 x"e1", x"f8", x"98", x"11", x"69", x"d9", x"8e", x"94",
507 x"9b", x"1e", x"87", x"e9", x"ce", x"55", x"28", x"df",
508 x"8c", x"a1", x"89", x"0d", x"bf", x"e6", x"42", x"68",
509 x"41", x"99", x"2d", x"0f", x"b0", x"54", x"bb", x"16");
510 begin
511 ct := pt_256(to_integer(unsigned(pt)));
512 return ct;
513 end;
514
515 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
516 end;
After the functions and top level entity have been defined, we can implement a test bench that applies a set of test data to the inputs and verifies that the correct output has been obtained. Notice that we use the assertion technique to identify correct operation.
1 library ieee;
2 use ieee.std_logic_1164.all; 3 entity testAES is
4 end; 567 library ieee;
8 use ieee.std_logic_1164.all; 9 use work.aes_functions.all;
10 architecture behavior of testAES is
11
12 component aes
13 port(
14 plaintext : in std_logic_vector(127 downto 0);
15 keytext : in std_logic_vector(127 downto 0);
16 encrypt : in std_logic;
17 go : in std_logic;
18 ciphertext : out std_logic_vector(127 downto 0);
19 done : out std_logic
20 );
21 end component;
22
23 for all : aes use entity work.aes;
24
25 signal plaintext : std_logic_vector(127 downto 0);
26 signal keytext : std_logic_vector(127 downto 0);
27 signal encrypt : std_logic;
28 signal go : std_logic := ’0’;
29 signal ciphertext : std_logic_vector(127 downto 0);
30 signal done : std_logic;
31 signal ok : std_logic := ’0’;
32 begin
33 plaintext <= X”00000000000000000000000000000000”, X”3243
f6a8885a308d313198a2e0370734” after 50 ns ;
34 keytext <= X”00000000000000000000000000000000”, X”2
b7e151628aed2a6abf7158809cf4f3c” after 100 ns;
35 process (ciphertext)
36 variable ct : std_logic_vector(127 downto 0) := X”3925841
d02dc09fbdc118597196a0b32”;
37 begin
38 assert ct = ciphertext
39 report ”Test vectors do not match”
40 severity note;
41 assert not (ct = ciphertext)
42 report ”Test vectors Matched”
43 severity note;
44 end process;
45
46
47 process
48 begin
49 go <= not go after 20 ns;
50 end process;
51
52 DUT : aes port map (plaintext, keytext, encrypt, go, ciphertext, done);
53 end;
Manufacturer:Xilinx
Product Categories: FPGAs (Field Programmable Gate Array)
Lifecycle:Active Active
RoHS:
Manufacturer:Xilinx
Product Categories: FPGAs (Field Programmable Gate Array)
Lifecycle:Active Active
RoHS:
Manufacturer:Xilinx
Product Categories: FPGAs (Field Programmable Gate Array)
Lifecycle:Obsolete -
RoHS:
Manufacturer:Xilinx
Product Categories: FPGAs (Field Programmable Gate Array)
Lifecycle:Obsolete -
RoHS:
Manufacturer:Xilinx
Product Categories: FPGAs
Lifecycle:Active Active
RoHS: No RoHS
Support