aboutsummaryrefslogblamecommitdiff
path: root/ecdh_fpga_model.cpp
blob: 8d2be889d9ec3e8f7b0d331e3cfa1e9874c21a8d (plain) (tree)

































































                                                                                                                                     
                                                        


















































                                                                                                    
                                                              

                                                              
                                                         




















































                                                                                                              




                                                                              


                                                          









                                                                


















































































                                                                                             
//------------------------------------------------------------------------------
//
// 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, ok_g;		// 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_g = abuse_point_multiplier(&ecdsa_g_x, &ecdsa_g_y);
	ok_a = abuse_point_multiplier(&ecdh_qa_x, &ecdh_qa_y);
	ok_b = abuse_point_multiplier(&ecdh_qb_x, &ecdh_qb_y);
	if (!ok_g || !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 + 1, n + 2
	FPGA_BUFFER two, n1, n2;
	fpga_modular_add(&ecdsa_one, &ecdsa_one, &two);	// n1 = n + 1
	fpga_modular_add(&ecdsa_n,   &ecdsa_one, &n1);	// n1 = n + 1
	fpga_modular_add(&n1,        &ecdsa_one, &n2);	// n2 = n1 + 1 = n + 2

	printf("Trying to abuse point multiplier...\n\n");

		// make sure, that (n + 1) * Q = Q
	FPGA_BUFFER qn1_x, qn1_y;
	fpga_curve_scalar_multiply(qx, qy, &n1, &qn1_x, &qn1_y);
	ok = compare_fpga_buffers(qx, qy, &qn1_x, &qn1_y);
	if (! ok)
	{	printf("\n    ERROR\n\n");
		return false;
	}
	else printf("\n    OK\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
//------------------------------------------------------------------------------