[Cryptech-Commits] [core/pkey/ecdsa256] 05/05: New testbench (basically the same as tb_curve_multiplier_256.v, but tests entire core starting from the wrapper)

git at cryptech.is git at cryptech.is
Tue Apr 13 14:21:08 UTC 2021


This is an automated email from the git hooks/post-receive script.

meisterpaul1 at yandex.ru pushed a commit to branch test_dpa_fix
in repository core/pkey/ecdsa256.

commit 1a02289102362a0e826f739048e9649fd3d8820d
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Mon Apr 12 17:35:49 2021 +0300

    New testbench (basically the same as tb_curve_multiplier_256.v, but tests
    entire core starting from the wrapper)
---
 bench/tb_ecdsa256_wrapper.v | 443 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 443 insertions(+)

diff --git a/bench/tb_ecdsa256_wrapper.v b/bench/tb_ecdsa256_wrapper.v
new file mode 100644
index 0000000..2e11d83
--- /dev/null
+++ b/bench/tb_ecdsa256_wrapper.v
@@ -0,0 +1,443 @@
+//------------------------------------------------------------------------------
+//
+// tb_ecdsa256_wrapper.v
+// -----------------------------------------------------------------------------
+// Testbench for 256-bit curve base point scalar multiplier.
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2016, 2018-2019, 2021 NORDUnet A/S
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// - Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+//
+// - 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.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// 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 HOLDER 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 tb_ecdsa256_wrapper;
+
+
+        //
+        // Test Vectors
+        //
+    `include "ecdsa256_test_vector_nsa.vh"
+    `include "ecdsa_test_vector_randomized.vh"
+
+
+        //
+        // Core Parameters
+        //
+    localparam WORD_COUNTER_WIDTH = 3;
+    localparam OPERAND_NUM_WORDS  = 8;
+
+
+        //
+        // Register Offsets
+        //
+    localparam CORE_ADDR_NAME0		= 24'h000000;
+    localparam CORE_ADDR_NAME1		= 24'h000001;
+    localparam CORE_ADDR_VERSION	= 24'h000002;
+    localparam CORE_ADDR_CONTROL	= 24'h000008;
+    localparam CORE_ADDR_STATUS		= 24'h000009;
+
+    localparam CORE_ADDR_BUF_K		= 24'h000020;
+    localparam CORE_ADDR_BUF_X		= 24'h000028;
+    localparam CORE_ADDR_BUF_Y		= 24'h000030;
+
+    localparam CORE_CONTROL_BIT_NEXT    = 32'h00000002;
+    localparam CORE_STATUS_BIT_VALID    = 32'h00000002;
+
+
+        //
+        // STM32 Settings
+        //
+    localparam STM32_FMC_LATENCY = 6;
+
+
+       //
+       // P-256 Domain Parameters
+       //
+    localparam ECDSA_P256_N =
+        {32'hffffffff, 32'h00000000, 32'hffffffff, 32'hffffffff,
+         32'hbce6faad, 32'ha7179e84, 32'hf3b9cac2, 32'hfc632551};
+
+    localparam ECDSA_P256_GX =
+        {32'h6b17d1f2, 32'he12c4247, 32'hf8bce6e5, 32'h63a440f2,
+         32'h77037d81, 32'h2deb33a0, 32'hf4a13945, 32'hd898c296};
+
+    localparam ECDSA_P256_GY =
+        {32'h4fe342e2, 32'hfe1a7f9b, 32'h8ee7eb4a, 32'h7c0f9e16,
+         32'h2bce3357, 32'h6b315ece, 32'hcbb64068, 32'h37bf51f5};
+
+    localparam ECDSA_P256_HX =
+        {32'h7cf27b18, 32'h8d034f7e, 32'h8a523803, 32'h04b51ac3,
+         32'hc08969e2, 32'h77f21b35, 32'ha60b48fc, 32'h47669978};
+    
+    localparam ECDSA_P256_HY =
+        {32'h07775510, 32'hdb8ed040, 32'h293d9ac6, 32'h9f7430db,
+         32'hba7dade6, 32'h3ce98229, 32'h9e04b79d, 32'h227873d1};
+
+
+        //
+        // FMC Clock (50 MHz)
+        //
+    localparam FMC_CLOCK_PERIOD         = 20.0;
+    localparam FMC_CLOCK_PERIOD_HALF    = 0.5 * FMC_CLOCK_PERIOD;
+    localparam FMC_CLOCK_PERIOD_QUARTER = 0.5 * FMC_CLOCK_PERIOD_HALF;
+
+    reg fmc_clk = 1'b0;
+
+    initial forever #FMC_CLOCK_PERIOD_HALF fmc_clk = ~fmc_clk;
+
+
+        //
+        // Clock Manager
+        //
+    wire io_clk;     // i/o clock
+    wire sys_clk;    // system clock
+    wire sys_rst_n;  // active-low reset
+
+	alpha_clkmgr clkmgr_inst
+	(        
+		.fmc_clk		(fmc_clk),
+        
+        .io_clk         (io_clk),
+		.sys_clk		(sys_clk),
+		.sys_rst_n		(sys_rst_n),
+        .core_clk       ()
+	);
+    
+    
+    //
+    // FMC Arbiter - FPGA Side
+    //
+    wire [23: 0] sys_fmc_addr;
+    wire         sys_fmc_wren;
+    wire         sys_fmc_rden;
+    wire [31: 0] sys_fmc_dout;
+    wire [31: 0] sys_fmc_din;
+
+
+    //
+    // FMC Arbiter - STM32 Side
+    //
+    reg  [23: 0] fmc_a = {24{1'bX}};
+    reg  [31: 0] fmc_d_drive;
+    wire [31: 0] fmc_d_bidir;
+    reg          fmc_ne1 = 1'b1;
+    reg          fmc_noe = 1'b1;
+    reg          fmc_nwe = 1'b1;
+    reg          fmc_nl = 1'b1;
+    wire         fmc_nwait_dummy;
+
+    assign fmc_d_bidir = fmc_noe ? fmc_d_drive : 32'hZZZZZZZZ;
+
+    fmc_arbiter #(.NUM_ADDR_BITS(24))
+    fmc_arbiter_inst
+    (
+        // fmc bus
+        .fmc_a     (fmc_a),
+        .fmc_d     (fmc_d_bidir),
+        .fmc_ne1   (fmc_ne1),
+        .fmc_nl    (fmc_nl),
+        .fmc_nwe   (fmc_nwe),
+        .fmc_noe   (fmc_noe),
+        .fmc_nwait (fmc_nwait_dummy),
+
+        // system clock, i/o clock
+        .io_clk  (io_clk),
+        .sys_clk (sys_clk),
+
+        // user bus
+        .sys_addr     (sys_fmc_addr),
+        .sys_wr_en    (sys_fmc_wren),
+        .sys_data_out (sys_fmc_dout),
+        .sys_rd_en    (sys_fmc_rden),
+        .sys_data_in  (sys_fmc_din)
+    );
+    
+    ecdsa256_wrapper uut
+    (
+        .clk            (sys_clk),
+        .reset_n        (sys_rst_n),
+
+        .cs             (sys_fmc_wren | sys_fmc_rden),
+        .we             (sys_fmc_wren),
+
+        .address        (sys_fmc_addr[5:0]),
+        .write_data     (sys_fmc_dout),
+        .read_data      (sys_fmc_din)
+    );
+
+
+        //
+        // Testbench Routine
+        //
+    reg ok = 1;
+    
+    reg [31:0] core_name0;
+    reg [31:0] core_name1;
+    reg [31:0] core_version;
+    
+    initial begin
+
+            /* wait for some time */
+        #4000;
+
+            /* sanity checks */
+        fmc_read(CORE_ADDR_NAME0,   core_name0);
+        fmc_read(CORE_ADDR_NAME1,   core_name1);
+        fmc_read(CORE_ADDR_VERSION, core_version);
+             
+        $display("CORE_NAME0:   %x", core_name0);             
+        $display("CORE_NAME1:   %x", core_name1);
+        $display("CORE_VERSION: %x", core_version);
+             
+            /* run tests */
+        $display("1. Q1 = d1 * G...");
+        test_curve_multiplier(ECDSA_P256_D_NSA, ECDSA_P256_QX_NSA, ECDSA_P256_QY_NSA);
+        
+        $display("2. R = k * G...");
+        test_curve_multiplier(ECDSA_P256_K_NSA, ECDSA_P256_RX_NSA, ECDSA_P256_RY_NSA);
+        
+        $display("3. Q2 = d2 * G...");
+        test_curve_multiplier(ECDSA_P256_D_RANDOM, ECDSA_P256_QX_RANDOM, ECDSA_P256_QY_RANDOM);
+
+        $display("4. O = n * G...");
+        test_curve_multiplier(ECDSA_P256_N, 256'd0, 256'd0);
+
+        $display("5. G = (n + 1) * G...");
+        test_curve_multiplier(ECDSA_P256_N + 256'd1, ECDSA_P256_GX, ECDSA_P256_GY);
+
+        $display("6. H = 2 * G...");
+        test_curve_multiplier(256'd2, ECDSA_P256_HX, ECDSA_P256_HY);
+
+        $display("7. H = (n + 2) * G...");
+        test_curve_multiplier(ECDSA_P256_N + 256'd2, ECDSA_P256_HX, ECDSA_P256_HY);
+
+            /* print result */
+        if (ok) $display("tb_curve_multiplier_256: SUCCESS");
+        else    $display("tb_curve_multiplier_256: FAILURE");
+
+        $finish;
+
+    end
+
+
+        //
+        // Test Task
+        //
+    reg p_ok;
+    integer w;
+    reg busy;
+    reg [31:0] reg_control;
+    reg [31:0] reg_status;
+    task test_curve_multiplier;
+    
+        input [255:0] k;
+        input [255:0] px;
+        input [255:0] py;
+
+        reg [255:0] k_shreg;
+        reg [255:0] px_shreg;
+        reg [255:0] py_shreg;
+
+        begin
+        
+                // initialize shift registers
+            k_shreg = k;
+
+                // write all the words
+            for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
+                fmc_write(CORE_ADDR_BUF_K + w, k_shreg[31:0]);
+                k_shreg = {{32{1'bX}}, k_shreg[255:32]};
+            end
+
+                // start operation
+            reg_control = {32{1'b0}};
+            fmc_write(CORE_ADDR_CONTROL, reg_control);
+            reg_control = CORE_CONTROL_BIT_NEXT;
+            fmc_write(CORE_ADDR_CONTROL, reg_control);
+            
+                // wait for operation to complete
+            busy = 1;
+            while (busy) begin
+                fmc_read(CORE_ADDR_STATUS, reg_status);
+                if ((reg_status & CORE_STATUS_BIT_VALID) == CORE_STATUS_BIT_VALID) busy = 0;
+            end
+            
+                // read result
+            for (w=0; w<OPERAND_NUM_WORDS; w=w+1) begin
+                px_shreg = {{32{1'bX}}, px_shreg[255:32]};
+                py_shreg = {{32{1'bX}}, py_shreg[255:32]};
+                fmc_read(CORE_ADDR_BUF_X + w, px_shreg[255:224]);
+                fmc_read(CORE_ADDR_BUF_Y + w, py_shreg[255:224]);
+            end
+
+                // compare
+            p_ok = (px_shreg === px) &&
+                   (py_shreg === py);
+
+                // display results
+            if (p_ok) $display("test_curve_multiplier(): OK");
+            else begin
+                $display("test_curve_multiplier(): ERROR");
+                $display("ref_px  == %x", px);
+                $display("calc_px == %x", px_shreg);
+                $display("ref_py  == %x", py);
+                $display("calc_py == %x", py_shreg);
+            end
+
+                // update global flag
+            ok = ok && p_ok;
+        
+        end
+
+    endtask
+
+    
+    //
+    // Helper Function
+    //
+    function  [31:0] _fmc_swap;
+        input [31:0]  data;
+        _fmc_swap = {data[7:0], data[15:8], data[23:16], data[31:24]};
+    endfunction
+    
+    
+    //-------------
+    task fmc_write;
+    //-------------
+        input [23: 0] addr;
+        input [31: 0] data;
+        begin
+            fmc_ne1 = 1'b0;                     // select
+            fmc_nl = 1'b0;                      // set latch flag
+            fmc_a = addr;                       // set address
+            fmc_nwe = 1'b0;                     // set write-enable
+            wait_full_tick();                   // mimic latency
+
+            fmc_nl = 1'b1;                      // clear latch flag
+            fmc_a = {24{1'bX}};                 // clear address
+            wait_n_ticks(STM32_FMC_LATENCY);    // mimic latency
+
+            fmc_d_drive = _fmc_swap(data);      // set data            
+
+            wait_half_tick();                   // mimic latency
+            wait_quarter_tick();
+
+            fmc_ne1 = 1'b1;                     // deselect
+            fmc_nwe = 1'b1;                     // clear write-enable
+            fmc_d_drive = 32'hXXXXXXXX;         // clear data
+
+            wait_quarter_tick();                // finish clock period
+            wait_full_tick();                   // pause
+        end
+    endtask
+
+    //------------
+    task fmc_read;
+    //------------
+        input  [23: 0] addr;
+        output [31: 0] data;
+        begin
+            fmc_ne1 = 1'b0;                     // select
+            fmc_nl = 1'b0;                      // set latch flag
+            fmc_a = addr;                       // set address
+
+            wait_full_tick();                   // mimic latency
+
+            fmc_nl = 1'b1;                      // clear latch flag
+            fmc_a = {24{1'bX}};                 // clear address
+            wait_full_tick();                   // mimic latency
+            fmc_noe = 1'b0;                     // tri-state bus
+            wait_n_ticks(STM32_FMC_LATENCY-1);  // mimic latency
+
+            wait_half_tick();                   // mimic latency
+            data = _fmc_swap(fmc_d_bidir);      // sample data
+            wait_half_tick();                   // mimic latency
+            
+            wait_full_tick();                   // mimic latency
+            
+            wait_half_tick();                   // mimic latency
+            wait_quarter_tick();
+
+            fmc_ne1 = 1'b1;                     // deselect
+            fmc_noe = 1'b1;                     // drive bus
+
+            wait_quarter_tick();                // finish clock period
+            wait_full_tick();                   // pause
+        end
+    endtask
+    
+    
+    //
+    // Helper Tasks
+    //
+    
+    //----------------------
+    task  wait_quarter_tick;
+    //----------------------
+        begin
+            #FMC_CLOCK_PERIOD_QUARTER;
+        end
+    endtask
+
+    //------------------
+    task wait_half_tick;
+    //------------------
+        begin
+            wait_quarter_tick();
+            wait_quarter_tick();
+        end
+    endtask
+
+    //------------------
+    task wait_full_tick;
+    //------------------
+        begin
+            wait_half_tick();
+            wait_half_tick();
+        end
+    endtask
+
+    //----------------
+    task wait_n_ticks;
+    //----------------
+        input integer n;
+        integer i;
+        begin
+            for (i=0; i<n; i=i+1)
+                wait_full_tick();
+        end
+    endtask
+    
+    
+endmodule
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------



More information about the Commits mailing list