Bug 798634 - Style patrol on mfbt/SHA1.*. r=espindola

--HG--
extra : rebase_source : 7282b80ebe5f23b669a5f3142f3a6e50b6776789
This commit is contained in:
Jeff Walden 2012-08-28 17:27:05 -07:00
parent 34be9490e9
commit 6c828f9bb0
3 changed files with 137 additions and 115 deletions

View File

@ -2,49 +2,54 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <string.h>
#include "mozilla/SHA1.h"
#include "mozilla/Assertions.h"
#include "mozilla/SHA1.h"
#include <string.h>
// FIXME: We should probably create a more complete mfbt/Endian.h. This assumes
// that any compiler that doesn't define these macros is little endian.
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define MOZ_IS_LITTLE_ENDIAN
#endif
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define MOZ_IS_LITTLE_ENDIAN
# endif
#else
#define MOZ_IS_LITTLE_ENDIAN
# define MOZ_IS_LITTLE_ENDIAN
#endif
using namespace mozilla;
using mozilla::SHA1Sum;
static inline uint32_t SHA_ROTL(uint32_t t, uint32_t n)
static inline uint32_t
SHA_ROTL(uint32_t t, uint32_t n)
{
return ((t << n) | (t >> (32 - n)));
MOZ_ASSERT(n < 32);
return (t << n) | (t >> (32 - n));
}
static inline unsigned
SHA_HTONL(unsigned x)
{
#ifdef MOZ_IS_LITTLE_ENDIAN
static inline unsigned SHA_HTONL(unsigned x) {
const unsigned int mask = 0x00FF00FF;
x = (x << 16) | (x >> 16);
return ((x & mask) << 8) | ((x >> 8) & mask);
}
#else
static inline unsigned SHA_HTONL(unsigned x) {
return x;
}
#endif
}
static void shaCompress(volatile unsigned *X, const uint32_t * datain);
static void
shaCompress(volatile unsigned* X, const uint32_t* datain);
#define SHA_F1(X,Y,Z) ((((Y)^(Z))&(X))^(Z))
#define SHA_F2(X,Y,Z) ((X)^(Y)^(Z))
#define SHA_F3(X,Y,Z) (((X)&(Y))|((Z)&((X)|(Y))))
#define SHA_F4(X,Y,Z) ((X)^(Y)^(Z))
#define SHA_F1(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
#define SHA_F2(X, Y, Z) ((X) ^ (Y) ^ (Z))
#define SHA_F3(X, Y, Z) (((X) & (Y)) | ((Z) & ((X) | (Y))))
#define SHA_F4(X, Y, Z) ((X) ^ (Y) ^ (Z))
#define SHA_MIX(n,a,b,c) XW(n) = SHA_ROTL(XW(a)^XW(b)^XW(c)^XW(n), 1)
#define SHA_MIX(n, a, b, c) XW(n) = SHA_ROTL(XW(a) ^ XW(b) ^ XW(c) ^XW(n), 1)
SHA1Sum::SHA1Sum() : size(0), mDone(false)
SHA1Sum::SHA1Sum()
: size(0), mDone(false)
{
// Initialize H with constants from FIPS180-1.
H[0] = 0x67452301L;
@ -54,7 +59,9 @@ SHA1Sum::SHA1Sum() : size(0), mDone(false)
H[4] = 0xc3d2e1f0L;
}
/* Explanation of H array and index values:
/*
* Explanation of H array and index values:
*
* The context's H array is actually the concatenation of two arrays
* defined by SHA1, the H array of state variables (5 elements),
* and the W array of intermediate values, of which there are 16 elements.
@ -91,80 +98,77 @@ SHA1Sum::SHA1Sum() : size(0), mDone(false)
/*
* SHA: Add data to context.
*/
void SHA1Sum::update(const uint8_t *dataIn, uint32_t len)
void
SHA1Sum::update(const uint8_t* dataIn, uint32_t len)
{
MOZ_ASSERT(!mDone);
register unsigned int lenB;
register unsigned int togo;
MOZ_ASSERT(!mDone, "SHA1Sum can only be used to compute a single hash.");
if (!len)
if (len == 0)
return;
/* accumulate the byte count. */
lenB = (unsigned int)(size) & 63U;
/* Accumulate the byte count. */
unsigned int lenB = static_cast<unsigned int>(size) & 63U;
size += len;
/*
* Read the data into W and process blocks as they get full
*/
/* Read the data into W and process blocks as they get full. */
unsigned int togo;
if (lenB > 0) {
togo = 64U - lenB;
if (len < togo)
togo = len;
memcpy(u.b + lenB, dataIn, togo);
len -= togo;
len -= togo;
dataIn += togo;
lenB = (lenB + togo) & 63U;
if (!lenB) {
lenB = (lenB + togo) & 63U;
if (!lenB)
shaCompress(&H[H2X], u.w);
}
}
while (len >= 64U) {
len -= 64U;
shaCompress(&H[H2X], (uint32_t *)dataIn);
len -= 64U;
shaCompress(&H[H2X], reinterpret_cast<const uint32_t*>(dataIn));
dataIn += 64U;
}
if (len) {
if (len > 0)
memcpy(u.b, dataIn, len);
}
}
/*
* SHA: Generate hash value
*/
void SHA1Sum::finish(uint8_t hashout[20])
void
SHA1Sum::finish(SHA1Sum::Hash& hashOut)
{
MOZ_ASSERT(!mDone);
register uint64_t size2 = size;
register uint32_t lenB = (uint32_t)size2 & 63;
MOZ_ASSERT(!mDone, "SHA1Sum can only be used to compute a single hash.");
static const uint8_t bulk_pad[64] = { 0x80,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
uint64_t size2 = size;
uint32_t lenB = uint32_t(size2) & 63;
/*
* Pad with a binary 1 (e.g. 0x80), then zeroes, then length in bits
*/
static const uint8_t bulk_pad[64] =
{ 0x80,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
/* Pad with a binary 1 (e.g. 0x80), then zeroes, then length in bits. */
update(bulk_pad, (((55 + 64) - lenB) & 63) + 1);
MOZ_ASSERT((uint32_t(size) & 63) == 56);
update(bulk_pad, (((55+64) - lenB) & 63) + 1);
MOZ_ASSERT(((uint32_t)size & 63) == 56);
/* Convert size from bytes to bits. */
size2 <<= 3;
u.w[14] = SHA_HTONL((uint32_t)(size2 >> 32));
u.w[15] = SHA_HTONL((uint32_t)size2);
u.w[14] = SHA_HTONL(uint32_t(size2 >> 32));
u.w[15] = SHA_HTONL(uint32_t(size2));
shaCompress(&H[H2X], u.w);
/*
* Output hash
*/
/* Output hash. */
u.w[0] = SHA_HTONL(H[0]);
u.w[1] = SHA_HTONL(H[1]);
u.w[2] = SHA_HTONL(H[2]);
u.w[3] = SHA_HTONL(H[3]);
u.w[4] = SHA_HTONL(H[4]);
memcpy(hashout, u.w, 20);
memcpy(hashOut, u.w, 20);
mDone = true;
}
@ -218,25 +222,24 @@ void SHA1Sum::finish(uint8_t hashout[20])
static void
shaCompress(volatile unsigned *X, const uint32_t *inbuf)
{
register unsigned A, B, C, D, E;
unsigned A, B, C, D, E;
#define XH(n) X[n-H2X]
#define XW(n) X[n-W2X]
#define XH(n) X[n - H2X]
#define XW(n) X[n - W2X]
#define K0 0x5a827999L
#define K1 0x6ed9eba1L
#define K2 0x8f1bbcdcL
#define K3 0xca62c1d6L
#define SHA_RND1(a,b,c,d,e,n) \
a = SHA_ROTL(b,5)+SHA_F1(c,d,e)+a+XW(n)+K0; c=SHA_ROTL(c,30)
#define SHA_RND2(a,b,c,d,e,n) \
a = SHA_ROTL(b,5)+SHA_F2(c,d,e)+a+XW(n)+K1; c=SHA_ROTL(c,30)
#define SHA_RND3(a,b,c,d,e,n) \
a = SHA_ROTL(b,5)+SHA_F3(c,d,e)+a+XW(n)+K2; c=SHA_ROTL(c,30)
#define SHA_RND4(a,b,c,d,e,n) \
a = SHA_ROTL(b,5)+SHA_F4(c,d,e)+a+XW(n)+K3; c=SHA_ROTL(c,30)
#define SHA_RND1(a, b, c, d, e, n) \
a = SHA_ROTL(b, 5) + SHA_F1(c, d, e) + a + XW(n) + K0; c = SHA_ROTL(c, 30)
#define SHA_RND2(a, b, c, d, e, n) \
a = SHA_ROTL(b, 5) + SHA_F2(c, d, e) + a + XW(n) + K1; c = SHA_ROTL(c, 30)
#define SHA_RND3(a, b, c, d, e, n) \
a = SHA_ROTL(b, 5) + SHA_F3(c, d, e) + a + XW(n) + K2; c = SHA_ROTL(c, 30)
#define SHA_RND4(a, b, c, d, e, n) \
a = SHA_ROTL(b ,5) + SHA_F4(c, d, e) + a + XW(n) + K3; c = SHA_ROTL(c, 30)
#define LOAD(n) XW(n) = SHA_HTONL(inbuf[n])

View File

@ -5,42 +5,56 @@
/* Simple class for computing SHA1. */
/*
* To compute the SHA1 of a buffer using this class you should write something
* like:
* void SHA1(const uint8_t* buf, unsigned size, uint8_t hash[20])
* {
* SHA1Sum S;
* S.update(buf, size);
* S.finish(hash);
* }
* If there are multiple buffers or chunks, the update method can be called
* multiple times and the SHA1 is computed on the concatenation of all the
* buffers passed to it.
* The finish method may only be called once and cannot be followed by calls
* to update.
*/
#ifndef mozilla_SHA1_h_
#define mozilla_SHA1_h_
#include "mozilla/StandardInteger.h"
namespace mozilla {
class SHA1Sum {
union {
uint32_t w[16]; /* input buffer */
uint8_t b[64];
} u;
uint64_t size; /* count of hashed bytes. */
unsigned H[22]; /* 5 state variables, 16 tmp values, 1 extra */
bool mDone;
public:
static const unsigned int HashSize = 20;
SHA1Sum();
void update(const uint8_t *dataIn, uint32_t len);
void finish(uint8_t hashout[20]);
#include <stddef.h>
namespace mozilla {
/**
* This class computes the SHA1 hash of a byte sequence, or of the concatenation
* of multiple sequences. For example, computing the SHA1 of two sequences of
* bytes could be done as follows:
*
* void SHA1(const uint8_t* buf1, uint32_t size1,
* const uint8_t* buf2, uint32_t size2,
* SHA1Sum::Hash& hash)
* {
* SHA1Sum s;
* s.update(buf1, size1);
* s.update(buf2, size2);
* s.finish(hash);
* }
*
* The finish method may only be called once and cannot be followed by calls
* to update.
*/
class SHA1Sum
{
union {
uint32_t w[16]; /* input buffer */
uint8_t b[64];
} u;
uint64_t size; /* count of hashed bytes. */
unsigned H[22]; /* 5 state variables, 16 tmp values, 1 extra */
bool mDone;
public:
SHA1Sum();
static const size_t HashSize = 20;
typedef uint8_t Hash[HashSize];
/* Add len bytes of dataIn to the data sequence being hashed. */
void update(const uint8_t* dataIn, uint32_t len);
/* Compute the final hash of all data into hashOut. */
void finish(SHA1Sum::Hash& hashOut);
};
}
} /* namespace mozilla */
#endif /* mozilla_SHA1_h_ */

View File

@ -2,11 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Assertions.h"
#include "mozilla/SHA1.h"
using namespace mozilla;
using mozilla::SHA1Sum;
static unsigned int TestV[1024] = {
static unsigned int testV[1024] = {
0x048edc1a, 0x4345588c, 0x0ef03cbf, 0x1d6438f5, 0x094e0a1e, 0x68535f60,
0x14e8c927, 0x60190043, 0x5d640ab7, 0x73dc7c62, 0x364223f9, 0x47320292,
0x3924cae0, 0x5f6b26d3, 0x5efa04ef, 0x7aab361e, 0x2773b1aa, 0x1631b07d,
@ -180,20 +181,24 @@ static unsigned int TestV[1024] = {
0x236f5e8d, 0x1a4b4495, 0x360bd008, 0x32227d40
};
int main()
int
main()
{
SHA1Sum S;
unsigned char hash[20];
S.update((const unsigned char*) TestV, sizeof(TestV));
S.finish(hash);
const unsigned char expected[20] = {
0xc8, 0xf2, 0x09, 0x59, 0x4e, 0x64, 0x40, 0xaa, 0x7b, 0xf7, 0xb8, 0xe0,
0xfa, 0x44, 0xb2, 0x31, 0x95, 0xad, 0x94, 0x81};
SHA1Sum sum;
SHA1Sum::Hash hash;
sum.update(reinterpret_cast<const uint8_t*>(testV), sizeof(testV));
sum.finish(hash);
static const uint8_t expected[20] =
{ 0xc8, 0xf2, 0x09, 0x59, 0x4e, 0x64, 0x40, 0xaa, 0x7b, 0xf7, 0xb8, 0xe0,
0xfa, 0x44, 0xb2, 0x31, 0x95, 0xad, 0x94, 0x81 };
MOZ_STATIC_ASSERT(sizeof(expected) == sizeof(SHA1Sum::Hash),
"expected-data size should be the same as the actual hash "
"size");
for (size_t i = 0; i < SHA1Sum::HashSize; i++)
MOZ_ASSERT(hash[i] == expected[i]);
for (unsigned int i = 0; i < 20; ++i) {
if (hash[i] != expected[i]) {
return 1;
}
}
return 0;
}