Introduction
AES (Advanced Encryption Standard)
In this work, AES is a variant of Rijndael, with a fixed block size of 128 bits, and a key size of 128 bits.
The 16-byte data b0,b1,…,b15 will be represented as
$$\begin{bmatrix}
b_0 & b_4 & b_8& b_{12} \\
b_1 & b_5 & b_9& b_{13} \\
b_2 & b_6 & b_{10}& b_{14} \\
b_3 & b_7 & b_{11}& b_{15} \\
\end{bmatrix} $$
Before starting to encrypt the message we need some initialization steps; key expansion and initial round.
The size of the key dictates how many rounds that we have to perform to get encrypted message. In this work key is 128 bits and we need 10 cycles. In each round a modified version of the original key will be used and that will be created by performing “AES Key Expansion” operation.
Stages: (will be performed for the first 16 byte of message, then next 16 byte will be taken, and continue on this way up to end of the message)
- Key expansion
- Initial Round
- AddRoundKey
- Rounds (repeat 9 times)
- SubBytes
- ShiftRows
- MixColumns
- AddRoundKey
- Final Round
- SubBytes
- ShiftRows
- AddRoundKey
Lets Assume the message is “AES Advanced Encryption Standard!”.
First 16 bytes (or characters) “AES Advanced Enc” will be taken (their ASCII values) for encryption and place in 4×4 matrix. It will be called as state.
$$\begin{bmatrix}
A & A & n & \\
E & d & c & E \\
S & v & e & n \\
& a & d & c \\
\end{bmatrix} = \begin{bmatrix}
41 & 41 & 6E & 20 \\
45 & 64 & 63 & 45 \\
53 & 76 & 65 & 6E \\
20 & 61 & 64 & 63 \\
\end{bmatrix} $$
and lets assume Cipher Key is
$$\begin{bmatrix}
2B & 28 & AB & 09 \\
7E & AE & F7 & CF \\
15 & D2 & 15 & 4F \\
16 & A6 & 88 & 3C \\
\end{bmatrix}$$
AddRoundKey Step
In this step each byte of the state will be XORed with the KEY.
For initial Round (Round 0)
$$\begin{bmatrix}
41 & 41 & 6E & 20 \\
45 & 64 & 63 & 45 \\
53 & 76 & 65 & 6E \\
20 & 61 & 64 & 63 \\
\end{bmatrix} XOR \begin{bmatrix}
2B & 28 & AB & 09 \\
7E & AE & F7 & CF \\
15 & D2 & 15 & 4F \\
16 & A6 & 88 & 3C \\
\end{bmatrix} =\begin{bmatrix}
6A & 69 & C5 & 29 \\
3B & CA & 94 & 8A \\
46 & A4 & 70 & 21 \\
36 & C7 & EC & 5F \\
\end{bmatrix} $$
After Round 0, the output of key expansion step will be used as round key.
SubBytes Step
Replace each byte of the state (16 byte chunk) with another byte by using Rijndael S-Box (Substitution Box). (details)
$$\begin{bmatrix}
6A & 69 & C5 & 29 \\
3B & CA & 94 & 8A \\
46 & A4 & 70 & 21 \\
36 & C7 & EC & 5F \\
\end{bmatrix} Replace with S-BOX \begin{bmatrix}
02 & F9 & A6 & A5 \\
E2 & 74 & 22 & 7E \\
5A & 49 & 51 & FD \\
05 & C6 & CE & CF \\
\end{bmatrix} $$
ShiftRows Step
The output of SubBytes step will be taken and the rows of the matrix will be rotated.
First row remains same,
Second row will be rotated left once,
Third row will be rotated left twice,
Fourth row will be rotated left 3 times.
$$ShiftRows\left(\begin{bmatrix}
02 & F9 & A6 & A5 \\
E2 & 74 & 22 & 7E \\
5A & 49 & 51 & FD \\
05 & C6 & CE & CF\\
\end{bmatrix} \right)= \begin{bmatrix}
02 & F9 & A6 & A5 \\
74 & 22 & 7E & E2 \\
51 & FD & 5A & 49 \\
CF & 05 & C6 & CE\\
\end{bmatrix}$$
MixColumns Step
The state will be modulo multiplied with Rijndael’s Galois Field Matrix.
The Galois Field Matrix is
$$\begin{bmatrix}
02 & 03 & 01 & 01 \\
01 & 02 & 03 & 01 \\
01 & 01 & 02 & 03 \\
03 & 01 & 01 & 02\\
\end{bmatrix}$$
The multiplication
$$\begin{bmatrix}
02 & 03 & 01 & 01 \\
01 & 02 & 03 & 01 \\
01 & 01 & 02 & 03 \\
03 & 01 & 01 & 02\\
\end{bmatrix}*\begin{bmatrix}
02 & F9 & A6 & A5 \\
74 & 22 & 7E & E2 \\
51 & FD & 5A & 49 \\
CF & 05 & C6 & CE\\
\end{bmatrix}=\begin{bmatrix}
06 & 77 & 49 & EB \\
D6 & A4 & 72 & 6F \\
9E & 35 & 3D & 9C \\
A6 & C5 & 42 & D8\\
\end{bmatrix}$$
b0 of the result matrix will be calculated as (02*02)⊕(03*74)⊕(01*51)⊕(01*CF)
For the multiplication;
If the Galois field value is 1: no need to calculate, ie, 51 and CF
If the Galois field value is 2: shift the value left once and if the leftmost bit of the value before shifting is 1 then xor the result of shift operation with 0x1B, otherwise leave it;
for (02*02): 00000010 will be shifted left once, the leftmost bit is not 1 so, the result is 00000100=4.
If the Galois field value is 3: perform GF(2) then xor it with the value,
for (03*74): 01110100 will be shifted left once, the leftmost bit is not 1 so, 11101000⊕01110100=9C.
and last: 04⊕9C⊕51⊕CF=06
At this point AddRoundKey step will be performed again with the key that is produced from the original key.
The steps SubBytes, ShiftRows, MixColumns and AddRoundKey steps will be repeated 9 times.
At the final round, SubBytes, ShiftRows and AddRoundKey steps will be performed. (no MixColumns step)
KEY EXPANSION
It is expansion of Chipher key. 11 keys will be used. The initial key in initial round, 10 keys, produced from initial key, will be used for 9 main rounds and the final round.
The initial chipher key
$$\begin{bmatrix}
2B & 28 & AB & 09 \\
7E & AE & F7 & CF \\
15 & D2 & 15 & 4F \\
16 & A6 & 88 & 3C \\
\end{bmatrix}$$
To produce a round key;
Last column will be taken from previous round key.
The column will be rotated up once.
Perform SubBytes operation.
$$\begin{bmatrix}
09 \\
CF\\
4F\\
3C\\
\end{bmatrix} rotate-up\begin{bmatrix}
CF\\
4F\\
3C\\
09\\
\end{bmatrix}Subbytes\begin{bmatrix}
8A\\
84\\
EB\\
01\\
\end{bmatrix}
$$
The next step is to use Rcon table. For the first round key, the first column of Rcon table will be used, for second round key the second column of Rcon tablewill be used and goes on in this way.
The Rcon table table is
$$\begin{bmatrix}
01 & 02 & 04 & 08 & 10 & 20 & 40 & 80 & 1B & 36\\
00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00\\
00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00\\
00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00\\
\end{bmatrix}$$
For each first column of round key, the first column of the previous round key, the column that we have calculated and associated Rcon column will be XORed.
$$\begin{bmatrix}
2B \\
7E\\
15\\
16\\
\end{bmatrix} ⊕\begin{bmatrix}
8A\\
84\\
EB\\
01\\
\end{bmatrix}⊕\begin{bmatrix}
01\\
00\\
00\\
00\\
\end{bmatrix}=\begin{bmatrix}
A0\\
FA\\
FE\\
17\\
\end{bmatrix}
$$
For the second column of the current round key, the second column of previous round key and the first column of the current round key will be XORed.
$$\begin{bmatrix}
28\\
AE\\
D2\\
A6\\
\end{bmatrix}⊕\begin{bmatrix}
A0\\
FA\\
FE\\
17\\
\end{bmatrix}=\begin{bmatrix}
88\\
54\\
2C\\
B1\\
\end{bmatrix}
$$
For the third column of current round key, the third column of previous round key and second column of current round key will be XORed.
$$\begin{bmatrix}
AB\\
F7\\
15\\
88\\
\end{bmatrix}⊕\begin{bmatrix}
88\\
54\\
2C\\
B1\\
\end{bmatrix}=\begin{bmatrix}
23\\
A3\\
39\\
39\\
\end{bmatrix}
$$
For the fourth column of current round key, the fourth column of previous round key and third column of current round key will be XORed.
$$\begin{bmatrix}
09\\
CF\\
4F\\
3C\\
\end{bmatrix}⊕\begin{bmatrix}
23\\
A3\\
39\\
39\\
\end{bmatrix}=\begin{bmatrix}
2A\\
6C\\
76\\
05\\
\end{bmatrix}
$$
The round key will be
$$\begin{bmatrix}
A0 & 88 & 23 & 2A \\
FA & 54 & A3 & 6C \\
FE & 2C & 39 & 76 \\
17 & B1 & 39 & 05 \\
\end{bmatrix}$$
For the keys of next rounds, same operations will be repeated with associated Rcon column. (10 Times)
Original source code can be found at https://github.com/secworks/aes
Main AES Module
//====================================================================== // // aes.v // -------- // Top level wrapper for the AES block cipher core. // // // Author: Joachim Strombergson // Copyright (c) 2013, 2014 Secworks Sweden AB // All rights reserved. `default_nettype none module aes( // Clock and reset. input wire clk, input wire reset_n, // Control. input wire cs, //comes from cpu --chip select input wire we, //comes from cpu --write enable // Data ports. input wire [7 : 0] address, //8 bit controls local params defined // ADDCTRL input wire [31 : 0] write_data, //test kodundan geliyor, ana test modülünde tb_write_data ile connected // hem data hem de control sinyalleri bunun üzerinde geliyor, address kontrol // edilip karar veriliyor output wire [31 : 0] read_data ); //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- //sisteme geri gönderilecek mesajın adres aralığı, by using read_data //questioning by outside agent localparam ADDR_NAME0 = 8'h00; localparam ADDR_NAME1 = 8'h01; localparam ADDR_VERSION = 8'h02; //questioning by outside agent localparam ADDR_CTRL = 8'h08; localparam CTRL_INIT_BIT = 0; localparam CTRL_NEXT_BIT = 1; //questioning by outside agent localparam ADDR_STATUS = 8'h09; localparam STATUS_READY_BIT = 0; localparam STATUS_VALID_BIT = 1; localparam ADDR_CONFIG = 8'h0a; localparam CTRL_ENCDEC_BIT = 0; localparam CTRL_KEYLEN_BIT = 1; // key_reg 8*32 array key için localparam ADDR_KEY0 = 8'h10; localparam ADDR_KEY7 = 8'h17; //block_reg 4*32 array data için localparam ADDR_BLOCK0 = 8'h20; localparam ADDR_BLOCK3 = 8'h23; //dış agent sonucu almak için bu adres aralığını kullanıyor localparam ADDR_RESULT0 = 8'h30; localparam ADDR_RESULT3 = 8'h33; //these are written to output read_data (first written into temp_read_data) localparam CORE_NAME0 = 32'h61657320; // "aes " localparam CORE_NAME1 = 32'h20202020; // " " localparam CORE_VERSION = 32'h302e3630; // "0.60" //---------------------------------------------------------------- // Registers including update variables and write enable. //---------------------------------------------------------------- reg init_reg; // initial state stored value (current state) reg init_new; // initial state new value (next state) reg next_reg; //current next reg next_new; // next "next" state reg encdec_reg; //encode or decode reg keylen_reg; // 128 or 256 bit encryption reg config_we; //???? reg [31 : 0] block_reg [0 : 3]; //4 * 32 bit data reg block_we; //block control reg [31 : 0] key_reg [0 : 7]; // 8 * 32 bit key value reg key_we; //key kontrol reg [127 : 0] result_reg; //128 bit result reg valid_reg; // reg ready_reg; //---------------------------------------------------------------- // Wires. //---------------------------------------------------------------- reg [31 : 0] tmp_read_data ; // data at every iteration ???? //all are aes_core connection wire core_encdec; wire core_init; //initial state value sent to aes_core wire core_next; //next state value sent to aes_core wire core_ready; // ready signal sent to aes_core wire [255 : 0] core_key; //256 bit key value wire core_keylen; // key is 128 or 256 bit wire [127 : 0] core_block; // 128 bit block sent to aes_core wire [127 : 0] core_result; //comes from aes_core as result wire core_valid; // core output is valid, read it from core_result //---------------------------------------------------------------- // Concurrent connectivity for ports etc. //---------------------------------------------------------------- assign read_data = tmp_read_data; //read_data dışarıya bilgi göndermek için kullanılıyor assign core_key = {key_reg[0], key_reg[1], key_reg[2], key_reg[3], // 8 32 bitlik key birleştirip 256 bitlik key oluşturuyor... key_reg[4], key_reg[5], key_reg[6], key_reg[7]}; //ama 128 bi key kullanılıyorsa sadece yarısını employ ediyor.. assign core_block = {block_reg[0], block_reg[1], block_reg[2], block_reg[3]}; //128 bitlik data oluşturuyor. assign core_init = init_reg; // init signal is assigned to core module assign core_next = next_reg; // next signal is assigned to core module assign core_encdec = encdec_reg; // enc or dec assign core_keylen = keylen_reg; // key length is assigned to core module //---------------------------------------------------------------- // core instantiation. //---------------------------------------------------------------- aes_core core( .clk(clk), .reset_n(reset_n), .encdec(core_encdec), .init(core_init), //goes to core. am I in an initial state? if so, go to initial state. write_data[0] ı gönderdi .next(core_next), //goes to core. should I pass to the next state? write_data[1] ı gönderdi .ready(core_ready), //comes from core. core is ready for the next step. .key(core_key), //key goes to core .keylen(core_keylen), //keylen goes to core .block(core_block), //goes to core .result(core_result), //comes from core. our main 128-bit result .result_valid(core_valid) //core output is valid??? ); //---------------------------------------------------------------- // reg_update // Update functionality for all registers in the core. // All registers are positive edge triggered with asynchronous // active low reset. //---------------------------------------------------------------- always @ (posedge clk or negedge reset_n) begin : reg_update integer i; if (!reset_n) // if reset begin // clear blocks and key for (i = 0 ; i < 4 ; i = i + 1) block_reg[i] <= 32'h0; for (i = 0 ; i < 8 ; i = i + 1) key_reg[i] <= 32'h0; init_reg <= 1'b0; // clear all control signals next_reg <= 1'b0; encdec_reg <= 1'b0; keylen_reg <= 1'b0; result_reg <= 128'h0; valid_reg <= 1'b0; ready_reg <= 1'b0; end else begin // if not reset, start ready_reg <= core_ready; // read ready signal from aes_core, aes core da enchiper bloktan geliyor enc_ready'ye bağlı valid_reg <= core_valid; //read valid signal from aes_core (defined as result_valid in aes_core) result_reg <= core_result; // read result(128bit) from aes_core init_reg <= init_new; // assign init_reg to init signal of aes_core next_reg <= next_new; // assign next_reg to next signal of aes_core if (config_we) // Gelen adres ADDR_CONFIG 0x0A ise configürasyon bilgileri alınıyor begin encdec_reg <= write_data[CTRL_ENCDEC_BIT];// write_data içinde encription veya decription yapacağı bilgisi geliyor keylen_reg <= write_data[CTRL_KEYLEN_BIT];// write_data içinde 128 veya 256 bit key kullanılacağı bilgisi geliyor end if (key_we) // eğer adres 0x10-0x17 arasındaysa key_reg[address[2 : 0]] <= write_data; //dışardan input edilen address in lsb 3 bitine bakıyor. // writedata da dışarıdan geliyor (input) // key 8 defa da geliyor (8*32) if (block_we) // eğer adres 0x20 - 0x23 arasındaysa block_reg[address[1 : 0]] <= write_data; end end // reg_update //---------------------------------------------------------------- // api // // The interface command decoding logic. //---------------------------------------------------------------- always @* begin : api init_new = 1'b0; next_new = 1'b0; config_we = 1'b0; key_we = 1'b0; block_we = 1'b0; tmp_read_data = 32'h0; if (cs) begin if (we) begin //we=1 if (address == ADDR_CTRL)//adres 0x08 gelirse aes_core parametreleri set ediliyor begin init_new = write_data[CTRL_INIT_BIT]; //write_datanın 0 ıncı biti init'e atanacak, init de core'a gönderiliyor next_new = write_data[CTRL_NEXT_BIT]; //write_datanın 1 ıncı biti next'e atanacak, next de core'a gönderiliyor end if (address == ADDR_CONFIG) //adres 0x0a gelirse, config_we 1 olacak, write_data'nın 0 ve 1inci biti encdec_reg ve // keylen_reg değerlerini belirlemek için kullanılacak config_we = 1'b1; if ((address >= ADDR_KEY0) && (address <= ADDR_KEY7)) //adres key ile ilgili aralıktaysa key_we 1 olacak key_we = 1'b1; if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK3)) // adress blok ile ilgili aralıktaysa block_we 1 olacak block_we = 1'b1; end // if (we) else // we=0 begin //questioning by outside agent case (address) //read_data ile dışarıya bilgi gönderiliyor (statü, control, data ) ADDR_NAME0: tmp_read_data = CORE_NAME0; //"aes" ADDR_NAME1: tmp_read_data = CORE_NAME1; // " " ADDR_VERSION: tmp_read_data = CORE_VERSION; //"0.60" ADDR_CTRL: tmp_read_data = {28'h0, keylen_reg, encdec_reg, next_reg, init_reg}; ADDR_STATUS: tmp_read_data = {30'h0, valid_reg, ready_reg}; default: begin end endcase // case (address) if ((address >= ADDR_RESULT0) && (address <= ADDR_RESULT3)) tmp_read_data = result_reg[(3 - (address - ADDR_RESULT0)) * 32 +: 32]; // indexed part-select. // 128 bitlik resultı gelen adrese göre // 32 bitlik 4 parçaya bölüp read_data //ile gönderiyor end end end // addr_decoder endmodule // aes //====================================================================== // EOF aes.v //======================================================================
AES Core Module
`default_nettype none module aes_core( // instantiated by aes.v input wire clk, //clock input wire reset_n, //reset input wire encdec, //encrpt or decryt input wire init, //initial state or not input wire next, //next state output wire ready, //ready signal input wire [255 : 0] key, //key input wire keylen, //128 or 256 bit key input wire [127 : 0] block, //data block to be encrpted output wire [127 : 0] result, // encryipted data to be printed output wire result_valid // to update the result ); //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- localparam CTRL_IDLE = 2'h0; //parameters for finite state machine Main FSM localparam CTRL_INIT = 2'h1; localparam CTRL_NEXT = 2'h2; //---------------------------------------------------------------- // Registers including update variables and write enable. //---------------------------------------------------------------- reg [1 : 0] aes_core_ctrl_reg; //stores state values reg [1 : 0] aes_core_ctrl_new; // reg aes_core_ctrl_we; reg result_valid_reg; reg result_valid_new; reg result_valid_we; reg ready_reg; reg ready_new; reg ready_we; //---------------------------------------------------------------- // Wires. //---------------------------------------------------------------- reg init_state; wire [127 : 0] round_key; wire key_ready; reg enc_next; wire [3 : 0] enc_round_nr; wire [127 : 0] enc_new_block; wire enc_ready; wire [31 : 0] enc_sboxw; reg dec_next; wire [3 : 0] dec_round_nr; wire [127 : 0] dec_new_block; wire dec_ready; reg [127 : 0] muxed_new_block; reg [3 : 0] muxed_round_nr; reg muxed_ready; wire [31 : 0] keymem_sboxw; /* verilator lint_off UNOPTFLAT */ reg [31 : 0] muxed_sboxw; wire [31 : 0] new_sboxw; /* verilator lint_on UNOPTFLAT */ //---------------------------------------------------------------- // Instantiations. //---------------------------------------------------------------- aes_encipher_block enc_block( .clk(clk),// input clock .reset_n(reset_n), // input reset .next(enc_next), // enchipher modüle gönderilen next sinyali .keylen(keylen), // key length 128 veya 256 bit işlem yapıldığını gösteriyor .round(enc_round_nr), // enchipher module kaçıncı raund'da olduğunun bilgisini gönderiyor, bu bilgi key_mem modüle iletilecek .round_key(round_key),//input 128 bit key for this round, keym_mem'den geliyor .sboxw(enc_sboxw), //output to sbox module to get new value .new_sboxw(new_sboxw), // input 32 bit new sbox value .block(block), // input 128 byte block data, şifrelenecek data .new_block(enc_new_block), //result of encription, .ready(enc_ready) //ready signal, ENCHIPHER Module sends it ); aes_decipher_block dec_block( // part for decryption .clk(clk), .reset_n(reset_n), .next(dec_next), .keylen(keylen), .round(dec_round_nr), .round_key(round_key), .block(block), .new_block(dec_new_block), .ready(dec_ready) ); aes_key_mem keymem( .clk(clk), // input clock .reset_n(reset_n), // input reset .key(key), // input 256 bit key, AES main'den gelen buraya gönderiliyor .keylen(keylen), //key length .init(init), //input initial state or not, Aes main'den geliyor buraya gönderiliyor .round_key(round_key), //input 128 bit key for this round, buradan gelen ENCHIPHER modüle gönderiliyor .ready(key_ready), //output ready signal for keymem, keymem sends it AES_CORE .sboxw(keymem_sboxw), //output to sbox module to get new value .new_sboxw(new_sboxw) //input 32 bit new value ); aes_sbox sbox_inst(.sboxw(muxed_sboxw), //input for sbox operations .new_sboxw(new_sboxw) // output ); //---------------------------------------------------------------- // Concurrent connectivity for ports etc. //---------------------------------------------------------------- assign ready = ready_reg; //Aes maine gönderilen işlem yapmaya hazır sinyali assign result = muxed_new_block; // AES_ENCIPHER modulden gelen şifrelenmiş veri AES Main'e muxed_new_block üzerinden gönderiliyor assign result_valid = result_valid_reg; //Aes main'e gönderilen sonucun hazır olduğuna dair kontrol sinyali //---------------------------------------------------------------- // reg_update // // Update functionality for all registers in the core. // All registers are positive edge triggered with asynchronous // active low reset. All registers have write enable. //---------------------------------------------------------------- always @ (posedge clk or negedge reset_n) begin: reg_update if (!reset_n) //reset begin result_valid_reg <= 1'b0; // sonucun hazır olmadığını belirtiyor ready_reg <= 1'b1; // işlem yapmaya hazır olduğunun sinyalini Aes main'e göndermek için hazırlıyor aes_core_ctrl_reg <= CTRL_IDLE; //ilk state IDLE olarak ayarlanıyor end else begin //run the hardware if (result_valid_we) // 1 olduğunda result_valid değişiyor, result_valid=1 ise AES main Result'ın hazır olduğunu anlıyor result_valid_reg <= result_valid_new; if (ready_we) //1 olduğunda ready sinyali değişiyor, ready_reg <= ready_new; if (aes_core_ctrl_we) //1 olduğunda state değişikliği gerçekleşiyor aes_core_ctrl_reg <= aes_core_ctrl_new; end end // reg_update //---------------------------------------------------------------- // sbox_mux // // Controls which of the encipher datapath or the key memory // that gets access to the sbox. //---------------------------------------------------------------- always @* begin : sbox_mux if (init_state) // if it is initial state then read data from key_mem else read it from enchipher block begin muxed_sboxw = keymem_sboxw; //sbox'ı keymem mi yoksa encipher modül mü kullanacak karar veriliyor end else begin muxed_sboxw = enc_sboxw; end end // sbox_mux //---------------------------------------------------------------- // encdex_mux // // Controls which of the datapaths that get the next signal, have // access to the memory as well as the block processing result. //---------------------------------------------------------------- always @* begin : encdec_mux //encription or decription initialization, decide whether enc or dec enc_next = 1'b0; dec_next = 1'b0; if (encdec) begin // Encipher operations enc_next = next; // aes main'den gelen next sinyali enchipher modüle aktarılıyor muxed_round_nr = enc_round_nr; //ENCHIPHER modülden gelen raund number alınıyor muxed_new_block = enc_new_block; // sbox'a gönderilecek olan 32 bit data enchipher modulden alınıyor muxed_ready = enc_ready; //enchipher modülden gelen ready sinyali alınıyor end else begin // Decipher operations dec_next = next; muxed_round_nr = dec_round_nr; muxed_new_block = dec_new_block; muxed_ready = dec_ready; end end // encdec_mux //---------------------------------------------------------------- // aes_core_ctrl // // Control FSM for aes core. Basically tracks if we are in // key init, encipher or decipher modes and connects the // different submodules to shared resources and interface ports. //---------------------------------------------------------------- always @* begin : aes_core_ctrl //initialization, first state is idle, every signal is assigned as 0 init_state = 1'b0; // stateler içinde değiştirilmeyen değişkenler için default değerler ready_new = 1'b0; ready_we = 1'b0; result_valid_new = 1'b0; result_valid_we = 1'b0; aes_core_ctrl_new = CTRL_IDLE; aes_core_ctrl_we = 1'b0; case (aes_core_ctrl_reg) // aes_core_ctrl_reg stateleri kontrol eden sinyal CTRL_IDLE: begin if (init) // AES Mainden geliyor. 1 ise initial işlem. begin //if init=1 init_state = 1'b1; //init_state is 1 so muxed_sboxw = keymem_sboxw; ready_new = 1'b0; //ready sinyali kapatılıyor, aes main yeni bir blok gönderemeyecek ready_we = 1'b1; //ready sinyalinin yazılmasını izin veriliyor result_valid_new = 1'b0; // CTRL_NEXT sonunda 1 olacak, aes main'e result'ın hazır olduğunu bildirmek için kullanılıyor result_valid_we = 1'b1; // result_valid'in yazılmasını kontrol ediyor aes_core_ctrl_new = CTRL_INIT; // next state INIT olarak atandı aes_core_ctrl_we = 1'b1; //state değişikliğine izin veren sinyal end else if (next) // init 1 değil ve next 1 ise bir sonraki işlem ile devam ediyor begin init_state = 1'b0; // bu durumda sbox'ı encipher module kullanacak ready_new = 1'b0; //ready sinyali kapatılıyor, aes main yeni bir blok gönderemeyecek ready_we = 1'b1; //ready sinyalinin yazılmasını izin veriliyor result_valid_new = 1'b0; // result hazır değil result_valid_we = 1'b1; // result_valid'in üzerine yeni değerin yazılmasına izin veriliyor aes_core_ctrl_new = CTRL_NEXT; //next state CTRL_NEXT olarak ayarlandı aes_core_ctrl_we = 1'b1; // state control register'ının üzerine yazılmasına izin verildi end end CTRL_INIT: begin init_state = 1'b1; //sbox'ı key modülü kullanacak if (key_ready) //eğer key_mem modülünden key'in hazır olduğuna dair sinyal geldiyse begin ready_new = 1'b1; //ready sinyali 1 olacak ve AES main'e ready sinyali gönderilecek, bu durumda yeni data okunabilir ready_we = 1'b1; aes_core_ctrl_new = CTRL_IDLE; //State IDLE olarak ayarlanacak aes_core_ctrl_we = 1'b1; end end CTRL_NEXT: begin init_state = 1'b0; //sbox'ı encipher modülü kullancak if (muxed_ready) //muxed_ready encipher ya da dechipher yapılmasına göre set ediliyor, begin //ben encipher varsaydım, bu durumda encipher işini bitirdiyse 1 olacak ready_new = 1'b1; // CTRL_INIT'teki işlemlerin aynıları yapılıyor ready_we = 1'b1; result_valid_new = 1'b1; result_valid_we = 1'b1; aes_core_ctrl_new = CTRL_IDLE; aes_core_ctrl_we = 1'b1; end end default: begin end endcase // case (aes_core_ctrl_reg) end // aes_core_ctrl endmodule // aes_core //====================================================================== // EOF aes_core.v //======================================================================
AES Key Module
`default_nettype none module aes_key_mem( input wire clk, input wire reset_n, input wire [255 : 0] key, // key AES_CORE'dan geliyor input wire keylen, // 128 veya 256 bit input wire init, // başlangıç sinyali input wire [3 : 0] round, //round bilgisi AES_ENCIPHER ile senkronize ilerliyor output wire [127 : 0] round_key, //O raundun keyi gönderiliyor output wire ready, //Keyin hazır olduğu bilgisi output wire [31 : 0] sboxw, //subbytes işlemi için 32bitlik blok gönderiliyor input wire [31 : 0] new_sboxw //subbyte yapılan sonuç geliyor ); //---------------------------------------------------------------- // Parameters. //---------------------------------------------------------------- localparam AES_128_BIT_KEY = 1'h0; localparam AES_256_BIT_KEY = 1'h1; localparam AES_128_NUM_ROUNDS = 10; localparam AES_256_NUM_ROUNDS = 14; localparam CTRL_IDLE = 3'h0; // main fsm için stateler localparam CTRL_INIT = 3'h1; localparam CTRL_GENERATE = 3'h2; localparam CTRL_DONE = 3'h3; //---------------------------------------------------------------- // Registers. //---------------------------------------------------------------- reg [127 : 0] key_mem [0 : 14]; reg [127 : 0] key_mem_new; reg key_mem_we; reg [127 : 0] prev_key0_reg; reg [127 : 0] prev_key0_new; reg prev_key0_we; reg [127 : 0] prev_key1_reg; reg [127 : 0] prev_key1_new; reg prev_key1_we; reg [3 : 0] round_ctr_reg; reg [3 : 0] round_ctr_new; reg round_ctr_rst; reg round_ctr_inc; reg round_ctr_we; reg [2 : 0] key_mem_ctrl_reg; reg [2 : 0] key_mem_ctrl_new; reg key_mem_ctrl_we; reg ready_reg; reg ready_new; reg ready_we; reg [7 : 0] rcon_reg; reg [7 : 0] rcon_new; reg rcon_we; reg rcon_set; reg rcon_next; //---------------------------------------------------------------- // Wires. //---------------------------------------------------------------- reg [31 : 0] tmp_sboxw; reg round_key_update; reg [127 : 0] tmp_round_key; //---------------------------------------------------------------- // Concurrent assignments for ports. //---------------------------------------------------------------- assign round_key = tmp_round_key; //output portlarına bağlantılar assign ready = ready_reg; assign sboxw = tmp_sboxw; //---------------------------------------------------------------- // reg_update // // Update functionality for all registers in the core. // All registers are positive edge triggered with asynchronous // active low reset. All registers have write enable. //---------------------------------------------------------------- always @ (posedge clk or negedge reset_n) begin: reg_update integer i; if (!reset_n) //reset sinyali geldiyse, her şey 0'lanıp IDLE state'e geçiyor. init sinyalini beklemeye başlıyor begin for (i = 0 ; i <= AES_256_NUM_ROUNDS ; i = i + 1) key_mem [i] <= 128'h0; ready_reg <= 1'b0; rcon_reg <= 8'h0; round_ctr_reg <= 4'h0; prev_key0_reg <= 128'h0; prev_key1_reg <= 128'h0; key_mem_ctrl_reg <= CTRL_IDLE; end else begin if (ready_we) //key hazır olduğunda CTRL_DONE State'inde 1 yapılıyor ready_reg <= ready_new; //keyin hazır olduğu bilgisi reg'e atanıyor, buradan AES_CORE'a gönderilecek if (rcon_we) //bir sonraki rcon kolonu değerinin yazılmasına ya da 0'lanmasına izin veriyor rcon_reg <= rcon_new; if (round_ctr_we) // round counter'ı arttığında ya da 0'lanması gerektiğinde 1 oluyor ve yeni değeri reg'e yazılıyor round_ctr_reg <= round_ctr_new; if (key_mem_we) //round key update edileceği zaman round_key_update kont içinde 1 yapılıyor key_mem[round_ctr_reg] <= key_mem_new; // oluşturulan round keyi key_mem'in gösterdiği round'un olduğu yere yazılıyor if (prev_key0_we) //256 bit olduğunda kullanıyoruz prev_key0_reg <= prev_key0_new; if (prev_key1_we) //yeni key oluştuğu zaman 1 yapılıyor, prev_key1_reg <= prev_key1_new; //böylelikle yeni keyin yedeği alınıyor, bir sonraki state'te kullanılacak if (key_mem_ctrl_we) // 1 olduğunda state değişikliği yapılacak key_mem_ctrl_reg <= key_mem_ctrl_new; end end // reg_update //---------------------------------------------------------------- // key_mem_read // // Combinational read port for the key memory. //---------------------------------------------------------------- always @* //key_mem içinde bütün raundlara ait keyler var, round değerine göre tmp_round_key'e alınıyor begin : key_mem_read //round_key üzerinden AES_CORE'a gönderiliyor (128 bit) tmp_round_key = key_mem[round]; end // key_mem_read //---------------------------------------------------------------- // round_key_gen // // The round key generator logic for AES-128 and AES-256. //---------------------------------------------------------------- always @* begin: round_key_gen reg [31 : 0] w0, w1, w2, w3, w4, w5, w6, w7; reg [31 : 0] k0, k1, k2, k3; reg [31 : 0] rconw, rotstw, tw, trw; // Default assignments. key_mem_new = 128'h0; key_mem_we = 1'b0; prev_key0_new = 128'h0; prev_key0_we = 1'b0; prev_key1_new = 128'h0; prev_key1_we = 1'b0; k0 = 32'h0; k1 = 32'h0; k2 = 32'h0; k3 = 32'h0; rcon_set = 1'b1; rcon_next = 1'b0; // Extract words and calculate intermediate values. // Perform rotation of sbox word etc. w0 = prev_key0_reg[127 : 096];//bu kısım 256 bit için w1 = prev_key0_reg[095 : 064]; w2 = prev_key0_reg[063 : 032]; w3 = prev_key0_reg[031 : 000]; w4 = prev_key1_reg[127 : 096];//128 bit key için bu kısımdan itibaren kullanılıyor w5 = prev_key1_reg[095 : 064];// bir önceki roundun keyi 4 kolon halinde alınıyor w6 = prev_key1_reg[063 : 032]; w7 = prev_key1_reg[031 : 000]; rconw = {rcon_reg, 24'h0}; // rcon matrix için kolonların değeri oluşturuluyor. rcon_reg içindeki değer 01,02,04,08 şeklinde artacak tmp_sboxw = w7; //bir önceki keyin son kolonu subbytes işlemi için sbox module gönderiliyor rotstw = {new_sboxw[23 : 00], new_sboxw[31 : 24]}; // subbytes sonucu geldikten sonra column rotate yapılıyor trw = rotstw ^ rconw; //rotate sonrası xor işlemi, yeni keyin hesaplanması için gereken kolon hazırlanıyor tw = new_sboxw; // Generate the specific round keys. if (round_key_update) // CTRL_GENERATE state'inde 1 yapılıyor, bu noktada yeni roundun keyi oluşturulmaya başlanıyor begin rcon_set = 1'b0; //rcon matrisinin ilk satırındaki değerlerin sırasıyla 1 2 4 8 şeklinde artışını kontrol eden sinyal, default 0 key_mem_we = 1'b1; //keyin yazılmasına izin veren sinyal, değişiklikler bu sinyal 1 olduğunda yapılıyor case (keylen) //keyin büyüklüğü AES_128_BIT_KEY: //128 bit key için begin if (round_ctr_reg == 0) //eğer ilk roundsa begin key_mem_new = key[255 : 128]; //AES_CORE'dan gelen key alınıyor, 128 bit olduğu için 128-256 arası bitler kullanılıyor prev_key1_new = key[255 : 128]; //bir önceki state'teki kolonlar yeni keyin oluşturulması sırasında kullanılacak // o yüzden bir yedeği alınıyor prev_key1_we = 1'b1; // prev_key'in yazılması için izin sinyali rcon_next = 1'b1; // bir sonraki rcon değerinin hesaplanması için izin sinyali end else // eğer ilk round değilse bir önceki roundda oluşturulan keyin son kolonu alınarak yeni key oluşturulmaya başlanıyor begin k0 = w4 ^ trw; //yeni keyin ilk kolonu için hesaplanan kolon(trw'de) önceki keyin ilk kolonu(w4'te) ile xorlanıyor, yeni keyin ilk kolonu oluşuyor k1 = w5 ^ w4 ^ trw; //yeni keyin ilk kolonu ile (k0=w4^trv) eski keyin 2. kolonu xorlanıp yeni keyin 2. kolonu oluşturuluyor k2 = w6 ^ w5 ^ w4 ^ trw; // yeni keyin 2. kolonu ile (k1=w5^w4^trw), eski keyin 3. kolonu xorlanıp yeni keyin 3. kolonu oluşturuluyor k3 = w7 ^ w6 ^ w5 ^ w4 ^ trw;// yeni keyin 3. kolonu ile (k2=w6^w5^w4^trw), eski keyin 4. kolonu xorlanıp yeni keyin 4. kolonu oluşturuluyor key_mem_new = {k0, k1, k2, k3}; // kolonlar birleştiriliyor ve yeni key tamamlanıyor prev_key1_new = {k0, k1, k2, k3}; //yeni keyin yedeği bir sonraki state'te kullanılmak için yedekleniyor prev_key1_we = 1'b1; //previous key yedeğinin yapılması için izin sinyali rcon_next = 1'b1; // bir sonraki rcon değerinin hesaplanması için izin sinyali end end AES_256_BIT_KEY: begin if (round_ctr_reg == 0) //0 ve 1 initial roundlar begin key_mem_new = key[255 : 128]; prev_key0_new = key[255 : 128]; prev_key0_we = 1'b1; end else if (round_ctr_reg == 1) begin key_mem_new = key[127 : 0]; prev_key1_new = key[127 : 0]; prev_key1_we = 1'b1; rcon_next = 1'b1; end else begin if (round_ctr_reg[0] == 0) //roundun tek veya çift sayıda olmasına bağlı olarak ilk 128 ve ikinci 128 bitlik begin //kısım üzerinde işlem yapıyor k0 = w0 ^ trw; k1 = w1 ^ w0 ^ trw; k2 = w2 ^ w1 ^ w0 ^ trw; k3 = w3 ^ w2 ^ w1 ^ w0 ^ trw; end else begin k0 = w0 ^ tw; k1 = w1 ^ w0 ^ tw; k2 = w2 ^ w1 ^ w0 ^ tw; k3 = w3 ^ w2 ^ w1 ^ w0 ^ tw; rcon_next = 1'b1; //ikinci 128bitlik kısım üzerinde işlem yaptıktan sonra bir sonraki rcon değerine geçmesine izin veriyor end // Store the generated round keys. key_mem_new = {k0, k1, k2, k3}; prev_key1_new = {k0, k1, k2, k3}; prev_key1_we = 1'b1; prev_key0_new = prev_key1_reg; prev_key0_we = 1'b1; end end default: begin end endcase // case (keylen) end end // round_key_gen //---------------------------------------------------------------- // rcon_logic // // Caclulates the rcon value for the different key expansion // iterations. //---------------------------------------------------------------- always @* begin : rcon_logic reg [7 : 0] tmp_rcon; rcon_new = 8'h00; //initial değerler rcon_we = 1'b0; //rcon_Set ya da rcon_next sinyali 1 olmadıkça değişmiyor, tmp_rcon = {rcon_reg[6 : 0], 1'b0} ^ (8'h1b & {8{rcon_reg[7]}});// MSB 0 iken sadece bir kere sola shift eder (2 ile çarpma) //MSB 1 olduğunda 0x1b ile xorlanıyor if (rcon_set) begin rcon_new = 8'h8d; //rcon ilk değer 01 olması lazım bunu burada sağlıyor. bu şekilde initial ediliyor 1000 1101 rcon_we = 1'b1; // ilk tmp_rcon hesabında(283. satır) {rcon_reg[6 : 0], 1'b0} = 0001 1010 end // {8{rcon_reg[7]} -->(1111 1111) bu değer 0001 1011 ile & --> 0001 1011 // 283 satır bu durumda 0001 1010 ^ 0001 1011 = 0000 0001 if (rcon_next) // her bir state için gereken 01 02 04 08 değerleri tmp_rcon içinde üretilmişti, burada next sinyali geldiyese begin // we 1 yapılarak rcon_new'un üzerine yazılmasını sağlanıyor rcon_new = tmp_rcon[7 : 0]; rcon_we = 1'b1; //değişiklik sinyali gelmedikçe bu always bloğu içinde 0 olarak assign ediliyor end end //---------------------------------------------------------------- // round_ctr // // The round counter logic with increase and reset. //---------------------------------------------------------------- always @* begin : round_ctr round_ctr_new = 4'h0; round_ctr_we = 1'b0; if (round_ctr_rst) // CTRL_INIT state'inde 1 yapılıyor, böylelikle yeni blok için counter 0'lanıyor begin round_ctr_new = 4'h0; round_ctr_we = 1'b1; end else if (round_ctr_inc) //her bir roundda işlem bittikten ve o raundun keyi hazır olduğunda CTRL_GENERATE statei 1 yapıyor begin round_ctr_new = round_ctr_reg + 1'b1; //counter arttırılıyor round_ctr_we = 1'b1; // yazılmasına izin veriyor end end //---------------------------------------------------------------- // key_mem_ctrl // // // The FSM that controls the round key generation. //---------------------------------------------------------------- always @* // main FSM begin: key_mem_ctrl reg [3 : 0] num_rounds; // Default assignments. // caseler içinde değiştirilmeyen kontrol sinyalleri için default değerler ready_new = 1'b0; ready_we = 1'b0; round_key_update = 1'b0; round_ctr_rst = 1'b0; round_ctr_inc = 1'b0; key_mem_ctrl_new = CTRL_IDLE; key_mem_ctrl_we = 1'b0; if (keylen == AES_128_BIT_KEY) // 128 veya 256 bit keye göre round sayısı num_rounds = AES_128_NUM_ROUNDS; //10 round else num_rounds = AES_256_NUM_ROUNDS; //14 round case(key_mem_ctrl_reg) //key_mem_ctrl_reg fsm'nin statelerini belirleyen ana değişken CTRL_IDLE: begin if (init) //init sinyali geldiyse. IDLE state içerisindeyse init sinyali önemli, diğer durumlarda gelen sinyale bakmıyor begin ready_new = 1'b0; //ready 0 yapılarak keyin hazır olmadığı belirtiliyor ready_we = 1'b1; //we 1 yapılarak ready sinyalinin yazılmasına izin veriyor key_mem_ctrl_new = CTRL_INIT; //state INIT olarak ayarlanıyor key_mem_ctrl_we = 1'b1; // state değişikliği için we sinyali 1 yapılıyor end end CTRL_INIT: //initialization state begin round_ctr_rst = 1'b1; //round counter'ın sıfırlanması için control sinyali. 1 olduğunda, yeni counter değeri 0 // olarak ayarlanacak ve round_ctr_we sinyali 1 yapılıp reg'e yazılacak key_mem_ctrl_new = CTRL_GENERATE; //state CTRL_GENERATE olarak ayarlanacak key_mem_ctrl_we = 1'b1; //state değişikliği için we sinyali 1 yapılacak end CTRL_GENERATE: //key generation state begin round_ctr_inc = 1'b1; //round counter'ın artmasına izin verecek round_key_update = 1'b1; //roundun keyinin oluşturulmasına başlanması için kontrol sinyali. 1 olduğunda işlemler başlayacak if (round_ctr_reg == num_rounds) //10 round olup olmadığının kontrolu burada begin key_mem_ctrl_new = CTRL_DONE; //10 round olduğunda state CTRL_DONE olarak değişecek key_mem_ctrl_we = 1'b1; // state değişikliğine izin verecek end end CTRL_DONE: // bu round için keyin bittiğini gösteren state begin ready_new = 1'b1;//keyin hazır olduğunu belirtiyor, AES_CORE'a gönderilecek ready_we = 1'b1;//ready sinyalinin yazılmasına izin veren kontrol sinyali key_mem_ctrl_new = CTRL_IDLE; //yeni rounda başlamak için IDLE state'e geri dönüyor key_mem_ctrl_we = 1'b1; //state değişikliğine izin verecek end default: begin end endcase // case (key_mem_ctrl_reg) end // key_mem_ctrl endmodule // aes_key_mem //====================================================================== // EOF aes_key_mem.v //======================================================================
AES Encipher Module
//====================================================================== // // aes_encipher_block.v // -------------------- // The AES encipher round. A pure combinational module that implements // the initial round, main round and final round logic for // enciper operations. // // // Author: Joachim Strombergson // Copyright (c) 2013, 2014, Secworks Sweden AB // All rights reserved. // `default_nettype none module aes_encipher_block( input wire clk, input wire reset_n, input wire next, //AES_CORE'dan geliyor, yeni işleme başlama komutu input wire keylen, // key 128 bit mi 256 bit mi olacak output wire [3 : 0] round, // round bilgisini AES_CORE'a gönderiyor, ona göre input wire [127 : 0] round_key, //round key gelecek output wire [31 : 0] sboxw, // Subbytes için AES_CORE'a 32 bit veri gidiyor input wire [31 : 0] new_sboxw, // Subbytes yapılmış veri geliyor input wire [127 : 0] block, //şifrelenecek 128 bit veri geliyor output wire [127 : 0] new_block, //şifrelenmiş hali AES_CORE'a gönderiliyor output wire ready // yeni 128 bitlik blok için hazır sinyali ); //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- localparam AES_128_BIT_KEY = 1'h0; localparam AES_256_BIT_KEY = 1'h1; localparam AES128_ROUNDS = 4'ha; localparam AES256_ROUNDS = 4'he; localparam NO_UPDATE = 3'h0; //yapılan işlemler için stateler localparam INIT_UPDATE = 3'h1; localparam SBOX_UPDATE = 3'h2; localparam MAIN_UPDATE = 3'h3; localparam FINAL_UPDATE = 3'h4; localparam CTRL_IDLE = 2'h0; //main FSM stateleri localparam CTRL_INIT = 2'h1; localparam CTRL_SBOX = 2'h2; localparam CTRL_MAIN = 2'h3; //---------------------------------------------------------------- // Round functions with sub functions. //---------------------------------------------------------------- function [7 : 0] gm2(input [7 : 0] op); //galois field matrixte 2 ile çarpma işlemi için gerekli, mixcolumns stepte kullanılıyor begin gm2 = {op[6 : 0], 1'b0} ^ (8'h1b & {8{op[7]}});// ({8{op[7]}}--> 8 tane op[7]), op[7] 1'se 0x1b ile xorla değilse xorlama end endfunction // gm2 function [7 : 0] gm3(input [7 : 0] op); //galois field matrixte 3 ile çarpma işlemi için gerekli, mixcolumns stepte kullanılıyor begin // gf(2) hesaplanıp kendisi ile xorlanıyor gm3 = gm2(op) ^ op; end endfunction // gm3 function [31 : 0] mixw(input [31 : 0] w); //mixcolumns step için yapılan galois field matrix çarpımı reg [7 : 0] b0, b1, b2, b3; //b kolon içindeki satırlar reg [7 : 0] mb0, mb1, mb2, mb3; //w içinde kolon alınıyor begin b0 = w[31 : 24]; b1 = w[23 : 16]; b2 = w[15 : 08]; b3 = w[07 : 00]; mb0 = gm2(b0) ^ gm3(b1) ^ b2 ^ b3; mb1 = b0 ^ gm2(b1) ^ gm3(b2) ^ b3; mb2 = b0 ^ b1 ^ gm2(b2) ^ gm3(b3); mb3 = gm3(b0) ^ b1 ^ b2 ^ gm2(b3); mixw = {mb0, mb1, mb2, mb3}; // sonuç tekrar kolona çevriliyor end endfunction // mixw function [127 : 0] mixcolumns(input [127 : 0] data); //mixcolumns step reg [31 : 0] w0, w1, w2, w3; //w içerisinde 4 kolon alınıyor mixw functiona gönderilip reg [31 : 0] ws0, ws1, ws2, ws3; // galois field ile çarpımı yapılıyor begin w0 = data[127 : 096]; //128 bit data 32 bitlik 4 kolona çevriliyor w1 = data[095 : 064]; w2 = data[063 : 032]; w3 = data[031 : 000]; ws0 = mixw(w0); ws1 = mixw(w1); ws2 = mixw(w2); ws3 = mixw(w3); mixcolumns = {ws0, ws1, ws2, ws3}; // mixcolumns işlemi sonunda 32 bitlik kolonlar birleştiriliyor end endfunction // mixcolumns function [127 : 0] shiftrows(input [127 : 0] data); //shiftrows step reg [31 : 0] w0, w1, w2, w3; // 1. satır aynı kalıyor reg [31 : 0] ws0, ws1, ws2, ws3; // 2. satır 1 kere, 3. satır 2 kere, 4. satır 3 kere rotate ediliyor begin w0 = data[127 : 096]; w1 = data[095 : 064]; w2 = data[063 : 032]; w3 = data[031 : 000]; ws0 = {w0[31 : 24], w1[23 : 16], w2[15 : 08], w3[07 : 00]}; ws1 = {w1[31 : 24], w2[23 : 16], w3[15 : 08], w0[07 : 00]}; ws2 = {w2[31 : 24], w3[23 : 16], w0[15 : 08], w1[07 : 00]}; ws3 = {w3[31 : 24], w0[23 : 16], w1[15 : 08], w2[07 : 00]}; shiftrows = {ws0, ws1, ws2, ws3}; // rotate edilen satırlar birleştiriliyor end endfunction // shiftrows function [127 : 0] addroundkey(input [127 : 0] data, input [127 : 0] rkey); //addroundkey step begin addroundkey = data ^ rkey; // o raundun keyi ile data xorlanıyor end endfunction // addroundkey //---------------------------------------------------------------- // Registers including update variables and write enable. //---------------------------------------------------------------- reg [1 : 0] sword_ctr_reg; reg [1 : 0] sword_ctr_new; reg sword_ctr_we; reg sword_ctr_inc; reg sword_ctr_rst; reg [3 : 0] round_ctr_reg; reg [3 : 0] round_ctr_new; reg round_ctr_we; reg round_ctr_rst; reg round_ctr_inc; reg [127 : 0] block_new; reg [31 : 0] block_w0_reg; reg [31 : 0] block_w1_reg; reg [31 : 0] block_w2_reg; reg [31 : 0] block_w3_reg; reg block_w0_we; reg block_w1_we; reg block_w2_we; reg block_w3_we; reg ready_reg; reg ready_new; reg ready_we; reg [1 : 0] enc_ctrl_reg; reg [1 : 0] enc_ctrl_new; reg enc_ctrl_we; //---------------------------------------------------------------- // Wires. //---------------------------------------------------------------- reg [2 : 0] update_type; reg [31 : 0] muxed_sboxw; //32 bitlik geçici sbox registerı, bunun üzerinden subbytes işlemi yapılıyor. //---------------------------------------------------------------- // Concurrent connectivity for ports etc. //---------------------------------------------------------------- assign round = round_ctr_reg; assign sboxw = muxed_sboxw; assign new_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg}; assign ready = ready_reg; //---------------------------------------------------------------- // reg_update // // Update functionality for all registers in the core. // All registers are positive edge triggered with asynchronous // active low reset. All registers have write enable. //---------------------------------------------------------------- always @ (posedge clk or negedge reset_n) begin: reg_update if (!reset_n) begin block_w0_reg <= 32'h0; block_w1_reg <= 32'h0; block_w2_reg <= 32'h0; block_w3_reg <= 32'h0; sword_ctr_reg <= 2'h0; round_ctr_reg <= 4'h0; ready_reg <= 1'b1; enc_ctrl_reg <= CTRL_IDLE; end else begin if (block_w0_we) //4 parçaya bölünen block her bir işlemden sonra we 1 olduğunda sonucun yazılması block_w0_reg <= block_new[127 : 096]; // sağlanıyor //SBOX_UPDATE adımında bu 4'e bölünen her kısımda aynı veri var if (block_w1_we) // hangi bloğun we sinyali 1 ise ona yazılacak block_w1_reg <= block_new[095 : 064]; // diğer adımlarda 128 bit birden işleme alındığında bütün we sinyalleri 1 olduğundan // tek seferde 4 blok da yazılıyor if (block_w2_we) block_w2_reg <= block_new[063 : 032]; if (block_w3_we) block_w3_reg <= block_new[031 : 000]; if (sword_ctr_we) // 1 olduğunda SBOX için yeni counter değeri reg'e atanıyor. 0'lanıyor ya da arttırılan yeni değeri atanıyor sword_ctr_reg <= sword_ctr_new; if (round_ctr_we) //counter arttıktan sonra ya da 0'landığında we 1 olacak, yeni counter değeri reg'e atanabilecek round_ctr_reg <= round_ctr_new; if (ready_we) //eğer we 1 olursa ready_reg üzerinden AES_CORE'a ready signalinin yeni değerinin gönderilmesini sağlayacak ready_reg <= ready_new; if (enc_ctrl_we) //FSM'de bir sonraki state'i belirliyor we 1 olduğunda state değişiyor enc_ctrl_reg <= enc_ctrl_new; end end // reg_update //---------------------------------------------------------------- // round_logic // // The logic needed to implement init, main and final rounds. //---------------------------------------------------------------- always @* begin : round_logic reg [127 : 0] old_block, shiftrows_block, mixcolumns_block; reg [127 : 0] addkey_init_block, addkey_main_block, addkey_final_block; block_new = 128'h0; muxed_sboxw = 32'h0; block_w0_we = 1'b0; block_w1_we = 1'b0; block_w2_we = 1'b0; block_w3_we = 1'b0; old_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg}; shiftrows_block = shiftrows(old_block); mixcolumns_block = mixcolumns(shiftrows_block); addkey_init_block = addroundkey(block, round_key); //128 bitlik gelen ilk data addroundkey'e gönderiliyor, sonuç addkey_init_block'ta saklanıyor addkey_main_block = addroundkey(mixcolumns_block, round_key); addkey_final_block = addroundkey(shiftrows_block, round_key); case (update_type) INIT_UPDATE: begin block_new = addkey_init_block; // eğer initial stepse bu stepte addroundkey işlemi sonucunda çıkan addkey_init_block'taki veri block_new'e aktarılıyor //gelen 128bitlik main block, round için gelen key ile xorlanıyor (AddRoundKey step) //128 bitlik blok "block" değişkeni içinde geldi. addroundkey functionına gönderildi. //addkey_init_block içerisinde işlemin sonucu tutuluyor, o da burada block_new'e aktarıldı block_w0_we = 1'b1; //SBOX işlemini 32bitlik 4 blok halinde yapacak o yüzden block 4 parçaya bölünecek block_w1_we = 1'b1; // sonuç 4 parça halinde w0-w3 içinde tutulacak, sonrasında birleştirilecek, üzerine yazılabilmesi için block_w2_we = 1'b1; //we sinyalleri 1 yapıldı block_w3_we = 1'b1; end SBOX_UPDATE: //eğer subbytes step ise block_new'e sbox'ta değiştirilen değerler yükleniyor begin //new_sboxw AES_CORE'dan gelen Subbytes yapılmış 32bitlik veri block_new = {new_sboxw, new_sboxw, new_sboxw, new_sboxw}; //32 bitlik 4 block halinde değişim yapılıyor // burada Subbytes yapılıp gelen 32bitlik değerin aynısı 4 bloğa da yazılıyor case (sword_ctr_reg) //Counter değerine göre her seferinde 1 tane 32 bitlik kısmın Subbytes yapmasını sağlıyor 2'h0: begin muxed_sboxw = block_w0_reg; //muxed_sboxw AES_CORE'e bağlı olan sboxw'a assign ediliyor. AES_CORE bunu AES_SBOX'a block_w0_we = 1'b1; // gönderip subbytes işleminin yapılmasını sağlıyor end 2'h1: begin muxed_sboxw = block_w1_reg; // hangi blok işleme alınacaksa onun we signali 1 oluyor block_w1_we = 1'b1; // diğerlerine bu always bloğunun başında default değer olarak 1 atanıyor end 2'h2: begin muxed_sboxw = block_w2_reg; block_w2_we = 1'b1; end 2'h3: begin muxed_sboxw = block_w3_reg; block_w3_we = 1'b1; end endcase // case (sbox_mux_ctrl_reg) end MAIN_UPDATE: //initial step sonrası 9 defa tekrar edecek kısım için, block_new'e addkey_main_block yükleniyor begin block_new = addkey_main_block; //muxed_sboxw'tan gelen subbytes yapılış değerler, ilk olarak block_w0-w3_reg üzerinden old_block'a yazılıyor // old_block shiftrows function'a gönderiliyor, shift işlemi sonrası sonuç shiftrows_block'ta tutuluyor // shiftrows_block mixcolumns function'a gönderiliyor, sonuç mixcolumns_block'ta tutuluyor //mixcolumns_block addroundkey function'a gönderiliyor, sonuç addkey_main_block'a geliyor //burada da sonuç block_new'e atanıyor, block_w0_we = 1'b1; //4 we sinyali de 1 yapılıyor, böylelikle block_new 4 parçaya bölünerek block_w0-w3_reg'e atanabilecek block_w1_we = 1'b1; //bir sonraki adımda block_w0-w3_reg'den alınan 4 parça kullanılacak block_w2_we = 1'b1; block_w3_we = 1'b1; end FINAL_UPDATE: // main step sonrası son adım için block_new'e addkey_final_block yükleniyor begin block_new = addkey_final_block; // mixcolumns yapmadan addroundkey function'ı shiftrows_block'ta saklı sonuç üzerinden çağırıyor block_w0_we = 1'b1; // geri kalan kısımlar MAIN_UPDATE ile aynı çalışıyor block_w1_we = 1'b1; block_w2_we = 1'b1; block_w3_we = 1'b1; end default: begin end endcase // case (update_type) end // round_logic //---------------------------------------------------------------- // sword_ctr // // The subbytes word counter with reset and increase logic. //---------------------------------------------------------------- always @* begin : sword_ctr sword_ctr_new = 2'h0; sword_ctr_we = 1'b0; if (sword_ctr_rst) //Eğer Sbox işlemi için ilk 32 bit alınacaksa counter resetleniyor begin sword_ctr_new = 2'h0; //Counterın yeni değeri 0 olarak set ediliyor sword_ctr_we = 1'b1; // we 1 yapılarak 0 olarak set edilen counter değerinin reg'e yazılmasına izin veriyor end else if (sword_ctr_inc) //SBOX_UPDATE kısmında sırası ile 4 bloğun da işleme alınması için gereken counterın artmasını sağlayan kontrol sinyali begin sword_ctr_new = sword_ctr_reg + 1'b1; sword_ctr_we = 1'b1; end end // sword_ctr //---------------------------------------------------------------- // round_ctr // // The round counter with reset and increase logic. //---------------------------------------------------------------- always @* begin : round_ctr round_ctr_new = 4'h0; round_ctr_we = 1'b0; if (round_ctr_rst) begin round_ctr_new = 4'h0; round_ctr_we = 1'b1; end else if (round_ctr_inc) // sinyal 1 geldiğinde counter reg içinde olan bir önceki değerin üzerine 1 ekleyip new'e atıyor. begin round_ctr_new = round_ctr_reg + 1'b1; round_ctr_we = 1'b1; // we 1 olunca'da yeni değerin reg'e yazılması sağlanıyor end end // round_ctr //---------------------------------------------------------------- // encipher_ctrl // // The FSM that controls the encipher operations. //---------------------------------------------------------------- always @* // Main FSM begin: encipher_ctrl reg [3 : 0] num_rounds; //counts the rounds (128 bit için 10) // Default assignments. // enc_ctrl_reg FSM'nin statelerini kontrol eden variable sword_ctr_inc = 1'b0; // enc_ctrl_reg'e göre assign edilen variablelar dışındakiler buradaki değerleri alıyor sword_ctr_rst = 1'b0; round_ctr_inc = 1'b0; round_ctr_rst = 1'b0; ready_new = 1'b0; ready_we = 1'b0; update_type = NO_UPDATE; enc_ctrl_new = CTRL_IDLE; enc_ctrl_we = 1'b0; if (keylen == AES_256_BIT_KEY) begin num_rounds = AES256_ROUNDS; end else begin num_rounds = AES128_ROUNDS; //128 bit için raund sayısı 10 end case(enc_ctrl_reg) CTRL_IDLE: begin if (next) //1 ise işlem başlayacak begin round_ctr_rst = 1'b1; //işleme başladığı zaman round counter 0'lanıyor ready_new = 1'b0; // dışarıya ready signalinin 0 olarak gönderilmesini sağlıyor, böylece AES_CORE'dan yeni ready_we = 1'b1; //bilgi gelmeyecek, ready sinyalinin yeni değerinin yazılabilmesi için we signali 1 yapıldı enc_ctrl_new = CTRL_INIT; //IDLE stateten INIT state geçişi saglıyor enc_ctrl_we = 1'b1; //kontrol sinyali, 1 olduğunda yeni state enc_ctrl_reg'e new üzerinden yazılacak end end CTRL_INIT: begin round_ctr_inc = 1'b1; //round counterın artması için gereken kontrol sinyali, 1 olduğunda counter'ı 1 arttıracak işlemi yapacak sword_ctr_rst = 1'b1; // SBOX işlemi 4 stepte yapılıyor, 32 bitlik 4 blok şeklinde. burada counter 0'lanarak ilk adımdan başlaması sağlanıyor // sbox Counter'ını 0'lamak için gereken sinyal update_type = INIT_UPDATE; //yapılan işlemin hangisi olduğunu tutan control değişkeni. Initial stepte ilk init update'i yapacağı bloğa gidecek enc_ctrl_new = CTRL_SBOX; //INIT stateten SBOX statee geçişi sağlıyor enc_ctrl_we = 1'b1; //kontrol sinyali, 1 olduğunda yeni state enc_ctrl_reg'e new üzerinden yazılacak end CTRL_SBOX: begin sword_ctr_inc = 1'b1; //SBOX 4 adımda yapılacak, INIT state'te counter 0'lanmıştı, burada counter arttırılacak update_type = SBOX_UPDATE; //yapılacak işi SBOX_UPDATE olarak ayarladı if (sword_ctr_reg == 2'h3) //4 sbox da bitince bir sonraki state CTRL_MAIN'e geçecek. Diğer durumda CTRL_SBOX state devam edecek begin //SBOX_UPDATE işlemi de yapılmaya devam edecek enc_ctrl_new = CTRL_MAIN; enc_ctrl_we = 1'b1; //kontrol sinyali, 1 olduğunda yeni state enc_ctrl_reg'e new üzerinden yazılacak end end CTRL_MAIN:// Subbytes, shiftrows, mixcolumns ve addroundkey 10 defa tekrar edilecek, 10 tekrarda mixcolumns işlemi olmayacak begin sword_ctr_rst = 1'b1; // her round başında sbox counterı sıfırlanacak, o yüzden reset sinyali 1 oluyor round_ctr_inc = 1'b1; // her roundda counter 1 arttırılacak, increment sinyali 1 oluyor if (round_ctr_reg < num_rounds) //num_rounds=10 ilk 9da MAIN_UPDATE yapılacak, sonuncu adımda FINAL_UPDATE yapılacak begin update_type = MAIN_UPDATE; // ilk 9 işlem için MAIN_UPDATE'de yapılacak işler için state ayarlandı enc_ctrl_new = CTRL_SBOX; // 1 round MAIN_UPDATE yapıldıktan sonra SBOX statee dönüp Subbytes işlemi yapacak enc_ctrl_we = 1'b1; end else begin update_type = FINAL_UPDATE; // son adımda FINAL_UPDATE yapılacak ready_new = 1'b1; // yeni 128'bitlik blok alınabilmesi için ready sinyali 1 yapıldı ready_we = 1'b1; // yeni ready sinyalinin yazılabilmesi için we sinyali 1 oldu enc_ctrl_new = CTRL_IDLE; // IDLE statee dönüp yeni 128 bitlik bloğun gelmesini bekleyecek enc_ctrl_we = 1'b1; end end default: begin // Empty. Just here to make the synthesis tool happy. end endcase // case (enc_ctrl_reg) end // encipher_ctrl endmodule // aes_encipher_block //====================================================================== // EOF aes_encipher_block.v //======================================================================
AES SBOX Module
`default_nettype none module aes_sbox( input wire [31 : 0] sboxw, output wire [31 : 0] new_sboxw ); //---------------------------------------------------------------- // The sbox array. //---------------------------------------------------------------- wire [7 : 0] sbox [0 : 255]; //---------------------------------------------------------------- // Four parallel muxes. //---------------------------------------------------------------- assign new_sboxw[31 : 24] = sbox[sboxw[31 : 24]]; assign new_sboxw[23 : 16] = sbox[sboxw[23 : 16]]; assign new_sboxw[15 : 08] = sbox[sboxw[15 : 08]]; assign new_sboxw[07 : 00] = sbox[sboxw[07 : 00]]; //---------------------------------------------------------------- // Creating the sbox array contents. //---------------------------------------------------------------- assign sbox[8'h00] = 8'h63; assign sbox[8'h01] = 8'h7c; assign sbox[8'h02] = 8'h77; assign sbox[8'h03] = 8'h7b; assign sbox[8'h04] = 8'hf2; assign sbox[8'h05] = 8'h6b; assign sbox[8'h06] = 8'h6f; assign sbox[8'h07] = 8'hc5; assign sbox[8'h08] = 8'h30; assign sbox[8'h09] = 8'h01; assign sbox[8'h0a] = 8'h67; assign sbox[8'h0b] = 8'h2b; assign sbox[8'h0c] = 8'hfe; assign sbox[8'h0d] = 8'hd7; assign sbox[8'h0e] = 8'hab; assign sbox[8'h0f] = 8'h76; assign sbox[8'h10] = 8'hca; assign sbox[8'h11] = 8'h82; assign sbox[8'h12] = 8'hc9; assign sbox[8'h13] = 8'h7d; assign sbox[8'h14] = 8'hfa; assign sbox[8'h15] = 8'h59; assign sbox[8'h16] = 8'h47; assign sbox[8'h17] = 8'hf0; assign sbox[8'h18] = 8'had; assign sbox[8'h19] = 8'hd4; assign sbox[8'h1a] = 8'ha2; assign sbox[8'h1b] = 8'haf; assign sbox[8'h1c] = 8'h9c; assign sbox[8'h1d] = 8'ha4; assign sbox[8'h1e] = 8'h72; assign sbox[8'h1f] = 8'hc0; assign sbox[8'h20] = 8'hb7; assign sbox[8'h21] = 8'hfd; assign sbox[8'h22] = 8'h93; assign sbox[8'h23] = 8'h26; assign sbox[8'h24] = 8'h36; assign sbox[8'h25] = 8'h3f; assign sbox[8'h26] = 8'hf7; assign sbox[8'h27] = 8'hcc; assign sbox[8'h28] = 8'h34; assign sbox[8'h29] = 8'ha5; assign sbox[8'h2a] = 8'he5; assign sbox[8'h2b] = 8'hf1; assign sbox[8'h2c] = 8'h71; assign sbox[8'h2d] = 8'hd8; assign sbox[8'h2e] = 8'h31; assign sbox[8'h2f] = 8'h15; assign sbox[8'h30] = 8'h04; assign sbox[8'h31] = 8'hc7; assign sbox[8'h32] = 8'h23; assign sbox[8'h33] = 8'hc3; assign sbox[8'h34] = 8'h18; assign sbox[8'h35] = 8'h96; assign sbox[8'h36] = 8'h05; assign sbox[8'h37] = 8'h9a; assign sbox[8'h38] = 8'h07; assign sbox[8'h39] = 8'h12; assign sbox[8'h3a] = 8'h80; assign sbox[8'h3b] = 8'he2; assign sbox[8'h3c] = 8'heb; assign sbox[8'h3d] = 8'h27; assign sbox[8'h3e] = 8'hb2; assign sbox[8'h3f] = 8'h75; assign sbox[8'h40] = 8'h09; assign sbox[8'h41] = 8'h83; assign sbox[8'h42] = 8'h2c; assign sbox[8'h43] = 8'h1a; assign sbox[8'h44] = 8'h1b; assign sbox[8'h45] = 8'h6e; assign sbox[8'h46] = 8'h5a; assign sbox[8'h47] = 8'ha0; assign sbox[8'h48] = 8'h52; assign sbox[8'h49] = 8'h3b; assign sbox[8'h4a] = 8'hd6; assign sbox[8'h4b] = 8'hb3; assign sbox[8'h4c] = 8'h29; assign sbox[8'h4d] = 8'he3; assign sbox[8'h4e] = 8'h2f; assign sbox[8'h4f] = 8'h84; assign sbox[8'h50] = 8'h53; assign sbox[8'h51] = 8'hd1; assign sbox[8'h52] = 8'h00; assign sbox[8'h53] = 8'hed; assign sbox[8'h54] = 8'h20; assign sbox[8'h55] = 8'hfc; assign sbox[8'h56] = 8'hb1; assign sbox[8'h57] = 8'h5b; assign sbox[8'h58] = 8'h6a; assign sbox[8'h59] = 8'hcb; assign sbox[8'h5a] = 8'hbe; assign sbox[8'h5b] = 8'h39; assign sbox[8'h5c] = 8'h4a; assign sbox[8'h5d] = 8'h4c; assign sbox[8'h5e] = 8'h58; assign sbox[8'h5f] = 8'hcf; assign sbox[8'h60] = 8'hd0; assign sbox[8'h61] = 8'hef; assign sbox[8'h62] = 8'haa; assign sbox[8'h63] = 8'hfb; assign sbox[8'h64] = 8'h43; assign sbox[8'h65] = 8'h4d; assign sbox[8'h66] = 8'h33; assign sbox[8'h67] = 8'h85; assign sbox[8'h68] = 8'h45; assign sbox[8'h69] = 8'hf9; assign sbox[8'h6a] = 8'h02; assign sbox[8'h6b] = 8'h7f; assign sbox[8'h6c] = 8'h50; assign sbox[8'h6d] = 8'h3c; assign sbox[8'h6e] = 8'h9f; assign sbox[8'h6f] = 8'ha8; assign sbox[8'h70] = 8'h51; assign sbox[8'h71] = 8'ha3; assign sbox[8'h72] = 8'h40; assign sbox[8'h73] = 8'h8f; assign sbox[8'h74] = 8'h92; assign sbox[8'h75] = 8'h9d; assign sbox[8'h76] = 8'h38; assign sbox[8'h77] = 8'hf5; assign sbox[8'h78] = 8'hbc; assign sbox[8'h79] = 8'hb6; assign sbox[8'h7a] = 8'hda; assign sbox[8'h7b] = 8'h21; assign sbox[8'h7c] = 8'h10; assign sbox[8'h7d] = 8'hff; assign sbox[8'h7e] = 8'hf3; assign sbox[8'h7f] = 8'hd2; assign sbox[8'h80] = 8'hcd; assign sbox[8'h81] = 8'h0c; assign sbox[8'h82] = 8'h13; assign sbox[8'h83] = 8'hec; assign sbox[8'h84] = 8'h5f; assign sbox[8'h85] = 8'h97; assign sbox[8'h86] = 8'h44; assign sbox[8'h87] = 8'h17; assign sbox[8'h88] = 8'hc4; assign sbox[8'h89] = 8'ha7; assign sbox[8'h8a] = 8'h7e; assign sbox[8'h8b] = 8'h3d; assign sbox[8'h8c] = 8'h64; assign sbox[8'h8d] = 8'h5d; assign sbox[8'h8e] = 8'h19; assign sbox[8'h8f] = 8'h73; assign sbox[8'h90] = 8'h60; assign sbox[8'h91] = 8'h81; assign sbox[8'h92] = 8'h4f; assign sbox[8'h93] = 8'hdc; assign sbox[8'h94] = 8'h22; assign sbox[8'h95] = 8'h2a; assign sbox[8'h96] = 8'h90; assign sbox[8'h97] = 8'h88; assign sbox[8'h98] = 8'h46; assign sbox[8'h99] = 8'hee; assign sbox[8'h9a] = 8'hb8; assign sbox[8'h9b] = 8'h14; assign sbox[8'h9c] = 8'hde; assign sbox[8'h9d] = 8'h5e; assign sbox[8'h9e] = 8'h0b; assign sbox[8'h9f] = 8'hdb; assign sbox[8'ha0] = 8'he0; assign sbox[8'ha1] = 8'h32; assign sbox[8'ha2] = 8'h3a; assign sbox[8'ha3] = 8'h0a; assign sbox[8'ha4] = 8'h49; assign sbox[8'ha5] = 8'h06; assign sbox[8'ha6] = 8'h24; assign sbox[8'ha7] = 8'h5c; assign sbox[8'ha8] = 8'hc2; assign sbox[8'ha9] = 8'hd3; assign sbox[8'haa] = 8'hac; assign sbox[8'hab] = 8'h62; assign sbox[8'hac] = 8'h91; assign sbox[8'had] = 8'h95; assign sbox[8'hae] = 8'he4; assign sbox[8'haf] = 8'h79; assign sbox[8'hb0] = 8'he7; assign sbox[8'hb1] = 8'hc8; assign sbox[8'hb2] = 8'h37; assign sbox[8'hb3] = 8'h6d; assign sbox[8'hb4] = 8'h8d; assign sbox[8'hb5] = 8'hd5; assign sbox[8'hb6] = 8'h4e; assign sbox[8'hb7] = 8'ha9; assign sbox[8'hb8] = 8'h6c; assign sbox[8'hb9] = 8'h56; assign sbox[8'hba] = 8'hf4; assign sbox[8'hbb] = 8'hea; assign sbox[8'hbc] = 8'h65; assign sbox[8'hbd] = 8'h7a; assign sbox[8'hbe] = 8'hae; assign sbox[8'hbf] = 8'h08; assign sbox[8'hc0] = 8'hba; assign sbox[8'hc1] = 8'h78; assign sbox[8'hc2] = 8'h25; assign sbox[8'hc3] = 8'h2e; assign sbox[8'hc4] = 8'h1c; assign sbox[8'hc5] = 8'ha6; assign sbox[8'hc6] = 8'hb4; assign sbox[8'hc7] = 8'hc6; assign sbox[8'hc8] = 8'he8; assign sbox[8'hc9] = 8'hdd; assign sbox[8'hca] = 8'h74; assign sbox[8'hcb] = 8'h1f; assign sbox[8'hcc] = 8'h4b; assign sbox[8'hcd] = 8'hbd; assign sbox[8'hce] = 8'h8b; assign sbox[8'hcf] = 8'h8a; assign sbox[8'hd0] = 8'h70; assign sbox[8'hd1] = 8'h3e; assign sbox[8'hd2] = 8'hb5; assign sbox[8'hd3] = 8'h66; assign sbox[8'hd4] = 8'h48; assign sbox[8'hd5] = 8'h03; assign sbox[8'hd6] = 8'hf6; assign sbox[8'hd7] = 8'h0e; assign sbox[8'hd8] = 8'h61; assign sbox[8'hd9] = 8'h35; assign sbox[8'hda] = 8'h57; assign sbox[8'hdb] = 8'hb9; assign sbox[8'hdc] = 8'h86; assign sbox[8'hdd] = 8'hc1; assign sbox[8'hde] = 8'h1d; assign sbox[8'hdf] = 8'h9e; assign sbox[8'he0] = 8'he1; assign sbox[8'he1] = 8'hf8; assign sbox[8'he2] = 8'h98; assign sbox[8'he3] = 8'h11; assign sbox[8'he4] = 8'h69; assign sbox[8'he5] = 8'hd9; assign sbox[8'he6] = 8'h8e; assign sbox[8'he7] = 8'h94; assign sbox[8'he8] = 8'h9b; assign sbox[8'he9] = 8'h1e; assign sbox[8'hea] = 8'h87; assign sbox[8'heb] = 8'he9; assign sbox[8'hec] = 8'hce; assign sbox[8'hed] = 8'h55; assign sbox[8'hee] = 8'h28; assign sbox[8'hef] = 8'hdf; assign sbox[8'hf0] = 8'h8c; assign sbox[8'hf1] = 8'ha1; assign sbox[8'hf2] = 8'h89; assign sbox[8'hf3] = 8'h0d; assign sbox[8'hf4] = 8'hbf; assign sbox[8'hf5] = 8'he6; assign sbox[8'hf6] = 8'h42; assign sbox[8'hf7] = 8'h68; assign sbox[8'hf8] = 8'h41; assign sbox[8'hf9] = 8'h99; assign sbox[8'hfa] = 8'h2d; assign sbox[8'hfb] = 8'h0f; assign sbox[8'hfc] = 8'hb0; assign sbox[8'hfd] = 8'h54; assign sbox[8'hfe] = 8'hbb; assign sbox[8'hff] = 8'h16; endmodule // aes_sbox //====================================================================== // EOF aes_sbox.v //======================================================================
The original source codes are taken from https://github.com/secworks/aes