From 862c0aa8806b226286205a3ce2482840721173d6 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Wed, 27 Apr 2016 14:59:12 -0400 Subject: [PATCH] Revert md_len removal from SHA256_CTX and SHA512_CTX. This reverts commits: - 91586371422dae70481c39752e55f01f50e9a93a - a90aa643024459c1698dbec84f4c79a3238b3db8 - c0d8b83b4462a0eb1889f32dbd7f46e83f4dbc81 It turns out code outside of BoringSSL also mismatches Init and Update/Final functions. Since this is largely cosmetic, it's probably not worth the cost to do this. Change-Id: I14e7b299172939f69ced2114be45ccba1dbbb704 Reviewed-on: https://boringssl-review.googlesource.com/7793 Reviewed-by: Adam Langley --- crypto/digest/md32_common.h | 21 ++++++--- crypto/md4/md4.c | 30 ++++++------- crypto/md5/md5.c | 30 ++++++------- crypto/sha/sha1.c | 34 +++++++-------- crypto/sha/sha256.c | 71 +++++++++++++++++++----------- crypto/sha/sha512.c | 86 ++++++++++++++++++++----------------- decrepit/ripemd/internal.h | 16 ++++++- decrepit/ripemd/ripemd.c | 18 -------- include/openssl/sha.h | 28 ++++++------ 9 files changed, 178 insertions(+), 156 deletions(-) diff --git a/crypto/digest/md32_common.h b/crypto/digest/md32_common.h index 77aaa449..4cf050ca 100644 --- a/crypto/digest/md32_common.h +++ b/crypto/digest/md32_common.h @@ -90,7 +90,7 @@ extern "C" { * |HASH_TRANSFORM| must be defined as the the name of the "Transform" * function to generate. * - * |HASH_FINISH| must be defined as the name of "finish" function to generate. + * |HASH_FINAL| must be defined as the name of "Final" function to generate. * * |HASH_BLOCK_DATA_ORDER| must be defined as the name of the "Block" function. * That function must be implemented manually. It must be capable of operating @@ -103,7 +103,11 @@ extern "C" { * It must update the hash state |state| with |num| blocks of data from |data|, * where each block is |HASH_CBLOCK| bytes; i.e. |data| points to a array of * |HASH_CBLOCK * num| bytes. |state| points to the |h| member of a |HASH_CTX|, - * and so will have | / sizeof(uint32_t)| elements. */ + * and so will have | / sizeof(uint32_t)| elements. + * + * |HASH_MAKE_STRING(c, s)| must be defined as a block statement that converts + * the hash state |c->h| into the output byte order, storing the result in |s|. + */ #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) #error "DATA_ORDER must be defined!" @@ -122,14 +126,18 @@ extern "C" { #ifndef HASH_TRANSFORM #error "HASH_TRANSFORM must be defined!" #endif -#ifndef HASH_FINISH -#error "HASH_FINISH must be defined!" +#ifndef HASH_FINAL +#error "HASH_FINAL must be defined!" #endif #ifndef HASH_BLOCK_DATA_ORDER #error "HASH_BLOCK_DATA_ORDER must be defined!" #endif +#ifndef HASH_MAKE_STRING +#error "HASH_MAKE_STRING must be defined!" +#endif + #if defined(DATA_ORDER_IS_BIG_ENDIAN) #define HOST_c2l(c, l) \ @@ -212,7 +220,7 @@ void HASH_TRANSFORM(HASH_CTX *c, const uint8_t *data) { } -static void HASH_FINISH(HASH_CTX *c) { +int HASH_FINAL(uint8_t *md, HASH_CTX *c) { /* |c->data| always has room for at least one byte. A full block would have * been consumed. */ size_t n = c->num; @@ -241,6 +249,9 @@ static void HASH_FINISH(HASH_CTX *c) { HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); c->num = 0; memset(c->data, 0, HASH_CBLOCK); + + HASH_MAKE_STRING(c, md); + return 1; } diff --git a/crypto/md4/md4.c b/crypto/md4/md4.c index 5293f14a..f79da9fd 100644 --- a/crypto/md4/md4.c +++ b/crypto/md4/md4.c @@ -88,27 +88,23 @@ void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num); #define HASH_CBLOCK 64 #define HASH_UPDATE MD4_Update #define HASH_TRANSFORM MD4_Transform -#define HASH_FINISH md4_finish +#define HASH_FINAL MD4_Final +#define HASH_MAKE_STRING(c, s) \ + do { \ + uint32_t ll; \ + ll = (c)->h[0]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + HOST_l2c(ll, (s)); \ + } while (0) #define HASH_BLOCK_DATA_ORDER md4_block_data_order #include "../digest/md32_common.h" -int MD4_Final(uint8_t *md, MD4_CTX *md4) { - md4_finish(md4); - - uint32_t ll; - ll = md4->h[0]; - HOST_l2c(ll, md); - ll = md4->h[1]; - HOST_l2c(ll, md); - ll = md4->h[2]; - HOST_l2c(ll, md); - ll = md4->h[3]; - HOST_l2c(ll, md); - - return 1; -} - /* As pointed out by Wei Dai , the above can be * simplified to the code below. Wei attributes these optimizations * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. */ diff --git a/crypto/md5/md5.c b/crypto/md5/md5.c index ad37537b..66483b84 100644 --- a/crypto/md5/md5.c +++ b/crypto/md5/md5.c @@ -101,27 +101,23 @@ void md5_block_data_order(uint32_t *state, const uint8_t *data, size_t num); #define HASH_CBLOCK 64 #define HASH_UPDATE MD5_Update #define HASH_TRANSFORM MD5_Transform -#define HASH_FINISH md5_finish +#define HASH_FINAL MD5_Final +#define HASH_MAKE_STRING(c, s) \ + do { \ + uint32_t ll; \ + ll = (c)->h[0]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + HOST_l2c(ll, (s)); \ + } while (0) #define HASH_BLOCK_DATA_ORDER md5_block_data_order #include "../digest/md32_common.h" -int MD5_Final(uint8_t *md, MD5_CTX *md5) { - md5_finish(md5); - - uint32_t ll; - ll = md5->h[0]; - HOST_l2c(ll, md); - ll = md5->h[1]; - HOST_l2c(ll, md); - ll = md5->h[2]; - HOST_l2c(ll, md); - ll = md5->h[3]; - HOST_l2c(ll, md); - - return 1; -} - /* As pointed out by Wei Dai , the above can be * simplified to the code below. Wei attributes these optimizations * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. diff --git a/crypto/sha/sha1.c b/crypto/sha/sha1.c index 5967af0c..74e841ca 100644 --- a/crypto/sha/sha1.c +++ b/crypto/sha/sha1.c @@ -98,10 +98,24 @@ uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t *out) { #define HASH_CTX SHA_CTX #define HASH_CBLOCK 64 +#define HASH_MAKE_STRING(c, s) \ + do { \ + uint32_t ll; \ + ll = (c)->h[0]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + HOST_l2c(ll, (s)); \ + ll = (c)->h[4]; \ + HOST_l2c(ll, (s)); \ + } while (0) #define HASH_UPDATE SHA1_Update #define HASH_TRANSFORM SHA1_Transform -#define HASH_FINISH sha1_finish +#define HASH_FINAL SHA1_Final #define HASH_BLOCK_DATA_ORDER sha1_block_data_order #define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) #define Xupdate(a, ix, ia, ib, ic, id) \ @@ -114,24 +128,6 @@ void sha1_block_data_order(uint32_t *state, const uint8_t *data, size_t num); #include "../digest/md32_common.h" -int SHA1_Final(uint8_t *md, SHA_CTX *sha) { - sha1_finish(sha); - - uint32_t ll; - ll = sha->h[0]; - HOST_l2c(ll, md); - ll = sha->h[1]; - HOST_l2c(ll, md); - ll = sha->h[2]; - HOST_l2c(ll, md); - ll = sha->h[3]; - HOST_l2c(ll, md); - ll = sha->h[4]; - HOST_l2c(ll, md); - - return 1; -} - #define K_00_19 0x5a827999UL #define K_20_39 0x6ed9eba1UL #define K_40_59 0x8f1bbcdcUL diff --git a/crypto/sha/sha256.c b/crypto/sha/sha256.c index f2bb54ed..58f7c42c 100644 --- a/crypto/sha/sha256.c +++ b/crypto/sha/sha256.c @@ -77,6 +77,7 @@ int SHA224_Init(SHA256_CTX *sha) { sha->h[5] = 0x68581511UL; sha->h[6] = 0x64f98fa7UL; sha->h[7] = 0xbefa4fa4UL; + sha->md_len = SHA224_DIGEST_LENGTH; return 1; } @@ -90,6 +91,7 @@ int SHA256_Init(SHA256_CTX *sha) { sha->h[5] = 0x9b05688cUL; sha->h[6] = 0x1f83d9abUL; sha->h[7] = 0x5be0cd19UL; + sha->md_len = SHA256_DIGEST_LENGTH; return 1; } @@ -127,14 +129,57 @@ int SHA224_Update(SHA256_CTX *ctx, const void *data, size_t len) { return SHA256_Update(ctx, data, len); } +int SHA224_Final(uint8_t *md, SHA256_CTX *ctx) { + return SHA256_Final(md, ctx); +} + #define DATA_ORDER_IS_BIG_ENDIAN #define HASH_CTX SHA256_CTX #define HASH_CBLOCK 64 +/* Note that FIPS180-2 discusses "Truncation of the Hash Function Output." + * default: case below covers for it. It's not clear however if it's permitted + * to truncate to amount of bytes not divisible by 4. I bet not, but if it is, + * then default: case shall be extended. For reference. Idea behind separate + * cases for pre-defined lenghts is to let the compiler decide if it's + * appropriate to unroll small loops. + * + * TODO(davidben): The small |md_len| case is one of the few places a low-level + * hash 'final' function can fail. This should never happen. */ +#define HASH_MAKE_STRING(c, s) \ + do { \ + uint32_t ll; \ + unsigned int nn; \ + switch ((c)->md_len) { \ + case SHA224_DIGEST_LENGTH: \ + for (nn = 0; nn < SHA224_DIGEST_LENGTH / 4; nn++) { \ + ll = (c)->h[nn]; \ + HOST_l2c(ll, (s)); \ + } \ + break; \ + case SHA256_DIGEST_LENGTH: \ + for (nn = 0; nn < SHA256_DIGEST_LENGTH / 4; nn++) { \ + ll = (c)->h[nn]; \ + HOST_l2c(ll, (s)); \ + } \ + break; \ + default: \ + if ((c)->md_len > SHA256_DIGEST_LENGTH) { \ + return 0; \ + } \ + for (nn = 0; nn < (c)->md_len / 4; nn++) { \ + ll = (c)->h[nn]; \ + HOST_l2c(ll, (s)); \ + } \ + break; \ + } \ + } while (0) + + #define HASH_UPDATE SHA256_Update #define HASH_TRANSFORM SHA256_Transform -#define HASH_FINISH sha256_finish +#define HASH_FINAL SHA256_Final #define HASH_BLOCK_DATA_ORDER sha256_block_data_order #ifndef SHA256_ASM static @@ -143,30 +188,6 @@ void sha256_block_data_order(uint32_t *state, const uint8_t *in, size_t num); #include "../digest/md32_common.h" -int SHA224_Final(uint8_t *md, SHA256_CTX *sha) { - sha256_finish(sha); - - unsigned nn; - for (nn = 0; nn < SHA224_DIGEST_LENGTH / 4; nn++) { - uint32_t ll = sha->h[nn]; - HOST_l2c(ll, md); - } - - return 1; -} - -int SHA256_Final(uint8_t *md, SHA256_CTX *sha) { - sha256_finish(sha); - - unsigned nn; - for (nn = 0; nn < SHA256_DIGEST_LENGTH / 4; nn++) { - uint32_t ll = sha->h[nn]; - HOST_l2c(ll, md); - } - - return 1; -} - #ifndef SHA256_ASM static const uint32_t K256[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, diff --git a/crypto/sha/sha512.c b/crypto/sha/sha512.c index dc2015d6..f4730463 100644 --- a/crypto/sha/sha512.c +++ b/crypto/sha/sha512.c @@ -97,6 +97,7 @@ int SHA384_Init(SHA512_CTX *sha) { sha->Nl = 0; sha->Nh = 0; sha->num = 0; + sha->md_len = SHA384_DIGEST_LENGTH; return 1; } @@ -114,6 +115,7 @@ int SHA512_Init(SHA512_CTX *sha) { sha->Nl = 0; sha->Nh = 0; sha->num = 0; + sha->md_len = SHA512_DIGEST_LENGTH; return 1; } @@ -153,36 +155,15 @@ static #endif void sha512_block_data_order(uint64_t *state, const uint64_t *W, size_t num); -static void sha512_finish(SHA512_CTX *sha); + +int SHA384_Final(uint8_t *md, SHA512_CTX *sha) { + return SHA512_Final(md, sha); +} int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len) { return SHA512_Update(sha, data, len); } -void SHA384_Transform(SHA512_CTX *c, const uint8_t *data) { - return SHA512_Transform(c, data); -} - -int SHA384_Final(uint8_t *md, SHA512_CTX *sha) { - sha512_finish(sha); - - size_t n; - for (n = 0; n < SHA384_DIGEST_LENGTH / 8; n++) { - uint64_t t = sha->h[n]; - - *(md++) = (uint8_t)(t >> 56); - *(md++) = (uint8_t)(t >> 48); - *(md++) = (uint8_t)(t >> 40); - *(md++) = (uint8_t)(t >> 32); - *(md++) = (uint8_t)(t >> 24); - *(md++) = (uint8_t)(t >> 16); - *(md++) = (uint8_t)(t >> 8); - *(md++) = (uint8_t)(t); - } - - return 1; -} - void SHA512_Transform(SHA512_CTX *c, const uint8_t *data) { #ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA if ((size_t)data % sizeof(c->u.d[0]) != 0) { @@ -253,7 +234,7 @@ int SHA512_Update(SHA512_CTX *c, const void *in_data, size_t len) { return 1; } -static void sha512_finish(SHA512_CTX *sha) { +int SHA512_Final(uint8_t *md, SHA512_CTX *sha) { uint8_t *p = (uint8_t *)sha->u.p; size_t n = sha->num; @@ -284,23 +265,48 @@ static void sha512_finish(SHA512_CTX *sha) { p[sizeof(sha->u) - 16] = (uint8_t)(sha->Nh >> 56); sha512_block_data_order(sha->h, (uint64_t *)p, 1); -} -int SHA512_Final(uint8_t *md, SHA512_CTX *sha) { - sha512_finish(sha); + if (md == NULL) { + /* TODO(davidben): This NULL check is absent in other low-level hash 'final' + * functions and is one of the few places one can fail. */ + return 0; + } - size_t n; - for (n = 0; n < SHA512_DIGEST_LENGTH / 8; n++) { - uint64_t t = sha->h[n]; + switch (sha->md_len) { + /* Let compiler decide if it's appropriate to unroll... */ + case SHA384_DIGEST_LENGTH: + for (n = 0; n < SHA384_DIGEST_LENGTH / 8; n++) { + uint64_t t = sha->h[n]; - *(md++) = (uint8_t)(t >> 56); - *(md++) = (uint8_t)(t >> 48); - *(md++) = (uint8_t)(t >> 40); - *(md++) = (uint8_t)(t >> 32); - *(md++) = (uint8_t)(t >> 24); - *(md++) = (uint8_t)(t >> 16); - *(md++) = (uint8_t)(t >> 8); - *(md++) = (uint8_t)(t); + *(md++) = (uint8_t)(t >> 56); + *(md++) = (uint8_t)(t >> 48); + *(md++) = (uint8_t)(t >> 40); + *(md++) = (uint8_t)(t >> 32); + *(md++) = (uint8_t)(t >> 24); + *(md++) = (uint8_t)(t >> 16); + *(md++) = (uint8_t)(t >> 8); + *(md++) = (uint8_t)(t); + } + break; + case SHA512_DIGEST_LENGTH: + for (n = 0; n < SHA512_DIGEST_LENGTH / 8; n++) { + uint64_t t = sha->h[n]; + + *(md++) = (uint8_t)(t >> 56); + *(md++) = (uint8_t)(t >> 48); + *(md++) = (uint8_t)(t >> 40); + *(md++) = (uint8_t)(t >> 32); + *(md++) = (uint8_t)(t >> 24); + *(md++) = (uint8_t)(t >> 16); + *(md++) = (uint8_t)(t >> 8); + *(md++) = (uint8_t)(t); + } + break; + /* ... as well as make sure md_len is not abused. */ + default: + /* TODO(davidben): This bad |md_len| case is one of the few places a + * low-level hash 'final' function can fail. This should never happen. */ + return 0; } return 1; diff --git a/decrepit/ripemd/internal.h b/decrepit/ripemd/internal.h index dea532ba..c4db4b23 100644 --- a/decrepit/ripemd/internal.h +++ b/decrepit/ripemd/internal.h @@ -74,7 +74,21 @@ static void ripemd160_block_data_order(uint32_t h[5], const uint8_t *data, #define HASH_CBLOCK RIPEMD160_CBLOCK #define HASH_UPDATE RIPEMD160_Update #define HASH_TRANSFORM RIPEMD160_Transform -#define HASH_FINISH ripemd160_finish +#define HASH_FINAL RIPEMD160_Final +#define HASH_MAKE_STRING(c, s) \ + do { \ + unsigned long ll; \ + ll = (c)->h[0]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[1]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[2]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[3]; \ + (void)HOST_l2c(ll, (s)); \ + ll = (c)->h[4]; \ + (void)HOST_l2c(ll, (s)); \ + } while (0) #define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order #include "../../crypto/digest/md32_common.h" diff --git a/decrepit/ripemd/ripemd.c b/decrepit/ripemd/ripemd.c index c871ea76..6ed7816c 100644 --- a/decrepit/ripemd/ripemd.c +++ b/decrepit/ripemd/ripemd.c @@ -71,24 +71,6 @@ int RIPEMD160_Init(RIPEMD160_CTX *ctx) { return 1; } -int RIPEMD160_Final(uint8_t *md, RIPEMD160_CTX *ctx) { - ripemd160_finish(ctx); - - unsigned long ll; - ll = ctx->h[0]; - (void)HOST_l2c(ll, md); - ll = ctx->h[1]; - (void)HOST_l2c(ll, md); - ll = ctx->h[2]; - (void)HOST_l2c(ll, md); - ll = ctx->h[3]; - (void)HOST_l2c(ll, md); - ll = ctx->h[4]; - (void)HOST_l2c(ll, md); - - return 1; -} - static void ripemd160_block_data_order(uint32_t h[5], const uint8_t *data, size_t num) { uint32_t A, B, C, D, E; diff --git a/include/openssl/sha.h b/include/openssl/sha.h index 6e3df8f1..48a52e8f 100644 --- a/include/openssl/sha.h +++ b/include/openssl/sha.h @@ -128,15 +128,15 @@ struct sha_state_st { /* SHA224_DIGEST_LENGTH is the length of a SHA-224 digest. */ #define SHA224_DIGEST_LENGTH 28 -/* SHA224_Init initialises |sha| and returns one. */ +/* SHA224_Init initialises |sha| and returns 1. */ OPENSSL_EXPORT int SHA224_Init(SHA256_CTX *sha); -/* SHA224_Update adds |len| bytes from |data| to |sha| and returns one. */ +/* SHA224_Update adds |len| bytes from |data| to |sha| and returns 1. */ OPENSSL_EXPORT int SHA224_Update(SHA256_CTX *sha, const void *data, size_t len); /* SHA224_Final adds the final padding to |sha| and writes the resulting digest * to |md|, which must have at least |SHA224_DIGEST_LENGTH| bytes of space. It - * returns one. */ + * returns one on success and zero on programmer error. */ OPENSSL_EXPORT int SHA224_Final(uint8_t *md, SHA256_CTX *sha); /* SHA224 writes the digest of |len| bytes from |data| to |out| and returns @@ -153,15 +153,15 @@ OPENSSL_EXPORT uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out); /* SHA256_DIGEST_LENGTH is the length of a SHA-256 digest. */ #define SHA256_DIGEST_LENGTH 32 -/* SHA256_Init initialises |sha| and returns one. */ +/* SHA256_Init initialises |sha| and returns 1. */ OPENSSL_EXPORT int SHA256_Init(SHA256_CTX *sha); -/* SHA256_Update adds |len| bytes from |data| to |sha| and returns one. */ +/* SHA256_Update adds |len| bytes from |data| to |sha| and returns 1. */ OPENSSL_EXPORT int SHA256_Update(SHA256_CTX *sha, const void *data, size_t len); /* SHA256_Final adds the final padding to |sha| and writes the resulting digest * to |md|, which must have at least |SHA256_DIGEST_LENGTH| bytes of space. It - * returns one. */ + * returns one on success and zero on programmer error. */ OPENSSL_EXPORT int SHA256_Final(uint8_t *md, SHA256_CTX *sha); /* SHA256 writes the digest of |len| bytes from |data| to |out| and returns @@ -177,7 +177,7 @@ struct sha256_state_st { uint32_t h[8]; uint32_t Nl, Nh; uint8_t data[SHA256_CBLOCK]; - unsigned num; + unsigned num, md_len; }; @@ -189,15 +189,15 @@ struct sha256_state_st { /* SHA384_DIGEST_LENGTH is the length of a SHA-384 digest. */ #define SHA384_DIGEST_LENGTH 48 -/* SHA384_Init initialises |sha| and returns one. */ +/* SHA384_Init initialises |sha| and returns 1. */ OPENSSL_EXPORT int SHA384_Init(SHA512_CTX *sha); -/* SHA384_Update adds |len| bytes from |data| to |sha| and returns one. */ +/* SHA384_Update adds |len| bytes from |data| to |sha| and returns 1. */ OPENSSL_EXPORT int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len); /* SHA384_Final adds the final padding to |sha| and writes the resulting digest * to |md|, which must have at least |SHA384_DIGEST_LENGTH| bytes of space. It - * returns one. */ + * returns one on success and zero on programmer error. */ OPENSSL_EXPORT int SHA384_Final(uint8_t *md, SHA512_CTX *sha); /* SHA384 writes the digest of |len| bytes from |data| to |out| and returns @@ -218,15 +218,15 @@ OPENSSL_EXPORT void SHA384_Transform(SHA512_CTX *sha, const uint8_t *data); /* SHA512_DIGEST_LENGTH is the length of a SHA-512 digest. */ #define SHA512_DIGEST_LENGTH 64 -/* SHA512_Init initialises |sha| and returns one. */ +/* SHA512_Init initialises |sha| and returns 1. */ OPENSSL_EXPORT int SHA512_Init(SHA512_CTX *sha); -/* SHA512_Update adds |len| bytes from |data| to |sha| and returns one. */ +/* SHA512_Update adds |len| bytes from |data| to |sha| and returns 1. */ OPENSSL_EXPORT int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len); /* SHA512_Final adds the final padding to |sha| and writes the resulting digest * to |md|, which must have at least |SHA512_DIGEST_LENGTH| bytes of space. It - * returns one. */ + * returns one on success and zero on programmer error. */ OPENSSL_EXPORT int SHA512_Final(uint8_t *md, SHA512_CTX *sha); /* SHA512 writes the digest of |len| bytes from |data| to |out| and returns @@ -245,7 +245,7 @@ struct sha512_state_st { uint64_t d[16]; uint8_t p[128]; } u; - unsigned num; + unsigned num, md_len; };