diff options
author | Rob Austein <sra@hactrn.net> | 2017-03-02 17:23:02 -0500 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2017-03-02 17:23:02 -0500 |
commit | 9afc5d0b081983779439aa6f91781efb3e56d01d (patch) | |
tree | db5981bc28b89501462026aca3269fb2f561171e | |
parent | 99407a540c7f1fbbc0987837173d1b81aee790bc (diff) |
Refactor to add P384 support. Untested.
-rw-r--r-- | ecdsa.c | 109 | ||||
-rw-r--r-- | hal.h | 3 | ||||
-rw-r--r-- | verilog_constants.h | 26 |
3 files changed, 119 insertions, 19 deletions
@@ -101,6 +101,25 @@ static int verilog_ecdsa256_multiplier = 1; #endif /* + * Whether to use experimental Verilog ECDSA-P384 point multiplier. + */ + +#ifndef HAL_ECDSA_VERILOG_ECDSA384_MULTIPLIER +#define HAL_ECDSA_VERILOG_ECDSA384_MULTIPLIER 1 +#endif + +#if HAL_ECDSA_VERILOG_ECDSA384_MULTIPLIER +static int verilog_ecdsa384_multiplier = 1; +#endif + +/* + * Whether to include Verilog point multiplier code at all. + */ + +#define HAL_ECDSA_ANY_VERILOG_MULTIPLIER \ + (HAL_ECDSA_VERILOG_ECDSA256_MULTIPLIER | HAL_ECDSA_VERILOG_ECDSA384_MULTIPLIER) + +/* * Whether we want debug output. */ @@ -136,6 +155,7 @@ typedef struct { fp_digit rho; /* Montgomery reduction value */ const uint8_t *oid; /* OBJECT IDENTIFIER */ size_t oid_len; /* Length of OBJECT IDENTIFIER */ + hal_curve_name_t curve; /* Curve name */ } ecdsa_curve_t; /* @@ -218,6 +238,7 @@ static const ecdsa_curve_t * const get_curve(const hal_curve_name_t curve) fp_montgomery_calc_normalization(curve_p256.mu, curve_p256.q); curve_p256.oid = p256_oid; curve_p256.oid_len = sizeof(p256_oid); + curve_p256.curve = HAL_CURVE_P256; fp_read_unsigned_bin(curve_p384.q, unconst_uint8_t(p384_q), sizeof(p384_q)); fp_read_unsigned_bin(curve_p384.b, unconst_uint8_t(p384_b), sizeof(p384_b)); @@ -230,6 +251,7 @@ static const ecdsa_curve_t * const get_curve(const hal_curve_name_t curve) fp_montgomery_calc_normalization(curve_p384.mu, curve_p384.q); curve_p384.oid = p384_oid; curve_p384.oid_len = sizeof(p384_oid); + curve_p384.curve = HAL_CURVE_P384; fp_read_unsigned_bin(curve_p521.q, unconst_uint8_t(p521_q), sizeof(p521_q)); fp_read_unsigned_bin(curve_p521.b, unconst_uint8_t(p521_b), sizeof(p521_b)); @@ -242,6 +264,7 @@ static const ecdsa_curve_t * const get_curve(const hal_curve_name_t curve) fp_montgomery_calc_normalization(curve_p521.mu, curve_p521.q); curve_p521.oid = p521_oid; curve_p521.oid_len = sizeof(p521_oid); + curve_p521.curve = HAL_CURVE_P521; initialized = 1; } @@ -761,20 +784,30 @@ 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 + * Use experimental Verilog base point multiplier cores 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 +#if HAL_ECDSA_ANY_VERILOG_MULTIPLIER -static hal_error_t verilog_point_pick_random(fp_int *k, ec_point_t *P) +typedef struct { + size_t bytes; + const char *name; + hal_addr_t k_addr; + hal_addr_t x_addr; + hal_addr_t y_addr; +} verilog_ecdsa_driver_t; + +static hal_error_t verilog_point_pick_random(const verilog_ecdsa_driver_t * const driver, + 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]; + uint8_t b[driver->bytes]; const uint8_t zero[4] = {0, 0, 0, 0}; hal_core_t *core = NULL; hal_error_t err; @@ -782,7 +815,7 @@ static hal_error_t verilog_point_pick_random(fp_int *k, ec_point_t *P) if (len > sizeof(b)) return HAL_ERROR_RESULT_TOO_LONG; - if ((err = hal_core_alloc(ECDSA256_NAME, &core)) != HAL_OK) + if ((err = hal_core_alloc(driver->name, &core)) != HAL_OK) goto fail; #define check(_x_) do { if ((err = (_x_)) != HAL_OK) goto fail; } while (0) @@ -791,18 +824,18 @@ static hal_error_t verilog_point_pick_random(fp_int *k, ec_point_t *P) 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, driver->k_addr + 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)); + check(hal_io_read(core, driver->x_addr + 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)); + check(hal_io_read(core, driver->y_addr + i/4, &b[sizeof(b) - 4 - i], 4)); fp_read_unsigned_bin(P->y, b, sizeof(b)); fp_set(P->z, 1); @@ -819,6 +852,46 @@ static hal_error_t verilog_point_pick_random(fp_int *k, ec_point_t *P) #endif +static inline hal_error_t verilog_p256_point_pick_random(fp_int *k, ec_point_t *P) +{ +#if HAL_ECDSA_VERILOG_ECDSA256_MULTIPLIER + + static const verilog_ecdsa_driver_t verilog_p256_driver = { + .name = ECDSA256_NAME, + .bytes = ECDSA256_OPERAND_BITS / 8, + .k_addr = ECDSA256_ADDR_K, + .x_addr = ECDSA256_ADDR_X, + .y_addr = ECDSA256_ADDR_Y + }; + + if (verilog_ecdsa256_multiplier) + return verilog_point_pick_random(&verilog_p256_driver, k, P); + +#endif + + return HAL_ERROR_CORE_NOT_FOUND; +} + +static inline hal_error_t verilog_p384_point_pick_random(fp_int *k, ec_point_t *P) +{ +#if HAL_ECDSA_VERILOG_ECDSA384_MULTIPLIER + + static const verilog_ecdsa_driver_t verilog_p384_driver = { + .name = ECDSA384_NAME, + .bytes = ECDSA384_OPERAND_BITS / 8, + .k_addr = ECDSA384_ADDR_K, + .x_addr = ECDSA384_ADDR_X, + .y_addr = ECDSA384_ADDR_Y + }; + + if (verilog_ecdsa256_multiplier) + return verilog_point_pick_random(&verilog_p256_driver, k, P); + +#endif + + return HAL_ERROR_CORE_NOT_FOUND; +} + /* * Pick a random point on the curve, return random scalar and * resulting point. @@ -863,10 +936,22 @@ 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; +#if HAL_ECDSA_ANY_VERILOG_MULTIPLIER + switch (curve->curve) { + + case HAL_CURVE_P256: + if ((err = verilog_p256_point_pick_random(k, P)) != HAL_ERROR_CORE_NOT_FOUND) + return err; + break; + + case HAL_CURVE_P384: + if ((err = verilog_p384_point_pick_random(k, P)) != HAL_ERROR_CORE_NOT_FOUND) + return err; + break; + + default: + break; + } #endif /* @@ -106,6 +106,9 @@ #define ECDSA256_NAME "ecdsa256" #define ECDSA256_VERSION "0.11" +#define ECDSA256_NAME "ecdsa384" +#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 900785c..c9bb566 100644 --- a/verilog_constants.h +++ b/verilog_constants.h @@ -241,7 +241,7 @@ #define MODEXPA7_ADDR_RESULT (MODEXPA7_ADDR_OPERANDS + 3 * MODEXPA7_OPERAND_WORDS) /* - * ECDSA P-256 point mulitipler core. ECDSA256_OPERAND_BITS is size + * ECDSA P-256 point multiplier 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 @@ -249,12 +249,24 @@ */ #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) +#define ECDSA256_ADDR_REGISTERS (0x00) +#define ECDSA256_ADDR_K (0x20) +#define ECDSA256_ADDR_X (0x28) +#define ECDSA256_ADDR_Y (0x30) + +/* + * ECDSA P-384 point multiplier core. ECDSA384_OPERAND_BITS is size + * in bits of the (only) supported operand size (384 bits, imagine that). + * + * (Not sure which category EC Point Mulitiplier will end up in, but + * let's pretend it's "math".) + */ + +#define ECDSA384_OPERAND_BITS (384) +#define ECDSA384_ADDR_REGISTERS (0x00) +#define ECDSA384_ADDR_K (0x40) +#define ECDSA384_ADDR_X (0x50) +#define ECDSA384_ADDR_Y (0x60) /* * Utility cores. |