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.
This commit is contained in:
Miroslav Lichvar 2018-08-27 16:26:01 +02:00
parent 7352e470e1
commit 6ab2ed0da6
3 changed files with 20 additions and 10 deletions

View file

@ -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

View file

@ -32,6 +32,7 @@
#include <nsslowhash.h>
#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;
}

View file

@ -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;
}