aboutsummaryrefslogtreecommitdiff
path: root/ecdh_fpga_model.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ecdh_fpga_model.cpp')
-rw-r--r--ecdh_fpga_model.cpp264
1 files changed, 264 insertions, 0 deletions
diff --git a/ecdh_fpga_model.cpp b/ecdh_fpga_model.cpp
new file mode 100644
index 0000000..730292e
--- /dev/null
+++ b/ecdh_fpga_model.cpp
@@ -0,0 +1,264 @@
+//------------------------------------------------------------------------------
+//
+// ecdh_fpga_model.cpp
+// --------------------------------------------
+// Curve point scalar multiplier model for ECDH
+//
+// Authors: Pavel Shatov
+//
+// Copyright (c) 2017-2018, 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.
+//
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "ecdh_fpga_model.h"
+#include "fpga_lowlevel.h"
+#include "fpga_modular.h"
+#include "fpga_curve.h"
+#include "fpga_util.h"
+
+
+//------------------------------------------------------------------------------
+// Prototypes
+//------------------------------------------------------------------------------
+bool test_point_multiplier (FPGA_BUFFER *px, FPGA_BUFFER *py, FPGA_BUFFER *k, FPGA_BUFFER *qx, FPGA_BUFFER *qy);
+bool abuse_point_multiplier (FPGA_BUFFER *qx, FPGA_BUFFER *qy);
+
+void print_fpga_buffer (const char *s, FPGA_BUFFER *v);
+bool compare_fpga_buffers (FPGA_BUFFER *ax, FPGA_BUFFER *ay, FPGA_BUFFER *bx, FPGA_BUFFER *by);
+
+
+//------------------------------------------------------------------------------
+int main()
+//------------------------------------------------------------------------------
+{
+ bool ok_a, ok_b; // flags
+
+ //
+ // initialize buffers
+ //
+ fpga_modular_init();
+ fpga_curve_init();
+
+
+ //
+ // test point multiplier: QA = dA * G
+ // QB = dB * G
+ //
+ printf("Trying to derive public keys from private keys...\n\n");
+ ok_a = test_point_multiplier(&ecdsa_g_x, &ecdsa_g_y, &ecdh_da, &ecdh_qa_x, &ecdh_qa_y);
+ ok_b = test_point_multiplier(&ecdsa_g_x, &ecdsa_g_y, &ecdh_db, &ecdh_qb_x, &ecdh_qb_y);
+ if (!ok_a || !ok_b) return EXIT_FAILURE;
+
+
+ //
+ // test point multiplier: S = dA * QB
+ // S = dB * QA
+ //
+ printf("Trying to derive shared secret key...\n\n");
+ ok_a = test_point_multiplier(&ecdh_qa_x, &ecdh_qa_y, &ecdh_db, &ecdh_s_x, &ecdh_s_y);
+ ok_b = test_point_multiplier(&ecdh_qb_x, &ecdh_qb_y, &ecdh_da, &ecdh_s_x, &ecdh_s_y);
+ if (!ok_a || !ok_b) return EXIT_FAILURE;
+
+
+ //
+ // test point multiplier: O = 0 * QA
+ // O = 0 * QB
+ //
+ printf("Trying to multiply public keys by zero...\n\n");
+ ok_a = test_point_multiplier(&ecdh_qa_x, &ecdh_qa_y, &ecdsa_zero, &ecdsa_zero, &ecdsa_zero);
+ ok_b = test_point_multiplier(&ecdh_qb_x, &ecdh_qb_y, &ecdsa_zero, &ecdsa_zero, &ecdsa_zero);
+ if (!ok_a || !ok_b) return EXIT_FAILURE;
+
+
+ //
+ // test point multiplier: QA = 1 * QA
+ // QB = 1 * QB
+ //
+ printf("Trying to multiply public keys by one...\n\n");
+ ok_a = test_point_multiplier(&ecdh_qa_x, &ecdh_qa_y, &ecdsa_one, &ecdh_qa_x, &ecdh_qa_y);
+ ok_b = test_point_multiplier(&ecdh_qb_x, &ecdh_qb_y, &ecdsa_one, &ecdh_qb_x, &ecdh_qb_y);
+ if (!ok_a || !ok_b) return EXIT_FAILURE;
+
+
+ //
+ // abuse point multiplier
+ //
+ ok_a = abuse_point_multiplier(&ecdh_qa_x, &ecdh_qa_y);
+ ok_b = abuse_point_multiplier(&ecdh_qb_x, &ecdh_qb_y);
+ if (!ok_a || !ok_b) return EXIT_FAILURE;
+
+
+ //
+ // everything went just fine
+ //
+ return EXIT_SUCCESS;
+}
+
+
+//------------------------------------------------------------------------------
+bool test_point_multiplier(FPGA_BUFFER *px, FPGA_BUFFER *py, FPGA_BUFFER *k, FPGA_BUFFER *qx, FPGA_BUFFER *qy)
+//------------------------------------------------------------------------------
+//
+// (px,py) - multiplicand
+// k - multiplier
+//
+// qx, qy - expected coordinates of product
+//
+// Returns true when point (rx,ry) = k * P matches the point (qx,qy).
+//
+//------------------------------------------------------------------------------
+{
+ bool ok; // flag
+ FPGA_BUFFER rx, ry; // result
+
+ /* run the model */
+ fpga_curve_scalar_multiply(px, py, k, &rx, &ry);
+
+ /* handle result */
+ ok = compare_fpga_buffers(qx, qy, &rx, &ry);
+ if (!ok)
+ { printf("\n ERROR\n\n");
+ return false;
+ }
+ else printf("\n OK\n\n");
+
+ // everything went just fine
+ return true;
+}
+
+
+//------------------------------------------------------------------------------
+bool abuse_point_multiplier(FPGA_BUFFER *qx, FPGA_BUFFER *qy)
+//------------------------------------------------------------------------------
+//
+// This routine tries to abuse the curve point multiplier by triggering the
+// rarely used code path where the internal adder has to add two identical
+// points.
+//
+//------------------------------------------------------------------------------
+{
+ bool ok; // flag
+
+ // obtain quantity n + 2
+ FPGA_BUFFER two, n2;
+ fpga_modular_add(&ecdsa_one, &ecdsa_one, &two); // n1 = n + 1
+ fpga_modular_add(&ecdsa_n, &two, &n2); // n2 = n1 + 1 = n + 2
+
+ printf("Trying to abuse point multiplier...\n\n");
+
+ // we first calculate 2 * Q
+ FPGA_BUFFER q2a_x, q2a_y;
+ fpga_curve_scalar_multiply(qx, qy, &two, &q2a_x, &q2a_y);
+
+ // we now calculate (n + 2) * Q
+ FPGA_BUFFER q2b_x, q2b_y;
+ fpga_curve_scalar_multiply(qx, qy, &n2, &q2b_x, &q2b_y);
+
+ // both calculations should produce the same point (Q2a == Q2b)
+ ok = compare_fpga_buffers(&q2a_x, &q2a_y, &q2b_x, &q2b_y);
+ if (! ok)
+ { printf("\n ERROR\n\n");
+ return false;
+ }
+ else printf("\n OK\n\n");
+
+ // everything went just fine
+ return true;
+}
+
+
+//------------------------------------------------------------------------------
+bool compare_fpga_buffers(FPGA_BUFFER *ax, FPGA_BUFFER *ay, FPGA_BUFFER *bx, FPGA_BUFFER *by)
+//------------------------------------------------------------------------------
+//
+// Compare affine coordinates of two points and return true when they match.
+//
+//------------------------------------------------------------------------------
+{
+ int w; // word counter
+
+ // print all the values
+ print_fpga_buffer(" Expected: X = ", ax);
+ print_fpga_buffer(" Calculated: X = ", bx);
+ printf("\n");
+ print_fpga_buffer(" Expected: Y = ", ay);
+ print_fpga_buffer(" Calculated: Y = ", by);
+
+ // compare values
+ for (w=0; w<OPERAND_NUM_WORDS; w++)
+ {
+ // compare x
+ if (ax->words[w] != bx->words[w]) return false;
+
+ // compare y
+ if (ay->words[w] != by->words[w]) return false;
+ }
+
+ // values are the same
+ return true;
+}
+
+
+//------------------------------------------------------------------------------
+void print_fpga_buffer(const char *s, FPGA_BUFFER *buf)
+//------------------------------------------------------------------------------
+//
+// Pretty print large multi-word integer.
+//
+//------------------------------------------------------------------------------
+{
+ int w; // word counter
+
+ // print header
+ printf("%s", s);
+
+ // print all bytes
+ for (w=OPERAND_NUM_WORDS; w>0; w--)
+ {
+ printf("%08x", buf->words[w-1]);
+
+ // insert space after every group of 4 bytes
+ if (w > 1) printf(" ");
+ }
+
+ // print footer
+ printf("\n");
+}
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------