Merge parsing and verification of RSASSA-PSS in X.509 modules
diff --git a/ChangeLog b/ChangeLog
index 5716b16..67332bf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,12 +11,20 @@
* Support for parsing and verifying RSASSA-PSS signatures in the X.509
modules (certificates, CRLs and CSRs).
+Changes
+ * Add LINK_WITH_PTHREAD option in CMake for explicit linking that is
+ required on some platforms (e.g. OpenBSD)
+
Bugfix
* Fix in debug_print_msg()
* Enforce alignment in the buffer allocator even if buffer is not aligned
* Remove less-than-zero checks on unsigned numbers
* Stricter check on SSL ClientHello internal sizes compared to actual packet
size (found by TrustInSoft)
+ * Fix WSAStartup() return value check (found by Peter Vaskovic)
+ * Other minor issues (found by Peter Vaskovic)
+ * Fix symlink command for cross compiling with CMake (found by Andre
+ Heinecke)
= PolarSSL 1.3.7 released on 2014-05-02
Features
diff --git a/include/polarssl/dhm.h b/include/polarssl/dhm.h
index 628cd62..c6c2d8f 100644
--- a/include/polarssl/dhm.h
+++ b/include/polarssl/dhm.h
@@ -43,6 +43,8 @@
#define POLARSSL_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read/write of file failed. */
/**
+ * RFC 2409 defines a number of standardized Diffie-Hellman groups
+ * that can be used.
* RFC 3526 defines a number of standardized Diffie-Hellman groups
* for IKE.
* RFC 5114 defines a number of standardized Diffie-Hellman groups
@@ -51,11 +53,22 @@
* Some are included here for convenience.
*
* Included are:
+ * RFC 2409 6.2. 1024-bit MODP Group (Second Oakley Group)
* RFC 3526 3. 2048-bit MODP Group
* RFC 3526 4. 3072-bit MODP Group
* RFC 5114 2.1. 1024-bit MODP Group with 160-bit Prime Order Subgroup
* RFC 5114 2.2. 2048-bit MODP Group with 224-bit Prime Order Subgroup
*/
+#define POLARSSL_DHM_RFC2409_MODP_1024_P \
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
+ "FFFFFFFFFFFFFFFF"
+
+#define POLARSSL_DHM_RFC2409_MODP_1024_G "02"
+
#define POLARSSL_DHM_RFC3526_MODP_2048_P \
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
diff --git a/include/polarssl/entropy.h b/include/polarssl/entropy.h
index 55b262f..f5fa928 100644
--- a/include/polarssl/entropy.h
+++ b/include/polarssl/entropy.h
@@ -183,7 +183,7 @@
*
* \param data Entropy context
* \param output Buffer to fill
- * \param len Length of buffer
+ * \param len Number of bytes desired, must be at most ENTROPY_BLOCK_SIZE
*
* \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED
*/
@@ -230,6 +230,15 @@
int entropy_update_seed_file( entropy_context *ctx, const char *path );
#endif /* POLARSSL_FS_IO */
+#if defined(POLARSSL_SELF_TEST)
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if a test failed
+ */
+int entropy_self_test( int verbose );
+#endif /* POLARSSL_SELF_TEST */
+
#ifdef __cplusplus
}
#endif
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 4cbd162..2e202de 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -1,5 +1,6 @@
option(USE_STATIC_POLARSSL_LIBRARY "Build PolarSSL static library." ON)
option(USE_SHARED_POLARSSL_LIBRARY "Build PolarSSL shared library." OFF)
+option(LINK_WITH_PTHREAD "Explicitly link PolarSSL library to pthread." OFF)
set(src
aes.c
@@ -102,6 +103,9 @@
target_link_libraries(${polarssl_static_target} ${ZLIB_LIBRARIES})
endif(ZLIB_FOUND)
+ if(LINK_WITH_PTHREAD)
+ target_link_libraries(${polarssl_static_target} pthread)
+ endif()
install(TARGETS ${polarssl_static_target}
DESTINATION ${LIB_INSTALL_DIR}
@@ -118,6 +122,10 @@
target_link_libraries(polarssl ${ZLIB_LIBRARIES})
endif(ZLIB_FOUND)
+ if(LINK_WITH_PTHREAD)
+ target_link_libraries(polarssl pthread)
+ endif()
+
install(TARGETS polarssl
DESTINATION ${LIB_INSTALL_DIR}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
diff --git a/library/aes.c b/library/aes.c
index ca5c906..c03cbbe 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -565,10 +565,6 @@
RK[15] = RK[7] ^ RK[14];
}
break;
-
- default:
-
- break;
}
return( 0 );
@@ -586,14 +582,6 @@
uint32_t *SK;
int ret;
- switch( keysize )
- {
- case 128: ctx->nr = 10; break;
- case 192: ctx->nr = 12; break;
- case 256: ctx->nr = 14; break;
- default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
- }
-
#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)
if( aes_padlock_ace == -1 )
aes_padlock_ace = padlock_supports( PADLOCK_ACE );
@@ -604,10 +592,12 @@
#endif
ctx->rk = RK = ctx->buf;
- ret = aes_setkey_enc( &cty, key, keysize );
- if( ret != 0 )
+ /* Also checks keysize */
+ if( ( ret = aes_setkey_enc( &cty, key, keysize ) ) != 0 )
return( ret );
+ ctx->nr = cty.nr;
+
#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
if( aesni_supports( POLARSSL_AESNI_AES ) )
{
diff --git a/library/camellia.c b/library/camellia.c
index 524e6ff..306be61 100644
--- a/library/camellia.c
+++ b/library/camellia.c
@@ -435,20 +435,14 @@
uint32_t *SK;
int ret;
- switch( keysize )
- {
- case 128: ctx->nr = 3; idx = 0; break;
- case 192:
- case 256: ctx->nr = 4; idx = 1; break;
- default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
- }
-
- RK = ctx->rk;
-
- ret = camellia_setkey_enc(&cty, key, keysize);
- if( ret != 0 )
+ /* Also checks keysize */
+ if( ( ret = camellia_setkey_enc(&cty, key, keysize) ) )
return( ret );
+ ctx->nr = cty.nr;
+ idx = ( ctx->nr == 4 );
+
+ RK = ctx->rk;
SK = cty.rk + 24 * 2 + 8 * idx * 2;
*RK++ = *SK++;
diff --git a/library/debug.c b/library/debug.c
index f2dd776..b747ddc 100644
--- a/library/debug.c
+++ b/library/debug.c
@@ -131,7 +131,7 @@
if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
- snprintf( str + idx, maxlen - idx, "dumping '%s' (%d bytes)\n",
+ snprintf( str + idx, maxlen - idx, "dumping '%s' (%u bytes)\n",
text, (unsigned int) len );
str[maxlen] = '\0';
diff --git a/library/des.c b/library/des.c
index 79c81bc..2f06af3 100644
--- a/library/des.c
+++ b/library/des.c
@@ -837,15 +837,12 @@
int i, j, u, v;
des_context ctx;
des3_context ctx3;
- unsigned char key[24];
unsigned char buf[8];
#if defined(POLARSSL_CIPHER_MODE_CBC)
unsigned char prv[8];
unsigned char iv[8];
#endif
- memset( key, 0, 24 );
-
/*
* ECB mode
*/
diff --git a/library/entropy.c b/library/entropy.c
index b500491..c01acf3 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -372,4 +372,97 @@
}
#endif /* POLARSSL_FS_IO */
+#if defined(POLARSSL_SELF_TEST)
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/*
+ * Dummy source function
+ */
+static int entropy_dummy_source( void *data, unsigned char *output,
+ size_t len, size_t *olen )
+{
+ ((void) data);
+
+ memset( output, 0x2a, len );
+ *olen = len;
+
+ return( 0 );
+}
+
+/*
+ * The actual entropy quality is hard to test, but we can at least
+ * test that the functions don't cause errors and write the correct
+ * amount of data to buffers.
+ */
+int entropy_self_test( int verbose )
+{
+ int ret = 0;
+ entropy_context ctx;
+ unsigned char buf[ENTROPY_BLOCK_SIZE] = { 0 };
+ unsigned char acc[ENTROPY_BLOCK_SIZE] = { 0 };
+ size_t i, j;
+
+ if( verbose != 0 )
+ polarssl_printf( " ENTROPY test: " );
+
+ entropy_init( &ctx );
+
+ ret = entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 );
+ if( ret != 0 )
+ goto cleanup;
+
+ if( ( ret = entropy_gather( &ctx ) ) != 0 )
+ goto cleanup;
+
+ if( ( ret = entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
+ goto cleanup;
+
+ /*
+ * To test that entropy_func writes correct number of bytes:
+ * - use the whole buffer and rely on ASan to detect overruns
+ * - collect entropy 8 times and OR the result in an accumulator:
+ * any byte should then be 0 with probably 2^(-64), so requiring
+ * each of the 32 or 64 bytes to be non-zero has a false failure rate
+ * of at most 2^(-58) which is acceptable.
+ */
+ for( i = 0; i < 8; i++ )
+ {
+ if( ( ret = entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
+ goto cleanup;
+
+ for( j = 0; j < sizeof( buf ); j++ )
+ acc[j] |= buf[j];
+ }
+
+ for( j = 0; j < sizeof( buf ); j++ )
+ {
+ if( acc[j] == 0 )
+ {
+ ret = 1;
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ entropy_free( &ctx );
+
+ if( verbose != 0 )
+ {
+ if( ret != 0 )
+ polarssl_printf( "failed\n" );
+ else
+ polarssl_printf( "passed\n" );
+
+ polarssl_printf( "\n" );
+ }
+
+ return( ret != 0 );
+}
+#endif /* POLARSSL_SELF_TEST */
+
#endif /* POLARSSL_ENTROPY_C */
diff --git a/library/gcm.c b/library/gcm.c
index a892076..62fe185 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -195,7 +195,6 @@
unsigned char output[16] )
{
int i = 0;
- unsigned char z[16];
unsigned char lo, hi, rem;
uint64_t zh, zl;
@@ -213,8 +212,6 @@
}
#endif /* POLARSSL_AESNI_C && POLARSSL_HAVE_X86_64 */
- memset( z, 0x00, 16 );
-
lo = x[15] & 0xf;
hi = x[15] >> 4;
diff --git a/library/net.c b/library/net.c
index be30fbd..0866149 100644
--- a/library/net.c
+++ b/library/net.c
@@ -146,7 +146,7 @@
if( wsa_init_done == 0 )
{
- if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
+ if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
return( POLARSSL_ERR_NET_SOCKET_FAILED );
wsa_init_done = 1;
diff --git a/library/pem.c b/library/pem.c
index 2775ef9..3dd3b79 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -370,11 +370,8 @@
void pem_free( pem_context *ctx )
{
- if( ctx->buf )
- polarssl_free( ctx->buf );
-
- if( ctx->info )
- polarssl_free( ctx->info );
+ polarssl_free( ctx->buf );
+ polarssl_free( ctx->info );
memset( ctx, 0, sizeof( pem_context ) );
}
diff --git a/library/ssl_cache.c b/library/ssl_cache.c
index 9e49b9a..836b685 100644
--- a/library/ssl_cache.c
+++ b/library/ssl_cache.c
@@ -321,8 +321,7 @@
ssl_session_free( &prv->session );
#if defined(POLARSSL_X509_CRT_PARSE_C)
- if( prv->peer_cert.p != NULL )
- polarssl_free( prv->peer_cert.p );
+ polarssl_free( prv->peer_cert.p );
#endif /* POLARSSL_X509_CRT_PARSE_C */
polarssl_free( prv );
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 5152895..53b3179 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -691,7 +691,7 @@
static int ssl_parse_alpn_ext( ssl_context *ssl,
unsigned char *buf, size_t len )
{
- size_t list_len, cur_len;
+ size_t list_len, cur_len, ours_len;
const unsigned char *theirs, *start, *end;
const char **ours;
@@ -722,6 +722,7 @@
end = buf + len;
for( ours = ssl->alpn_list; *ours != NULL; ours++ )
{
+ ours_len = strlen( *ours );
for( theirs = start; theirs != end; theirs += cur_len )
{
/* If the list is well formed, we should get equality first */
@@ -734,7 +735,7 @@
if( cur_len == 0 )
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
- if( cur_len == strlen( *ours ) &&
+ if( cur_len == ours_len &&
memcmp( theirs, *ours, cur_len ) == 0 )
{
ssl->alpn_chosen = *ours;
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 8c29e21..2cd0cce 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -97,7 +97,7 @@
x509_crt_init( dst->peer_cert );
if( ( ret = x509_crt_parse( dst->peer_cert, src->peer_cert->raw.p,
- src->peer_cert->raw.len ) != 0 ) )
+ src->peer_cert->raw.len ) ) != 0 )
{
polarssl_free( dst->peer_cert );
dst->peer_cert = NULL;
@@ -1070,8 +1070,7 @@
if( ssl->out_msglen != olen )
{
- SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
- ssl->out_msglen, olen ) );
+ SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
}
}
@@ -1146,8 +1145,7 @@
if( olen != enc_msglen )
{
- SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
- enc_msglen, olen ) );
+ SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
}
@@ -1225,8 +1223,7 @@
if( enc_msglen != olen )
{
- SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
- enc_msglen, olen ) );
+ SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
}
@@ -1308,7 +1305,7 @@
if( ssl->in_msglen != olen )
{
- SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
+ SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
}
}
@@ -1372,8 +1369,7 @@
if( olen != dec_msglen )
{
- SSL_DEBUG_MSG( 1, ( "total decrypted length incorrect %d %d",
- dec_msglen, olen ) );
+ SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
}
}
@@ -1448,7 +1444,7 @@
if( dec_msglen != olen )
{
- SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
+ SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
}
diff --git a/library/timing.c b/library/timing.c
index 4b29d7e..fe741b9 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -337,6 +337,25 @@
#endif
/*
+ * Busy-waits for the given number of milliseconds.
+ * Used for testing hardclock.
+ */
+static void busy_msleep( unsigned long msec )
+{
+ struct hr_time hires;
+ unsigned long i = 0; /* for busy-waiting */
+ volatile unsigned long j; /* to prevent optimisation */
+
+ (void) get_timer( &hires, 1 );
+
+ while( get_timer( &hires, 0 ) < msec )
+ i++;
+
+ j = i;
+ (void) j;
+}
+
+/*
* Checkup routine
*
* Warning: this is work in progress, some tests may not be reliable enough
@@ -350,7 +369,7 @@
struct hr_time hires;
if( verbose != 0)
- polarssl_printf( " TIMING tests warning: will take some time!\n" );
+ polarssl_printf( " TIMING tests note: will take some time!\n" );
if( verbose != 0 )
polarssl_printf( " TIMING test #1 (m_sleep / get_timer): " );
@@ -401,7 +420,7 @@
polarssl_printf( "passed\n" );
if( verbose != 0 )
- polarssl_printf( " TIMING test #3 (hardclock / m_sleep ): " );
+ polarssl_printf( " TIMING test #3 (hardclock / get_timer): " );
/*
* Allow one failure for possible counter wrapping.
@@ -420,15 +439,17 @@
}
/* Get a reference ratio cycles/ms */
+ millisecs = 1;
cycles = hardclock();
- m_sleep( 1 );
+ busy_msleep( millisecs );
cycles = hardclock() - cycles;
- ratio = cycles / 1;
+ ratio = cycles / millisecs;
+ /* Check that the ratio is mostly constant */
for( millisecs = 2; millisecs <= 4; millisecs++ )
{
cycles = hardclock();
- m_sleep( millisecs );
+ busy_msleep( millisecs );
cycles = hardclock() - cycles;
/* Allow variation up to 20% */
@@ -443,9 +464,6 @@
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): " );
@@ -471,6 +489,9 @@
polarssl_printf( "passed\n" );
#endif /* POLARSSL_NET_C */
+ if( verbose != 0 )
+ polarssl_printf( "\n" );
+
return( 0 );
}
diff --git a/library/x509_crt.c b/library/x509_crt.c
index fa09596..0f41f40 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1554,12 +1554,12 @@
static int x509_wildcard_verify( const char *cn, x509_buf *name )
{
size_t i;
- size_t cn_idx = 0;
+ size_t cn_idx = 0, cn_len = strlen( cn );
if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
return( 0 );
- for( i = 0; i < strlen( cn ); ++i )
+ for( i = 0; i < cn_len; ++i )
{
if( cn[i] == '.' )
{
@@ -1571,7 +1571,7 @@
if( cn_idx == 0 )
return( 0 );
- if( strlen( cn ) - cn_idx == name->len - 1 &&
+ if( cn_len - cn_idx == name->len - 1 &&
x509_name_cmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
{
return( 1 );
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 06e4a16..8db6ddb 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -458,11 +458,9 @@
opt.psk_identity = q;
else if( strcmp( p, "force_ciphersuite" ) == 0 )
{
- opt.force_ciphersuite[0] = -1;
-
opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );
- if( opt.force_ciphersuite[0] <= 0 )
+ if( opt.force_ciphersuite[0] == 0 )
{
ret = 2;
goto usage;
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 2b6e426..9f53ad2 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -77,7 +77,9 @@
#define DFL_KEY_FILE2 ""
#define DFL_PSK ""
#define DFL_PSK_IDENTITY "Client_identity"
+#define DFL_PSK_LIST NULL
#define DFL_FORCE_CIPHER 0
+#define DFL_VERSION_SUITES NULL
#define DFL_RENEGOTIATION SSL_RENEGOTIATION_DISABLED
#define DFL_ALLOW_LEGACY SSL_LEGACY_NO_RENEGOTIATION
#define DFL_RENEGOTIATE 0
@@ -91,6 +93,7 @@
#define DFL_CACHE_TIMEOUT -1
#define DFL_SNI NULL
#define DFL_ALPN_STRING NULL
+#define DFL_DHM_FILE NULL
#define LONG_RESPONSE "<p>01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
"02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
@@ -107,6 +110,16 @@
"<h2>PolarSSL Test Server</h2>\r\n" \
"<p>Successful connection using: %s</p>\r\n" // LONG_RESPONSE
+#define MAX_PSK_LEN 256
+
+/*
+ * Size of the basic I/O buffer. Able to hold our default response.
+ *
+ * You will need to adapt the ssl_get_bytes_avail() test in ssl-opt.sh
+ * if you change this value to something outside the range <= 100 or > 500
+ */
+#define IO_BUF_LEN 200
+
/*
* global options
*/
@@ -124,7 +137,9 @@
const char *key_file2; /* the file with the 2nd server key */
const char *psk; /* the pre-shared key */
const char *psk_identity; /* the pre-shared key identity */
+ char *psk_list; /* list of PSK id/key pairs for callback */
int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
+ const char *version_suites; /* per-version ciphersuites */
int renegotiation; /* enable / disable renegotiation */
int allow_legacy; /* allow legacy renegotiation */
int renegotiate; /* attempt renegotiation? */
@@ -138,6 +153,7 @@
int cache_timeout; /* expiration delay of session cache entries */
char *sni; /* string describing sni information */
const char *alpn_string; /* ALPN supported protocols */
+ const char *dhm_file; /* the file with the DH parameters */
} opt;
static void my_debug( void *ctx, int level, const char *str )
@@ -200,7 +216,9 @@
" default: see note after key_file2\n" \
" key_file2=%%s default: see note below\n" \
" note: if neither crt_file/key_file nor crt_file2/key_file2 are used,\n" \
- " preloaded certificate(s) and key(s) are used if available\n"
+ " preloaded certificate(s) and key(s) are used if available\n" \
+ " dhm_file=%%s File containing Diffie-Hellman parameters\n" \
+ " default: preloaded parameters\n"
#else
#define USAGE_IO \
"\n" \
@@ -286,9 +304,12 @@
" min_version=%%s default: \"ssl3\"\n" \
" max_version=%%s default: \"tls1_2\"\n" \
" force_version=%%s default: \"\" (none)\n" \
- " options: ssl3, tls1, tls1_1, tls1_2\n" \
- "\n" \
- " force_ciphersuite=<name> default: all enabled\n"\
+ " options: ssl3, tls1, tls1_1, tls1_2\n" \
+ "\n" \
+ " version_suites=a,b,c,d per-version ciphersuites\n" \
+ " in order from ssl3 to tls1_2\n" \
+ " default: all enabled\n" \
+ " force_ciphersuite=<name> default: all enabled\n" \
" acceptable ciphersuite names:\n"
#if !defined(POLARSSL_ENTROPY_C) || \
@@ -306,6 +327,16 @@
}
#else
+/*
+ * Used by sni_parse and psk_parse to handle coma-separated lists
+ */
+#define GET_ITEM( dst ) \
+ dst = p; \
+ while( *p != ',' ) \
+ if( ++p > end ) \
+ return( NULL ); \
+ *p++ = '\0';
+
#if defined(POLARSSL_SNI)
typedef struct _sni_entry sni_entry;
@@ -320,8 +351,8 @@
* Parse a string of triplets name1,crt1,key1[,name2,crt2,key2[,...]]
* into a usable sni_entry list.
*
- * Note: this is not production quality: leaks memory if parsing fails,
- * and error reporting is poor.
+ * Modifies the input string! This is not production quality!
+ * (leaks memory if parsing fails, no error reporting, ...)
*/
sni_entry *sni_parse( char *sni_string )
{
@@ -343,44 +374,21 @@
if( ( new->cert = polarssl_malloc( sizeof( x509_crt ) ) ) == NULL ||
( new->key = polarssl_malloc( sizeof( pk_context ) ) ) == NULL )
- {
- cur = NULL;
- goto exit;
- }
+ return( NULL );
x509_crt_init( new->cert );
pk_init( new->key );
- new->name = p;
- while( *p != ',' ) if( ++p > end ) { cur = NULL; goto exit; }
- *p++ = '\0';
-
- crt_file = p;
- while( *p != ',' ) if( ++p > end ) { cur = NULL; goto exit; }
- *p++ = '\0';
-
- key_file = p;
- while( *p != ',' ) if( ++p > end ) { cur = NULL; goto exit; }
- *p++ = '\0';
+ GET_ITEM( new->name );
+ GET_ITEM( crt_file );
+ GET_ITEM( key_file );
if( x509_crt_parse_file( new->cert, crt_file ) != 0 ||
pk_parse_keyfile( new->key, key_file, "" ) != 0 )
- {
- cur = NULL;
- goto exit;
- }
+ return( NULL );
new->next = cur;
cur = new;
- new = NULL;
- }
-
-exit:
- if( new != NULL )
- {
- x509_crt_free( new->cert);
- pk_free( new->key );
- polarssl_free( new );
}
return( cur );
@@ -429,15 +437,144 @@
#endif /* POLARSSL_SNI */
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+
+#define HEX2NUM( c ) \
+ if( c >= '0' && c <= '9' ) \
+ c -= '0'; \
+ else if( c >= 'a' && c <= 'f' ) \
+ c -= 'a' - 10; \
+ else if( c >= 'A' && c <= 'F' ) \
+ c -= 'A' - 10; \
+ else \
+ return( -1 );
+
+/*
+ * Convert a hex string to bytes.
+ * Return 0 on success, -1 on error.
+ */
+int unhexify( unsigned char *output, const char *input, size_t *olen )
+{
+ unsigned char c;
+ size_t j;
+
+ *olen = strlen( input );
+ if( *olen % 2 != 0 || *olen / 2 > MAX_PSK_LEN )
+ return( -1 );
+ *olen /= 2;
+
+ for( j = 0; j < *olen * 2; j += 2 )
+ {
+ c = input[j];
+ HEX2NUM( c );
+ output[ j / 2 ] = c << 4;
+
+ c = input[j + 1];
+ HEX2NUM( c );
+ output[ j / 2 ] |= c;
+ }
+
+ return( 0 );
+}
+
+typedef struct _psk_entry psk_entry;
+
+struct _psk_entry
+{
+ const char *name;
+ size_t key_len;
+ unsigned char key[MAX_PSK_LEN];
+ psk_entry *next;
+};
+
+/*
+ * Parse a string of pairs name1,key1[,name2,key2[,...]]
+ * into a usable psk_entry list.
+ *
+ * Modifies the input string! This is not production quality!
+ * (leaks memory if parsing fails, no error reporting, ...)
+ */
+psk_entry *psk_parse( char *psk_string )
+{
+ psk_entry *cur = NULL, *new = NULL;
+ char *p = psk_string;
+ char *end = p;
+ char *key_hex;
+
+ while( *end != '\0' )
+ ++end;
+ *end = ',';
+
+ while( p <= end )
+ {
+ if( ( new = polarssl_malloc( sizeof( psk_entry ) ) ) == NULL )
+ return( NULL );
+
+ memset( new, 0, sizeof( psk_entry ) );
+
+ GET_ITEM( new->name );
+ GET_ITEM( key_hex );
+
+ if( unhexify( new->key, key_hex, &new->key_len ) != 0 )
+ return( NULL );
+
+ new->next = cur;
+ cur = new;
+ }
+
+ return( cur );
+}
+
+/*
+ * Free a list of psk_entry's
+ */
+void psk_free( psk_entry *head )
+{
+ psk_entry *next;
+
+ while( head != NULL )
+ {
+ next = head->next;
+ polarssl_free( head );
+ head = next;
+ }
+}
+
+/*
+ * PSK callback
+ */
+int psk_callback( void *p_info, ssl_context *ssl,
+ const unsigned char *name, size_t name_len )
+{
+ psk_entry *cur = (psk_entry *) p_info;
+
+ while( cur != NULL )
+ {
+ if( name_len == strlen( cur->name ) &&
+ memcmp( name, cur->name, name_len ) == 0 )
+ {
+ return( ssl_set_psk( ssl, cur->key, cur->key_len,
+ name, name_len ) );
+ }
+
+ cur = cur->next;
+ }
+
+ return( -1 );
+}
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
+
int main( int argc, char *argv[] )
{
int ret = 0, len, written, frags;
int listen_fd;
int client_fd = -1;
- unsigned char buf[SSL_MAX_CONTENT_LEN + 1];
+ int version_suites[4][2];
+ unsigned char buf[IO_BUF_LEN];
#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
- unsigned char psk[256];
+ unsigned char psk[MAX_PSK_LEN];
size_t psk_len = 0;
+ psk_entry *psk_info;
#endif
const char *pers = "ssl_server2";
@@ -452,6 +589,9 @@
pk_context pkey2;
int key_cert_init = 0, key_cert_init2 = 0;
#endif
+#if defined(POLARSSL_DHM_C) && defined(POLARSSL_FS_IO)
+ dhm_context dhm;
+#endif
#if defined(POLARSSL_SSL_CACHE_C)
ssl_cache_context cache;
#endif
@@ -485,6 +625,9 @@
x509_crt_init( &srvcert2 );
pk_init( &pkey2 );
#endif
+#if defined(POLARSSL_DHM_C) && defined(POLARSSL_FS_IO)
+ memset( &dhm, 0, sizeof( dhm_context ) );
+#endif
#if defined(POLARSSL_SSL_CACHE_C)
ssl_cache_init( &cache );
#endif
@@ -526,7 +669,9 @@
opt.key_file2 = DFL_KEY_FILE2;
opt.psk = DFL_PSK;
opt.psk_identity = DFL_PSK_IDENTITY;
+ opt.psk_list = DFL_PSK_LIST;
opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
+ opt.version_suites = DFL_VERSION_SUITES;
opt.renegotiation = DFL_RENEGOTIATION;
opt.allow_legacy = DFL_ALLOW_LEGACY;
opt.renegotiate = DFL_RENEGOTIATE;
@@ -540,6 +685,7 @@
opt.cache_timeout = DFL_CACHE_TIMEOUT;
opt.sni = DFL_SNI;
opt.alpn_string = DFL_ALPN_STRING;
+ opt.dhm_file = DFL_DHM_FILE;
for( i = 1; i < argc; i++ )
{
@@ -580,23 +726,27 @@
opt.crt_file2 = q;
else if( strcmp( p, "key_file2" ) == 0 )
opt.key_file2 = q;
+ else if( strcmp( p, "dhm_file" ) == 0 )
+ opt.dhm_file = q;
else if( strcmp( p, "psk" ) == 0 )
opt.psk = q;
else if( strcmp( p, "psk_identity" ) == 0 )
opt.psk_identity = q;
+ else if( strcmp( p, "psk_list" ) == 0 )
+ opt.psk_list = q;
else if( strcmp( p, "force_ciphersuite" ) == 0 )
{
- opt.force_ciphersuite[0] = -1;
-
opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );
- if( opt.force_ciphersuite[0] <= 0 )
+ if( opt.force_ciphersuite[0] == 0 )
{
ret = 2;
goto usage;
}
opt.force_ciphersuite[1] = 0;
}
+ else if( strcmp( p, "version_suites" ) == 0 )
+ opt.version_suites = q;
else if( strcmp( p, "renegotiation" ) == 0 )
{
opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED :
@@ -754,52 +904,63 @@
opt.min_version = ciphersuite_info->min_minor_ver;
}
-#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
- /*
- * Unhexify the pre-shared key if any is given
- */
- if( strlen( opt.psk ) )
+ if( opt.version_suites != NULL )
{
- unsigned char c;
- size_t j;
+ const char *name[4] = { 0 };
- if( strlen( opt.psk ) % 2 != 0 )
+ /* Parse 4-element coma-separated list */
+ for( i = 0, p = (char *) opt.version_suites;
+ i < 4 && *p != '\0';
+ i++ )
{
- printf("pre-shared key not valid hex\n");
+ name[i] = p;
+
+ /* Terminate the current string and move on to next one */
+ while( *p != ',' && *p != '\0' )
+ p++;
+ if( *p == ',' )
+ *p++ = '\0';
+ }
+
+ if( i != 4 )
+ {
+ printf( "too few values for version_suites\n" );
+ ret = 1;
goto exit;
}
- psk_len = strlen( opt.psk ) / 2;
+ memset( version_suites, 0, sizeof( version_suites ) );
- for( j = 0; j < strlen( opt.psk ); j += 2 )
+ /* Get the suites identifiers from their name */
+ for( i = 0; i < 4; i++ )
{
- c = opt.psk[j];
- if( c >= '0' && c <= '9' )
- c -= '0';
- else if( c >= 'a' && c <= 'f' )
- c -= 'a' - 10;
- else if( c >= 'A' && c <= 'F' )
- c -= 'A' - 10;
- else
- {
- printf("pre-shared key not valid hex\n");
- goto exit;
- }
- psk[ j / 2 ] = c << 4;
+ version_suites[i][0] = ssl_get_ciphersuite_id( name[i] );
- c = opt.psk[j + 1];
- if( c >= '0' && c <= '9' )
- c -= '0';
- else if( c >= 'a' && c <= 'f' )
- c -= 'a' - 10;
- else if( c >= 'A' && c <= 'F' )
- c -= 'A' - 10;
- else
+ if( version_suites[i][0] == 0 )
{
- printf("pre-shared key not valid hex\n");
- goto exit;
+ printf( "unknown ciphersuite: '%s'\n", name[i] );
+ ret = 2;
+ goto usage;
}
- psk[ j / 2 ] |= c;
+ }
+ }
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+ /*
+ * Unhexify the pre-shared key and parse the list if any given
+ */
+ if( unhexify( psk, opt.psk, &psk_len ) != 0 )
+ {
+ printf( "pre-shared key not valid hex\n" );
+ goto exit;
+ }
+
+ if( opt.psk_list != NULL )
+ {
+ if( ( psk_info = psk_parse( opt.psk_list ) ) == NULL )
+ {
+ printf( "psk_list invalid" );
+ goto exit;
}
}
#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
@@ -988,6 +1149,23 @@
printf( " ok\n" );
#endif /* POLARSSL_X509_CRT_PARSE_C */
+#if defined(POLARSSL_DHM_C) && defined(POLARSSL_FS_IO)
+ if( opt.dhm_file != NULL )
+ {
+ printf( " . Loading DHM parameters..." );
+ fflush( stdout );
+
+ if( ( ret = dhm_parse_dhmfile( &dhm, opt.dhm_file ) ) != 0 )
+ {
+ printf( " failed\n ! dhm_parse_dhmfile returned -0x%04X\n\n",
+ -ret );
+ goto exit;
+ }
+
+ printf( " ok\n" );
+ }
+#endif
+
#if defined(POLARSSL_SNI)
if( opt.sni != NULL )
{
@@ -1067,6 +1245,22 @@
if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );
+ if( opt.version_suites != NULL )
+ {
+ ssl_set_ciphersuites_for_version( &ssl, version_suites[0],
+ SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_0 );
+ ssl_set_ciphersuites_for_version( &ssl, version_suites[1],
+ SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_1 );
+ ssl_set_ciphersuites_for_version( &ssl, version_suites[2],
+ SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_2 );
+ ssl_set_ciphersuites_for_version( &ssl, version_suites[3],
+ SSL_MAJOR_VERSION_3,
+ SSL_MINOR_VERSION_3 );
+ }
+
ssl_set_renegotiation( &ssl, opt.renegotiation );
ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
@@ -1088,16 +1282,39 @@
#endif
#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
- ssl_set_psk( &ssl, psk, psk_len, (const unsigned char *) opt.psk_identity,
- strlen( opt.psk_identity ) );
+ if( strlen( opt.psk ) != 0 && strlen( opt.psk_identity ) != 0 )
+ {
+ ret = ssl_set_psk( &ssl, psk, psk_len,
+ (const unsigned char *) opt.psk_identity,
+ strlen( opt.psk_identity ) );
+ if( ret != 0 )
+ {
+ printf( " failed\n ssl_set_psk returned -0x%04X\n\n", - ret );
+ goto exit;
+ }
+ }
+
+ if( opt.psk_list != NULL )
+ ssl_set_psk_cb( &ssl, psk_callback, psk_info );
#endif
#if defined(POLARSSL_DHM_C)
/*
* Use different group than default DHM group
*/
- ssl_set_dh_param( &ssl, POLARSSL_DHM_RFC5114_MODP_2048_P,
- POLARSSL_DHM_RFC5114_MODP_2048_G );
+#if defined(POLARSSL_FS_IO)
+ if( opt.dhm_file != NULL )
+ ret = ssl_set_dh_param_ctx( &ssl, &dhm );
+ else
+#endif
+ ret = ssl_set_dh_param( &ssl, POLARSSL_DHM_RFC5114_MODP_2048_P,
+ POLARSSL_DHM_RFC5114_MODP_2048_G );
+
+ if( ret != 0 )
+ {
+ printf( " failed\n ssl_set_dh_param returned -0x%04X\n\n", - ret );
+ goto exit;
+ }
#endif
if( opt.min_version != -1 )
@@ -1252,9 +1469,48 @@
break;
}
- len = ret;
- buf[len] = '\0';
- printf( " %d bytes read\n\n%s\n", len, (char *) buf );
+ if( ssl_get_bytes_avail( &ssl ) == 0 )
+ {
+ len = ret;
+ buf[len] = '\0';
+ printf( " %d bytes read\n\n%s\n", len, (char *) buf );
+ }
+ else
+ {
+ int extra_len, ori_len;
+ unsigned char *larger_buf;
+
+ ori_len = ret;
+ extra_len = ssl_get_bytes_avail( &ssl );
+
+ larger_buf = polarssl_malloc( ori_len + extra_len + 1 );
+ if( larger_buf == NULL )
+ {
+ printf( " ! memory allocation failed\n" );
+ ret = 1;
+ goto exit;
+ }
+
+ memset( larger_buf, 0, ori_len + extra_len );
+ memcpy( larger_buf, buf, ori_len );
+
+ /* This read should never fail and get the whole cached data */
+ ret = ssl_read( &ssl, larger_buf + ori_len, extra_len );
+ if( ret != extra_len ||
+ ssl_get_bytes_avail( &ssl ) != 0 )
+ {
+ printf( " ! ssl_read failed on cached data\n" );
+ ret = 1;
+ goto exit;
+ }
+
+ larger_buf[ori_len + extra_len] = '\0';
+ printf( " %u bytes read (%u + %u)\n\n%s\n",
+ ori_len + extra_len, ori_len, extra_len, (char *) buf );
+
+ polarssl_free( larger_buf );
+ }
+
if( memcmp( buf, "SERVERQUIT", 10 ) == 0 )
{
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 07e2b12..0210a19 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -32,6 +32,7 @@
#include <string.h>
#include <stdio.h>
+#include "polarssl/entropy.h"
#include "polarssl/hmac_drbg.h"
#include "polarssl/ctr_drbg.h"
#include "polarssl/dhm.h"
@@ -193,6 +194,11 @@
return( ret );
#endif
+#if defined(POLARSSL_ENTROPY_C)
+ if( ( ret = entropy_self_test( v ) ) != 0 )
+ return( ret );
+#endif
+
/* Slow tests last */
#if defined(POLARSSL_PBKDF2_C)
@@ -205,10 +211,7 @@
#endif
#endif
-/*
- * Not reliable enough yet
- */
-#if 0 && defined(POLARSSL_TIMING_C)
+#if defined(POLARSSL_TIMING_C)
if( ( ret = timing_self_test( v ) ) != 0 )
return( ret );
#endif
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index 72618e6..e558da2 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -65,6 +65,7 @@
#define DFL_MODE MODE_NONE
#define DFL_FILENAME "cert.crt"
#define DFL_CA_FILE ""
+#define DFL_CRL_FILE ""
#define DFL_CA_PATH ""
#define DFL_SERVER_NAME "localhost"
#define DFL_SERVER_PORT 4433
@@ -79,6 +80,7 @@
int mode; /* the mode to run the application in */
const char *filename; /* filename of the certificate file */
const char *ca_file; /* the file with the CA certificate(s) */
+ const char *crl_file; /* the file with the CRL to use */
const char *ca_path; /* the path with the CA certificate(s) reside */
const char *server_name; /* hostname of the server (client only) */
int server_port; /* port on which the ssl service runs */
@@ -134,6 +136,8 @@
#define USAGE_IO \
" ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \
" default: \"\" (none)\n" \
+ " crl_file=%%s The single CRL file you want to use\n" \
+ " default: \"\" (none)\n" \
" ca_path=%%s The path containing the top-level CA(s) you fully trust\n" \
" default: \"\" (none) (overrides ca_file)\n"
@@ -158,6 +162,7 @@
ssl_context ssl;
x509_crt cacert;
x509_crt clicert;
+ x509_crl cacrl;
pk_context pkey;
int i, j;
int flags, verify = 0;
@@ -170,6 +175,7 @@
server_fd = 0;
x509_crt_init( &cacert );
x509_crt_init( &clicert );
+ x509_crl_init( &cacrl );
pk_init( &pkey );
if( argc == 0 )
@@ -182,6 +188,7 @@
opt.mode = DFL_MODE;
opt.filename = DFL_FILENAME;
opt.ca_file = DFL_CA_FILE;
+ opt.crl_file = DFL_CRL_FILE;
opt.ca_path = DFL_CA_PATH;
opt.server_name = DFL_SERVER_NAME;
opt.server_port = DFL_SERVER_PORT;
@@ -214,6 +221,8 @@
opt.filename = q;
else if( strcmp( p, "ca_file" ) == 0 )
opt.ca_file = q;
+ else if( strcmp( p, "crl_file" ) == 0 )
+ opt.crl_file = q;
else if( strcmp( p, "ca_path" ) == 0 )
opt.ca_path = q;
else if( strcmp( p, "server_name" ) == 0 )
@@ -265,6 +274,18 @@
printf( " ok (%d skipped)\n", ret );
+ if( strlen( opt.crl_file ) )
+ {
+ ret = x509_crl_parse_file( &cacrl, opt.crl_file );
+ verify = 1;
+ }
+
+ if( ret < 0 )
+ {
+ printf( " failed\n ! x509_crl_parse returned -0x%x\n\n", -ret );
+ goto exit;
+ }
+
if( opt.mode == MODE_FILE )
{
x509_crt crt;
@@ -322,7 +343,7 @@
{
printf( " . Verifying X.509 certificate..." );
- if( ( ret = x509_crt_verify( &crt, &cacert, NULL, NULL, &flags,
+ if( ( ret = x509_crt_verify( &crt, &cacert, &cacrl, NULL, &flags,
my_verify, NULL ) ) != 0 )
{
printf( " failed\n" );
@@ -452,6 +473,7 @@
net_close( server_fd );
x509_crt_free( &cacert );
x509_crt_free( &clicert );
+ x509_crl_free( &cacrl );
pk_free( &pkey );
entropy_free( &entropy );
diff --git a/tests/.gitignore b/tests/.gitignore
index a83ad32..6590f0f 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -3,3 +3,4 @@
data_files/mpi_write
data_files/hmac_drbg_seed
data_files/ctr_drbg_seed
+data_files/entropy_seed
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index d75752c..b8a125c 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -40,6 +40,7 @@
add_test_suite(aes aes.cfb)
add_test_suite(aes aes.rest)
add_test_suite(arc4)
+add_test_suite(asn1write)
add_test_suite(base64)
add_test_suite(blowfish)
add_test_suite(camellia)
@@ -60,6 +61,7 @@
add_test_suite(ecp)
add_test_suite(ecdh)
add_test_suite(ecdsa)
+add_test_suite(entropy)
add_test_suite(error)
add_test_suite(gcm gcm.aes128_en)
add_test_suite(gcm gcm.aes192_en)
@@ -97,7 +99,7 @@
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/data_files" target)
if (NOT EXISTS ${link})
- if (UNIX)
+ if (CMAKE_HOST_UNIX)
set(command ln -s ${target} ${link})
else()
set(command cmd.exe /c mklink ${link} ${target})
diff --git a/tests/Makefile b/tests/Makefile
index 61e38c4..c37b790 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -32,7 +32,7 @@
APPS = test_suite_aes.ecb test_suite_aes.cbc \
test_suite_aes.cfb test_suite_aes.rest \
- test_suite_arc4 \
+ test_suite_arc4 test_suite_asn1write \
test_suite_base64 test_suite_blowfish \
test_suite_camellia test_suite_ccm \
test_suite_cipher.aes \
@@ -46,7 +46,7 @@
test_suite_des test_suite_dhm \
test_suite_ecdh test_suite_ecdsa \
test_suite_ecp \
- test_suite_error \
+ test_suite_error test_suite_entropy \
test_suite_gcm.aes128_de \
test_suite_gcm.aes192_de \
test_suite_gcm.aes256_de \
@@ -192,6 +192,10 @@
echo " CC $@.c"
$(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
+test_suite_asn1write: test_suite_asn1write.c $(DEP)
+ echo " CC $@.c"
+ $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
+
test_suite_base64: test_suite_base64.c $(DEP)
echo " CC $@.c"
$(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
@@ -268,6 +272,10 @@
echo " CC $@.c"
$(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
+test_suite_entropy: test_suite_entropy.c $(DEP)
+ echo " CC $@.c"
+ $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
+
test_suite_error: test_suite_error.c $(DEP)
echo " CC $@.c"
$(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
diff --git a/tests/compat.sh b/tests/compat.sh
index 724311c..06243bd 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -645,14 +645,14 @@
exit 1;
esac
- P_SERVER_ARGS="server_addr=0.0.0.0 force_version=$MODE"
- O_SERVER_ARGS="-www -cipher NULL,ALL -$MODE"
- G_SERVER_ARGS="-p 4433 --http"
+ P_SERVER_ARGS="server_port=$PORT server_addr=0.0.0.0 force_version=$MODE"
+ O_SERVER_ARGS="-accept $PORT -www -cipher NULL,ALL -$MODE"
+ G_SERVER_ARGS="-p $PORT --http"
G_SERVER_PRIO="EXPORT:+NULL:+MD5:+PSK:+DHE-PSK:+ECDHE-PSK:+RSA-PSK:-VERS-TLS-ALL:$G_PRIO_MODE"
- P_CLIENT_ARGS="force_version=$MODE"
- O_CLIENT_ARGS="-$MODE"
- G_CLIENT_ARGS="-p 4433 --debug 3"
+ P_CLIENT_ARGS="server_port=$PORT force_version=$MODE"
+ O_CLIENT_ARGS="-connect localhost:$PORT -$MODE"
+ G_CLIENT_ARGS="-p $PORT --debug 3"
G_CLIENT_PRIO="NONE:$G_PRIO_MODE:+COMP-NULL:+CURVE-ALL:+SIGN-ALL"
if [ "X$VERIFY" = "XYES" ];
@@ -757,8 +757,8 @@
SERVER_NAME=$1
log "$SERVER_CMD"
- echo "$SERVER_CMD" > srv_out
- $SERVER_CMD >> srv_out 2>&1 &
+ echo "$SERVER_CMD" > $SRV_OUT
+ $SERVER_CMD >> $SRV_OUT 2>&1 &
PROCESS_ID=$!
sleep 1
@@ -768,6 +768,10 @@
stop_server() {
case $SERVER_NAME in
[Pp]olar*)
+ # start watchdog in case SERVERQUIT fails
+ ( sleep 20; echo "SERVERQUIT TIMEOUT"; kill $MAIN_PID ) &
+ WATCHDOG_PID=$!
+
# we must force a PSK suite when in PSK mode (otherwise client
# auth will fail), so try every entry in $P_CIPHERS in turn (in
# case the first one is not implemented in this configuration)
@@ -779,27 +783,31 @@
break
fi
done
+
+ wait $PROCESS_ID 2>/dev/null
+ kill $WATCHDOG_PID 2>/dev/null
+ wait $WATCHDOG_PID 2>/dev/null
;;
*)
kill $PROCESS_ID 2>/dev/null
+ wait $PROCESS_ID 2>/dev/null
esac
- wait $PROCESS_ID 2>/dev/null
if [ "$MEMCHECK" -gt 0 ]; then
- if is_polar "$SERVER_CMD" && has_mem_err srv_out; then
+ if is_polar "$SERVER_CMD" && has_mem_err $SRV_OUT; then
echo " ! Server had memory errors"
let "srvmem++"
return
fi
fi
- rm -f srv_out
+ rm -f $SRV_OUT
}
# kill the running server (used when killed by signal)
cleanup() {
- rm -f srv_out cli_out
+ rm -f $SRV_OUT $CLI_OUT
kill $PROCESS_ID
exit 1
}
@@ -820,14 +828,14 @@
[Oo]pen*)
CLIENT_CMD="$OPENSSL_CMD s_client $O_CLIENT_ARGS -cipher $2"
log "$CLIENT_CMD"
- echo "$CLIENT_CMD" > cli_out
- ( echo -e 'GET HTTP/1.0'; echo; ) | $CLIENT_CMD >> cli_out 2>&1
+ echo "$CLIENT_CMD" > $CLI_OUT
+ ( echo -e 'GET HTTP/1.0'; echo; ) | $CLIENT_CMD >> $CLI_OUT 2>&1
EXIT=$?
if [ "$EXIT" == "0" ]; then
RESULT=0
else
- if grep 'Cipher is (NONE)' cli_out >/dev/null; then
+ if grep 'Cipher is (NONE)' $CLI_OUT >/dev/null; then
RESULT=1
else
RESULT=2
@@ -838,8 +846,8 @@
[Gg]nu*)
CLIENT_CMD="$GNUTLS_CLI $G_CLIENT_ARGS --priority $G_PRIO_MODE:$2 localhost"
log "$CLIENT_CMD"
- echo "$CLIENT_CMD" > cli_out
- ( echo -e 'GET HTTP/1.0'; echo; ) | $CLIENT_CMD >> cli_out 2>&1
+ echo "$CLIENT_CMD" > $CLI_OUT
+ ( echo -e 'GET HTTP/1.0'; echo; ) | $CLIENT_CMD >> $CLI_OUT 2>&1
EXIT=$?
if [ "$EXIT" == "0" ]; then
@@ -848,8 +856,8 @@
RESULT=2
# interpret early failure, with a handshake_failure alert
# before the server hello, as "no ciphersuite in common"
- if grep -F 'Received alert [40]: Handshake failed' cli_out; then
- if grep -i 'SERVER HELLO .* was received' cli_out; then :
+ if grep -F 'Received alert [40]: Handshake failed' $CLI_OUT; then
+ if grep -i 'SERVER HELLO .* was received' $CLI_OUT; then :
else
RESULT=1
fi
@@ -863,8 +871,8 @@
CLIENT_CMD="valgrind --leak-check=full $CLIENT_CMD"
fi
log "$CLIENT_CMD"
- echo "$CLIENT_CMD" > cli_out
- $CLIENT_CMD >> cli_out 2>&1
+ echo "$CLIENT_CMD" > $CLI_OUT
+ $CLIENT_CMD >> $CLI_OUT 2>&1
EXIT=$?
case $EXIT in
@@ -874,7 +882,7 @@
esac
if [ "$MEMCHECK" -gt 0 ]; then
- if is_polar "$CLIENT_CMD" && has_mem_err cli_out; then
+ if is_polar "$CLIENT_CMD" && has_mem_err $CLI_OUT; then
RESULT=2
fi
fi
@@ -887,7 +895,7 @@
;;
esac
- echo "EXIT: $EXIT" >> cli_out
+ echo "EXIT: $EXIT" >> $CLI_OUT
# report and count result
case $RESULT in
@@ -900,14 +908,14 @@
;;
"2")
echo FAIL
- cp srv_out c-srv-${tests}.log
- cp cli_out c-cli-${tests}.log
+ cp $SRV_OUT c-srv-${tests}.log
+ cp $CLI_OUT c-cli-${tests}.log
echo " ! outputs saved to c-srv-${tests}.log, c-cli-${tests}.log"
let "failed++"
;;
esac
- rm -f cli_out
+ rm -f $CLI_OUT
}
#
@@ -952,7 +960,17 @@
esac
done
-killall -q gnutls-serv openssl ssl_server ssl_server2
+# used by watchdog
+MAIN_PID="$$"
+
+# Pick a "unique" port in the range 10000-19999.
+PORT="0000$$"
+PORT="1$(echo $PORT | tail -c 4)"
+
+# Also pick a unique name for intermediate files
+SRV_OUT="srv_out.$$"
+CLI_OUT="cli_out.$$"
+
trap cleanup INT TERM HUP
for VERIFY in $VERIFIES; do
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 1e11d78..d01dc25 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -6,8 +6,8 @@
# CMake configuration. After this script is run, the CMake cache is lost and
# CMake is not initialised any more!
#
-# Assumes gcc, clang (recent enough for using ASan) are available, as weel as
-# cmake. Also assumes valgrind is available if --memcheck is used.
+# Assumes gcc and clang (recent enough for using ASan) are available,
+# as well as cmake and valgrind.
# Abort on errors (and uninitiliased variables)
set -eu
@@ -54,54 +54,72 @@
echo "******************************************************************"
}
-# Step 1: various build types
+# The test ordering tries to optimize for the following criteria:
+# 1. Catch possible problems early, by running first test that run quickly
+# and/or are more likely to fail than others.
+# 2. Minimize total running time, by avoiding useless rebuilds
+#
+# Indicative running times are given for reference.
-msg "Unix make, default compiler and flags"
-cleanup
-make
-
-msg "cmake, gcc with lots of warnings"
+msg "build: cmake, gcc with lots of warnings" # ~ 1 min
cleanup
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Check .
make
-msg "cmake, clang with lots of warnings"
+msg "test: main suites with valgrind" # ~ 2 min 10s
+make memcheck
+
+msg "build: with ASan" # ~ 1 min
+cleanup
+cmake -D CMAKE_BUILD_TYPE:String=ASan .
+make
+
+msg "test: ssl-opt.sh (ASan build)" # ~ 1 min 10s
+cd tests
+./ssl-opt.sh
+cd ..
+
+msg "test: main suites and selftest (ASan build)" # ~ 10s + 30s
+make test
+programs/test/selftest
+
+msg "test: ref-configs (ASan build)" # ~ 4 min 45 s
+tests/scripts/test-ref-configs.pl
+
+# Most issues are likely to be caught at this point
+
+msg "build: with ASan (rebuild after ref-configs)" # ~ 1 min
+make
+
+msg "test: compat.sh (ASan build)" # ~ 7 min 30s
+cd tests
+./compat.sh
+cd ..
+
+msg "build: cmake, clang with lots of warnings" # ~ 40s
cleanup
CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check .
make
-# Step 2: Full tests, with ASan
-
-msg "ASan build and full tests"
+msg "build: Unix make, -O2" # ~ 30s
cleanup
-cmake -D CMAKE_BUILD_TYPE:String=ASan .
make
-make test
-programs/test/selftest
-cd tests
-./compat.sh
-./ssl-opt.sh
-cd ..
-tests/scripts/test-ref-configs.pl
-# Step 3: using valgrind's memcheck
-
-msg "Release build, test suites with valgrind's memcheck"
-cleanup
-# optimized build to compensate a bit for valgrind slowdown
-cmake -D CMAKE_BUILD_TYPE:String=Release .
-make
-make memcheck
+# Optional parts that take a long time to run
if [ "$MEMORY" -gt 0 ]; then
+ msg "test: ssl-opt --memcheck (-02 build)" # ~ 8 min
cd tests
./ssl-opt.sh --memcheck
- [ "$MEMORY" -gt 1 ] && ./compat.sh --memcheck
cd ..
- # no test-ref-configs: doesn't have a memcheck option (yet?)
-fi
-# Done
+ if [ "$MEMORY" -gt 1 ]; then
+ msg "test: compat --memcheck (-02 build)" # ~ 42 min
+ cd tests
+ ./compat.sh --memcheck
+ cd ..
+ fi
+fi
echo "Done."
cleanup
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index f4fbc01..5104712 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -89,8 +89,8 @@
echo "FAIL"
echo " ! $1"
- cp srv_out o-srv-${TESTS}.log
- cp cli_out o-cli-${TESTS}.log
+ cp $SRV_OUT o-srv-${TESTS}.log
+ cp $CLI_OUT o-cli-${TESTS}.log
echo " ! outputs saved to o-srv-${TESTS}.log and o-cli-${TESTS}.log"
FAILS=`echo $FAILS + 1 | bc`
@@ -112,6 +112,28 @@
fi
}
+# wait for server to be ready
+wait_srv_ready() {
+ if is_polar "$SRV_CMD"; then
+ READY_MSG="Waiting for a remote connection"
+ else
+ READY_MSG="ACCEPT"
+ fi
+
+ # If the server isn't ready after 10 secs, something probably went wrong
+ ( sleep 10; echo "SERVERSTART TIMEOUT"; kill $MAIN_PID ) &
+ WATCHDOG_PID=$!
+
+ while ! grep "$READY_MSG" $SRV_OUT >/dev/null; do
+ # don't use sleep, since the whole goal is to avoid wasting time,
+ # and 1 second is usually way more than the server needs to start
+ true
+ done
+
+ kill $WATCHDOG_PID
+ wait $WATCHDOG_PID
+}
+
# Usage: run_test name srv_cmd cli_cmd cli_exit [option [...]]
# Options: -s pattern pattern that must be present in server output
# -c pattern pattern that must be present in client output
@@ -142,38 +164,46 @@
fi
# run the commands
- echo "$SRV_CMD" > srv_out
- $SRV_CMD >> srv_out 2>&1 &
+ echo "$SRV_CMD" > $SRV_OUT
+ $SRV_CMD >> $SRV_OUT 2>&1 &
SRV_PID=$!
- sleep 1
- echo "$CLI_CMD" > cli_out
- eval "$CLI_CMD" >> cli_out 2>&1
+ wait_srv_ready
+ echo "$CLI_CMD" > $CLI_OUT
+ eval "$CLI_CMD" >> $CLI_OUT 2>&1
CLI_EXIT=$?
- echo "EXIT: $CLI_EXIT" >> cli_out
+ echo "EXIT: $CLI_EXIT" >> $CLI_OUT
- # psk is useful when server only has bad certs
if is_polar "$SRV_CMD"; then
- "$P_CLI" request_page=SERVERQUIT tickets=0 auth_mode=none psk=abc123 \
+ # start watchdog in case SERVERQUIT fails
+ ( sleep 10; echo "SERVERQUIT TIMEOUT"; kill $MAIN_PID ) &
+ WATCHDOG_PID=$!
+
+ # psk is useful when server only has bad certs
+ $P_CLI request_page=SERVERQUIT tickets=0 auth_mode=none psk=abc123 \
crt_file=data_files/cli2.crt key_file=data_files/cli2.key \
>/dev/null
+
+ wait $SRV_PID
+ kill $WATCHDOG_PID
+ wait $WATCHDOG_PID
else
kill $SRV_PID
+ wait $SRV_PID
fi
- wait $SRV_PID
# check if the client and server went at least to the handshake stage
# (useful to avoid tests with only negative assertions and non-zero
# expected client exit to incorrectly succeed in case of catastrophic
# failure)
if is_polar "$SRV_CMD"; then
- if grep "Performing the SSL/TLS handshake" srv_out >/dev/null; then :;
+ if grep "Performing the SSL/TLS handshake" $SRV_OUT >/dev/null; then :;
else
fail "server failed to start"
return
fi
fi
if is_polar "$CLI_CMD"; then
- if grep "Performing the SSL/TLS handshake" cli_out >/dev/null; then :;
+ if grep "Performing the SSL/TLS handshake" $CLI_OUT >/dev/null; then :;
else
fail "client failed to start"
return
@@ -199,28 +229,28 @@
do
case $1 in
"-s")
- if grep "$2" srv_out >/dev/null; then :; else
+ if grep "$2" $SRV_OUT >/dev/null; then :; else
fail "-s $2"
return
fi
;;
"-c")
- if grep "$2" cli_out >/dev/null; then :; else
+ if grep "$2" $CLI_OUT >/dev/null; then :; else
fail "-c $2"
return
fi
;;
"-S")
- if grep "$2" srv_out >/dev/null; then
+ if grep "$2" $SRV_OUT >/dev/null; then
fail "-S $2"
return
fi
;;
"-C")
- if grep "$2" cli_out >/dev/null; then
+ if grep "$2" $CLI_OUT >/dev/null; then
fail "-C $2"
return
fi
@@ -235,11 +265,11 @@
# check valgrind's results
if [ "$MEMCHECK" -gt 0 ]; then
- if is_polar "$SRV_CMD" && has_mem_err srv_out; then
+ if is_polar "$SRV_CMD" && has_mem_err $SRV_OUT; then
fail "Server has memory errors"
return
fi
- if is_polar "$CLI_CMD" && has_mem_err cli_out; then
+ if is_polar "$CLI_CMD" && has_mem_err $CLI_OUT; then
fail "Client has memory errors"
return
fi
@@ -247,11 +277,11 @@
# if we're here, everything is ok
echo "PASS"
- rm -f srv_out cli_out
+ rm -f $SRV_OUT $CLI_OUT
}
cleanup() {
- rm -f cli_out srv_out sess
+ rm -f $CLI_OUT $SRV_OUT $SESSION
kill $SRV_PID
exit 1
}
@@ -276,7 +306,24 @@
exit 1
fi
-killall -q openssl ssl_server ssl_server2
+# used by watchdog
+MAIN_PID="$$"
+
+# Pick a "unique" port in the range 10000-19999.
+PORT="0000$$"
+PORT="1$(echo $PORT | tail -c 4)"
+
+# fix commands to use this port
+P_SRV="$P_SRV server_port=$PORT"
+P_CLI="$P_CLI server_port=$PORT"
+O_SRV="$O_SRV -accept $PORT"
+O_CLI="$O_CLI -connect localhost:$PORT"
+
+# Also pick a unique name for intermediate files
+SRV_OUT="srv_out.$$"
+CLI_OUT="cli_out.$$"
+SESSION="session.$$"
+
trap cleanup INT TERM HUP
# Test for SSLv2 ClientHello
@@ -365,7 +412,9 @@
run_test "Session resume using tickets #5 (openssl client)" \
"$P_SRV debug_level=4 tickets=1" \
- "($O_CLI -sess_out sess; $O_CLI -sess_in sess; rm -f sess)" \
+ "( $O_CLI -sess_out $SESSION; \
+ $O_CLI -sess_in $SESSION; \
+ rm -f $SESSION )" \
0 \
-s "found session ticket extension" \
-s "server hello, adding session ticket extension" \
@@ -450,7 +499,9 @@
run_test "Session resume using cache #8 (openssl client)" \
"$P_SRV debug_level=4 tickets=0" \
- "($O_CLI -sess_out sess; $O_CLI -sess_in sess; rm -f sess)" \
+ "( $O_CLI -sess_out $SESSION; \
+ $O_CLI -sess_in $SESSION; \
+ rm -f $SESSION )" \
0 \
-s "found session ticket extension" \
-S "server hello, adding session ticket extension" \
@@ -1243,6 +1294,129 @@
-s "bad certificate (usage extensions)" \
-s "Processing of the Certificate handshake message failed"
+# Tests for DHM parameters loading
+
+run_test "DHM parameters #0 (reference)" \
+ "$P_SRV" \
+ "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+ debug_level=3" \
+ 0 \
+ -c "value of 'DHM: P ' (2048 bits)" \
+ -c "value of 'DHM: G ' (2048 bits)"
+
+run_test "DHM parameters #1 (other parameters)" \
+ "$P_SRV dhm_file=data_files/dhparams.pem" \
+ "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+ debug_level=3" \
+ 0 \
+ -c "value of 'DHM: P ' (1024 bits)" \
+ -c "value of 'DHM: G ' (2 bits)"
+
+# Tests for PSK callback
+
+run_test "PSK callback #0a (psk, no callback)" \
+ "$P_SRV psk=abc123 psk_identity=foo" \
+ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+ psk_identity=foo psk=abc123" \
+ 0 \
+ -S "SSL - The server has no ciphersuites in common" \
+ -S "SSL - Unknown identity received" \
+ -S "SSL - Verification of the message MAC failed"
+
+run_test "PSK callback #0b (no psk, no callback)" \
+ "$P_SRV" \
+ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+ psk_identity=foo psk=abc123" \
+ 1 \
+ -s "SSL - The server has no ciphersuites in common" \
+ -S "SSL - Unknown identity received" \
+ -S "SSL - Verification of the message MAC failed"
+
+run_test "PSK callback #1 (callback overrides other settings)" \
+ "$P_SRV psk=abc123 psk_identity=foo psk_list=abc,dead,def,beef" \
+ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+ psk_identity=foo psk=abc123" \
+ 1 \
+ -S "SSL - The server has no ciphersuites in common" \
+ -s "SSL - Unknown identity received" \
+ -S "SSL - Verification of the message MAC failed"
+
+run_test "PSK callback #2 (first id matches)" \
+ "$P_SRV psk_list=abc,dead,def,beef" \
+ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+ psk_identity=abc psk=dead" \
+ 0 \
+ -S "SSL - The server has no ciphersuites in common" \
+ -S "SSL - Unknown identity received" \
+ -S "SSL - Verification of the message MAC failed"
+
+run_test "PSK callback #3 (second id matches)" \
+ "$P_SRV psk_list=abc,dead,def,beef" \
+ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+ psk_identity=def psk=beef" \
+ 0 \
+ -S "SSL - The server has no ciphersuites in common" \
+ -S "SSL - Unknown identity received" \
+ -S "SSL - Verification of the message MAC failed"
+
+run_test "PSK callback #4 (no match)" \
+ "$P_SRV psk_list=abc,dead,def,beef" \
+ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+ psk_identity=ghi psk=beef" \
+ 1 \
+ -S "SSL - The server has no ciphersuites in common" \
+ -s "SSL - Unknown identity received" \
+ -S "SSL - Verification of the message MAC failed"
+
+run_test "PSK callback #5 (wrong key)" \
+ "$P_SRV psk_list=abc,dead,def,beef" \
+ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+ psk_identity=abc psk=beef" \
+ 1 \
+ -S "SSL - The server has no ciphersuites in common" \
+ -S "SSL - Unknown identity received" \
+ -s "SSL - Verification of the message MAC failed"
+
+# Tests for ciphersuites per version
+
+run_test "Per-version suites #1" \
+ "$P_SRV version_suites=TLS-RSA-WITH-3DES-EDE-CBC-SHA,TLS-RSA-WITH-RC4-128-SHA,TLS-RSA-WITH-AES-128-CBC-SHA,TLS-RSA-WITH-AES-128-GCM-SHA256" \
+ "$P_CLI force_version=ssl3" \
+ 0 \
+ -c "Ciphersuite is TLS-RSA-WITH-3DES-EDE-CBC-SHA"
+
+run_test "Per-version suites #2" \
+ "$P_SRV version_suites=TLS-RSA-WITH-3DES-EDE-CBC-SHA,TLS-RSA-WITH-RC4-128-SHA,TLS-RSA-WITH-AES-128-CBC-SHA,TLS-RSA-WITH-AES-128-GCM-SHA256" \
+ "$P_CLI force_version=tls1" \
+ 0 \
+ -c "Ciphersuite is TLS-RSA-WITH-RC4-128-SHA"
+
+run_test "Per-version suites #3" \
+ "$P_SRV version_suites=TLS-RSA-WITH-3DES-EDE-CBC-SHA,TLS-RSA-WITH-RC4-128-SHA,TLS-RSA-WITH-AES-128-CBC-SHA,TLS-RSA-WITH-AES-128-GCM-SHA256" \
+ "$P_CLI force_version=tls1_1" \
+ 0 \
+ -c "Ciphersuite is TLS-RSA-WITH-AES-128-CBC-SHA"
+
+run_test "Per-version suites #4" \
+ "$P_SRV version_suites=TLS-RSA-WITH-3DES-EDE-CBC-SHA,TLS-RSA-WITH-RC4-128-SHA,TLS-RSA-WITH-AES-128-CBC-SHA,TLS-RSA-WITH-AES-128-GCM-SHA256" \
+ "$P_CLI force_version=tls1_2" \
+ 0 \
+ -c "Ciphersuite is TLS-RSA-WITH-AES-128-GCM-SHA256"
+
+# Tests for ssl_get_bytes_avail()
+
+run_test "ssl_get_bytes_avail #1 (no extra data)" \
+ "$P_SRV" \
+ "$P_CLI request_size=100" \
+ 0 \
+ -s "Read from client: 100 bytes read$"
+
+run_test "ssl_get_bytes_avail #2 (extra data)" \
+ "$P_SRV" \
+ "$P_CLI request_size=500" \
+ 0 \
+ -s "Read from client: 500 bytes read (.*+.*)"
+
# Final report
echo "------------------------------------------------------------------------"
diff --git a/tests/suites/test_suite_asn1write.data b/tests/suites/test_suite_asn1write.data
new file mode 100644
index 0000000..17f2067
--- /dev/null
+++ b/tests/suites/test_suite_asn1write.data
@@ -0,0 +1,50 @@
+ASN.1 Write Octet String #0 (Empty string)
+asn1_write_octet_string:"":"0400":2:2
+
+ASN.1 Write Octet String #1 (Large buffer)
+asn1_write_octet_string:"AABBCC":"0403AABBCC":10:5
+
+ASN.1 Write Octet String #2 (Buffer just fits)
+asn1_write_octet_string:"AABBCC":"0403AABBCC":5:5
+
+ASN.1 Write Octet String #3 (Buffer too small for tag)
+asn1_write_octet_string:"AABBCC":"0403AABBCC":4:POLARSSL_ERR_ASN1_BUF_TOO_SMALL
+
+ASN.1 Write Octet String #4 (Buffer too small for len)
+asn1_write_octet_string:"AABBCC":"0403AABBCC":3:POLARSSL_ERR_ASN1_BUF_TOO_SMALL
+
+ASN.1 Write Octet String #5 (Buffer too small for string)
+asn1_write_octet_string:"AABBCC":"0403AABBCC":2:POLARSSL_ERR_ASN1_BUF_TOO_SMALL
+
+ASN.1 Write Octet String #6 (l = 128, large buffer)
+asn1_write_octet_string:"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":"048180000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":140:131
+
+ASN.1 Write Octet String #7 (l = 128, buffer just fits)
+asn1_write_octet_string:"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":"048180000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":131:131
+
+ASN.1 Write Octet String #8 (l = 128, buffer too small for tag)
+asn1_write_octet_string:"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":"":130:POLARSSL_ERR_ASN1_BUF_TOO_SMALL
+
+ASN.1 Write Octet String #9 (l = 128, buffer too small for len)
+asn1_write_octet_string:"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":"":129:POLARSSL_ERR_ASN1_BUF_TOO_SMALL
+
+ASN.1 Write Octet String #9 (l = 128, buffer too small for string)
+asn1_write_octet_string:"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":"":127:POLARSSL_ERR_ASN1_BUF_TOO_SMALL
+
+ASN.1 Write IA5 String #0 (Empty string)
+asn1_write_ia5_string:"":"1600":2:2
+
+ASN.1 Write IA5 String #1 (Large buffer)
+asn1_write_ia5_string:"ABC":"1603414243":10:5
+
+ASN.1 Write IA5 String #2 (Buffer just fits)
+asn1_write_ia5_string:"ABC":"1603414243":5:5
+
+ASN.1 Write IA5 String #3 (Buffer too small for tag)
+asn1_write_ia5_string:"ABC":"":4:POLARSSL_ERR_ASN1_BUF_TOO_SMALL
+
+ASN.1 Write IA5 String #4 (Buffer too small for len)
+asn1_write_ia5_string:"ABC":"":3:POLARSSL_ERR_ASN1_BUF_TOO_SMALL
+
+ASN.1 Write IA5 String #5 (Buffer too small for string)
+asn1_write_ia5_string:"ABC":"":2:POLARSSL_ERR_ASN1_BUF_TOO_SMALL
diff --git a/tests/suites/test_suite_asn1write.function b/tests/suites/test_suite_asn1write.function
new file mode 100644
index 0000000..72e9b4b
--- /dev/null
+++ b/tests/suites/test_suite_asn1write.function
@@ -0,0 +1,84 @@
+/* BEGIN_HEADER */
+#include <polarssl/asn1write.h>
+
+#define GUARD_LEN 4
+#define GUARD_VAL 0x2a
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:POLARSSL_ASN1_WRITE_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void asn1_write_octet_string( char *hex_str, char *hex_asn1,
+ int buf_len, int result )
+{
+ int ret;
+ unsigned char buf[150];
+ unsigned char str[150] = { 0 };
+ unsigned char asn1[150] = { 0 };
+ size_t str_len, asn1_len, i;
+ unsigned char *p;
+
+ memset( buf, GUARD_VAL, sizeof( buf ) );
+
+ str_len = unhexify( str, hex_str );
+ asn1_len = unhexify( asn1, hex_asn1 );
+
+ p = buf + GUARD_LEN + buf_len;
+
+ ret = asn1_write_octet_string( &p, buf + GUARD_LEN, str, str_len );
+
+ /* Check for buffer overwrite on both sides */
+ for( i = 0; i < GUARD_LEN; i++ )
+ {
+ TEST_ASSERT( buf[i] == GUARD_VAL );
+ TEST_ASSERT( buf[GUARD_LEN + buf_len + i] == GUARD_VAL );
+ }
+
+ if( result >= 0 )
+ {
+ TEST_ASSERT( (size_t) ret == asn1_len );
+ TEST_ASSERT( p + asn1_len == buf + GUARD_LEN + buf_len );
+
+ TEST_ASSERT( memcmp( p, asn1, asn1_len ) == 0 );
+ }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void asn1_write_ia5_string( char *str, char *hex_asn1,
+ int buf_len, int result )
+{
+ int ret;
+ unsigned char buf[150];
+ unsigned char asn1[150] = { 0 };
+ size_t str_len, asn1_len, i;
+ unsigned char *p;
+
+ memset( buf, GUARD_VAL, sizeof( buf ) );
+
+ str_len = strlen( str );
+ asn1_len = unhexify( asn1, hex_asn1 );
+
+ p = buf + GUARD_LEN + buf_len;
+
+ ret = asn1_write_ia5_string( &p, buf + GUARD_LEN, str, str_len );
+
+ /* Check for buffer overwrite on both sides */
+ for( i = 0; i < GUARD_LEN; i++ )
+ {
+ TEST_ASSERT( buf[i] == GUARD_VAL );
+ TEST_ASSERT( buf[GUARD_LEN + buf_len + i] == GUARD_VAL );
+ }
+
+ if( result >= 0 )
+ {
+ TEST_ASSERT( (size_t) ret == asn1_len );
+ TEST_ASSERT( p + asn1_len == buf + GUARD_LEN + buf_len );
+
+ TEST_ASSERT( memcmp( p, asn1, asn1_len ) == 0 );
+ }
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_entropy.data b/tests/suites/test_suite_entropy.data
new file mode 100644
index 0000000..d81061c
--- /dev/null
+++ b/tests/suites/test_suite_entropy.data
@@ -0,0 +1,41 @@
+Entropy write/update seed file
+entropy_seed_file:"data_files/entropy_seed":0
+
+Entropy write/update seed file
+entropy_seed_file:"no_such_dir/file":POLARSSL_ERR_ENTROPY_FILE_IO_ERROR
+
+Entropy too many sources
+entropy_too_many_sources:
+
+Entropy output length #1
+entropy_func_len:0:0
+
+Entropy output length #2
+entropy_func_len:1:0
+
+Entropy output length #3
+entropy_func_len:2:0
+
+Entropy output length #4
+entropy_func_len:31:0
+
+Entropy output length #5
+entropy_func_len:65:POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+
+Entropy failing source
+entropy_source_fail:"data_files/entropy_seed"
+
+Entropy threshold #1
+entropy_threshold:16:2:8
+
+Entropy threshold #2
+entropy_threshold:32:1:32
+
+Entropy thershold #3
+entropy_threshold:16:0:POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+
+Entropy thershold #4
+entropy_threshold:1024:1:POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+
+Entropy self test
+entropy_selftest:
diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function
new file mode 100644
index 0000000..844eb96
--- /dev/null
+++ b/tests/suites/test_suite_entropy.function
@@ -0,0 +1,171 @@
+/* BEGIN_HEADER */
+#include <polarssl/entropy.h>
+
+/*
+ * Number of calls made to entropy_dummy_source()
+ */
+static size_t entropy_dummy_calls;
+
+/*
+ * Dummy entropy source
+ *
+ * If data is NULL, write exactly the requested length.
+ * Otherwise, write the length indicated by data or error if negative
+ */
+static int entropy_dummy_source( void *data, unsigned char *output,
+ size_t len, size_t *olen )
+{
+ entropy_dummy_calls++;
+
+ if( data == NULL )
+ *olen = len;
+ else
+ {
+ int *d = (int *) data;
+
+ if( *d < 0 )
+ return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+ else
+ *olen = *d;
+ }
+
+ memset( output, 0x2a, *olen );
+
+ return( 0 );
+}
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:POLARSSL_ENTROPY_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:POLARSSL_FS_IO */
+void entropy_seed_file( char *path, int ret )
+{
+ entropy_context ctx;
+
+ entropy_init( &ctx );
+
+ TEST_ASSERT( entropy_write_seed_file( &ctx, path ) == ret );
+ TEST_ASSERT( entropy_update_seed_file( &ctx, path ) == ret );
+
+ entropy_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void entropy_too_many_sources( )
+{
+ entropy_context ctx;
+ size_t i;
+
+ entropy_init( &ctx );
+
+ /*
+ * It's hard to tell precisely when the error will occur,
+ * since we don't know how many sources were automatically added.
+ */
+ for( i = 0; i < ENTROPY_MAX_SOURCES; i++ )
+ (void) entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 );
+
+ TEST_ASSERT( entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 )
+ == POLARSSL_ERR_ENTROPY_MAX_SOURCES );
+
+ entropy_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void entropy_func_len( int len, int ret )
+{
+ entropy_context ctx;
+ unsigned char buf[ENTROPY_BLOCK_SIZE + 10] = { 0 };
+ unsigned char acc[ENTROPY_BLOCK_SIZE + 10] = { 0 };
+ size_t i, j;
+
+ entropy_init( &ctx );
+
+ /*
+ * See comments in entropy_self_test()
+ */
+ for( i = 0; i < 8; i++ )
+ {
+ TEST_ASSERT( entropy_func( &ctx, buf, len ) == ret );
+ for( j = 0; j < sizeof( buf ); j++ )
+ acc[j] |= buf[j];
+ }
+
+ if( ret == 0 )
+ for( j = 0; j < (size_t) len; j++ )
+ TEST_ASSERT( acc[j] != 0 );
+
+ for( j = len; j < sizeof( buf ); j++ )
+ TEST_ASSERT( acc[j] == 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void entropy_source_fail( char *path )
+{
+ entropy_context ctx;
+ int fail = -1;
+ unsigned char buf[16];
+
+ entropy_init( &ctx );
+
+ TEST_ASSERT( entropy_add_source( &ctx, entropy_dummy_source, &fail, 16 )
+ == 0 );
+
+ TEST_ASSERT( entropy_func( &ctx, buf, sizeof( buf ) )
+ == POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+ TEST_ASSERT( entropy_gather( &ctx )
+ == POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+#if defined(POLARSSL_FS_IO)
+ TEST_ASSERT( entropy_write_seed_file( &ctx, path )
+ == POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+ TEST_ASSERT( entropy_update_seed_file( &ctx, path )
+ == POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+#else
+ ((void) path);
+#endif
+
+ entropy_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void entropy_threshold( int threshold, int chunk_size, int result )
+{
+ entropy_context ctx;
+ unsigned char buf[ENTROPY_BLOCK_SIZE] = { 0 };
+ int ret;
+
+ entropy_init( &ctx );
+
+ TEST_ASSERT( entropy_add_source( &ctx, entropy_dummy_source,
+ &chunk_size, threshold ) == 0 );
+
+ entropy_dummy_calls = 0;
+ ret = entropy_func( &ctx, buf, sizeof( buf ) );
+
+ if( result >= 0 )
+ {
+ TEST_ASSERT( ret == 0 );
+ TEST_ASSERT( entropy_dummy_calls == (size_t) result );
+ }
+ else
+ {
+ TEST_ASSERT( ret == result );
+ }
+
+ entropy_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:POLARSSL_SELF_TEST */
+void entropy_selftest( )
+{
+ TEST_ASSERT( entropy_self_test( 0 ) == 0 );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_xtea.data b/tests/suites/test_suite_xtea.data
index 37d065c..109e6b6 100644
--- a/tests/suites/test_suite_xtea.data
+++ b/tests/suites/test_suite_xtea.data
@@ -34,6 +34,43 @@
XTEA Decrypt_ecb #6
xtea_decrypt_ecb:"00000000000000000000000000000000":"4141414141414141":"70e1225d6e4e7655"
+XTEA Encrypt CBC #1
+xtea_encrypt_cbc:"000102030405060708090a0b0c0d0e0f":"6162636465666768":"4142434445464748":"6b982bec15a7b558"
+
+XTEA Encrypt CBC #2
+xtea_encrypt_cbc:"000102030405060708090a0b0c0d0e0f":"4142434445464748":"41414141414141414141414141414141":"2c6aeb799561c8e973b0927f072e3801"
+
+XTEA Encrypt CBC #3
+xtea_encrypt_cbc:"000102030405060708090a0b0c0d0e0f":"0000000000000000":"5a5b6e278948d77f70e1225d6e4e7655e78f2d13744341d8":"41414141414141415fee100fe2c030025d8a557f2677cb33"
+
+XTEA Encrypt CBC #4
+xtea_encrypt_cbc:"00000000000000000000000000000000":"6162636465666768":"4142434445464748":"5b0c065a3803900d"
+
+XTEA Encrypt CBC #5
+xtea_encrypt_cbc:"00000000000000000000000000000000":"4142434445464748":"41414141414141414141414141414141":"bdae508aa320aa5caa7cd79dbc9c38aa"
+
+XTEA Encrypt CBC #6
+xtea_encrypt_cbc:"00000000000000000000000000000000":"0000000000000000":"5a5b6e278948d77f70e1225d6e4e7655e78f2d13744341d8":"61f5082a2c996f632da3ea16ff8e06558b69f069d8637b31"
+
+XTEA Decrypt CBC #1
+xtea_decrypt_cbc:"000102030405060708090a0b0c0d0e0f":"6162636465666768":"4142434445464748":"359def46515c71b2"
+
+XTEA Decrypt CBC #2
+xtea_decrypt_cbc:"000102030405060708090a0b0c0d0e0f":"4142434445464748":"41414141414141414141414141414141":"1b192d63cc0e90371b1a2f66c809963e"
+
+XTEA Decrypt CBC #3
+xtea_decrypt_cbc:"000102030405060708090a0b0c0d0e0f":"0000000000000000":"5a5b6e278948d77f70e1225d6e4e7655e78f2d13744341d8":"2e76e5cc03543cdc40ca03358a5764c331a0631c2f0f3714"
+
+XTEA Decrypt CBC #4
+xtea_decrypt_cbc:"00000000000000000000000000000000":"6162636465666768":"4142434445464748":"81476a15138174dc"
+
+XTEA Decrypt CBC #5
+xtea_decrypt_cbc:"00000000000000000000000000000000":"4142434445464748":"41414141414141414141414141414141":"31a361192b08311d31a0631c2f0f3714"
+
+XTEA Decrypt CBC #6
+xtea_decrypt_cbc:"00000000000000000000000000000000":"0000000000000000":"5a5b6e278948d77f70e1225d6e4e7655e78f2d13744341d8":"c1e2dbbf67ee786e29e051bea18c6abc66f1de5c2daefc2a"
+
XTEA Selftest
depends_on:POLARSSL_SELF_TEST
xtea_selftest:
+
diff --git a/tests/suites/test_suite_xtea.function b/tests/suites/test_suite_xtea.function
index 091752f..74ca678 100644
--- a/tests/suites/test_suite_xtea.function
+++ b/tests/suites/test_suite_xtea.function
@@ -59,6 +59,68 @@
}
/* END_CASE */
+/* BEGIN_CASE */
+void xtea_encrypt_cbc( char *hex_key_string, char *hex_iv_string,
+ char *hex_src_string, char *hex_dst_string )
+{
+ unsigned char key_str[100];
+ unsigned char src_str[100];
+ unsigned char dst_str[100];
+ unsigned char iv_str[100];
+ unsigned char output[100];
+ size_t len;
+ xtea_context ctx;
+
+ memset(key_str, 0x00, 100);
+ memset(src_str, 0x00, 100);
+ memset(dst_str, 0x00, 100);
+ memset(iv_str, 0x00, 100);
+ memset(output, 0x00, 100);
+
+ unhexify( key_str, hex_key_string );
+ unhexify( iv_str, hex_iv_string );
+ len = unhexify( src_str, hex_src_string );
+
+ xtea_setup( &ctx, key_str );
+ TEST_ASSERT( xtea_crypt_cbc( &ctx, XTEA_ENCRYPT, len, iv_str,
+ src_str, output ) == 0 );
+ hexify( dst_str, output, len );
+
+ TEST_ASSERT( strcmp( (char *) dst_str, hex_dst_string ) == 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void xtea_decrypt_cbc( char *hex_key_string, char *hex_iv_string,
+ char *hex_src_string, char *hex_dst_string )
+{
+ unsigned char key_str[100];
+ unsigned char src_str[100];
+ unsigned char dst_str[100];
+ unsigned char iv_str[100];
+ unsigned char output[100];
+ size_t len;
+ xtea_context ctx;
+
+ memset(key_str, 0x00, 100);
+ memset(src_str, 0x00, 100);
+ memset(dst_str, 0x00, 100);
+ memset(iv_str, 0x00, 100);
+ memset(output, 0x00, 100);
+
+ unhexify( key_str, hex_key_string );
+ unhexify( iv_str, hex_iv_string );
+ len = unhexify( src_str, hex_src_string );
+
+ xtea_setup( &ctx, key_str );
+ TEST_ASSERT( xtea_crypt_cbc( &ctx, XTEA_DECRYPT, len, iv_str,
+ src_str, output ) == 0 );
+ hexify( dst_str, output, len );
+
+ TEST_ASSERT( strcmp( (char *) dst_str, hex_dst_string ) == 0 );
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:POLARSSL_SELF_TEST */
void xtea_selftest()
{