[tor-commits] [tor/master] Introduce ed25519_{sign, checksig}_prefixed functions().

nickm at torproject.org nickm at torproject.org
Tue Aug 23 13:00:17 UTC 2016


commit b8bfdf638e9448ecda9dda1a2c02d7bbf4778341
Author: George Kadianakis <desnacked at riseup.net>
Date:   Tue Aug 23 14:53:01 2016 +0300

    Introduce ed25519_{sign,checksig}_prefixed functions().
---
 src/common/crypto_ed25519.c | 95 +++++++++++++++++++++++++++++++++++++++++++++
 src/common/crypto_ed25519.h | 11 ++++++
 src/test/test_crypto.c      | 35 +++++++++++++++++
 3 files changed, 141 insertions(+)

diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c
index 84c3eec..817c1a2 100644
--- a/src/common/crypto_ed25519.c
+++ b/src/common/crypto_ed25519.c
@@ -184,9 +184,43 @@ ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong)
   return 0;
 }
 
+/* Return a heap-allocated array that contains <b>msg</b> prefixed by the
+ * string <b>prefix_str</b>. Set <b>final_msg_len_out</b> to the size of the
+ * final array. If an error occured, return NULL. It's the resonsibility of the
+ * caller to free the returned array. */
+static uint8_t *
+get_prefixed_msg(const uint8_t *msg, size_t msg_len,
+                 const char *prefix_str,
+                 size_t *final_msg_len_out)
+{
+  size_t prefixed_msg_len, prefix_len;
+  uint8_t *prefixed_msg;
+
+  tor_assert(prefix_str);
+  tor_assert(final_msg_len_out);
+
+  prefix_len = strlen(prefix_str);
+
+  /* msg_len + strlen(prefix_str) must not overflow. */
+  if (msg_len > SIZE_T_CEILING - prefix_len) {
+    return NULL;
+  }
+
+  prefixed_msg_len = msg_len + prefix_len;
+  prefixed_msg = tor_malloc_zero(prefixed_msg_len);
+
+  memcpy(prefixed_msg, prefix_str, prefix_len);
+  memcpy(prefixed_msg + prefix_len, msg, msg_len);
+
+  *final_msg_len_out = prefixed_msg_len;
+  return prefixed_msg;
+}
+
 /**
  * Set <b>signature_out</b> to a signature of the <b>len</b>-byte message
  * <b>msg</b>, using the secret and public key in <b>keypair</b>.
+ *
+ * Return 0 if we successfuly signed the message, otherwise return -1.
  */
 int
 ed25519_sign(ed25519_signature_t *signature_out,
@@ -203,6 +237,37 @@ ed25519_sign(ed25519_signature_t *signature_out,
 }
 
 /**
+ * Like ed25519_sign(), but also prefix <b>msg</b> with <b>prefix_str</b>
+ * before signing. <b>prefix_str</b> must be a NUL-terminated string.
+ */
+int
+ed25519_sign_prefixed(ed25519_signature_t *signature_out,
+                      const uint8_t *msg, size_t msg_len,
+                      const char *prefix_str,
+                      const ed25519_keypair_t *keypair)
+{
+  int retval;
+  size_t prefixed_msg_len;
+  uint8_t *prefixed_msg;
+
+  tor_assert(prefix_str);
+
+  prefixed_msg = get_prefixed_msg(msg, msg_len, prefix_str,
+                                  &prefixed_msg_len);
+  if (!prefixed_msg) {
+    log_warn(LD_GENERAL, "Failed to get prefixed msg.");
+    return -1;
+  }
+
+  retval = ed25519_sign(signature_out,
+                        prefixed_msg, prefixed_msg_len,
+                        keypair);
+  tor_free(prefixed_msg);
+
+  return retval;
+}
+
+/**
  * Check whether if <b>signature</b> is a valid signature for the
  * <b>len</b>-byte message in <b>msg</b> made with the key <b>pubkey</b>.
  *
@@ -217,6 +282,36 @@ ed25519_checksig(const ed25519_signature_t *signature,
     get_ed_impl()->open(signature->sig, msg, len, pubkey->pubkey) < 0 ? -1 : 0;
 }
 
+/**
+ * Like ed2519_checksig(), but also prefix <b>msg</b> with <b>prefix_str</b>
+ * before verifying signature. <b>prefix_str</b> must be a NUL-terminated
+ * string.
+ */
+int
+ed25519_checksig_prefixed(const ed25519_signature_t *signature,
+                          const uint8_t *msg, size_t msg_len,
+                          const char *prefix_str,
+                          const ed25519_public_key_t *pubkey)
+{
+  int retval;
+  size_t prefixed_msg_len;
+  uint8_t *prefixed_msg;
+
+  prefixed_msg = get_prefixed_msg(msg, msg_len, prefix_str,
+                                  &prefixed_msg_len);
+  if (!prefixed_msg) {
+    log_warn(LD_GENERAL, "Failed to get prefixed msg.");
+    return -1;
+  }
+
+  retval = ed25519_checksig(signature,
+                            prefixed_msg, prefixed_msg_len,
+                            pubkey);
+  tor_free(prefixed_msg);
+
+  return retval;
+}
+
 /** Validate every signature among those in <b>checkable</b>, which contains
  * exactly <b>n_checkable</b> elements.  If <b>okay_out</b> is non-NULL, set
  * the i'th element of <b>okay_out</b> to 1 if the i'th element of
diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h
index 44c2ad9..31afc49 100644
--- a/src/common/crypto_ed25519.h
+++ b/src/common/crypto_ed25519.h
@@ -55,6 +55,17 @@ int ed25519_checksig(const ed25519_signature_t *signature,
                      const uint8_t *msg, size_t len,
                      const ed25519_public_key_t *pubkey);
 
+int
+ed25519_sign_prefixed(ed25519_signature_t *signature_out,
+                      const uint8_t *msg, size_t len,
+                      const char *prefix_str,
+                      const ed25519_keypair_t *keypair);
+int
+ed25519_checksig_prefixed(const ed25519_signature_t *signature,
+                          const uint8_t *msg, size_t len,
+                          const char *prefix_str,
+                          const ed25519_public_key_t *pubkey);
+
 /**
  * A collection of information necessary to check an Ed25519 signature. Used
  * for batch verification.
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index ba2fb86..542512b 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -2242,6 +2242,41 @@ test_crypto_ed25519_simple(void *arg)
     tt_int_op(0, OP_EQ, ed25519_checksig_batch(NULL, ch, 2));
   }
 
+  /* Test the string-prefixed sign/checksig functions */
+  {
+    ed25519_signature_t manual_sig;
+    char *prefixed_msg;
+
+    /* Generate a signature with a prefixed msg. */
+    tt_int_op(0, OP_EQ, ed25519_sign_prefixed(&sig1, msg, msg_len,
+                                              "always in the mood",
+                                              &kp1));
+
+    /* First, check that ed25519_sign_prefixed() returns the exact same sig as
+       if we had manually prefixed the msg ourselves. */
+    tor_asprintf(&prefixed_msg, "%s%s", "always in the mood", msg);
+    tt_int_op(0, OP_EQ, ed25519_sign(&manual_sig, (uint8_t *)prefixed_msg,
+                                     strlen(prefixed_msg), &kp1));
+    tor_free(prefixed_msg);
+    tt_assert(!memcmp(sig1.sig, manual_sig.sig, sizeof(sig1.sig)));
+
+    /* Test that prefixed checksig verifies it properly. */
+    tt_int_op(0, OP_EQ, ed25519_checksig_prefixed(&sig1, msg, msg_len,
+                                                  "always in the mood",
+                                                  &pub1));
+
+    /* Test that checksig with wrong prefix fails. */
+    tt_int_op(-1, OP_EQ, ed25519_checksig_prefixed(&sig1, msg, msg_len,
+                                                   "always in the moo",
+                                                   &pub1));
+    tt_int_op(-1, OP_EQ, ed25519_checksig_prefixed(&sig1, msg, msg_len,
+                                                   "always in the moon",
+                                                   &pub1));
+    tt_int_op(-1, OP_EQ, ed25519_checksig_prefixed(&sig1, msg, msg_len,
+                                                   "always in the mood!",
+                                                   &pub1));
+  }
+
  done:
   ;
 }





More information about the tor-commits mailing list