summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2016-08-23 08:50:32 -0400
committerNick Mathewson <nickm@torproject.org>2016-08-23 08:50:32 -0400
commita3d419634bef0bbac4118d08272d59c9fe66a1bb (patch)
tree4f5dcec8a4f6b8bff495f36db345ba80204cd264
parentb3f43a22ab921ce6e256dd8f4e1cbedf2d280392 (diff)
parentb8bfdf638e9448ecda9dda1a2c02d7bbf4778341 (diff)
downloadtor-a3d419634bef0bbac4118d08272d59c9fe66a1bb.tar.gz
tor-a3d419634bef0bbac4118d08272d59c9fe66a1bb.zip
Merge remote-tracking branch 'asn/bug19872_v2'
-rw-r--r--src/common/crypto_ed25519.c95
-rw-r--r--src/common/crypto_ed25519.h11
-rw-r--r--src/test/test_crypto.c35
3 files changed, 141 insertions, 0 deletions
diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c
index 84c3eece6d..817c1a271b 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 44c2ad9775..31afc49ccc 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 ba2fb86246..542512bd44 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:
;
}