From 9fa6e368879d30835880b3bb0e87c8cf13dd9874 Mon Sep 17 00:00:00 2001 From: "Pavel V. Shatov (Meister)" Date: Sun, 12 Feb 2017 22:21:57 +0300 Subject: Various clean-ups * Added sample C program for STM32 to test the core in hardware * Parametrized math modules are now instantiated with explicit operand width for clarify (previously relied on default parameter values in underlying modules) * Fixed some comments --- bench/tb_modular_multiplier_256.v | 340 ++++++++++++++++---------------- rtl/curve/curve_dbl_add_256.v | 12 +- rtl/modular/modular_multiplier_256.v | 30 +-- rtl/modular/modular_reductor_256.v | 352 ++++++++++++++++++---------------- stm32_driver/ecdsa256_driver_sample.c | 173 +++++++++++++++++ stm32_driver/ecdsa_model.h | 204 ++++++++++++++++++++ 6 files changed, 760 insertions(+), 351 deletions(-) create mode 100644 stm32_driver/ecdsa256_driver_sample.c create mode 100644 stm32_driver/ecdsa_model.h diff --git a/bench/tb_modular_multiplier_256.v b/bench/tb_modular_multiplier_256.v index 3f62767..5277c20 100644 --- a/bench/tb_modular_multiplier_256.v +++ b/bench/tb_modular_multiplier_256.v @@ -38,59 +38,59 @@ //------------------------------------------------------------------------------ `timescale 1ns / 1ps -//------------------------------------------------------------------------------ - -module tb_modular_multiplier_256; - - - // - // Test Vectors - // - localparam [255:0] N = 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff; - - localparam [255:0] X_1 = 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; - localparam [255:0] Y_1 = 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; - localparam [255:0] P_1 = 256'h823cd15f6dd3c71933565064513a6b2bd183e554c6a08622f713ebbbface98be; - - localparam [255:0] X_2 = 256'h29d05c193da77b710e86323538b77e1b11f904fea42998be16bd8d744ece7ad0; - localparam [255:0] Y_2 = 256'hb01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae07; - localparam [255:0] P_2 = 256'h76b2571d1d009ab0e7d1cc086c7d3648f08755b2e2585e780d11f053b06fb6ec; - - localparam [255:0] X_3 = 256'h8101ece47464a6ead70cf69a6e2bd3d88691a3262d22cba4f7635eaff26680a8; - localparam [255:0] Y_3 = 256'hd8a12ba61d599235f67d9cb4d58f1783d3ca43e78f0a5abaa624079936c0c3a9; - localparam [255:0] P_3 = 256'h944fea6a4fac7ae475a6bb211db4bbd394bd9b3ee9a038f6c17125a00b3a5375; - - localparam [255:0] X_4 = 256'h7214bc9647160bbd39ff2f80533f5dc6ddd70ddf86bb815661e805d5d4e6f27c; - localparam [255:0] Y_4 = 256'h8b81e3e977597110c7cf2633435b2294b72642987defd3d4007e1cfc5df84541; - localparam [255:0] P_4 = 256'h78d3e33c81ab9c652679363c76df004ea6f9a9e3a242a0fb71a4e8fdf41ab519; - - +//------------------------------------------------------------------------------ + +module tb_modular_multiplier_256; + + + // + // Test Vectors + // + localparam [255:0] N = 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff; + + localparam [255:0] X_1 = 256'h6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296; + localparam [255:0] Y_1 = 256'h4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5; + localparam [255:0] P_1 = 256'h823cd15f6dd3c71933565064513a6b2bd183e554c6a08622f713ebbbface98be; + + localparam [255:0] X_2 = 256'h29d05c193da77b710e86323538b77e1b11f904fea42998be16bd8d744ece7ad0; + localparam [255:0] Y_2 = 256'hb01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae07; + localparam [255:0] P_2 = 256'h76b2571d1d009ab0e7d1cc086c7d3648f08755b2e2585e780d11f053b06fb6ec; + + localparam [255:0] X_3 = 256'h8101ece47464a6ead70cf69a6e2bd3d88691a3262d22cba4f7635eaff26680a8; + localparam [255:0] Y_3 = 256'hd8a12ba61d599235f67d9cb4d58f1783d3ca43e78f0a5abaa624079936c0c3a9; + localparam [255:0] P_3 = 256'h944fea6a4fac7ae475a6bb211db4bbd394bd9b3ee9a038f6c17125a00b3a5375; + + localparam [255:0] X_4 = 256'h7214bc9647160bbd39ff2f80533f5dc6ddd70ddf86bb815661e805d5d4e6f27c; + localparam [255:0] Y_4 = 256'h8b81e3e977597110c7cf2633435b2294b72642987defd3d4007e1cfc5df84541; + localparam [255:0] P_4 = 256'h78d3e33c81ab9c652679363c76df004ea6f9a9e3a242a0fb71a4e8fdf41ab519; + + // // Core Parameters // localparam WORD_COUNTER_WIDTH = 3; - localparam OPERAND_NUM_WORDS = 8; - - - // - // Clock (100 MHz) - // - reg clk = 1'b0; - always #5 clk = ~clk; - - - // - // Inputs, Outputs - // - reg rst_n; - reg ena; - wire rdy; - - + localparam OPERAND_NUM_WORDS = 8; + + + // + // Clock (100 MHz) + // + reg clk = 1'b0; + always #5 clk = ~clk; + + + // + // Inputs, Outputs + // + reg rst_n; + reg ena; + wire rdy; + + // // Buffers (X, Y, N, P) // - wire [WORD_COUNTER_WIDTH-1:0] core_x_addr; + wire [WORD_COUNTER_WIDTH-1:0] core_x_addr; wire [WORD_COUNTER_WIDTH-1:0] core_y_addr; wire [WORD_COUNTER_WIDTH-1:0] core_n_addr; wire [WORD_COUNTER_WIDTH-1:0] core_p_addr; @@ -103,7 +103,7 @@ module tb_modular_multiplier_256; wire [ 31:0] core_p_data; reg [WORD_COUNTER_WIDTH-1:0] tb_xyn_addr; - reg [WORD_COUNTER_WIDTH-1:0] tb_p_addr; + reg [WORD_COUNTER_WIDTH-1:0] tb_p_addr; reg tb_xyn_wren; @@ -182,94 +182,94 @@ module tb_modular_multiplier_256; .b_addr (tb_p_addr), .b_out (tb_p_data) - ); - - - // - // UUT - // - modular_multiplier_256 uut - ( - .clk (clk), - .rst_n (rst_n), - - .ena (ena), - .rdy (rdy), - - .a_addr (core_x_addr), - .b_addr (core_y_addr), - .n_addr (core_n_addr), - .p_addr (core_p_addr), - .p_wren (core_p_wren), - - .a_din (core_x_data), - .b_din (core_y_data), - .n_din (core_n_data), - .p_dout (core_p_data) - ); - - - // - // Testbench Routine - // - reg ok = 1; - initial begin - - /* initialize control inputs */ - rst_n = 0; - ena = 0; - - tb_xyn_wren = 0; - - /* wait for some time */ - #200; - - /* de-assert reset */ - rst_n = 1; - - /* wait for some time */ - #100; - - /* run tests */ - test_modular_multiplier(X_1, Y_1, N, P_1); - test_modular_multiplier(X_2, Y_2, N, P_2); - test_modular_multiplier(X_3, Y_3, N, P_3); - test_modular_multiplier(X_4, Y_4, N, P_4); - - /* print result */ + ); + + + // + // UUT + // + modular_multiplier_256 uut + ( + .clk (clk), + .rst_n (rst_n), + + .ena (ena), + .rdy (rdy), + + .a_addr (core_x_addr), + .b_addr (core_y_addr), + .n_addr (core_n_addr), + .p_addr (core_p_addr), + .p_wren (core_p_wren), + + .a_din (core_x_data), + .b_din (core_y_data), + .n_din (core_n_data), + .p_dout (core_p_data) + ); + + + // + // Testbench Routine + // + reg ok = 1; + initial begin + + /* initialize control inputs */ + rst_n = 0; + ena = 0; + + tb_xyn_wren = 0; + + /* wait for some time */ + #200; + + /* de-assert reset */ + rst_n = 1; + + /* wait for some time */ + #100; + + /* run tests */ + test_modular_multiplier(X_1, Y_1, N, P_1); + test_modular_multiplier(X_2, Y_2, N, P_2); + test_modular_multiplier(X_3, Y_3, N, P_3); + test_modular_multiplier(X_4, Y_4, N, P_4); + + /* print result */ if (ok) $display("tb_modular_multiplier_256: SUCCESS"); else $display("tb_modular_multiplier_256: FAILURE"); // //$finish; - // - end - - - // - // Test Task - // - reg [255:0] p; - reg p_ok; - - integer w; - - reg [511:0] pp_full; - reg [255:0] pp_ref; - - task test_modular_multiplier; - - input [255:0] x; - input [255:0] y; - input [255:0] n; - input [255:0] pp; - + // + end + + + // + // Test Task + // + reg [255:0] p; + reg p_ok; + + integer w; + + reg [511:0] pp_full; + reg [255:0] pp_ref; + + task test_modular_multiplier; + + input [255:0] x; + input [255:0] y; + input [255:0] n; + input [255:0] pp; + reg [255:0] x_shreg; reg [255:0] y_shreg; reg [255:0] n_shreg; - reg [255:0] p_shreg; - - begin - + reg [255:0] p_shreg; + + begin + /* start filling memories */ tb_xyn_wren = 1; @@ -308,27 +308,27 @@ module tb_modular_multiplier_256; tb_n_data = {32{1'bX}}; /* stop filling memories */ - tb_xyn_wren = 0; - - /* calculate reference value */ - pp_full = {{256{1'b0}}, x} * {{256{1'b0}}, y}; - pp_ref = pp_full % {{256{1'b0}}, n}; - - /* compare reference value against hard-coded one */ - if (pp_ref != pp) begin - $display("ERROR: pp_ref != pp"); - $finish; - end - - /* start operation */ - ena = 1; - - /* clear flag */ - #10 ena = 0; - - /* wait for operation to complete */ - while (!rdy) #10; - + tb_xyn_wren = 0; + + /* calculate reference value */ + pp_full = {{256{1'b0}}, x} * {{256{1'b0}}, y}; + pp_ref = pp_full % {{256{1'b0}}, n}; + + /* compare reference value against hard-coded one */ + if (pp_ref != pp) begin + $display("ERROR: pp_ref != pp"); + $finish; + end + + /* start operation */ + ena = 1; + + /* clear flag */ + #10 ena = 0; + + /* wait for operation to complete */ + while (!rdy) #10; + /* read result */ for (w=0; w WORD_INDEX_ZERO) ? - WORD_INDEX_CURRENT - 1'b1 : WORD_INDEX_LAST; - end + // + // Handy Functions + // + function [WORD_COUNTER_WIDTH:0] WORD_INDEX_PREVIOUS_OR_LAST; + input [WORD_COUNTER_WIDTH:0] WORD_INDEX_CURRENT; + begin + WORD_INDEX_PREVIOUS_OR_LAST = (WORD_INDEX_CURRENT > WORD_INDEX_ZERO) ? + WORD_INDEX_CURRENT - 1'b1 : WORD_INDEX_LAST; + end endfunction // // Ports - // + // input wire clk; // system clock - input wire rst_n; // active-low async reset - - input wire ena; // enable input + input wire rst_n; // active-low async reset + + input wire ena; // enable input output wire rdy; // ready output - - output wire [WORD_COUNTER_WIDTH-0:0] x_addr; // index of current X word - output wire [WORD_COUNTER_WIDTH-1:0] n_addr; // index of current N word - output wire [WORD_COUNTER_WIDTH-1:0] p_addr; // index of current P word + + output wire [WORD_COUNTER_WIDTH-0:0] x_addr; // index of current X word + output wire [WORD_COUNTER_WIDTH-1:0] n_addr; // index of current N word + output wire [WORD_COUNTER_WIDTH-1:0] p_addr; // index of current P word output wire p_wren; // store current P word now - + input wire [ 31:0] x_din; // X input wire [ 31:0] n_din; // N (must be P-256!) output wire [ 31:0] p_dout; // P = X mod N - // - // Word Indices - // + // + // Word Indices + // reg [WORD_COUNTER_WIDTH:0] index_x; - - - /* map registers to output ports */ + + + /* map registers to output ports */ assign x_addr = index_x; - - // + + // // FSM // localparam FSM_SHREG_WIDTH = (2 * OPERAND_NUM_WORDS + 1) + (5 * 2) + 1; @@ -136,34 +136,34 @@ module modular_reductor_256 wire reduce_done_all = reduce_adder0_done & reduce_adder1_done & reduce_subtractor_done; - always @(posedge clk or negedge rst_n) - // - if (rst_n == 1'b0) - // - fsm_shreg <= {{FSM_SHREG_WIDTH-1{1'b0}}, 1'b1}; - // - else begin - // + always @(posedge clk or negedge rst_n) + // + if (rst_n == 1'b0) + // + fsm_shreg <= {{FSM_SHREG_WIDTH-1{1'b0}}, 1'b1}; + // + else begin + // if (rdy) // fsm_shreg <= {ena, {FSM_SHREG_WIDTH-2{1'b0}}, ~ena}; - // + // else if (!reduce_stop || reduce_done_all) // - fsm_shreg <= {1'b0, fsm_shreg[FSM_SHREG_WIDTH-1:1]}; - // + fsm_shreg <= {1'b0, fsm_shreg[FSM_SHREG_WIDTH-1:1]}; + // end - // - // Word Index Increment Logic - // - always @(posedge clk) - // - if (rdy) - // - index_x <= WORD_INDEX_LAST; - // + // + // Word Index Increment Logic + // + always @(posedge clk) + // + if (rdy) + // + index_x <= WORD_INDEX_LAST; + // else if (inc_index_x) // index_x <= WORD_INDEX_PREVIOUS_OR_LAST(index_x); @@ -173,14 +173,27 @@ module modular_reductor_256 // Look-up Table // - // TODO: Explain s5!!! + // + // Take a look at the corresponding C model for more information + // on how exactly the math behind reduction works. The first step + // is to assemble nine 256-bit values ("z-words") from 32-bit parts + // of the full 512-bit product ("c-word"). The problem with z5 is + // that it contains c13 two times. This implementation scans from + // c15 to c0 and writes current part of c-word into corresponding + // parts of z-words. Since those 32-bit parts are stored in block + // memories, one source word can only be written to one location in + // every z-word at a time. The trick is to delay c13 and then write + // the delayed value at the corresponding location in z5 instead of + // the next c12. "z_save" flag is used to indicate that the current + // word should be delayed and written once again during the next cycle. + // reg [9*WORD_COUNTER_WIDTH-1:0] z_addr; // reg [9 -1:0] z_wren; // reg [9 -1:0] z_mask; // mask input to store zero word reg [9 -1:0] z_save; // save previous word once again - always @(posedge clk) + always @(posedge clk) // if (inc_index_x) // @@ -204,9 +217,9 @@ module modular_reductor_256 4'd13: z_addr <= {3'd07, 3'd00, 3'd01, 3'd02, 3'd03, 3'd05, 3'd04, 3'd05, 3'dxx}; 4'd14: z_addr <= {3'd00, 3'd01, 3'd02, 3'd04, 3'd04, 3'd06, 3'd05, 3'd06, 3'dxx}; 4'd15: z_addr <= {3'd01, 3'd02, 3'd03, 3'd05, 3'd05, 3'd07, 3'd06, 3'd07, 3'dxx}; - // + // default: z_addr <= {9*WORD_COUNTER_WIDTH{1'bX}}; - // + // endcase always @(posedge clk) @@ -231,9 +244,9 @@ module modular_reductor_256 4'd13: z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0}; 4'd14: z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0}; 4'd15: z_wren <= {1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0}; - // + // default: z_wren <= {9{1'b0}}; - // + // endcase always @(posedge clk) @@ -260,11 +273,11 @@ module modular_reductor_256 4'd13: z_mask <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0}; 4'd14: z_mask <= {1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0}; 4'd15: z_mask <= {1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0}; - // + // default: z_mask <= {9{1'bX}}; - // + // endcase - + always @(posedge clk) // if (inc_index_x) @@ -289,9 +302,9 @@ module modular_reductor_256 4'd13: z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0}; 4'd14: z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0}; 4'd15: z_save <= {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0}; - // + // default: z_save <= {9{1'bX}}; - // + // endcase @@ -312,18 +325,18 @@ module modular_reductor_256 // begin : gen_z_bram // - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_c_inst - ( - .clk (clk), - - .a_addr (z_addr[(z-1) * WORD_COUNTER_WIDTH +: WORD_COUNTER_WIDTH]), - .a_wr (z_wren[z-1] & store_word_z), - .a_in (z_mask[z-1] ? {32{1'b0}} : (z_save[z-1] ? x_din_dly : x_din)), - .a_out (), - - .b_addr (reduce_z_addr[z]), - .b_out (reduce_z_dout[z]) + bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) + bram_c_inst + ( + .clk (clk), + + .a_addr (z_addr[(z-1) * WORD_COUNTER_WIDTH +: WORD_COUNTER_WIDTH]), + .a_wr (z_wren[z-1] & store_word_z), + .a_in (z_mask[z-1] ? {32{1'b0}} : (z_save[z-1] ? x_din_dly : x_din)), + .a_out (), + + .b_addr (reduce_z_addr[z]), + .b_out (reduce_z_dout[z]) ); // end @@ -355,50 +368,49 @@ module modular_reductor_256 reg [WORD_COUNTER_WIDTH-1:0] bram_diff_rd_addr; - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_sum0_inst - ( - .clk (clk), - - .a_addr (bram_sum0_wr_addr), - .a_wr (bram_sum0_wr_wren), - .a_in (bram_sum0_wr_din), - .a_out (), - - .b_addr (bram_sum0_rd_addr), - .b_out (bram_sum0_rd_dout) + bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) + bram_sum0_inst + ( + .clk (clk), + + .a_addr (bram_sum0_wr_addr), + .a_wr (bram_sum0_wr_wren), + .a_in (bram_sum0_wr_din), + .a_out (), + + .b_addr (bram_sum0_rd_addr), + .b_out (bram_sum0_rd_dout) ); - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_sum1_inst - ( - .clk (clk), - - .a_addr (bram_sum1_wr_addr), - .a_wr (bram_sum1_wr_wren), - .a_in (bram_sum1_wr_din), - .a_out (), - - .b_addr (bram_sum1_rd_addr), - .b_out (bram_sum1_rd_dout) + bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) + bram_sum1_inst + ( + .clk (clk), + + .a_addr (bram_sum1_wr_addr), + .a_wr (bram_sum1_wr_wren), + .a_in (bram_sum1_wr_din), + .a_out (), + + .b_addr (bram_sum1_rd_addr), + .b_out (bram_sum1_rd_dout) ); - bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) - bram_diff_inst - ( - .clk (clk), - - .a_addr (bram_diff_wr_addr), - .a_wr (bram_diff_wr_wren), - .a_in (bram_diff_wr_din), - .a_out (), - - .b_addr (bram_diff_rd_addr), - .b_out (bram_diff_rd_dout) + bram_1rw_1ro_readfirst # (.MEM_WIDTH(32), .MEM_ADDR_BITS(WORD_COUNTER_WIDTH)) + bram_diff_inst + ( + .clk (clk), + + .a_addr (bram_diff_wr_addr), + .a_wr (bram_diff_wr_wren), + .a_in (bram_diff_wr_din), + .a_out (), + + .b_addr (bram_diff_rd_addr), + .b_out (bram_diff_rd_dout) ); - wire [WORD_COUNTER_WIDTH-1:0] adder0_ab_addr; wire [WORD_COUNTER_WIDTH-1:0] adder1_ab_addr; wire [WORD_COUNTER_WIDTH-1:0] subtractor_ab_addr; @@ -414,7 +426,12 @@ module modular_reductor_256 // n_addr - only 1 output, because all modules are in sync - modular_adder adder_inst0 + modular_adder # + ( + .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS), + .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH) + ) + adder_inst0 ( .clk (clk), .rst_n (rst_n), @@ -426,14 +443,19 @@ module modular_reductor_256 .n_addr (), .s_addr (bram_sum0_wr_addr), .s_wren (bram_sum0_wr_wren), - + .a_din (adder0_a_din), .b_din (adder0_b_din), .n_din (n_din), .s_dout (bram_sum0_wr_din) ); - modular_adder adder_inst1 + modular_adder # + ( + .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS), + .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH) + ) + adder_inst1 ( .clk (clk), .rst_n (rst_n), @@ -445,14 +467,19 @@ module modular_reductor_256 .n_addr (), .s_addr (bram_sum1_wr_addr), .s_wren (bram_sum1_wr_wren), - + .a_din (adder1_a_din), .b_din (adder1_b_din), .n_din (n_din), .s_dout (bram_sum1_wr_din) ); - modular_subtractor subtractor_inst + modular_subtractor # + ( + .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS), + .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH) + ) + subtractor_inst ( .clk (clk), .rst_n (rst_n), @@ -464,7 +491,7 @@ module modular_reductor_256 .n_addr (n_addr), .d_addr (bram_diff_wr_addr), .d_wren (bram_diff_wr_wren), - + .a_din (subtractor_a_din), .b_din (subtractor_b_din), .n_din (n_din), @@ -473,7 +500,7 @@ module modular_reductor_256 // - // address + // Address (Operand) Selector // always @(*) // @@ -572,7 +599,6 @@ module modular_reductor_256 endcase - // // adder 0 // @@ -650,17 +676,17 @@ module modular_reductor_256 end - - - assign p_addr = bram_sum0_wr_addr; + // + // Address Mapping + // + assign p_addr = bram_sum0_wr_addr; assign p_wren = bram_sum0_wr_wren & store_p; assign p_dout = bram_sum0_wr_din; - - + endmodule -//------------------------------------------------------------------------------ -// End-of-File +//------------------------------------------------------------------------------ +// End-of-File //------------------------------------------------------------------------------ diff --git a/stm32_driver/ecdsa256_driver_sample.c b/stm32_driver/ecdsa256_driver_sample.c new file mode 100644 index 0000000..cef4af0 --- /dev/null +++ b/stm32_driver/ecdsa256_driver_sample.c @@ -0,0 +1,173 @@ + // + // simple driver to test "ecdsa384" core in hardware + // + + // + // note, that the test program needs a custom bitstream where + // the core is located at offset 0 (without the core selector) + // + + // stm32 headers +#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) + + // locations of data buffers +#define CORE_ADDR_BUF_K (0x20 << 2) +#define CORE_ADDR_BUF_X (0x28 << 2) +#define CORE_ADDR_BUF_Y (0x30 << 2) + + // bit maps +#define CORE_CONTROL_BIT_NEXT 0x00000002 +#define CORE_STATUS_BIT_READY 0x00000002 + + // curve selection +#define USE_CURVE 1 + +#include "ecdsa_model.h" + +#define BUF_NUM_WORDS (OPERAND_WIDTH / (sizeof(uint32_t) << 3)) // 8 + + // + // test vectors + // +static const uint32_t p256_d[BUF_NUM_WORDS] = ECDSA_D; +static const uint32_t p256_qx[BUF_NUM_WORDS] = ECDSA_Q_X; +static const uint32_t p256_qy[BUF_NUM_WORDS] = ECDSA_Q_Y; + +static const uint32_t p256_k[BUF_NUM_WORDS] = ECDSA_K; +static const uint32_t p256_rx[BUF_NUM_WORDS] = ECDSA_R_X; +static const uint32_t p256_ry[BUF_NUM_WORDS] = ECDSA_R_Y; + +static const uint32_t p256_i[BUF_NUM_WORDS] = ECDSA_ONE; +static const uint32_t p256_gx[BUF_NUM_WORDS] = ECDSA_G_X; +static const uint32_t p256_gy[BUF_NUM_WORDS] = ECDSA_G_Y; + +static const uint32_t p256_z[BUF_NUM_WORDS] = ECDSA_ZERO; +static const uint32_t p256_n[BUF_NUM_WORDS] = ECDSA_N; + + // + // prototypes + // +void toggle_yellow_led(void); +int test_p256_multiplier(const uint32_t *k, const uint32_t *px, const uint32_t *py); + + // + // test routine + // +int main() +{ + int ok; + + stm_init(); + fmc_init(); + + led_on(LED_GREEN); + led_off(LED_RED); + + led_off(LED_YELLOW); + led_off(LED_BLUE); + + uint32_t core_name0; + uint32_t core_name1; + + fmc_read_32(CORE_ADDR_NAME0, &core_name0); + fmc_read_32(CORE_ADDR_NAME1, &core_name1); + + // "ecds", "a256" + if ((core_name0 != 0x65636473) || (core_name1 != 0x61323536)) + { + led_off(LED_GREEN); + led_on(LED_RED); + while (1); + } + + // repeat forever + while (1) + { + ok = 1; + ok = ok && test_p256_multiplier(p256_d, p256_qx, p256_qy); + ok = ok && test_p256_multiplier(p256_k, p256_rx, p256_ry); + ok = ok && test_p256_multiplier(p256_z, p256_z, p256_z); + ok = ok && test_p256_multiplier(p256_i, p256_gx, p256_gy); + ok = ok && test_p256_multiplier(p256_n, p256_z, p256_z); + + if (!ok) + { led_off(LED_GREEN); + led_on(LED_RED); + } + + toggle_yellow_led(); + } +} + + + // + // this routine uses the hardware multiplier to obtain Q(qx,qy), which is the + // scalar multiple of the base point, qx and qy are then compared to the values + // px and py (correct result known in advance) + // +int test_p256_multiplier(const uint32_t *k, const uint32_t *px, const uint32_t *py) +{ + int i, num_cyc; + uint32_t reg_control, reg_status; + uint32_t k_word, qx_word, qy_word; + + // fill k + for (i=0; i P-256 +// USE_CURVE == 2 -> P-384 +// +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// Model Parameters +//------------------------------------------------------------------------------ +#if USE_CURVE == 1 +#define OPERAND_WIDTH (256) // largest supported operand width in bits +#elif USE_CURVE == 2 +#define OPERAND_WIDTH (384) // largest supported operand width in bits +#else +#error USE_CURVE must be either 1 or 2! +#endif + + +//------------------------------------------------------------------------------ +// P-256 Parameters and Test Vectors +//------------------------------------------------------------------------------ + +/* Field Size */ +#define P_256_Q {0xffffffff, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff} + +/* Generic Numbers */ +#define P_256_ZERO {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000} +#define P_256_ONE {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001} + +/* Division Factor */ +#define P_256_DELTA {0x7fffffff, 0x80000000, 0x80000000, 0x00000000, 0x00000000, 0x80000000, 0x00000000, 0x00000000} + +/* Base Point */ +#define P_256_G_X {0x6b17d1f2, 0xe12c4247, 0xf8bce6e5, 0x63a440f2, 0x77037d81, 0x2deb33a0, 0xf4a13945, 0xd898c296} +#define P_256_G_Y {0x4fe342e2, 0xfe1a7f9b, 0x8ee7eb4a, 0x7c0f9e16, 0x2bce3357, 0x6b315ece, 0xcbb64068, 0x37bf51f5} + +/* Doubled Base Point */ +#define P_256_H_X {0x29d05c19, 0x3da77b71, 0x0e863235, 0x38b77e1b, 0x11f904fe, 0xa42998be, 0x16bd8d74, 0x4ece7ad0} +#define P_256_H_Y {0xb01cbd1c, 0x01e58065, 0x711814b5, 0x83f061e9, 0xd431cca9, 0x94cea131, 0x3449bf97, 0xc840ae07} + +/* Base Point Order */ +#define P_256_N {0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xbce6faad, 0xa7179e84, 0xf3b9cac2, 0xfc632551} + +/* Private Key */ +#define P_256_D {0x70a12c2d, 0xb16845ed, 0x56ff68cf, 0xc21a472b, 0x3f04d7d6, 0x851bf634, 0x9f2d7d5b, 0x3452b38a} + +/* Per-message Random Number */ +#define P_256_K {0x580ec00d, 0x85643433, 0x4cef3f71, 0xecaed496, 0x5b12ae37, 0xfa47055b, 0x1965c7b1, 0x34ee45d0} + +/* Public Key */ +#define P_256_Q_X {0x8101ece4, 0x7464a6ea, 0xd70cf69a, 0x6e2bd3d8, 0x8691a326, 0x2d22cba4, 0xf7635eaf, 0xf26680a8} +#define P_256_Q_Y {0xd8a12ba6, 0x1d599235, 0xf67d9cb4, 0xd58f1783, 0xd3ca43e7, 0x8f0a5aba, 0xa6240799, 0x36c0c3a9} + +/* Part of Signature */ +#define P_256_R_X {0x7214bc96, 0x47160bbd, 0x39ff2f80, 0x533f5dc6, 0xddd70ddf, 0x86bb8156, 0x61e805d5, 0xd4e6f27c} +#define P_256_R_Y {0x8b81e3e9, 0x77597110, 0xc7cf2633, 0x435b2294, 0xb7264298, 0x7defd3d4, 0x007e1cfc, 0x5df84541} + + +//------------------------------------------------------------------------------ +// P-384 Parameters and Test Vectors +//------------------------------------------------------------------------------ + +/* Field Size */ +#define P_384_Q {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff} + +/* Generic Numbers */ +#define P_384_ZERO {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000} +#define P_384_ONE {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001} + +/* Division Factor */ +#define P_384_DELTA {0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff, 0x80000000, 0x0000000, 0x080000000} + +/* Base Point */ +#define P_384_G_X {0xaa87ca22, 0xbe8b0537, 0x8eb1c71e, 0xf320ad74, 0x6e1d3b62, 0x8ba79b98, 0x59f741e0, 0x82542a38, 0x5502f25d, 0xbf55296c, 0x3a545e38, 0x72760ab7} +#define P_384_G_Y {0x3617de4a, 0x96262c6f, 0x5d9e98bf, 0x9292dc29, 0xf8f41dbd, 0x289a147c, 0xe9da3113, 0xb5f0b8c0, 0x0a60b1ce, 0x1d7e819d, 0x7a431d7c, 0x90ea0e5f} + +/* Doubled Base Point */ +#define P_384_H_X {0xaaf06bba, 0x82e9f590, 0xe29c71c2, 0x19bea517, 0x23c5893a, 0xe8b0c8cf, 0x4c117c3e, 0xfb57ab8d, 0x55fa1b42, 0x8155ad27, 0x8b574391, 0x1b13ea8a} +#define P_384_H_Y {0xc9e821b5, 0x69d9d390, 0xa2616740, 0x6d6d23d6, 0x070be242, 0xd765eb83, 0x1625ceec, 0x4a0f473e, 0xf59f4e30, 0xe2817e62, 0x85bce284, 0x6f15f19d} + +/* Base Point Order */ +#define P_384_N {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xc7634d81, 0xf4372ddf, 0x581a0db2, 0x48b0a77a, 0xecec196a, 0xccc52973} + +/* Private Key */ +#define P_384_D {0xc838b852, 0x53ef8dc7, 0x394fa580, 0x8a518398, 0x1c7deef5, 0xa69ba8f4, 0xf2117ffe, 0xa39cfcd9, 0x0e95f6cb, 0xc854abac, 0xab701d50, 0xc1f3cf24} + +/* Per-message Random Number */ +#define P_384_K {0xdc6b4403, 0x6989a196, 0xe39d1cda, 0xc000812f, 0x4bdd8b2d, 0xb41bb33a, 0xf5137258, 0x5ebd1db6, 0x3f0ce827, 0x5aa1fd45, 0xe2d2a735, 0xf8749359} + +/* Public Key */ +#define P_384_Q_X {0x1fbac8ee, 0xbd0cbf35, 0x640b39ef, 0xe0808dd7, 0x74debff2, 0x0a2a329e, 0x91713baf, 0x7d7f3c3e, 0x81546d88, 0x3730bee7, 0xe48678f8, 0x57b02ca0} +#define P_384_Q_Y {0xeb213103, 0xbd68ce34, 0x3365a8a4, 0xc3d4555f, 0xa385f533, 0x0203bdd7, 0x6ffad1f3, 0xaffb9575, 0x1c132007, 0xe1b24035, 0x3cb0a4cf, 0x1693bdf9} + +/* Part of Signature */ +#define P_384_R_X {0xa0c27ec8, 0x93092dea, 0x1e1bd2cc, 0xfed3cf94, 0x5c8134ed, 0x0c9f8131, 0x1a0f4a05, 0x942db8db, 0xed8dd59f, 0x267471d5, 0x462aa14f, 0xe72de856} +#define P_384_R_Y {0x85564940, 0x9815bb91, 0x424eaca5, 0xfd76c973, 0x75d575d1, 0x422ec53d, 0x343bd33b, 0x847fdf0c, 0x11569685, 0xb528ab25, 0x49301542, 0x8d7cf72b} + + +//------------------------------------------------------------------------------ +// Parameter and Test Vector Selection +//------------------------------------------------------------------------------ +#if USE_CURVE == 1 + +#define ECDSA_Q P_256_Q + +#define ECDSA_ZERO P_256_ZERO +#define ECDSA_ONE P_256_ONE + +#define ECDSA_DELTA P_256_DELTA + +#define ECDSA_G_X P_256_G_X +#define ECDSA_G_Y P_256_G_Y + +#define ECDSA_H_X P_256_H_X +#define ECDSA_H_Y P_256_H_Y + +#define ECDSA_N P_256_N +#define ECDSA_D P_256_D +#define ECDSA_K P_256_K + +#define ECDSA_Q_X P_256_Q_X +#define ECDSA_Q_Y P_256_Q_Y + +#define ECDSA_R_X P_256_R_X +#define ECDSA_R_Y P_256_R_Y + +#elif USE_CURVE == 2 + +#define ECDSA_Q P_384_Q + +#define ECDSA_ZERO P_384_ZERO +#define ECDSA_ONE P_384_ONE + +#define ECDSA_DELTA P_384_DELTA + +#define ECDSA_G_X P_384_G_X +#define ECDSA_G_Y P_384_G_Y + +#define ECDSA_H_X P_384_H_X +#define ECDSA_H_Y P_384_H_Y + +#define ECDSA_N P_384_N +#define ECDSA_D P_384_D +#define ECDSA_K P_384_K + +#define ECDSA_Q_X P_384_Q_X +#define ECDSA_Q_Y P_384_Q_Y + +#define ECDSA_R_X P_384_R_X +#define ECDSA_R_Y P_384_R_Y + +#else + +#error USE_CURVE must be either 1 or 2! + +#endif + + +//------------------------------------------------------------------------------ +// End-of-File +//------------------------------------------------------------------------------ -- cgit v1.2.3