mincrypt: support SHA-256 hash algorithm

- adds a library to compute the SHA-256 hash

- updates the RSA verifier to take an argument specifying either SHA-1
  or SHA-256

- updates DumpPublicKey to with new "key" version numbers for
  specifying SHA-256

- adds new argument to adb auth code to maintain existing behavior

Change-Id: I5b1406cf57c2b8993f6032eda3e29139f7740839
diff --git a/Android.mk b/Android.mk
index f58eab9..addbed8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -4,13 +4,13 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := libmincrypt
-LOCAL_SRC_FILES := rsa.c rsa_e_3.c rsa_e_f4.c sha.c
+LOCAL_SRC_FILES := rsa.c rsa_e_3.c rsa_e_f4.c sha.c sha256.c
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := libmincrypt
-LOCAL_SRC_FILES := rsa.c rsa_e_3.c rsa_e_f4.c sha.c
+LOCAL_SRC_FILES := rsa.c rsa_e_3.c rsa_e_f4.c sha.c sha256.c
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 
diff --git a/include/mincrypt/hash-internal.h b/include/mincrypt/hash-internal.h
new file mode 100644
index 0000000..96806f7
--- /dev/null
+++ b/include/mincrypt/hash-internal.h
@@ -0,0 +1,40 @@
+// Copyright 2007 Google Inc. All Rights Reserved.
+// Author: mschilder@google.com (Marius Schilder)
+
+#ifndef SECURITY_UTIL_LITE_HASH_INTERNAL_H__
+#define SECURITY_UTIL_LITE_HASH_INTERNAL_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
+
+struct HASH_CTX;  // forward decl
+
+typedef struct HASH_VTAB {
+  void (* const init)(struct HASH_CTX*);
+  void (* const update)(struct HASH_CTX*, const void*, int);
+  const uint8_t* (* const final)(struct HASH_CTX*);
+  const uint8_t* (* const hash)(const void*, int, uint8_t*);
+  int size;
+} HASH_VTAB;
+
+typedef struct HASH_CTX {
+  const HASH_VTAB * f;
+  uint64_t count;
+  uint8_t buf[64];
+  uint32_t state[8];  // upto SHA2
+} HASH_CTX;
+
+#define HASH_init(ctx) (ctx)->f->init(ctx)
+#define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len)
+#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 __cplusplus
+}
+#endif  // __cplusplus
+
+#endif  // SECURITY_UTIL_LITE_HASH_INTERNAL_H__
diff --git a/include/mincrypt/rsa.h b/include/mincrypt/rsa.h
index d7429fc..cc0e800 100644
--- a/include/mincrypt/rsa.h
+++ b/include/mincrypt/rsa.h
@@ -48,7 +48,8 @@
 int RSA_verify(const RSAPublicKey *key,
                const uint8_t* signature,
                const int len,
-               const uint8_t* sha);
+               const uint8_t* hash,
+               const int hash_len);
 
 #ifdef __cplusplus
 }
diff --git a/include/mincrypt/sha.h b/include/mincrypt/sha.h
index af63e87..120ddcb 100644
--- a/include/mincrypt/sha.h
+++ b/include/mincrypt/sha.h
@@ -1,63 +1,30 @@
-/* sha.h
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are met:
-**     * Redistributions of source code must retain the above copyright
-**       notice, this list of conditions and the following disclaimer.
-**     * Redistributions in binary form must reproduce the above copyright
-**       notice, this list of conditions and the following disclaimer in the
-**       documentation and/or other materials provided with the distribution.
-**     * Neither the name of Google Inc. nor the names of its contributors may
-**       be used to endorse or promote products derived from this software
-**       without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
-** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+// Copyright 2005 Google Inc. All Rights Reserved.
+// Author: mschilder@google.com (Marius Schilder)
 
-#ifndef _EMBEDDED_SHA_H_
-#define _EMBEDDED_SHA_H_
+#ifndef SECURITY_UTIL_LITE_SHA1_H__
+#define SECURITY_UTIL_LITE_SHA1_H__
 
-#include <inttypes.h>
+#include <stdint.h>
+#include "hash-internal.h"
 
 #ifdef __cplusplus
 extern "C" {
-#endif
+#endif // __cplusplus
 
-typedef struct SHA_CTX {
-    uint64_t count;
-    uint32_t state[5];
-#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
-    union {
-        uint8_t b[64];
-        uint32_t w[16];
-    } buf;
-#else
-    uint8_t buf[64];
-#endif
-} SHA_CTX;
+typedef HASH_CTX SHA_CTX;
 
 void SHA_init(SHA_CTX* ctx);
 void SHA_update(SHA_CTX* ctx, const void* data, int len);
 const uint8_t* SHA_final(SHA_CTX* ctx);
 
-/* Convenience method. Returns digest parameter value. */
-const uint8_t* SHA(const void* data, int len, uint8_t* digest);
+// Convenience method. Returns digest address.
+// NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes.
+const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest);
 
 #define SHA_DIGEST_SIZE 20
 
 #ifdef __cplusplus
 }
-#endif
+#endif // __cplusplus
 
-#endif
+#endif  // SECURITY_UTIL_LITE_SHA1_H__
diff --git a/include/mincrypt/sha256.h b/include/mincrypt/sha256.h
new file mode 100644
index 0000000..0f3efb7
--- /dev/null
+++ b/include/mincrypt/sha256.h
@@ -0,0 +1,29 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: mschilder@google.com (Marius Schilder)
+
+#ifndef SECURITY_UTIL_LITE_SHA256_H__
+#define SECURITY_UTIL_LITE_SHA256_H__
+
+#include <stdint.h>
+#include "hash-internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+typedef HASH_CTX SHA256_CTX;
+
+void SHA256_init(SHA256_CTX* ctx);
+void SHA256_update(SHA256_CTX* ctx, const void* data, int len);
+const uint8_t* SHA256_final(SHA256_CTX* ctx);
+
+// Convenience method. Returns digest address.
+const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest);
+
+#define SHA256_DIGEST_SIZE 32
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif  // SECURITY_UTIL_LITE_SHA256_H__
diff --git a/rsa.c b/rsa.c
index b4ee6af..0cdbaa2 100644
--- a/rsa.c
+++ b/rsa.c
@@ -30,23 +30,26 @@
 int RSA_e_f4_verify(const RSAPublicKey* key,
                     const uint8_t* signature,
                     const int len,
-                    const uint8_t* sha);
+                    const uint8_t* hash,
+                    const int hash_len);
 
 int RSA_e_3_verify(const RSAPublicKey *key,
                    const uint8_t *signature,
                    const int len,
-                   const uint8_t *sha);
+                   const uint8_t *hash,
+                   const int hash_len);
 
 int RSA_verify(const RSAPublicKey *key,
                const uint8_t *signature,
                const int len,
-               const uint8_t *sha) {
+               const uint8_t *hash,
+               const int hash_len) {
     switch (key->exponent) {
         case 3:
-            return RSA_e_3_verify(key, signature, len, sha);
+            return RSA_e_3_verify(key, signature, len, hash, hash_len);
             break;
         case 65537:
-            return RSA_e_f4_verify(key, signature, len, sha);
+            return RSA_e_f4_verify(key, signature, len, hash, hash_len);
             break;
         default:
             return 0;
diff --git a/rsa_e_3.c b/rsa_e_3.c
index c8c02c4..012a357 100644
--- a/rsa_e_3.c
+++ b/rsa_e_3.c
@@ -27,6 +27,7 @@
 
 #include "mincrypt/rsa.h"
 #include "mincrypt/sha.h"
+#include "mincrypt/sha256.h"
 
 /* a[] -= mod */
 static void subM(const RSAPublicKey *key, uint32_t *a) {
@@ -134,7 +135,7 @@
 ** other flavor which omits the optional parameter entirely). This code does not
 ** accept signatures without the optional parameter.
 */
-static const uint8_t padding[RSANUMBYTES - SHA_DIGEST_SIZE] = {
+static const uint8_t sha_padding[RSANUMBYTES - SHA_DIGEST_SIZE] = {
     0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
     0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
@@ -156,15 +157,56 @@
     0x04,0x14
 };
 
+static const uint8_t sha256_padding[RSANUMBYTES - SHA256_DIGEST_SIZE] = {
+    0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x31,0x30,
+    0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,
+    0x00,0x04,0x20
+};
+
+
 /* Verify a 2048 bit RSA e=3 PKCS1.5 signature against an expected SHA-1 hash.
 ** Returns 0 on failure, 1 on success.
 */
 int RSA_e_3_verify(const RSAPublicKey *key,
                    const uint8_t *signature,
                    const int len,
-                   const uint8_t *sha) {
+                   const uint8_t *hash,
+                   const int hash_len) {
     uint8_t buf[RSANUMBYTES];
     int i;
+    int padding_size;
+    const uint8_t* padding;
+
+    switch (hash_len) {
+        case SHA_DIGEST_SIZE:
+            padding = sha_padding;
+            padding_size = sizeof(sha_padding);
+            break;
+        case SHA256_DIGEST_SIZE:
+            padding = sha256_padding;
+            padding_size = sizeof(sha256_padding);
+            break;
+        default:
+            return 0;  // unsupported hash
+    }
 
     if (key->len != RSANUMWORDS) {
         return 0;  /* Wrong key passed in. */
@@ -185,7 +227,7 @@
     modpow3(key, buf);
 
     /* Check pkcs1.5 padding bytes. */
-    for (i = 0; i < (int) sizeof(padding); ++i) {
+    for (i = 0; i < padding_size; ++i) {
         if (buf[i] != padding[i]) {
             return 0;
         }
@@ -193,7 +235,7 @@
 
     /* Check sha digest matches. */
     for (; i < len; ++i) {
-        if (buf[i] != *sha++) {
+        if (buf[i] != *hash++) {
             return 0;
         }
     }
diff --git a/rsa_e_f4.c b/rsa_e_f4.c
index 6701bcc..17a2de2 100644
--- a/rsa_e_f4.c
+++ b/rsa_e_f4.c
@@ -27,6 +27,7 @@
 
 #include "mincrypt/rsa.h"
 #include "mincrypt/sha.h"
+#include "mincrypt/sha256.h"
 
 // a[] -= mod
 static void subM(const RSAPublicKey* key,
@@ -138,26 +139,79 @@
 // other flavor which omits the optional parameter entirely). This code does not
 // accept signatures without the optional parameter.
 /*
-static const uint8_t padding[RSANUMBYTES] = {
+static const uint8_t sha_padding[RSANUMBYTES] = {
 0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 };
+
+static const uint8_t sha256_padding[RSANUMBYTES] = {
+    0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x30,0x31,0x30,
+    0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,
+    0x00,0x04,0x20,
+
+    // 32 bytes of hash go here.
+    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,
+};
+
 */
 
-// SHA-1 of PKCS1.5 signature padding for 2048 bit, as above.
+// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above.
 // At the location of the bytes of the hash all 00 are hashed.
 static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
   0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e, 0x6e, 0xfc,
   0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68, 0x7c, 0xfb, 0xf1, 0x67
 };
 
+// SHA-256 of PKCS1.5 signature sha256_padding for 2048 bit, as above.
+// At the location of the bytes of the hash all 00 are hashed.
+static const uint8_t kExpectedPadSha256Rsa2048[SHA256_DIGEST_SIZE] = {
+  0xab, 0x28, 0x8d, 0x8a, 0xd7, 0xd9, 0x59, 0x92,
+  0xba, 0xcc, 0xf8, 0x67, 0x20, 0xe1, 0x15, 0x2e,
+  0x39, 0x8d, 0x80, 0x36, 0xd6, 0x6f, 0xf0, 0xfd,
+  0x90, 0xe8, 0x7d, 0x8b, 0xe1, 0x7c, 0x87, 0x59,
+};
+
 // Verify a 2048 bit RSA e=65537 PKCS1.5 signature against an expected
 // SHA-1 hash.  Returns 0 on failure, 1 on success.
 int RSA_e_f4_verify(const RSAPublicKey* key,
                     const uint8_t* signature,
                     const int len,
-                    const uint8_t* sha) {
+                    const uint8_t* hash,
+                    const int hash_len) {
   uint8_t buf[RSANUMBYTES];
   int i;
+  const uint8_t* padding_hash;
+
+  switch (hash_len) {
+    case SHA_DIGEST_SIZE:
+      padding_hash = kExpectedPadShaRsa2048;
+      break;
+    case SHA256_DIGEST_SIZE:
+      padding_hash = kExpectedPadSha256Rsa2048;
+      break;
+    default:
+      return 0;  // unsupported hash
+  }
 
   if (key->len != RSANUMWORDS) {
     return 0;  // Wrong key passed in.
@@ -178,16 +232,25 @@
   modpowF4(key, buf);  // In-place exponentiation.
 
   // Xor sha portion, so it all becomes 00 iff equal.
-  for (i = len - SHA_DIGEST_SIZE; i < len; ++i) {
-    buf[i] ^= *sha++;
+  for (i = len - hash_len; i < len; ++i) {
+    buf[i] ^= *hash++;
   }
 
   // Hash resulting buf, in-place.
-  SHA(buf, len, buf);
+  switch (hash_len) {
+      case SHA_DIGEST_SIZE:
+          SHA_hash(buf, len, buf);
+          break;
+      case SHA256_DIGEST_SIZE:
+          SHA256_hash(buf, len, buf);
+          break;
+      default:
+          return 0;
+  }
 
   // Compare against expected hash value.
-  for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
-    if (buf[i] != kExpectedPadShaRsa2048[i]) {
+  for (i = 0; i < hash_len; ++i) {
+    if (buf[i] != padding_hash[i]) {
       return 0;
     }
   }
diff --git a/sha.c b/sha.c
index e089d79..5bef32e 100644
--- a/sha.c
+++ b/sha.c
@@ -1,6 +1,6 @@
 /* sha.c
 **
-** Copyright 2008, The Android Open Source Project
+** Copyright 2013, The Android Open Source Project
 **
 ** Redistribution and use in source and binary forms, with or without
 ** modification, are permitted provided that the following conditions are met:
@@ -25,177 +25,20 @@
 ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+// Optimized for minimal code size.
+
 #include "mincrypt/sha.h"
 
-// Some machines lack byteswap.h and endian.h.  These have to use the
-// slower code, even if they're little-endian.
-
-#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
-
-#include <byteswap.h>
-#include <memory.h>
-
-// This version is about 28% faster than the generic version below,
-// but assumes little-endianness.
-
-static inline uint32_t ror27(uint32_t val) {
-    return (val >> 27) | (val << 5);
-}
-static inline uint32_t ror2(uint32_t val) {
-    return (val >> 2) | (val << 30);
-}
-static inline uint32_t ror31(uint32_t val) {
-    return (val >> 31) | (val << 1);
-}
-
-static void SHA1_Transform(SHA_CTX* ctx) {
-    uint32_t W[80];
-    register uint32_t A, B, C, D, E;
-    int t;
-
-    A = ctx->state[0];
-    B = ctx->state[1];
-    C = ctx->state[2];
-    D = ctx->state[3];
-    E = ctx->state[4];
-
-#define SHA_F1(A,B,C,D,E,t)                     \
-    E += ror27(A) +                             \
-        (W[t] = bswap_32(ctx->buf.w[t])) +      \
-        (D^(B&(C^D))) + 0x5A827999;             \
-    B = ror2(B);
-
-    for (t = 0; t < 15; t += 5) {
-        SHA_F1(A,B,C,D,E,t + 0);
-        SHA_F1(E,A,B,C,D,t + 1);
-        SHA_F1(D,E,A,B,C,t + 2);
-        SHA_F1(C,D,E,A,B,t + 3);
-        SHA_F1(B,C,D,E,A,t + 4);
-    }
-    SHA_F1(A,B,C,D,E,t + 0);  // 16th one, t == 15
-
-#undef SHA_F1
-
-#define SHA_F1(A,B,C,D,E,t)                                     \
-    E += ror27(A) +                                             \
-        (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
-        (D^(B&(C^D))) + 0x5A827999;                             \
-    B = ror2(B);
-
-    SHA_F1(E,A,B,C,D,t + 1);
-    SHA_F1(D,E,A,B,C,t + 2);
-    SHA_F1(C,D,E,A,B,t + 3);
-    SHA_F1(B,C,D,E,A,t + 4);
-
-#undef SHA_F1
-
-#define SHA_F2(A,B,C,D,E,t)                                     \
-    E += ror27(A) +                                             \
-        (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
-        (B^C^D) + 0x6ED9EBA1;                                   \
-    B = ror2(B);
-
-    for (t = 20; t < 40; t += 5) {
-        SHA_F2(A,B,C,D,E,t + 0);
-        SHA_F2(E,A,B,C,D,t + 1);
-        SHA_F2(D,E,A,B,C,t + 2);
-        SHA_F2(C,D,E,A,B,t + 3);
-        SHA_F2(B,C,D,E,A,t + 4);
-    }
-
-#undef SHA_F2
-
-#define SHA_F3(A,B,C,D,E,t)                                     \
-    E += ror27(A) +                                             \
-        (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
-        ((B&C)|(D&(B|C))) + 0x8F1BBCDC;                         \
-    B = ror2(B);
-
-    for (; t < 60; t += 5) {
-        SHA_F3(A,B,C,D,E,t + 0);
-        SHA_F3(E,A,B,C,D,t + 1);
-        SHA_F3(D,E,A,B,C,t + 2);
-        SHA_F3(C,D,E,A,B,t + 3);
-        SHA_F3(B,C,D,E,A,t + 4);
-    }
-
-#undef SHA_F3
-
-#define SHA_F4(A,B,C,D,E,t)                                     \
-    E += ror27(A) +                                             \
-        (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
-        (B^C^D) + 0xCA62C1D6;                                   \
-    B = ror2(B);
-
-    for (; t < 80; t += 5) {
-        SHA_F4(A,B,C,D,E,t + 0);
-        SHA_F4(E,A,B,C,D,t + 1);
-        SHA_F4(D,E,A,B,C,t + 2);
-        SHA_F4(C,D,E,A,B,t + 3);
-        SHA_F4(B,C,D,E,A,t + 4);
-    }
-
-#undef SHA_F4
-
-    ctx->state[0] += A;
-    ctx->state[1] += B;
-    ctx->state[2] += C;
-    ctx->state[3] += D;
-    ctx->state[4] += E;
-}
-
-void SHA_update(SHA_CTX* ctx, const void* data, int len) {
-    int i = ctx->count % sizeof(ctx->buf);
-    const uint8_t* p = (const uint8_t*)data;
-
-    ctx->count += len;
-
-    while (len > sizeof(ctx->buf) - i) {
-        memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i);
-        len -= sizeof(ctx->buf) - i;
-        p += sizeof(ctx->buf) - i;
-        SHA1_Transform(ctx);
-        i = 0;
-    }
-
-    while (len--) {
-        ctx->buf.b[i++] = *p++;
-        if (i == sizeof(ctx->buf)) {
-            SHA1_Transform(ctx);
-            i = 0;
-        }
-    }
-}
-
-
-const uint8_t* SHA_final(SHA_CTX* ctx) {
-    uint64_t cnt = ctx->count * 8;
-    int i;
-
-    SHA_update(ctx, (uint8_t*)"\x80", 1);
-    while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
-        SHA_update(ctx, (uint8_t*)"\0", 1);
-    }
-    for (i = 0; i < 8; ++i) {
-        uint8_t tmp = cnt >> ((7 - i) * 8);
-        SHA_update(ctx, &tmp, 1);
-    }
-
-    for (i = 0; i < 5; i++) {
-        ctx->buf.w[i] = bswap_32(ctx->state[i]);
-    }
-
-    return ctx->buf.b;
-}
-
-#else   // #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
 
 #define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
 
-static void SHA1_transform(SHA_CTX *ctx) {
+static void SHA1_Transform(SHA_CTX* ctx) {
     uint32_t W[80];
     uint32_t A, B, C, D, E;
-    uint8_t *p = ctx->buf;
+    uint8_t* p = ctx->buf;
     int t;
 
     for(t = 0; t < 16; ++t) {
@@ -242,31 +85,52 @@
     ctx->state[4] += E;
 }
 
-void SHA_update(SHA_CTX *ctx, const void *data, int len) {
-    int i = ctx->count % sizeof(ctx->buf);
+static const HASH_VTAB SHA_VTAB = {
+    SHA_init,
+    SHA_update,
+    SHA_final,
+    SHA_hash,
+    SHA_DIGEST_SIZE
+};
+
+void SHA_init(SHA_CTX* ctx) {
+    ctx->f = &SHA_VTAB;
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+    ctx->state[4] = 0xC3D2E1F0;
+    ctx->count = 0;
+}
+
+
+void SHA_update(SHA_CTX* ctx, const void* data, int len) {
+    int i = (int) (ctx->count & 63);
     const uint8_t* p = (const uint8_t*)data;
 
     ctx->count += len;
 
     while (len--) {
         ctx->buf[i++] = *p++;
-        if (i == sizeof(ctx->buf)) {
-            SHA1_transform(ctx);
+        if (i == 64) {
+            SHA1_Transform(ctx);
             i = 0;
         }
     }
 }
-const uint8_t *SHA_final(SHA_CTX *ctx) {
+
+
+const uint8_t* SHA_final(SHA_CTX* ctx) {
     uint8_t *p = ctx->buf;
     uint64_t cnt = ctx->count * 8;
     int i;
 
     SHA_update(ctx, (uint8_t*)"\x80", 1);
-    while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
+    while ((ctx->count & 63) != 56) {
         SHA_update(ctx, (uint8_t*)"\0", 1);
     }
     for (i = 0; i < 8; ++i) {
-        uint8_t tmp = cnt >> ((7 - i) * 8);
+        uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
         SHA_update(ctx, &tmp, 1);
     }
 
@@ -281,27 +145,11 @@
     return ctx->buf;
 }
 
-#endif // endianness
-
-void SHA_init(SHA_CTX* ctx) {
-    ctx->state[0] = 0x67452301;
-    ctx->state[1] = 0xEFCDAB89;
-    ctx->state[2] = 0x98BADCFE;
-    ctx->state[3] = 0x10325476;
-    ctx->state[4] = 0xC3D2E1F0;
-    ctx->count = 0;
-}
-
 /* Convenience function */
-const uint8_t* SHA(const void *data, int len, uint8_t *digest) {
-    const uint8_t *p;
-    int i;
+const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) {
     SHA_CTX ctx;
     SHA_init(&ctx);
     SHA_update(&ctx, data, len);
-    p = SHA_final(&ctx);
-    for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
-        digest[i] = *p++;
-    }
+    memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE);
     return digest;
 }
diff --git a/sha256.c b/sha256.c
new file mode 100644
index 0000000..eb6e308
--- /dev/null
+++ b/sha256.c
@@ -0,0 +1,184 @@
+/* sha256.c
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**     * Redistributions of source code must retain the above copyright
+**       notice, this list of conditions and the following disclaimer.
+**     * Redistributions in binary form must reproduce the above copyright
+**       notice, this list of conditions and the following disclaimer in the
+**       documentation and/or other materials provided with the distribution.
+**     * Neither the name of Google Inc. nor the names of its contributors may
+**       be used to endorse or promote products derived from this software
+**       without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Optimized for minimal code size.
+
+#include "mincrypt/sha256.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
+#define shr(value, bits) ((value) >> (bits))
+
+static const uint32_t K[64] = {
+    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
+
+static void SHA256_Transform(SHA256_CTX* ctx) {
+    uint32_t W[64];
+    uint32_t A, B, C, D, E, F, G, H;
+    uint8_t* p = ctx->buf;
+    int t;
+
+    for(t = 0; t < 16; ++t) {
+        uint32_t tmp =  *p++ << 24;
+        tmp |= *p++ << 16;
+        tmp |= *p++ << 8;
+        tmp |= *p++;
+        W[t] = tmp;
+    }
+
+    for(; t < 64; t++) {
+        uint32_t s0 = ror(W[t-15], 7) ^ ror(W[t-15], 18) ^ shr(W[t-15], 3);
+        uint32_t s1 = ror(W[t-2], 17) ^ ror(W[t-2], 19) ^ shr(W[t-2], 10);
+        W[t] = W[t-16] + s0 + W[t-7] + s1;
+    }
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+    F = ctx->state[5];
+    G = ctx->state[6];
+    H = ctx->state[7];
+
+    for(t = 0; t < 64; t++) {
+        uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22);
+        uint32_t maj = (A & B) ^ (A & C) ^ (B & C);
+        uint32_t t2 = s0 + maj;
+        uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25);
+        uint32_t ch = (E & F) ^ ((~E) & G);
+        uint32_t t1 = H + s1 + ch + K[t] + W[t];
+
+        H = G;
+        G = F;
+        F = E;
+        E = D + t1;
+        D = C;
+        C = B;
+        B = A;
+        A = t1 + t2;
+    }
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+    ctx->state[5] += F;
+    ctx->state[6] += G;
+    ctx->state[7] += H;
+}
+
+static const HASH_VTAB SHA256_VTAB = {
+    SHA256_init,
+    SHA256_update,
+    SHA256_final,
+    SHA256_hash,
+    SHA256_DIGEST_SIZE
+};
+
+void SHA256_init(SHA256_CTX* ctx) {
+    ctx->f = &SHA256_VTAB;
+    ctx->state[0] = 0x6a09e667;
+    ctx->state[1] = 0xbb67ae85;
+    ctx->state[2] = 0x3c6ef372;
+    ctx->state[3] = 0xa54ff53a;
+    ctx->state[4] = 0x510e527f;
+    ctx->state[5] = 0x9b05688c;
+    ctx->state[6] = 0x1f83d9ab;
+    ctx->state[7] = 0x5be0cd19;
+    ctx->count = 0;
+}
+
+
+void SHA256_update(SHA256_CTX* ctx, const void* data, int len) {
+    int i = (int) (ctx->count & 63);
+    const uint8_t* p = (const uint8_t*)data;
+
+    ctx->count += len;
+
+    while (len--) {
+        ctx->buf[i++] = *p++;
+        if (i == 64) {
+            SHA256_Transform(ctx);
+            i = 0;
+        }
+    }
+}
+
+
+const uint8_t* SHA256_final(SHA256_CTX* ctx) {
+    uint8_t *p = ctx->buf;
+    uint64_t cnt = ctx->count * 8;
+    int i;
+
+    SHA256_update(ctx, (uint8_t*)"\x80", 1);
+    while ((ctx->count & 63) != 56) {
+        SHA256_update(ctx, (uint8_t*)"\0", 1);
+    }
+    for (i = 0; i < 8; ++i) {
+        uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
+        SHA256_update(ctx, &tmp, 1);
+    }
+
+    for (i = 0; i < 8; i++) {
+        uint32_t tmp = ctx->state[i];
+        *p++ = tmp >> 24;
+        *p++ = tmp >> 16;
+        *p++ = tmp >> 8;
+        *p++ = tmp >> 0;
+    }
+
+    return ctx->buf;
+}
+
+/* Convenience function */
+const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest) {
+    SHA256_CTX ctx;
+    SHA256_init(&ctx);
+    SHA256_update(&ctx, data, len);
+    memcpy(digest, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
+    return digest;
+}
diff --git a/tools/DumpPublicKey.java b/tools/DumpPublicKey.java
index 12b4f56..7189116 100644
--- a/tools/DumpPublicKey.java
+++ b/tools/DumpPublicKey.java
@@ -19,7 +19,7 @@
 import java.io.FileInputStream;
 import java.math.BigInteger;
 import java.security.cert.CertificateFactory;
-import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
 import java.security.KeyStore;
 import java.security.Key;
 import java.security.PublicKey;
@@ -34,20 +34,22 @@
     /**
      * @param key to perform sanity checks on
      * @return version number of key.  Supported versions are:
-     *     1: 2048-bit key with e=3
-     *     2: 2048-bit key with e=65537
+     *     1: 2048-bit RSA key with e=3 and SHA-1 hash
+     *     2: 2048-bit RSA key with e=65537 and SHA-1 hash
+     *     3: 2048-bit RSA key with e=3 and SHA-256 hash
+     *     4: 2048-bit RSA key with e=65537 and SHA-256 hash
      * @throws Exception if the key has the wrong size or public exponent
 
      */
-    static int check(RSAPublicKey key) throws Exception {
+    static int check(RSAPublicKey key, boolean useSHA256) throws Exception {
         BigInteger pubexp = key.getPublicExponent();
         BigInteger modulus = key.getModulus();
         int version;
 
         if (pubexp.equals(BigInteger.valueOf(3))) {
-            version = 1;
+            version = useSHA256 ? 3 : 1;
         } else if (pubexp.equals(BigInteger.valueOf(65537))) {
-            version = 2;
+            version = useSHA256 ? 4 : 2;
         } else {
             throw new Exception("Public exponent should be 3 or 65537 but is " +
                                 pubexp.toString(10) + ".");
@@ -67,8 +69,8 @@
      *    version 1 key, the string will be a C initializer; this is
      *    not true for newer key versions.
      */
-    static String print(RSAPublicKey key) throws Exception {
-        int version = check(key);
+    static String print(RSAPublicKey key, boolean useSHA256) throws Exception {
+        int version = check(key, useSHA256);
 
         BigInteger N = key.getModulus();
 
@@ -135,10 +137,27 @@
             for (int i = 0; i < args.length; i++) {
                 FileInputStream input = new FileInputStream(args[i]);
                 CertificateFactory cf = CertificateFactory.getInstance("X.509");
-                Certificate cert = cf.generateCertificate(input);
+                X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
+
+                boolean useSHA256 = false;
+                String sigAlg = cert.getSigAlgName();
+                if ("SHA1withRSA".equals(sigAlg) || "MD5withRSA".equals(sigAlg)) {
+                    // SignApk has historically accepted "MD5withRSA"
+                    // certificates, but treated them as "SHA1withRSA"
+                    // anyway.  Continue to do so for backwards
+                    // compatibility.
+                  useSHA256 = false;
+                } else if ("SHA256withRSA".equals(sigAlg)) {
+                  useSHA256 = true;
+                } else {
+                  System.err.println(args[i] + ": unsupported signature algorithm \"" +
+                                     sigAlg + "\"");
+                  System.exit(1);
+                }
+
                 RSAPublicKey key = (RSAPublicKey) (cert.getPublicKey());
-                check(key);
-                System.out.print(print(key));
+                check(key, useSHA256);
+                System.out.print(print(key, useSHA256));
                 System.out.println(i < args.length - 1 ? "," : "");
             }
         } catch (Exception e) {