Make md32_common.h single-included and use an unsized helper for SHA-256. Similar to https://boringssl-review.googlesource.com/c/boringssl/+/46405, SHA256_Final and SHA224_Final hit array size warnings in the new GCC. The array sizes are, strictly speaking, purely decoration, but this is a good warning so we should be clean with it on. That same change is difficult to apply to md32_common.h because md32_common.h generates the functions for us. md32_common.h is already strange in that it is multiply-included and changes behavior based on macros defined by the caller. Instead, replace it with inline functions, which are a bit more conventional and typesafe. This allows each hash function to define the function prototype. Use this to add an unsized helper for SHA-256. Bug: 402 Change-Id: I61bc30fb58c54dd40a55c9b1ebf3fb9adde5e038 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47807 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Peter Foley <pefoley@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/fipsmodule/digest/md32_common.h b/crypto/fipsmodule/digest/md32_common.h index 8a14108..129ec48 100644 --- a/crypto/fipsmodule/digest/md32_common.h +++ b/crypto/fipsmodule/digest/md32_common.h
@@ -46,6 +46,9 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ +#ifndef OPENSSL_HEADER_DIGEST_MD32_COMMON_H +#define OPENSSL_HEADER_DIGEST_MD32_COMMON_H + #include <openssl/base.h> #include <assert.h> @@ -59,22 +62,15 @@ // This is a generic 32-bit "collector" for message digest algorithms. It // collects input character stream into chunks of 32-bit values and invokes the -// block function that performs the actual hash calculations. To make use of -// this mechanism, the following macros must be defined before including -// md32_common.h. +// block function that performs the actual hash calculations. // -// One of |DATA_ORDER_IS_BIG_ENDIAN| or |DATA_ORDER_IS_LITTLE_ENDIAN| must be -// defined to specify the byte order of the input stream. -// -// |HASH_CBLOCK| must be defined as the integer block size, in bytes. -// -// |HASH_CTX| must be defined as the name of the context structure, which must -// have at least the following members: +// To make use of this mechanism, the hash context should be defined with the +// following parameters. // // typedef struct <name>_state_st { // uint32_t h[<chaining length> / sizeof(uint32_t)]; // uint32_t Nl, Nh; -// uint8_t data[HASH_CBLOCK]; +// uint8_t data[<block size>]; // unsigned num; // ... // } <NAME>_CTX; @@ -83,136 +79,117 @@ // any truncation (e.g. 64 for SHA-224 and SHA-256, 128 for SHA-384 and // SHA-512). // -// |HASH_UPDATE| must be defined as the name of the "Update" 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 -// on *unaligned* input data in its original (data) byte order. It must have -// this signature: -// -// void HASH_BLOCK_DATA_ORDER(uint32_t *state, const uint8_t *data, -// size_t num); -// -// 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 |<chaining length> / 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|. +// |h| is the hash state and is updated by a function of type +// |crypto_md32_block_func|. |data| is the partial unprocessed block and has +// |num| bytes. |Nl| and |Nh| maintain the number of bits processed so far. -#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) -#error "DATA_ORDER must be defined!" -#endif +// A crypto_md32_block_func should incorporate |num_blocks| of input from |data| +// into |state|. It is assumed the caller has sized |state| and |data| for the +// hash function. +typedef void (*crypto_md32_block_func)(uint32_t *state, const uint8_t *data, + size_t num_blocks); -#ifndef HASH_CBLOCK -#error "HASH_CBLOCK must be defined!" -#endif -#ifndef HASH_CTX -#error "HASH_CTX must be defined!" -#endif - -#ifndef HASH_UPDATE -#error "HASH_UPDATE must be defined!" -#endif -#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 - -int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) { - const uint8_t *data = data_; - +// crypto_md32_update adds |len| bytes from |in| to the digest. |data| must be a +// buffer of length |block_size| with the first |*num| bytes containing a +// partial block. This function combines the partial block with |in| and +// incorporates any complete blocks into the digest state |h|. It then updates +// |data| and |*num| with the new partial block and updates |*Nh| and |*Nl| with +// the data consumed. +static inline void crypto_md32_update(crypto_md32_block_func block_func, + uint32_t *h, uint8_t *data, + size_t block_size, unsigned *num, + uint32_t *Nh, uint32_t *Nl, + const uint8_t *in, size_t len) { if (len == 0) { - return 1; + return; } - uint32_t l = c->Nl + (((uint32_t)len) << 3); - if (l < c->Nl) { + uint32_t l = *Nl + (((uint32_t)len) << 3); + if (l < *Nl) { // Handle carries. - c->Nh++; + (*Nh)++; } - c->Nh += (uint32_t)(len >> 29); - c->Nl = l; + *Nh += (uint32_t)(len >> 29); + *Nl = l; - size_t n = c->num; + size_t n = *num; if (n != 0) { - if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) { - OPENSSL_memcpy(c->data + n, data, HASH_CBLOCK - n); - HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); - n = HASH_CBLOCK - n; - data += n; + if (len >= block_size || len + n >= block_size) { + OPENSSL_memcpy(data + n, in, block_size - n); + block_func(h, data, 1); + n = block_size - n; + in += n; len -= n; - c->num = 0; - // Keep |c->data| zeroed when unused. - OPENSSL_memset(c->data, 0, HASH_CBLOCK); + *num = 0; + // Keep |data| zeroed when unused. + OPENSSL_memset(data, 0, block_size); } else { - OPENSSL_memcpy(c->data + n, data, len); - c->num += (unsigned)len; - return 1; + OPENSSL_memcpy(data + n, in, len); + *num += (unsigned)len; + return; } } - n = len / HASH_CBLOCK; + n = len / block_size; if (n > 0) { - HASH_BLOCK_DATA_ORDER(c->h, data, n); - n *= HASH_CBLOCK; - data += n; + block_func(h, in, n); + n *= block_size; + in += n; len -= n; } if (len != 0) { - c->num = (unsigned)len; - OPENSSL_memcpy(c->data, data, len); + *num = (unsigned)len; + OPENSSL_memcpy(data, in, len); } - return 1; } - -int HASH_FINAL(uint8_t out[HASH_DIGEST_LENGTH], HASH_CTX *c) { - // |c->data| always has room for at least one byte. A full block would have +// crypto_md32_final incorporates the partial block and trailing length into the +// digest state |h|. The trailing length is encoded in little-endian if +// |is_big_endian| is zero and big-endian otherwise. |data| must be a buffer of +// length |block_size| with the first |*num| bytes containing a partial block. +// |Nh| and |Nl| contain the total number of bits processed. On return, this +// function clears the partial block in |data| and +// |*num|. +// +// This function does not serialize |h| into a final digest. This is the +// responsibility of the caller. +static inline void crypto_md32_final(crypto_md32_block_func block_func, + uint32_t *h, uint8_t *data, + size_t block_size, unsigned *num, + uint32_t Nh, uint32_t Nl, + int is_big_endian) { + // |data| always has room for at least one byte. A full block would have // been consumed. - size_t n = c->num; - assert(n < HASH_CBLOCK); - c->data[n] = 0x80; + size_t n = *num; + assert(n < block_size); + data[n] = 0x80; n++; // Fill the block with zeros if there isn't room for a 64-bit length. - if (n > (HASH_CBLOCK - 8)) { - OPENSSL_memset(c->data + n, 0, HASH_CBLOCK - n); + if (n > block_size - 8) { + OPENSSL_memset(data + n, 0, block_size - n); n = 0; - HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); + block_func(h, data, 1); } - OPENSSL_memset(c->data + n, 0, HASH_CBLOCK - 8 - n); + OPENSSL_memset(data + n, 0, block_size - 8 - n); // Append a 64-bit length to the block and process it. - uint8_t *p = c->data + HASH_CBLOCK - 8; -#if defined(DATA_ORDER_IS_BIG_ENDIAN) - CRYPTO_store_u32_be(p, c->Nh); - CRYPTO_store_u32_be(p + 4, c->Nl); -#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) - CRYPTO_store_u32_le(p, c->Nl); - CRYPTO_store_u32_le(p + 4, c->Nh); -#endif - HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); - c->num = 0; - OPENSSL_memset(c->data, 0, HASH_CBLOCK); - - HASH_MAKE_STRING(c, out); - return 1; + if (is_big_endian) { + CRYPTO_store_u32_be(data + block_size - 8, Nh); + CRYPTO_store_u32_be(data + block_size - 4, Nl); + } else { + CRYPTO_store_u32_le(data + block_size - 8, Nl); + CRYPTO_store_u32_le(data + block_size - 4, Nh); + } + block_func(h, data, 1); + *num = 0; + OPENSSL_memset(data, 0, block_size); } #if defined(__cplusplus) } // extern C #endif + +#endif // OPENSSL_HEADER_DIGEST_MD32_COMMON_H
diff --git a/crypto/fipsmodule/md4/md4.c b/crypto/fipsmodule/md4/md4.c index 9d229bf..8779402 100644 --- a/crypto/fipsmodule/md4/md4.c +++ b/crypto/fipsmodule/md4/md4.c
@@ -60,6 +60,7 @@ #include <string.h> #include "../../internal.h" +#include "../digest/md32_common.h" uint8_t *MD4(const uint8_t *data, size_t len, uint8_t out[MD4_DIGEST_LENGTH]) { @@ -88,27 +89,22 @@ md4_block_data_order(c->h, data, 1); } -#define DATA_ORDER_IS_LITTLE_ENDIAN +int MD4_Update(MD4_CTX *c, const void *data, size_t len) { + crypto_md32_update(&md4_block_data_order, c->h, c->data, MD4_CBLOCK, &c->num, + &c->Nh, &c->Nl, data, len); + return 1; +} -#define HASH_CTX MD4_CTX -#define HASH_CBLOCK 64 -#define HASH_DIGEST_LENGTH 16 -#define HASH_UPDATE MD4_Update -#define HASH_FINAL MD4_Final -#define HASH_MAKE_STRING(c, s) \ - do { \ - CRYPTO_store_u32_le((s), (c)->h[0]); \ - (s) += 4; \ - CRYPTO_store_u32_le((s), (c)->h[1]); \ - (s) += 4; \ - CRYPTO_store_u32_le((s), (c)->h[2]); \ - (s) += 4; \ - CRYPTO_store_u32_le((s), (c)->h[3]); \ - (s) += 4; \ - } while (0) -#define HASH_BLOCK_DATA_ORDER md4_block_data_order +int MD4_Final(uint8_t out[MD4_DIGEST_LENGTH], MD4_CTX *c) { + crypto_md32_final(&md4_block_data_order, c->h, c->data, MD4_CBLOCK, &c->num, + c->Nh, c->Nl, /*is_big_endian=*/0); -#include "../digest/md32_common.h" + CRYPTO_store_u32_le(out, c->h[0]); + CRYPTO_store_u32_le(out + 4, c->h[1]); + CRYPTO_store_u32_le(out + 8, c->h[2]); + CRYPTO_store_u32_le(out + 12, c->h[3]); + return 1; +} // As pointed out by Wei Dai <weidai@eskimo.com>, the above can be // simplified to the code below. Wei attributes these optimizations @@ -238,14 +234,6 @@ } } -#undef DATA_ORDER_IS_LITTLE_ENDIAN -#undef HASH_CTX -#undef HASH_CBLOCK -#undef HASH_DIGEST_LENGTH -#undef HASH_UPDATE -#undef HASH_FINAL -#undef HASH_MAKE_STRING -#undef HASH_BLOCK_DATA_ORDER #undef F #undef G #undef H
diff --git a/crypto/fipsmodule/md5/md5.c b/crypto/fipsmodule/md5/md5.c index e454a84..eba34bc 100644 --- a/crypto/fipsmodule/md5/md5.c +++ b/crypto/fipsmodule/md5/md5.c
@@ -60,8 +60,9 @@ #include <openssl/mem.h> -#include "internal.h" #include "../../internal.h" +#include "../digest/md32_common.h" +#include "internal.h" uint8_t *MD5(const uint8_t *data, size_t len, uint8_t out[MD5_DIGEST_LENGTH]) { @@ -93,27 +94,22 @@ md5_block_data_order(c->h, data, 1); } -#define DATA_ORDER_IS_LITTLE_ENDIAN +int MD5_Update(MD5_CTX *c, const void *data, size_t len) { + crypto_md32_update(&md5_block_data_order, c->h, c->data, MD5_CBLOCK, &c->num, + &c->Nh, &c->Nl, data, len); + return 1; +} -#define HASH_CTX MD5_CTX -#define HASH_CBLOCK 64 -#define HASH_DIGEST_LENGTH 16 -#define HASH_UPDATE MD5_Update -#define HASH_FINAL MD5_Final -#define HASH_MAKE_STRING(c, s) \ - do { \ - CRYPTO_store_u32_le((s), (c)->h[0]); \ - (s) += 4; \ - CRYPTO_store_u32_le((s), (c)->h[1]); \ - (s) += 4; \ - CRYPTO_store_u32_le((s), (c)->h[2]); \ - (s) += 4; \ - CRYPTO_store_u32_le((s), (c)->h[3]); \ - (s) += 4; \ - } while (0) -#define HASH_BLOCK_DATA_ORDER md5_block_data_order +int MD5_Final(uint8_t out[MD5_DIGEST_LENGTH], MD5_CTX *c) { + crypto_md32_final(&md5_block_data_order, c->h, c->data, MD5_CBLOCK, &c->num, + c->Nh, c->Nl, /*is_big_endian=*/0); -#include "../digest/md32_common.h" + CRYPTO_store_u32_le(out, c->h[0]); + CRYPTO_store_u32_le(out + 4, c->h[1]); + CRYPTO_store_u32_le(out + 8, c->h[2]); + CRYPTO_store_u32_le(out + 12, c->h[3]); + return 1; +} // As pointed out by Wei Dai <weidai@eskimo.com>, the above can be // simplified to the code below. Wei attributes these optimizations @@ -280,14 +276,6 @@ #undef X #endif -#undef DATA_ORDER_IS_LITTLE_ENDIAN -#undef HASH_CTX -#undef HASH_CBLOCK -#undef HASH_DIGEST_LENGTH -#undef HASH_UPDATE -#undef HASH_FINAL -#undef HASH_MAKE_STRING -#undef HASH_BLOCK_DATA_ORDER #undef F #undef G #undef H
diff --git a/crypto/fipsmodule/sha/sha1.c b/crypto/fipsmodule/sha/sha1.c index 7149d11..c629308 100644 --- a/crypto/fipsmodule/sha/sha1.c +++ b/crypto/fipsmodule/sha/sha1.c
@@ -60,8 +60,9 @@ #include <openssl/mem.h> -#include "internal.h" #include "../../internal.h" +#include "../digest/md32_common.h" +#include "internal.h" int SHA1_Init(SHA_CTX *sha) { @@ -92,28 +93,24 @@ sha1_block_data_order(c->h, data, 1); } -#define DATA_ORDER_IS_BIG_ENDIAN +int SHA1_Update(SHA_CTX *c, const void *data, size_t len) { + crypto_md32_update(&sha1_block_data_order, c->h, c->data, SHA_CBLOCK, &c->num, + &c->Nh, &c->Nl, data, len); + return 1; +} -#define HASH_CTX SHA_CTX -#define HASH_CBLOCK 64 -#define HASH_DIGEST_LENGTH 20 -#define HASH_MAKE_STRING(c, s) \ - do { \ - CRYPTO_store_u32_be((s), (c)->h[0]); \ - (s) += 4; \ - CRYPTO_store_u32_be((s), (c)->h[1]); \ - (s) += 4; \ - CRYPTO_store_u32_be((s), (c)->h[2]); \ - (s) += 4; \ - CRYPTO_store_u32_be((s), (c)->h[3]); \ - (s) += 4; \ - CRYPTO_store_u32_be((s), (c)->h[4]); \ - (s) += 4; \ - } while (0) +int SHA1_Final(uint8_t out[SHA_DIGEST_LENGTH], SHA_CTX *c) { + crypto_md32_final(&sha1_block_data_order, c->h, c->data, SHA_CBLOCK, &c->num, + c->Nh, c->Nl, /*is_big_endian=*/1); -#define HASH_UPDATE SHA1_Update -#define HASH_FINAL SHA1_Final -#define HASH_BLOCK_DATA_ORDER sha1_block_data_order + CRYPTO_store_u32_be(out, c->h[0]); + CRYPTO_store_u32_be(out + 4, c->h[1]); + CRYPTO_store_u32_be(out + 8, c->h[2]); + CRYPTO_store_u32_be(out + 12, c->h[3]); + CRYPTO_store_u32_be(out + 16, c->h[4]); + return 1; +} + #define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) #define Xupdate(a, ix, ia, ib, ic, id) \ do { \ @@ -121,8 +118,6 @@ (ix) = (a) = ROTATE((a), 1); \ } while (0) -#include "../digest/md32_common.h" - #define K_00_19 0x5a827999UL #define K_20_39 0x6ed9eba1UL #define K_40_59 0x8f1bbcdcUL @@ -343,14 +338,6 @@ } #endif -#undef DATA_ORDER_IS_BIG_ENDIAN -#undef HASH_CTX -#undef HASH_CBLOCK -#undef HASH_DIGEST_LENGTH -#undef HASH_MAKE_STRING -#undef HASH_UPDATE -#undef HASH_FINAL -#undef HASH_BLOCK_DATA_ORDER #undef ROTATE #undef Xupdate #undef K_00_19
diff --git a/crypto/fipsmodule/sha/sha256.c b/crypto/fipsmodule/sha/sha256.c index ff961c8..4394f4a 100644 --- a/crypto/fipsmodule/sha/sha256.c +++ b/crypto/fipsmodule/sha/sha256.c
@@ -60,8 +60,9 @@ #include <openssl/mem.h> -#include "internal.h" #include "../../internal.h" +#include "../digest/md32_common.h" +#include "internal.h" int SHA224_Init(SHA256_CTX *sha) { @@ -112,16 +113,6 @@ return out; } -int SHA224_Update(SHA256_CTX *ctx, const void *data, size_t len) { - return SHA256_Update(ctx, data, len); -} - -int SHA224_Final(uint8_t out[SHA224_DIGEST_LENGTH], SHA256_CTX *ctx) { - // SHA224_Init sets |ctx->md_len| to |SHA224_DIGEST_LENGTH|, so this has a - // smaller output. - return SHA256_Final(out, ctx); -} - #ifndef SHA256_ASM static void sha256_block_data_order(uint32_t *state, const uint8_t *in, size_t num); @@ -131,55 +122,51 @@ sha256_block_data_order(c->h, data, 1); } -#define DATA_ORDER_IS_BIG_ENDIAN +int SHA256_Update(SHA256_CTX *c, const void *data, size_t len) { + crypto_md32_update(&sha256_block_data_order, c->h, c->data, SHA256_CBLOCK, + &c->num, &c->Nh, &c->Nl, data, len); + return 1; +} -#define HASH_CTX SHA256_CTX -#define HASH_CBLOCK 64 -#define HASH_DIGEST_LENGTH 32 +int SHA224_Update(SHA256_CTX *ctx, const void *data, size_t len) { + return SHA256_Update(ctx, data, len); +} -// 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 { \ - unsigned int nn; \ - switch ((c)->md_len) { \ - case SHA224_DIGEST_LENGTH: \ - for (nn = 0; nn < SHA224_DIGEST_LENGTH / 4; nn++) { \ - CRYPTO_store_u32_be((s), (c)->h[nn]); \ - (s) += 4; \ - } \ - break; \ - case SHA256_DIGEST_LENGTH: \ - for (nn = 0; nn < SHA256_DIGEST_LENGTH / 4; nn++) { \ - CRYPTO_store_u32_be((s), (c)->h[nn]); \ - (s) += 4; \ - } \ - break; \ - default: \ - if ((c)->md_len > SHA256_DIGEST_LENGTH) { \ - return 0; \ - } \ - for (nn = 0; nn < (c)->md_len / 4; nn++) { \ - CRYPTO_store_u32_be((s), (c)->h[nn]); \ - (s) += 4; \ - } \ - break; \ - } \ - } while (0) +static int sha256_final_impl(uint8_t *out, SHA256_CTX *c) { + crypto_md32_final(&sha256_block_data_order, c->h, c->data, SHA256_CBLOCK, + &c->num, c->Nh, c->Nl, /*is_big_endian=*/1); + // TODO(davidben): This overflow check one of the few places a low-level hash + // 'final' function can fail. SHA-512 does not have a corresponding check. + // These functions already misbehave if the caller arbitrarily mutates |c|, so + // can we assume one of |SHA256_Init| or |SHA224_Init| was used? + if (c->md_len > SHA256_DIGEST_LENGTH) { + return 0; + } -#define HASH_UPDATE SHA256_Update -#define HASH_FINAL SHA256_Final -#define HASH_BLOCK_DATA_ORDER sha256_block_data_order + assert(c->md_len % 4 == 0); + const size_t out_words = c->md_len / 4; + for (size_t i = 0; i < out_words; i++) { + CRYPTO_store_u32_be(out, c->h[i]); + out += 4; + } + return 1; +} -#include "../digest/md32_common.h" +int SHA256_Final(uint8_t out[SHA256_DIGEST_LENGTH], SHA256_CTX *c) { + // Ideally we would assert |sha->md_len| is |SHA256_DIGEST_LENGTH| to match + // the size hint, but calling code often pairs |SHA224_Init| with + // |SHA256_Final| and expects |sha->md_len| to carry the size over. + // + // TODO(davidben): Add an assert and fix code to match them up. + return sha256_final_impl(out, c); +} +int SHA224_Final(uint8_t out[SHA224_DIGEST_LENGTH], SHA256_CTX *ctx) { + // SHA224_Init sets |ctx->md_len| to |SHA224_DIGEST_LENGTH|, so this has a + // smaller output. + assert(ctx->md_len == SHA224_DIGEST_LENGTH); + return sha256_final_impl(out, ctx); +} #ifndef SHA256_ASM static const uint32_t K256[64] = { @@ -322,14 +309,6 @@ sha256_block_data_order(state, data, num_blocks); } -#undef DATA_ORDER_IS_BIG_ENDIAN -#undef HASH_CTX -#undef HASH_CBLOCK -#undef HASH_DIGEST_LENGTH -#undef HASH_MAKE_STRING -#undef HASH_UPDATE -#undef HASH_FINAL -#undef HASH_BLOCK_DATA_ORDER #undef ROTATE #undef Sigma0 #undef Sigma1
diff --git a/crypto/fipsmodule/sha/sha512.c b/crypto/fipsmodule/sha/sha512.c index 1f40e7a..befdd52 100644 --- a/crypto/fipsmodule/sha/sha512.c +++ b/crypto/fipsmodule/sha/sha512.c
@@ -162,7 +162,7 @@ int SHA384_Final(uint8_t out[SHA384_DIGEST_LENGTH], SHA512_CTX *sha) { // |SHA384_Init| sets |sha->md_len| to |SHA384_DIGEST_LENGTH|, so this has a - // |smaller output. + // smaller output. assert(sha->md_len == SHA384_DIGEST_LENGTH); return sha512_final_impl(out, sha); } @@ -237,7 +237,7 @@ int SHA512_Final(uint8_t out[SHA512_DIGEST_LENGTH], SHA512_CTX *sha) { // Ideally we would assert |sha->md_len| is |SHA512_DIGEST_LENGTH| to match // the size hint, but calling code often pairs |SHA384_Init| with - // |SHA512_Final| and expects |sha->md_len| to carry the over. + // |SHA512_Final| and expects |sha->md_len| to carry the size over. // // TODO(davidben): Add an assert and fix code to match them up. return sha512_final_impl(out, sha); @@ -270,9 +270,8 @@ assert(sha->md_len % 8 == 0); const size_t out_words = sha->md_len / 8; for (size_t i = 0; i < out_words; i++) { - const uint64_t t = CRYPTO_bswap8(sha->h[i]); - memcpy(out, &t, sizeof(t)); - out += sizeof(t); + CRYPTO_store_u64_be(out, sha->h[i]); + out += 8; } return 1;
diff --git a/decrepit/ripemd/ripemd.c b/decrepit/ripemd/ripemd.c index ac6bd83..9120cdd 100644 --- a/decrepit/ripemd/ripemd.c +++ b/decrepit/ripemd/ripemd.c
@@ -59,6 +59,7 @@ #include <string.h> #include "../../crypto/internal.h" +#include "../../crypto/fipsmodule/digest/md32_common.h" #define RIPEMD160_A 0x67452301L @@ -85,31 +86,24 @@ ripemd160_block_data_order(c->h, data, 1); } -#define DATA_ORDER_IS_LITTLE_ENDIAN +int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, size_t len) { + crypto_md32_update(&ripemd160_block_data_order, c->h, c->data, + RIPEMD160_CBLOCK, &c->num, &c->Nh, &c->Nl, data, len); + return 1; +} -#define HASH_LONG uint32_t -#define HASH_CTX RIPEMD160_CTX -#define HASH_CBLOCK RIPEMD160_CBLOCK -#define HASH_DIGEST_LENGTH RIPEMD160_DIGEST_LENGTH -#define HASH_UPDATE RIPEMD160_Update -#define HASH_FINAL RIPEMD160_Final -#define HASH_MAKE_STRING(c, s) \ - do { \ - CRYPTO_store_u32_le((s), (c)->h[0]); \ - (s) += 4; \ - CRYPTO_store_u32_le((s), (c)->h[1]); \ - (s) += 4; \ - CRYPTO_store_u32_le((s), (c)->h[2]); \ - (s) += 4; \ - CRYPTO_store_u32_le((s), (c)->h[3]); \ - (s) += 4; \ - CRYPTO_store_u32_le((s), (c)->h[4]); \ - (s) += 4; \ - } while (0) +int RIPEMD160_Final(uint8_t out[RIPEMD160_DIGEST_LENGTH], RIPEMD160_CTX *c) { + crypto_md32_final(&ripemd160_block_data_order, c->h, c->data, + RIPEMD160_CBLOCK, &c->num, c->Nh, c->Nl, + /*is_big_endian=*/0); -#define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order - -#include "../../crypto/fipsmodule/digest/md32_common.h" + CRYPTO_store_u32_le(out, c->h[0]); + CRYPTO_store_u32_le(out + 4, c->h[1]); + CRYPTO_store_u32_le(out + 8, c->h[2]); + CRYPTO_store_u32_le(out + 12, c->h[3]); + CRYPTO_store_u32_le(out + 16, c->h[4]); + return 1; +} // Transformed F2 and F4 are courtesy of Wei Dai <weidai@eskimo.com> #define F1(x, y, z) ((x) ^ (y) ^ (z))