Merged additional tests and improved code coverage

Conflicts:
	ChangeLog
diff --git a/ChangeLog b/ChangeLog
index f667bf6..36532ba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -32,6 +32,11 @@
      (found by Gergely Budai)
    * Fix compile errors when POLARSSL_ERROR_STRERROR_BC is undefined (found by
      Shuo Chen).
+   * oid_get_numeric_string() used to truncate the output without returning an
+     error if the output buffer was just 1 byte too small.
+   * dhm_parse_dhm() (hence dhm_parse_dhmfile()) did not set dhm->len.
+   * Calling pk_debug() on an RSA-alt key would segfault.
+   * pk_get_size() and pk_get_len() were off by a factor 8 for RSA-alt keys.
 
 = PolarSSL 1.3.5 released on 2014-03-26
 Features
diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h
index 1cafc46..3942891 100644
--- a/include/polarssl/ecp.h
+++ b/include/polarssl/ecp.h
@@ -621,12 +621,14 @@
 int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key,
                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
 
+#if defined(POLARSSL_SELF_TEST)
 /**
  * \brief          Checkup routine
  *
- * \return         0 if successful, or 1 if the test failed
+ * \return         0 if successful, or 1 if a test failed
  */
 int ecp_self_test( int verbose );
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/include/polarssl/error.h b/include/polarssl/error.h
index feba67b..23c0ed7 100644
--- a/include/polarssl/error.h
+++ b/include/polarssl/error.h
@@ -60,7 +60,7 @@
  * CAMELLIA  2  0x0024-0x0026
  * XTEA      1  0x0028-0x0028
  * BASE64    2  0x002A-0x002C
- * OID       1  0x002E-0x002E
+ * OID       1  0x002E-0x002E   0x000B-0x000B
  * PADLOCK   1  0x0030-0x0030
  * DES       1  0x0032-0x0032
  * CTR_DBRG  4  0x0034-0x003A
diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h
index 2470d5e..0c471c5 100644
--- a/include/polarssl/oid.h
+++ b/include/polarssl/oid.h
@@ -44,6 +44,7 @@
 #endif
 
 #define POLARSSL_ERR_OID_NOT_FOUND                         -0x002E  /**< OID is not found. */
+#define POLARSSL_ERR_OID_BUF_TOO_SMALL                     -0x000B  /**< output buffer is too small */
 
 /*
  * Top level OID tuples
@@ -376,7 +377,8 @@
  * \param size      size of the buffer
  * \param oid       OID to translate
  *
- * \return          POLARSSL_ERR_DEBUG_BUF_TOO_SMALL or actual length used
+ * \return          Length of the string written (excluding final NULL) or
+ *                  POLARSSL_ERR_OID_BUF_TO_SMALL in case of error
  */
 int oid_get_numeric_string( char *buf, size_t size, const asn1_buf *oid );
 
diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h
index 6f21dab..b764d55 100644
--- a/include/polarssl/pk.h
+++ b/include/polarssl/pk.h
@@ -234,7 +234,7 @@
  * \param key       RSA key pointer
  * \param decrypt_func  Decryption function
  * \param sign_func     Signing function
- * \param key_len_func  Function returning key length
+ * \param key_len_func  Function returning key length in bytes
  *
  * \return          0 on success, or POLARSSL_ERR_PK_BAD_INPUT_DATA if the
  *                  context wasn't already initialized as RSA_ALT.
diff --git a/include/polarssl/timing.h b/include/polarssl/timing.h
index cb6abe3..09624fc 100644
--- a/include/polarssl/timing.h
+++ b/include/polarssl/timing.h
@@ -74,6 +74,15 @@
  */
 void m_sleep( int milliseconds );
 
+#if defined(POLARSSL_SELF_TEST)
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if a test failed
+ */
+int timing_self_test( int verbose );
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h
index ad8049a..003154b 100644
--- a/include/polarssl/x509.h
+++ b/include/polarssl/x509.h
@@ -212,6 +212,8 @@
 
 /**
  * \brief          Give an known OID, return its descriptive string.
+ *                 (Deprecated. Use oid_get_extended_key_usage() instead.)
+ *                 Warning: only works for extended_key_usage OIDs!
  *
  * \param oid      buffer containing the oid
  *
@@ -228,8 +230,8 @@
  * \param size     Maximum size of buffer
  * \param oid      Buffer containing the OID
  *
- * \return         The amount of data written to the buffer, or -1 in
- *                 case of an error.
+ * \return         Length of the string written (exluding final NULL) or
+ *                 POLARSSL_ERR_OID_BUF_TO_SMALL in case of error
  */
 int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid );
 
diff --git a/library/dhm.c b/library/dhm.c
index 8bc9f0e..406404a 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -460,6 +460,8 @@
 
     ret = 0;
 
+    dhm->len = mpi_size( &dhm->P );
+
 exit:
 #if defined(POLARSSL_PEM_PARSE_C)
     pem_free( &pem );
diff --git a/library/error.c b/library/error.c
index 9980a91..2ca755c 100644
--- a/library/error.c
+++ b/library/error.c
@@ -655,6 +655,8 @@
 #if defined(POLARSSL_OID_C)
     if( use_ret == -(POLARSSL_ERR_OID_NOT_FOUND) )
         snprintf( buf, buflen, "OID - OID is not found" );
+    if( use_ret == -(POLARSSL_ERR_OID_BUF_TOO_SMALL) )
+        snprintf( buf, buflen, "OID - output buffer is too small" );
 #endif /* POLARSSL_OID_C */
 
 #if defined(POLARSSL_PADLOCK_C)
diff --git a/library/oid.c b/library/oid.c
index f943c6d..a2b929b 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -590,16 +590,14 @@
 #define snprintf compat_snprintf
 #endif
 
-#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
-
 #define SAFE_SNPRINTF()                         \
 {                                               \
     if( ret == -1 )                             \
-        return( -1 );                           \
+        return POLARSSL_ERR_OID_BUF_TOO_SMALL;  \
                                                 \
-    if ( (unsigned int) ret > n ) {             \
+    if ( (unsigned int) ret >= n ) {            \
         p[n - 1] = '\0';                        \
-        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
+        return POLARSSL_ERR_OID_BUF_TOO_SMALL;  \
     }                                           \
                                                 \
     n -= (unsigned int) ret;                    \
@@ -630,7 +628,7 @@
     {
         /* Prevent overflow in value. */
         if ( ( ( value << 7 ) >> 7 ) != value )
-            return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL );
+            return( POLARSSL_ERR_OID_BUF_TOO_SMALL );
 
         value <<= 7;
         value += oid->p[i] & 0x7F;
diff --git a/library/pk.c b/library/pk.c
index 80eccc9..cfde265 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -258,6 +258,9 @@
     if( ctx == NULL || ctx->pk_info == NULL )
         return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
 
+    if( ctx->pk_info->debug_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
     ctx->pk_info->debug_func( ctx->pk_ctx, items );
     return( 0 );
 }
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 99535d6..96695d4 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -357,7 +357,7 @@
 {
     const rsa_alt_context *rsa_alt = (const rsa_alt_context *) ctx;
 
-    return( rsa_alt->key_len_func( rsa_alt->key ) );
+    return( 8 * rsa_alt->key_len_func( rsa_alt->key ) );
 }
 
 static int rsa_alt_sign_wrap( void *ctx, md_type_t md_alg,
diff --git a/library/pkcs5.c b/library/pkcs5.c
index c4cdf03..2845f68 100644
--- a/library/pkcs5.c
+++ b/library/pkcs5.c
@@ -361,9 +361,13 @@
     if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 )
         return( 1 );
 
+    if( verbose != 0 )
+        polarssl_printf( "  PBKDF2 warning: test #3 may be slow!\n" );
+
     for( i = 0; i < MAX_TESTS; i++ )
     {
-        polarssl_printf( "  PBKDF2 (SHA1) #%d: ", i );
+        if( verbose != 0 )
+            polarssl_printf( "  PBKDF2 (SHA1) #%d: ", i );
 
         ret = pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i],
                                   slen[i], it_cnt[i], key_len[i], key );
diff --git a/library/timing.c b/library/timing.c
index f1d8a1f..7085b3b 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -25,6 +25,13 @@
 
 #include "polarssl/config.h"
 
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf     printf
+#endif
+
 #if defined(POLARSSL_TIMING_C) && !defined(POLARSSL_TIMING_ALT)
 
 #include "polarssl/timing.h"
@@ -55,7 +62,7 @@
 #endif
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
-	(defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+    (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
 
 #define POLARSSL_HAVE_HARDCLOCK
 
@@ -76,7 +83,7 @@
 unsigned long hardclock( void )
 {
     unsigned long lo, hi;
-    asm( "rdtsc" : "=a" (lo), "=d" (hi) );
+    asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
     return( lo );
 }
 #endif
@@ -89,7 +96,7 @@
 unsigned long hardclock( void )
 {
     unsigned long lo, hi;
-    asm( "rdtsc" : "=a" (lo), "=d" (hi) ); 
+    asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
     return( lo | (hi << 32) );
 }
 #endif
@@ -105,9 +112,9 @@
 
     do
     {
-        asm( "mftbu %0" : "=r" (tbu0) );
-        asm( "mftb  %0" : "=r" (tbl ) );
-        asm( "mftbu %0" : "=r" (tbu1) );
+        asm volatile( "mftbu %0" : "=r" (tbu0) );
+        asm volatile( "mftb  %0" : "=r" (tbl ) );
+        asm volatile( "mftbu %0" : "=r" (tbu1) );
     }
     while( tbu0 != tbu1 );
 
@@ -126,7 +133,7 @@
 unsigned long hardclock( void )
 {
     unsigned long tick;
-    asm( "rdpr %%tick, %0;" : "=&r" (tick) );
+    asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) );
     return( tick );
 }
 #endif
@@ -140,8 +147,8 @@
 unsigned long hardclock( void )
 {
     unsigned long tick;
-    asm( ".byte 0x83, 0x41, 0x00, 0x00" );
-    asm( "mov   %%g1, %0" : "=r" (tick) );
+    asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" );
+    asm volatile( "mov   %%g1, %0" : "=r" (tick) );
     return( tick );
 }
 #endif
@@ -154,7 +161,7 @@
 unsigned long hardclock( void )
 {
     unsigned long cc;
-    asm( "rpcc %0" : "=r" (cc) );
+    asm volatile( "rpcc %0" : "=r" (cc) );
     return( cc & 0xFFFFFFFF );
 }
 #endif
@@ -167,7 +174,7 @@
 unsigned long hardclock( void )
 {
     unsigned long itc;
-    asm( "mov %0 = ar.itc" : "=r" (itc) );
+    asm volatile( "mov %0 = ar.itc" : "=r" (itc) );
     return( itc );
 }
 #endif
@@ -181,9 +188,9 @@
 {
     LARGE_INTEGER offset;
 
-	QueryPerformanceCounter( &offset );
+    QueryPerformanceCounter( &offset );
 
-	return (unsigned long)( offset.QuadPart );
+    return (unsigned long)( offset.QuadPart );
 }
 #endif
 
@@ -234,17 +241,17 @@
 }
 
 DWORD WINAPI TimerProc( LPVOID uElapse )
-{   
+{
     Sleep( (DWORD) uElapse );
-    alarmed = 1; 
+    alarmed = 1;
     return( TRUE );
 }
 
 void set_alarm( int seconds )
-{   
+{
     DWORD ThreadId;
 
-    alarmed = 0; 
+    alarmed = 0;
     CloseHandle( CreateThread( NULL, 0, TimerProc,
         (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) );
 }
@@ -254,7 +261,7 @@
     Sleep( milliseconds );
 }
 
-#else
+#else /* _WIN32 && !EFIX64 && !EFI32 */
 
 unsigned long get_timer( struct hr_time *val, int reset )
 {
@@ -282,10 +289,10 @@
     usleep( milliseconds * 1000 );
 }
 
-#else
+#else /* INTEGRITY */
 
 static void sighandler( int signum )
-{   
+{
     alarmed = 1;
     signal( signum, sighandler );
 }
@@ -308,6 +315,150 @@
 }
 #endif /* INTEGRITY */
 
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+
+#if defined(POLARSSL_SELF_TEST)
+
+/* To test net_usleep against our functions */
+#if defined(POLARSSL_NET_C)
+#include "polarssl/net.h"
 #endif
 
+/*
+ * Checkup routine
+ */
+int timing_self_test( int verbose )
+{
+    unsigned long cycles, ratio;
+    unsigned long millisecs, secs;
+    int hardfail;
+    struct hr_time hires;
+
+    if( verbose != 0)
+        polarssl_printf( "  TIMING tests warning: will take some time!\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #1 (m_sleep   / get_timer): " );
+
+    for( secs = 1; secs <= 3; secs++ )
+    {
+        (void) get_timer( &hires, 1 );
+
+        m_sleep( 500 * secs );
+
+        millisecs = get_timer( &hires, 0 );
+
+        if( millisecs < 450 * secs || millisecs > 550 * secs )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #2 (set_alarm / get_timer): " );
+
+    for( secs = 1; secs <= 3; secs++ )
+    {
+        (void) get_timer( &hires, 1 );
+
+        set_alarm( secs );
+        while( !alarmed )
+            ;
+
+        millisecs = get_timer( &hires, 0 );
+
+        if( millisecs < 900 * secs || millisecs > 1100 * secs )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #3 (hardclock / m_sleep  ): " );
+
+    /*
+     * Allow one failure for possible counter wrapping.
+     * On a 4Ghz 32-bit machine the cycle counter wraps about once per second;
+     * since the whole test is about 10ms, it shouldn't happen twice in a row.
+     */
+    hardfail = 0;
+
+hard_test:
+    if( hardfail > 1 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    /* Get a reference ratio cycles/ms */
+    cycles = hardclock();
+    m_sleep( 1 );
+    cycles = hardclock() - cycles;
+    ratio = cycles / 1;
+
+    for( millisecs = 2; millisecs <= 4; millisecs++ )
+    {
+        cycles = hardclock();
+        m_sleep( millisecs );
+        cycles = hardclock() - cycles;
+
+        /* Allow variation up to 20% */
+        if( cycles / millisecs < ratio - ratio / 5 ||
+            cycles / millisecs > ratio + ratio / 5 )
+        {
+            hardfail++;
+            goto hard_test;
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+#if defined(POLARSSL_NET_C)
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #4 (net_usleep/ get_timer): " );
+
+    for( secs = 1; secs <= 3; secs++ )
+    {
+        (void) get_timer( &hires, 1 );
+
+        net_usleep( 500000 * secs );
+
+        millisecs = get_timer( &hires, 0 );
+
+        if( millisecs < 450 * secs || millisecs > 550 * secs )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
 #endif
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_TIMING_C && !POLARSSL_TIMING_ALT */
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 0fb5886..82477e5 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -49,7 +49,9 @@
 #include "polarssl/x509.h"
 #include "polarssl/xtea.h"
 #include "polarssl/pkcs5.h"
+#include "polarssl/pbkdf2.h"
 #include "polarssl/ecp.h"
+#include "polarssl/timing.h"
 
 #if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
 #include "polarssl/memory.h"
@@ -171,11 +173,6 @@
         return( ret );
 #endif
 
-#if defined(POLARSSL_PKCS5_C)
-    if( ( ret = pkcs5_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
 #if defined(POLARSSL_ECP_C)
     if( ( ret = ecp_self_test( v ) ) != 0 )
         return( ret );
@@ -186,6 +183,23 @@
         return( ret );
 #endif
 
+/* Slow tests last */
+
+#if defined(POLARSSL_PBKDF2_C)
+    if( ( ret = pbkdf2_self_test( v ) ) != 0 )
+        return( ret );
+#else
+#if defined(POLARSSL_PKCS5_C)
+    if( ( ret = pkcs5_self_test( v ) ) != 0 )
+        return( ret );
+#endif
+#endif
+
+#if defined(POLARSSL_TIMING_C)
+    if( ( ret = timing_self_test( v ) ) != 0 )
+        return( ret );
+#endif
+
 #else
     printf( " POLARSSL_SELF_TEST not defined.\n" );
 #endif
diff --git a/tests/Descriptions.txt b/tests/Descriptions.txt
index b6309f3..8b13bb3 100644
--- a/tests/Descriptions.txt
+++ b/tests/Descriptions.txt
@@ -4,12 +4,17 @@
     (reference test vectors, sanity checks, malformed input for parsing
     functions, etc.) for all modules except the SSL modules.
 
+selftests
+    The 'programs/test/selftest' program runs the 'XXX_self_test()' functions
+    of each individual module. Most of them are included in the respective
+    test suite, but some slower ones are only included here.
+
 compat
     The 'tests/compat.sh' script checks interoperability with OpenSSL and
     GnuTLS (and ourselves!) for every common ciphersuite, in every TLS
     version, both ways (client/server), using client authentication or not.
     For each ciphersuite/version/side/authmode it performs a full handshake
-    and a small data exchange. 
+    and a small data exchange.
 
 ssl_opt
     The 'tests/ssl-opt.sh' script checks various options and/or operations not
diff --git a/tests/compat.sh b/tests/compat.sh
index bf52847..89764f5 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -5,16 +5,15 @@
 # Check each common ciphersuite, with each version, both ways (client/server),
 # with and without client authentication.
 
+set -u
+
 # test if those two are set in the environment before assigning defaults
-if [ -n "$GNUTLS_CLI" -a -n "$GNUTLS_SERV" ]; then
+if [ -n "${GNUTLS_CLI:-}" -a -n "${GNUTLS_SERV:-}" ]; then
     GNUTLS_AVAILABLE=1
 else
     GNUTLS_AVAILABLE=0
 fi
 
-# catch undefined variables from now on
-set -u
-
 # initialise counters
 let "tests = 0"
 let "failed = 0"
diff --git a/tests/data_files/dhparams.pem b/tests/data_files/dhparams.pem
new file mode 100644
index 0000000..7ce05f0
--- /dev/null
+++ b/tests/data_files/dhparams.pem
@@ -0,0 +1,5 @@
+-----BEGIN DH PARAMETERS-----
+MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh
+1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32
+9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC
+-----END DH PARAMETERS-----
diff --git a/tests/data_files/server1.req.cert_type b/tests/data_files/server1.req.cert_type
new file mode 100644
index 0000000..5677f32
--- /dev/null
+++ b/tests/data_files/server1.req.cert_type
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICpTCCAY0CAQAwPDELMAkGA1UEBhMCTkwxETAPBgNVBAoTCFBvbGFyU1NMMRow
+GAYDVQQDExFQb2xhclNTTCBTZXJ2ZXIgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKkCHz1AatVVU4v9Nu6CZS4VYV6Jv7joRZDb7ogWUtPxQ1BHlhJZ
+ZIdr/SvgRvlzvt3PkuGRW+1moG+JKXlFgNCDatVBQ3dfOXwJBEeCsFc5cO2j7BUZ
+HqgzCEfBBUKp/UzDtN/dBh9NEFFAZ3MTD0D4bYElXwqxU8YwfhU5rPla7n+SnqYF
+W+cTl4W1I5LZ1CQG1QkliXUH3aYajz8JGb6tZSxk65Wb3P5BXhem2mxbacwCuhQs
+FiScStzN0PdSZ3PxLaAj/X70McotcMqJCwTbLqZPcG6ezr1YieJTWZ5uWpJl4og/
+DJQZo93l6J2VE+0p26twEtxaymsXq1KCVLECAwEAAaAkMCIGCSqGSIb3DQEJDjEV
+MBMwEQYJYIZIAYb4QgEBBAQDAgBAMA0GCSqGSIb3DQEBBQUAA4IBAQB95Pkjpg/N
+Jbgl5nZcAk8maGMpUFlrhJS4kGutQKZugNX9v8cfABW905IHYXV1dm6zxVcyeqZM
+FiOgbV943fu5JbufoazdYXnnR2/iKMigqX4CzZrK3F5ZzegxkfDIfDrn/shC+rWb
+SS5WBVLJ3QNj9vwn3/b66IRbp/ViOwHx7+9JT4K/rLId/ynjYf2T57AsmNd/jptc
+Zs19fGgtrUXweWkliEZN2zE47Cc53jkx6+Li4TNs4Bjk5P/aXrCP0fBwgGt2K6YW
+dQ/nr0PwIbXzVlgUukSTHkJJfhF4Y/WqcUfOPrRdw+zxOLusJ9nzJBR0FOohcBxM
+kPBVna0dze/o
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/data_files/server1.req.key_usage b/tests/data_files/server1.req.key_usage
new file mode 100644
index 0000000..053aed9
--- /dev/null
+++ b/tests/data_files/server1.req.key_usage
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICnzCCAYcCAQAwPDELMAkGA1UEBhMCTkwxETAPBgNVBAoTCFBvbGFyU1NMMRow
+GAYDVQQDExFQb2xhclNTTCBTZXJ2ZXIgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKkCHz1AatVVU4v9Nu6CZS4VYV6Jv7joRZDb7ogWUtPxQ1BHlhJZ
+ZIdr/SvgRvlzvt3PkuGRW+1moG+JKXlFgNCDatVBQ3dfOXwJBEeCsFc5cO2j7BUZ
+HqgzCEfBBUKp/UzDtN/dBh9NEFFAZ3MTD0D4bYElXwqxU8YwfhU5rPla7n+SnqYF
+W+cTl4W1I5LZ1CQG1QkliXUH3aYajz8JGb6tZSxk65Wb3P5BXhem2mxbacwCuhQs
+FiScStzN0PdSZ3PxLaAj/X70McotcMqJCwTbLqZPcG6ezr1YieJTWZ5uWpJl4og/
+DJQZo93l6J2VE+0p26twEtxaymsXq1KCVLECAwEAAaAeMBwGCSqGSIb3DQEJDjEP
+MA0wCwYDVR0PBAQDAgHgMA0GCSqGSIb3DQEBBQUAA4IBAQCj6jCu0wE5OQ1JGQwZ
+FNwPqZrvKntSq2yLIbgmGxwlvDLxOzn0KmidSFiKRqh0KXwj9siodlz5C0d9tUqq
+7xUXg+j+wDHqUV8zo42Jke+UmWXFPpnXx/fDFGTITdLSn8ZDxkt31ESLTEVZvPFD
+odm+C+zWJtKpyL+9op4KvyBQ1MZ9nWZpwMaK4g4mdtOIsz75gMa74w8ZT7VzhGMY
+cZGmafsl7x++GDDtf0oCPgrj9xy+Ovv/GyUBaB+6lweflTfPDTRSoN0meFlP5ynF
+vqcBM5JKH2FUQIizfc9o6Z8tKxe9FCov3x8szAuoMRA7bjhVngeQIrEkTcaQBvBY
+NalC
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/data_files/server1.req.ku-ct b/tests/data_files/server1.req.ku-ct
new file mode 100644
index 0000000..0e057d5
--- /dev/null
+++ b/tests/data_files/server1.req.ku-ct
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICsjCCAZoCAQAwPDELMAkGA1UEBhMCTkwxETAPBgNVBAoTCFBvbGFyU1NMMRow
+GAYDVQQDExFQb2xhclNTTCBTZXJ2ZXIgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKkCHz1AatVVU4v9Nu6CZS4VYV6Jv7joRZDb7ogWUtPxQ1BHlhJZ
+ZIdr/SvgRvlzvt3PkuGRW+1moG+JKXlFgNCDatVBQ3dfOXwJBEeCsFc5cO2j7BUZ
+HqgzCEfBBUKp/UzDtN/dBh9NEFFAZ3MTD0D4bYElXwqxU8YwfhU5rPla7n+SnqYF
+W+cTl4W1I5LZ1CQG1QkliXUH3aYajz8JGb6tZSxk65Wb3P5BXhem2mxbacwCuhQs
+FiScStzN0PdSZ3PxLaAj/X70McotcMqJCwTbLqZPcG6ezr1YieJTWZ5uWpJl4og/
+DJQZo93l6J2VE+0p26twEtxaymsXq1KCVLECAwEAAaAxMC8GCSqGSIb3DQEJDjEi
+MCAwCwYDVR0PBAQDAgHgMBEGCWCGSAGG+EIBAQQEAwIAQDANBgkqhkiG9w0BAQUF
+AAOCAQEANlNG9hW852OzVKj2Z8TtU9jxstAoSCH9yc9Coj4Vw2TTjs1zcuBWsMl1
+2bf2I6ZvEH6ZhcQY7i7nyHQyPlqE4l6U9D8ct967QN7smuAHNY2HiQ2++eCBTHck
+PdtGJAzIvNlXcoqNi8UC5fGepNtI1usNo41SKMvbg6nGA5gdcQKk7CVlk8lrD0qI
+Xn/HvjSRoDE4ZGxAtNvPXWorGSxtgcy8EMPoXVUab5fNt8q//x/NQ4yEQKPrexmR
+IuOiQ8VW8QZtkORGpZbGSvskU0WfKANui4zCcXYRc4mVR4Wf0C+fyHeihhjslSnT
+RbC7nQn5HSHp31qJlr80QodywaK1Dg==
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/data_files/server1.v1.crt b/tests/data_files/server1.v1.crt
new file mode 100644
index 0000000..0a4b2a5
--- /dev/null
+++ b/tests/data_files/server1.v1.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC9DCCAdygAwIBAAIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G
+A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/
+uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD
+d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf
+CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr
+lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w
+bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB
+owIwADANBgkqhkiG9w0BAQUFAAOCAQEAoZVuVi7bIslKgMJhejSFXiO+ICMz1fmK
+b0tPN68mRYhI/gsjRT0cmX6GUNrg+U5mcBWhMwHgyvx1CARU4YToKZxcXGNL0DPd
+Z1hF8nCrJCZBQvNuWE7s0ufw92xz5ZfuKkVxi94RYR529F6gzgl4rpX8UQVu2ym/
+9pTlHKr4MKi9LNppyJMS89uRcb2FJFMdhAKbhNtbIjI9qGZ7x//0belAaWhq389u
+6XWFnZt35PU6Zz6YbAQ5pjZYsTaohuufgrpOlFPUuc4uR+RfGHIQ6id12lZaQC2m
+OFIBDcU0x1cFfPfMgVdBLf6klPt/v/tD77mwx0eztSp28NIf+ACw8A==
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server5.req.ku.sha1 b/tests/data_files/server5.req.ku.sha1
new file mode 100644
index 0000000..7556d1a
--- /dev/null
+++ b/tests/data_files/server5.req.ku.sha1
@@ -0,0 +1,8 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBFjCBvAIBADA8MQswCQYDVQQGEwJOTDERMA8GA1UEChMIUG9sYXJTU0wxGjAY
+BgNVBAMTEVBvbGFyU1NMIFNlcnZlciAxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
+QgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/6i/SNF1d
+Fr2KiMJrdw1VzYoqDvoByLTt/6AeMBwGCSqGSIb3DQEJDjEPMA0wCwYDVR0PBAQD
+AgHAMAsGByqGSM49BAEFAANIADBFAiBjnnD7nwsFnCL+MpPPFJE3K/Tgj+5rAgXj
+e5UejDX2CAIhAKdbigWJL/ZatvG9CFHq7ykrRns2x8JEXehWu8DsXdx9
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 249be3b..8dba3ec 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -74,6 +74,7 @@
 cmake -D CMAKE_BUILD_TYPE:String=ASan .
 make
 make test
+programs/test/selftest
 cd tests
 ./compat.sh
 ./ssl-opt.sh
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 916ce77..b35a9e4 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -10,6 +10,14 @@
 
 set -u
 
+# test if it is defined from the environment before assining default
+# if yes, assume it means it's a build with all the options we need (SSLv2)
+if [ -n "${OPENSSL_CMD:-}" ]; then
+    OPENSSL_OK=1
+else
+    OPENSSL_OK=0
+fi
+
 # default values, can be overriden by the environment
 : ${P_SRV:=../programs/ssl/ssl_server2}
 : ${P_CLI:=../programs/ssl/ssl_client2}
@@ -25,7 +33,11 @@
 
 MEMCHECK=0
 FILTER='.*'
-EXCLUDE='SSLv2' # disabled by default, needs OpenSSL compiled with SSLv2
+if [ "$OPENSSL_OK" -gt 0 ]; then
+    EXCLUDE='^$'
+else
+    EXCLUDE='SSLv2'
+fi
 
 print_usage() {
     echo "Usage: $0 [options]"
@@ -247,6 +259,8 @@
 # MAIN
 #
 
+get_options "$@"
+
 # sanity checks, avoid an avalanche of errors
 if [ ! -x "$P_SRV" ]; then
     echo "Command '$P_SRV' is not an executable file"
@@ -261,8 +275,6 @@
     exit 1
 fi
 
-get_options "$@"
-
 killall -q openssl ssl_server ssl_server2
 trap cleanup INT TERM HUP
 
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index b8f1df3..c39da5b 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -12,6 +12,16 @@
  */
 
 /* BEGIN_CASE */
+void cipher_list( )
+{
+    const int *cipher_type;
+
+    for( cipher_type = cipher_list(); *cipher_type != 0; cipher_type++ )
+        TEST_ASSERT( cipher_info_from_type( *cipher_type ) != NULL );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void enc_dec_buf( int cipher_id, char *cipher_string, int key_len,
                   int length_val, int pad_mode )
 {
diff --git a/tests/suites/test_suite_cipher.padding.data b/tests/suites/test_suite_cipher.padding.data
index 8776a28..702c88f 100644
--- a/tests/suites/test_suite_cipher.padding.data
+++ b/tests/suites/test_suite_cipher.padding.data
@@ -1,3 +1,6 @@
+Cipher list
+cipher_list:
+
 Set padding with AES-CBC
 depends_on:POLARSSL_AES_C:POLARSSL_CIPHER_MODE_CBC:POLARSSL_CIPHER_PADDING_PKCS7
 set_padding:POLARSSL_CIPHER_AES_128_CBC:POLARSSL_PADDING_PKCS7:0
diff --git a/tests/suites/test_suite_des.data b/tests/suites/test_suite_des.data
index 7291649..559d5de 100644
--- a/tests/suites/test_suite_des.data
+++ b/tests/suites/test_suite_des.data
@@ -1,3 +1,15 @@
+DES check weak key #1
+des_check_weak:"0101010101010101":1
+
+DES check weak key #2
+des_check_weak:"FEE0FEE0FEF1FEF1":1
+
+DES check weak key #3
+des_check_weak:"0101010101010100":0
+
+DES check weak key #4
+des_check_weak:"EEE0FEE0FEF1FEF1":0
+
 DES Encrypt OpenSSL Test Vector #1
 des_encrypt_ecb:"0000000000000000":"0000000000000000":"8CA64DE9C1B123A7"
 
diff --git a/tests/suites/test_suite_des.function b/tests/suites/test_suite_des.function
index ee327c9..d5d0f11 100644
--- a/tests/suites/test_suite_des.function
+++ b/tests/suites/test_suite_des.function
@@ -8,6 +8,19 @@
  */
 
 /* BEGIN_CASE */
+void des_check_weak( char *key_hex, int ret )
+{
+    unsigned char key[DES_KEY_SIZE];
+
+    memset( key, 0, sizeof key );
+
+    unhexify( key, key_hex );
+
+    TEST_ASSERT( des_key_check_weak( key ) == ret );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void des_encrypt_ecb( char *hex_key_string, char *hex_src_string,
                       char *hex_dst_string )
 {
diff --git a/tests/suites/test_suite_dhm.data b/tests/suites/test_suite_dhm.data
index aecbfc5..57db3db 100644
--- a/tests/suites/test_suite_dhm.data
+++ b/tests/suites/test_suite_dhm.data
@@ -7,5 +7,8 @@
 Diffie-Hellman full exchange #3
 dhm_do_dhm:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271"
 
+Diffie-Hallman load parameters from file
+dhm_file:"data_files/dhparams.pem":"9e35f430443a09904f3a39a979797d070df53378e79c2438bef4e761f3c714553328589b041c809be1d6c6b5f1fc9f47d3a25443188253a992a56818b37ba9de5a40d362e56eff0be5417474c125c199272c8fe41dea733df6f662c92ae76556e755d10c64e6a50968f67fc6ea73d0dca8569be2ba204e23580d8bca2f4975b3":"02":128
+
 Diffie-Hellman selftest
 dhm_selftest:
diff --git a/tests/suites/test_suite_dhm.function b/tests/suites/test_suite_dhm.function
index d66998f..b0df9fd 100644
--- a/tests/suites/test_suite_dhm.function
+++ b/tests/suites/test_suite_dhm.function
@@ -97,6 +97,29 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO */
+void dhm_file( char *filename, char *p, char *g, int len )
+{
+    dhm_context ctx;
+    mpi P, G;
+
+    memset( &ctx, 0, sizeof ctx );
+    mpi_init( &P ); mpi_init( &G );
+
+    TEST_ASSERT( mpi_read_string( &P, 16, p ) == 0 );
+    TEST_ASSERT( mpi_read_string( &G, 16, g ) == 0 );
+
+    TEST_ASSERT( dhm_parse_dhmfile( &ctx, filename ) == 0 );
+
+    TEST_ASSERT( ctx.len == (size_t) len );
+    TEST_ASSERT( mpi_cmp_mpi( &ctx.P, &P ) == 0 );
+    TEST_ASSERT( mpi_cmp_mpi( &ctx.G, &G ) == 0 );
+
+    mpi_free( &P ); mpi_free( &G );
+    dhm_free( &ctx );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:POLARSSL_SELF_TEST */
 void dhm_selftest()
 {
diff --git a/tests/suites/test_suite_error.function b/tests/suites/test_suite_error.function
index a514cee..4532530 100644
--- a/tests/suites/test_suite_error.function
+++ b/tests/suites/test_suite_error.function
@@ -12,8 +12,18 @@
 {
     char buf[500];
 
+    memset( buf, 0, sizeof( buf ) );
+
     polarssl_strerror( code, buf, 500 );
 
     TEST_ASSERT( strcmp( buf, result_str ) == 0 );
+
+#if defined(POLARSSL_ERROR_STRERROR_BC)
+    memset( buf, 0, sizeof( buf ) );
+
+    error_strerror( code, buf, 500 );
+
+    TEST_ASSERT( strcmp( buf, result_str ) == 0 );
+#endif
 }
 /* END_CASE */
diff --git a/tests/suites/test_suite_hmac_shax.function b/tests/suites/test_suite_hmac_shax.function
index 4a15322..d65437b 100644
--- a/tests/suites/test_suite_hmac_shax.function
+++ b/tests/suites/test_suite_hmac_shax.function
@@ -10,21 +10,51 @@
 {
     unsigned char src_str[10000];
     unsigned char key_str[10000];
-    unsigned char hash_str[10000];
-    unsigned char output[41];
+    unsigned char hash_str[41];
+    unsigned char output[20];
     int key_len, src_len;
+    sha1_context ctx;
 
-    memset(src_str, 0x00, 10000);
-    memset(key_str, 0x00, 10000);
-    memset(hash_str, 0x00, 10000);
-    memset(output, 0x00, 41);
+    memset(src_str, 0x00, sizeof src_str);
+    memset(key_str, 0x00, sizeof key_str);
 
     key_len = unhexify( key_str, hex_key_string );
     src_len = unhexify( src_str, hex_src_string );
 
-    sha1_hmac( key_str, key_len, src_str, src_len, output );
-    hexify( hash_str, output, 20 );
+    /* Test the all-in-one interface */
+    memset(hash_str, 0x00, sizeof hash_str);
+    memset(output, 0x00, sizeof output);
 
+    sha1_hmac( key_str, key_len, src_str, src_len, output );
+
+    hexify( hash_str, output, sizeof output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Also test the "streaming" interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+    memset( &ctx, 0x00, sizeof ctx );
+
+    sha1_hmac_starts( &ctx, key_str, key_len );
+    sha1_hmac_update( &ctx, src_str, 0 );
+    sha1_hmac_update( &ctx, src_str, src_len / 2 );
+    sha1_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    sha1_hmac_update( &ctx, src_str + src_len, 0 );
+    sha1_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Again, to test hmac_reset() */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+
+    sha1_hmac_reset( &ctx );
+    sha1_hmac_update( &ctx, src_str, src_len / 2 );
+    sha1_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    sha1_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
 }
 /* END_CASE */
@@ -35,21 +65,51 @@
 {
     unsigned char src_str[10000];
     unsigned char key_str[10000];
-    unsigned char hash_str[10000];
-    unsigned char output[57];
+    unsigned char hash_str[57];
+    unsigned char output[28];
     int key_len, src_len;
+    sha256_context ctx;
 
-    memset(src_str, 0x00, 10000);
-    memset(key_str, 0x00, 10000);
-    memset(hash_str, 0x00, 10000);
-    memset(output, 0x00, 57);
+    memset(src_str, 0x00, sizeof src_str);
+    memset(key_str, 0x00, sizeof key_str);
 
     key_len = unhexify( key_str, hex_key_string );
     src_len = unhexify( src_str, hex_src_string );
 
-    sha256_hmac( key_str, key_len, src_str, src_len, output, 1 );
-    hexify( hash_str, output, 28 );
+    /* Test the all-in-one interface */
+    memset(hash_str, 0x00, sizeof hash_str);
+    memset(output, 0x00, sizeof output);
 
+    sha256_hmac( key_str, key_len, src_str, src_len, output, 1 );
+
+    hexify( hash_str, output, sizeof output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Also test the "streaming" interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+    memset( &ctx, 0x00, sizeof ctx );
+
+    sha256_hmac_starts( &ctx, key_str, key_len, 1 );
+    sha256_hmac_update( &ctx, src_str, 0 );
+    sha256_hmac_update( &ctx, src_str, src_len / 2 );
+    sha256_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    sha256_hmac_update( &ctx, src_str + src_len, 0 );
+    sha256_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Again, to test hmac_reset() */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+
+    sha256_hmac_reset( &ctx );
+    sha256_hmac_update( &ctx, src_str, src_len / 2 );
+    sha256_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    sha256_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
 }
 /* END_CASE */
@@ -60,21 +120,51 @@
 {
     unsigned char src_str[10000];
     unsigned char key_str[10000];
-    unsigned char hash_str[10000];
-    unsigned char output[65];
+    unsigned char hash_str[65];
+    unsigned char output[32];
     int key_len, src_len;
+    sha256_context ctx;
 
-    memset(src_str, 0x00, 10000);
-    memset(key_str, 0x00, 10000);
-    memset(hash_str, 0x00, 10000);
-    memset(output, 0x00, 65);
+    memset(src_str, 0x00, sizeof src_str);
+    memset(key_str, 0x00, sizeof key_str);
 
     key_len = unhexify( key_str, hex_key_string );
     src_len = unhexify( src_str, hex_src_string );
 
-    sha256_hmac( key_str, key_len, src_str, src_len, output, 0 );
-    hexify( hash_str, output, 32 );
+    /* Test the all-in-one interface */
+    memset(hash_str, 0x00, sizeof hash_str);
+    memset(output, 0x00, sizeof output);
 
+    sha256_hmac( key_str, key_len, src_str, src_len, output, 0 );
+
+    hexify( hash_str, output, sizeof output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Also test the "streaming" interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+    memset( &ctx, 0x00, sizeof ctx );
+
+    sha256_hmac_starts( &ctx, key_str, key_len, 0 );
+    sha256_hmac_update( &ctx, src_str, 0 );
+    sha256_hmac_update( &ctx, src_str, src_len / 2 );
+    sha256_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    sha256_hmac_update( &ctx, src_str + src_len, 0 );
+    sha256_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Again, to test hmac_reset() */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+
+    sha256_hmac_reset( &ctx );
+    sha256_hmac_update( &ctx, src_str, src_len / 2 );
+    sha256_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    sha256_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
 }
 /* END_CASE */
@@ -85,21 +175,51 @@
 {
     unsigned char src_str[10000];
     unsigned char key_str[10000];
-    unsigned char hash_str[10000];
-    unsigned char output[97];
+    unsigned char hash_str[97];
+    unsigned char output[48];
     int key_len, src_len;
+    sha512_context ctx;
 
-    memset(src_str, 0x00, 10000);
-    memset(key_str, 0x00, 10000);
-    memset(hash_str, 0x00, 10000);
-    memset(output, 0x00, 97);
+    memset(src_str, 0x00, sizeof src_str);
+    memset(key_str, 0x00, sizeof key_str);
 
     key_len = unhexify( key_str, hex_key_string );
     src_len = unhexify( src_str, hex_src_string );
 
-    sha512_hmac( key_str, key_len, src_str, src_len, output, 1 );
-    hexify( hash_str, output, 48 );
+    /* Test the all-in-one interface */
+    memset(hash_str, 0x00, sizeof hash_str);
+    memset(output, 0x00, sizeof output);
 
+    sha512_hmac( key_str, key_len, src_str, src_len, output, 1 );
+
+    hexify( hash_str, output, sizeof output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Also test the "streaming" interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+    memset( &ctx, 0x00, sizeof ctx );
+
+    sha512_hmac_starts( &ctx, key_str, key_len, 1 );
+    sha512_hmac_update( &ctx, src_str, 0 );
+    sha512_hmac_update( &ctx, src_str, src_len / 2 );
+    sha512_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    sha512_hmac_update( &ctx, src_str + src_len, 0 );
+    sha512_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Again, to test hmac_reset() */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+
+    sha512_hmac_reset( &ctx );
+    sha512_hmac_update( &ctx, src_str, src_len / 2 );
+    sha512_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    sha512_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
 }
 /* END_CASE */
@@ -110,21 +230,51 @@
 {
     unsigned char src_str[10000];
     unsigned char key_str[10000];
-    unsigned char hash_str[10000];
-    unsigned char output[129];
+    unsigned char hash_str[129];
+    unsigned char output[64];
     int key_len, src_len;
+    sha512_context ctx;
 
-    memset(src_str, 0x00, 10000);
-    memset(key_str, 0x00, 10000);
-    memset(hash_str, 0x00, 10000);
-    memset(output, 0x00, 129);
+    memset(src_str, 0x00, sizeof src_str);
+    memset(key_str, 0x00, sizeof key_str);
 
     key_len = unhexify( key_str, hex_key_string );
     src_len = unhexify( src_str, hex_src_string );
 
-    sha512_hmac( key_str, key_len, src_str, src_len, output, 0 );
-    hexify( hash_str, output, 64 );
+    /* Test the all-in-one interface */
+    memset(hash_str, 0x00, sizeof hash_str);
+    memset(output, 0x00, sizeof output);
 
+    sha512_hmac( key_str, key_len, src_str, src_len, output, 0 );
+
+    hexify( hash_str, output, sizeof output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Also test the "streaming" interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+    memset( &ctx, 0x00, sizeof ctx );
+
+    sha512_hmac_starts( &ctx, key_str, key_len, 0 );
+    sha512_hmac_update( &ctx, src_str, 0 );
+    sha512_hmac_update( &ctx, src_str, src_len / 2 );
+    sha512_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    sha512_hmac_update( &ctx, src_str + src_len, 0 );
+    sha512_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Again, to test hmac_reset() */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+
+    sha512_hmac_reset( &ctx );
+    sha512_hmac_update( &ctx, src_str, src_len / 2 );
+    sha512_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    sha512_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
 }
 /* END_CASE */
diff --git a/tests/suites/test_suite_md.data b/tests/suites/test_suite_md.data
index cc1851c..bd25a53 100644
--- a/tests/suites/test_suite_md.data
+++ b/tests/suites/test_suite_md.data
@@ -1,3 +1,42 @@
+MD process
+md_process:
+
+Information on MD2
+depends_on:POLARSSL_MD2_C
+md_info:POLARSSL_MD_MD2:"MD2":16
+
+Information on MD4
+depends_on:POLARSSL_MD4_C
+md_info:POLARSSL_MD_MD4:"MD4":16
+
+Information on MD5
+depends_on:POLARSSL_MD5_C
+md_info:POLARSSL_MD_MD5:"MD5":16
+
+Information on RIPEMD160
+depends_on:POLARSSL_RIPEMD160_C
+md_info:POLARSSL_MD_RIPEMD160:"RIPEMD160":20
+
+Information on SHA1
+depends_on:POLARSSL_SHA1_C
+md_info:POLARSSL_MD_SHA1:"SHA1":20
+
+Information on SHA224
+depends_on:POLARSSL_SHA256_C
+md_info:POLARSSL_MD_SHA224:"SHA224":28
+
+Information on SHA256
+depends_on:POLARSSL_SHA256_C
+md_info:POLARSSL_MD_SHA256:"SHA256":32
+
+Information on SHA384
+depends_on:POLARSSL_SHA512_C
+md_info:POLARSSL_MD_SHA384:"SHA384":48
+
+Information on SHA512
+depends_on:POLARSSL_SHA512_C
+md_info:POLARSSL_MD_SHA512:"SHA512":64
+
 generic md2 Test vector RFC1319 #1
 depends_on:POLARSSL_MD2_C
 md_text:"md2":"":"8350e5a3e24c153df2275c9f80692773"
@@ -82,35 +121,35 @@
 depends_on:POLARSSL_MD5_C
 md_text:"md5":"12345678901234567890123456789012345678901234567890123456789012345678901234567890":"57edf4a22be3c955ac49da2e2107b67a"
 
-ripemd160 Test vector from paper #1
+generic ripemd160 Test vector from paper #1
 depends_on:POLARSSL_RIPEMD160_C
 md_text:"ripemd160":"":"9c1185a5c5e9fc54612808977ee8f548b2258d31"
 
-ripemd160 Test vector from paper #2
+generic ripemd160 Test vector from paper #2
 depends_on:POLARSSL_RIPEMD160_C
 md_text:"ripemd160":"a":"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"
 
-ripemd160 Test vector from paper #3
+generic ripemd160 Test vector from paper #3
 depends_on:POLARSSL_RIPEMD160_C
 md_text:"ripemd160":"abc":"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
 
-ripemd160 Test vector from paper #4
+generic ripemd160 Test vector from paper #4
 depends_on:POLARSSL_RIPEMD160_C
 md_text:"ripemd160":"message digest":"5d0689ef49d2fae572b881b123a85ffa21595f36"
 
-ripemd160 Test vector from paper #5
+generic ripemd160 Test vector from paper #5
 depends_on:POLARSSL_RIPEMD160_C
 md_text:"ripemd160":"abcdefghijklmnopqrstuvwxyz":"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"
 
-ripemd160 Test vector from paper #6
+generic ripemd160 Test vector from paper #6
 depends_on:POLARSSL_RIPEMD160_C
 md_text:"ripemd160":"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq":"12a053384a9c0c88e405a06c27dcf49ada62eb2b"
 
-ripemd160 Test vector from paper #7
+generic ripemd160 Test vector from paper #7
 depends_on:POLARSSL_RIPEMD160_C
 md_text:"ripemd160":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789":"b0e20b6e3116640286ed3a87a5713079b21f5189"
 
-ripemd160 Test vector from paper #8
+generic ripemd160 Test vector from paper #8
 depends_on:POLARSSL_RIPEMD160_C
 md_text:"ripemd160":"12345678901234567890123456789012345678901234567890123456789012345678901234567890":"9b752e45573d4b39f4dbd3323cab82bf63326bfb"
 
@@ -178,31 +217,31 @@
 depends_on:POLARSSL_MD5_C
 md_hmac:"md5":16:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d53697a652044617461":"6f630fad67cda0ee1fb1f562db3aa53e"
 
-HMAC-RIPEMD160 Test vector RFC 2286 #1
+generic HMAC-RIPEMD160 Test vector RFC 2286 #1
 depends_on:POLARSSL_RIPEMD160_C
 md_hmac:"ripemd160":20:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"4869205468657265":"24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668"
 
-HMAC-RIPEMD160 Test vector RFC 2286 #2
+generic HMAC-RIPEMD160 Test vector RFC 2286 #2
 depends_on:POLARSSL_RIPEMD160_C
 md_hmac:"ripemd160":20:"4a656665":"7768617420646f2079612077616e7420666f72206e6f7468696e673f":"dda6c0213a485a9e24f4742064a7f033b43c4069"
 
-HMAC-RIPEMD160 Test vector RFC 2286 #3
+generic HMAC-RIPEMD160 Test vector RFC 2286 #3
 depends_on:POLARSSL_RIPEMD160_C
 md_hmac:"ripemd160":20:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd":"b0b105360de759960ab4f35298e116e295d8e7c1"
 
-HMAC-RIPEMD160 Test vector RFC 2286 #4
+generic HMAC-RIPEMD160 Test vector RFC 2286 #4
 depends_on:POLARSSL_RIPEMD160_C
 md_hmac:"ripemd160":20:"0102030405060708090a0b0c0d0e0f10111213141516171819":"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd":"d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4"
 
-HMAC-RIPEMD160 Test vector RFC 2286 #5
+generic HMAC-RIPEMD160 Test vector RFC 2286 #5
 depends_on:POLARSSL_RIPEMD160_C
 md_hmac:"ripemd160":20:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":"546573742057697468205472756e636174696f6e":"7619693978f91d90539ae786500ff3d8e0518e39"
 
-HMAC-RIPEMD160 Test vector RFC 2286 #6
+generic HMAC-RIPEMD160 Test vector RFC 2286 #6
 depends_on:POLARSSL_RIPEMD160_C
 md_hmac:"ripemd160":20:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374":"6466ca07ac5eac29e1bd523e5ada7605b791fd8b"
 
-HMAC-RIPEMD160 Test vector RFC 2286 #7
+generic HMAC-RIPEMD160 Test vector RFC 2286 #7
 depends_on:POLARSSL_RIPEMD160_C
 md_hmac:"ripemd160":20:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d53697a652044617461":"69ea60798d71616cce5fd0871e23754cd75d5a0a"
 
@@ -290,6 +329,38 @@
 depends_on:POLARSSL_MD5_C
 md_text_multi:"md5":"12345678901234567890123456789012345678901234567890123456789012345678901234567890":"57edf4a22be3c955ac49da2e2107b67a"
 
+generic multi step ripemd160 Test vector from paper #1
+depends_on:POLARSSL_RIPEMD160_C
+md_text_multi:"ripemd160":"":"9c1185a5c5e9fc54612808977ee8f548b2258d31"
+
+generic multi step ripemd160 Test vector from paper #2
+depends_on:POLARSSL_RIPEMD160_C
+md_text_multi:"ripemd160":"a":"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"
+
+generic multi step ripemd160 Test vector from paper #3
+depends_on:POLARSSL_RIPEMD160_C
+md_text_multi:"ripemd160":"abc":"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
+
+generic multi step ripemd160 Test vector from paper #4
+depends_on:POLARSSL_RIPEMD160_C
+md_text_multi:"ripemd160":"message digest":"5d0689ef49d2fae572b881b123a85ffa21595f36"
+
+generic multi step ripemd160 Test vector from paper #5
+depends_on:POLARSSL_RIPEMD160_C
+md_text_multi:"ripemd160":"abcdefghijklmnopqrstuvwxyz":"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"
+
+generic multi step ripemd160 Test vector from paper #6
+depends_on:POLARSSL_RIPEMD160_C
+md_text_multi:"ripemd160":"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq":"12a053384a9c0c88e405a06c27dcf49ada62eb2b"
+
+generic multi step ripemd160 Test vector from paper #7
+depends_on:POLARSSL_RIPEMD160_C
+md_text_multi:"ripemd160":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789":"b0e20b6e3116640286ed3a87a5713079b21f5189"
+
+generic multi step ripemd160 Test vector from paper #8
+depends_on:POLARSSL_RIPEMD160_C
+md_text_multi:"ripemd160":"12345678901234567890123456789012345678901234567890123456789012345678901234567890":"9b752e45573d4b39f4dbd3323cab82bf63326bfb"
+
 generic multi step HMAC-MD2 Hash File OpenSSL test #1
 depends_on:POLARSSL_MD2_C
 md_hmac_multi:"md2":16:"61616161616161616161616161616161":"b91ce5ac77d33c234e61002ed6":"d5732582f494f5ddf35efd166c85af9c"
@@ -354,6 +425,34 @@
 depends_on:POLARSSL_MD5_C
 md_hmac_multi:"md5":16:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d53697a652044617461":"6f630fad67cda0ee1fb1f562db3aa53e"
 
+generic multi step HMAC-RIPEMD160 Test vector RFC 2286 #1
+depends_on:POLARSSL_RIPEMD160_C
+md_hmac_multi:"ripemd160":20:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"4869205468657265":"24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668"
+
+generic multi step HMAC-RIPEMD160 Test vector RFC 2286 #2
+depends_on:POLARSSL_RIPEMD160_C
+md_hmac_multi:"ripemd160":20:"4a656665":"7768617420646f2079612077616e7420666f72206e6f7468696e673f":"dda6c0213a485a9e24f4742064a7f033b43c4069"
+
+generic multi step HMAC-RIPEMD160 Test vector RFC 2286 #3
+depends_on:POLARSSL_RIPEMD160_C
+md_hmac_multi:"ripemd160":20:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd":"b0b105360de759960ab4f35298e116e295d8e7c1"
+
+generic multi step HMAC-RIPEMD160 Test vector RFC 2286 #4
+depends_on:POLARSSL_RIPEMD160_C
+md_hmac_multi:"ripemd160":20:"0102030405060708090a0b0c0d0e0f10111213141516171819":"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd":"d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4"
+
+generic multi step HMAC-RIPEMD160 Test vector RFC 2286 #5
+depends_on:POLARSSL_RIPEMD160_C
+md_hmac_multi:"ripemd160":20:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":"546573742057697468205472756e636174696f6e":"7619693978f91d90539ae786500ff3d8e0518e39"
+
+generic multi step HMAC-RIPEMD160 Test vector RFC 2286 #6
+depends_on:POLARSSL_RIPEMD160_C
+md_hmac_multi:"ripemd160":20:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374":"6466ca07ac5eac29e1bd523e5ada7605b791fd8b"
+
+generic multi step HMAC-RIPEMD160 Test vector RFC 2286 #7
+depends_on:POLARSSL_RIPEMD160_C
+md_hmac_multi:"ripemd160":20:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d53697a652044617461":"69ea60798d71616cce5fd0871e23754cd75d5a0a"
+
 generic MD2 Hash file #1
 depends_on:POLARSSL_MD2_C
 md_file:"md2":"data_files/hash_file_1":"b593c098712d2e21628c8986695451a8"
@@ -402,6 +501,26 @@
 depends_on:POLARSSL_MD5_C
 md_file:"md5":"data_files/hash_file_4":"d41d8cd98f00b204e9800998ecf8427e"
 
+generic RIPEMD160 Hash file #0 (from paper)
+depends_on:POLARSSL_RIPEMD160_C
+md_file:"ripemd160":"data_files/hash_file_5":"52783243c1697bdbe16d37f97f68f08325dc1528"
+
+generic RIPEMD160 Hash file #1
+depends_on:POLARSSL_RIPEMD160_C
+md_file:"ripemd160":"data_files/hash_file_1":"82f1d072f0ec0c2b353703a7b575a04c113af1a6"
+
+generic RIPEMD160 Hash file #2
+depends_on:POLARSSL_RIPEMD160_C
+md_file:"ripemd160":"data_files/hash_file_2":"996fbc8b79206ba7393ebcd246584069b1c08f0f"
+
+generic RIPEMD160 Hash file #3
+depends_on:POLARSSL_RIPEMD160_C
+md_file:"ripemd160":"data_files/hash_file_3":"8653b46d65998fa8c8846efa17937e742533ae48"
+
+generic RIPEMD160 Hash file #4
+depends_on:POLARSSL_RIPEMD160_C
+md_file:"ripemd160":"data_files/hash_file_4":"9c1185a5c5e9fc54612808977ee8f548b2258d31"
+
 generic HMAC-SHA-1 Test Vector FIPS-198a #1
 depends_on:POLARSSL_SHA1_C
 md_hmac:"sha1":20:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":"53616d706c65202331":"4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0a"
@@ -1010,26 +1129,6 @@
 depends_on:POLARSSL_SHA512_C
 md_hex_multi:"sha512":"990d1ae71a62d7bda9bfdaa1762a68d296eee72a4cd946f287a898fbabc002ea941fd8d4d991030b4d27a637cce501a834bb95eab1b7889a3e784c7968e67cbf552006b206b68f76d9191327524fcc251aeb56af483d10b4e0c6c5e599ee8c0fe4faeca8293844a8547c6a9a90d093f2526873a19ad4a5e776794c68c742fb834793d2dfcb7fea46c63af4b70fd11cb6e41834e72ee40edb067b292a794990c288d5007e73f349fb383af6a756b8301ad6e5e0aa8cd614399bb3a452376b1575afa6bdaeaafc286cb064bb91edef97c632b6c1113d107fa93a0905098a105043c2f05397f702514439a08a9e5ddc196100721d45c8fc17d2ed659376f8a00bd5cb9a0860e26d8a29d8d6aaf52de97e9346033d6db501a35dbbaf97c20b830cd2d18c2532f3a59cc497ee64c0e57d8d060e5069b28d86edf1adcf59144b221ce3ddaef134b3124fbc7dd000240eff0f5f5f41e83cd7f5bb37c9ae21953fe302b0f6e8b68fa91c6ab99265c64b2fd9cd4942be04321bb5d6d71932376c6f2f88e02422ba6a5e2cb765df93fd5dd0728c6abdaf03bce22e0678a544e2c3636f741b6f4447ee58a8fc656b43ef817932176adbfc2e04b2c812c273cd6cbfa4098f0be036a34221fa02643f5ee2e0b38135f2a18ecd2f16ebc45f8eb31b8ab967a1567ee016904188910861ca1fa205c7adaa194b286893ffe2f4fbe0384c2aef72a4522aeafd3ebc71f9db71eeeef86c48394a1c86d5b36c352cc33a0a2c800bc99e62fd65b3a2fd69e0b53996ec13d8ce483ce9319efd9a85acefabdb5342226febb83fd1daf4b24265f50c61c6de74077ef89b6fecf9f29a1f871af1e9f89b2d345cda7499bd45c42fa5d195a1e1a6ba84851889e730da3b2b916e96152ae0c92154b49719841db7e7cc707ba8a5d7b101eb4ac7b629bb327817910fff61580b59aab78182d1a2e33473d05b00b170b29e331870826cfe45af206aa7d0246bbd8566ca7cfb2d3c10bfa1db7dd48dd786036469ce7282093d78b5e1a5b0fc81a54c8ed4ceac1e5305305e78284ac276f5d7862727aff246e17addde50c670028d572cbfc0be2e4f8b2eb28fa68ad7b4c6c2a239c460441bfb5ea049f23b08563b4e47729a59e5986a61a6093dbd54f8c36ebe87edae01f251cb060ad1364ce677d7e8d5a4a4ca966a7241cc360bc2acb280e5f9e9c1b032ad6a180a35e0c5180b9d16d026c865b252098cc1d99ba7375ca31c7702c0d943d5e3dd2f6861fa55bd46d94b67ed3e52eccd8dd06d968e01897d6de97ed3058d91dd":"8e4bc6f8b8c60fe4d68c61d9b159c8693c3151c46749af58da228442d927f23359bd6ccd6c2ec8fa3f00a86cecbfa728e1ad60b821ed22fcd309ba91a4138bc9"
 
-RIPEMD160 Hash file #0 (from paper)
-depends_on:POLARSSL_RIPEMD160_C
-md_file:"ripemd160":"data_files/hash_file_5":"52783243c1697bdbe16d37f97f68f08325dc1528"
-
-RIPEMD160 Hash file #1
-depends_on:POLARSSL_RIPEMD160_C
-md_file:"ripemd160":"data_files/hash_file_1":"82f1d072f0ec0c2b353703a7b575a04c113af1a6"
-
-RIPEMD160 Hash file #2
-depends_on:POLARSSL_RIPEMD160_C
-md_file:"ripemd160":"data_files/hash_file_2":"996fbc8b79206ba7393ebcd246584069b1c08f0f"
-
-RIPEMD160 Hash file #3
-depends_on:POLARSSL_RIPEMD160_C
-md_file:"ripemd160":"data_files/hash_file_3":"8653b46d65998fa8c8846efa17937e742533ae48"
-
-RIPEMD160 Hash file #4
-depends_on:POLARSSL_RIPEMD160_C
-md_file:"ripemd160":"data_files/hash_file_4":"9c1185a5c5e9fc54612808977ee8f548b2258d31"
-
 generic SHA1 Hash file #1
 depends_on:POLARSSL_SHA1_C
 md_file:"sha1":"data_files/hash_file_1":"d21c965b1e768bd7a6aa6869f5f821901d255f9f"
diff --git a/tests/suites/test_suite_md.function b/tests/suites/test_suite_md.function
index c972cc2..4b5921f 100644
--- a/tests/suites/test_suite_md.function
+++ b/tests/suites/test_suite_md.function
@@ -8,6 +8,55 @@
  */
 
 /* BEGIN_CASE */
+void md_process( )
+{
+    const int *md_type_ptr;
+    const md_info_t *info;
+    md_context_t ctx;
+    unsigned char buf[150];
+
+    memset( &ctx, 0, sizeof ctx );
+
+    /*
+     * Very minimal testing of md_process, just make sure the various
+     * xxx_process_wrap() function pointers are valid. (Testing that they
+     * indeed do the right thing whould require messing with the internal
+     * state of the underlying md/sha context.)
+     *
+     * Also tests that md_list() only returns valid MDs.
+     */
+    for( md_type_ptr = md_list(); *md_type_ptr != 0; md_type_ptr++ )
+    {
+        TEST_ASSERT( ( info = md_info_from_type( *md_type_ptr ) ) != NULL );
+        TEST_ASSERT( md_init_ctx( &ctx, info ) == 0 );
+        TEST_ASSERT( md_process( &ctx, buf ) == 0 );
+        TEST_ASSERT( md_free_ctx( &ctx ) == 0 );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void md_info( int md_type, char *md_name, int md_size )
+{
+    const md_info_t *md_info;
+    const int *md_type_ptr;
+    int found;
+
+    TEST_ASSERT( ( md_info = md_info_from_type( md_type ) ) != NULL );
+    TEST_ASSERT( md_info == md_info_from_string( md_name ) );
+
+    TEST_ASSERT( md_get_type( md_info ) == (md_type_t) md_type );
+    TEST_ASSERT( md_get_size( md_info ) == (unsigned char) md_size );
+
+    found = 0;
+    for( md_type_ptr = md_list(); *md_type_ptr != 0; md_type_ptr++ )
+        if( *md_type_ptr == md_type )
+            found = 1;
+    TEST_ASSERT( found == 1 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void md_text( char *text_md_name, char *text_src_string, char *hex_hash_string )
 {
     char md_name[100];
@@ -197,11 +246,23 @@
     TEST_ASSERT ( ctx.md_ctx != NULL );
     TEST_ASSERT ( 0 == md_hmac_update( &ctx, src_str, src_len ) );
     TEST_ASSERT ( 0 == md_hmac_finish( &ctx, output ) );
+
+    hexify( hash_str, output, md_get_size(md_info) );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Test again, for reset() */
+    memset(hash_str, 0x00, 10000);
+    memset(output, 0x00, 100);
+
+    TEST_ASSERT ( 0 == md_hmac_reset( &ctx ) );
+    TEST_ASSERT ( 0 == md_hmac_update( &ctx, src_str, src_len ) );
+    TEST_ASSERT ( 0 == md_hmac_finish( &ctx, output ) );
     TEST_ASSERT ( 0 == md_free_ctx( &ctx ) );
 
     hexify( hash_str, output, md_get_size(md_info) );
-
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    TEST_ASSERT ( 0 == md_free_ctx( &ctx ) );
 }
 /* END_CASE */
 
diff --git a/tests/suites/test_suite_mdx.function b/tests/suites/test_suite_mdx.function
index 6b21b2d..0676d82 100644
--- a/tests/suites/test_suite_mdx.function
+++ b/tests/suites/test_suite_mdx.function
@@ -94,18 +94,48 @@
     unsigned char hash_str[33];
     unsigned char output[16];
     int key_len, src_len;
+    md2_context ctx;
 
     memset( src_str, 0x00, sizeof src_str );
     memset( key_str, 0x00, sizeof key_str );
-    memset( hash_str, 0x00, sizeof hash_str );
-    memset( output, 0x00, sizeof output );
 
     key_len = unhexify( key_str, hex_key_string );
     src_len = unhexify( src_str, hex_src_string );
 
-    md2_hmac( key_str, key_len, src_str, src_len, output );
-    hexify( hash_str, output, sizeof  output );
+    /* Test the all-in-one interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
 
+    md2_hmac( key_str, key_len, src_str, src_len, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Also test the "streaming" interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+    memset( &ctx, 0x00, sizeof ctx );
+
+    md2_hmac_starts( &ctx, key_str, key_len );
+    md2_hmac_update( &ctx, src_str, 0 );
+    md2_hmac_update( &ctx, src_str, src_len / 2 );
+    md2_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    md2_hmac_update( &ctx, src_str + src_len, 0 );
+    md2_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Again, to test hmac_reset() */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+
+    md2_hmac_reset( &ctx );
+    md2_hmac_update( &ctx, src_str, src_len / 2 );
+    md2_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    md2_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
 }
 /* END_CASE */
@@ -119,18 +149,48 @@
     unsigned char hash_str[33];
     unsigned char output[16];
     int key_len, src_len;
+    md4_context ctx;
 
     memset( src_str, 0x00, sizeof src_str );
     memset( key_str, 0x00, sizeof key_str );
-    memset( hash_str, 0x00, sizeof hash_str );
-    memset( output, 0x00, sizeof output );
 
     key_len = unhexify( key_str, hex_key_string );
     src_len = unhexify( src_str, hex_src_string );
 
-    md4_hmac( key_str, key_len, src_str, src_len, output );
-    hexify( hash_str, output, sizeof  output );
+    /* Test the all-in-one interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
 
+    md4_hmac( key_str, key_len, src_str, src_len, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Also test the "streaming" interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+    memset( &ctx, 0x00, sizeof ctx );
+
+    md4_hmac_starts( &ctx, key_str, key_len );
+    md4_hmac_update( &ctx, src_str, 0 );
+    md4_hmac_update( &ctx, src_str, src_len / 2 );
+    md4_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    md4_hmac_update( &ctx, src_str + src_len, 0 );
+    md4_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Again, to test hmac_reset() */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+
+    md4_hmac_reset( &ctx );
+    md4_hmac_update( &ctx, src_str, src_len / 2 );
+    md4_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    md4_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
 }
 /* END_CASE */
@@ -144,18 +204,48 @@
     unsigned char hash_str[33];
     unsigned char output[16];
     int key_len, src_len;
+    md5_context ctx;
 
     memset( src_str, 0x00, sizeof src_str );
     memset( key_str, 0x00, sizeof key_str );
-    memset( hash_str, 0x00, sizeof hash_str );
-    memset( output, 0x00, sizeof output );
 
     key_len = unhexify( key_str, hex_key_string );
     src_len = unhexify( src_str, hex_src_string );
 
-    md5_hmac( key_str, key_len, src_str, src_len, output );
-    hexify( hash_str, output, sizeof  output );
+    /* Test the all-in-one interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
 
+    md5_hmac( key_str, key_len, src_str, src_len, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Also test the "streaming" interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+    memset( &ctx, 0x00, sizeof ctx );
+
+    md5_hmac_starts( &ctx, key_str, key_len );
+    md5_hmac_update( &ctx, src_str, 0 );
+    md5_hmac_update( &ctx, src_str, src_len / 2 );
+    md5_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    md5_hmac_update( &ctx, src_str + src_len, 0 );
+    md5_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Again, to test hmac_reset() */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+
+    md5_hmac_reset( &ctx );
+    md5_hmac_update( &ctx, src_str, src_len / 2 );
+    md5_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    md5_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
 }
 /* END_CASE */
@@ -169,18 +259,48 @@
     unsigned char hash_str[41];
     unsigned char output[20];
     int key_len, src_len;
+    ripemd160_context ctx;
 
     memset( src_str, 0x00, sizeof src_str );
     memset( key_str, 0x00, sizeof key_str );
-    memset( hash_str, 0x00, sizeof hash_str );
-    memset( output, 0x00, sizeof output );
 
     key_len = unhexify( key_str, hex_key_string );
     src_len = unhexify( src_str, hex_src_string );
 
-    ripemd160_hmac( key_str, key_len, src_str, src_len, output );
-    hexify( hash_str, output, sizeof  output );
+    /* Test the all-in-one interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
 
+    ripemd160_hmac( key_str, key_len, src_str, src_len, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Also test the "streaming" interface */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+    memset( &ctx, 0x00, sizeof ctx );
+
+    ripemd160_hmac_starts( &ctx, key_str, key_len );
+    ripemd160_hmac_update( &ctx, src_str, 0 );
+    ripemd160_hmac_update( &ctx, src_str, src_len / 2 );
+    ripemd160_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    ripemd160_hmac_update( &ctx, src_str + src_len, 0 );
+    ripemd160_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
+    TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
+
+    /* Again, to test hmac_reset() */
+    memset( hash_str, 0x00, sizeof hash_str );
+    memset( output, 0x00, sizeof output );
+
+    ripemd160_hmac_reset( &ctx );
+    ripemd160_hmac_update( &ctx, src_str, src_len / 2 );
+    ripemd160_hmac_update( &ctx, src_str + src_len / 2, src_len - src_len / 2 );
+    ripemd160_hmac_finish( &ctx, output );
+
+    hexify( hash_str, output, sizeof  output );
     TEST_ASSERT( strncmp( (char *) hash_str, hex_hash_string, trunc_size * 2 ) == 0 );
 }
 /* END_CASE */
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index e07495a..974748c 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -77,3 +77,7 @@
 ECDSA nocrypt
 depends_on:POLARSSL_ECDSA_C
 pk_ec_nocrypt:POLARSSL_PK_ECDSA
+
+RSA_ALT consistency
+depends_on:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_GENPRIME
+pk_rsa_alt:
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 85cdb74..f82ed67 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -3,13 +3,16 @@
 
 static int rnd_std_rand( void *rng_state, unsigned char *output, size_t len );
 
+#define RSA_KEY_SIZE 512
+#define RSA_KEY_LEN   64
+
 static int pk_genkey( pk_context *pk )
 {
     ((void) pk);
 
 #if defined(POLARSSL_RSA_C) && defined(POLARSSL_GENPRIME)
     if( pk_get_type( pk ) == POLARSSL_PK_RSA )
-        return rsa_gen_key( pk_rsa( *pk ), rnd_std_rand, NULL, 512, 3 );
+        return rsa_gen_key( pk_rsa( *pk ), rnd_std_rand, NULL, RSA_KEY_SIZE, 3 );
 #endif
 #if defined(POLARSSL_ECP_C)
     if( pk_get_type( pk ) == POLARSSL_PK_ECKEY ||
@@ -27,6 +30,28 @@
 #endif
     return( -1 );
 }
+
+#if defined(POLARSSL_RSA_C)
+int rsa_decrypt_func( void *ctx, int mode, size_t *olen,
+                       const unsigned char *input, unsigned char *output,
+                       size_t output_max_len )
+{
+    return( rsa_pkcs1_decrypt( (rsa_context *) ctx, NULL, NULL, mode, olen,
+                               input, output, output_max_len ) );
+}
+int rsa_sign_func( void *ctx,
+                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                   int mode, md_type_t md_alg, unsigned int hashlen,
+                   const unsigned char *hash, unsigned char *sig )
+{
+    return( rsa_pkcs1_sign( (rsa_context *) ctx, f_rng, p_rng, mode,
+                            md_alg, hashlen, hash, sig ) );
+}
+size_t rsa_key_len_func( void *ctx )
+{
+    return( ((const rsa_context *) ctx)->len );
+}
+#endif /* POLARSSL_RSA_C */
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -282,3 +307,77 @@
     pk_free( &pk );
 }
 /* END_CASE */
+
+/* BEGIN_CASE depends_on:POLARSSL_RSA_C */
+void pk_rsa_alt( )
+{
+    /*
+     * An rsa_alt context can only do private operations (decrypt, sign).
+     * Test it against the public operations (encrypt, verify) of a
+     * corresponding rsa context.
+     */
+    rsa_context raw;
+    pk_context rsa, alt;
+    pk_debug_item dbg_items[10];
+    unsigned char hash[50], sig[1000];
+    unsigned char msg[50], ciph[1000], test[1000];
+    size_t sig_len, ciph_len, test_len;
+    int ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+
+    rsa_init( &raw, RSA_PKCS_V15, POLARSSL_MD_NONE );
+    pk_init( &rsa ); pk_init( &alt );
+
+    memset( hash, 0x2a, sizeof hash );
+    memset( sig, 0, sizeof sig );
+    memset( msg, 0x2a, sizeof msg );
+    memset( ciph, 0, sizeof ciph );
+    memset( test, 0, sizeof test );
+
+    /* Initiliaze PK RSA context with random key */
+    TEST_ASSERT( pk_init_ctx( &rsa,
+                              pk_info_from_type( POLARSSL_PK_RSA ) ) == 0 );
+    TEST_ASSERT( pk_genkey( &rsa ) == 0 );
+
+    /* Extract key to the raw rsa context */
+    TEST_ASSERT( rsa_copy( &raw, pk_rsa( rsa ) ) == 0 );
+
+    /* Initialize PK RSA_ALT context */
+    TEST_ASSERT( pk_init_ctx_rsa_alt( &alt, (void *) &raw,
+                 rsa_decrypt_func, rsa_sign_func, rsa_key_len_func ) == 0 );
+
+    /* Test administrative functions */
+    TEST_ASSERT( pk_can_do( &alt, POLARSSL_PK_RSA ) );
+    TEST_ASSERT( pk_get_size( &alt ) == RSA_KEY_SIZE );
+    TEST_ASSERT( pk_get_len( &alt ) == RSA_KEY_LEN );
+    TEST_ASSERT( pk_get_type( &alt ) == POLARSSL_PK_RSA_ALT );
+    TEST_ASSERT( strcmp( pk_get_name( &alt ), "RSA-alt" ) == 0 );
+
+    /* Test signature */
+    TEST_ASSERT( pk_sign( &alt, POLARSSL_MD_NONE, hash, sizeof hash,
+                          sig, &sig_len, rnd_std_rand, NULL ) == 0 );
+    TEST_ASSERT( sig_len == RSA_KEY_LEN );
+    TEST_ASSERT( pk_verify( &rsa, POLARSSL_MD_NONE,
+                            hash, sizeof hash, sig, sig_len ) == 0 );
+
+    /* Test decrypt */
+    TEST_ASSERT( pk_encrypt( &rsa, msg, sizeof msg,
+                             ciph, &ciph_len, sizeof ciph,
+                             rnd_std_rand, NULL ) == 0 );
+    TEST_ASSERT( pk_decrypt( &alt, ciph, ciph_len,
+                             test, &test_len, sizeof test,
+                             rnd_std_rand, NULL ) == 0 );
+    TEST_ASSERT( test_len == sizeof msg );
+    TEST_ASSERT( memcmp( test, msg, test_len ) == 0 );
+
+    /* Test forbidden operations */
+    TEST_ASSERT( pk_encrypt( &alt, msg, sizeof msg,
+                             ciph, &ciph_len, sizeof ciph,
+                             rnd_std_rand, NULL ) == ret );
+    TEST_ASSERT( pk_verify( &alt, POLARSSL_MD_NONE,
+                            hash, sizeof hash, sig, sig_len ) == ret );
+    TEST_ASSERT( pk_debug( &alt, dbg_items ) == ret );
+
+    rsa_free( &raw );
+    pk_free( &rsa ); pk_free( &alt );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 03caa74..ef9a331 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -802,3 +802,27 @@
 X509 CRT parse path #4 (two certs, one non-cert)
 depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_SHA256_C:POLARSSL_ECDSA_C:POLARSSL_ECP_DP_SECP384R1_ENABLED
 x509_crt_parse_path:"data_files/dir3":1:2
+
+X509 OID description #1
+x509_oid_desc:"2B06010505070301":"TLS Web Server Authentication"
+
+X509 OID description #2
+x509_oid_desc:"2B0601050507030f":"notfound"
+
+X509 OID description #3
+x509_oid_desc:"2B0601050507030100":"notfound"
+
+X509 OID numstring #1 (wide buffer)
+x509_oid_numstr:"2B06010505070301":"1.3.6.1.5.5.7.3.1":20:17
+
+X509 OID numstring #2 (buffer just fits)
+x509_oid_numstr:"2B06010505070301":"1.3.6.1.5.5.7.3.1":18:17
+
+X509 OID numstring #3 (buffer too small)
+x509_oid_numstr:"2B06010505070301":"1.3.6.1.5.5.7.3.1":17:POLARSSL_ERR_OID_BUF_TOO_SMALL
+
+X509 OID numstring #4 (larger number)
+x509_oid_numstr:"2A864886F70D":"1.2.840.113549":15:14
+
+X509 OID numstring #5 (arithmetic overflow)
+x509_oid_numstr:"2A8648F9F8F7F6F5F4F3F2F1F001":"":100:POLARSSL_ERR_OID_BUF_TOO_SMALL
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index 8638235..effa4cc 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -265,6 +265,57 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void x509_oid_desc( char *oid_str, char *ref_desc )
+{
+    x509_buf oid;
+    const char *desc;
+    unsigned char buf[20];
+
+    memset( buf, 0, sizeof buf );
+
+    oid.tag = ASN1_OID;
+    oid.len = unhexify( buf, oid_str );
+    oid.p   = buf;
+
+    desc = x509_oid_get_description( &oid );
+
+    if( strcmp( ref_desc, "notfound" ) == 0 )
+        TEST_ASSERT( desc == NULL );
+    else
+    {
+        TEST_ASSERT( desc != NULL );
+        TEST_ASSERT( strcmp( desc, ref_desc ) == 0 );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void x509_oid_numstr( char *oid_str, char *numstr, int blen, int ret )
+{
+    x509_buf oid;
+    unsigned char oid_buf[20];
+    char num_buf[100];
+
+    memset( oid_buf, 0x00, sizeof oid_buf );
+    memset( num_buf, 0x2a, sizeof num_buf );
+
+    oid.tag = ASN1_OID;
+    oid.len = unhexify( oid_buf, oid_str );
+    oid.p   = oid_buf;
+
+    TEST_ASSERT( (size_t) blen <= sizeof num_buf );
+
+    TEST_ASSERT( x509_oid_get_numeric_string( num_buf, blen, &oid ) == ret );
+
+    if( ret >= 0 )
+    {
+        TEST_ASSERT( num_buf[ret] == 0 );
+        TEST_ASSERT( strcmp( num_buf, numstr ) == 0 );
+    }
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:POLARSSL_X509_CRT_PARSE_C:POLARSSL_SELF_TEST */
 void x509_selftest()
 {
diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data
index 1b2754e..04a24de 100644
--- a/tests/suites/test_suite_x509write.data
+++ b/tests/suites/test_suite_x509write.data
@@ -1,31 +1,59 @@
 Certificate Request check Server1 SHA1
 depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
-x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA1:"data_files/server1.req.sha1"
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha1":POLARSSL_MD_SHA1:0:0
 
 Certificate Request check Server1 SHA224
 depends_on:POLARSSL_SHA256_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
-x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA224:"data_files/server1.req.sha224"
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha224":POLARSSL_MD_SHA224:0:0
 
 Certificate Request check Server1 SHA256
 depends_on:POLARSSL_SHA256_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
-x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA256:"data_files/server1.req.sha256"
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha256":POLARSSL_MD_SHA256:0:0
 
 Certificate Request check Server1 SHA384
 depends_on:POLARSSL_SHA512_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
-x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA384:"data_files/server1.req.sha384"
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha384":POLARSSL_MD_SHA384:0:0
 
 Certificate Request check Server1 SHA512
 depends_on:POLARSSL_SHA512_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
-x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA512:"data_files/server1.req.sha512"
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.sha512":POLARSSL_MD_SHA512:0:0
 
 Certificate Request check Server1 MD4
 depends_on:POLARSSL_MD4_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
-x509_csr_check:"data_files/server1.key":POLARSSL_MD_MD4:"data_files/server1.req.md4"
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.md4":POLARSSL_MD_MD4:0:0
 
 Certificate Request check Server1 MD5
 depends_on:POLARSSL_MD5_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
-x509_csr_check:"data_files/server1.key":POLARSSL_MD_MD5:"data_files/server1.req.md5"
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.md5":POLARSSL_MD_MD5:0:0
+
+Certificate Request check Server1 key_usage
+depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.key_usage":POLARSSL_MD_SHA1:KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION | KU_KEY_ENCIPHERMENT:0
+
+Certificate Request check Server1 ns_cert_type
+depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.cert_type":POLARSSL_MD_SHA1:0:NS_CERT_TYPE_SSL_SERVER
+
+Certificate Request check Server1 key_usage + ns_cert_type
+depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
+x509_csr_check:"data_files/server1.key":"data_files/server1.req.ku-ct":POLARSSL_MD_SHA1:KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION | KU_KEY_ENCIPHERMENT:NS_CERT_TYPE_SSL_SERVER
+
+Certificate Request check Server5 ECDSA, key_usage
+depends_on:POLARSSL_SHA1_C:POLARSSL_ECDSA_C:POLARSSL_ECDSA_DETERMINISTIC
+x509_csr_check:"data_files/server5.key":"data_files/server5.req.ku.sha1":POLARSSL_MD_SHA1:KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION:0
 
 Certificate write check Server1 SHA1
 depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_DES_C:POLARSSL_CIPHER_MODE_CBC:POLARSSL_MD5_C
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":POLARSSL_MD_SHA1:"data_files/server1.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":POLARSSL_MD_SHA1:0:0:-1:"data_files/server1.crt"
+
+Certificate write check Server1 SHA1, key_usage
+depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_DES_C:POLARSSL_CIPHER_MODE_CBC:POLARSSL_MD5_C
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":POLARSSL_MD_SHA1:KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION | KU_KEY_ENCIPHERMENT:0:-1:"data_files/server1.key_usage.crt"
+
+Certificate write check Server1 SHA1, ns_cert_type
+depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_DES_C:POLARSSL_CIPHER_MODE_CBC:POLARSSL_MD5_C
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":POLARSSL_MD_SHA1:0:NS_CERT_TYPE_SSL_SERVER:-1:"data_files/server1.cert_type.crt"
+
+Certificate write check Server1 SHA1, version 1
+depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_DES_C:POLARSSL_CIPHER_MODE_CBC:POLARSSL_MD5_C
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":POLARSSL_MD_SHA1:0:0:X509_CRT_VERSION_1:"data_files/server1.v1.crt"
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index ca097e7..0cea5f9 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -11,8 +11,8 @@
  */
 
 /* BEGIN_CASE depends_on:POLARSSL_PEM_WRITE_C:POLARSSL_X509_CSR_WRITE_C */
-void x509_csr_check( char *key_file, int md_type,
-                          char *cert_req_check_file )
+void x509_csr_check( char *key_file, char *cert_req_check_file,
+                     int md_type, int key_usage, int cert_type )
 {
     pk_context key;
     x509write_csr req;
@@ -33,6 +33,10 @@
     x509write_csr_set_md_alg( &req, md_type );
     x509write_csr_set_key( &req, &key );
     TEST_ASSERT( x509write_csr_set_subject_name( &req, subject_name ) == 0 );
+    if( key_usage != 0 )
+        TEST_ASSERT( x509write_csr_set_key_usage( &req, key_usage ) == 0 );
+    if( cert_type != 0 )
+        TEST_ASSERT( x509write_csr_set_ns_cert_type( &req, cert_type ) == 0 );
 
     ret = x509write_csr_pem( &req, buf, sizeof(buf),
                              rnd_pseudo_rand, &rnd_info );
@@ -58,7 +62,8 @@
                      char *subject_name, char *issuer_key_file,
                      char *issuer_pwd, char *issuer_name,
                      char *serial_str, char *not_before, char *not_after,
-                     int md_type, char *cert_check_file )
+                     int md_type, int key_usage, int cert_type, int ver,
+                     char *cert_check_file )
 {
     pk_context subject_key, issuer_key;
     x509write_cert crt;
@@ -82,7 +87,9 @@
     TEST_ASSERT( mpi_read_string( &serial, 10, serial_str ) == 0 );
 
     x509write_crt_init( &crt );
-    x509write_crt_set_serial( &crt, &serial );
+    if( ver != -1 )
+        x509write_crt_set_version( &crt, ver );
+    TEST_ASSERT( x509write_crt_set_serial( &crt, &serial ) == 0 );
     TEST_ASSERT( x509write_crt_set_validity( &crt, not_before,
                                                    not_after ) == 0 );
     x509write_crt_set_md_alg( &crt, md_type );
@@ -91,9 +98,16 @@
     x509write_crt_set_subject_key( &crt, &subject_key );
     x509write_crt_set_issuer_key( &crt, &issuer_key );
 
-    TEST_ASSERT( x509write_crt_set_basic_constraints( &crt, 0, 0 ) == 0 );
-    TEST_ASSERT( x509write_crt_set_subject_key_identifier( &crt ) == 0 );
-    TEST_ASSERT( x509write_crt_set_authority_key_identifier( &crt ) == 0 );
+    if( crt.version >= X509_CRT_VERSION_3 )
+    {
+        TEST_ASSERT( x509write_crt_set_basic_constraints( &crt, 0, 0 ) == 0 );
+        TEST_ASSERT( x509write_crt_set_subject_key_identifier( &crt ) == 0 );
+        TEST_ASSERT( x509write_crt_set_authority_key_identifier( &crt ) == 0 );
+        if( key_usage != 0 )
+            TEST_ASSERT( x509write_crt_set_key_usage( &crt, key_usage ) == 0 );
+        if( cert_type != 0 )
+            TEST_ASSERT( x509write_crt_set_ns_cert_type( &crt, cert_type ) == 0 );
+    }
 
     ret = x509write_crt_pem( &crt, buf, sizeof(buf),
                              rnd_pseudo_rand, &rnd_info );