From 9c5acbbcd7928a2958d370923d9cc0276037f1aa Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Mon, 31 May 2021 17:29:10 -0400 Subject: Reformatted --- src/rtl/sha3.v | 310 +++++++++--------- src/rtl/sha3_wrapper.v | 40 +-- stm32/sha3_driver_sample.c | 773 +++++++++++++++++++++++---------------------- 3 files changed, 562 insertions(+), 561 deletions(-) diff --git a/src/rtl/sha3.v b/src/rtl/sha3.v index ab18ca0..b01d50c 100644 --- a/src/rtl/sha3.v +++ b/src/rtl/sha3.v @@ -41,161 +41,161 @@ `define pilni(i) ((piln>>((23-i)*5)) & 5'h1f) `define rndci(i) ((rndc>>((23-i)*64)) & 64'hffffffffffffffff) -`define SHA3_NUM_ROUNDS 5'd24 - -module sha3( input wire clk, - nreset, - w, - input wire [ 8:2] addr, - input wire [32-1:0] din, - output reg [32-1:0] dout, - input wire init, - input wire next, - output wire ready); - - integer i, j; - - reg [64-1:0] blk[0:24], // input block - st [0:24], // current state - stn[0:24], // new state - bc [0: 4], // intermediate values - t; // temporary variable - - reg [ 4:0] round; // counter value - - - localparam [ 4: 0] roundlimit = `SHA3_NUM_ROUNDS - 'b1; - - - localparam [24*6-1:0] rotc = - { 6'h01, 6'h03, 6'h06, 6'h0A, 6'h0F, 6'h15, - 6'h1C, 6'h24, 6'h2D, 6'h37, 6'h02, 6'h0E, - 6'h1B, 6'h29, 6'h38, 6'h08, 6'h19, 6'h2B, - 6'h3E, 6'h12, 6'h27, 6'h3D, 6'h14, 6'h2C}; - - localparam [24*5-1:0] piln = - { 5'h0A, 5'h07, 5'h0B, 5'h11, 5'h12, 5'h03, - 5'h05, 5'h10, 5'h08, 5'h15, 5'h18, 5'h04, - 5'h0F, 5'h17, 5'h13, 5'h0D, 5'h0C, 5'h02, - 5'h14, 5'h0E, 5'h16, 5'h09, 5'h06, 5'h01}; - - localparam [24*64-1:0] rndc = - { 64'h0000000000000001, 64'h0000000000008082, - 64'h800000000000808a, 64'h8000000080008000, - 64'h000000000000808b, 64'h0000000080000001, - 64'h8000000080008081, 64'h8000000000008009, - 64'h000000000000008a, 64'h0000000000000088, - 64'h0000000080008009, 64'h000000008000000a, - 64'h000000008000808b, 64'h800000000000008b, - 64'h8000000000008089, 64'h8000000000008003, - 64'h8000000000008002, 64'h8000000000000080, - 64'h000000000000800a, 64'h800000008000000a, - 64'h8000000080008081, 64'h8000000000008080, - 64'h0000000080000001, 64'h8000000080008008}; - - /* input block buffer is mapped to the lower half of the - address space, sponge state is mapped to the upper one */ - - /* the lowest address bit determines what part of 64-bit word to return */ - - always @(posedge clk) - // - dout <= addr[8] ? - (~addr[2] ? st [addr[7:3]][31:0] : st [addr[7:3]][63:32]) : - (~addr[2] ? blk[addr[7:3]][31:0] : blk[addr[7:3]][63:32]) ; - - - always @* begin - - // theta1 - for (i=0; i<25; i=i+1) - stn[i] = st[i]; - - for (i=0; i<5; i=i+1) - bc[i] = stn[i] ^ stn[i+5] ^ stn[i+10] ^ stn[i+15] ^ stn[i+20]; - - // theta2 - for (i=0; i<5; i=i+1) begin - - t = bc[(i+4)%5] ^ `rotl64(bc[(i+1)%5], 1); - - for(j=i; j<25; j=j+5) - stn[j] = t ^ stn[j]; - end - - // rophi - t = stn[1]; - for(i=0; i<24; i=i+1) begin - j = `pilni(i); - { stn[j], t } = { `rotl64(t, `rotci(i)), stn[j] }; - end - - // chi - for (j=0; j<25; j=j+5) begin - - for (i=0; i<5; i=i+1) - bc[i] = stn[j + i]; - - for (i=0; i<5; i=i+1) - stn[j+i] = stn[j+i] ^ (~bc[(i+1)%5] & bc[(i+2)%5]); - end - - // iota - stn[0] = stn[0] ^ `rndci(round); - end - - - /* ready flag logic */ - - reg ready_reg = 'b1; - assign ready = ready_reg; - - always @(posedge clk or negedge nreset) - // - if (!nreset) ready_reg <= 'b1; - else begin - if (ready) ready_reg <= !(init || next); - else ready_reg <= !(round < roundlimit); - end - - /* state update logic */ - always @(posedge clk or negedge nreset) - // - if (!nreset) begin - - for (i=0; i<25; i=i+1) begin - st[i] <= 64'hX; // wipe state - blk[i] <= 64'h0; // wipe block - end - - round <= `SHA3_NUM_ROUNDS; - - end else begin - - if (!ready) begin - - for (i=0; i<25; i=i+1) - st[i] <= stn[i]; - - round <= round + 'd1; - - end else if (init || next) begin - - for (i=0; i<25; i=i+1) - st[i] <= init ? blk[i] : st[i] ^ blk[i]; // init has priority over next - - round <= 'd0; - - end - - if (w && !addr[8]) // only the first half of memory is writeable - // - case (addr[2]) - 1: blk[addr[7:3]][63:32] <= din; - 0: blk[addr[7:3]][31: 0] <= din; - endcase // case (addr[2]) - - end +`define SHA3_NUM_ROUNDS 5'd24 + +module sha3( input wire clk, + input wire nreset, + input wire w, + input wire [ 8:2] addr, + input wire [32-1:0] din, + output reg [32-1:0] dout, + input wire init, + input wire next, + output wire ready); + + integer i, j; + + reg [64-1:0] blk[0:24], // input block + st [0:24], // current state + stn[0:24], // new state + bc [0: 4], // intermediate values + t; // temporary variable + + reg [ 4:0] round; // counter value + + + localparam [ 4: 0] roundlimit = `SHA3_NUM_ROUNDS - 'b1; + + + localparam [24*6-1:0] rotc = + { 6'h01, 6'h03, 6'h06, 6'h0A, 6'h0F, 6'h15, + 6'h1C, 6'h24, 6'h2D, 6'h37, 6'h02, 6'h0E, + 6'h1B, 6'h29, 6'h38, 6'h08, 6'h19, 6'h2B, + 6'h3E, 6'h12, 6'h27, 6'h3D, 6'h14, 6'h2C}; + + localparam [24*5-1:0] piln = + { 5'h0A, 5'h07, 5'h0B, 5'h11, 5'h12, 5'h03, + 5'h05, 5'h10, 5'h08, 5'h15, 5'h18, 5'h04, + 5'h0F, 5'h17, 5'h13, 5'h0D, 5'h0C, 5'h02, + 5'h14, 5'h0E, 5'h16, 5'h09, 5'h06, 5'h01}; + + localparam [24*64-1:0] rndc = + { 64'h0000000000000001, 64'h0000000000008082, + 64'h800000000000808a, 64'h8000000080008000, + 64'h000000000000808b, 64'h0000000080000001, + 64'h8000000080008081, 64'h8000000000008009, + 64'h000000000000008a, 64'h0000000000000088, + 64'h0000000080008009, 64'h000000008000000a, + 64'h000000008000808b, 64'h800000000000008b, + 64'h8000000000008089, 64'h8000000000008003, + 64'h8000000000008002, 64'h8000000000000080, + 64'h000000000000800a, 64'h800000008000000a, + 64'h8000000080008081, 64'h8000000000008080, + 64'h0000000080000001, 64'h8000000080008008}; + + /* input block buffer is mapped to the lower half of the + address space, sponge state is mapped to the upper one */ + + /* the lowest address bit determines what part of 64-bit word to return */ + + always @(posedge clk) + // + dout <= addr[8] ? + (~addr[2] ? st [addr[7:3]][31:0] : st [addr[7:3]][63:32]) : + (~addr[2] ? blk[addr[7:3]][31:0] : blk[addr[7:3]][63:32]) ; + + + always @* begin + + // theta1 + for (i=0; i<25; i=i+1) + stn[i] = st[i]; + + for (i=0; i<5; i=i+1) + bc[i] = stn[i] ^ stn[i+5] ^ stn[i+10] ^ stn[i+15] ^ stn[i+20]; + + // theta2 + for (i=0; i<5; i=i+1) begin + + t = bc[(i+4)%5] ^ `rotl64(bc[(i+1)%5], 1); + + for(j=i; j<25; j=j+5) + stn[j] = t ^ stn[j]; + end + + // rophi + t = stn[1]; + for(i=0; i<24; i=i+1) begin + j = `pilni(i); + { stn[j], t } = { `rotl64(t, `rotci(i)), stn[j] }; + end + + // chi + for (j=0; j<25; j=j+5) begin + + for (i=0; i<5; i=i+1) + bc[i] = stn[j + i]; + + for (i=0; i<5; i=i+1) + stn[j+i] = stn[j+i] ^ (~bc[(i+1)%5] & bc[(i+2)%5]); + end + + // iota + stn[0] = stn[0] ^ `rndci(round); + end + + + /* ready flag logic */ + + reg ready_reg = 'b1; + assign ready = ready_reg; + + always @(posedge clk or negedge nreset) + // + if (!nreset) ready_reg <= 'b1; + else begin + if (ready) ready_reg <= !(init || next); + else ready_reg <= !(round < roundlimit); + end + + /* state update logic */ + always @(posedge clk or negedge nreset) + // + if (!nreset) begin + + for (i=0; i<25; i=i+1) begin + st[i] <= 64'hX; // wipe state + blk[i] <= 64'h0; // wipe block + end + + round <= `SHA3_NUM_ROUNDS; + + end else begin + + if (!ready) begin + + for (i=0; i<25; i=i+1) + st[i] <= stn[i]; + + round <= round + 'd1; + + end else if (init || next) begin + + for (i=0; i<25; i=i+1) + st[i] <= init ? blk[i] : st[i] ^ blk[i]; // init has priority over next + + round <= 'd0; + + end + + if (w && !addr[8]) // only the first half of memory is writeable + // + case (addr[2]) + 1: blk[addr[7:3]][63:32] <= din; + 0: blk[addr[7:3]][31: 0] <= din; + endcase // case (addr[2]) + + end endmodule // sha3 diff --git a/src/rtl/sha3_wrapper.v b/src/rtl/sha3_wrapper.v index 9140b08..c19f64f 100644 --- a/src/rtl/sha3_wrapper.v +++ b/src/rtl/sha3_wrapper.v @@ -48,8 +48,8 @@ module sha3_wrapper // Address Decoder // localparam ADDR_MSB_REGS = 1'b0; - localparam ADDR_MSB_CORE = 1'b1; - + localparam ADDR_MSB_CORE = 1'b1; + wire [0:0] addr_msb = address[7]; wire [6:0] addr_lsb = address[6:0]; @@ -71,7 +71,7 @@ module sha3_wrapper localparam ADDR_CONTROL = 5'h08; // {next, init} localparam ADDR_STATUS = 5'h09; // {valid, ready} - localparam CONTROL_INIT_BIT = 0; + localparam CONTROL_INIT_BIT = 0; localparam CONTROL_NEXT_BIT = 1; // localparam STATUS_READY_BIT = 0; -- hardcoded to always read 1 @@ -86,17 +86,17 @@ module sha3_wrapper // Registers // reg [ 1:0] reg_control; - reg [ 1:0] reg_control_prev; - - - // - // Flags - // - wire reg_control_init_posedge = - reg_control[CONTROL_INIT_BIT] & ~reg_control_prev[CONTROL_INIT_BIT]; + reg [ 1:0] reg_control_prev; + + + // + // Flags + // + wire reg_control_init_posedge = + reg_control[CONTROL_INIT_BIT] & ~reg_control_prev[CONTROL_INIT_BIT]; - wire reg_control_next_posedge = - reg_control[CONTROL_NEXT_BIT] & ~reg_control_prev[CONTROL_NEXT_BIT]; + wire reg_control_next_posedge = + reg_control[CONTROL_NEXT_BIT] & ~reg_control_prev[CONTROL_NEXT_BIT]; // @@ -109,11 +109,11 @@ module sha3_wrapper // SHA-3 // sha3 sha3_inst - ( + ( .clk (clk), - .nreset (rst_n), + .nreset (rst_n), - .init (reg_control_init_posedge), + .init (reg_control_init_posedge), .next (reg_control_next_posedge), .ready (reg_status_valid), @@ -122,7 +122,7 @@ module sha3_wrapper .addr (addr_lsb), .din (write_data), .dout (read_data_core) - ); + ); // @@ -136,8 +136,8 @@ module sha3_wrapper // always @(posedge clk) // - if (!rst_n) reg_control_prev <= 2'b00; - else reg_control_prev <= reg_control; + if (!rst_n) reg_control_prev <= 2'b00; + else reg_control_prev <= reg_control; // @@ -188,7 +188,7 @@ module sha3_wrapper reg addr_msb_last; always @(posedge clk) addr_msb_last <= addr_msb; - assign read_data = (addr_msb_last == ADDR_MSB_REGS) ? tmp_read_data : read_data_core; + assign read_data = (addr_msb_last == ADDR_MSB_REGS) ? tmp_read_data : read_data_core; endmodule diff --git a/stm32/sha3_driver_sample.c b/stm32/sha3_driver_sample.c index 8dcc333..7344ce1 100644 --- a/stm32/sha3_driver_sample.c +++ b/stm32/sha3_driver_sample.c @@ -33,162 +33,162 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - - /* - * Note, that the test program needs a custom bitstream without - * the core selector, where the DUT is at offset 0. - */ - // stm32 headers +/* + * Note, that the test program needs a custom bitstream without + * the core selector, where the DUT is at offset 0. + */ + +// stm32 headers #include #include "stm-init.h" #include "stm-led.h" #include "stm-fmc.h" - // locations of core registers -#define CORE_ADDR_NAME0 (0x00 << 2) -#define CORE_ADDR_NAME1 (0x01 << 2) -#define CORE_ADDR_VERSION (0x02 << 2) -#define CORE_ADDR_CONTROL (0x08 << 2) -#define CORE_ADDR_STATUS (0x09 << 2) - - // control and status register bit maps -#define CORE_CONTROL_BIT_INIT 0x00000001 -#define CORE_CONTROL_BIT_NEXT 0x00000002 - -#define CORE_STATUS_BIT_READY 0x00000001 -#define CORE_STATUS_BIT_VALID 0x00000002 - - // locations of banks (operand buffers) -#define CORE_ADDR_BANK_BLOCK 0x200 -#define CORE_ADDR_BANK_STATE 0x300 - - // sha-3 parameters -#define SHA3_STATE_BITS 1600 -#define SHA3_STATE_BYTES (SHA3_STATE_BITS / 8) - -#define SHA3_PADDING_SUFFIX 0x06 -#define SHA3_PADDING_FINAL 0x80 - -#define SHA3_224_BLOCK_BITS 1152 -#define SHA3_256_BLOCK_BITS 1088 -#define SHA3_384_BLOCK_BITS 832 -#define SHA3_512_BLOCK_BITS 576 - -#define SHA3_224_OUTPUT_BITS 224 -#define SHA3_256_OUTPUT_BITS 256 -#define SHA3_384_OUTPUT_BITS 384 -#define SHA3_512_OUTPUT_BITS 512 - - /* - * test vectors - hashes of empty message - * - * https://en.wikipedia.org/wiki/SHA-3#Examples_of_SHA-3_variants - * - */ -#define SHA3_224_HASH_EMPTY_MSG \ - {0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7, \ - 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab, \ - 0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f, \ - 0x5b, 0x5a, 0x6b, 0xc7} - -#define SHA3_256_HASH_EMPTY_MSG \ - {0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66, \ - 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62, \ - 0xf5, 0x80, 0xff,0x4d, 0xe4, 0x3b, 0x49, 0xfa, \ - 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a} - -#define SHA3_384_HASH_EMPTY_MSG \ - {0x0c, 0x63, 0xa7, 0x5b, 0x84, 0x5e, 0x4f, 0x7d, \ - 0x01, 0x10, 0x7d, 0x85, 0x2e, 0x4c, 0x24, 0x85, \ - 0xc5, 0x1a, 0x50, 0xaa, 0xaa, 0x94, 0xfc, 0x61, \ - 0x99, 0x5e, 0x71, 0xbb, 0xee, 0x98, 0x3a, 0x2a, \ - 0xc3, 0x71, 0x38, 0x31, 0x26, 0x4a, 0xdb, 0x47, \ - 0xfb, 0x6b, 0xd1, 0xe0, 0x58, 0xd5, 0xf0, 0x04} - -#define SHA3_512_HASH_EMPTY_MSG \ - {0xa6, 0x9f, 0x73, 0xcc, 0xa2, 0x3a, 0x9a, 0xc5, \ - 0xc8, 0xb5, 0x67, 0xdc, 0x18, 0x5a, 0x75, 0x6e, \ - 0x97, 0xc9, 0x82, 0x16, 0x4f, 0xe2, 0x58, 0x59, \ - 0xe0, 0xd1, 0xdc, 0xc1, 0x47, 0x5c, 0x80, 0xa6, \ - 0x15, 0xb2, 0x12, 0x3a, 0xf1, 0xf5, 0xf9, 0x4c, \ - 0x11, 0xe3, 0xe9, 0x40, 0x2c, 0x3a, 0xc5, 0x58, \ - 0xf5, 0x00, 0x19, 0x9d, 0x95, 0xb6, 0xd3, 0xe3, \ - 0x01, 0x75, 0x85, 0x86, 0x28, 0x1d, 0xcd, 0x26} - - /* - * test vectors - hashes of short message "abc" - * - * https://www.di-mgt.com.au/sha_testvectors.html - * - */ -#define SHA3_224_HASH_SHORT_MSG \ - {0xe6, 0x42, 0x82, 0x4c, 0x3f, 0x8c, 0xf2, 0x4a, \ - 0xd0, 0x92, 0x34, 0xee, 0x7d, 0x3c, 0x76, 0x6f, \ - 0xc9, 0xa3, 0xa5, 0x16, 0x8d, 0x0c, 0x94, 0xad, \ - 0x73, 0xb4, 0x6f, 0xdf} - -#define SHA3_256_HASH_SHORT_MSG \ - {0x3a, 0x98, 0x5d, 0xa7, 0x4f, 0xe2, 0x25, 0xb2, \ - 0x04, 0x5c, 0x17, 0x2d, 0x6b, 0xd3, 0x90, 0xbd, \ - 0x85, 0x5f, 0x08, 0x6e, 0x3e, 0x9d, 0x52, 0x5b, \ - 0x46, 0xbf, 0xe2, 0x45, 0x11, 0x43, 0x15, 0x32} - -#define SHA3_384_HASH_SHORT_MSG \ - {0xec, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6f, 0xc9, \ - 0x26, 0x45, 0x9f, 0x58, 0xe2, 0xc6, 0xad, 0x8d, \ - 0xf9, 0xb4, 0x73, 0xcb, 0x0f, 0xc0, 0x8c, 0x25, \ - 0x96, 0xda, 0x7c, 0xf0, 0xe4, 0x9b, 0xe4, 0xb2, \ - 0x98, 0xd8, 0x8c, 0xea, 0x92, 0x7a, 0xc7, 0xf5, \ - 0x39, 0xf1, 0xed, 0xf2, 0x28, 0x37, 0x6d, 0x25} - -#define SHA3_512_HASH_SHORT_MSG \ - {0xb7, 0x51, 0x85, 0x0b, 0x1a, 0x57, 0x16, 0x8a, \ - 0x56, 0x93, 0xcd, 0x92, 0x4b, 0x6b, 0x09, 0x6e, \ - 0x08, 0xf6, 0x21, 0x82, 0x74, 0x44, 0xf7, 0x0d, \ - 0x88, 0x4f, 0x5d, 0x02, 0x40, 0xd2, 0x71, 0x2e, \ - 0x10, 0xe1, 0x16, 0xe9, 0x19, 0x2a, 0xf3, 0xc9, \ - 0x1a, 0x7e, 0xc5, 0x76, 0x47, 0xe3, 0x93, 0x40, \ - 0x57, 0x34, 0x0b, 0x4c, 0xf4, 0x08, 0xd5, 0xa5, \ - 0x65, 0x92, 0xf8, 0x27, 0x4e, 0xec, 0x53, 0xf0} - - /* - * test vectors - hashes of long message (see below) - * - * https://csrc.nist.gov/Projects/Cryptographic-Standards-and-Guidelines/example-values - * - */ - -#define SHA3_224_HASH_LONG_MSG \ - {0x93, 0x76, 0x81, 0x6A, 0xBA, 0x50, 0x3F, 0x72, \ - 0xF9, 0x6C, 0xE7, 0xEB, 0x65, 0xAC, 0x09, 0x5D, \ - 0xEE, 0xE3, 0xBE, 0x4B, 0xF9, 0xBB, 0xC2, 0xA1, \ - 0xCB, 0x7E, 0x11, 0xE0} - -#define SHA3_256_HASH_LONG_MSG \ - {0x79, 0xF3, 0x8A, 0xDE, 0xC5, 0xC2, 0x03, 0x07, \ - 0xA9, 0x8E, 0xF7, 0x6E, 0x83, 0x24, 0xAF, 0xBF, \ - 0xD4, 0x6C, 0xFD, 0x81, 0xB2, 0x2E, 0x39, 0x73, \ - 0xC6, 0x5F, 0xA1, 0xBD, 0x9D, 0xE3, 0x17, 0x87} - -#define SHA3_384_HASH_LONG_MSG \ - {0x18, 0x81, 0xDE, 0x2C, 0xA7, 0xE4, 0x1E, 0xF9, \ - 0x5D, 0xC4, 0x73, 0x2B, 0x8F, 0x5F, 0x00, 0x2B, \ - 0x18, 0x9C, 0xC1, 0xE4, 0x2B, 0x74, 0x16, 0x8E, \ - 0xD1, 0x73, 0x26, 0x49, 0xCE, 0x1D, 0xBC, 0xDD, \ - 0x76, 0x19, 0x7A, 0x31, 0xFD, 0x55, 0xEE, 0x98, \ - 0x9F, 0x2D, 0x70, 0x50, 0xDD, 0x47, 0x3E, 0x8F} - -#define SHA3_512_HASH_LONG_MSG \ - {0xE7, 0x6D, 0xFA, 0xD2, 0x20, 0x84, 0xA8, 0xB1, \ - 0x46, 0x7F, 0xCF, 0x2F, 0xFA, 0x58, 0x36, 0x1B, \ - 0xEC, 0x76, 0x28, 0xED, 0xF5, 0xF3, 0xFD, 0xC0, \ - 0xE4, 0x80, 0x5D, 0xC4, 0x8C, 0xAE, 0xEC, 0xA8, \ - 0x1B, 0x7C, 0x13, 0xC3, 0x0A, 0xDF, 0x52, 0xA3, \ - 0x65, 0x95, 0x84, 0x73, 0x9A, 0x2D, 0xF4, 0x6B, \ - 0xE5, 0x89, 0xC5, 0x1C, 0xA1, 0xA4, 0xA8, 0x41, \ - 0x6D, 0xF6, 0x54, 0x5A, 0x1C, 0xE8, 0xBA, 0x00} - +// locations of core registers +#define CORE_ADDR_NAME0 (0x00 << 2) +#define CORE_ADDR_NAME1 (0x01 << 2) +#define CORE_ADDR_VERSION (0x02 << 2) +#define CORE_ADDR_CONTROL (0x08 << 2) +#define CORE_ADDR_STATUS (0x09 << 2) + +// control and status register bit maps +#define CORE_CONTROL_BIT_INIT 0x00000001 +#define CORE_CONTROL_BIT_NEXT 0x00000002 + +#define CORE_STATUS_BIT_READY 0x00000001 +#define CORE_STATUS_BIT_VALID 0x00000002 + +// locations of banks (operand buffers) +#define CORE_ADDR_BANK_BLOCK 0x200 +#define CORE_ADDR_BANK_STATE 0x300 + +// sha-3 parameters +#define SHA3_STATE_BITS 1600 +#define SHA3_STATE_BYTES (SHA3_STATE_BITS / 8) + +#define SHA3_PADDING_SUFFIX 0x06 +#define SHA3_PADDING_FINAL 0x80 + +#define SHA3_224_BLOCK_BITS 1152 +#define SHA3_256_BLOCK_BITS 1088 +#define SHA3_384_BLOCK_BITS 832 +#define SHA3_512_BLOCK_BITS 576 + +#define SHA3_224_OUTPUT_BITS 224 +#define SHA3_256_OUTPUT_BITS 256 +#define SHA3_384_OUTPUT_BITS 384 +#define SHA3_512_OUTPUT_BITS 512 + +/* + * test vectors - hashes of empty message + * + * https://en.wikipedia.org/wiki/SHA-3#Examples_of_SHA-3_variants + * + */ +#define SHA3_224_HASH_EMPTY_MSG \ + {0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7, \ + 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab, \ + 0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f, \ + 0x5b, 0x5a, 0x6b, 0xc7} + +#define SHA3_256_HASH_EMPTY_MSG \ + {0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66, \ + 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62, \ + 0xf5, 0x80,0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa, \ + 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a} + +#define SHA3_384_HASH_EMPTY_MSG \ + {0x0c, 0x63, 0xa7, 0x5b, 0x84, 0x5e, 0x4f, 0x7d, \ + 0x01, 0x10, 0x7d, 0x85, 0x2e, 0x4c, 0x24, 0x85, \ + 0xc5, 0x1a, 0x50, 0xaa, 0xaa, 0x94, 0xfc, 0x61, \ + 0x99, 0x5e, 0x71, 0xbb, 0xee, 0x98, 0x3a, 0x2a, \ + 0xc3, 0x71, 0x38, 0x31, 0x26, 0x4a, 0xdb, 0x47, \ + 0xfb, 0x6b, 0xd1, 0xe0, 0x58, 0xd5, 0xf0, 0x04} + +#define SHA3_512_HASH_EMPTY_MSG \ + {0xa6, 0x9f, 0x73, 0xcc, 0xa2, 0x3a, 0x9a, 0xc5, \ + 0xc8, 0xb5, 0x67, 0xdc, 0x18, 0x5a, 0x75, 0x6e, \ + 0x97, 0xc9, 0x82, 0x16, 0x4f, 0xe2, 0x58, 0x59, \ + 0xe0, 0xd1, 0xdc, 0xc1, 0x47, 0x5c, 0x80, 0xa6, \ + 0x15, 0xb2, 0x12, 0x3a, 0xf1, 0xf5, 0xf9, 0x4c, \ + 0x11, 0xe3, 0xe9, 0x40, 0x2c, 0x3a, 0xc5, 0x58, \ + 0xf5, 0x00, 0x19, 0x9d, 0x95, 0xb6, 0xd3, 0xe3, \ + 0x01, 0x75, 0x85, 0x86, 0x28, 0x1d, 0xcd, 0x26} + +/* + * test vectors - hashes of short message "abc" + * + * https://www.di-mgt.com.au/sha_testvectors.html + * + */ +#define SHA3_224_HASH_SHORT_MSG \ + {0xe6, 0x42, 0x82, 0x4c, 0x3f, 0x8c, 0xf2, 0x4a, \ + 0xd0, 0x92, 0x34, 0xee, 0x7d, 0x3c, 0x76, 0x6f, \ + 0xc9, 0xa3, 0xa5, 0x16, 0x8d, 0x0c, 0x94, 0xad, \ + 0x73, 0xb4, 0x6f, 0xdf} + +#define SHA3_256_HASH_SHORT_MSG \ + {0x3a, 0x98, 0x5d, 0xa7, 0x4f, 0xe2, 0x25, 0xb2, \ + 0x04, 0x5c, 0x17, 0x2d, 0x6b, 0xd3, 0x90, 0xbd, \ + 0x85, 0x5f, 0x08, 0x6e, 0x3e, 0x9d, 0x52, 0x5b, \ + 0x46, 0xbf, 0xe2, 0x45, 0x11, 0x43, 0x15, 0x32} + +#define SHA3_384_HASH_SHORT_MSG \ + {0xec, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6f, 0xc9, \ + 0x26, 0x45, 0x9f, 0x58, 0xe2, 0xc6, 0xad, 0x8d, \ + 0xf9, 0xb4, 0x73, 0xcb, 0x0f, 0xc0, 0x8c, 0x25, \ + 0x96, 0xda, 0x7c, 0xf0, 0xe4, 0x9b, 0xe4, 0xb2, \ + 0x98, 0xd8, 0x8c, 0xea, 0x92, 0x7a, 0xc7, 0xf5, \ + 0x39, 0xf1, 0xed, 0xf2, 0x28, 0x37, 0x6d, 0x25} + +#define SHA3_512_HASH_SHORT_MSG \ + {0xb7, 0x51, 0x85, 0x0b, 0x1a, 0x57, 0x16, 0x8a, \ + 0x56, 0x93, 0xcd, 0x92, 0x4b, 0x6b, 0x09, 0x6e, \ + 0x08, 0xf6, 0x21, 0x82, 0x74, 0x44, 0xf7, 0x0d, \ + 0x88, 0x4f, 0x5d, 0x02, 0x40, 0xd2, 0x71, 0x2e, \ + 0x10, 0xe1, 0x16, 0xe9, 0x19, 0x2a, 0xf3, 0xc9, \ + 0x1a, 0x7e, 0xc5, 0x76, 0x47, 0xe3, 0x93, 0x40, \ + 0x57, 0x34, 0x0b, 0x4c, 0xf4, 0x08, 0xd5, 0xa5, \ + 0x65, 0x92, 0xf8, 0x27, 0x4e, 0xec, 0x53, 0xf0} + +/* + * test vectors - hashes of long message (see below) + * + * https://csrc.nist.gov/Projects/Cryptographic-Standards-and-Guidelines/example-values + * + */ + +#define SHA3_224_HASH_LONG_MSG \ + {0x93, 0x76, 0x81, 0x6A, 0xBA, 0x50, 0x3F, 0x72, \ + 0xF9, 0x6C, 0xE7, 0xEB, 0x65, 0xAC, 0x09, 0x5D, \ + 0xEE, 0xE3, 0xBE, 0x4B, 0xF9, 0xBB, 0xC2, 0xA1, \ + 0xCB, 0x7E, 0x11, 0xE0} + +#define SHA3_256_HASH_LONG_MSG \ + {0x79, 0xF3, 0x8A, 0xDE, 0xC5, 0xC2, 0x03, 0x07, \ + 0xA9, 0x8E, 0xF7, 0x6E, 0x83, 0x24, 0xAF, 0xBF, \ + 0xD4, 0x6C, 0xFD, 0x81, 0xB2, 0x2E, 0x39, 0x73, \ + 0xC6, 0x5F, 0xA1, 0xBD, 0x9D, 0xE3, 0x17, 0x87} + +#define SHA3_384_HASH_LONG_MSG \ + {0x18, 0x81, 0xDE, 0x2C, 0xA7, 0xE4, 0x1E, 0xF9, \ + 0x5D, 0xC4, 0x73, 0x2B, 0x8F, 0x5F, 0x00, 0x2B, \ + 0x18, 0x9C, 0xC1, 0xE4, 0x2B, 0x74, 0x16, 0x8E, \ + 0xD1, 0x73, 0x26, 0x49, 0xCE, 0x1D, 0xBC, 0xDD, \ + 0x76, 0x19, 0x7A, 0x31, 0xFD, 0x55, 0xEE, 0x98, \ + 0x9F, 0x2D, 0x70, 0x50, 0xDD, 0x47, 0x3E, 0x8F} + +#define SHA3_512_HASH_LONG_MSG \ + {0xE7, 0x6D, 0xFA, 0xD2, 0x20, 0x84, 0xA8, 0xB1, \ + 0x46, 0x7F, 0xCF, 0x2F, 0xFA, 0x58, 0x36, 0x1B, \ + 0xEC, 0x76, 0x28, 0xED, 0xF5, 0xF3, 0xFD, 0xC0, \ + 0xE4, 0x80, 0x5D, 0xC4, 0x8C, 0xAE, 0xEC, 0xA8, \ + 0x1B, 0x7C, 0x13, 0xC3, 0x0A, 0xDF, 0x52, 0xA3, \ + 0x65, 0x95, 0x84, 0x73, 0x9A, 0x2D, 0xF4, 0x6B, \ + 0xE5, 0x89, 0xC5, 0x1C, 0xA1, 0xA4, 0xA8, 0x41, \ + 0x6D, 0xF6, 0x54, 0x5A, 0x1C, 0xE8, 0xBA, 0x00} + static const uint8_t hash_224_empty_msg[SHA3_224_OUTPUT_BITS / 8] = SHA3_224_HASH_EMPTY_MSG; static const uint8_t hash_256_empty_msg[SHA3_256_OUTPUT_BITS / 8] = SHA3_256_HASH_EMPTY_MSG; static const uint8_t hash_384_empty_msg[SHA3_384_OUTPUT_BITS / 8] = SHA3_384_HASH_EMPTY_MSG; @@ -203,271 +203,272 @@ static const uint8_t hash_224_long_msg[SHA3_224_OUTPUT_BITS / 8] = SHA3_224_HASH static const uint8_t hash_256_long_msg[SHA3_256_OUTPUT_BITS / 8] = SHA3_256_HASH_LONG_MSG; static const uint8_t hash_384_long_msg[SHA3_384_OUTPUT_BITS / 8] = SHA3_384_HASH_LONG_MSG; static const uint8_t hash_512_long_msg[SHA3_512_OUTPUT_BITS / 8] = SHA3_512_HASH_LONG_MSG; - - /* short message, will always fit in single block */ + +/* short message, will always fit in single block */ static const char msg_short[] = "abc"; - - /* long message, guaranteed to _not_ fit in one block */ + +/* long message, guaranteed to _not_ fit in one block */ static const char msg_long[] = - "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" - "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" - "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" - "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" - "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" - "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" - "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" - "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" - "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" - "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3"; - - - /* - * prototypes - */ + "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" + "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" + "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" + "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" + "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" + "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" + "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" + "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" + "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3" + "\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3\xA3"; + + +/* + * prototypes + */ void toggle_yellow_led(void); -int test_sha3( const uint8_t *msg, - uint32_t num_msg_bytes, - uint32_t num_block_bits, - const uint8_t *hash, - uint32_t num_hash_bits); +int test_sha3(const uint8_t *msg, + uint32_t num_msg_bytes, + uint32_t num_block_bits, + const uint8_t *hash, + uint32_t num_hash_bits); -void sha3_absorb( uint32_t *state, - uint32_t num_block_bytes, - uint32_t block_number); +void sha3_absorb(uint32_t *state, + uint32_t num_block_bytes, + uint32_t block_number); - - /* - * test routine - */ + +/* + * test routine + */ int main() { - int ok; - + int ok; + stm_init(); fmc_init(); - - // turn on the green led + + // turn on the green led led_on(LED_GREEN); led_off(LED_RED); led_off(LED_YELLOW); led_off(LED_BLUE); - // check, that core is present - uint32_t core_name0; - uint32_t core_name1; - uint32_t core_version; - - fmc_read_32(CORE_ADDR_NAME0, &core_name0); - fmc_read_32(CORE_ADDR_NAME1, &core_name1); - fmc_read_32(CORE_ADDR_VERSION, &core_version); - - // must be "sha3", " " [four spaces], "0.10" - if ( (core_name0 != 0x73686133) || - (core_name1 != 0x20202020) || - (core_version != 0x302E3130)) - { - led_off(LED_GREEN); - led_on(LED_RED); - while (1); - } - - // repeat forever - while (1) - { - // fresh start - ok = 1; - - // test with empty message - ok = ok && test_sha3(NULL, 0, SHA3_224_BLOCK_BITS, hash_224_empty_msg, SHA3_224_OUTPUT_BITS); - ok = ok && test_sha3(NULL, 0, SHA3_256_BLOCK_BITS, hash_256_empty_msg, SHA3_256_OUTPUT_BITS); - ok = ok && test_sha3(NULL, 0, SHA3_384_BLOCK_BITS, hash_384_empty_msg, SHA3_384_OUTPUT_BITS); - ok = ok && test_sha3(NULL, 0, SHA3_512_BLOCK_BITS, hash_512_empty_msg, SHA3_512_OUTPUT_BITS); - - // test with the short message ("abc") - ok = ok && test_sha3((uint8_t *)msg_short, strlen(msg_short), SHA3_224_BLOCK_BITS, hash_224_short_msg, SHA3_224_OUTPUT_BITS); - ok = ok && test_sha3((uint8_t *)msg_short, strlen(msg_short), SHA3_256_BLOCK_BITS, hash_256_short_msg, SHA3_256_OUTPUT_BITS); - ok = ok && test_sha3((uint8_t *)msg_short, strlen(msg_short), SHA3_384_BLOCK_BITS, hash_384_short_msg, SHA3_384_OUTPUT_BITS); - ok = ok && test_sha3((uint8_t *)msg_short, strlen(msg_short), SHA3_512_BLOCK_BITS, hash_512_short_msg, SHA3_512_OUTPUT_BITS); - - // test with the long message - ok = ok && test_sha3((uint8_t *)msg_long, strlen(msg_long), SHA3_224_BLOCK_BITS, hash_224_long_msg, SHA3_224_OUTPUT_BITS); - ok = ok && test_sha3((uint8_t *)msg_long, strlen(msg_long), SHA3_256_BLOCK_BITS, hash_256_long_msg, SHA3_256_OUTPUT_BITS); - ok = ok && test_sha3((uint8_t *)msg_long, strlen(msg_long), SHA3_384_BLOCK_BITS, hash_384_long_msg, SHA3_384_OUTPUT_BITS); - ok = ok && test_sha3((uint8_t *)msg_long, strlen(msg_long), SHA3_512_BLOCK_BITS, hash_512_long_msg, SHA3_512_OUTPUT_BITS); - - // turn on the red led to indicate something went wrong - if (!ok) - { led_off(LED_GREEN); - led_on(LED_RED); - } - - // indicate, that we're alive doing something... - toggle_yellow_led(); - } + // check, that core is present + uint32_t core_name0; + uint32_t core_name1; + uint32_t core_version; + + fmc_read_32(CORE_ADDR_NAME0, &core_name0); + fmc_read_32(CORE_ADDR_NAME1, &core_name1); + fmc_read_32(CORE_ADDR_VERSION, &core_version); + + // must be "sha3", " " [four spaces], "0.10" + if ((core_name0 != 0x73686133) || + (core_name1 != 0x20202020) || + (core_version != 0x302E3130)) + { + led_off(LED_GREEN); + led_on(LED_RED); + while (1); + } + + // repeat forever + while (1) + { + // fresh start + ok = 1; + + // test with empty message + ok = ok && test_sha3(NULL, 0, SHA3_224_BLOCK_BITS, hash_224_empty_msg, SHA3_224_OUTPUT_BITS); + ok = ok && test_sha3(NULL, 0, SHA3_256_BLOCK_BITS, hash_256_empty_msg, SHA3_256_OUTPUT_BITS); + ok = ok && test_sha3(NULL, 0, SHA3_384_BLOCK_BITS, hash_384_empty_msg, SHA3_384_OUTPUT_BITS); + ok = ok && test_sha3(NULL, 0, SHA3_512_BLOCK_BITS, hash_512_empty_msg, SHA3_512_OUTPUT_BITS); + + // test with the short message ("abc") + ok = ok && test_sha3((uint8_t *)msg_short, strlen(msg_short), SHA3_224_BLOCK_BITS, hash_224_short_msg, SHA3_224_OUTPUT_BITS); + ok = ok && test_sha3((uint8_t *)msg_short, strlen(msg_short), SHA3_256_BLOCK_BITS, hash_256_short_msg, SHA3_256_OUTPUT_BITS); + ok = ok && test_sha3((uint8_t *)msg_short, strlen(msg_short), SHA3_384_BLOCK_BITS, hash_384_short_msg, SHA3_384_OUTPUT_BITS); + ok = ok && test_sha3((uint8_t *)msg_short, strlen(msg_short), SHA3_512_BLOCK_BITS, hash_512_short_msg, SHA3_512_OUTPUT_BITS); + + // test with the long message + ok = ok && test_sha3((uint8_t *)msg_long, strlen(msg_long), SHA3_224_BLOCK_BITS, hash_224_long_msg, SHA3_224_OUTPUT_BITS); + ok = ok && test_sha3((uint8_t *)msg_long, strlen(msg_long), SHA3_256_BLOCK_BITS, hash_256_long_msg, SHA3_256_OUTPUT_BITS); + ok = ok && test_sha3((uint8_t *)msg_long, strlen(msg_long), SHA3_384_BLOCK_BITS, hash_384_long_msg, SHA3_384_OUTPUT_BITS); + ok = ok && test_sha3((uint8_t *)msg_long, strlen(msg_long), SHA3_512_BLOCK_BITS, hash_512_long_msg, SHA3_512_OUTPUT_BITS); + + // turn on the red led to indicate something went wrong + if (!ok) + { + led_off(LED_GREEN); + led_on(LED_RED); + } + + // indicate, that we're alive doing something... + toggle_yellow_led(); + } } -int test_sha3( const uint8_t *msg, - uint32_t num_msg_bytes, - uint32_t num_block_bits, - const uint8_t *hash, - uint32_t num_hash_bits) +int test_sha3(const uint8_t *msg, + uint32_t num_msg_bytes, + uint32_t num_block_bits, + const uint8_t *hash, + uint32_t num_hash_bits) { - /* calculate digest of 'msg' and compare it against known reference 'hash' */ - - // counter - uint32_t i; - - // buffer for input block, consists of 32-bit words to ease copying over FMC - uint32_t block32[SHA3_STATE_BYTES / 4]; - - // byte pointer, handy for storing one byte at a time - uint8_t *block = (uint8_t *)&block32; - - // handy values - uint32_t num_block_bytes = num_block_bits >> 3; // /8 - uint32_t num_hash_bytes = num_hash_bits >> 3; // /8 - - // counters - uint32_t block_number = 0; // number of blocks absorbed (we need this, because for the - // very first block we toggle the 'init' control bit, for all the - // subsequent blocks we toggle the 'next' bit) - - uint32_t block_offset = 0; // current byte position in the input block (we need this to - // apply padding properly) - - // first wipe entire input block... - for (i=0; i<(SHA3_STATE_BYTES / sizeof(uint32_t)); i++) - block32[i] = 0; - - // ...then absorb all the bytes... - while (num_msg_bytes) - { - // store the next byte - block[block_offset] = msg[0]; - - msg++; // advance pointer - block_offset++; // increment block offset - num_msg_bytes--; // reduce remaining byte count - - // check, whether we've already filled entire block - if (block_offset == num_block_bytes) - { - // absorb part of message accumulated in block - sha3_absorb(block32, num_block_bytes, block_number); - - block_number++; // increment processed block count - block_offset = 0; // start filling a new block - } - - } - - // ...and finally apply padding - - // Now do the required padding, block_offset points to the very first empty byte in block - // (there should be at least 1 empty byte now, because we would have processed completely - // filled block earlier while absorbing bytes). - - /* Padding involves three steps: - * - * 1. Add "011" bit string (0x06) to the message ("01" is SHA-3 domain suffix, "1" is actual padding) - * 2. Add zero or more "0" bits until the message is exactly 1 bit short of full block - * 3. Add final "1" bit (0x80) to make the message length a multiple of block size - * - */ - - // add "011" part - block[block_offset] = SHA3_PADDING_SUFFIX; - - // wipe all the remaining bytes in block (if there are any) - while (block_offset < (num_block_bytes - 1)) - { - block_offset++; - block[block_offset] = 0x00; - } - - - // add the final "1" part. note, that we must use |=, not just =, - // because we could have added no extra null bytes and state[block_offset] - // might already contain the suffix, we should not overwrite it. - block[block_offset] |= SHA3_PADDING_FINAL; - - // absorb the last block with padding - sha3_absorb(block32, num_block_bytes, block_number); - - // read state from core... - for (i=0; i<(num_hash_bytes / sizeof(uint32_t)); i++) - fmc_read_32(CORE_ADDR_BANK_STATE + i * sizeof(uint32_t), block32 + i); - - // ...and now compare state to known good hash - for (i=0; i> 3; // /8 + uint32_t num_hash_bytes = num_hash_bits >> 3; // /8 + + // counters + uint32_t block_number = 0; // number of blocks absorbed (we need this, because for the + // very first block we toggle the 'init' control bit, for all the + // subsequent blocks we toggle the 'next' bit) + + uint32_t block_offset = 0; // current byte position in the input block (we need this to + // apply padding properly) + + // first wipe entire input block... + for (i=0; i<(SHA3_STATE_BYTES / sizeof(uint32_t)); i++) + block32[i] = 0; + + // ...then absorb all the bytes... + while (num_msg_bytes) + { + // store the next byte + block[block_offset] = msg[0]; + + msg++; // advance pointer + block_offset++; // increment block offset + num_msg_bytes--; // reduce remaining byte count + + // check, whether we've already filled entire block + if (block_offset == num_block_bytes) + { + // absorb part of message accumulated in block + sha3_absorb(block32, num_block_bytes, block_number); + + block_number++; // increment processed block count + block_offset = 0; // start filling a new block + } + + } + + // ...and finally apply padding + + // Now do the required padding, block_offset points to the very first empty byte in block + // (there should be at least 1 empty byte now, because we would have processed completely + // filled block earlier while absorbing bytes). + + /* Padding involves three steps: + * + * 1. Add "011" bit string (0x06) to the message ("01" is SHA-3 domain suffix, "1" is actual padding) + * 2. Add zero or more "0" bits until the message is exactly 1 bit short of full block + * 3. Add final "1" bit (0x80) to make the message length a multiple of block size + * + */ + + // add "011" part + block[block_offset] = SHA3_PADDING_SUFFIX; + + // wipe all the remaining bytes in block (if there are any) + while (block_offset < (num_block_bytes - 1)) + { + block_offset++; + block[block_offset] = 0x00; + } + + + // add the final "1" part. note, that we must use |=, not just =, + // because we could have added no extra null bytes and state[block_offset] + // might already contain the suffix, we should not overwrite it. + block[block_offset] |= SHA3_PADDING_FINAL; + + // absorb the last block with padding + sha3_absorb(block32, num_block_bytes, block_number); + + // read state from core... + for (i=0; i<(num_hash_bytes / sizeof(uint32_t)); i++) + fmc_read_32(CORE_ADDR_BANK_STATE + i * sizeof(uint32_t), block32 + i); + + // ...and now compare state to known good hash + for (i=0; i 0) ? CORE_CONTROL_BIT_NEXT : CORE_CONTROL_BIT_INIT; - fmc_write_32(CORE_ADDR_CONTROL, &ctrl); - - // wait for 'valid' bit to be set - sts = 0; - while (!(sts & CORE_STATUS_BIT_VALID)) - fmc_read_32(CORE_ADDR_STATUS, &sts); + uint32_t i; // word counter + uint32_t ctrl, sts; // control register, status register + + // copy 32-bit words from state into core's input block buffer + for (i=0; i<(num_block_bytes / sizeof(uint32_t)); i++) + fmc_write_32(CORE_ADDR_BANK_BLOCK + i * sizeof(uint32_t), block + i); + + // note, that the very first block needs special handling: 'init' bit copies + // input block into core's state, 'next' bit xor's current core's state with input block + + // block has enough space for entire core state, lower words are filled with + // message and upper words remain zeroes. When the very first block is absorbed + // into the sponge, we need to initialize *all* the core's state bits, because the + // upper part of core's state may contain leftovers from previously absorbed data. + + // for subsequent blocks we don't need to copy the upper null part of block into the input + // bank, because we've already filled it with zeroes for the very first block + + if (block_number == 0) + { + for (; i<(SHA3_STATE_BYTES / sizeof(uint32_t)); i++) + fmc_write_32(CORE_ADDR_BANK_BLOCK + i * sizeof(uint32_t), block + i); + } + + // CONTROL = 0 + ctrl = 0; + fmc_write_32(CORE_ADDR_CONTROL, &ctrl); + + // determine what control bit to set ('init' for the very first block, + // 'next' for all the subsequent blocks) + ctrl = (block_number > 0) ? CORE_CONTROL_BIT_NEXT : CORE_CONTROL_BIT_INIT; + fmc_write_32(CORE_ADDR_CONTROL, &ctrl); + + // wait for 'valid' bit to be set + sts = 0; + while (!(sts & CORE_STATUS_BIT_VALID)) + fmc_read_32(CORE_ADDR_STATUS, &sts); } - // - // toggle the yellow led to indicate that we're not stuck somewhere - // +// +// toggle the yellow led to indicate that we're not stuck somewhere +// void toggle_yellow_led(void) { - static int led_state = 0; - - led_state = !led_state; - - if (led_state) led_on(LED_YELLOW); - else led_off(LED_YELLOW); + static int led_state = 0; + + led_state = !led_state; + + if (led_state) led_on(LED_YELLOW); + else led_off(LED_YELLOW); } - // - // end of file - // +// +// end of file +// -- cgit v1.2.3