From 6ab2ed0da6f9149a1bb5dd29b3f38375f92c73ea Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Mon, 27 Aug 2018 16:26:01 +0200 Subject: [PATCH] hash: allow truncated output Tomcrypt, some NSS hash functions, and the internal MD5 require the output buffer to be at least as long as the digest. To provide the same hashing API with all four options, use an extra buffer for the digest when necessary and copy only the requested bytes to the caller. --- hash_intmd5.c | 9 ++++----- hash_nss.c | 7 ++++++- hash_tomcrypt.c | 14 ++++++++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/hash_intmd5.c b/hash_intmd5.c index 64e0b9c..0b60f9b 100644 --- a/hash_intmd5.c +++ b/hash_intmd5.c @@ -49,18 +49,17 @@ HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len, const unsigned char *in2, unsigned int in2_len, unsigned char *out, unsigned int out_len) { - if (out_len < 16) - return 0; - MD5Init(&ctx); MD5Update(&ctx, in1, in1_len); if (in2) MD5Update(&ctx, in2, in2_len); MD5Final(&ctx); - memcpy(out, ctx.digest, 16); + out_len = MIN(out_len, 16); - return 16; + memcpy(out, ctx.digest, out_len); + + return out_len; } void diff --git a/hash_nss.c b/hash_nss.c index eb1f050..9967bf8 100644 --- a/hash_nss.c +++ b/hash_nss.c @@ -32,6 +32,7 @@ #include #include "hash.h" +#include "util.h" static NSSLOWInitContext *ictx; @@ -78,13 +79,17 @@ HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len, const unsigned char *in2, unsigned int in2_len, unsigned char *out, unsigned int out_len) { + unsigned char buf[MAX_HASH_LENGTH]; unsigned int ret = 0; NSSLOWHASH_Begin(hashes[id].context); NSSLOWHASH_Update(hashes[id].context, in1, in1_len); if (in2) NSSLOWHASH_Update(hashes[id].context, in2, in2_len); - NSSLOWHASH_End(hashes[id].context, out, &ret, out_len); + NSSLOWHASH_End(hashes[id].context, buf, &ret, sizeof (buf)); + + ret = MIN(ret, out_len); + memcpy(out, buf, ret); return ret; } diff --git a/hash_tomcrypt.c b/hash_tomcrypt.c index 5e16233..51b63d9 100644 --- a/hash_tomcrypt.c +++ b/hash_tomcrypt.c @@ -29,6 +29,7 @@ #include "config.h" #include "hash.h" +#include "util.h" struct hash { const char *name; @@ -105,19 +106,24 @@ HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len, const unsigned char *in2, unsigned int in2_len, unsigned char *out, unsigned int out_len) { + unsigned char buf[MAX_HASH_LENGTH]; unsigned long len; int r; - len = out_len; + len = sizeof (buf); if (in2) - r = hash_memory_multi(id, out, &len, - in1, (unsigned long)in1_len, in2, (unsigned long)in2_len, NULL, 0); + r = hash_memory_multi(id, buf, &len, + in1, (unsigned long)in1_len, + in2, (unsigned long)in2_len, NULL, 0); else - r = hash_memory(id, in1, in1_len, out, &len); + r = hash_memory(id, in1, in1_len, buf, &len); if (r != CRYPT_OK) return 0; + len = MIN(len, out_len); + memcpy(out, buf, len); + return len; }