Add blake2s core

Signed-off-by: Joachim Strömbergson <joachim@assured.se>
This commit is contained in:
Joachim Strömbergson 2023-09-08 14:52:40 +02:00
parent 1ab36c7c83
commit 6e6c2ab3ca
No known key found for this signature in database
GPG Key ID: 865B8A548EA61679
6 changed files with 1483 additions and 1 deletions

View File

@ -66,7 +66,11 @@ VERILOG_SRCS = \
$(P)/core/uart/rtl/uart_core.v \
$(P)/core/uart/rtl/uart_fifo.v \
$(P)/core/uart/rtl/uart.v \
$(P)/core/trng/rtl/rosc.v
$(P)/core/trng/rtl/rosc.v \
$(P)/core/blake2s/rtl/blake2s_core.v \
$(P)/core/blake2s/rtl/blake2s_G.v \
$(P)/core/blake2s/rtl/blake2s_m_select.v \
$(P)/core/blake2s/rtl/blake2s.v \
FIRMWARE_DEPS = \
$(P)/fw/tk1_mem.h \

View File

@ -0,0 +1,230 @@
//======================================================================
//
// blake2s.v
// --------
// Top level wrapper for the blake2s hash function core providing
// a simple memory like interface with 32 bit data access.
//
//
// Author: Joachim Strömbergson// Copyright (c) 2018, Assured AB
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module blake2s(
input wire clk,
input wire reset_n,
input wire cs,
input wire we,
input wire [7 : 0] address,
input wire [31 : 0] write_data,
output wire [31 : 0] read_data
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
localparam ADDR_NAME0 = 8'h00;
localparam ADDR_NAME1 = 8'h01;
localparam ADDR_VERSION = 8'h02;
localparam ADDR_CTRL = 8'h08;
localparam CTRL_INIT_BIT = 0;
localparam CTRL_UPDATE_BIT = 1;
localparam CTRL_FINISH_BIT = 2;
localparam ADDR_STATUS = 8'h09;
localparam STATUS_READY_BIT = 0;
localparam ADDR_BLOCKLEN = 8'h0a;
localparam ADDR_BLOCK0 = 8'h10;
localparam ADDR_BLOCK15 = 8'h1f;
localparam ADDR_DIGEST0 = 8'h40;
localparam ADDR_DIGEST7 = 8'h47;
localparam CORE_NAME0 = 32'h626c616b; // "blak"
localparam CORE_NAME1 = 32'h65327320; // "e2s "
localparam CORE_VERSION = 32'h302e3830; // "0.80"
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg init_reg;
reg init_new;
reg update_reg;
reg update_new;
reg finish_reg;
reg finish_new;
reg [6 : 0] blocklen_reg;
reg blocklen_we;
reg [31 : 0] block_mem [0 : 15];
reg block_mem_we;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
wire core_ready;
wire [511 : 0] core_block;
wire [255 : 0] core_digest;
reg [31 : 0] tmp_read_data;
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign core_block = {block_mem[0], block_mem[1], block_mem[2], block_mem[3],
block_mem[4], block_mem[5], block_mem[6], block_mem[7],
block_mem[8], block_mem[9], block_mem[10], block_mem[11],
block_mem[12], block_mem[13], block_mem[14], block_mem[15]};
assign read_data = tmp_read_data;
//----------------------------------------------------------------
// core instantiation.
//----------------------------------------------------------------
blake2s_core core(
.clk(clk),
.reset_n(reset_n),
.init(init_reg),
.update(update_reg),
.finish(finish_reg),
.block(core_block),
.blocklen(blocklen_reg),
.digest(core_digest),
.ready(core_ready)
);
//----------------------------------------------------------------
// reg_update
//----------------------------------------------------------------
always @ (posedge clk)
begin : reg_update
integer i;
if (!reset_n)
begin
for (i = 0 ; i < 16 ; i = i + 1)
block_mem[i] <= 32'h0;
init_reg <= 1'h0;
update_reg <= 1'h0;
finish_reg <= 1'h0;
blocklen_reg <= 7'h0;
end
else
begin
init_reg <= init_new;
update_reg <= update_new;
finish_reg <= finish_new;
if (blocklen_we) begin
blocklen_reg <= write_data[6 : 0];
end
if (block_mem_we) begin
block_mem[address[3 : 0]] <= write_data;
end
end
end // reg_update
//----------------------------------------------------------------
// api
// The interface command decoding logic.
//----------------------------------------------------------------
always @*
begin : api
init_new = 1'h0;
update_new = 1'h0;
finish_new = 1'h0;
block_mem_we = 1'h0;
blocklen_we = 1'h0;
tmp_read_data = 32'h0;
if (cs)
begin
if (we)
begin
if (address == ADDR_CTRL) begin
init_new = write_data[CTRL_INIT_BIT];
update_new = write_data[CTRL_UPDATE_BIT];
finish_new = write_data[CTRL_FINISH_BIT];
end
if (address == ADDR_BLOCKLEN) begin
blocklen_we = 1;
end
if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK15)) begin
block_mem_we = 1;
end
end
else
begin
if (address == ADDR_NAME0) begin
tmp_read_data = CORE_NAME0;
end
if (address == ADDR_NAME1) begin
tmp_read_data = CORE_NAME1;
end
if (address == ADDR_VERSION) begin
tmp_read_data = CORE_VERSION;
end
if (address == ADDR_STATUS) begin
tmp_read_data = {31'h0, core_ready};
end
if ((address >= ADDR_DIGEST0) && (address <= ADDR_DIGEST7)) begin
tmp_read_data = core_digest[(7 - (address - ADDR_DIGEST0)) * 32 +: 32];
end
end
end
end // api
endmodule // blake2s
//======================================================================
// EOF blake2s.v
//======================================================================

View File

@ -0,0 +1,112 @@
//======================================================================
//
// blake2s_G.v
// -----------
// Verilog 2001 implementation of the G function in the
// blake2s hash function core. This is pure combinational logic in a
// separade module to allow us to build versions with 1, 2, 4
// and even 8 parallel compression functions.
//
//
// Author: Joachim Strömbergson
// Copyright (c) 2018, Assured AB
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module blake2s_G(
input wire [31 : 0] a,
input wire [31 : 0] b,
input wire [31 : 0] c,
input wire [31 : 0] d,
input wire [31 : 0] m0,
input wire [31 : 0] m1,
output wire [31 : 0] a_prim,
output wire [31 : 0] b_prim,
output wire [31 : 0] c_prim,
output wire [31 : 0] d_prim
);
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg [31 : 0] a1;
reg [31 : 0] a2;
reg [31 : 0] b1;
reg [31 : 0] b2;
reg [31 : 0] b3;
reg [31 : 0] b4;
reg [31 : 0] c1;
reg [31 : 0] c2;
reg [31 : 0] d1;
reg [31 : 0] d2;
reg [31 : 0] d3;
reg [31 : 0] d4;
//----------------------------------------------------------------
// Concurrent connectivity for ports.
//----------------------------------------------------------------
assign a_prim = a2;
assign b_prim = b4;
assign c_prim = c2;
assign d_prim = d4;
//----------------------------------------------------------------
// G_function
//----------------------------------------------------------------
always @*
begin : G_function
a1 = a + b + m0;
d1 = d ^ a1;
d2 = {d1[15 : 0], d1[31 : 16]};
c1 = c + d2;
b1 = b ^ c1;
b2 = {b1[11 : 0], b1[31 : 12]};
a2 = a1 + b2 + m1;
d3 = d2 ^ a2;
d4 = {d3[7 : 0], d3[31 : 8]};
c2 = c1 + d4;
b3 = b2 ^ c2;
b4 = {b3[6 : 0], b3[31 : 7]};
end // G_function
endmodule // blake2s_G
//======================================================================
// EOF blake2s_G.v
//======================================================================

View File

@ -0,0 +1,713 @@
//======================================================================
//
// blake2s_core.v
// --------------
// Verilog 2001 implementation of the hash function blake2s.
// This is the internal core with wide interfaces.
//
//
// Author: Joachim Strömbergson
// Copyright (c) 2018, Assured AB
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module blake2s_core(
input wire clk,
input wire reset_n,
input wire init,
input wire update,
input wire finish,
input wire [511 : 0] block,
input wire [6 : 0] blocklen,
output wire [255 : 0] digest,
output wire ready
);
//----------------------------------------------------------------
// Parameter block.
// See BLAKE2 paper and RFC 7693 for definition.
// Chapter 2.8 in https://blake2.net/blake2.pdf
// Section 2.5 in https://tools.ietf.org/html/rfc7693
//----------------------------------------------------------------
// The digest length in bytes. Minimum: 1, Maximum: 32
localparam [7 : 0] DIGEST_LENGTH = 8'd32;
localparam [7 : 0] KEY_LENGTH = 8'd0;
localparam [7 : 0] FANOUT = 8'd1;
localparam [7 : 0] DEPTH = 8'd01;
localparam [31 : 0] LEAF_LENGTH = 32'd0;
localparam [47 : 0] NODE_OFFSET = 48'd0;
localparam [7 : 0] NODE_DEPTH = 8'd0;
localparam [7 : 0] INNER_LENGTH = 8'd0;
localparam [63 : 0] SALT = 64'h0;
localparam [63 : 0] PERSONALIZATION = 64'h0;
wire [255 : 0] parameter_block = {PERSONALIZATION, SALT, INNER_LENGTH,
NODE_DEPTH, NODE_OFFSET, LEAF_LENGTH,
DEPTH, FANOUT, KEY_LENGTH, DIGEST_LENGTH};
//----------------------------------------------------------------
// Internal constant definitions.
//----------------------------------------------------------------
localparam NUM_ROUNDS = 10;
localparam BLOCK_BYTES = 7'd64;
// G function modes.
localparam G_ROW = 1'h0;
localparam G_DIAGONAL = 1'h1;
// Initial vectors.
localparam IV0 = 32'h6a09e667;
localparam IV1 = 32'hbb67ae85;
localparam IV2 = 32'h3c6ef372;
localparam IV3 = 32'ha54ff53a;
localparam IV4 = 32'h510e527f;
localparam IV5 = 32'h9b05688c;
localparam IV6 = 32'h1f83d9ab;
localparam IV7 = 32'h5be0cd19;
// Control FSM state names.
localparam CTRL_IDLE = 3'h0;
localparam CTRL_INIT_ROUND = 3'h1;
localparam CTRL_G_ROW = 3'h2;
localparam CTRL_G_DIAGONAL = 3'h3;
localparam CTRL_COMP_DONE = 3'h4;
localparam CTRL_FINISH = 3'h5;
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg [31 : 0] h_reg [0 : 7];
reg [31 : 0] h_new [0 : 7];
reg h_we;
reg [31 : 0] v_reg [0 : 15];
reg [31 : 0] v_new [0 : 15];
reg v_we;
reg init_v;
reg update_v;
reg [3 : 0] round_ctr_reg;
reg [3 : 0] round_ctr_new;
reg round_ctr_we;
reg round_ctr_inc;
reg round_ctr_rst;
reg [31 : 0] t0_reg;
reg [31 : 0] t0_new;
reg t0_we;
reg [31 : 0] t1_reg;
reg [31 : 0] t1_new;
reg t1_we;
reg t_ctr_inc;
reg t_ctr_rst;
reg last_reg;
reg last_new;
reg last_we;
reg ready_reg;
reg ready_new;
reg ready_we;
reg [2 : 0] blake2s_ctrl_reg;
reg [2 : 0] blake2s_ctrl_new;
reg blake2s_ctrl_we;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg init_state;
reg update_state;
reg load_m;
reg G_mode;
reg [31 : 0] G0_a;
reg [31 : 0] G0_b;
reg [31 : 0] G0_c;
reg [31 : 0] G0_d;
wire [31 : 0] G0_m0;
wire [31 : 0] G0_m1;
wire [31 : 0] G0_a_prim;
wire [31 : 0] G0_b_prim;
wire [31 : 0] G0_c_prim;
wire [31 : 0] G0_d_prim;
reg [31 : 0] G1_a;
reg [31 : 0] G1_b;
reg [31 : 0] G1_c;
reg [31 : 0] G1_d;
wire [31 : 0] G1_m0;
wire [31 : 0] G1_m1;
wire [31 : 0] G1_a_prim;
wire [31 : 0] G1_b_prim;
wire [31 : 0] G1_c_prim;
wire [31 : 0] G1_d_prim;
reg [31 : 0] G2_a;
reg [31 : 0] G2_b;
reg [31 : 0] G2_c;
reg [31 : 0] G2_d;
wire [31 : 0] G2_m0;
wire [31 : 0] G2_m1;
wire [31 : 0] G2_a_prim;
wire [31 : 0] G2_b_prim;
wire [31 : 0] G2_c_prim;
wire [31 : 0] G2_d_prim;
reg [31 : 0] G3_a;
reg [31 : 0] G3_b;
reg [31 : 0] G3_c;
reg [31 : 0] G3_d;
wire [31 : 0] G3_m0;
wire [31 : 0] G3_m1;
wire [31 : 0] G3_a_prim;
wire [31 : 0] G3_b_prim;
wire [31 : 0] G3_c_prim;
wire [31 : 0] G3_d_prim;
//----------------------------------------------------------------
// Module instantations.
//----------------------------------------------------------------
blake2s_m_select mselect(
.clk(clk),
.reset_n(reset_n),
.load(load_m),
.m(block),
.round(round_ctr_reg),
.mode(G_mode),
.G0_m0(G0_m0),
.G0_m1(G0_m1),
.G1_m0(G1_m0),
.G1_m1(G1_m1),
.G2_m0(G2_m0),
.G2_m1(G2_m1),
.G3_m0(G3_m0),
.G3_m1(G3_m1)
);
blake2s_G G0(
.a(G0_a),
.b(G0_b),
.c(G0_c),
.d(G0_d),
.m0(G0_m0),
.m1(G0_m1),
.a_prim(G0_a_prim),
.b_prim(G0_b_prim),
.c_prim(G0_c_prim),
.d_prim(G0_d_prim)
);
blake2s_G G1(
.a(G1_a),
.b(G1_b),
.c(G1_c),
.d(G1_d),
.m0(G1_m0),
.m1(G1_m1),
.a_prim(G1_a_prim),
.b_prim(G1_b_prim),
.c_prim(G1_c_prim),
.d_prim(G1_d_prim)
);
blake2s_G G2(
.a(G2_a),
.b(G2_b),
.c(G2_c),
.d(G2_d),
.m0(G2_m0),
.m1(G2_m1),
.a_prim(G2_a_prim),
.b_prim(G2_b_prim),
.c_prim(G2_c_prim),
.d_prim(G2_d_prim)
);
blake2s_G G3(
.a(G3_a),
.b(G3_b),
.c(G3_c),
.d(G3_d),
.m0(G3_m0),
.m1(G3_m1),
.a_prim(G3_a_prim),
.b_prim(G3_b_prim),
.c_prim(G3_c_prim),
.d_prim(G3_d_prim)
);
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign digest = {h_reg[0][7 : 0], h_reg[0][15 : 8], h_reg[0][23 : 16], h_reg[0][31 : 24],
h_reg[1][7 : 0], h_reg[1][15 : 8], h_reg[1][23 : 16], h_reg[1][31 : 24],
h_reg[2][7 : 0], h_reg[2][15 : 8], h_reg[2][23 : 16], h_reg[2][31 : 24],
h_reg[3][7 : 0], h_reg[3][15 : 8], h_reg[3][23 : 16], h_reg[3][31 : 24],
h_reg[4][7 : 0], h_reg[4][15 : 8], h_reg[4][23 : 16], h_reg[4][31 : 24],
h_reg[5][7 : 0], h_reg[5][15 : 8], h_reg[5][23 : 16], h_reg[5][31 : 24],
h_reg[6][7 : 0], h_reg[6][15 : 8], h_reg[6][23 : 16], h_reg[6][31 : 24],
h_reg[7][7 : 0], h_reg[7][15 : 8], h_reg[7][23 : 16], h_reg[7][31 : 24]};
assign ready = ready_reg;
//----------------------------------------------------------------
// reg_update
//----------------------------------------------------------------
always @ (posedge clk)
begin : reg_update
integer i;
if (!reset_n) begin
for (i = 0; i < 8; i = i + 1) begin
h_reg[i] <= 32'h0;
end
for (i = 0; i < 16; i = i + 1) begin
v_reg[i] <= 32'h0;
end
t0_reg <= 32'h0;
t1_reg <= 32'h0;
last_reg <= 1'h0;
ready_reg <= 1'h1;
round_ctr_reg <= 4'h0;
blake2s_ctrl_reg <= CTRL_IDLE;
end
else begin
if (h_we) begin
for (i = 0; i < 8; i = i + 1) begin
h_reg[i] <= h_new[i];
end
end
if (v_we) begin
for (i = 0; i < 16; i = i + 1) begin
v_reg[i] <= v_new[i];
end
end
if (t0_we) begin
t0_reg <= t0_new;
end
if (t1_we) begin
t1_reg <= t1_new;
end
if (last_we) begin
last_reg <= last_new;
end
if (ready_we) begin
ready_reg <= ready_new;
end
if (round_ctr_we) begin
round_ctr_reg <= round_ctr_new;
end
if (blake2s_ctrl_we) begin
blake2s_ctrl_reg <= blake2s_ctrl_new;
end
end
end // reg_update
//----------------------------------------------------------------
// state_logic
//
// Logic for updating the hash state.
//----------------------------------------------------------------
always @*
begin : state_logic
integer i;
for (i = 0; i < 8; i = i + 1) begin
h_new[i] = 32'h0;
end
h_we = 1'h0;
if (init_state) begin
h_new[0] = IV0 ^ parameter_block[31 : 0];
h_new[1] = IV1 ^ parameter_block[63 : 32];
h_new[2] = IV2 ^ parameter_block[95 : 64];
h_new[3] = IV3 ^ parameter_block[127 : 96];
h_new[4] = IV4 ^ parameter_block[159 : 128];
h_new[5] = IV5 ^ parameter_block[191 : 160];
h_new[6] = IV6 ^ parameter_block[223 : 192];
h_new[7] = IV7 ^ parameter_block[255 : 224];
h_we = 1;
end
if (update_state) begin
h_new[0] = h_reg[0] ^ v_reg[0] ^ v_reg[8];
h_new[1] = h_reg[1] ^ v_reg[1] ^ v_reg[9];
h_new[2] = h_reg[2] ^ v_reg[2] ^ v_reg[10];
h_new[3] = h_reg[3] ^ v_reg[3] ^ v_reg[11];
h_new[4] = h_reg[4] ^ v_reg[4] ^ v_reg[12];
h_new[5] = h_reg[5] ^ v_reg[5] ^ v_reg[13];
h_new[6] = h_reg[6] ^ v_reg[6] ^ v_reg[14];
h_new[7] = h_reg[7] ^ v_reg[7] ^ v_reg[15];
h_we = 1;
end
end // state_logic
//----------------------------------------------------------------
// compress_logic
//----------------------------------------------------------------
always @*
begin : compress_logic
integer i;
for (i = 0; i < 16; i = i + 1) begin
v_new[i] = 32'h0;
end
v_we = 1'h0;
G0_a = 32'h0;
G0_b = 32'h0;
G0_c = 32'h0;
G0_d = 32'h0;
G1_a = 32'h0;
G1_b = 32'h0;
G1_c = 32'h0;
G1_d = 32'h0;
G2_a = 32'h0;
G2_b = 32'h0;
G2_c = 32'h0;
G2_d = 32'h0;
G3_a = 32'h0;
G3_b = 32'h0;
G3_c = 32'h0;
G3_d = 32'h0;
if (init_v)
begin
v_new[0] = h_reg[0];
v_new[1] = h_reg[1];
v_new[2] = h_reg[2];
v_new[3] = h_reg[3];
v_new[4] = h_reg[4];
v_new[5] = h_reg[5];
v_new[6] = h_reg[6];
v_new[7] = h_reg[7];
v_new[8] = IV0;
v_new[9] = IV1;
v_new[10] = IV2;
v_new[11] = IV3;
v_new[12] = t0_reg ^ IV4;
v_new[13] = t1_reg ^ IV5;
if (last_reg) begin
v_new[14] = ~IV6;
end else begin
v_new[14] = IV6;
end
v_new[15] = IV7;
v_we = 1;
end
if (update_v)
begin
v_we = 1;
if (G_mode == G_ROW) begin
// Row updates.
G0_a = v_reg[0];
G0_b = v_reg[4];
G0_c = v_reg[8];
G0_d = v_reg[12];
v_new[0] = G0_a_prim;
v_new[4] = G0_b_prim;
v_new[8] = G0_c_prim;
v_new[12] = G0_d_prim;
G1_a = v_reg[1];
G1_b = v_reg[5];
G1_c = v_reg[9];
G1_d = v_reg[13];
v_new[1] = G1_a_prim;
v_new[5] = G1_b_prim;
v_new[9] = G1_c_prim;
v_new[13] = G1_d_prim;
G2_a = v_reg[2];
G2_b = v_reg[6];
G2_c = v_reg[10];
G2_d = v_reg[14];
v_new[2] = G2_a_prim;
v_new[6] = G2_b_prim;
v_new[10] = G2_c_prim;
v_new[14] = G2_d_prim;
G3_a = v_reg[3];
G3_b = v_reg[7];
G3_c = v_reg[11];
G3_d = v_reg[15];
v_new[3] = G3_a_prim;
v_new[7] = G3_b_prim;
v_new[11] = G3_c_prim;
v_new[15] = G3_d_prim;
end
else begin
// Diagonal updates.
G0_a = v_reg[0];
G0_b = v_reg[5];
G0_c = v_reg[10];
G0_d = v_reg[15];
v_new[0] = G0_a_prim;
v_new[5] = G0_b_prim;
v_new[10] = G0_c_prim;
v_new[15] = G0_d_prim;
G1_a = v_reg[1];
G1_b = v_reg[6];
G1_c = v_reg[11];
G1_d = v_reg[12];
v_new[1] = G1_a_prim;
v_new[6] = G1_b_prim;
v_new[11] = G1_c_prim;
v_new[12] = G1_d_prim;
G2_a = v_reg[2];
G2_b = v_reg[7];
G2_c = v_reg[8];
G2_d = v_reg[13];
v_new[2] = G2_a_prim;
v_new[7] = G2_b_prim;
v_new[8] = G2_c_prim;
v_new[13] = G2_d_prim;
G3_a = v_reg[3];
G3_b = v_reg[4];
G3_c = v_reg[9];
G3_d = v_reg[14];
v_new[3] = G3_a_prim;
v_new[4] = G3_b_prim;
v_new[9] = G3_c_prim;
v_new[14] = G3_d_prim;
end
end // if (update_v)
end // compress_logic
//----------------------------------------------------------------
// t_ctr
// Update logic for the length counter t, a monotonically
// increasing counter with reset.
//----------------------------------------------------------------
always @*
begin : t_ctr
t0_new = 32'h0;
t0_we = 1'h0;
t1_new = 32'h0;
t1_we = 1'h0;
if (t_ctr_rst) begin
t0_new = 32'h0;
t0_we = 1'h1;
t1_new = 32'h0;
t1_we = 1'h1;
end
if (t_ctr_inc) begin
t0_we = 1'h1;
if (last_new) begin
t0_new = t0_reg + {25'h0, blocklen};
end else begin
t0_new = t0_reg + {25'h0, BLOCK_BYTES};
end
if (t0_new < t0_reg) begin
t1_new = t1_reg + 1'h1;
t1_we = 1'h1;
end
end
end // t_ctr
//----------------------------------------------------------------
// round_ctr
// Update logic for the round counter, a monotonically
// increasing counter with reset.
//----------------------------------------------------------------
always @*
begin : round_ctr
round_ctr_new = 4'h0;
round_ctr_we = 1'h0;
if (round_ctr_rst)
begin
round_ctr_new = 4'h0;
round_ctr_we = 1'h1;
end
if (round_ctr_inc)
begin
round_ctr_new = round_ctr_reg + 1'b1;
round_ctr_we = 1'h1;
end
end // round_ctr
//----------------------------------------------------------------
// blake2s_ctrl
//----------------------------------------------------------------
always @*
begin : blake2s_ctrl
init_state = 1'h0;
update_state = 1'h0;
init_v = 1'h0;
update_v = 1'h0;
load_m = 1'h0;
G_mode = G_ROW;
round_ctr_inc = 1'h0;
round_ctr_rst = 1'h0;
t_ctr_inc = 1'h0;
t_ctr_rst = 1'h0;
last_new = 1'h0;
last_we = 1'h0;
ready_new = 1'h0;
ready_we = 1'h0;
blake2s_ctrl_new = CTRL_IDLE;
blake2s_ctrl_we = 1'h0;
case (blake2s_ctrl_reg)
CTRL_IDLE: begin
if (init) begin
last_new = 1'h0;
last_we = 1'h1;
init_state = 1'h1;
t_ctr_rst = 1'h1;
ready_new = 1'h0;
ready_we = 1'h1;
blake2s_ctrl_new = CTRL_FINISH;
blake2s_ctrl_we = 1'h1;
end
if (update) begin
if (blocklen == BLOCK_BYTES) begin
load_m = 1'h1;
t_ctr_inc = 1'h1;
ready_new = 1'h0;
ready_we = 1'h1;
blake2s_ctrl_new = CTRL_INIT_ROUND;
blake2s_ctrl_we = 1'h1;
end
end
if (finish) begin
load_m = 1'h1;
t_ctr_inc = 1'h1;
last_new = 1'h1;
last_we = 1'h1;
ready_new = 1'h0;
ready_we = 1'h1;
blake2s_ctrl_new = CTRL_INIT_ROUND;
blake2s_ctrl_we = 1'h1;
end
end
CTRL_INIT_ROUND: begin
init_v = 1'h1;
round_ctr_rst = 1'h1;
blake2s_ctrl_new = CTRL_G_ROW;
blake2s_ctrl_we = 1'h1;
end
CTRL_G_ROW: begin
G_mode = G_ROW;
update_v = 1'h1;
blake2s_ctrl_new = CTRL_G_DIAGONAL;
blake2s_ctrl_we = 1'h1;
end
CTRL_G_DIAGONAL: begin
G_mode = G_DIAGONAL;
update_v = 1'h1;
round_ctr_inc = 1'h1;
if (round_ctr_reg == (NUM_ROUNDS - 1)) begin
blake2s_ctrl_new = CTRL_COMP_DONE;
blake2s_ctrl_we = 1'h1;
end
else begin
blake2s_ctrl_new = CTRL_G_ROW;
blake2s_ctrl_we = 1'h1;
end
end
CTRL_COMP_DONE: begin
last_new = 1'h0;
last_we = 1'h1;
update_state = 1'h1;
blake2s_ctrl_new = CTRL_FINISH;
blake2s_ctrl_we = 1'h1;
end
CTRL_FINISH: begin
ready_new = 1'h1;
ready_we = 1'h1;
blake2s_ctrl_new = CTRL_IDLE;
blake2s_ctrl_we = 1'h1;
end
default: begin end
endcase // case (blake2s_ctrl_reg)
end // blake2s_ctrl
endmodule // blake2s_core
//======================================================================
// EOF blake2s_core.v
//======================================================================

View File

@ -0,0 +1,391 @@
//======================================================================
//
// blake2s_m_select.v
// ------------------
// Verilog 2001 implementation of the message word selection in the
// blake2 hash function core. Based on the given round and mode, we
// extract the indices for the eight m words to select.
// The words are then selected and returned. This is basically a
// mux based implementation of the permutation table in combination
// with the actual word selection.
//
//
// Note that we use the mode to signal which indices to select
// for a given round. This is because we don't do 8 G-functions
// in a single cycle.
//
//
// Author: Joachim Strömbergson
// Copyright (c) 2018, Assured AB
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module blake2s_m_select(
input wire clk,
input wire reset_n,
input wire load,
input wire [511 : 0] m,
input wire [3 : 0] round,
input wire mode,
output wire [31 : 0] G0_m0,
output wire [31 : 0] G0_m1,
output wire [31 : 0] G1_m0,
output wire [31 : 0] G1_m1,
output wire [31 : 0] G2_m0,
output wire [31 : 0] G2_m1,
output wire [31 : 0] G3_m0,
output wire [31 : 0] G3_m1
);
//----------------------------------------------------------------
// regs.
//----------------------------------------------------------------
reg [31 : 0] m_mem [0 : 15];
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg [3 : 0] i_G0_m0;
reg [3 : 0] i_G0_m1;
reg [3 : 0] i_G1_m0;
reg [3 : 0] i_G1_m1;
reg [3 : 0] i_G2_m0;
reg [3 : 0] i_G2_m1;
reg [3 : 0] i_G3_m0;
reg [3 : 0] i_G3_m1;
//----------------------------------------------------------------
// Concurrent connectivity for ports.
//----------------------------------------------------------------
// Eight parallel, muxes that extract the message block words.
assign G0_m0 = m_mem[i_G0_m0];
assign G0_m1 = m_mem[i_G0_m1];
assign G1_m0 = m_mem[i_G1_m0];
assign G1_m1 = m_mem[i_G1_m1];
assign G2_m0 = m_mem[i_G2_m0];
assign G2_m1 = m_mem[i_G2_m1];
assign G3_m0 = m_mem[i_G3_m0];
assign G3_m1 = m_mem[i_G3_m1];
//----------------------------------------------------------------
// reg_update
//
// Update functionality for all registers in the core.
// All registers are positive edge triggered with synchronous,
// active low reset. All registers have write enable.
//----------------------------------------------------------------
always @ (posedge clk)
begin : reg_update
integer i;
if (!reset_n)
begin
for (i = 0 ; i < 16 ; i = i + 1)
m_mem[i] <= 32'h0;
end
else
begin
if (load)
begin
// Big to little endian conversion during register load.
m_mem[00] <= {m[0487 : 0480], m[0495 : 0488], m[0503 : 0496], m[0511 : 0504]};
m_mem[01] <= {m[0455 : 0448], m[0463 : 0456], m[0471 : 0464], m[0479 : 0472]};
m_mem[02] <= {m[0423 : 0416], m[0431 : 0424], m[0439 : 0432], m[0447 : 0440]};
m_mem[03] <= {m[0391 : 0384], m[0399 : 0392], m[0407 : 0400], m[0415 : 0408]};
m_mem[04] <= {m[0359 : 0352], m[0367 : 0360], m[0375 : 0368], m[0383 : 0376]};
m_mem[05] <= {m[0327 : 0320], m[0335 : 0328], m[0343 : 0336], m[0351 : 0344]};
m_mem[06] <= {m[0295 : 0288], m[0303 : 0296], m[0311 : 0304], m[0319 : 0312]};
m_mem[07] <= {m[0263 : 0256], m[0271 : 0264], m[0279 : 0272], m[0287 : 0280]};
m_mem[08] <= {m[0231 : 0224], m[0239 : 0232], m[0247 : 0240], m[0255 : 0248]};
m_mem[09] <= {m[0199 : 0192], m[0207 : 0200], m[0215 : 0208], m[0223 : 0216]};
m_mem[10] <= {m[0167 : 0160], m[0175 : 0168], m[0183 : 0176], m[0191 : 0184]};
m_mem[11] <= {m[0135 : 0128], m[0143 : 0136], m[0151 : 0144], m[0159 : 0152]};
m_mem[12] <= {m[0103 : 0096], m[0111 : 0104], m[0119 : 0112], m[0127 : 0120]};
m_mem[13] <= {m[0071 : 0064], m[0079 : 0072], m[0087 : 0080], m[0095 : 0088]};
m_mem[14] <= {m[0039 : 0032], m[0047 : 0040], m[0055 : 0048], m[0063 : 0056]};
m_mem[15] <= {m[0007 : 0000], m[0015 : 0008], m[0023 : 0016], m[0031 : 0024]};
end
end
end // reg_update
//----------------------------------------------------------------
// get_indices
//
// Get the indices from the permutation table given the
// round and the G function mode. This is the SIGMA table.
//----------------------------------------------------------------
always @*
begin : get_indices
i_G0_m0 = 4'd0;
i_G0_m1 = 4'd0;
i_G1_m0 = 4'd0;
i_G1_m1 = 4'd0;
i_G2_m0 = 4'd0;
i_G2_m1 = 4'd0;
i_G3_m0 = 4'd0;
i_G3_m1 = 4'd0;
case ({round, mode})
0: begin
i_G0_m0 = 4'd00;
i_G0_m1 = 4'd01;
i_G1_m0 = 4'd02;
i_G1_m1 = 4'd03;
i_G2_m0 = 4'd04;
i_G2_m1 = 4'd05;
i_G3_m0 = 4'd06;
i_G3_m1 = 4'd07;
end
1: begin
i_G0_m0 = 4'd08;
i_G0_m1 = 4'd09;
i_G1_m0 = 4'd10;
i_G1_m1 = 4'd11;
i_G2_m0 = 4'd12;
i_G2_m1 = 4'd13;
i_G3_m0 = 4'd14;
i_G3_m1 = 4'd15;
end
2: begin
i_G0_m0 = 4'd14;
i_G0_m1 = 4'd10;
i_G1_m0 = 4'd04;
i_G1_m1 = 4'd08;
i_G2_m0 = 4'd09;
i_G2_m1 = 4'd15;
i_G3_m0 = 4'd13;
i_G3_m1 = 4'd06;
end
3: begin
i_G0_m0 = 4'd01;
i_G0_m1 = 4'd12;
i_G1_m0 = 4'd00;
i_G1_m1 = 4'd02;
i_G2_m0 = 4'd11;
i_G2_m1 = 4'd07;
i_G3_m0 = 4'd05;
i_G3_m1 = 4'd03;
end
4: begin
i_G0_m0 = 4'd11;
i_G0_m1 = 4'd08;
i_G1_m0 = 4'd12;
i_G1_m1 = 4'd00;
i_G2_m0 = 4'd05;
i_G2_m1 = 4'd02;
i_G3_m0 = 4'd15;
i_G3_m1 = 4'd13;
end
5: begin
i_G0_m0 = 4'd10;
i_G0_m1 = 4'd14;
i_G1_m0 = 4'd03;
i_G1_m1 = 4'd06;
i_G2_m0 = 4'd07;
i_G2_m1 = 4'd01;
i_G3_m0 = 4'd09;
i_G3_m1 = 4'd04;
end
6: begin
i_G0_m0 = 4'd07;
i_G0_m1 = 4'd09;
i_G1_m0 = 4'd03;
i_G1_m1 = 4'd01;
i_G2_m0 = 4'd13;
i_G2_m1 = 4'd12;
i_G3_m0 = 4'd11;
i_G3_m1 = 4'd14;
end
7: begin
i_G0_m0 = 4'd02;
i_G0_m1 = 4'd06;
i_G1_m0 = 4'd05;
i_G1_m1 = 4'd10;
i_G2_m0 = 4'd04;
i_G2_m1 = 4'd00;
i_G3_m0 = 4'd15;
i_G3_m1 = 4'd08;
end
8: begin
i_G0_m0 = 4'd09;
i_G0_m1 = 4'd00;
i_G1_m0 = 4'd05;
i_G1_m1 = 4'd07;
i_G2_m0 = 4'd02;
i_G2_m1 = 4'd04;
i_G3_m0 = 4'd10;
i_G3_m1 = 4'd15;
end
9: begin
i_G0_m0 = 4'd14;
i_G0_m1 = 4'd01;
i_G1_m0 = 4'd11;
i_G1_m1 = 4'd12;
i_G2_m0 = 4'd06;
i_G2_m1 = 4'd08;
i_G3_m0 = 4'd03;
i_G3_m1 = 4'd13;
end
10: begin
i_G0_m0 = 4'd02;
i_G0_m1 = 4'd12;
i_G1_m0 = 4'd06;
i_G1_m1 = 4'd10;
i_G2_m0 = 4'd00;
i_G2_m1 = 4'd11;
i_G3_m0 = 4'd08;
i_G3_m1 = 4'd03;
end
11: begin
i_G0_m0 = 4'd04;
i_G0_m1 = 4'd13;
i_G1_m0 = 4'd07;
i_G1_m1 = 4'd05;
i_G2_m0 = 4'd15;
i_G2_m1 = 4'd14;
i_G3_m0 = 4'd01;
i_G3_m1 = 4'd09;
end
12: begin
i_G0_m0 = 4'd12;
i_G0_m1 = 4'd05;
i_G1_m0 = 4'd01;
i_G1_m1 = 4'd15;
i_G2_m0 = 4'd14;
i_G2_m1 = 4'd13;
i_G3_m0 = 4'd04;
i_G3_m1 = 4'd10;
end
13: begin
i_G0_m0 = 4'd00;
i_G0_m1 = 4'd07;
i_G1_m0 = 4'd06;
i_G1_m1 = 4'd03;
i_G2_m0 = 4'd09;
i_G2_m1 = 4'd02;
i_G3_m0 = 4'd08;
i_G3_m1 = 4'd11;
end
14: begin
i_G0_m0 = 4'd13;
i_G0_m1 = 4'd11;
i_G1_m0 = 4'd07;
i_G1_m1 = 4'd14;
i_G2_m0 = 4'd12;
i_G2_m1 = 4'd01;
i_G3_m0 = 4'd03;
i_G3_m1 = 4'd09;
end
15: begin
i_G0_m0 = 4'd05;
i_G0_m1 = 4'd00;
i_G1_m0 = 4'd15;
i_G1_m1 = 4'd04;
i_G2_m0 = 4'd08;
i_G2_m1 = 4'd06;
i_G3_m0 = 4'd02;
i_G3_m1 = 4'd10;
end
16: begin
i_G0_m0 = 4'd06;
i_G0_m1 = 4'd15;
i_G1_m0 = 4'd14;
i_G1_m1 = 4'd09;
i_G2_m0 = 4'd11;
i_G2_m1 = 4'd03;
i_G3_m0 = 4'd00;
i_G3_m1 = 4'd08;
end
17: begin
i_G0_m0 = 4'd12;
i_G0_m1 = 4'd02;
i_G1_m0 = 4'd13;
i_G1_m1 = 4'd07;
i_G2_m0 = 4'd01;
i_G2_m1 = 4'd04;
i_G3_m0 = 4'd10;
i_G3_m1 = 4'd05;
end
18: begin
i_G0_m0 = 4'd10;
i_G0_m1 = 4'd02;
i_G1_m0 = 4'd08;
i_G1_m1 = 4'd04;
i_G2_m0 = 4'd07;
i_G2_m1 = 4'd06;
i_G3_m0 = 4'd01;
i_G3_m1 = 4'd05;
end
19: begin
i_G0_m0 = 4'd15;
i_G0_m1 = 4'd11;
i_G1_m0 = 4'd09;
i_G1_m1 = 4'd14;
i_G2_m0 = 4'd03;
i_G2_m1 = 4'd12;
i_G3_m0 = 4'd13;
i_G3_m1 = 4'd00;
end
default: begin end
endcase // case ({round, mode})
end
endmodule // blake2s_m_select
//======================================================================
// EOF blake2s_m_select.v
//======================================================================

View File

@ -49,6 +49,7 @@ module application_fpga(
localparam UART_PREFIX = 6'h03;
localparam TOUCH_SENSE_PREFIX = 6'h04;
localparam FW_RAM_PREFIX = 6'h10;
localparam BLAKE2S_PREFIX = 6'h12;
localparam TK1_PREFIX = 6'h3f;
// Instruction used to cause a trap.
@ -103,6 +104,15 @@ module application_fpga(
wire [31 : 0] trng_read_data;
wire trng_ready;
/* verilator lint_off UNOPTFLAT */
reg blake2s_cs;
/* verilator lint_on UNOPTFLAT */
reg blake2s_we;
reg [7 : 0] blake2s_address;
reg [31 : 0] blake2s_write_data;
wire [31 : 0] blake2s_read_data;
wire blake2s_ready;
/* verilator lint_off UNOPTFLAT */
reg timer_cs;
/* verilator lint_on UNOPTFLAT */
@ -258,6 +268,17 @@ module application_fpga(
);
blake2s blake2s_inst(
.clk(clk),
.reset_n(reset_n),
.cs(blake2s_cs),
.we(blake2s_we),
.address(blake2s_address),
.write_data(blake2s_write_data),
.read_data(blake2s_read_data)
);
timer timer_inst(
.clk(clk),
.reset_n(reset_n),
@ -398,6 +419,11 @@ module application_fpga(
trng_address = cpu_addr[9 : 2];
trng_write_data = cpu_wdata;
blake2s_cs = 1'h0;
blake2s_we = |cpu_wstrb;
blake2s_address = cpu_addr[9 : 2];
blake2s_write_data = cpu_wdata;
timer_cs = 1'h0;
timer_we = |cpu_wstrb;
timer_address = cpu_addr[9 : 2];
@ -482,6 +508,12 @@ module application_fpga(
muxed_ready_new = fw_ram_ready;
end
BLAKE2S_PREFIX: begin
blake2s_cs = 1'h1;
muxed_rdata_new = blake2s_read_data;
muxed_ready_new = 1'h1;
end
TK1_PREFIX: begin
tk1_cs = 1'h1;
muxed_rdata_new = tk1_read_data;