Loading src/common/crypto_ed25519.c +95 −0 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -202,6 +236,37 @@ ed25519_sign(ed25519_signature_t *signature_out, return 0; } /** * 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>. Loading @@ -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 Loading src/common/crypto_ed25519.h +11 −0 Original line number Diff line number Diff line Loading @@ -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. Loading src/test/test_crypto.c +35 −0 Original line number Diff line number Diff line Loading @@ -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: ; } Loading Loading
src/common/crypto_ed25519.c +95 −0 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -202,6 +236,37 @@ ed25519_sign(ed25519_signature_t *signature_out, return 0; } /** * 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>. Loading @@ -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 Loading
src/common/crypto_ed25519.h +11 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
src/test/test_crypto.c +35 −0 Original line number Diff line number Diff line Loading @@ -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: ; } Loading