Make entropy bias self test poll multiple times

Instead of polling the hardware entropy source a single time and
comparing the output with itself, the source is polled at least twice
and make sure that the separate outputs are different.
diff --git a/library/entropy.c b/library/entropy.c
index e09c24c..42ace55 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -470,80 +470,89 @@
     return( 0 );
 }
 
-#if !defined(MBEDTLS_TEST_NULL_ENTROPY) && defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
+#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
 
-#define MBEDTLS_SELF_TEST_BIAS_PATTERN( buf_len, type )             \
-    {                                                               \
-        size_t i;                                                   \
-        int has_pat = 1;                                            \
-        for( i = 0; i < buf_len; i += sizeof( type ) )              \
-        {                                                           \
-            has_pat &= memcmp( buf, buf + i, sizeof( type ) ) == 0; \
-        }                                                           \
-        if( ( ret = has_pat ) != 0 )                                \
-            goto cleanup;                                           \
-    } while( 0 )                                                    \
+static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len )
+{
+    int ret = 0;
+    size_t entropy_len = 0;
+    size_t olen = 0;
+    size_t attempts = buf_len;
+
+    while( attempts > 0 && entropy_len < buf_len )
+    {
+        if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len,
+            buf_len - entropy_len, &olen ) ) != 0 )
+            return( ret );
+
+        entropy_len += olen;
+        attempts--;
+    }
+
+    if( entropy_len < buf_len )
+    {
+        ret = 1;
+    }
+
+    return( ret );
+}
+
+
+static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf,
+                                                        size_t buf_len )
+{
+    unsigned char set= 0xFF;
+    unsigned char unset = 0x00;
+    size_t i;
+
+    for( i = 0; i < buf_len; i++ )
+    {
+        set &= buf[i];
+        unset |= buf[i];
+    }
+
+    return( set == 0xFF || unset == 0x00 );
+}
 
 /*
- * A quick test to ensure hat the entropy sources are functioning correctly
- * and there is no obvious bias. The test performs the following checks:
+ * A test to ensure hat the entropy sources are functioning correctly
+ * and there is no obvious failure. The test performs the following checks:
  *  - The entropy source is not providing only 0s (all bits unset) or 1s (all
  *    bits set).
  *  - The entropy source is not providing values in a pattern. Because the
- *    hardware could be providing data in an arbitrary length, this check is
- *    only perform for bytes, words and long words.
+ *    hardware could be providing data in an arbitrary length, this check polls
+ *    the hardware entropy source twice and compares the result to ensure they
+ *    are not equal.
  *  - The error code returned by the entropy source is not an error.
  */
-int mbedtls_entropy_self_test_bias( int verbose )
+int mbedtls_entropy_source_self_test( int verbose )
 {
     int ret = 0;
-    unsigned char buf[2 * sizeof( unsigned long long int )];
-    mbedtls_entropy_context ctx;
-    size_t entropy_len;
-    size_t olen;
-    size_t gather_tries;
+    unsigned char buf0[2 * sizeof( unsigned long long int )];
+    unsigned char buf1[2 * sizeof( unsigned long long int )];
 
     if( verbose != 0 )
         mbedtls_printf( "  ENTROPY_BIAS test: " );
 
-    memset( buf, 0x00, sizeof( buf ) );
+    memset( buf0, 0x00, sizeof( buf0 ) );
+    memset( buf1, 0x00, sizeof( buf1 ) );
 
-    mbedtls_entropy_init( &ctx );
-
-    /* The hardware entropy source could return less than the amount of
-     * bytes we requested, so we poll the source as many times as there are
-     * bytes */
-    gather_tries = sizeof( buf );
-    entropy_len = 0;
-    while( gather_tries > 0 && entropy_len < sizeof( buf ) )
-    {
-        if( ( ret = mbedtls_hardware_poll( &ctx, buf + entropy_len,
-            sizeof( buf ) - entropy_len, &olen ) ) != 0 )
-            goto cleanup;
-
-        entropy_len += olen;
-        gather_tries--;
-    }
-
-    if( entropy_len < sizeof( buf ) )
-    {
-        /* We still do not have enough entropy: fail */
-        ret = 1;
+    if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 )
         goto cleanup;
-    }
+    if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 )
+        goto cleanup;
+
+    /* Make sure that the returned values are not all 0 or 1 */
+    if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 )
+        goto cleanup;
+    if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 )
+        goto cleanup;
 
     /* Make sure that the entropy source is not returning values in a
      * pattern */
-    /* Byte */
-    MBEDTLS_SELF_TEST_BIAS_PATTERN( 2 * sizeof( unsigned long long int ), unsigned char );
-    /* Word */
-    MBEDTLS_SELF_TEST_BIAS_PATTERN( 2 * sizeof( unsigned long long int ), unsigned long );
-    /* Long word */
-    MBEDTLS_SELF_TEST_BIAS_PATTERN( 2 * sizeof( unsigned long long int ), unsigned long long int );
+    ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0;
 
 cleanup:
-    mbedtls_entropy_free( &ctx );
-
     if( verbose != 0 )
     {
         if( ret != 0 )
@@ -556,7 +565,8 @@
 
     return( ret != 0 );
 }
-#endif /* !MBEDTLS_TEST_NULL_ENTROPY && MBEDTLS_ENTROPY_HARDWARE_ALT */
+
+#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
 
 /*
  * The actual entropy quality is hard to test, but we can at least
@@ -614,6 +624,11 @@
         }
     }
 
+#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
+    if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 )
+        goto cleanup;
+#endif
+
 cleanup:
     mbedtls_entropy_free( &ctx );