aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2017-02-12 22:21:57 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2017-02-12 22:21:57 +0300
commit9fa6e368879d30835880b3bb0e87c8cf13dd9874 (patch)
tree75d141e3c84a38e6bbe4e449424066492c125ff1
parenta66be3237f5e9f4b6144cec093b047acfd70ffc6 (diff)
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
-rw-r--r--bench/tb_modular_multiplier_256.v340
-rw-r--r--rtl/curve/curve_dbl_add_256.v12
-rw-r--r--rtl/modular/modular_multiplier_256.v30
-rw-r--r--rtl/modular/modular_reductor_256.v352
-rw-r--r--stm32_driver/ecdsa256_driver_sample.c173
-rw-r--r--stm32_driver/ecdsa_model.h204
6 files changed, 760 insertions, 351 deletions
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<OPERAND_NUM_WORDS; w=w+1) begin
@@ -341,26 +341,26 @@ module tb_modular_multiplier_256;
/* store data word */
p_shreg = {tb_p_data, p_shreg[255:32]};
- end
-
- /* compare */
- p_ok = (p_shreg == pp);
-
- /* display results */
- $display("test_modular_multiplier(): %s", p_ok ? "OK" : "ERROR");
-
- /* update flag */
- ok = ok && p_ok;
-
- end
-
- endtask
-
-
-
-
-endmodule
-
+ end
+
+ /* compare */
+ p_ok = (p_shreg == pp);
+
+ /* display results */
+ $display("test_modular_multiplier_256(): %s", p_ok ? "OK" : "ERROR");
+
+ /* update flag */
+ ok = ok && p_ok;
+
+ end
+
+ endtask
+
+
+
+
+endmodule
+
//------------------------------------------------------------------------------
// End-of-File
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
diff --git a/rtl/curve/curve_dbl_add_256.v b/rtl/curve/curve_dbl_add_256.v
index 08a9931..8ef505d 100644
--- a/rtl/curve/curve_dbl_add_256.v
+++ b/rtl/curve/curve_dbl_add_256.v
@@ -1,8 +1,8 @@
//------------------------------------------------------------------------------
//
-// curve_adder_256.v
+// curve_dbl_add_256.v
// -----------------------------------------------------------------------------
-// Elliptic curve point adder.
+// Elliptic curve point adder and doubler.
//
// Authors: Pavel Shatov
//
@@ -292,7 +292,13 @@ module curve_dbl_add_256
wire [ 32-1:0] mw_mov_din_x;
wire [ 32-1:0] mw_mov_dout_y;
- mw_mover mw_mover_inst
+ mw_mover #
+ (
+ .WORD_COUNTER_WIDTH (WORD_COUNTER_WIDTH),
+ .OPERAND_NUM_WORDS (OPERAND_NUM_WORDS)
+
+ )
+ mw_mover_inst
(
.clk (clk),
.rst_n (rst_n),
diff --git a/rtl/modular/modular_multiplier_256.v b/rtl/modular/modular_multiplier_256.v
index 8487aee..c2f2661 100644
--- a/rtl/modular/modular_multiplier_256.v
+++ b/rtl/modular/modular_multiplier_256.v
@@ -293,8 +293,8 @@ module modular_multiplier_256
//
// Accumulators
//
- wire [46: 0] add48_cw0_s;
- wire [46: 0] add48_cw1_s;
+ wire [46: 0] add47_cw0_s;
+ wire [46: 0] add47_cw1_s;
//
@@ -314,26 +314,26 @@ module modular_multiplier_256
//
si_next_dly <= si_lsb[62:47];
- wire [46: 0] add48_cw0_a = si_lsb[46:0];
- wire [46: 0] add48_cw0_b = {{16{1'b0}}, si_prev_dly};
+ wire [46: 0] add47_cw0_a = si_lsb[46:0];
+ wire [46: 0] add47_cw0_b = {{16{1'b0}}, si_prev_dly};
- wire [46: 0] add48_cw1_a = add48_cw0_s;
- wire [46: 0] add48_cw1_b = {{15{1'b0}}, si_next_dly, mask_cw1_sum ? {16{1'b0}} : {1'b0, add48_cw1_s[46:32]}};
+ wire [46: 0] add47_cw1_a = add47_cw0_s;
+ wire [46: 0] add47_cw1_b = {{15{1'b0}}, si_next_dly, mask_cw1_sum ? {16{1'b0}} : {1'b0, add47_cw1_s[46:32]}};
- adder47_wrapper add48_cw0_inst
+ adder47_wrapper add47_cw0_inst
(
.clk (clk),
- .a (add48_cw0_a),
- .b (add48_cw0_b),
- .s (add48_cw0_s)
+ .a (add47_cw0_a),
+ .b (add47_cw0_b),
+ .s (add47_cw0_s)
);
- adder47_wrapper add48_cw1_inst
+ adder47_wrapper add47_cw1_inst
(
.clk (clk),
- .a (add48_cw1_a),
- .b (add48_cw1_b),
- .s (add48_cw1_s)
+ .a (add47_cw1_a),
+ .b (add47_cw1_b),
+ .s (add47_cw1_s)
);
@@ -364,7 +364,7 @@ module modular_multiplier_256
.a_addr (bram_c_addr),
.a_wr (store_c_word),
- .a_in (add48_cw1_s[31:0]),
+ .a_in (add47_cw1_s[31:0]),
.a_out (),
.b_addr (reduce_c_addr),
diff --git a/rtl/modular/modular_reductor_256.v b/rtl/modular/modular_reductor_256.v
index 774f42e..e4b346a 100644
--- a/rtl/modular/modular_reductor_256.v
+++ b/rtl/modular/modular_reductor_256.v
@@ -1,39 +1,39 @@
-//------------------------------------------------------------------------------
-//
-// modular_reductor_256.v
-// -----------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+//
+// modular_reductor_256.v
+// -----------------------------------------------------------------------------
// Modular reductor.
-//
-// Authors: Pavel Shatov
-//
-// Copyright (c) 2015-2016, 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.
-//
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2015-2016, 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 modular_reductor_256
@@ -44,62 +44,62 @@ module modular_reductor_256
x_din, n_din, p_dout
);
- //
- // Constants
- //
+ //
+ // Constants
+ //
localparam OPERAND_NUM_WORDS = 8;
localparam WORD_COUNTER_WIDTH = 3;
- //
- // Handy Numbers
- //
- localparam [WORD_COUNTER_WIDTH:0] WORD_INDEX_ZERO = 0;
+ //
+ // Handy Numbers
+ //
+ localparam [WORD_COUNTER_WIDTH:0] WORD_INDEX_ZERO = 0;
localparam [WORD_COUNTER_WIDTH:0] WORD_INDEX_LAST = 2 * OPERAND_NUM_WORDS - 1;
- //
- // 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
+ //
+ // 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<BUF_NUM_WORDS; i++)
+ { k_word = k[i];
+ fmc_write_32(CORE_ADDR_BUF_K + ((BUF_NUM_WORDS - (i + 1)) * sizeof(uint32_t)), &k_word);
+ }
+
+ // clear 'next' control bit, then set 'next' control bit again to trigger new operation
+ reg_control = 0;
+ fmc_write_32(CORE_ADDR_CONTROL, &reg_control);
+ reg_control = CORE_CONTROL_BIT_NEXT;
+ fmc_write_32(CORE_ADDR_CONTROL, &reg_control);
+
+ // wait for 'ready' status bit to be set
+ num_cyc = 0;
+ do
+ { num_cyc++;
+ fmc_read_32(CORE_ADDR_STATUS, &reg_status);
+ }
+ while (!(reg_status & CORE_STATUS_BIT_READY));
+
+ // read back x and y word-by-word, then compare to the reference values
+ for (i=0; i<BUF_NUM_WORDS; i++)
+ {
+ fmc_read_32(CORE_ADDR_BUF_X + (i * sizeof(uint32_t)), &qx_word);
+ fmc_read_32(CORE_ADDR_BUF_Y + (i * sizeof(uint32_t)), &qy_word);
+
+ if ((qx_word != px[BUF_NUM_WORDS - (i + 1)])) return 0;
+ if ((qy_word != py[BUF_NUM_WORDS - (i + 1)])) return 0;
+ }
+
+ // everything went just fine
+ return 1;
+}
+
+ //
+ // 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);
+}
+
+
+ //
+ // end of file
+ //
diff --git a/stm32_driver/ecdsa_model.h b/stm32_driver/ecdsa_model.h
new file mode 100644
index 0000000..44ab59f
--- /dev/null
+++ b/stm32_driver/ecdsa_model.h
@@ -0,0 +1,204 @@
+//------------------------------------------------------------------------------
+//
+// ecdsa_model.h
+// --------------------------------------------
+// Base point scalar multiplier model for ECDSA
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2015-2016, 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.
+//
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+//
+// Curve Selection
+//
+// USE_CURVE == 1 -> 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
+//------------------------------------------------------------------------------