From b8bfdf638e9448ecda9dda1a2c02d7bbf4778341 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Tue, 23 Aug 2016 14:53:01 +0300 Subject: Introduce ed25519_{sign,checksig}_prefixed functions(). --- src/common/crypto_ed25519.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ src/common/crypto_ed25519.h | 11 ++++++ 2 files changed, 106 insertions(+) (limited to 'src/common') 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 msg prefixed by the + * string prefix_str. Set final_msg_len_out 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 signature_out to a signature of the len-byte message * msg, using the secret and public key in keypair. + * + * Return 0 if we successfuly signed the message, otherwise return -1. */ int ed25519_sign(ed25519_signature_t *signature_out, @@ -202,6 +236,37 @@ ed25519_sign(ed25519_signature_t *signature_out, return 0; } +/** + * Like ed25519_sign(), but also prefix msg with prefix_str + * before signing. prefix_str 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 signature is a valid signature for the * len-byte message in msg made with the key pubkey. @@ -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 msg with prefix_str + * before verifying signature. prefix_str 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 checkable, which contains * exactly n_checkable elements. If okay_out is non-NULL, set * the i'th element of okay_out 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. -- cgit v1.2.3-54-g00ecf