Merge "cryptoc: sync with upstream sources"
diff --git a/Makefile b/Makefile
index 3a5b54b..863a53b 100644
--- a/Makefile
+++ b/Makefile
@@ -8,11 +8,13 @@
 AR ?= $(CROSS_COMPILE)ar
 
 SOURCES = hmac.c
+SOURCES += md5.c
 SOURCES += p256.c
 SOURCES += p256_ec.c
 SOURCES += p256_ecdsa.c
 SOURCES += p256_prng.c
 SOURCES += sha.c
+SOURCES += sha224.c
 SOURCES += sha256.c
 ifeq ($(CONFIG_UPTO_SHA512),y)
 SOURCES += sha384.c
diff --git a/hmac.c b/hmac.c
index ef6ad82..9fa569d 100644
--- a/hmac.c
+++ b/hmac.c
@@ -17,13 +17,16 @@
 #include <string.h>
 #include "cryptoc/sha.h"
 #include "cryptoc/md5.h"
+#include "cryptoc/sha224.h"
 #include "cryptoc/sha256.h"
+#include "cryptoc/sha384.h"
+#include "cryptoc/sha512.h"
 
 static void HMAC_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) {
   unsigned int i;
   memset(&ctx->opad[0], 0, sizeof(ctx->opad));
 
-  if (len > sizeof(ctx->opad)) {
+  if (len > HASH_block_size(&ctx->hash)) {
     HASH_init(&ctx->hash);
     HASH_update(&ctx->hash, key, len);
     memcpy(&ctx->opad[0], HASH_final(&ctx->hash), HASH_size(&ctx->hash));
@@ -31,14 +34,14 @@
     memcpy(&ctx->opad[0], key, len);
   }
 
-  for (i = 0; i < sizeof(ctx->opad); ++i) {
+  for (i = 0; i < HASH_block_size(&ctx->hash); ++i) {
     ctx->opad[i] ^= 0x36;
   }
 
   HASH_init(&ctx->hash);
-  HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad));  // hash ipad
+  HASH_update(&ctx->hash, ctx->opad, HASH_block_size(&ctx->hash));  // hash ipad
 
-  for (i = 0; i < sizeof(ctx->opad); ++i) {
+  for (i = 0; i < HASH_block_size(&ctx->hash); ++i) {
     ctx->opad[i] ^= (0x36 ^ 0x5c);
   }
 }
@@ -53,18 +56,39 @@
   HMAC_init(ctx, key, len);
 }
 
+void HMAC_SHA224_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) {
+  SHA224_init(&ctx->hash);
+  HMAC_init(ctx, key, len);
+}
+
 void HMAC_SHA256_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) {
   SHA256_init(&ctx->hash);
   HMAC_init(ctx, key, len);
 }
 
+#ifdef SHA512_SUPPORT
+void HMAC_SHA384_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) {
+  SHA384_init(&ctx->hash);
+  HMAC_init(ctx, key, len);
+}
+
+void HMAC_SHA512_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) {
+  SHA512_init(&ctx->hash);
+  HMAC_init(ctx, key, len);
+}
+#endif
+
 const uint8_t* HMAC_final(LITE_HMAC_CTX* ctx) {
-  uint8_t digest[32];  // upto SHA2
+#ifndef SHA512_SUPPORT
+  uint8_t digest[32];  // upto SHA2-256
+#else
+  uint8_t digest[64];  // upto SHA2-512
+#endif
   memcpy(digest, HASH_final(&ctx->hash),
          (HASH_size(&ctx->hash) <= sizeof(digest) ?
              HASH_size(&ctx->hash) : sizeof(digest)));
   HASH_init(&ctx->hash);
-  HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad));
+  HASH_update(&ctx->hash, ctx->opad, HASH_block_size(&ctx->hash));
   HASH_update(&ctx->hash, digest, HASH_size(&ctx->hash));
   always_memset(&ctx->opad[0], 0, sizeof(ctx->opad));  // wipe key
   return HASH_final(&ctx->hash);
diff --git a/include/cryptoc/hash-internal.h b/include/cryptoc/hash-internal.h
index 668cafc..e6ebcef 100644
--- a/include/cryptoc/hash-internal.h
+++ b/include/cryptoc/hash-internal.h
@@ -14,8 +14,16 @@
 #ifndef SECURITY_UTIL_LITE_HASH_INTERNAL_H__
 #define SECURITY_UTIL_LITE_HASH_INTERNAL_H__
 
-#include <stdint.h>
 #include <stddef.h>
+#include <stdint.h>
+
+#ifdef LITE_EMULATED_64BIT_OPS
+#define LITE_LShiftU64(a, b) LShiftU64((a), (b))
+#define LITE_RShiftU64(a, b) RShiftU64((a), (b))
+#else
+#define LITE_LShiftU64(a, b) ((a) << (b))
+#define LITE_RShiftU64(a, b) ((a) >> (b))
+#endif  // LITE_EMULATED_64BIT_OPS
 
 #ifdef __cplusplus
 extern "C" {
@@ -29,6 +37,9 @@
   const uint8_t* (* const final)(struct HASH_CTX*);
   const uint8_t* (* const hash)(const void*, size_t, uint8_t*);
   unsigned int size;
+#ifdef SHA512_SUPPORT
+  unsigned int block_size;
+#endif
 } HASH_VTAB;
 
 typedef struct HASH_CTX {
@@ -48,6 +59,11 @@
 #define HASH_final(ctx) (ctx)->f->final(ctx)
 #define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest)
 #define HASH_size(ctx) (ctx)->f->size
+#ifdef SHA512_SUPPORT
+#define HASH_block_size(ctx) (ctx)->f->block_size
+#else
+#define HASH_block_size(ctx) sizeof((ctx)->buf)
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/include/cryptoc/hmac.h b/include/cryptoc/hmac.h
index 4e86dec..15f6563 100644
--- a/include/cryptoc/hmac.h
+++ b/include/cryptoc/hmac.h
@@ -23,12 +23,19 @@
 
 typedef struct LITE_HMAC_CTX {
   HASH_CTX hash;
+#ifndef SHA512_SUPPORT
   uint8_t opad[64];
+#else
+  uint8_t opad[128];
+#endif
 } LITE_HMAC_CTX;
 
 void HMAC_MD5_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
 void HMAC_SHA_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
+void HMAC_SHA224_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
 void HMAC_SHA256_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
+void HMAC_SHA384_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
+void HMAC_SHA512_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len);
 const uint8_t* HMAC_final(LITE_HMAC_CTX* ctx);
 
 #define HMAC_update(ctx, data, len) HASH_update(&(ctx)->hash, data, len)
diff --git a/include/cryptoc/md5.h b/include/cryptoc/md5.h
index f335568..a86f0e8 100644
--- a/include/cryptoc/md5.h
+++ b/include/cryptoc/md5.h
@@ -14,8 +14,8 @@
 #ifndef SECURITY_UTIL_LITE_MD5_H__
 #define SECURITY_UTIL_LITE_MD5_H__
 
-#include <stdint.h>
 #include <stddef.h>
+#include <stdint.h>
 #include "cryptoc/hash-internal.h"
 
 #ifdef __cplusplus
@@ -33,6 +33,7 @@
 const uint8_t* MD5_hash(const void* data, size_t len, uint8_t* digest);
 
 #define MD5_DIGEST_SIZE 16
+#define MD5_BLOCK_SIZE 64
 
 #ifdef __cplusplus
 }
diff --git a/include/cryptoc/p256.h b/include/cryptoc/p256.h
index fc482ce..e63badc 100644
--- a/include/cryptoc/p256.h
+++ b/include/cryptoc/p256.h
@@ -140,10 +140,16 @@
 // Outputs big-endian binary form. No leading zero skips.
 void p256_to_bin(const p256_int* src, uint8_t dst[P256_NBYTES]);
 
+// Outputs little-endian binary form. No leading zero skips.
+void p256_to_le_bin(const p256_int* src, uint8_t dst[P256_NBYTES]);
+
 // Reads from big-endian binary form,
 // thus pre-pad with leading zeros if short.
 void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst);
 
+// Reads from little-endian binary form.
+void p256_from_le_bin(const uint8_t src[P256_NBYTES], p256_int* dst);
+
 #define P256_DIGITS(x) ((x)->a)
 #define P256_DIGIT(x,y) ((x)->a[y])
 
diff --git a/include/cryptoc/p256_prng.h b/include/cryptoc/p256_prng.h
index c459f19..d0a6dc0 100644
--- a/include/cryptoc/p256_prng.h
+++ b/include/cryptoc/p256_prng.h
@@ -34,8 +34,8 @@
 #define P256_PRNG_SIZE 32
 
 typedef struct P256_PRNG_CTX {
-  uint32_t Key[P256_PRNG_SIZE];
-  uint32_t V[P256_PRNG_SIZE];
+  uint8_t Key[P256_PRNG_SIZE];
+  uint8_t V[P256_PRNG_SIZE];
   uint64_t instance_count;
   uint64_t call_count;
 } P256_PRNG_CTX;
diff --git a/include/cryptoc/sha.h b/include/cryptoc/sha.h
index d760ac2..ca402a9 100644
--- a/include/cryptoc/sha.h
+++ b/include/cryptoc/sha.h
@@ -34,6 +34,7 @@
 #ifndef SHA_DIGEST_SIZE
 #define SHA_DIGEST_SIZE 20
 #endif
+#define SHA_BLOCK_SIZE 64
 
 #ifdef __cplusplus
 }
diff --git a/include/cryptoc/sha224.h b/include/cryptoc/sha224.h
new file mode 100644
index 0000000..2a1074a
--- /dev/null
+++ b/include/cryptoc/sha224.h
@@ -0,0 +1,42 @@
+// Copyright 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef SECURITY_UTIL_LITE_SHA224_H__
+#define SECURITY_UTIL_LITE_SHA224_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include "cryptoc/hash-internal.h"
+#include "cryptoc/sha256.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
+
+typedef HASH_CTX LITE_SHA224_CTX;
+
+void SHA224_init(LITE_SHA224_CTX* ctx);
+#define SHA224_update(ctx, data, len) SHA256_update((ctx), (data), (len));
+#define SHA224_final(ctx) SHA256_final((ctx))
+
+// Convenience method. Returns digest address.
+const uint8_t* SHA224_hash(const void* data, size_t len, uint8_t* digest);
+
+#define SHA224_DIGEST_SIZE 28
+#define SHA224_BLOCK_SIZE 64
+
+#ifdef __cplusplus
+}
+#endif  // __cplusplus
+
+#endif  // SECURITY_UTIL_LITE_SHA224_H__
diff --git a/include/cryptoc/sha256.h b/include/cryptoc/sha256.h
index 6b86c8e..8797d97 100644
--- a/include/cryptoc/sha256.h
+++ b/include/cryptoc/sha256.h
@@ -32,6 +32,7 @@
 const uint8_t* SHA256_hash(const void* data, size_t len, uint8_t* digest);
 
 #define SHA256_DIGEST_SIZE 32
+#define SHA256_BLOCK_SIZE 64
 
 #ifdef __cplusplus
 }
diff --git a/include/cryptoc/sha384.h b/include/cryptoc/sha384.h
index 3cd848b..29c538d 100644
--- a/include/cryptoc/sha384.h
+++ b/include/cryptoc/sha384.h
@@ -32,6 +32,7 @@
 const uint8_t* SHA384_hash(const void* data, size_t len, uint8_t* digest);
 
 #define SHA384_DIGEST_SIZE 48
+#define SHA384_BLOCK_SIZE 128
 
 #ifdef __cplusplus
 }
diff --git a/include/cryptoc/sha512.h b/include/cryptoc/sha512.h
index e882b3e..d6002c9 100644
--- a/include/cryptoc/sha512.h
+++ b/include/cryptoc/sha512.h
@@ -32,6 +32,7 @@
 const uint8_t* SHA512_hash(const void* data, size_t len, uint8_t* digest);
 
 #define SHA512_DIGEST_SIZE 64
+#define SHA512_BLOCK_SIZE 128
 
 #ifdef __cplusplus
 }
diff --git a/include/cryptoc/util.h b/include/cryptoc/util.h
index 4ba7b21..6c65c45 100644
--- a/include/cryptoc/util.h
+++ b/include/cryptoc/util.h
@@ -15,9 +15,22 @@
 #define SECURITY_UTIL_LITE_UTIL_H_
 
 #include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
 
 /* An implementation of memset that ought not to be optimized away;
  * useful for scrubbing security sensitive buffers. */
 void *always_memset(void *s, int c, size_t n);
 
+/* Constant-time memory equality test. Returns 0 to indicate equivalence to
+ * behave in a memcmp()-compatible way. */
+int ct_memeq(const void* s1, const void* s2, uint32_t n);
+
+#ifdef __cplusplus
+}
+#endif  // __cplusplus
+
 #endif  // SECURITY_UTIL_LITE_UTIL_H_
diff --git a/md5.c b/md5.c
new file mode 100644
index 0000000..ab4af66
--- /dev/null
+++ b/md5.c
@@ -0,0 +1,174 @@
+// Copyright 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "cryptoc/md5.h"
+
+#include <string.h>
+#include <stdint.h>
+
+#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+static const char Kr[64] =
+{
+  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,
+  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
+  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,
+  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21
+};
+
+static const uint32_t KK[64] =
+{
+  0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+  0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+  0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+  0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+  0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+  0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+  0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+  0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+  0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+  0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+  0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+  0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+  0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+  0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+  0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+  0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+};
+
+static void MD5_Transform(LITE_MD5_CTX* ctx) {
+  uint32_t W[64];
+  uint32_t A, B, C, D;
+  uint8_t* p = ctx->buf;
+  int t;
+
+  for(t = 0; t < 16; ++t) {
+    uint32_t tmp =  *p++;
+    tmp |= (uint32_t)*p++ << 8u;
+    tmp |= (uint32_t)*p++ << 16u;
+    tmp |= (uint32_t)*p++ << 24u;
+    W[t] = tmp;
+  }
+
+  A = ctx->state[0];
+  B = ctx->state[1];
+  C = ctx->state[2];
+  D = ctx->state[3];
+
+  for(t = 0; t < 64; t++) {
+    uint32_t f, tmp;
+    int g;
+
+    if (t < 16) {
+      f = (D^(B&(C^D)));
+      g = t;
+    } else if ( t < 32) {
+      f = (C^(D&(B^C)));
+      g = (5*t + 1) & 15;
+    } else if ( t < 48) {
+      f = (B^C^D);
+      g = (3*t + 5) & 15;
+    } else {
+      f = (C^(B|(~D)));
+      g = (7*t) & 15;
+    }
+
+    tmp = D;
+    D = C;
+    C = B;
+    B = B + rol(Kr[t], (A+f+KK[t]+W[g]));
+    A = tmp;
+  }
+
+  ctx->state[0] += A;
+  ctx->state[1] += B;
+  ctx->state[2] += C;
+  ctx->state[3] += D;
+}
+
+static const HASH_VTAB MD5_VTAB = {
+  MD5_init,
+  MD5_update,
+  MD5_final,
+  MD5_hash,
+  MD5_DIGEST_SIZE,
+#ifdef SHA512_SUPPORT
+  MD5_BLOCK_SIZE,
+#endif
+};
+
+void MD5_init(LITE_MD5_CTX* ctx) {
+  ctx->f = &MD5_VTAB;
+  ctx->state[0] = 0x67452301;
+  ctx->state[1] = 0xEFCDAB89;
+  ctx->state[2] = 0x98BADCFE;
+  ctx->state[3] = 0x10325476;
+  ctx->count = 0;
+}
+
+
+void MD5_update(LITE_MD5_CTX* ctx, const void* data, size_t len) {
+  unsigned int i = (unsigned int)(ctx->count & 63);
+  const uint8_t* p = (const uint8_t*)data;
+
+  ctx->count += len;
+
+  while (len--) {
+    ctx->buf[i++] = *p++;
+    if (i == 64) {
+      MD5_Transform(ctx);
+      i = 0;
+    }
+  }
+}
+
+
+const uint8_t* MD5_final(LITE_MD5_CTX* ctx) {
+  uint8_t* p = ctx->buf;
+  uint64_t cnt = ctx->count * 8;
+  int i;
+
+  MD5_update(ctx, (uint8_t*)"\x80", 1);
+  while ((ctx->count & 63) != 56) {
+    MD5_update(ctx, (uint8_t*)"\0", 1);
+  }
+  for (i = 0; i < 4; ++i) {
+    uint8_t tmp = (uint8_t)(((uint32_t)cnt) >> (i * 8));
+    MD5_update(ctx, &tmp, 1);
+  }
+  cnt >>= 32;
+  for (i = 0; i < 4; ++i) {
+    uint8_t tmp = (uint8_t)(((uint32_t)cnt) >> (i * 8));
+    MD5_update(ctx, &tmp, 1);
+  }
+
+  for (i = 0; i < 4; i++) {
+    uint32_t tmp = ctx->state[i];
+    *p++ = tmp;
+    *p++ = tmp >> 8;
+    *p++ = tmp >> 16;
+    *p++ = tmp >> 24;
+  }
+
+  return ctx->buf;
+}
+
+
+/* Convenience function */
+const uint8_t* MD5_hash(const void* data, size_t len, uint8_t* digest) {
+  LITE_MD5_CTX ctx;
+  MD5_init(&ctx);
+  MD5_update(&ctx, data, len);
+  memcpy(digest, MD5_final(&ctx), MD5_DIGEST_SIZE);
+  return digest;
+}
diff --git a/p256.c b/p256.c
index d31c4fc..0fdd35c 100644
--- a/p256.c
+++ b/p256.c
@@ -400,6 +400,34 @@
   return p256_cmp(&y2, &x3) == 0;
 }
 
+void p256_to_bin(const p256_int* src, uint8_t dst[P256_NBYTES]) {
+  int i;
+  uint8_t* p = &dst[0];
+
+  for (i = P256_NDIGITS - 1; i >= 0; --i) {
+    p256_digit digit = P256_DIGIT(src, i);
+    p[0] = (uint8_t)(digit >> 24);
+    p[1] = (uint8_t)(digit >> 16);
+    p[2] = (uint8_t)(digit >> 8);
+    p[3] = (uint8_t)(digit);
+    p += 4;
+  }
+}
+
+void p256_to_le_bin(const p256_int* src, uint8_t dst[P256_NBYTES]) {
+  int i;
+  uint8_t* p = &dst[0];
+
+  for (i = 0; i < P256_NDIGITS; ++i) {
+    p256_digit digit = P256_DIGIT(src, i);
+    p[0] = (uint8_t)(digit);
+    p[1] = (uint8_t)(digit >> 8);
+    p[2] = (uint8_t)(digit >> 16);
+    p[3] = (uint8_t)(digit >> 24);
+    p += 4;
+  }
+}
+
 void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst) {
   int i;
   const uint8_t* p = &src[0];
@@ -414,16 +442,16 @@
   }
 }
 
-void p256_to_bin(const p256_int* src, uint8_t dst[P256_NBYTES]) {
+void p256_from_le_bin(const uint8_t src[P256_NBYTES], p256_int* dst) {
   int i;
-  uint8_t* p = &dst[0];
+  const uint8_t* p = &src[0];
 
-  for (i = P256_NDIGITS - 1; i >= 0; --i) {
-    p256_digit digit = P256_DIGIT(src, i);
-    p[0] = (uint8_t)(digit >> 24);
-    p[1] = (uint8_t)(digit >> 16);
-    p[2] = (uint8_t)(digit >> 8);
-    p[3] = (uint8_t)(digit);
+  for (i = 0; i < P256_NDIGITS; ++i) {
+    P256_DIGIT(dst, i) =
+        (uint32_t)p[0] |
+        ((uint32_t)p[1] << 8) |
+        ((uint32_t)p[2] << 16) |
+        ((uint32_t)p[3] << 24);
     p += 4;
   }
 }
diff --git a/p256_unittest.c b/p256_unittest.c
index 03954eb..fb0b87a 100644
--- a/p256_unittest.c
+++ b/p256_unittest.c
@@ -14,6 +14,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "cryptoc/p256.h"
 
@@ -139,11 +140,43 @@
   CHECK(p256_is_valid_point(&x, &y) == 1);
 }
 
+void test_bin() {
+  p256_int a = {{1}};
+  p256_int b;
+  uint8_t a_bytes_be[P256_NBYTES];
+  uint8_t a_bytes_le[P256_NBYTES];
+  int i;
+
+  p256_to_bin(&a, a_bytes_be);
+  p256_to_le_bin(&a, a_bytes_le);
+
+  // Check big-endian serialization.
+  for (i = 0; i < P256_NBYTES - 1; ++i) {
+    CHECK(a_bytes_be[i] == 0);
+  }
+  CHECK(a_bytes_be[P256_NBYTES - 1] == 1);
+
+  // Check little-endian serialization.
+  CHECK(a_bytes_le[0] == 1);
+  for (i = 1; i < P256_NBYTES; ++i) {
+    CHECK(a_bytes_le[i] == 0);
+  }
+
+  // Check big-endian parsing.
+  p256_from_bin(a_bytes_be, &b);
+  CHECK(memcmp(&a, &b, sizeof(a)) == 0);
+
+  // Check little-endian parsing.
+  p256_from_le_bin(a_bytes_le, &b);
+  CHECK(memcmp(&a, &b, sizeof(a)) == 0);
+}
+
 int main(int argc, char* argv[]) {
   test_cpu_behavior();
   test_shifts();
   test_add_sub_cmp();
   test_mul_inv();
   test_valid_point();
+  test_bin();
   return 0;
 }
diff --git a/sha.c b/sha.c
index b0cd8f3..39fa8c9 100644
--- a/sha.c
+++ b/sha.c
@@ -25,10 +25,10 @@
   int t;
 
   for(t = 0; t < 16; ++t) {
-    uint32_t tmp =  *p++ << 24;
-    tmp |= *p++ << 16;
-    tmp |= *p++ << 8;
-    tmp |= *p++;
+    uint32_t tmp = (uint32_t)(*p++) << 24;
+    tmp |= (uint32_t)(*p++) << 16;
+    tmp |= (uint32_t)(*p++) << 8;
+    tmp |= (uint32_t)(*p++);
     W[t] = tmp;
   }
 
@@ -73,7 +73,10 @@
   SHA_update,
   SHA_final,
   SHA_hash,
-  SHA_DIGEST_SIZE
+  SHA_DIGEST_SIZE,
+#ifdef SHA512_SUPPORT
+  SHA_BLOCK_SIZE,
+#endif
 };
 
 void SHA_init(SHA_CTX* ctx) {
@@ -105,7 +108,7 @@
 
 const uint8_t* SHA_final(SHA_CTX* ctx) {
   uint8_t *p = ctx->buf;
-  uint64_t cnt = ctx->count * 8;
+  uint64_t cnt = LITE_LShiftU64(ctx->count, 3);
   int i;
 
   SHA_update(ctx, (uint8_t*)"\x80", 1);
@@ -113,8 +116,8 @@
     SHA_update(ctx, (uint8_t*)"\0", 1);
   }
   for (i = 0; i < 8; ++i) {
-    uint8_t tmp = (uint8_t) (cnt >> 56);
-    cnt <<= 8;
+    uint8_t tmp = (uint8_t) LITE_RShiftU64(cnt, 56);
+    cnt = LITE_LShiftU64(cnt, 8);
     SHA_update(ctx, &tmp, 1);
   }
 
diff --git a/sha224.c b/sha224.c
new file mode 100644
index 0000000..bb4dca1
--- /dev/null
+++ b/sha224.c
@@ -0,0 +1,52 @@
+// Copyright 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "cryptoc/sha224.h"
+#include "cryptoc/sha256.h"
+
+#include <string.h>
+#include <stdint.h>
+
+static const HASH_VTAB SHA224_VTAB = {
+  SHA224_init,
+  SHA256_update,
+  SHA256_final,
+  SHA224_hash,
+  SHA224_DIGEST_SIZE,
+#ifdef SHA512_SUPPORT
+  SHA224_BLOCK_SIZE,
+#endif
+};
+
+void SHA224_init(LITE_SHA224_CTX* ctx) {
+  ctx->f = &SHA224_VTAB;
+  ctx->state[0] = 0xc1059ed8;
+  ctx->state[1] = 0x367cd507;
+  ctx->state[2] = 0x3070dd17;
+  ctx->state[3] = 0xf70e5939;
+  ctx->state[4] = 0xffc00b31;
+  ctx->state[5] = 0x68581511;
+  ctx->state[6] = 0x64f98fa7;
+  ctx->state[7] = 0xbefa4fa4;
+  ctx->count = 0;
+}
+
+/* Convenience function */
+const uint8_t* SHA224_hash(const void* data, size_t len,
+                           uint8_t* digest) {
+  LITE_SHA224_CTX ctx;
+  SHA224_init(&ctx);
+  SHA224_update(&ctx, data, len);
+  memcpy(digest, SHA224_final(&ctx), SHA224_DIGEST_SIZE);
+  return digest;
+}
diff --git a/sha256.c b/sha256.c
index ae074ac..44263a4 100644
--- a/sha256.c
+++ b/sha256.c
@@ -44,10 +44,10 @@
   int t;
 
   for(t = 0; t < 16; ++t) {
-    uint32_t tmp =  *p++ << 24;
-    tmp |= *p++ << 16;
-    tmp |= *p++ << 8;
-    tmp |= *p++;
+    uint32_t tmp =  (uint32_t)*p++ << 24;
+    tmp |= (uint32_t)*p++ << 16;
+    tmp |= (uint32_t)*p++ << 8;
+    tmp |= (uint32_t)*p++;
     W[t] = tmp;
   }
 
@@ -99,7 +99,10 @@
   SHA256_update,
   SHA256_final,
   SHA256_hash,
-  SHA256_DIGEST_SIZE
+  SHA256_DIGEST_SIZE,
+#ifdef SHA512_SUPPORT
+  SHA256_BLOCK_SIZE,
+#endif
 };
 
 void SHA256_init(LITE_SHA256_CTX* ctx) {
@@ -134,7 +137,7 @@
 
 const uint8_t* SHA256_final(LITE_SHA256_CTX* ctx) {
   uint8_t *p = ctx->buf;
-  uint64_t cnt = ctx->count * 8;
+  uint64_t cnt = LITE_LShiftU64(ctx->count, 3);
   int i;
 
   SHA256_update(ctx, (uint8_t*)"\x80", 1);
@@ -142,8 +145,8 @@
     SHA256_update(ctx, (uint8_t*)"\0", 1);
   }
   for (i = 0; i < 8; ++i) {
-    uint8_t tmp = (uint8_t) (cnt >> 56);
-    cnt <<= 8;
+    uint8_t tmp = (uint8_t)LITE_RShiftU64(cnt, 56);
+    cnt = LITE_LShiftU64(cnt, 8);
     SHA256_update(ctx, &tmp, 1);
   }
 
diff --git a/sha384.c b/sha384.c
index 3ce72d0..1485aad 100644
--- a/sha384.c
+++ b/sha384.c
@@ -27,7 +27,8 @@
   SHA512_update,
   SHA512_final,
   SHA384_hash,
-  SHA384_DIGEST_SIZE
+  SHA384_DIGEST_SIZE,
+  SHA384_BLOCK_SIZE
 };
 
 void SHA384_init(LITE_SHA384_CTX* ctx) {
diff --git a/sha512.c b/sha512.c
index eabff01..105d76c 100644
--- a/sha512.c
+++ b/sha512.c
@@ -125,7 +125,8 @@
   SHA512_update,
   SHA512_final,
   SHA512_hash,
-  SHA512_DIGEST_SIZE
+  SHA512_DIGEST_SIZE,
+  SHA512_BLOCK_SIZE
 };
 
 void SHA512_init(LITE_SHA512_CTX* ctx) {
diff --git a/util.c b/util.c
index 6f40509..c027715 100644
--- a/util.c
+++ b/util.c
@@ -19,6 +19,22 @@
 }
 
 void *always_memset(void *s, int c, size_t n) {
-  always_memset_impl(s, c, n);
+  always_memset_impl((char*) s, c, n);
   return s;
 }
+
+int ct_memeq(const void* s1, const void* s2, uint32_t n) {
+  uint8_t diff = 0;
+  const uint8_t* ps1 = s1;
+  const uint8_t* ps2 = s2;
+
+  while (n--) {
+    diff |= *ps1 ^ *ps2;
+    ps1++;
+    ps2++;
+  }
+
+  // Counter-intuitive, but we can't just return diff because we don't want to
+  // leak the xor of non-equal bytes
+  return 0 != diff;
+}