Pull HASH_MAKE_STRING out of md32_common.h.

This is in preparation for taking md_len out of SHA256_CTX by allowing us to do
something similar to SHA512_CTX. md32_common.h now emits a static "finish"
function which Final composes with the extraction step.

Change-Id: I314fb31e2482af642fd280500cc0e4716aef1ac6
Reviewed-on: https://boringssl-review.googlesource.com/7721
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
David Benjamin 2016-04-19 23:51:11 -04:00 committed by Adam Langley
parent e3118b8dc4
commit a90aa64302
7 changed files with 112 additions and 112 deletions

View File

@ -90,7 +90,7 @@ extern "C" {
* |HASH_TRANSFORM| must be defined as the the name of the "Transform"
* function to generate.
*
* |HASH_FINAL| must be defined as the name of "Final" function to generate.
* |HASH_FINISH| must be defined as the name of "finish" 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,11 +103,7 @@ 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 |<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|.
*/
* and so will have |<chaining length> / sizeof(uint32_t)| elements. */
#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
#error "DATA_ORDER must be defined!"
@ -126,18 +122,14 @@ extern "C" {
#ifndef HASH_TRANSFORM
#error "HASH_TRANSFORM must be defined!"
#endif
#ifndef HASH_FINAL
#error "HASH_FINAL must be defined!"
#ifndef HASH_FINISH
#error "HASH_FINISH 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) \
@ -220,7 +212,7 @@ void HASH_TRANSFORM(HASH_CTX *c, const uint8_t *data) {
}
int HASH_FINAL(uint8_t *md, HASH_CTX *c) {
static void HASH_FINISH(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;
@ -249,9 +241,6 @@ int HASH_FINAL(uint8_t *md, 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;
}

View File

@ -88,23 +88,27 @@ 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_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_FINISH md4_finish
#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 <weidai@eskimo.com>, 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. */

View File

@ -101,23 +101,27 @@ 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_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_FINISH md5_finish
#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 <weidai@eskimo.com>, 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.

View File

@ -98,24 +98,10 @@ 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_FINAL SHA1_Final
#define HASH_FINISH sha1_finish
#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) \
@ -128,6 +114,24 @@ 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

View File

@ -138,48 +138,9 @@ int SHA224_Final(uint8_t *md, SHA256_CTX *ctx) {
#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_FINAL SHA256_Final
#define HASH_FINISH sha256_finish
#define HASH_BLOCK_DATA_ORDER sha256_block_data_order
#ifndef SHA256_ASM
static
@ -188,6 +149,40 @@ void sha256_block_data_order(uint32_t *state, const uint8_t *in, size_t num);
#include "../digest/md32_common.h"
int SHA256_Final(uint8_t *md, SHA256_CTX *sha) {
sha256_finish(sha);
/* TODO(davidben): Replace this with different versions of SHA256_Final
* and SHA224_Final. */
uint32_t ll;
unsigned int nn;
switch (sha->md_len) {
case SHA224_DIGEST_LENGTH:
for (nn = 0; nn < SHA224_DIGEST_LENGTH / 4; nn++) {
ll = sha->h[nn];
HOST_l2c(ll, md);
}
break;
case SHA256_DIGEST_LENGTH:
for (nn = 0; nn < SHA256_DIGEST_LENGTH / 4; nn++) {
ll = sha->h[nn];
HOST_l2c(ll, md);
}
break;
default:
if (sha->md_len > SHA256_DIGEST_LENGTH) {
return 0;
}
for (nn = 0; nn < sha->md_len / 4; nn++) {
ll = sha->h[nn];
HOST_l2c(ll, md);
}
break;
}
return 1;
}
#ifndef SHA256_ASM
static const uint32_t K256[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,

View File

@ -74,21 +74,7 @@ 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_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_FINISH ripemd160_finish
#define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order
#include "../../crypto/digest/md32_common.h"

View File

@ -71,6 +71,24 @@ 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;