Add option for even smaller SHA-256
diff --git a/ChangeLog b/ChangeLog
index 4843341..209b1e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,8 @@
      ability to override the whole module.
    * New server-side implementation of session tickets that rotate keys to
      preserve forward secrecy, and allows sharing across multiple contexts.
+   * Reduced ROM fooprint of SHA-256 and added an option to reduce it even
+     more (at the expense of performance) MBEDTLS_SHA256_SMALLER.
 
 API Changes
    * All public identifiers moved to the mbedtls_* or MBEDTLS_* namespace.
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 6c841ae..f0d293c 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -828,6 +828,22 @@
 #define MBEDTLS_SELF_TEST
 
 /**
+ * \def MBEDTLS_SHA256_SMALLER
+ *
+ * Enable an implementation of SHA-256 that has lower ROM footprint but also
+ * lower performance.
+ *
+ * The default implementation is meant to be a reasonnable compromise between
+ * performance and size. This version optimizes more aggressively for size at
+ * the expense of performance. Eg on Cortex-M4 it reduces the size of
+ * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
+ * 30%.
+ *
+ * Uncomment to enable the smaller implementation of SHA256.
+ */
+//#define MBEDTLS_SHA256_SMALLER
+
+/**
  * \def MBEDTLS_SSL_AEAD_RANDOM_IV
  *
  * Generate a random IV rather than using the record sequence number as a
diff --git a/library/sha256.c b/library/sha256.c
index f80c2b8..4e0b1f3 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -62,22 +62,22 @@
  */
 #ifndef GET_UINT32_BE
 #define GET_UINT32_BE(n,b,i)                            \
-{                                                       \
+do {                                                    \
     (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
         | ( (uint32_t) (b)[(i) + 1] << 16 )             \
         | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
         | ( (uint32_t) (b)[(i) + 3]       );            \
-}
+} while( 0 )
 #endif
 
 #ifndef PUT_UINT32_BE
 #define PUT_UINT32_BE(n,b,i)                            \
-{                                                       \
+do {                                                    \
     (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
     (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
     (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
     (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-}
+} while( 0 )
 #endif
 
 void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
@@ -181,12 +181,26 @@
     uint32_t A[8];
     unsigned int i;
 
-    for( i = 0; i < 16; i++ )
-        GET_UINT32_BE( W[i], data, 4 * i );
-
     for( i = 0; i < 8; i++ )
         A[i] = ctx->state[i];
 
+#if defined(MBEDTLS_SHA256_SMALLER)
+    for( i = 0; i < 64; i++ )
+    {
+        if( i < 16 )
+            GET_UINT32_BE( W[i], data, 4 * i );
+        else
+            R( i );
+
+        P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
+
+        temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
+        A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
+    }
+#else /* MBEDTLS_SHA256_SMALLER */
+    for( i = 0; i < 16; i++ )
+        GET_UINT32_BE( W[i], data, 4 * i );
+
     for( i = 0; i < 16; i += 8 )
     {
         P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
@@ -210,6 +224,7 @@
         P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] );
         P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] );
     }
+#endif /* MBEDTLS_SHA256_SMALLER */
 
     for( i = 0; i < 8; i++ )
         ctx->state[i] += A[i];
diff --git a/library/version_features.c b/library/version_features.c
index 429d54e..d910b60 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -315,6 +315,9 @@
 #if defined(MBEDTLS_SELF_TEST)
     "MBEDTLS_SELF_TEST",
 #endif /* MBEDTLS_SELF_TEST */
+#if defined(MBEDTLS_SHA256_SMALLER)
+    "MBEDTLS_SHA256_SMALLER",
+#endif /* MBEDTLS_SHA256_SMALLER */
 #if defined(MBEDTLS_SSL_AEAD_RANDOM_IV)
     "MBEDTLS_SSL_AEAD_RANDOM_IV",
 #endif /* MBEDTLS_SSL_AEAD_RANDOM_IV */