From 5c4d3b9b62cd8de2fae6ae49d479ee06173cadc4 Mon Sep 17 00:00:00 2001 From: "Pavel V. Shatov (Meister)" Date: Sun, 6 Aug 2017 21:47:56 +0300 Subject: Added demo program that shows how to talk to the core and sign something. --- src/stm32/modexpa7_driver_sample.c | 306 +++++++++++++++++++++++++++++ src/stm32/test/modexp_fpga_model_vectors.h | 94 +++++++++ 2 files changed, 400 insertions(+) create mode 100644 src/stm32/modexpa7_driver_sample.c create mode 100644 src/stm32/test/modexp_fpga_model_vectors.h diff --git a/src/stm32/modexpa7_driver_sample.c b/src/stm32/modexpa7_driver_sample.c new file mode 100644 index 0000000..4738026 --- /dev/null +++ b/src/stm32/modexpa7_driver_sample.c @@ -0,0 +1,306 @@ +/* + * modexpa7_driver_sample.c + * ---------------------------------------------- + * Demo program to test ModExpA7 core in hardware + * + * Authors: Pavel Shatov + * Copyright (c) 2017, NORDUnet A/S + * All rights reserved. + * + * 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. + */ + + /* + * Note, that the test program needs a custom bitstream without + * the core selector, where the DUT is at offset 0. + */ + + // stm32 headers +#include "stm-init.h" +#include "stm-led.h" +#include "stm-fmc.h" + + // test vectors +#include "test/modexp_fpga_model_vectors.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) +#define CORE_ADDR_MODE (0x10 << 2) +#define CORE_ADDR_MODULUS_BITS (0x11 << 2) +#define CORE_ADDR_EXPONENT_BITS (0x12 << 2) +#define CORE_ADDR_BUFFER_BITS (0x13 << 2) +#define CORE_ADDR_ARRAY_BITS (0x14 << 2) + + + // locations of operand buffers +#define CORE_ADDR_BANK_MODULUS (0x800 + 0 * 0x200) +#define CORE_ADDR_BANK_MESSAGE (0x800 + 1 * 0x200) +#define CORE_ADDR_BANK_EXPONENT (0x800 + 2 * 0x200) +#define CORE_ADDR_BANK_RESULT (0x800 + 3 * 0x200) + + // bit maps +#define CORE_CONTROL_BIT_INIT 0x00000001 +#define CORE_CONTROL_BIT_NEXT 0x00000002 + +#define CORE_STATUS_BIT_READY 0x00000001 +#define CORE_STATUS_BIT_VALID 0x00000002 + +#define CORE_MODE_BIT_CRT 0x00000002 + + + /* + * test vectors + */ +static const uint32_t m_384[] = M_384; +static const uint32_t n_384[] = N_384; +static const uint32_t d_384[] = D_384; +static const uint32_t s_384[] = S_384; + +static const uint32_t m_512[] = M_512; +static const uint32_t n_512[] = N_512; +static const uint32_t d_512[] = D_512; +static const uint32_t s_512[] = S_512; + + + /* + * prototypes + */ +void toggle_yellow_led(void); + +void setup_modexpa7( const uint32_t *n, size_t l); + +int test_modexpa7( const uint32_t *m, + const uint32_t *d, + const uint32_t *s, + size_t l); + + + /* + * test routine + */ +int main() +{ + int ok; + + stm_init(); + fmc_init(); + + // turn on the green led + led_on(LED_GREEN); + led_off(LED_RED); + led_off(LED_YELLOW); + led_off(LED_BLUE); + + // check, that core is present + uint32_t core_name0; + uint32_t core_name1; + uint32_t core_version; + + fmc_read_32(CORE_ADDR_NAME0, &core_name0); + fmc_read_32(CORE_ADDR_NAME1, &core_name1); + fmc_read_32(CORE_ADDR_VERSION, &core_version); + + // must be "mode", "xpa7", "0.20" + if ( (core_name0 != 0x6D6F6465) || + (core_name1 != 0x78706137) || + (core_version != 0x302E3230)) + { + led_off(LED_GREEN); + led_on(LED_RED); + while (1); + } + + // read compile-time settings + uint32_t core_buffer_bits; + uint32_t core_array_bits; + + // largest supported operand width, systolic array "power" + fmc_read_32(CORE_ADDR_BUFFER_BITS, &core_buffer_bits); + fmc_read_32(CORE_ADDR_ARRAY_BITS, &core_array_bits); + + // repeat forever + while (1) + { + // New modulus requires precomputation of modulus-dependent + // speed-up coefficient, this must be done once per new + // modulus, i.e. when we're repeatedly signing with the + // same key, we only need to do precomputation once before + // starting the very first signing operation. + + // fresh start + ok = 1; + + { + // run precomputation of modulus-dependent factor for the 384-bit modulus + setup_modexpa7(n_384, 384); + + // try signing the message from the 384-bit test vector + ok = ok && test_modexpa7(m_384, d_384, s_384, 384); + } + { + // run precomputation of modulus-dependent factor for the 512-bit modulus + setup_modexpa7(n_512, 512); + + // try signing the message from the 512-bit test vector + ok = ok && test_modexpa7(m_512, d_512, s_512, 512); + } + + // turn on the red led to indicate something went wrong + if (!ok) + { led_off(LED_GREEN); + led_on(LED_RED); + } + + // indicate, that we're alive doing something... + toggle_yellow_led(); + } +} + + + /* + * Load new modulus and do the necessary precomputations. + */ +void setup_modexpa7( const uint32_t *n, + size_t l) +{ + size_t i, num_words; + uint32_t num_bits; + uint32_t reg_control, reg_status; + uint32_t n_word; + uint32_t dummy_num_cyc; + + // determine numbers of 32-bit words + num_words = l >> 5; + + // set modulus width + num_bits = l; + fmc_write_32(CORE_ADDR_MODULUS_BITS, &num_bits); + + // fill modulus bank (the least significant word + // is at the lowest offset) + for (i=0; i> 5; + + // set exponent width + num_bits = l; + fmc_write_32(CORE_ADDR_EXPONENT_BITS, &num_bits); + + // fill modulus bank (the least significant word + // is at the lowest offset) + for (i=0; i