summaryrefslogtreecommitdiff
path: root/src/common/crypto_ed25519.c
diff options
context:
space:
mode:
authorYawning Angel <yawning@schwanenlied.me>2015-08-12 16:01:28 +0000
committerYawning Angel <yawning@schwanenlied.me>2015-08-12 16:01:28 +0000
commit78fad380cda75b0de86f0d8d2b4d7e55f239f326 (patch)
treef7b9ca624ea88af62ed4f02b65c6408f404bd214 /src/common/crypto_ed25519.c
parentaf898f54752f45fa2a8da28ca88379c89ca1f5a0 (diff)
downloadtor-78fad380cda75b0de86f0d8d2b4d7e55f239f326.tar.gz
tor-78fad380cda75b0de86f0d8d2b4d7e55f239f326.zip
Use ed25519-donna's batch verification support when applicable.
The code was always in our Ed25519 wrappers, so enable it when using the ed25519-donna backend, and deal with the mocking related crypto_rand silliness. Implements feature 16533.
Diffstat (limited to 'src/common/crypto_ed25519.c')
-rw-r--r--src/common/crypto_ed25519.c112
1 files changed, 64 insertions, 48 deletions
diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c
index 3a629322cb..7e995f4616 100644
--- a/src/common/crypto_ed25519.c
+++ b/src/common/crypto_ed25519.c
@@ -37,6 +37,8 @@ typedef struct {
unsigned char *);
int (*sign)(unsigned char *, const unsigned char *, size_t,
const unsigned char *, const unsigned char *);
+ int (*open_batch)(const unsigned char **, size_t *, const unsigned char **,
+ const unsigned char **, size_t, int *);
int (*blind_secret_key)(unsigned char *, const unsigned char *,
const unsigned char *);
@@ -57,6 +59,7 @@ static const ed25519_impl_t impl_ref10 = {
ed25519_ref10_open,
ed25519_ref10_sign,
+ NULL,
ed25519_ref10_blind_secret_key,
ed25519_ref10_blind_public_key,
@@ -74,6 +77,7 @@ static const ed25519_impl_t impl_donna = {
ed25519_donna_open,
ed25519_donna_sign,
+ ed25519_sign_open_batch_donna,
ed25519_donna_blind_secret_key,
ed25519_donna_blind_public_key,
@@ -197,57 +201,69 @@ ed25519_checksig_batch(int *okay_out,
const ed25519_checkable_t *checkable,
int n_checkable)
{
- int res, i;
-
- res = 0;
- for (i = 0; i < n_checkable; ++i) {
- const ed25519_checkable_t *ch = &checkable[i];
- int r = ed25519_checksig(&ch->signature, ch->msg, ch->len, ch->pubkey);
- if (r < 0)
- --res;
- if (okay_out)
- okay_out[i] = (r == 0);
- }
-
-#if 0
- /* This is how we'd do it if we were using ed25519_donna. I'll keep this
- * code around here in case we ever do that. */
- const uint8_t **ms;
- size_t *lens;
- const uint8_t **pks;
- const uint8_t **sigs;
- int *oks;
-
- ms = tor_malloc(sizeof(uint8_t*)*n_checkable);
- lens = tor_malloc(sizeof(size_t)*n_checkable);
- pks = tor_malloc(sizeof(uint8_t*)*n_checkable);
- sigs = tor_malloc(sizeof(uint8_t*)*n_checkable);
- oks = okay_out ? okay_out : tor_malloc(sizeof(int)*n_checkable);
-
- for (i = 0; i < n_checkable; ++i) {
- ms[i] = checkable[i].msg;
- lens[i] = checkable[i].len;
- pks[i] = checkable[i].pubkey->pubkey;
- sigs[i] = checkable[i].signature.sig;
- oks[i] = 0;
- }
-
- ed25519_sign_open_batch_donna_fb(ms, lens, pks, sigs, n_checkable, oks);
+ int i, res;
+ const ed25519_impl_t *impl = get_ed_impl();
- res = 0;
- for (i = 0; i < n_checkable; ++i) {
- /* XXX/yawning: Propagate to okay_out? */
- if (!oks[i])
- --res;
+ if (impl->open_batch == NULL) {
+ /* No batch verification implementation available, fake it by checking the
+ * each signature individually.
+ */
+ res = 0;
+ for (i = 0; i < n_checkable; ++i) {
+ const ed25519_checkable_t *ch = &checkable[i];
+ int r = ed25519_checksig(&ch->signature, ch->msg, ch->len, ch->pubkey);
+ if (r < 0)
+ --res;
+ if (okay_out)
+ okay_out[i] = (r == 0);
+ }
+ } else {
+ /* ed25519-donna style batch verification available.
+ *
+ * Theoretically, this should only be called if n_checkable >= 3, since
+ * that's the threshold where the batch verification actually kicks in,
+ * but the only difference is a few mallocs/frees.
+ */
+ const uint8_t **ms;
+ size_t *lens;
+ const uint8_t **pks;
+ const uint8_t **sigs;
+ int *oks;
+ int all_ok;
+
+ ms = tor_malloc(sizeof(uint8_t*)*n_checkable);
+ lens = tor_malloc(sizeof(size_t)*n_checkable);
+ pks = tor_malloc(sizeof(uint8_t*)*n_checkable);
+ sigs = tor_malloc(sizeof(uint8_t*)*n_checkable);
+ oks = okay_out ? okay_out : tor_malloc(sizeof(int)*n_checkable);
+
+ for (i = 0; i < n_checkable; ++i) {
+ ms[i] = checkable[i].msg;
+ lens[i] = checkable[i].len;
+ pks[i] = checkable[i].pubkey->pubkey;
+ sigs[i] = checkable[i].signature.sig;
+ oks[i] = 0;
+ }
+
+ res = 0;
+ all_ok = impl->open_batch(ms, lens, pks, sigs, n_checkable, oks);
+ for (i = 0; i < n_checkable; ++i) {
+ if (!oks[i])
+ --res;
+ }
+ /* XXX: For now sanity check oks with the return value. Once we have
+ * more confidence in the code, if `all_ok == 0` we can skip iterating
+ * over oks since all the signatures were found to be valid.
+ */
+ tor_assert(((res == 0) && !all_ok) || ((res < 0) && all_ok));
+
+ tor_free(ms);
+ tor_free(lens);
+ tor_free(pks);
+ if (! okay_out)
+ tor_free(oks);
}
- tor_free(ms);
- tor_free(lens);
- tor_free(pks);
- if (! okay_out)
- tor_free(oks);
-#endif
-
return res;
}