diff --git a/hphp/runtime/ext/ext_hash.cpp b/hphp/runtime/ext/ext_hash.cpp index ea78b7e38..30182e7e9 100644 --- a/hphp/runtime/ext/ext_hash.cpp +++ b/hphp/runtime/ext/ext_hash.cpp @@ -51,6 +51,7 @@ public: HashEngines["md4"] = HashEnginePtr(new hash_md4()); HashEngines["md5"] = HashEnginePtr(new hash_md5()); HashEngines["sha1"] = HashEnginePtr(new hash_sha1()); + HashEngines["sha224"] = HashEnginePtr(new hash_sha224()); HashEngines["sha256"] = HashEnginePtr(new hash_sha256()); HashEngines["sha384"] = HashEnginePtr(new hash_sha384()); HashEngines["sha512"] = HashEnginePtr(new hash_sha512()); diff --git a/hphp/runtime/ext/hash/hash_sha.cpp b/hphp/runtime/ext/hash/hash_sha.cpp index 2bee432ff..9dfe95bb8 100644 --- a/hphp/runtime/ext/hash/hash_sha.cpp +++ b/hphp/runtime/ext/hash/hash_sha.cpp @@ -37,7 +37,8 @@ typedef struct { unsigned char buffer[64]; /* input buffer */ } PHP_SHA256_CTX; -hash_sha256::hash_sha256() : HashEngine(32, 64, sizeof(PHP_SHA256_CTX)) { +hash_sha256::hash_sha256(int size /*= 32 */) : + HashEngine(size, 64, sizeof(PHP_SHA256_CTX)) { } /////////////////////////////////////////////////////////////////////////////// @@ -347,22 +348,22 @@ void hash_sha1::hash_final(unsigned char *digest, void *context_) { /////////////////////////////////////////////////////////////////////////////// -#define ROTR32(b,x) ((x >> b) | (x << (32 - b))) -#define ROTR64(b,x) ((x >> b) | (x << (64 - b))) -#define SHR(b, x) (x >> b) +#define ROTR32(b,x) ((x >> b) | (x << (32 - b))) +#define ROTR64(b,x) ((x >> b) | (x << (64 - b))) +#define SHR(b, x) (x >> b) /* Ch */ -#define SHA256_F0(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define SHA256_F0(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) /* Maj */ -#define SHA256_F1(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +#define SHA256_F1(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) /* SUM0 */ -#define SHA256_F2(x) (ROTR32( 2,(x)) ^ ROTR32(13,(x)) ^ ROTR32(22,(x))) +#define SHA256_F2(x) (ROTR32( 2,(x)) ^ ROTR32(13,(x)) ^ ROTR32(22,(x))) /* SUM1 */ -#define SHA256_F3(x) (ROTR32( 6,(x)) ^ ROTR32(11,(x)) ^ ROTR32(25,(x))) +#define SHA256_F3(x) (ROTR32( 6,(x)) ^ ROTR32(11,(x)) ^ ROTR32(25,(x))) /* OM0 */ -#define SHA256_F4(x) (ROTR32( 7,(x)) ^ ROTR32(18,(x)) ^ SHR( 3,(x))) +#define SHA256_F4(x) (ROTR32( 7,(x)) ^ ROTR32(18,(x)) ^ SHR( 3,(x))) /* OM1 */ -#define SHA256_F5(x) (ROTR32(17,(x)) ^ ROTR32(19,(x)) ^ SHR(10,(x))) +#define SHA256_F5(x) (ROTR32(17,(x)) ^ ROTR32(19,(x)) ^ SHR(10,(x))) static const unsigned int SHA256_K[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, @@ -511,21 +512,44 @@ void hash_sha256::hash_final(unsigned char *digest, void *context_) { memset((unsigned char*) context, 0, sizeof(*context)); } +/////////////////////////////////////////////////////////////////////////////// + +void hash_sha224::hash_init(void *context_) { + PHP_SHA256_CTX *context = (PHP_SHA256_CTX*)context_; + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. + */ + context->state[0] = 0xc1059ed8; + context->state[1] = 0x367cd507; + context->state[2] = 0x3070dd17; + context->state[3] = 0xf70e5939; + context->state[4] = 0xffc00b31; + context->state[5] = 0x68581511; + context->state[6] = 0x64f98fa7; + context->state[7] = 0xbefa4fa4; +} + +void hash_sha224::hash_final(unsigned char *digest, void *context_) { + unsigned char digest256[32]; + hash_sha256::hash_final(digest256, context_); + memcpy(digest, digest256, 28); +} + /////////////////////////////////////////////////////////////////////////////// /* sha384/sha512 */ /* Ch */ -#define SHA512_F0(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define SHA512_F0(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) /* Maj */ -#define SHA512_F1(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +#define SHA512_F1(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) /* SUM0 */ -#define SHA512_F2(x) (ROTR64(28, x) ^ ROTR64(34, x) ^ ROTR64(39, x)) +#define SHA512_F2(x) (ROTR64(28, x) ^ ROTR64(34, x) ^ ROTR64(39, x)) /* SUM1 */ -#define SHA512_F3(x) (ROTR64(14, x) ^ ROTR64(18, x) ^ ROTR64(41, x)) +#define SHA512_F3(x) (ROTR64(14, x) ^ ROTR64(18, x) ^ ROTR64(41, x)) /* OM0 */ -#define SHA512_F4(x) (ROTR64( 1, x) ^ ROTR64( 8, x) ^ SHR(7, x)) +#define SHA512_F4(x) (ROTR64( 1, x) ^ ROTR64( 8, x) ^ SHR(7, x)) /* OM1 */ -#define SHA512_F5(x) (ROTR64(19, x) ^ ROTR64(61, x) ^ SHR(6, x)) +#define SHA512_F5(x) (ROTR64(19, x) ^ ROTR64(61, x) ^ SHR(6, x)) static const uint64_t SHA512_K[128] = { L64(0x428a2f98d728ae22), L64(0x7137449123ef65cd), L64(0xb5c0fbcfec4d3b2f), L64(0xe9b5dba58189dbbc), diff --git a/hphp/runtime/ext/hash/hash_sha.h b/hphp/runtime/ext/hash/hash_sha.h index 8cf7a7d77..ba0e6c07e 100644 --- a/hphp/runtime/ext/hash/hash_sha.h +++ b/hphp/runtime/ext/hash/hash_sha.h @@ -35,7 +35,7 @@ public: class hash_sha256 : public HashEngine { public: - hash_sha256(); + explicit hash_sha256(int size = 32); virtual void hash_init(void *context); virtual void hash_update(void *context, const unsigned char *buf, @@ -43,6 +43,17 @@ public: virtual void hash_final(unsigned char *digest, void *context); }; +/* sha224 is just sha256 with a different initial vector + * and a truncated output. + */ +class hash_sha224 : public hash_sha256 { +public: + hash_sha224() : hash_sha256(28) {} + + virtual void hash_init(void *context); + virtual void hash_final(unsigned char *digest, void *context); +}; + class hash_sha384 : public HashEngine { public: hash_sha384(); diff --git a/hphp/test/zend/bad/ext-hash/sha224.php b/hphp/test/zend/good/ext-hash/sha224.php similarity index 100% rename from hphp/test/zend/bad/ext-hash/sha224.php rename to hphp/test/zend/good/ext-hash/sha224.php diff --git a/hphp/test/zend/bad/ext-hash/sha224.php.expectf b/hphp/test/zend/good/ext-hash/sha224.php.expectf similarity index 100% rename from hphp/test/zend/bad/ext-hash/sha224.php.expectf rename to hphp/test/zend/good/ext-hash/sha224.php.expectf