//------------------------------------------------------------------------------ // // ecdsa_model_fpga.cpp // -------------------------------------------- // 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. // //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Headers //------------------------------------------------------------------------------ #include #include #include #include "ecdsa_model.h" #include "fpga_lowlevel.h" #include "fpga_modular.h" #include "fpga_curve.h" #include "fpga_util.h" //------------------------------------------------------------------------------ // Prototypes //------------------------------------------------------------------------------ void fpga_model_init (); bool test_base_point_multiplier (FPGA_BUFFER *k, FPGA_BUFFER *qx, FPGA_BUFFER *qy); bool abuse_internal_point_adder (); bool abuse_internal_point_doubler (); 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); bool compare_fpga_buffers (FPGA_BUFFER *ax, FPGA_BUFFER *ay, FPGA_BUFFER *az, FPGA_BUFFER *bx, FPGA_BUFFER *by, FPGA_BUFFER *bz); //------------------------------------------------------------------------------ // Locals //------------------------------------------------------------------------------ static FPGA_BUFFER ecdsa_d; static FPGA_BUFFER ecdsa_k; static FPGA_BUFFER ecdsa_n; //------------------------------------------------------------------------------ int main() //------------------------------------------------------------------------------ { bool ok; // flag // // initialize buffers // fpga_model_init(); fpga_modular_init(); fpga_curve_init(); // // test base point multiplier: Q = d * G // printf("Trying to derive public key from private key...\n\n"); ok = test_base_point_multiplier(&ecdsa_d, &ecdsa_q_x, &ecdsa_q_y); if (!ok) return EXIT_FAILURE; // // test base point multiplier: R = k * G // printf("Trying to sign something...\n\n"); ok = test_base_point_multiplier(&ecdsa_k, &ecdsa_r_x, &ecdsa_r_y); if (!ok) return EXIT_FAILURE; // // test base point multiplier: O = n * G // printf("Trying to multiply the base point by its order...\n\n"); ok = test_base_point_multiplier(&ecdsa_n, &ecdsa_zero, &ecdsa_zero); if (!ok) return EXIT_FAILURE; // // test base point multiplier: H = 2 * G // FPGA_BUFFER two; fpga_modular_add(&ecdsa_one, &ecdsa_one, &two); printf("Trying to double the base point...\n\n"); ok = test_base_point_multiplier(&two, &ecdsa_h_x, &ecdsa_h_y); if (!ok) return EXIT_FAILURE; // // test base point multiplier: G = (n + 1) * G // FPGA_BUFFER n1; fpga_modular_add(&ecdsa_n, &ecdsa_one, &n1); // n1 = n + 1 printf("Trying to multiply the base point by its order plus one...\n\n"); ok = test_base_point_multiplier(&n1, &ecdsa_g_x, &ecdsa_g_y); if (!ok) return EXIT_FAILURE; // // test base point multiplier: G = (n + 2) * G // FPGA_BUFFER n2; fpga_modular_add(&ecdsa_n, &two, &n2); // n2 = n + two printf("Trying to multiply the base point by its order plus two...\n\n"); ok = test_base_point_multiplier(&n2, &ecdsa_h_x, &ecdsa_h_y); if (!ok) return EXIT_FAILURE; // // try to abuse internal point doubler // ok = abuse_internal_point_doubler(); if (!ok) return EXIT_FAILURE; // // try to abuse internal point adder // ok = abuse_internal_point_adder(); if (!ok) return EXIT_FAILURE; // // everything went just fine // return EXIT_SUCCESS; } //------------------------------------------------------------------------------ void fpga_model_init() //------------------------------------------------------------------------------ { int w; // word counter FPGA_BUFFER tmp_d = ECDSA_D; FPGA_BUFFER tmp_k = ECDSA_K; FPGA_BUFFER tmp_n = ECDSA_N; /* fill buffers for large multi-word integers */ for (w=0; w0; w--) { printf("%08x", buf->words[w-1]); // insert space after every group of 4 bytes if (w > 1) printf(" "); } // print footer printf("\n"); } //------------------------------------------------------------------------------ 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; wwords[w] != bx->words[w]) return false; // compare y if (ay->words[w] != by->words[w]) return false; } // values are the same return true; } //------------------------------------------------------------------------------ bool compare_fpga_buffers(FPGA_BUFFER *ax, FPGA_BUFFER *ay, FPGA_BUFFER *az, FPGA_BUFFER *bx, FPGA_BUFFER *by, FPGA_BUFFER *bz) //------------------------------------------------------------------------------ // // Compare projective 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); printf("\n"); print_fpga_buffer(" Expected: Z = ", az); print_fpga_buffer(" Calculated: Z = ", bz); // compare values for (w=0; wwords[w] != bx->words[w]) return false; // compare y if (ay->words[w] != by->words[w]) return false; // compare z if (az->words[w] != bz->words[w]) return false; } // values are the same return true; } //------------------------------------------------------------------------------ // End-of-File //------------------------------------------------------------------------------