From 1df12e3915bb7713a3122cee27827072077b51f6 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 21 Aug 2015 23:13:59 +0100 Subject: [PATCH] Add copy and free methods to 'struct ssh_hash'. This permits a hash state to be cloned in the middle of being used, so that multiple strings with the same prefix can be hashed without having to repeat all the computation over the prefix. Having done that, we'll also sometimes need to free a hash state that we aren't generating actual hash output from, so we need a free method as well. --- ssh.h | 2 ++ sshsh256.c | 24 +++++++++++++++++++++--- sshsh512.c | 27 +++++++++++++++++++++++---- sshsha.c | 23 ++++++++++++++++++++--- 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/ssh.h b/ssh.h index db694c58..139ea33f 100644 --- a/ssh.h +++ b/ssh.h @@ -353,8 +353,10 @@ struct ssh_mac { struct ssh_hash { void *(*init)(void); /* also allocates context */ + void *(*copy)(const void *); void (*bytes)(void *, const void *, int); void (*final)(void *, unsigned char *); /* also frees context */ + void (*free)(void *); int hlen; /* output length in bytes */ const char *text_name; }; diff --git a/sshsh256.c b/sshsh256.c index 8e3d4fc1..b2bd862e 100644 --- a/sshsh256.c +++ b/sshsh256.c @@ -200,6 +200,24 @@ static void *sha256_init(void) return s; } +static void *sha256_copy(const void *vold) +{ + const SHA256_State *old = (const SHA256_State *)vold; + SHA256_State *s; + + s = snew(SHA256_State); + *s = *old; + return s; +} + +static void sha256_free(void *handle) +{ + SHA256_State *s = handle; + + smemclr(s, sizeof(*s)); + sfree(s); +} + static void sha256_bytes(void *handle, const void *p, int len) { SHA256_State *s = handle; @@ -212,12 +230,12 @@ static void sha256_final(void *handle, unsigned char *output) SHA256_State *s = handle; SHA256_Final(s, output); - smemclr(s, sizeof(*s)); - sfree(s); + sha256_free(s); } const struct ssh_hash ssh_sha256 = { - sha256_init, sha256_bytes, sha256_final, 32, "SHA-256" + sha256_init, sha256_copy, sha256_bytes, sha256_final, sha256_free, + 32, "SHA-256" }; /* ---------------------------------------------------------------------- diff --git a/sshsh512.c b/sshsh512.c index f0f13510..bdfc1e9d 100644 --- a/sshsh512.c +++ b/sshsh512.c @@ -331,6 +331,24 @@ static void *sha512_init(void) return s; } +static void *sha512_copy(const void *vold) +{ + const SHA512_State *old = (const SHA512_State *)vold; + SHA512_State *s; + + s = snew(SHA512_State); + *s = *old; + return s; +} + +static void sha512_free(void *handle) +{ + SHA512_State *s = handle; + + smemclr(s, sizeof(*s)); + sfree(s); +} + static void sha512_bytes(void *handle, const void *p, int len) { SHA512_State *s = handle; @@ -343,12 +361,12 @@ static void sha512_final(void *handle, unsigned char *output) SHA512_State *s = handle; SHA512_Final(s, output); - smemclr(s, sizeof(*s)); - sfree(s); + sha512_free(s); } const struct ssh_hash ssh_sha512 = { - sha512_init, sha512_bytes, sha512_final, 64, "SHA-512" + sha512_init, sha512_copy, sha512_bytes, sha512_final, sha512_free, + 64, "SHA-512" }; static void *sha384_init(void) @@ -370,7 +388,8 @@ static void sha384_final(void *handle, unsigned char *output) } const struct ssh_hash ssh_sha384 = { - sha384_init, sha512_bytes, sha384_final, 48, "SHA-384" + sha384_init, sha512_copy, sha512_bytes, sha384_final, sha512_free, + 48, "SHA-384" }; #ifdef TEST diff --git a/sshsha.c b/sshsha.c index 2b2eead1..07a71ca2 100644 --- a/sshsha.c +++ b/sshsha.c @@ -230,6 +230,24 @@ static void *sha1_init(void) return s; } +static void *sha1_copy(const void *vold) +{ + const SHA_State *old = (const SHA_State *)vold; + SHA_State *s; + + s = snew(SHA_State); + *s = *old; + return s; +} + +static void sha1_free(void *handle) +{ + SHA_State *s = handle; + + smemclr(s, sizeof(*s)); + sfree(s); +} + static void sha1_bytes(void *handle, const void *p, int len) { SHA_State *s = handle; @@ -242,12 +260,11 @@ static void sha1_final(void *handle, unsigned char *output) SHA_State *s = handle; SHA_Final(s, output); - smemclr(s, sizeof(*s)); - sfree(s); + sha1_free(s); } const struct ssh_hash ssh_sha1 = { - sha1_init, sha1_bytes, sha1_final, 20, "SHA-1" + sha1_init, sha1_copy, sha1_bytes, sha1_final, sha1_free, 20, "SHA-1" }; /* ----------------------------------------------------------------------