aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ecdsa.c77
-rw-r--r--hal.h3
-rw-r--r--verilog_constants.h18
3 files changed, 97 insertions, 1 deletions
diff --git a/ecdsa.c b/ecdsa.c
index 916a2f4..42ea307 100644
--- a/ecdsa.c
+++ b/ecdsa.c
@@ -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.
*/
diff --git a/hal.h b/hal.h
index 72b1d58..b1a217a 100644
--- a/hal.h
+++ b/hal.h
@@ -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.
*/