diff options
-rw-r--r-- | ecdsa.c | 77 | ||||
-rw-r--r-- | hal.h | 3 | ||||
-rw-r--r-- | verilog_constants.h | 18 |
3 files changed, 97 insertions, 1 deletions
@@ -89,6 +89,18 @@ #endif /* + * Whether to use experimental Verilog ECDSA-P256 point multiplier. + */ + +#ifndef HAL_ECDSA_VERILOG_ECDSA256_MULTIPLIER +#define HAL_ECDSA_VERILOG_ECDSA256_MULTIPLIER 1 +#endif + +#if HAL_ECDSA_VERILOG_ECDSA256_MULTIPLIER +static int verilog_ecdsa256_multiplier = 1; +#endif + +/* * Whether we want debug output. */ @@ -749,6 +761,65 @@ static inline hal_error_t get_random(void *buffer, const size_t length) #endif /* HAL_ECDSA_DEBUG_ONLY_STATIC_TEST_VECTOR_RANDOM */ /* + * Use experimental Verilog base point multiplier core to calculate + * public key given a private key. point_pick_random() has already + * selected a suitable private key for us, we just need to calculate + * the corresponding public key. + */ + +#if HAL_ECDSA_VERILOG_ECDSA256_MULTIPLIER + +static hal_error_t verilog_point_pick_random(fp_int *k, ec_point_t *P) +{ + assert(k != NULL && P != NULL); + + const size_t len = fp_unsigned_bin_size(k); + uint8_t b[ECDSA256_OPERAND_BITS / 8]; + const uint8_t zero[4] = {0, 0, 0, 0}; + hal_core_t *core = NULL; + hal_error_t err; + + if (len > sizeof(b)) + return HAL_ERROR_RESULT_TOO_LONG; + + if ((err = hal_core_alloc(ECDSA256_NAME, &core)) != HAL_OK) + goto fail; + +#define check(_x_) do { if ((err = (_x_)) != HAL_OK) goto fail; } while (0) + + memset(b, 0, sizeof(b)); + fp_to_unsigned_bin(k, b + sizeof(b) - len); + + for (int i = 0; i < sizeof(b); i += 4) + check(hal_io_write(core, ECDSA256_ADDR_K + i/4, &b[sizeof(b) - 4 - i], 4)); + + check(hal_io_write(core, ADDR_CTRL, zero, sizeof(zero))); + check(hal_io_next(core)); + check(hal_io_wait_ready(core)); + + for (int i = 0; i < sizeof(b); i += 4) + check(hal_io_read(core, ECDSA256_ADDR_X + i/4, &b[sizeof(b) - 4 - i], 4)); + fp_read_unsigned_bin(P->x, b, sizeof(b)); + + for (int i = 0; i < sizeof(b); i += 4) + check(hal_io_read(core, ECDSA256_ADDR_Y + i/4, &b[sizeof(b) - 4 - i], 4)); + fp_read_unsigned_bin(P->y, b, sizeof(b)); + + fp_set(P->z, 1); + +#undef check + + err = HAL_OK; + + fail: + hal_core_free(core); + memset(b, 0, sizeof(b)); + return err; +} + +#endif + +/* * Pick a random point on the curve, return random scalar and * resulting point. */ @@ -792,6 +863,12 @@ static hal_error_t point_pick_random(const ecdsa_curve_t * const curve, memset(k_buf, 0, sizeof(k_buf)); +#if HAL_ECDSA_VERILOG_ECDSA256_MULTIPLIER + if (verilog_ecdsa256_multiplier && curve == get_curve(HAL_CURVE_P256) && + (err = verilog_point_pick_random(k, P)) != HAL_ERROR_CORE_NOT_FOUND) + return err; +#endif + /* * Calculate P = kG and return. */ @@ -103,6 +103,9 @@ #define MKMIF_NAME "mkmif " #define MKMIF_VERSION "0.10" +#define ECDSA256_NAME "ecdsa256" +#define ECDSA256_VERSION "0.11" + /* * C API error codes. Defined in this form so we can keep the tokens * and error strings together. See errorstrings.c. diff --git a/verilog_constants.h b/verilog_constants.h index f0ae070..900785c 100644 --- a/verilog_constants.h +++ b/verilog_constants.h @@ -8,7 +8,7 @@ * hand-edited. * * Authors: Joachim Strombergson, Paul Selkirk, Rob Austein - * Copyright (c) 2015-2016, NORDUnet A/S All rights reserved. + * Copyright (c) 2015-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 @@ -241,6 +241,22 @@ #define MODEXPA7_ADDR_RESULT (MODEXPA7_ADDR_OPERANDS + 3 * MODEXPA7_OPERAND_WORDS) /* + * ECDSA P-256 point mulitipler core. ECDSA256_OPERAND_BITS is size + * in bits of the (only) supported operand size (256 bits, imagine that). + * + * (Not sure which category EC Point Mulitiplier will end up in, but + * let's pretend it's "math".) + */ + +#define ECDSA256_OPERAND_BITS (256) +#define ECDSA256_OPERAND_WORDS (ECDSA256_OPERAND_BITS / 32) +#define ECDSA256_ADDR_REGISTERS (0 * ECDSA256_OPERAND_WORDS) +#define ECDSA256_ADDR_OPERANDS (4 * ECDSA256_OPERAND_WORDS) +#define ECDSA256_ADDR_K (ECDSA256_ADDR_OPERANDS + 0 * ECDSA256_OPERAND_WORDS) +#define ECDSA256_ADDR_X (ECDSA256_ADDR_OPERANDS + 1 * ECDSA256_OPERAND_WORDS) +#define ECDSA256_ADDR_Y (ECDSA256_ADDR_OPERANDS + 2 * ECDSA256_OPERAND_WORDS) + +/* * Utility cores. */ |