From db96dfe0f45ca6ba1ef32efb435a25225f84f6d5 Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Thu, 13 Nov 2014 09:59:21 +1030 Subject: [PATCH] Add SHA512_Final_Len() et al An optimisation: programmers can now easily take just a part of the digest without needing an intermediate buffer to hold the entire digest --- sha2.c | 43 ++++++++++++++++++++++--------------------- sha2.h | 6 ++++++ 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/sha2.c b/sha2.c index 6b9f3fd5..54b5d98c 100644 --- a/sha2.c +++ b/sha2.c @@ -611,7 +611,10 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { } void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { - sha2_word32 *d = (sha2_word32*)digest; + SHA256_Final_Len(digest, SHA256_DIGEST_LENGTH, context); +} + +void SHA256_Final_Len(sha2_byte digest[], size_t digestlen, SHA256_CTX* context) { unsigned int usedspace; /* Sanity check: */ @@ -619,6 +622,7 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { /* If no digest buffer is passed, we don't bother doing this: */ if (digest != (sha2_byte*)0) { + assert(digestlen <= SHA256_DIGEST_LENGTH); usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; #if BYTE_ORDER == LITTLE_ENDIAN /* Convert FROM host byte order */ @@ -658,15 +662,12 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { #if BYTE_ORDER == LITTLE_ENDIAN { /* Convert TO host byte order */ - int j; - for (j = 0; j < 8; j++) { + unsigned j; + for (j = 0; j < 8; j++) REVERSE32(context->state[j],context->state[j]); - *d++ = context->state[j]; - } } -#else - MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH); #endif + MEMCPY_BCOPY(digest, context->state, digestlen); } /* Clean up state data: */ @@ -976,28 +977,28 @@ void SHA512_Last(SHA512_CTX* context) { } void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) { - sha2_word64 *d = (sha2_word64*)digest; + SHA512_Final_Len(digest, SHA512_DIGEST_LENGTH, context); +} +void SHA512_Final_Len(sha2_byte digest[], size_t digestlen, SHA512_CTX* context) { /* Sanity check: */ assert(context != (SHA512_CTX*)0); /* If no digest buffer is passed, we don't bother doing this: */ if (digest != (sha2_byte*)0) { + assert(digestlen <= SHA512_DIGEST_LENGTH); SHA512_Last(context); /* Save the hash data for output: */ #if BYTE_ORDER == LITTLE_ENDIAN { /* Convert TO host byte order */ - int j; - for (j = 0; j < 8; j++) { + unsigned j; + for (j = 0; j < 8; j++) REVERSE64(context->state[j],context->state[j]); - *d++ = context->state[j]; - } } -#else - MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH); #endif + MEMCPY_BCOPY(digest, context->state, digestlen); } /* Zero out state data */ @@ -1051,28 +1052,28 @@ void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) { } void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) { - sha2_word64 *d = (sha2_word64*)digest; + SHA384_Final_Len(digest, SHA384_DIGEST_LENGTH, context); +} +void SHA384_Final_Len(sha2_byte digest[], size_t digestlen, SHA384_CTX* context) { /* Sanity check: */ assert(context != (SHA384_CTX*)0); /* If no digest buffer is passed, we don't bother doing this: */ if (digest != (sha2_byte*)0) { + assert(digestlen <= SHA384_DIGEST_LENGTH); SHA512_Last((SHA512_CTX*)context); /* Save the hash data for output: */ #if BYTE_ORDER == LITTLE_ENDIAN { /* Convert TO host byte order */ - int j; - for (j = 0; j < 6; j++) { + unsigned j; + for (j = 0; j < 6; j++) REVERSE64(context->state[j],context->state[j]); - *d++ = context->state[j]; - } } -#else - MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH); #endif + MEMCPY_BCOPY(digest, context->state, digestlen); } /* Zero out state data */ diff --git a/sha2.h b/sha2.h index bf759ad4..7b5347b2 100644 --- a/sha2.h +++ b/sha2.h @@ -130,18 +130,21 @@ typedef SHA512_CTX SHA384_CTX; void SHA256_Init(SHA256_CTX *); void SHA256_Update(SHA256_CTX*, const uint8_t*, size_t); void SHA256_Final(uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*); +void SHA256_Final_Len(uint8_t[], size_t, SHA256_CTX*); char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); char* SHA256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); void SHA384_Init(SHA384_CTX*); void SHA384_Update(SHA384_CTX*, const uint8_t*, size_t); void SHA384_Final(uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*); +void SHA384_Final_Len(uint8_t[], size_t, SHA384_CTX*); char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); char* SHA384_Data(const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]); void SHA512_Init(SHA512_CTX*); void SHA512_Update(SHA512_CTX*, const uint8_t*, size_t); void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); +void SHA512_Final_Len(uint8_t[], size_t, SHA512_CTX*); char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); char* SHA512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); @@ -150,18 +153,21 @@ char* SHA512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); void SHA256_Init(SHA256_CTX *); void SHA256_Update(SHA256_CTX*, const u_int8_t*, size_t); void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*); +void SHA256_Final_Len(u_int8_t[], size_t, SHA256_CTX*); char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); void SHA384_Init(SHA384_CTX*); void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t); void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*); +void SHA384_Final_Len(u_int8_t[], size_t, SHA384_CTX*); char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]); void SHA512_Init(SHA512_CTX*); void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t); void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); +void SHA512_Final_Len(u_int8_t[], size_t, SHA512_CTX*); char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);