diff --git a/.gitignore b/.gitignore index 02b0a98c5..fdd50b245 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ CTestTestfile.cmake cmake_install.cmake Testing Coverage +*.gcno +*.gcda +library/polarssl.info diff --git a/CMakeLists.txt b/CMakeLists.txt index 0be112edd..ac4be4c02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,10 +76,22 @@ ADD_CUSTOM_TARGET(test-ref-config COMMAND tests/scripts/test-ref-configs.pl ) +# add programs/test/selftest even though the selftest functions are +# called from the testsuites since it runs them in verbose mode, +# avoiding spurious "uncovered" printf lines +ADD_CUSTOM_TARGET(covtest + COMMAND make test + COMMAND programs/test/selftest + COMMAND cd tests && ./compat.sh + COMMAND cd tests && ./ssl-opt.sh + ) + ADD_CUSTOM_TARGET(lcov - COMMAND geninfo *.gcda - COMMAND genhtml -o ../../../Coverage *.info - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/library/CMakeFiles/polarssl.dir + COMMAND rm -rf Coverage + COMMAND lcov --capture --directory library/CMakeFiles/polarssl.dir -o polarssl.info + COMMAND gendesc tests/Descriptions.txt -o descriptions + COMMAND genhtml --title PolarSSL --description-file descriptions --keep-descriptions --legend --no-branch-coverage -o Coverage polarssl.info + COMMAND rm -f polarssl.info descriptions ) ADD_CUSTOM_TARGET(memcheck diff --git a/ChangeLog b/ChangeLog index e6f167993..0667d2348 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,7 @@ PolarSSL ChangeLog (Sorted per branch, date) = PolarSSL 1.3 branch Features * HMAC-DRBG as a separate module - * Option to set the Curve preference order + * Option to set the Curve preference order (disabled by default) * Single Platform compatilibity layer (for memory / printf / fprintf) * Ability to provide alternate timing implementation * Ability to force the entropy module to use SHA-256 as its basis @@ -35,6 +35,14 @@ Bugfix * Programs rsa_sign_pss and rsa_verify_pss were not using PSS since 1.3.0 * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by Alex Wilson.) + * ssl_cache was creating entries when max_entries=0 if TIMING_C was enabled. + * m_sleep() was sleeping twice too long on most Unix platforms. + * Fixed bug with session tickets and non-blocking I/O in the unlikely case + send() would return an EAGAIN error when sending the ticket. + * ssl_cache was leaking memory when reusing a timed out entry containing a + client certificate. + * ssl_srv was leaking memory when client presented a timed out ticket + containing a client certificate = PolarSSL 1.3.4 released on 2014-01-27 Features diff --git a/Makefile b/Makefile index 2ca3cf54e..ec09f9cca 100644 --- a/Makefile +++ b/Makefile @@ -56,10 +56,23 @@ check: lib test-ref-configs: tests/scripts/test-ref-configs.pl +# note: for coverage testing, build with: +# CFLAGS='--coverage' make OFLAGS='-g3 -O0' +covtest: + make check + # add programs/test/selftest even though the selftest functions are + # called from the testsuites since it runs them in verbose mode, + # avoiding spurious "uncovered" printf lines + programs/test/selftest + ( cd tests && ./compat.sh ) + ( cd tests && ./ssl-opt.sh ) + lcov: rm -rf Coverage - ( cd library && geninfo *.gcda ) - ( cd library && genhtml -o ../Coverage *.info ) + lcov --capture --directory library -o polarssl.info + gendesc tests/Descriptions.txt -o descriptions + genhtml --title PolarSSL --description-file descriptions --keep-descriptions --legend --no-branch-coverage -o Coverage polarssl.info + rm -f polarssl.info descriptions apidoc: mkdir -p apidoc diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 74e818948..c070df2ac 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -2273,6 +2273,11 @@ #error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites" #endif +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) && \ + !defined(POLARSSL_X509_CRT_PARSE_C) +#error "POLARSSL_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + #if defined(POLARSSL_THREADING_PTHREAD) #if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL) #error "POLARSSL_THREADING_PTHREAD defined, but not all prerequisites" diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 89e337529..2e33ffd5a 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -1118,7 +1118,7 @@ int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len, * * If set, the PSK callback is called for each * handshake where a PSK ciphersuite was negotiated. - * The callback provides the identity received and wants to + * The caller provides the identity received and wants to * receive the actual PSK data and length. * * The callback has the following parameters: (void *parameter, diff --git a/include/polarssl/ssl_cache.h b/include/polarssl/ssl_cache.h index daa07acb6..16144fee8 100644 --- a/include/polarssl/ssl_cache.h +++ b/include/polarssl/ssl_cache.h @@ -106,7 +106,7 @@ int ssl_cache_set( void *data, const ssl_session *session ); * A timeout of 0 indicates no timeout. * * \param cache SSL cache context - * \param timeout cache entry timeout + * \param timeout cache entry timeout in seconds */ void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout ); #endif /* POLARSSL_HAVE_TIME */ diff --git a/library/certs.c b/library/certs.c index 17775b889..7409efad1 100644 --- a/library/certs.c +++ b/library/certs.c @@ -169,55 +169,56 @@ const char test_ca_pwd_rsa[] = "PolarSSLTest"; const char test_srv_crt_rsa[] = "-----BEGIN CERTIFICATE-----\r\n" -"MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" "MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" -"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN\r\n" -"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/\r\n" -"uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD\r\n" -"d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf\r\n" -"CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr\r\n" -"lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w\r\n" -"bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB\r\n" -"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf\r\n" -"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n" -"AQEAvc+WwZUemsJu2IiI2Cp6liA+UAvIx98dQe3kZs2zAoF9VwQbXcYzWQ/BILkj\r\n" -"NImKbPL9x0g2jIDn4ZvGYFywMwIO/d++YbwYiQw42/v7RiMy94zBPnzeHi86dy/0\r\n" -"jpOOJUx3IXRsGLdyjb/1T11klcFqGnARiK+8VYolMPP6afKvLXX7K4kiUpsFQhUp\r\n" -"E5VeM5pV1Mci2ETOJau2cO40FJvI/C9W/wR+GAArMaw2fxG77E3laaa0LAOlexM6\r\n" -"A4KOb5f5cGTM5Ih6tEF5FVq3/9vzNIYMa1FqzacBLZF8zSHYLEimXBdzjBoN4qDU\r\n" -"/WzRyYRBRjAI49mzHX6raleqnw==\r\n" +"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" +"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" +"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" +"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" +"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" +"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" +"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" +"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" +"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" +"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" +"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" +"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" +"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" +"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" +"zhuYwjVuX6JHG0c=\r\n" "-----END CERTIFICATE-----\r\n"; const char test_srv_key_rsa[] = "-----BEGIN RSA PRIVATE KEY-----\r\n" -"MIIEogIBAAKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/uOhFkNvuiBZS0/FDUEeW\r\n" -"Ellkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFDd185fAkER4KwVzlw7aPs\r\n" -"FRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVfCrFTxjB+FTms+Vruf5Ke\r\n" -"pgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTrlZvc/kFeF6babFtpzAK6\r\n" -"FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9wbp7OvViJ4lNZnm5akmXi\r\n" -"iD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQABAoIBABaJ9eiRQq4Ypv+w\r\n" -"UTcVpLC0oTueWzcpor1i1zjG4Vzqe/Ok2FqyGToGKMlFK7Hwwa+LEyeJ3xyV5yd4\r\n" -"v1Mw9bDZFdJC1eCBjoUAHtX6k9HOE0Vd6woVQ4Vi6OPI1g7B5Mnr/58rNrnN6TMs\r\n" -"x58NF6euecwTU811QJrZtLbX7j2Cr28yB2Vs8qyYlHwVw5jbDOv43D7vU5gmlIDN\r\n" -"0JQRuWAnOuPzZNoJr4SfJKqHNGxYYY6pHZ1s0dOTLIDb/B8KQWapA2kRmZyid2EH\r\n" -"nwzgLbAsHJCf+bQnhXjXuxtUsrcIL8noZLazlOMxwNEammglVWW23Ud/QRnFgJg5\r\n" -"UgcAcRECgYEA19uYetht5qmwdJ+12oC6zeO+vXLcyD9gon23T5J6w2YThld7/OW0\r\n" -"oArQJGgkAdaq0pcTyOIjtTQVMFygdVmCEJmxh/3RutPcTeydqW9fphKDMej32J8e\r\n" -"GniGmNGiclbcfNOS8E5TGp445yZb9P1+7AHng16bGg3Ykj5EA4G+HCcCgYEAyHAl\r\n" -"//ekk8YjQElm+8izLtFkymIK0aCtEe9C/RIRhFYBeFaotC5dStNhBOncn4ovMAPD\r\n" -"lX/92yDi9OP8PPLN3a4B9XpW3k/SS5GrbT5cwOivBHNllZSmu/2qz5WPGcjVCOrB\r\n" -"LYl3YWr2h3EGKICT03kEoTkiDBvCeOpW7cCGl2cCgYBD5whoXHz1+ptPlI4YVjZt\r\n" -"Xh86aU+ajpVPiEyJ84I6xXmO4SZXv8q6LaycR0ZMbcL+zBelMb4Z2nBv7jNrtuR7\r\n" -"ZF28cdPv+YVr3esaybZE/73VjXup4SQPH6r3l7qKTVi+y6+FeJ4b2Xn8/MwgnT23\r\n" -"8EFrye7wmzpthrjOgZnUMQKBgE9Lhsz/5J0Nis6Y+2Pqn3CLKEukg9Ewtqdct2y0\r\n" -"5Dcta0F3TyCRIxlCDKTL/BslqMtfAdY4H268UO0+8IAQMn9boqzBrHIgs/pvc5kx\r\n" -"TbKHmw2wtWR6vYersBKVgVpbCGSRssDYHGFu1n74qM4HJ/RGcR1zI9QUe1gopSFD\r\n" -"xDtLAoGAVAdWvrqDwgoL2hHW3scGpxdE/ygJDOwHnf+1B9goKAOP5lf2FJaiAxf3\r\n" -"ectoPOgZbCmm/iiDmigu703ld3O+VoCLDD4qx3R+KyALL78gtVJYzSRiKhzgCZ3g\r\n" -"mKsIVRBq4IfwiwyMNG2BYZQAwbSDjjPtn/kPBduPzPj7eriByhI=\r\n" +"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" +"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" +"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" +"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" +"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" +"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" +"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" +"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" +"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" +"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" +"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" +"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" +"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" +"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" +"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" +"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" +"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" +"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" +"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" +"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" +"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" +"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" +"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" +"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" +"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" "-----END RSA PRIVATE KEY-----\r\n"; + const char test_cli_crt_rsa[] = "-----BEGIN CERTIFICATE-----\r\n" "MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" diff --git a/library/ssl_cache.c b/library/ssl_cache.c index 6fff54b32..4c7d3dbb0 100644 --- a/library/ssl_cache.c +++ b/library/ssl_cache.c @@ -186,17 +186,15 @@ int ssl_cache_set( void *data, const ssl_session *session ) /* * Reuse oldest entry if max_entries reached */ - if( old != NULL && count >= cache->max_entries ) + if( count >= cache->max_entries ) { - cur = old; - memset( &cur->session, 0, sizeof(ssl_session) ); -#if defined(POLARSSL_X509_CRT_PARSE_C) - if( cur->peer_cert.p != NULL ) + if( old == NULL ) { - polarssl_free( cur->peer_cert.p ); - memset( &cur->peer_cert, 0, sizeof(x509_buf) ); + ret = 1; + goto exit; } -#endif /* POLARSSL_X509_CRT_PARSE_C */ + + cur = old; } #else /* POLARSSL_HAVE_TIME */ /* @@ -213,21 +211,15 @@ int ssl_cache_set( void *data, const ssl_session *session ) cur = cache->chain; cache->chain = cur->next; - -#if defined(POLARSSL_X509_CRT_PARSE_C) - if( cur->peer_cert.p != NULL ) - { - polarssl_free( cur->peer_cert.p ); - memset( &cur->peer_cert, 0, sizeof(x509_buf) ); - } -#endif /* POLARSSL_X509_CRT_PARSE_C */ - - memset( cur, 0, sizeof(ssl_cache_entry) ); + cur->next = NULL; prv->next = cur; } #endif /* POLARSSL_HAVE_TIME */ else { + /* + * max_entries not reached, create new entry + */ cur = (ssl_cache_entry *) polarssl_malloc( sizeof(ssl_cache_entry) ); if( cur == NULL ) { @@ -251,6 +243,15 @@ int ssl_cache_set( void *data, const ssl_session *session ) memcpy( &cur->session, session, sizeof( ssl_session ) ); #if defined(POLARSSL_X509_CRT_PARSE_C) + /* + * If we're reusing an entry, free its certificate first + */ + if( cur->peer_cert.p != NULL ) + { + polarssl_free( cur->peer_cert.p ); + memset( &cur->peer_cert, 0, sizeof(x509_buf) ); + } + /* * Store peer certificate */ diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 54c931aee..85490502f 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -310,7 +310,7 @@ static int ssl_parse_ticket( ssl_context *ssl, if( ( ret = ssl_load_session( &session, ticket, clear_len ) ) != 0 ) { SSL_DEBUG_MSG( 1, ( "failed to parse ticket content" ) ); - memset( &session, 0, sizeof( ssl_session ) ); + ssl_session_free( &session ); return( ret ); } @@ -319,7 +319,7 @@ static int ssl_parse_ticket( ssl_context *ssl, if( (int) ( time( NULL) - session.start ) > ssl->ticket_lifetime ) { SSL_DEBUG_MSG( 1, ( "session ticket expired" ) ); - memset( &session, 0, sizeof( ssl_session ) ); + ssl_session_free( &session ); return( POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED ); } #endif @@ -367,6 +367,8 @@ static int ssl_parse_servername_ext( ssl_context *ssl, size_t servername_list_size, hostname_len; const unsigned char *p; + SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( servername_list_size + 2 != len ) { @@ -389,6 +391,7 @@ static int ssl_parse_servername_ext( ssl_context *ssl, ret = ssl_sni_wrapper( ssl, p + 3, hostname_len ); if( ret != 0 ) { + SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, SSL_ALERT_MSG_UNRECOGNIZED_NAME ); return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); @@ -1690,6 +1693,7 @@ static int ssl_write_server_hello( ssl_context *ssl ) ssl->f_get_cache != NULL && ssl->f_get_cache( ssl->p_get_cache, ssl->session_negotiate ) == 0 ) { + SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); ssl->handshake->resume = 1; } @@ -2041,7 +2045,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) { ssl_get_ecdh_params_from_cert( ssl ); - SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); ssl->state++; return( 0 ); } @@ -2999,15 +3003,18 @@ static int ssl_write_new_session_ticket( ssl_context *ssl ) ssl->out_msglen = 10 + tlen; + /* + * Morally equivalent to updating ssl->state, but NewSessionTicket and + * ChangeCipherSpec share the same state. + */ + ssl->handshake->new_session_ticket = 0; + if( ( ret = ssl_write_record( ssl ) ) != 0 ) { SSL_DEBUG_RET( 1, "ssl_write_record", ret ); return( ret ); } - /* No need to remember writing a NewSessionTicket any more */ - ssl->handshake->new_session_ticket = 0; - SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); return( 0 ); diff --git a/library/timing.c b/library/timing.c index c70b78c26..f1d8a1fed 100644 --- a/library/timing.c +++ b/library/timing.c @@ -302,7 +302,7 @@ void m_sleep( int milliseconds ) struct timeval tv; tv.tv_sec = milliseconds / 1000; - tv.tv_usec = milliseconds * 1000; + tv.tv_usec = ( milliseconds % 1000 ) * 1000; select( 0, NULL, NULL, NULL, &tv ); } diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 5f7c3be3b..3b8dec740 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -37,10 +37,16 @@ #include "polarssl/x509.h" #include "polarssl/error.h" +#if defined(POLARSSL_TIMING_C) +#include "polarssl/timing.h" +#endif + #define DFL_SERVER_NAME "localhost" +#define DFL_SERVER_ADDR NULL #define DFL_SERVER_PORT 4433 #define DFL_REQUEST_PAGE "/" #define DFL_DEBUG_LEVEL 0 +#define DFL_NBIO 0 #define DFL_CA_FILE "" #define DFL_CA_PATH "" #define DFL_CRT_FILE "" @@ -50,12 +56,14 @@ #define DFL_FORCE_CIPHER 0 #define DFL_RENEGOTIATION SSL_RENEGOTIATION_ENABLED #define DFL_ALLOW_LEGACY SSL_LEGACY_NO_RENEGOTIATION +#define DFL_RENEGOTIATE 0 #define DFL_MIN_VERSION -1 #define DFL_MAX_VERSION -1 #define DFL_AUTH_MODE SSL_VERIFY_REQUIRED #define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE #define DFL_TRUNC_HMAC 0 #define DFL_RECONNECT 0 +#define DFL_RECO_DELAY 0 #define DFL_TICKETS SSL_SESSION_TICKETS_ENABLED #define LONG_HEADER "User-agent: blah-blah-blah-blah-blah-blah-blah-blah-" \ @@ -71,17 +79,16 @@ * longer paquets (for fragmentation purposes) */ #define GET_REQUEST "GET %s HTTP/1.0\r\n" /* LONG_HEADER */ "\r\n" -/* Uncomment to test client-initiated renegotiation */ -// #define TEST_RENEGO - /* * global options */ struct options { const char *server_name; /* hostname of the server (client only) */ + const char *server_addr; /* address of the server (client only) */ int server_port; /* port on which the ssl service runs */ int debug_level; /* level of debugging */ + int nbio; /* should I/O be blocking? */ const char *request_page; /* page on server to request */ const char *ca_file; /* the file with the CA certificate(s) */ const char *ca_path; /* the path with the CA certificate(s) reside */ @@ -92,12 +99,14 @@ struct options int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ int renegotiation; /* enable / disable renegotiation */ int allow_legacy; /* allow legacy renegotiation */ + int renegotiate; /* attempt renegotiation? */ int min_version; /* minimum protocol version accepted */ int max_version; /* maximum protocol version accepted */ int auth_mode; /* verify mode for connection */ unsigned char mfl_code; /* code for maximum fragment length */ int trunc_hmac; /* negotiate truncated hmac or not */ int reconnect; /* attempt to resume session */ + int reco_delay; /* delay in seconds before resuming session */ int tickets; /* enable / disable session tickets */ } opt; @@ -110,6 +119,44 @@ static void my_debug( void *ctx, int level, const char *str ) } } +/* + * Test recv/send functions that make sure each try returns + * WANT_READ/WANT_WRITE at least once before sucesseding + */ +static int my_recv( void *ctx, unsigned char *buf, size_t len ) +{ + static int first_try = 1; + int ret; + + if( first_try ) + { + first_try = 0; + return( POLARSSL_ERR_NET_WANT_READ ); + } + + ret = net_recv( ctx, buf, len ); + if( ret != POLARSSL_ERR_NET_WANT_READ ) + first_try = 1; /* Next call will be a new operation */ + return( ret ); +} + +static int my_send( void *ctx, const unsigned char *buf, size_t len ) +{ + static int first_try = 1; + int ret; + + if( first_try ) + { + first_try = 0; + return( POLARSSL_ERR_NET_WANT_WRITE ); + } + + ret = net_send( ctx, buf, len ); + if( ret != POLARSSL_ERR_NET_WANT_WRITE ) + first_try = 1; /* Next call will be a new operation */ + return( ret ); +} + #if defined(POLARSSL_X509_CRT_PARSE_C) /* * Enabled if debug_level > 1 in code below @@ -199,18 +246,38 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags ) #define USAGE_MAX_FRAG_LEN "" #endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(POLARSSL_TIMING_C) +#define USAGE_TIME \ + " reco_delay=%%d default: 0 seconds\n" +#else +#define USAGE_TIME "" +#endif /* POLARSSL_TIMING_C */ + #define USAGE \ "\n usage: ssl_client2 param=<>...\n" \ "\n acceptable parameters:\n" \ " server_name=%%s default: localhost\n" \ + " server_addr=%%s default: given by name\n" \ " server_port=%%d default: 4433\n" \ - " debug_level=%%d default: 0 (disabled)\n" \ - USAGE_IO \ " request_page=%%s default: \".\"\n" \ + " debug_level=%%d default: 0 (disabled)\n" \ + " nbio=%%d default: 0 (blocking I/O)\n" \ + " options: 1 (non-blocking), 2 (added delays)\n" \ + "\n" \ + " auth_mode=%%s default: \"optional\"\n" \ + " options: none, optional, required\n" \ + USAGE_IO \ + "\n" \ + USAGE_PSK \ + "\n" \ " renegotiation=%%d default: 1 (enabled)\n" \ " allow_legacy=%%d default: 0 (disabled)\n" \ + " renegotiate=%%d default: 0 (disabled)\n" \ " reconnect=%%d default: 0 (disabled)\n" \ + USAGE_TIME \ USAGE_TICKETS \ + USAGE_MAX_FRAG_LEN \ + USAGE_TRUNC_HMAC \ "\n" \ " min_version=%%s default: \"\" (ssl3)\n" \ " max_version=%%s default: \"\" (tls1_2)\n" \ @@ -218,9 +285,6 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags ) " options: ssl3, tls1, tls1_1, tls1_2\n" \ " auth_mode=%%s default: \"required\"\n" \ " options: none, optional, required\n" \ - USAGE_MAX_FRAG_LEN \ - USAGE_TRUNC_HMAC \ - USAGE_PSK \ "\n" \ " force_ciphersuite= default: all enabled\n"\ " acceptable ciphersuite names:\n" @@ -296,8 +360,10 @@ int main( int argc, char *argv[] ) } opt.server_name = DFL_SERVER_NAME; + opt.server_addr = DFL_SERVER_ADDR; opt.server_port = DFL_SERVER_PORT; opt.debug_level = DFL_DEBUG_LEVEL; + opt.nbio = DFL_NBIO; opt.request_page = DFL_REQUEST_PAGE; opt.ca_file = DFL_CA_FILE; opt.ca_path = DFL_CA_PATH; @@ -308,12 +374,14 @@ int main( int argc, char *argv[] ) opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; opt.renegotiation = DFL_RENEGOTIATION; opt.allow_legacy = DFL_ALLOW_LEGACY; + opt.renegotiate = DFL_RENEGOTIATE; opt.min_version = DFL_MIN_VERSION; opt.max_version = DFL_MAX_VERSION; opt.auth_mode = DFL_AUTH_MODE; opt.mfl_code = DFL_MFL_CODE; opt.trunc_hmac = DFL_TRUNC_HMAC; opt.reconnect = DFL_RECONNECT; + opt.reco_delay = DFL_RECO_DELAY; opt.tickets = DFL_TICKETS; for( i = 1; i < argc; i++ ) @@ -325,6 +393,8 @@ int main( int argc, char *argv[] ) if( strcmp( p, "server_name" ) == 0 ) opt.server_name = q; + else if( strcmp( p, "server_addr" ) == 0 ) + opt.server_addr = q; else if( strcmp( p, "server_port" ) == 0 ) { opt.server_port = atoi( q ); @@ -337,6 +407,12 @@ int main( int argc, char *argv[] ) if( opt.debug_level < 0 || opt.debug_level > 65535 ) goto usage; } + else if( strcmp( p, "nbio" ) == 0 ) + { + opt.nbio = atoi( q ); + if( opt.nbio < 0 || opt.nbio > 2 ) + goto usage; + } else if( strcmp( p, "request_page" ) == 0 ) opt.request_page = q; else if( strcmp( p, "ca_file" ) == 0 ) @@ -375,12 +451,24 @@ int main( int argc, char *argv[] ) if( opt.allow_legacy < 0 || opt.allow_legacy > 1 ) goto usage; } + else if( strcmp( p, "renegotiate" ) == 0 ) + { + opt.renegotiate = atoi( q ); + if( opt.renegotiate < 0 || opt.renegotiate > 1 ) + goto usage; + } else if( strcmp( p, "reconnect" ) == 0 ) { opt.reconnect = atoi( q ); if( opt.reconnect < 0 || opt.reconnect > 2 ) goto usage; } + else if( strcmp( p, "reco_delay" ) == 0 ) + { + opt.reco_delay = atoi( q ); + if( opt.reco_delay < 0 ) + goto usage; + } else if( strcmp( p, "tickets" ) == 0 ) { opt.tickets = atoi( q ); @@ -573,9 +661,15 @@ int main( int argc, char *argv[] ) #if defined(POLARSSL_FS_IO) if( strlen( opt.ca_path ) ) - ret = x509_crt_parse_path( &cacert, opt.ca_path ); + if( strcmp( opt.ca_path, "none" ) == 0 ) + ret = 0; + else + ret = x509_crt_parse_path( &cacert, opt.ca_path ); else if( strlen( opt.ca_file ) ) - ret = x509_crt_parse_file( &cacert, opt.ca_file ); + if( strcmp( opt.ca_file, "none" ) == 0 ) + ret = 0; + else + ret = x509_crt_parse_file( &cacert, opt.ca_file ); else #endif #if defined(POLARSSL_CERTS_C) @@ -605,7 +699,10 @@ int main( int argc, char *argv[] ) #if defined(POLARSSL_FS_IO) if( strlen( opt.crt_file ) ) - ret = x509_crt_parse_file( &clicert, opt.crt_file ); + if( strcmp( opt.crt_file, "none" ) == 0 ) + ret = 0; + else + ret = x509_crt_parse_file( &clicert, opt.crt_file ); else #endif #if defined(POLARSSL_CERTS_C) @@ -625,7 +722,10 @@ int main( int argc, char *argv[] ) #if defined(POLARSSL_FS_IO) if( strlen( opt.key_file ) ) - ret = pk_parse_keyfile( &pkey, opt.key_file, "" ); + if( strcmp( opt.key_file, "none" ) == 0 ) + ret = 0; + else + ret = pk_parse_keyfile( &pkey, opt.key_file, "" ); else #endif #if defined(POLARSSL_CERTS_C) @@ -649,17 +749,30 @@ int main( int argc, char *argv[] ) /* * 2. Start the connection */ - printf( " . Connecting to tcp/%s/%-4d...", opt.server_name, + if( opt.server_addr == NULL) + opt.server_addr = opt.server_name; + + printf( " . Connecting to tcp/%s/%-4d...", opt.server_addr, opt.server_port ); fflush( stdout ); - if( ( ret = net_connect( &server_fd, opt.server_name, + if( ( ret = net_connect( &server_fd, opt.server_addr, opt.server_port ) ) != 0 ) { printf( " failed\n ! net_connect returned -0x%x\n\n", -ret ); goto exit; } + if( opt.nbio > 0 ) + ret = net_set_nonblock( server_fd ); + else + ret = net_set_block( server_fd ); + if( ret != 0 ) + { + printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret ); + goto exit; + } + printf( " ok\n" ); /* @@ -695,8 +808,11 @@ int main( int argc, char *argv[] ) ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg ); ssl_set_dbg( &ssl, my_debug, stdout ); - ssl_set_bio( &ssl, net_recv, &server_fd, - net_send, &server_fd ); + + if( opt.nbio == 2 ) + ssl_set_bio( &ssl, my_recv, &server_fd, my_send, &server_fd ); + else + ssl_set_bio( &ssl, net_recv, &server_fd, net_send, &server_fd ); #if defined(POLARSSL_SSL_SESSION_TICKETS) ssl_set_session_tickets( &ssl, opt.tickets ); @@ -709,8 +825,16 @@ int main( int argc, char *argv[] ) ssl_legacy_renegotiation( &ssl, opt.allow_legacy ); #if defined(POLARSSL_X509_CRT_PARSE_C) - ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name ); - ssl_set_own_cert( &ssl, &clicert, &pkey ); + if( strcmp( opt.ca_path, "none" ) != 0 && + strcmp( opt.ca_file, "none" ) != 0 ) + { + ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name ); + } + if( strcmp( opt.crt_file, "none" ) != 0 && + strcmp( opt.key_file, "none" ) != 0 ) + { + ssl_set_own_cert( &ssl, &clicert, &pkey ); + } #endif #if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) @@ -804,23 +928,25 @@ int main( int argc, char *argv[] ) } #endif /* POLARSSL_X509_CRT_PARSE_C */ -#ifdef TEST_RENEGO - /* - * Perform renegotiation (this must be done when the server is waiting - * for input from our side). - */ - printf( " . Performing renegotiation..." ); - fflush( stdout ); - while( ( ret = ssl_renegotiate( &ssl ) ) != 0 ) + if( opt.renegotiate ) { - if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) + /* + * Perform renegotiation (this must be done when the server is waiting + * for input from our side). + */ + printf( " . Performing renegotiation..." ); + fflush( stdout ); + while( ( ret = ssl_renegotiate( &ssl ) ) != 0 ) { - printf( " failed\n ! ssl_renegotiate returned %d\n\n", ret ); - goto exit; + if( ret != POLARSSL_ERR_NET_WANT_READ && + ret != POLARSSL_ERR_NET_WANT_WRITE ) + { + printf( " failed\n ! ssl_renegotiate returned %d\n\n", ret ); + goto exit; + } } + printf( " ok\n" ); } - printf( " ok\n" ); -#endif /* * 6. Write the GET request @@ -829,7 +955,10 @@ send_request: printf( " > Write to server:" ); fflush( stdout ); - len = sprintf( (char *) buf, GET_REQUEST, opt.request_page ); + if( strcmp( opt.request_page, "SERVERQUIT" ) == 0 ) + len = sprintf( (char *) buf, "%s", opt.request_page ); + else + len = sprintf( (char *) buf, GET_REQUEST, opt.request_page ); for( written = 0, frags = 0; written < len; written += ret, frags++ ) { @@ -887,8 +1016,10 @@ send_request: { --opt.reconnect; - // printf( " ! Press a key to reconnect\n" ); - // (void) getchar(); +#if defined(POLARSSL_TIMING_C) + if( opt.reco_delay > 0 ) + m_sleep( 1000 * opt.reco_delay ); +#endif printf( " . Reconnecting with saved session..." ); fflush( stdout ); @@ -931,6 +1062,9 @@ exit: char error_buf[100]; polarssl_strerror( ret, error_buf, 100 ); printf("Last error was: -0x%X - %s\n\n", -ret, error_buf ); + + if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY ) + ret = 0; } #endif diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index c916b8ba0..7a23e7728 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -25,6 +25,17 @@ #include "polarssl/config.h" +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) && defined(POLARSSL_FS_IO) +#define POLARSSL_SNI +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + #if defined(_WIN32) #include #endif @@ -52,6 +63,7 @@ #define DFL_SERVER_ADDR NULL #define DFL_SERVER_PORT 4433 #define DFL_DEBUG_LEVEL 0 +#define DFL_NBIO 0 #define DFL_CA_FILE "" #define DFL_CA_PATH "" #define DFL_CRT_FILE "" @@ -63,11 +75,16 @@ #define DFL_FORCE_CIPHER 0 #define DFL_RENEGOTIATION SSL_RENEGOTIATION_ENABLED #define DFL_ALLOW_LEGACY SSL_LEGACY_NO_RENEGOTIATION +#define DFL_RENEGOTIATE 0 #define DFL_MIN_VERSION -1 #define DFL_MAX_VERSION -1 #define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL #define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE #define DFL_TICKETS SSL_SESSION_TICKETS_ENABLED +#define DFL_TICKET_TIMEOUT -1 +#define DFL_CACHE_MAX -1 +#define DFL_CACHE_TIMEOUT -1 +#define DFL_SNI NULL #define LONG_RESPONSE "

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" \ @@ -84,9 +101,6 @@ "

PolarSSL Test Server

\r\n" \ "

Successful connection using: %s

\r\n" // LONG_RESPONSE -/* Uncomment to test server-initiated renegotiation */ -// #define TEST_RENEGO - /* * global options */ @@ -95,6 +109,7 @@ struct options const char *server_addr; /* address on which the ssl service runs */ int server_port; /* port on which the ssl service runs */ int debug_level; /* level of debugging */ + int nbio; /* should I/O be blocking? */ const char *ca_file; /* the file with the CA certificate(s) */ const char *ca_path; /* the path with the CA certificate(s) reside */ const char *crt_file; /* the file with the server certificate */ @@ -106,11 +121,16 @@ struct options int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ int renegotiation; /* enable / disable renegotiation */ int allow_legacy; /* allow legacy renegotiation */ + int renegotiate; /* attempt renegotiation? */ int min_version; /* minimum protocol version accepted */ int max_version; /* maximum protocol version accepted */ int auth_mode; /* verify mode for connection */ unsigned char mfl_code; /* code for maximum fragment length */ int tickets; /* enable / disable session tickets */ + int ticket_timeout; /* session ticket lifetime */ + int cache_max; /* max number of session cache entries */ + int cache_timeout; /* expiration delay of session cache entries */ + char *sni; /* string decribing sni information */ } opt; static void my_debug( void *ctx, int level, const char *str ) @@ -122,6 +142,43 @@ static void my_debug( void *ctx, int level, const char *str ) } } +/* + * Test recv/send functions that make sure each try returns + * WANT_READ/WANT_WRITE at least once before sucesseding + */ +static int my_recv( void *ctx, unsigned char *buf, size_t len ) +{ + static int first_try = 1; + int ret; + + if( first_try ) + { + first_try = 0; + return( POLARSSL_ERR_NET_WANT_READ ); + } + + ret = net_recv( ctx, buf, len ); + if( ret != POLARSSL_ERR_NET_WANT_READ ) + first_try = 1; /* Next call will be a new operation */ + return( ret ); +} + +static int my_send( void *ctx, const unsigned char *buf, size_t len ) +{ + static int first_try = 1; + int ret; + + if( first_try ) + { + first_try = 0; + return( POLARSSL_ERR_NET_WANT_WRITE ); + } + + ret = net_send( ctx, buf, len ); + if( ret != POLARSSL_ERR_NET_WANT_WRITE ) + first_try = 1; /* Next call will be a new operation */ + return( ret ); +} #if defined(POLARSSL_X509_CRT_PARSE_C) #if defined(POLARSSL_FS_IO) @@ -158,11 +215,28 @@ static void my_debug( void *ctx, int level, const char *str ) #if defined(POLARSSL_SSL_SESSION_TICKETS) #define USAGE_TICKETS \ - " tickets=%%d default: 1 (enabled)\n" + " tickets=%%d default: 1 (enabled)\n" \ + " ticket_timeout=%%d default: ticket default (1d)\n" #else #define USAGE_TICKETS "" #endif /* POLARSSL_SSL_SESSION_TICKETS */ +#if defined(POLARSSL_SSL_CACHE_C) +#define USAGE_CACHE \ + " cache_max=%%d default: cache default (50)\n" \ + " cache_timeout=%%d default: cache default (1d)\n" +#else +#define USAGE_CACHE "" +#endif /* POLARSSL_SSL_CACHE_C */ + +#if defined(POLARSSL_SNI) +#define USAGE_SNI \ + " sni=%%s name1,cert1,key1[,name2,cert2,key2[,...]]\n" \ + " default: disabled\n" +#else +#define USAGE_SNI "" +#endif /* POLARSSL_SNI */ + #if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) #define USAGE_MAX_FRAG_LEN \ " max_frag_len=%%d default: 16384 (tls default)\n" \ @@ -177,19 +251,27 @@ static void my_debug( void *ctx, int level, const char *str ) " server_addr=%%d default: (all interfaces)\n" \ " server_port=%%d default: 4433\n" \ " debug_level=%%d default: 0 (disabled)\n" \ + " nbio=%%d default: 0 (blocking I/O)\n" \ + " options: 1 (non-blocking), 2 (added delays)\n" \ + "\n" \ + " auth_mode=%%s default: \"optional\"\n" \ + " options: none, optional, required\n" \ USAGE_IO \ - " request_page=%%s default: \".\"\n" \ + USAGE_SNI \ + "\n" \ + USAGE_PSK \ + "\n" \ " renegotiation=%%d default: 1 (enabled)\n" \ - USAGE_TICKETS \ " allow_legacy=%%d default: 0 (disabled)\n" \ + " renegotiate=%%d default: 0 (disabled)\n" \ + USAGE_TICKETS \ + USAGE_CACHE \ + USAGE_MAX_FRAG_LEN \ + "\n" \ " 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" \ - " auth_mode=%%s default: \"optional\"\n" \ - " options: none, optional, required\n" \ - USAGE_MAX_FRAG_LEN \ - USAGE_PSK \ "\n" \ " force_ciphersuite= default: all enabled\n"\ " acceptable ciphersuite names:\n" @@ -208,6 +290,116 @@ int main( int argc, char *argv[] ) return( 0 ); } #else + +#if defined(POLARSSL_SNI) +typedef struct _sni_entry sni_entry; + +struct _sni_entry { + const char *name; + x509_crt *cert; + pk_context *key; + sni_entry *next; +}; + +/* + * 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. + */ +sni_entry *sni_parse( char *sni_string ) +{ + sni_entry *cur = NULL, *new = NULL; + char *p = sni_string; + char *end = p; + char *crt_file, *key_file; + + while( *end != '\0' ) + ++end; + *end = ','; + + while( p <= end ) + { + if( ( new = polarssl_malloc( sizeof( sni_entry ) ) ) == NULL ) + return( NULL ); + + memset( new, 0, sizeof( sni_entry ) ); + + if( ( new->cert = polarssl_malloc( sizeof( x509_crt ) ) ) == NULL || + ( new->key = polarssl_malloc( sizeof( pk_context ) ) ) == NULL ) + return( NULL ); + + x509_crt_init( new->cert ); + pk_init( new->key ); + + new->name = p; + while( *p != ',' ) if( ++p > end ) return( NULL ); + *p++ = '\0'; + + crt_file = p; + while( *p != ',' ) if( ++p > end ) return( NULL ); + *p++ = '\0'; + + key_file = p; + while( *p != ',' ) if( ++p > end ) return( NULL ); + *p++ = '\0'; + + if( x509_crt_parse_file( new->cert, crt_file ) != 0 || + pk_parse_keyfile( new->key, key_file, "" ) != 0 ) + return( NULL ); + + new->next = cur; + cur = new; + + } + + return( cur ); +} + +void sni_free( sni_entry *head ) +{ + sni_entry *cur = head, *next; + + while( cur != NULL ) + { + x509_crt_free( cur->cert ); + polarssl_free( cur->cert ); + + pk_free( cur->key ); + polarssl_free( cur->key ); + + next = cur->next; + polarssl_free( cur ); + cur = next; + } +} + +/* + * SNI callback. + */ +int sni_callback( void *p_info, ssl_context *ssl, + const unsigned char *name, size_t name_len ) +{ + sni_entry *cur = (sni_entry *) p_info; + + while( cur != NULL ) + { + if( name_len == strlen( cur->name ) && + memcmp( name, cur->name, name_len ) == 0 ) + { + ssl_set_own_cert( ssl, cur->cert, cur->key ); + return( 0 ); + } + + cur = cur->next; + } + + return( -1 ); +} + +#endif /* POLARSSL_SNI */ + int main( int argc, char *argv[] ) { int ret = 0, len, written, frags; @@ -234,6 +426,9 @@ int main( int argc, char *argv[] ) #if defined(POLARSSL_SSL_CACHE_C) ssl_cache_context cache; #endif +#if defined(POLARSSL_SNI) + sni_entry *sni_info = NULL; +#endif #if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) unsigned char alloc_buf[100000]; #endif @@ -287,6 +482,7 @@ int main( int argc, char *argv[] ) opt.server_addr = DFL_SERVER_ADDR; opt.server_port = DFL_SERVER_PORT; opt.debug_level = DFL_DEBUG_LEVEL; + opt.nbio = DFL_NBIO; opt.ca_file = DFL_CA_FILE; opt.ca_path = DFL_CA_PATH; opt.crt_file = DFL_CRT_FILE; @@ -298,11 +494,16 @@ int main( int argc, char *argv[] ) opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; opt.renegotiation = DFL_RENEGOTIATION; opt.allow_legacy = DFL_ALLOW_LEGACY; + opt.renegotiate = DFL_RENEGOTIATE; opt.min_version = DFL_MIN_VERSION; opt.max_version = DFL_MAX_VERSION; opt.auth_mode = DFL_AUTH_MODE; opt.mfl_code = DFL_MFL_CODE; opt.tickets = DFL_TICKETS; + opt.ticket_timeout = DFL_TICKET_TIMEOUT; + opt.cache_max = DFL_CACHE_MAX; + opt.cache_timeout = DFL_CACHE_TIMEOUT; + opt.sni = DFL_SNI; for( i = 1; i < argc; i++ ) { @@ -325,6 +526,12 @@ int main( int argc, char *argv[] ) if( opt.debug_level < 0 || opt.debug_level > 65535 ) goto usage; } + else if( strcmp( p, "nbio" ) == 0 ) + { + opt.nbio = atoi( q ); + if( opt.nbio < 0 || opt.nbio > 2 ) + goto usage; + } else if( strcmp( p, "ca_file" ) == 0 ) opt.ca_file = q; else if( strcmp( p, "ca_path" ) == 0 ) @@ -365,6 +572,12 @@ int main( int argc, char *argv[] ) if( opt.allow_legacy < 0 || opt.allow_legacy > 1 ) goto usage; } + else if( strcmp( p, "renegotiate" ) == 0 ) + { + opt.renegotiate = atoi( q ); + if( opt.renegotiate < 0 || opt.renegotiate > 1 ) + goto usage; + } else if( strcmp( p, "min_version" ) == 0 ) { if( strcmp( q, "ssl3" ) == 0 ) @@ -446,6 +659,28 @@ int main( int argc, char *argv[] ) if( opt.tickets < 0 || opt.tickets > 1 ) goto usage; } + else if( strcmp( p, "ticket_timeout" ) == 0 ) + { + opt.ticket_timeout = atoi( q ); + if( opt.ticket_timeout < 0 ) + goto usage; + } + else if( strcmp( p, "cache_max" ) == 0 ) + { + opt.cache_max = atoi( q ); + if( opt.cache_max < 0 ) + goto usage; + } + else if( strcmp( p, "cache_timeout" ) == 0 ) + { + opt.cache_timeout = atoi( q ); + if( opt.cache_timeout < 0 ) + goto usage; + } + else if( strcmp( p, "sni" ) == 0 ) + { + opt.sni = q; + } else goto usage; } @@ -551,9 +786,15 @@ int main( int argc, char *argv[] ) #if defined(POLARSSL_FS_IO) if( strlen( opt.ca_path ) ) - ret = x509_crt_parse_path( &cacert, opt.ca_path ); + if( strcmp( opt.ca_path, "none" ) == 0 ) + ret = 0; + else + ret = x509_crt_parse_path( &cacert, opt.ca_path ); else if( strlen( opt.ca_file ) ) - ret = x509_crt_parse_file( &cacert, opt.ca_file ); + if( strcmp( opt.ca_file, "none" ) == 0 ) + ret = 0; + else + ret = x509_crt_parse_file( &cacert, opt.ca_file ); else #endif #if defined(POLARSSL_CERTS_C) @@ -580,7 +821,7 @@ int main( int argc, char *argv[] ) fflush( stdout ); #if defined(POLARSSL_FS_IO) - if( strlen( opt.crt_file ) ) + if( strlen( opt.crt_file ) && strcmp( opt.crt_file, "none" ) != 0 ) { key_cert_init++; if( ( ret = x509_crt_parse_file( &srvcert, opt.crt_file ) ) != 0 ) @@ -590,7 +831,7 @@ int main( int argc, char *argv[] ) goto exit; } } - if( strlen( opt.key_file ) ) + if( strlen( opt.key_file ) && strcmp( opt.key_file, "none" ) != 0 ) { key_cert_init++; if( ( ret = pk_parse_keyfile( &pkey, opt.key_file, "" ) ) != 0 ) @@ -605,7 +846,7 @@ int main( int argc, char *argv[] ) goto exit; } - if( strlen( opt.crt_file2 ) ) + if( strlen( opt.crt_file2 ) && strcmp( opt.crt_file2, "none" ) != 0 ) { key_cert_init2++; if( ( ret = x509_crt_parse_file( &srvcert2, opt.crt_file2 ) ) != 0 ) @@ -615,7 +856,7 @@ int main( int argc, char *argv[] ) goto exit; } } - if( strlen( opt.key_file2 ) ) + if( strlen( opt.key_file2 ) && strcmp( opt.key_file2, "none" ) != 0 ) { key_cert_init2++; if( ( ret = pk_parse_keyfile( &pkey2, opt.key_file2, "" ) ) != 0 ) @@ -631,7 +872,12 @@ int main( int argc, char *argv[] ) goto exit; } #endif - if( key_cert_init == 0 && key_cert_init2 == 0 ) + if( key_cert_init == 0 && + strcmp( opt.crt_file, "none" ) != 0 && + strcmp( opt.key_file, "none" ) != 0 && + key_cert_init2 == 0 && + strcmp( opt.crt_file2, "none" ) != 0 && + strcmp( opt.key_file2, "none" ) != 0 ) { #if !defined(POLARSSL_CERTS_C) printf( "Not certificated or key provided, and \n" @@ -678,6 +924,22 @@ int main( int argc, char *argv[] ) printf( " ok\n" ); #endif /* POLARSSL_X509_CRT_PARSE_C */ +#if defined(POLARSSL_SNI) + if( opt.sni != NULL ) + { + printf( " . Setting up SNI information..." ); + fflush( stdout ); + + if( ( sni_info = sni_parse( opt.sni ) ) == NULL ) + { + printf( " failed\n" ); + goto exit; + } + + printf( " ok\n" ); + } +#endif /* POLARSSL_SNI */ + /* * 2. Setup the listening TCP socket */ @@ -716,12 +978,21 @@ int main( int argc, char *argv[] ) ssl_set_dbg( &ssl, my_debug, stdout ); #if defined(POLARSSL_SSL_CACHE_C) + if( opt.cache_max != -1 ) + ssl_cache_set_max_entries( &cache, opt.cache_max ); + + if( opt.cache_timeout != -1 ) + ssl_cache_set_timeout( &cache, opt.cache_timeout ); + ssl_set_session_cache( &ssl, ssl_cache_get, &cache, ssl_cache_set, &cache ); #endif #if defined(POLARSSL_SSL_SESSION_TICKETS) ssl_set_session_tickets( &ssl, opt.tickets ); + + if( opt.ticket_timeout != -1 ) + ssl_set_session_ticket_lifetime( &ssl, opt.ticket_timeout ); #endif if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) @@ -731,13 +1002,22 @@ int main( int argc, char *argv[] ) ssl_legacy_renegotiation( &ssl, opt.allow_legacy ); #if defined(POLARSSL_X509_CRT_PARSE_C) - ssl_set_ca_chain( &ssl, &cacert, NULL, NULL ); + if( strcmp( opt.ca_path, "none" ) != 0 && + strcmp( opt.ca_file, "none" ) != 0 ) + { + ssl_set_ca_chain( &ssl, &cacert, NULL, NULL ); + } if( key_cert_init ) ssl_set_own_cert( &ssl, &srvcert, &pkey ); if( key_cert_init2 ) ssl_set_own_cert( &ssl, &srvcert2, &pkey2 ); #endif +#if defined(POLARSSL_SNI) + if( opt.sni != NULL ) + ssl_set_sni( &ssl, sni_callback, sni_info ); +#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 ) ); @@ -788,8 +1068,20 @@ reset: goto exit; } - ssl_set_bio( &ssl, net_recv, &client_fd, - net_send, &client_fd ); + if( opt.nbio > 0 ) + ret = net_set_nonblock( client_fd ); + else + ret = net_set_block( client_fd ); + if( ret != 0 ) + { + printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret ); + goto exit; + } + + if( opt.nbio == 2 ) + ssl_set_bio( &ssl, my_recv, &client_fd, my_send, &client_fd ); + else + ssl_set_bio( &ssl, net_recv, &client_fd, net_send, &client_fd ); printf( " ok\n" ); @@ -926,43 +1218,48 @@ reset: buf[written] = '\0'; printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf ); -#ifdef TEST_RENEGO - /* - * Request renegotiation (this must be done when the client is still - * waiting for input from our side). - */ - printf( " . Requestion renegotiation..." ); - fflush( stdout ); - while( ( ret = ssl_renegotiate( &ssl ) ) != 0 ) + if( opt.renegotiate ) { - if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) + /* + * Request renegotiation (this must be done when the client is still + * waiting for input from our side). + */ + printf( " . Requestion renegotiation..." ); + fflush( stdout ); + while( ( ret = ssl_renegotiate( &ssl ) ) != 0 ) { - printf( " failed\n ! ssl_renegotiate returned %d\n\n", ret ); - goto exit; - } - } - - /* - * Should be a while loop, not an if, but here we're not actually - * expecting data from the client, and since we're running tests locally, - * we can just hope the handshake will finish the during the first call. - */ - if( ( ret = ssl_read( &ssl, buf, 0 ) ) != 0 ) - { - if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) - { - printf( " failed\n ! ssl_read returned %d\n\n", ret ); - - /* Unexpected message probably means client didn't renegotiate */ - if( ret == POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ) - goto reset; - else + if( ret != POLARSSL_ERR_NET_WANT_READ && + ret != POLARSSL_ERR_NET_WANT_WRITE ) + { + printf( " failed\n ! ssl_renegotiate returned %d\n\n", ret ); goto exit; + } } - } - printf( " ok\n" ); -#endif + /* + * Should be a while loop, not an if, but here we're not actually + * expecting data from the client, and since we're running tests + * locally, we can just hope the handshake will finish the during the + * first call. + */ + if( ( ret = ssl_read( &ssl, buf, 0 ) ) != 0 ) + { + if( ret != POLARSSL_ERR_NET_WANT_READ && + ret != POLARSSL_ERR_NET_WANT_WRITE ) + { + printf( " failed\n ! ssl_read returned %d\n\n", ret ); + + /* Unexpected message probably means client didn't renegotiate + * as requested */ + if( ret == POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ) + goto reset; + else + goto exit; + } + } + + printf( " ok\n" ); + } ret = 0; goto reset; @@ -986,6 +1283,9 @@ exit: x509_crt_free( &srvcert2 ); pk_free( &pkey2 ); #endif +#if defined(POLARSSL_SNI) + sni_free( sni_info ); +#endif ssl_free( &ssl ); entropy_free( &entropy ); diff --git a/tests/Descriptions.txt b/tests/Descriptions.txt new file mode 100644 index 000000000..5b546e939 --- /dev/null +++ b/tests/Descriptions.txt @@ -0,0 +1,16 @@ +test_suites + The various 'test_suite_XXX' programs from the 'tests' directory, executed + using 'make check' (Unix make) or 'make test' (Cmake), include test cases + (reference test vectors, sanity checks, etc.) for all modules except the + SSL modules. + +compat + The 'tests/compat.sh' script checks interoperability with OpenSSL for every + ciphersuite, in every version, using client authentication or not. For + each ciphersuite/version it performs a full handshake and a small data + exchange. + +ssl_opt + The 'tests/ssl-opt.sh' script checks various options and/or operations not + covered by compat.sh: session resumption (using session cache or tickets), + renegotiation, SNI, other extensions, etc. diff --git a/tests/compat.sh b/tests/compat.sh index bf1691b3b..d06adb8d2 100755 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -1,69 +1,87 @@ #!/bin/bash -killall -q openssl ssl_server ssl_server2 +# Test interop with OpenSSL for each common ciphersuite and version. +# Also test selfop for ciphersuites not shared with OpenSSL. + +set -u let "tests = 0" let "failed = 0" let "skipped = 0" +let "srvmem = 0" + +# default values, can be overriden by the environment +: ${P_SRV:=../programs/ssl/ssl_server2} +: ${P_CLI:=../programs/ssl/ssl_client2} +: ${OPENSSL_CMD:=openssl} # OPENSSL would conflict with the build system +: ${GNUTLS_CLI:=gnutls-cli} +: ${GNUTLS_SERV:=gnutls-serv} MODES="ssl3 tls1 tls1_1 tls1_2" VERIFIES="NO YES" TYPES="ECDSA RSA PSK" -OPENSSL=openssl FILTER="" +EXCLUDE='NULL\|DES-CBC-' # avoid plain DES but keep 3DES-EDE-CBC (PolarSSL), DES-CBC3 (OpenSSL) VERBOSE="" +PEERS="OpenSSL PolarSSL" # GnuTLS not enabled by default, 3.2.4 might not be available on all buildbot machines +MEMCHECK=0 -# Parse arguments -# -until [ -z "$1" ] -do - case "$1" in - -f|--filter) - # Filter ciphersuites - shift - FILTER=$1 - ;; - -m|--modes) - # Perform modes - shift - MODES=$1 - ;; - -t|--types) - # Key exchange types - shift - TYPES=$1 - ;; - -V|--verify) - # Verifiction modes - shift - VERIFIES=$1 - ;; - -v|--verbose) - # Set verbosity - shift - VERBOSE=1 - ;; - -h|--help) - # print help - echo "Usage: $0" - echo -e " -f|--filter\tFilter ciphersuites to test (Default: all)" - echo -e " -h|--help\t\tPrint this help." - echo -e " -m|--modes\tWhich modes to perform (Default: \"ssl3 tls1 tls1_1 tls1_2\")" - echo -e " -t|--types\tWhich key exchange type to perform (Default: \"ECDSA RSA PSK\")" - echo -e " -V|--verify\tWhich verification modes to perform (Default: \"NO YES\")" - echo -e " -v|--verbose\t\tSet verbose output." - exit 1 - ;; - *) - # print error - echo "Unknown argument: '$1'" - exit 1 - ;; - esac - shift -done +print_usage() { + echo "Usage: $0" + echo -e " -h|--help\tPrint this help." + echo -e " -f|--filter\tOnly matching ciphersuites are tested (Default: '$FILTER')" + echo -e " -e|--exclude\tMatching ciphersuites are excluded (Default: '$EXCLUDE')" + echo -e " -m|--modes\tWhich modes to perform (Default: '$MODES')" + echo -e " -t|--types\tWhich key exchange type to perform (Default: '$TYPES')" + echo -e " -V|--verify\tWhich verification modes to perform (Default: '$VERIFIES')" + echo -e " -p|--peers\tWhich peers to use (Default: '$PEERS')" + echo -e " \tAlso available: GnuTLS (needs v3.2.4 or higher)" + echo -e " -M|--memcheck\tCheck memory leaks and errors." + echo -e " -v|--verbose\tSet verbose output." +} -log () { +get_options() { + while [ $# -gt 0 ]; do + case "$1" in + -f|--filter) + shift; FILTER=$1 + ;; + -e|--exclude) + shift; EXCLUDE=$1 + ;; + -m|--modes) + shift; MODES=$1 + ;; + -t|--types) + shift; TYPES=$1 + ;; + -V|--verify) + shift; VERIFIES=$1 + ;; + -p|--peers) + shift; PEERS=$1 + ;; + -v|--verbose) + VERBOSE=1 + ;; + -M|--memcheck) + MEMCHECK=1 + ;; + -h|--help) + print_usage + exit 0 + ;; + *) + echo "Unknown argument: '$1'" + print_usage + exit 1 + ;; + esac + shift + done +} + +log() { if [ "X" != "X$VERBOSE" ]; then echo "$@" fi @@ -71,509 +89,822 @@ log () { filter() { - LIST=$1 - FILTER=$2 - + LIST="$1" NEW_LIST="" for i in $LIST; do - NEW_LIST="$NEW_LIST $( echo "$i" | grep "$FILTER" )" + NEW_LIST="$NEW_LIST $( echo "$i" | grep "$FILTER" | grep -v "$EXCLUDE" )" done - echo "$NEW_LIST" + # normalize whitespace + echo "$NEW_LIST" | sed -e 's/[[:space:]]\+/ /g' -e 's/^ //' -e 's/ $//' } -for VERIFY in $VERIFIES; -do - -if [ "X$VERIFY" = "XYES" ]; -then - P_SERVER_BASE="ca_file=data_files/test-ca_cat12.crt auth_mode=required" - P_CLIENT_BASE="ca_file=data_files/test-ca_cat12.crt" - O_SERVER_BASE="-CAfile data_files/test-ca_cat12.crt -Verify 10" - O_CLIENT_BASE="-CAfile data_files/test-ca_cat12.crt" -else - P_SERVER_BASE="" - P_CLIENT_BASE="" - O_SERVER_BASE="" - O_CLIENT_BASE="" -fi - - -for MODE in $MODES; -do - -# avoid an avalanche of errors due to typos -case $MODE in - ssl3|tls1|tls1_1|tls1_2) - ;; - *) - echo "error: invalid mode: $MODE" >&2 - exit 1; -esac - -echo "-----------" -echo "Running for $MODE (Verify: $VERIFY)" -echo "-----------" - -for TYPE in $TYPES; -do - -P_CIPHERS="" -O_CIPHERS="" - -case $TYPE in - - "ECDSA") - - P_SERVER_ARGS="$P_SERVER_BASE crt_file=data_files/server5.crt key_file=data_files/server5.key" - P_CLIENT_ARGS="$P_CLIENT_BASE crt_file=data_files/server6.crt key_file=data_files/server6.key" - O_SERVER_ARGS="$O_SERVER_BASE -cert data_files/server5.crt -key data_files/server5.key" - O_CLIENT_ARGS="$O_CLIENT_BASE -cert data_files/server6.crt -key data_files/server6.key" - - if [ "$MODE" != "ssl3" ]; - then - P_CIPHERS="$P_CIPHERS \ - TLS-ECDHE-ECDSA-WITH-NULL-SHA \ - TLS-ECDHE-ECDSA-WITH-RC4-128-SHA \ - TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA \ - TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA \ - TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA \ - TLS-ECDH-ECDSA-WITH-NULL-SHA \ - TLS-ECDH-ECDSA-WITH-RC4-128-SHA \ - TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA \ - TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA \ - TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA \ - " - - O_CIPHERS="$O_CIPHERS \ - ECDHE-ECDSA-NULL-SHA \ - ECDHE-ECDSA-RC4-SHA \ - ECDHE-ECDSA-DES-CBC3-SHA \ - ECDHE-ECDSA-AES128-SHA \ - ECDHE-ECDSA-AES256-SHA \ - ECDH-ECDSA-NULL-SHA \ - ECDH-ECDSA-RC4-SHA \ - ECDH-ECDSA-DES-CBC3-SHA \ - ECDH-ECDSA-AES128-SHA \ - ECDH-ECDSA-AES256-SHA \ - " - fi - - if [ "$MODE" = "tls1_2" ]; - then - P_CIPHERS="$P_CIPHERS \ - TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 \ - TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384 \ - TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ - TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 \ - TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256 \ - TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384 \ - TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256 \ - TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384 \ - " - - O_CIPHERS="$O_CIPHERS \ - ECDHE-ECDSA-AES128-SHA256 \ - ECDHE-ECDSA-AES256-SHA384 \ - ECDHE-ECDSA-AES128-GCM-SHA256 \ - ECDHE-ECDSA-AES256-GCM-SHA384 \ - ECDH-ECDSA-AES128-SHA256 \ - ECDH-ECDSA-AES256-SHA384 \ - ECDH-ECDSA-AES128-GCM-SHA256 \ - ECDH-ECDSA-AES256-GCM-SHA384 \ - " - fi - - ;; - - "RSA") - - P_SERVER_ARGS="$P_SERVER_BASE crt_file=data_files/server1.crt key_file=data_files/server1.key" - P_CLIENT_ARGS="$P_CLIENT_BASE crt_file=data_files/server2.crt key_file=data_files/server2.key" - O_SERVER_ARGS="$O_SERVER_BASE -cert data_files/server1.crt -key data_files/server1.key" - O_CLIENT_ARGS="$O_CLIENT_BASE -cert data_files/server2.crt -key data_files/server2.key" - - P_CIPHERS="$P_CIPHERS \ - TLS-DHE-RSA-WITH-AES-128-CBC-SHA \ - TLS-DHE-RSA-WITH-AES-256-CBC-SHA \ - TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA \ - TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA \ - TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA \ - TLS-RSA-WITH-AES-256-CBC-SHA \ - TLS-RSA-WITH-CAMELLIA-256-CBC-SHA \ - TLS-RSA-WITH-AES-128-CBC-SHA \ - TLS-RSA-WITH-CAMELLIA-128-CBC-SHA \ - TLS-RSA-WITH-3DES-EDE-CBC-SHA \ - TLS-RSA-WITH-RC4-128-SHA \ - TLS-RSA-WITH-RC4-128-MD5 \ - TLS-RSA-WITH-NULL-MD5 \ - TLS-RSA-WITH-NULL-SHA \ - TLS-RSA-WITH-DES-CBC-SHA \ - TLS-DHE-RSA-WITH-DES-CBC-SHA \ - " - - O_CIPHERS="$O_CIPHERS \ - DHE-RSA-AES128-SHA \ - DHE-RSA-AES256-SHA \ - DHE-RSA-CAMELLIA128-SHA \ - DHE-RSA-CAMELLIA256-SHA \ - EDH-RSA-DES-CBC3-SHA \ - AES256-SHA \ - CAMELLIA256-SHA \ - AES128-SHA \ - CAMELLIA128-SHA \ - DES-CBC3-SHA \ - RC4-SHA \ - RC4-MD5 \ - NULL-MD5 \ - NULL-SHA \ - DES-CBC-SHA \ - EDH-RSA-DES-CBC-SHA \ - " - - if [ "$MODE" != "ssl3" ]; - then - P_CIPHERS="$P_CIPHERS \ - TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA \ - TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA \ - TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA \ - TLS-ECDHE-RSA-WITH-RC4-128-SHA \ - TLS-ECDHE-RSA-WITH-NULL-SHA \ - " - - O_CIPHERS="$O_CIPHERS \ - ECDHE-RSA-AES256-SHA \ - ECDHE-RSA-AES128-SHA \ - ECDHE-RSA-DES-CBC3-SHA \ - ECDHE-RSA-RC4-SHA \ - ECDHE-RSA-NULL-SHA \ - " - fi - - if [ "$MODE" = "tls1_2" ]; - then - P_CIPHERS="$P_CIPHERS \ - TLS-RSA-WITH-NULL-SHA256 \ - TLS-RSA-WITH-AES-128-CBC-SHA256 \ - TLS-DHE-RSA-WITH-AES-128-CBC-SHA256 \ - TLS-RSA-WITH-AES-256-CBC-SHA256 \ - TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 \ - TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256 \ - TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384 \ - TLS-RSA-WITH-AES-128-GCM-SHA256 \ - TLS-RSA-WITH-AES-256-GCM-SHA384 \ - TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 \ - TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 \ - TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 \ - TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384 \ - " - - O_CIPHERS="$O_CIPHERS \ - NULL-SHA256 \ - AES128-SHA256 \ - DHE-RSA-AES128-SHA256 \ - AES256-SHA256 \ - DHE-RSA-AES256-SHA256 \ - ECDHE-RSA-AES128-SHA256 \ - ECDHE-RSA-AES256-SHA384 \ - AES128-GCM-SHA256 \ - DHE-RSA-AES128-GCM-SHA256 \ - AES256-GCM-SHA384 \ - DHE-RSA-AES256-GCM-SHA384 \ - ECDHE-RSA-AES128-GCM-SHA256 \ - ECDHE-RSA-AES256-GCM-SHA384 \ - " - fi - - ;; - - "PSK") - - P_SERVER_ARGS="$P_SERVER_BASE psk=6162636465666768696a6b6c6d6e6f70" - P_CLIENT_ARGS="$P_CLIENT_BASE psk=6162636465666768696a6b6c6d6e6f70" - # openssl s_server won't start without certificates... - O_SERVER_ARGS="$O_SERVER_BASE -psk 6162636465666768696a6b6c6d6e6f70 -cert data_files/server1.crt -key data_files/server1.key" - O_CLIENT_ARGS="$O_CLIENT_BASE -psk 6162636465666768696a6b6c6d6e6f70" - - P_CIPHERS="$P_CIPHERS \ - TLS-PSK-WITH-RC4-128-SHA \ - TLS-PSK-WITH-3DES-EDE-CBC-SHA \ - TLS-PSK-WITH-AES-128-CBC-SHA \ - TLS-PSK-WITH-AES-256-CBC-SHA \ - " - - O_CIPHERS="$O_CIPHERS \ - PSK-RC4-SHA \ - PSK-3DES-EDE-CBC-SHA \ - PSK-AES128-CBC-SHA \ - PSK-AES256-CBC-SHA \ - " - - ;; - -esac - -# Filter ciphersuites -if [ "X" != "X$FILTER" ]; -then - O_CIPHERS=$( filter "$O_CIPHERS" "$FILTER" ) - P_CIPHERS=$( filter "$P_CIPHERS" "$FILTER" ) -fi - - -log "$OPENSSL s_server -www -quiet -cipher NULL,ALL $O_SERVER_ARGS -$MODE" -$OPENSSL s_server -www -quiet -cipher NULL,ALL $O_SERVER_ARGS -$MODE >/dev/null 2>&1 & -PROCESS_ID=$! - -sleep 1 - -for i in $P_CIPHERS; -do - let "tests++" - log "../programs/ssl/ssl_client2 $P_CLIENT_ARGS force_ciphersuite=$i force_version=$MODE" - RESULT="$( ../programs/ssl/ssl_client2 $P_CLIENT_ARGS force_ciphersuite=$i force_version=$MODE )" - EXIT=$? - echo -n "OpenSSL Server - PolarSSL Client - $i : $EXIT - " - if [ "$EXIT" = "2" ]; +filter_ciphersuites() +{ + if [ "X" != "X$FILTER" -o "X" != "X$EXCLUDE" ]; then - echo Ciphersuite not supported in client - let "skipped++" - elif [ "$EXIT" != "0" ]; - then - echo Failed - echo "$OPENSSL s_server -www -quiet -cipher NULL,ALL $O_SERVER_ARGS -$MODE" - echo "ssl_client2 force_ciphersuite=$i force_version=$MODE $P_CLIENT_ARGS" - echo $RESULT - let "failed++" - else - echo Success + P_CIPHERS=$( filter "$P_CIPHERS" ) + O_CIPHERS=$( filter "$O_CIPHERS" ) + G_CIPHERS=$( filter "$G_CIPHERS" ) fi -done -kill $PROCESS_ID 2>/dev/null -wait $PROCESS_ID 2>/dev/null +} -log "../programs/ssl/ssl_server2 server_addr=0.0.0.0 $P_SERVER_ARGS force_version=$MODE > /dev/null" -../programs/ssl/ssl_server2 server_addr=0.0.0.0 $P_SERVER_ARGS force_version=$MODE > /dev/null & -PROCESS_ID=$! +reset_ciphersuites() +{ + P_CIPHERS="" + O_CIPHERS="" + G_CIPHERS="" +} -sleep 1 +add_openssl_ciphersuites() +{ + case $TYPE in -for i in $O_CIPHERS; -do - let "tests++" - log "$OPENSSL s_client -$MODE -cipher $i $O_CLIENT_ARGS" - RESULT="$( ( echo -e 'GET HTTP/1.0'; echo; sleep 1 ) | $OPENSSL s_client -$MODE -cipher $i $O_CLIENT_ARGS 2>&1 )" - EXIT=$? - echo -n "PolarSSL Server - OpenSSL Client - $i : $EXIT - " + "ECDSA") + if [ "$MODE" != "ssl3" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-ECDHE-ECDSA-WITH-NULL-SHA \ + TLS-ECDHE-ECDSA-WITH-RC4-128-SHA \ + TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA \ + TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA \ + TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA \ + TLS-ECDH-ECDSA-WITH-NULL-SHA \ + TLS-ECDH-ECDSA-WITH-RC4-128-SHA \ + TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA \ + TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA \ + TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA \ + " + O_CIPHERS="$O_CIPHERS \ + ECDHE-ECDSA-NULL-SHA \ + ECDHE-ECDSA-RC4-SHA \ + ECDHE-ECDSA-DES-CBC3-SHA \ + ECDHE-ECDSA-AES128-SHA \ + ECDHE-ECDSA-AES256-SHA \ + ECDH-ECDSA-NULL-SHA \ + ECDH-ECDSA-RC4-SHA \ + ECDH-ECDSA-DES-CBC3-SHA \ + ECDH-ECDSA-AES128-SHA \ + ECDH-ECDSA-AES256-SHA \ + " + fi + if [ "$MODE" = "tls1_2" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 \ + TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384 \ + TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 \ + TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256 \ + TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384 \ + TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256 \ + TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384 \ + " + O_CIPHERS="$O_CIPHERS \ + ECDHE-ECDSA-AES128-SHA256 \ + ECDHE-ECDSA-AES256-SHA384 \ + ECDHE-ECDSA-AES128-GCM-SHA256 \ + ECDHE-ECDSA-AES256-GCM-SHA384 \ + ECDH-ECDSA-AES128-SHA256 \ + ECDH-ECDSA-AES256-SHA384 \ + ECDH-ECDSA-AES128-GCM-SHA256 \ + ECDH-ECDSA-AES256-GCM-SHA384 \ + " + fi + ;; - if [ "$EXIT" != "0" ]; - then - SUPPORTED="$( echo $RESULT | grep 'Cipher is (NONE)' )" - if [ "X$SUPPORTED" != "X" ] - then - echo "Ciphersuite not supported in server" - let "skipped++" - else - echo Failed - echo "ssl_server2 $P_SERVER_ARGS force_version=$MODE" - echo "$OPENSSL s_client -$MODE -cipher $i $O_CLIENT_ARGS" - echo $RESULT - let "failed++" - fi - else - echo Success - fi -done - -kill $PROCESS_ID 2>/dev/null -wait $PROCESS_ID 2>/dev/null - -log "../programs/ssl/ssl_server2 server_addr=0.0.0.0 $P_SERVER_ARGS force_version=$MODE" -../programs/ssl/ssl_server2 server_addr=0.0.0.0 $P_SERVER_ARGS force_version=$MODE > /dev/null & -PROCESS_ID=$! - -sleep 1 - -# Add ciphersuites supported by PolarSSL only - -case $TYPE in - - "ECDSA") - - if [ "$MODE" != "ssl3" ]; - then - P_CIPHERS="$P_CIPHERS \ - TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256 \ - TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384 \ - TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256 \ - TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384 \ - " - fi - - if [ "$MODE" = "tls1_2" ]; - then - P_CIPHERS="$P_CIPHERS \ - TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256 \ - TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384 \ - TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256 \ - TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384 \ - " - fi - - ;; - - "RSA") - - if [ "$MODE" != "ssl3" ]; - then - P_CIPHERS="$P_CIPHERS \ - TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 \ - TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384 \ - " - fi - - if [ "$MODE" = "tls1_2" ]; - then - P_CIPHERS="$P_CIPHERS \ - TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256 \ - TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256 \ - TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 \ - TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256 \ - TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256 \ - TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384 \ - TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256 \ - TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384 \ - TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256 \ - TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384 \ - " - fi - - ;; - - "PSK") - - P_CIPHERS="$P_CIPHERS \ - TLS-DHE-PSK-WITH-RC4-128-SHA \ - TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA \ - TLS-DHE-PSK-WITH-AES-128-CBC-SHA \ - TLS-DHE-PSK-WITH-AES-256-CBC-SHA \ - TLS-DHE-PSK-WITH-NULL-SHA \ - TLS-PSK-WITH-NULL-SHA \ - TLS-RSA-PSK-WITH-RC4-128-SHA \ - TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA \ - TLS-RSA-PSK-WITH-AES-256-CBC-SHA \ - TLS-RSA-PSK-WITH-AES-128-CBC-SHA \ - TLS-RSA-WITH-NULL-SHA \ - TLS-RSA-WITH-NULL-MD5 \ - TLS-PSK-WITH-AES-128-CBC-SHA256 \ - TLS-PSK-WITH-AES-256-CBC-SHA384 \ - TLS-DHE-PSK-WITH-AES-128-CBC-SHA256 \ - TLS-DHE-PSK-WITH-AES-256-CBC-SHA384 \ - TLS-PSK-WITH-NULL-SHA256 \ - TLS-PSK-WITH-NULL-SHA384 \ - TLS-DHE-PSK-WITH-NULL-SHA256 \ - TLS-DHE-PSK-WITH-NULL-SHA384 \ - TLS-RSA-PSK-WITH-AES-256-CBC-SHA384 \ - TLS-RSA-PSK-WITH-AES-128-CBC-SHA256 \ - TLS-RSA-PSK-WITH-NULL-SHA256 \ - TLS-RSA-PSK-WITH-NULL-SHA384 \ - TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256 \ - TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384 \ - TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256 \ - TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384 \ - TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384 \ - TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256 \ - " - - - if [ "$MODE" != "ssl3" ]; - then + "RSA") P_CIPHERS="$P_CIPHERS \ - TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA \ - TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA \ - TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA \ - TLS-ECDHE-PSK-WITH-RC4-128-SHA \ - TLS-ECDHE-PSK-WITH-NULL-SHA \ - TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384 \ - TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384 \ - TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 \ - TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256 \ - TLS-ECDHE-PSK-WITH-NULL-SHA384 \ - TLS-ECDHE-PSK-WITH-NULL-SHA256 \ + TLS-DHE-RSA-WITH-AES-128-CBC-SHA \ + TLS-DHE-RSA-WITH-AES-256-CBC-SHA \ + TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA \ + TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA \ + TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA \ + TLS-RSA-WITH-AES-256-CBC-SHA \ + TLS-RSA-WITH-CAMELLIA-256-CBC-SHA \ + TLS-RSA-WITH-AES-128-CBC-SHA \ + TLS-RSA-WITH-CAMELLIA-128-CBC-SHA \ + TLS-RSA-WITH-3DES-EDE-CBC-SHA \ + TLS-RSA-WITH-RC4-128-SHA \ + TLS-RSA-WITH-RC4-128-MD5 \ + TLS-RSA-WITH-NULL-MD5 \ + TLS-RSA-WITH-NULL-SHA \ + TLS-RSA-WITH-DES-CBC-SHA \ + TLS-DHE-RSA-WITH-DES-CBC-SHA \ " - fi + O_CIPHERS="$O_CIPHERS \ + DHE-RSA-AES128-SHA \ + DHE-RSA-AES256-SHA \ + DHE-RSA-CAMELLIA128-SHA \ + DHE-RSA-CAMELLIA256-SHA \ + EDH-RSA-DES-CBC3-SHA \ + AES256-SHA \ + CAMELLIA256-SHA \ + AES128-SHA \ + CAMELLIA128-SHA \ + DES-CBC3-SHA \ + RC4-SHA \ + RC4-MD5 \ + NULL-MD5 \ + NULL-SHA \ + DES-CBC-SHA \ + EDH-RSA-DES-CBC-SHA \ + " + if [ "$MODE" != "ssl3" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA \ + TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA \ + TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA \ + TLS-ECDHE-RSA-WITH-RC4-128-SHA \ + TLS-ECDHE-RSA-WITH-NULL-SHA \ + " + O_CIPHERS="$O_CIPHERS \ + ECDHE-RSA-AES256-SHA \ + ECDHE-RSA-AES128-SHA \ + ECDHE-RSA-DES-CBC3-SHA \ + ECDHE-RSA-RC4-SHA \ + ECDHE-RSA-NULL-SHA \ + " + fi + if [ "$MODE" = "tls1_2" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-RSA-WITH-NULL-SHA256 \ + TLS-RSA-WITH-AES-128-CBC-SHA256 \ + TLS-DHE-RSA-WITH-AES-128-CBC-SHA256 \ + TLS-RSA-WITH-AES-256-CBC-SHA256 \ + TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 \ + TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256 \ + TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384 \ + TLS-RSA-WITH-AES-128-GCM-SHA256 \ + TLS-RSA-WITH-AES-256-GCM-SHA384 \ + TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 \ + TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 \ + TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 \ + TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384 \ + " + O_CIPHERS="$O_CIPHERS \ + NULL-SHA256 \ + AES128-SHA256 \ + DHE-RSA-AES128-SHA256 \ + AES256-SHA256 \ + DHE-RSA-AES256-SHA256 \ + ECDHE-RSA-AES128-SHA256 \ + ECDHE-RSA-AES256-SHA384 \ + AES128-GCM-SHA256 \ + DHE-RSA-AES128-GCM-SHA256 \ + AES256-GCM-SHA384 \ + DHE-RSA-AES256-GCM-SHA384 \ + ECDHE-RSA-AES128-GCM-SHA256 \ + ECDHE-RSA-AES256-GCM-SHA384 \ + " + fi + ;; - if [ "$MODE" = "tls1_2" ]; - then + "PSK") + P_CIPHERS="$P_CIPHERS \ + TLS-PSK-WITH-RC4-128-SHA \ + TLS-PSK-WITH-3DES-EDE-CBC-SHA \ + TLS-PSK-WITH-AES-128-CBC-SHA \ + TLS-PSK-WITH-AES-256-CBC-SHA \ + " + O_CIPHERS="$O_CIPHERS \ + PSK-RC4-SHA \ + PSK-3DES-EDE-CBC-SHA \ + PSK-AES128-CBC-SHA \ + PSK-AES256-CBC-SHA \ + " + ;; + esac +} + +add_gnutls_ciphersuites() +{ + case $TYPE in + + "ECDSA") + if [ "$MODE" = "tls1_2" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256 \ + TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384 \ + TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256 \ + TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384 \ + " + G_CIPHERS="$G_CIPHERS \ + +ECDHE-ECDSA:+CAMELLIA-128-CBC:+SHA256 \ + +ECDHE-ECDSA:+CAMELLIA-256-CBC:+SHA384 \ + +ECDHE-ECDSA:+CAMELLIA-128-GCM:+AEAD \ + +ECDHE-ECDSA:+CAMELLIA-256-GCM:+AEAD \ + " + fi + ;; + + "RSA") + if [ "$MODE" = "tls1_2" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 \ + TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384 \ + TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256 \ + TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256 \ + TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 \ + TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256 \ + TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256 \ + TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384 \ + TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256 \ + TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384 \ + TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256 \ + TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384 \ + TLS-RSA-WITH-NULL-SHA256 \ + TLS-RSA-WITH-NULL-SHA \ + TLS-RSA-WITH-NULL-MD5 \ + " + G_CIPHERS="$G_CIPHERS \ + +ECDHE-RSA:+CAMELLIA-128-CBC:+SHA256 \ + +ECDHE-RSA:+CAMELLIA-256-CBC:+SHA384 \ + +RSA:+CAMELLIA-128-CBC:+SHA256 \ + +RSA:+CAMELLIA-256-CBC:+SHA256 \ + +DHE-RSA:+CAMELLIA-128-CBC:+SHA256 \ + +DHE-RSA:+CAMELLIA-256-CBC:+SHA256 \ + +ECDHE-RSA:+CAMELLIA-128-GCM:+AEAD \ + +ECDHE-RSA:+CAMELLIA-256-GCM:+AEAD \ + +DHE-RSA:+CAMELLIA-128-GCM:+AEAD \ + +DHE-RSA:+CAMELLIA-256-GCM:+AEAD \ + +RSA:+CAMELLIA-128-GCM:+AEAD \ + +RSA:+CAMELLIA-256-GCM:+AEAD \ + +RSA:+NULL:+SHA256 \ + +RSA:+NULL:+SHA1 \ + +RSA:+NULL:+MD5 \ + " + fi + ;; + + "PSK") + # GnuTLS 3.2.11 (2014-02-13) requires TLS 1.x for most *PSK suites + if [ "$MODE" != "ssl3" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA \ + TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA \ + TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA \ + TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA \ + TLS-DHE-PSK-WITH-AES-128-CBC-SHA \ + TLS-DHE-PSK-WITH-AES-256-CBC-SHA \ + TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA \ + TLS-RSA-PSK-WITH-AES-256-CBC-SHA \ + TLS-RSA-PSK-WITH-AES-128-CBC-SHA \ + " + G_CIPHERS="$G_CIPHERS \ + +ECDHE-PSK:+AES-256-CBC:+SHA1 \ + +ECDHE-PSK:+AES-128-CBC:+SHA1 \ + +ECDHE-PSK:+3DES-CBC:+SHA1 \ + +DHE-PSK:+3DES-CBC:+SHA1 \ + +DHE-PSK:+AES-128-CBC:+SHA1 \ + +DHE-PSK:+AES-256-CBC:+SHA1 \ + +RSA-PSK:+3DES-CBC:+SHA1 \ + +RSA-PSK:+AES-256-CBC:+SHA1 \ + +RSA-PSK:+AES-128-CBC:+SHA1 \ + " + fi + if [ "$MODE" = "tls1_2" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384 \ + TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384 \ + TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 \ + TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256 \ + TLS-ECDHE-PSK-WITH-NULL-SHA384 \ + TLS-ECDHE-PSK-WITH-NULL-SHA256 \ + TLS-PSK-WITH-AES-128-CBC-SHA256 \ + TLS-PSK-WITH-AES-256-CBC-SHA384 \ + TLS-DHE-PSK-WITH-AES-128-CBC-SHA256 \ + TLS-DHE-PSK-WITH-AES-256-CBC-SHA384 \ + TLS-PSK-WITH-NULL-SHA256 \ + TLS-PSK-WITH-NULL-SHA384 \ + TLS-DHE-PSK-WITH-NULL-SHA256 \ + TLS-DHE-PSK-WITH-NULL-SHA384 \ + TLS-RSA-PSK-WITH-AES-256-CBC-SHA384 \ + TLS-RSA-PSK-WITH-AES-128-CBC-SHA256 \ + TLS-RSA-PSK-WITH-NULL-SHA256 \ + TLS-RSA-PSK-WITH-NULL-SHA384 \ + TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256 \ + TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384 \ + TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256 \ + TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384 \ + TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384 \ + TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256 \ + TLS-PSK-WITH-AES-128-GCM-SHA256 \ + TLS-PSK-WITH-AES-256-GCM-SHA384 \ + TLS-DHE-PSK-WITH-AES-128-GCM-SHA256 \ + TLS-DHE-PSK-WITH-AES-256-GCM-SHA384 \ + TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256 \ + TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384 \ + TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256 \ + TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384 \ + TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256 \ + TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384 \ + TLS-RSA-PSK-WITH-AES-256-GCM-SHA384 \ + TLS-RSA-PSK-WITH-AES-128-GCM-SHA256 \ + " + G_CIPHERS="$G_CIPHERS \ + +ECDHE-PSK:+AES-256-CBC:+SHA384 \ + +ECDHE-PSK:+CAMELLIA-256-CBC:+SHA384 \ + +ECDHE-PSK:+AES-128-CBC:+SHA256 \ + +ECDHE-PSK:+CAMELLIA-128-CBC:+SHA256 \ + +PSK:+AES-128-CBC:+SHA256 \ + +PSK:+AES-256-CBC:+SHA384 \ + +DHE-PSK:+AES-128-CBC:+SHA256 \ + +DHE-PSK:+AES-256-CBC:+SHA384 \ + +RSA-PSK:+AES-256-CBC:+SHA384 \ + +RSA-PSK:+AES-128-CBC:+SHA256 \ + +DHE-PSK:+CAMELLIA-128-CBC:+SHA256 \ + +DHE-PSK:+CAMELLIA-256-CBC:+SHA384 \ + +PSK:+CAMELLIA-128-CBC:+SHA256 \ + +PSK:+CAMELLIA-256-CBC:+SHA384 \ + +RSA-PSK:+CAMELLIA-256-CBC:+SHA384 \ + +RSA-PSK:+CAMELLIA-128-CBC:+SHA256 \ + +PSK:+AES-128-GCM:+AEAD \ + +PSK:+AES-256-GCM:+AEAD \ + +DHE-PSK:+AES-128-GCM:+AEAD \ + +DHE-PSK:+AES-256-GCM:+AEAD \ + +RSA-PSK:+CAMELLIA-128-GCM:+AEAD \ + +RSA-PSK:+CAMELLIA-256-GCM:+AEAD \ + +PSK:+CAMELLIA-128-GCM:+AEAD \ + +PSK:+CAMELLIA-256-GCM:+AEAD \ + +DHE-PSK:+CAMELLIA-128-GCM:+AEAD \ + +DHE-PSK:+CAMELLIA-256-GCM:+AEAD \ + +RSA-PSK:+AES-256-GCM:+AEAD \ + +RSA-PSK:+AES-128-GCM:+AEAD \ + +ECDHE-PSK:+NULL:+SHA384 \ + +ECDHE-PSK:+NULL:+SHA256 \ + +PSK:+NULL:+SHA256 \ + +PSK:+NULL:+SHA384 \ + +DHE-PSK:+NULL:+SHA256 \ + +DHE-PSK:+NULL:+SHA384 \ + +RSA-PSK:+NULL:+SHA256 \ + +RSA-PSK:+NULL:+SHA384 \ + " + fi + ;; + esac +} + +add_polarssl_ciphersuites() +{ + case $TYPE in + + "ECDSA") + if [ "$MODE" != "ssl3" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256 \ + TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384 \ + " + fi + if [ "$MODE" = "tls1_2" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256 \ + TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384 \ + " + fi + ;; + + "RSA") + ;; + + "PSK") P_CIPHERS="$P_CIPHERS \ - TLS-PSK-WITH-AES-128-GCM-SHA256 \ - TLS-PSK-WITH-AES-256-GCM-SHA384 \ - TLS-DHE-PSK-WITH-AES-128-GCM-SHA256 \ - TLS-DHE-PSK-WITH-AES-256-GCM-SHA384 \ - TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256 \ - TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384 \ - TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256 \ - TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384 \ - TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256 \ - TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384 \ - TLS-RSA-PSK-WITH-AES-256-GCM-SHA384 \ - TLS-RSA-PSK-WITH-AES-128-GCM-SHA256 \ - TLS-RSA-WITH-NULL-SHA256 \ + TLS-PSK-WITH-NULL-SHA \ + TLS-DHE-PSK-WITH-RC4-128-SHA \ + TLS-DHE-PSK-WITH-NULL-SHA \ + TLS-RSA-PSK-WITH-RC4-128-SHA \ " - fi + if [ "$MODE" != "ssl3" ]; + then + P_CIPHERS="$P_CIPHERS \ + TLS-ECDHE-PSK-WITH-RC4-128-SHA \ + TLS-ECDHE-PSK-WITH-NULL-SHA \ + " + fi + ;; + esac +} -esac +setup_arguments() +{ + case $MODE in + "ssl3") + G_PRIO_MODE="+VERS-SSL3.0" + ;; + "tls1") + G_PRIO_MODE="+VERS-TLS1.0" + ;; + "tls1_1") + G_PRIO_MODE="+VERS-TLS1.1" + ;; + "tls1_2") + G_PRIO_MODE="+VERS-TLS1.2" + ;; + *) + echo "error: invalid mode: $MODE" >&2 + exit 1; + esac -# Filter ciphersuites -if [ "X" != "X$FILTER" ]; -then - O_CIPHERS=$( filter "$O_CIPHERS" "$FILTER" ) - P_CIPHERS=$( filter "$P_CIPHERS" "$FILTER" ) -fi + 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" + G_SERVER_PRIO="EXPORT:+NULL:+PSK:+DHE-PSK:+ECDHE-PSK:+RSA-PSK:-VERS-TLS-ALL:$G_PRIO_MODE" -for i in $P_CIPHERS; -do - let "tests++" - log "../programs/ssl/ssl_client2 force_ciphersuite=$i force_version=$MODE $P_CLIENT_ARGS" - RESULT="$( ../programs/ssl/ssl_client2 force_ciphersuite=$i force_version=$MODE $P_CLIENT_ARGS )" - EXIT=$? - echo -n "PolarSSL Server - PolarSSL Client - $i : $EXIT - " - if [ "$EXIT" = "2" ]; + P_CLIENT_ARGS="force_version=$MODE" + O_CLIENT_ARGS="-$MODE" + G_CLIENT_ARGS="-p 4433 --debug 3" + G_CLIENT_PRIO="NONE:$G_PRIO_MODE:+COMP-NULL:+CURVE-ALL:+SIGN-ALL" + + if [ "X$VERIFY" = "XYES" ]; then - echo Ciphersuite not supported in client - let "skipped++" - elif [ "$EXIT" != "0" ]; - then - echo Failed - echo "ssl_server2 $P_SERVER_ARGS" - echo "ssl_client2 force_ciphersuite=$i force_version=$MODE $P_CLIENT_ARGS" - echo $RESULT - let "failed++" + P_SERVER_ARGS="$P_SERVER_ARGS ca_file=data_files/test-ca_cat12.crt auth_mode=required" + O_SERVER_ARGS="$O_SERVER_ARGS -CAfile data_files/test-ca_cat12.crt -Verify 10" + G_SERVER_ARGS="$G_SERVER_ARGS --x509cafile data_files/test-ca_cat12.crt --require-client-cert" + + P_CLIENT_ARGS="$P_CLIENT_ARGS ca_file=data_files/test-ca_cat12.crt auth_mode=required" + O_CLIENT_ARGS="$O_CLIENT_ARGS -CAfile data_files/test-ca_cat12.crt -verify 10" + G_CLIENT_ARGS="$G_CLIENT_ARGS --x509cafile data_files/test-ca_cat12.crt" else - echo Success + # don't request a client cert at all + P_SERVER_ARGS="$P_SERVER_ARGS ca_file=none auth_mode=none" + G_SERVER_ARGS="$G_SERVER_ARGS --disable-client-cert" + + # give dummy CA to clients + P_CLIENT_ARGS="$P_CLIENT_ARGS ca_file=data_files/cli2.crt auth_mode=optional" + O_CLIENT_ARGS="$O_CLIENT_ARGS -CAfile data_files/cli2.crt" + G_CLIENT_ARGS="$G_CLIENT_ARGS --x509cafile data_files/cli2.crt --insecure" + fi + + case $TYPE in + "ECDSA") + P_SERVER_ARGS="$P_SERVER_ARGS crt_file=data_files/server5.crt key_file=data_files/server5.key" + O_SERVER_ARGS="$O_SERVER_ARGS -cert data_files/server5.crt -key data_files/server5.key" + G_SERVER_ARGS="$G_SERVER_ARGS --x509certfile data_files/server5.crt --x509keyfile data_files/server5.key" + + if [ "X$VERIFY" = "XYES" ]; then + P_CLIENT_ARGS="$P_CLIENT_ARGS crt_file=data_files/server6.crt key_file=data_files/server6.key" + O_CLIENT_ARGS="$O_CLIENT_ARGS -cert data_files/server6.crt -key data_files/server6.key" + G_CLIENT_ARGS="$G_CLIENT_ARGS --x509certfile data_files/server6.crt --x509keyfile data_files/server6.key" + else + P_CLIENT_ARGS="$P_CLIENT_ARGS crt_file=none key_file=none" + fi + ;; + + "RSA") + P_SERVER_ARGS="$P_SERVER_ARGS crt_file=data_files/server2.crt key_file=data_files/server2.key" + O_SERVER_ARGS="$O_SERVER_ARGS -cert data_files/server2.crt -key data_files/server2.key" + G_SERVER_ARGS="$G_SERVER_ARGS --x509certfile data_files/server2.crt --x509keyfile data_files/server2.key" + + if [ "X$VERIFY" = "XYES" ]; then + P_CLIENT_ARGS="$P_CLIENT_ARGS crt_file=data_files/server1.crt key_file=data_files/server1.key" + O_CLIENT_ARGS="$O_CLIENT_ARGS -cert data_files/server1.crt -key data_files/server1.key" + G_CLIENT_ARGS="$G_CLIENT_ARGS --x509certfile data_files/server1.crt --x509keyfile data_files/server1.key" + else + P_CLIENT_ARGS="$P_CLIENT_ARGS crt_file=none key_file=none" + fi + ;; + + "PSK") + # give RSA-PSK-capable server a RSA cert + # (should be a separate type, but harder to close with openssl) + P_SERVER_ARGS="$P_SERVER_ARGS psk=6162636465666768696a6b6c6d6e6f70 ca_file=none crt_file=data_files/server2.crt key_file=data_files/server2.key" + O_SERVER_ARGS="$O_SERVER_ARGS -psk 6162636465666768696a6b6c6d6e6f70 -nocert" + G_SERVER_ARGS="$G_SERVER_ARGS --x509certfile data_files/server2.crt --x509keyfile data_files/server2.key --pskpasswd data_files/passwd.psk" + + P_CLIENT_ARGS="$P_CLIENT_ARGS psk=6162636465666768696a6b6c6d6e6f70 crt_file=none key_file=none" + O_CLIENT_ARGS="$O_CLIENT_ARGS -psk 6162636465666768696a6b6c6d6e6f70" + G_CLIENT_ARGS="$G_CLIENT_ARGS --pskusername Client_identity --pskkey=6162636465666768696a6b6c6d6e6f70" + ;; + esac +} + +# is_polar +is_polar() { + echo "$1" | grep 'ssl_server2\|ssl_client2' > /dev/null +} + +# has_mem_err +has_mem_err() { + if ( grep -F 'All heap blocks were freed -- no leaks are possible' "$1" && + grep -F 'ERROR SUMMARY: 0 errors from 0 contexts' "$1" ) > /dev/null + then + return 1 # false: does not have errors + else + return 0 # true: has errors + fi +} + +# start_server +# also saves name and command +start_server() { + case $1 in + [Oo]pen*) + SERVER_CMD="$OPENSSL_CMD s_server $O_SERVER_ARGS" + ;; + [Gg]nu*) + SERVER_CMD="$GNUTLS_SERV $G_SERVER_ARGS --priority $G_SERVER_PRIO" + ;; + [Pp]olar*) + SERVER_CMD="$P_SRV $P_SERVER_ARGS" + if [ "$MEMCHECK" -gt 0 ]; then + SERVER_CMD="valgrind --leak-check=full $SERVER_CMD" + fi + ;; + *) + echo "error: invalid server name: $1" >&2 + exit 1 + ;; + esac + SERVER_NAME=$1 + + log "$SERVER_CMD" + echo "$SERVER_CMD" > srv_out + $SERVER_CMD >> srv_out 2>&1 & + PROCESS_ID=$! + + sleep 1 +} + +# terminate the running server (closing it cleanly if it is ours) +stop_server() { + case $SERVER_NAME in + [Pp]olar*) + # 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) + for i in $P_CIPHERS; do + "$P_CLI" $P_CLIENT_ARGS request_page=SERVERQUIT auth_mode=none \ + crt_file=data_files/cli2.crt key_file=data_files/cli2.key \ + force_ciphersuite=$i >/dev/null + if [ "$?" == 0 ]; then + break + fi + done + ;; + *) + kill $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 + echo " ! Server had memory errors" + let "srvmem++" + return + fi + fi + + rm -f srv_out +} + +# kill the running server (used when killed by signal) +cleanup() { + rm -f srv_out cli_out + kill $PROCESS_ID + exit 1 +} + +# run_client +run_client() { + # announce what we're going to do + let "tests++" + VERIF=$(echo $VERIFY | tr '[:upper:]' '[:lower:]') + TITLE="${1:0:1}->${SERVER_NAME:0:1} $MODE,$VERIF $2 " + echo -n "$TITLE" + LEN=`echo "$TITLE" | wc -c` + LEN=`echo 72 - $LEN | bc` + for i in `seq 1 $LEN`; do echo -n '.'; done; echo -n ' ' + + # run the command and interpret result + case $1 in + [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 + EXIT=$? + + if [ "$EXIT" == "0" ]; then + RESULT=0 + else + if grep 'Cipher is (NONE)' cli_out >/dev/null; then + RESULT=1 + else + RESULT=2 + fi + fi + ;; + + [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 + EXIT=$? + + if [ "$EXIT" == "0" ]; then + RESULT=0 + else + 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 : + else + RESULT=1 + fi + fi >/dev/null + fi + ;; + + [Pp]olar*) + CLIENT_CMD="$P_CLI $P_CLIENT_ARGS force_ciphersuite=$2" + if [ "$MEMCHECK" -gt 0 ]; then + CLIENT_CMD="valgrind --leak-check=full $CLIENT_CMD" + fi + log "$CLIENT_CMD" + echo "$CLIENT_CMD" > cli_out + $CLIENT_CMD >> cli_out 2>&1 + EXIT=$? + + case $EXIT in + "0") RESULT=0 ;; + "2") RESULT=1 ;; + *) RESULT=2 ;; + esac + + if [ "$MEMCHECK" -gt 0 ]; then + if is_polar "$CLIENT_CMD" && has_mem_err cli_out; then + RESULT=2 + fi + fi + + ;; + + *) + echo "error: invalid client name: $1" >&2 + exit 1 + ;; + esac + + # report and count result + case $RESULT in + "0") + echo PASS + ;; + "1") + echo SKIP + let "skipped++" + ;; + "2") + echo FAIL + echo " ! $SERVER_CMD" + echo " ! $CLIENT_CMD" + 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 +} + +# +# MAIN +# + +# sanity checks, avoid an avalanche of errors +if [ ! -x "$P_SRV" ]; then + echo "Command '$P_SRV' is not an executable file" + exit 1 +fi +if [ ! -x "$P_CLI" ]; then + echo "Command '$P_CLI' is not an executable file" + exit 1 +fi +for CMD in $OPENSSL_CMD $GNUTLS_CLI $GNUTLS_SERV; do + if which "$CMD" >/dev/null 2>&1; then :; else + echo "Command '$CMD' not found" + exit 1 fi done -kill $PROCESS_ID 2>/dev/null -wait $PROCESS_ID 2>/dev/null -done -done +get_options "$@" + +killall -q gnutls-serv openssl ssl_server ssl_server2 +trap cleanup INT TERM HUP + +for VERIFY in $VERIFIES; do + for MODE in $MODES; do + for TYPE in $TYPES; do + for PEER in $PEERS; do + + setup_arguments + + case "$PEER" in + + [Oo]pen*) + + reset_ciphersuites + add_openssl_ciphersuites + filter_ciphersuites + + if [ "X" != "X$P_CIPHERS" ]; then + start_server "OpenSSL" + for i in $P_CIPHERS; do + run_client PolarSSL $i + done + stop_server + fi + + if [ "X" != "X$O_CIPHERS" ]; then + start_server "PolarSSL" + for i in $O_CIPHERS; do + run_client OpenSSL $i + done + stop_server + fi + + ;; + + [Gg]nu*) + + reset_ciphersuites + add_gnutls_ciphersuites + filter_ciphersuites + + if [ "X" != "X$P_CIPHERS" ]; then + start_server "GnuTLS" + for i in $P_CIPHERS; do + run_client PolarSSL $i + done + stop_server + fi + + if [ "X" != "X$G_CIPHERS" ]; then + start_server "PolarSSL" + for i in $G_CIPHERS; do + run_client GnuTLS $i + done + stop_server + fi + + ;; + + [Pp]olar*) + + reset_ciphersuites + add_openssl_ciphersuites + add_gnutls_ciphersuites + add_polarssl_ciphersuites + filter_ciphersuites + + if [ "X" != "X$P_CIPHERS" ]; then + start_server "PolarSSL" + for i in $P_CIPHERS; do + run_client PolarSSL $i + done + stop_server + fi + + ;; + + esac + + done + done + done done -echo "" -echo "-------------------------------------------------------------------------" -echo "" +echo "------------------------------------------------------------------------" -if (( failed != 0 )); +if (( failed != 0 && srvmem != 0 )); then echo -n "FAILED" else echo -n "PASSED" fi -let "passed = tests - failed" -echo " ($passed / $tests tests ($skipped skipped))" +if [ "$MEMCHECK" -gt 0 ]; then + MEMREPORT=", $srvmem server memory errors" +else + MEMREPORT="" +fi +let "passed = tests - failed" +echo " ($passed / $tests tests ($skipped skipped$MEMREPORT))" + +let "failed += srvmem" exit $failed diff --git a/tests/data_files/passwd.psk b/tests/data_files/passwd.psk new file mode 100644 index 000000000..17fee37df --- /dev/null +++ b/tests/data_files/passwd.psk @@ -0,0 +1 @@ +Client_identity:6162636465666768696a6b6c6d6e6f70 diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh new file mode 100755 index 000000000..51e2e0b79 --- /dev/null +++ b/tests/ssl-opt.sh @@ -0,0 +1,887 @@ +#!/bin/sh + +# Test various options that are not covered by compat.sh +# +# Here the goal is not to cover every ciphersuite/version, but +# rather specific options (max fragment length, truncated hmac, etc) +# or procedures (session resumption from cache or ticket, renego, etc). +# +# Assumes all options are compiled in. + +set -u + +# default values, can be overriden by the environment +: ${P_SRV:=../programs/ssl/ssl_server2} +: ${P_CLI:=../programs/ssl/ssl_client2} +: ${OPENSSL_CMD:=openssl} # OPENSSL would conflict with the build system + +O_SRV="$OPENSSL_CMD s_server -www -cert data_files/server5.crt -key data_files/server5.key" +O_CLI="echo 'GET / HTTP/1.0' | $OPENSSL_CMD s_client" + +TESTS=0 +FAILS=0 + +MEMCHECK=0 +FILTER='.*' +EXCLUDE='SSLv2' # disabled by default, needs OpenSSL compiled with SSLv2 + +print_usage() { + echo "Usage: $0 [options]" + echo -e " -h|--help\tPrint this help." + echo -e " -m|--memcheck\tCheck memory leaks and errors." + echo -e " -f|--filter\tOnly matching tests are executed (default: '$FILTER')" + echo -e " -e|--exclude\tMatching tests are excluded (default: '$EXCLUDE')" +} + +get_options() { + while [ $# -gt 0 ]; do + case "$1" in + -f|--filter) + shift; FILTER=$1 + ;; + -e|--exclude) + shift; EXCLUDE=$1 + ;; + -m|--memcheck) + MEMCHECK=1 + ;; + -h|--help) + print_usage + exit 0 + ;; + *) + echo "Unkown argument: '$1'" + print_usage + exit 1 + ;; + esac + shift + done +} + +# print_name +print_name() { + echo -n "$1 " + LEN=`echo "$1" | wc -c` + LEN=`echo 72 - $LEN | bc` + for i in `seq 1 $LEN`; do echo -n '.'; done + echo -n ' ' + + TESTS=`echo $TESTS + 1 | bc` +} + +# fail +fail() { + echo "FAIL" + echo " ! $1" + + 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` +} + +# is_polar +is_polar() { + echo "$1" | grep 'ssl_server2\|ssl_client2' > /dev/null +} + +# has_mem_err +has_mem_err() { + if ( grep -F 'All heap blocks were freed -- no leaks are possible' "$1" && + grep -F 'ERROR SUMMARY: 0 errors from 0 contexts' "$1" ) > /dev/null + then + return 1 # false: does not have errors + else + return 0 # true: has errors + fi +} + +# 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 +# -S pattern pattern that must be absent in server output +# -C pattern pattern that must be absent in client output +run_test() { + NAME="$1" + SRV_CMD="$2" + CLI_CMD="$3" + CLI_EXPECT="$4" + shift 4 + + if echo "$NAME" | grep "$FILTER" | grep -v "$EXCLUDE" >/dev/null; then : + else + return + fi + + print_name "$NAME" + + # prepend valgrind to our commands if active + if [ "$MEMCHECK" -gt 0 ]; then + if is_polar "$SRV_CMD"; then + SRV_CMD="valgrind --leak-check=full $SRV_CMD" + fi + if is_polar "$CLI_CMD"; then + CLI_CMD="valgrind --leak-check=full $CLI_CMD" + fi + fi + + # run the commands + echo "$SRV_CMD" > srv_out + $SHELL -c "$SRV_CMD" >> srv_out 2>&1 & + SRV_PID=$! + sleep 1 + echo "$CLI_CMD" > cli_out + $SHELL -c "$CLI_CMD" >> cli_out 2>&1 + CLI_EXIT=$? + if is_polar "$SRV_CMD"; then + "$P_CLI" request_page=SERVERQUIT tickets=0 auth_mode=none \ + crt_file=data_files/cli2.crt key_file=data_files/cli2.key \ + >/dev/null + else + kill $SRV_PID + fi + wait $SRV_PID + + # check if the client and server went at least to the handshake stage + # (usefull 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 :; + 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 :; + else + fail "client failed to start" + return + fi + fi + + # check server exit code + if [ $? != 0 ]; then + fail "server fail" + return + fi + + # check client exit code + if [ \( "$CLI_EXPECT" = 0 -a "$CLI_EXIT" != 0 \) -o \ + \( "$CLI_EXPECT" != 0 -a "$CLI_EXIT" = 0 \) ] + then + fail "bad client exit code" + return + fi + + # check other assertions + while [ $# -gt 0 ] + do + case $1 in + "-s") + if grep "$2" srv_out >/dev/null; then :; else + fail "-s $2" + return + fi + ;; + + "-c") + if grep "$2" cli_out >/dev/null; then :; else + fail "-c $2" + return + fi + ;; + + "-S") + if grep "$2" srv_out >/dev/null; then + fail "-S $2" + return + fi + ;; + + "-C") + if grep "$2" cli_out >/dev/null; then + fail "-C $2" + return + fi + ;; + + *) + echo "Unkown test: $1" >&2 + exit 1 + esac + shift 2 + done + + # check valgrind's results + if [ "$MEMCHECK" -gt 0 ]; 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 + fail "Client has memory errors" + return + fi + fi + + # if we're here, everything is ok + echo "PASS" + rm -f srv_out cli_out +} + +cleanup() { + rm -f cli_out srv_out sess + kill $SRV_PID + exit 1 +} + +# +# MAIN +# + +# sanity checks, avoid an avalanche of errors +if [ ! -x "$P_SRV" ]; then + echo "Command '$P_SRV' is not an executable file" + exit 1 +fi +if [ ! -x "$P_CLI" ]; then + echo "Command '$P_CLI' is not an executable file" + exit 1 +fi +if which $OPENSSL_CMD >/dev/null 2>&1; then :; else + echo "Command '$OPENSSL_CMD' not found" + exit 1 +fi + +get_options "$@" + +killall -q openssl ssl_server ssl_server2 +trap cleanup INT TERM HUP + +# Test for SSLv2 ClientHello + +run_test "SSLv2 ClientHello #0 (reference)" \ + "$P_SRV debug_level=3" \ + "$O_CLI -no_ssl2" \ + 0 \ + -S "parse client hello v2" \ + -S "ssl_handshake returned" + +# Adding a SSL2-only suite makes OpenSSL client send SSLv2 ClientHello +run_test "SSLv2 ClientHello #1 (actual test)" \ + "$P_SRV debug_level=3" \ + "$O_CLI -cipher 'DES-CBC-MD5:ALL'" \ + 0 \ + -s "parse client hello v2" \ + -S "ssl_handshake returned" + +# Tests for Truncated HMAC extension + +run_test "Truncated HMAC #0" \ + "$P_SRV debug_level=5" \ + "$P_CLI trunc_hmac=0 force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \ + 0 \ + -s "dumping 'computed mac' (20 bytes)" + +run_test "Truncated HMAC #1" \ + "$P_SRV debug_level=5" \ + "$P_CLI trunc_hmac=1 force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \ + 0 \ + -s "dumping 'computed mac' (10 bytes)" + +# Tests for Session Tickets + +run_test "Session resume using tickets #1 (basic)" \ + "$P_SRV debug_level=4 tickets=1" \ + "$P_CLI debug_level=4 tickets=1 reconnect=1" \ + 0 \ + -c "client hello, adding session ticket extension" \ + -s "found session ticket extension" \ + -s "server hello, adding session ticket extension" \ + -c "found session_ticket extension" \ + -c "parse new session ticket" \ + -S "session successfully restored from cache" \ + -s "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + +run_test "Session resume using tickets #2 (cache disabled)" \ + "$P_SRV debug_level=4 tickets=1 cache_max=0" \ + "$P_CLI debug_level=4 tickets=1 reconnect=1" \ + 0 \ + -c "client hello, adding session ticket extension" \ + -s "found session ticket extension" \ + -s "server hello, adding session ticket extension" \ + -c "found session_ticket extension" \ + -c "parse new session ticket" \ + -S "session successfully restored from cache" \ + -s "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + +run_test "Session resume using tickets #3 (timeout)" \ + "$P_SRV debug_level=4 tickets=1 cache_max=0 ticket_timeout=1" \ + "$P_CLI debug_level=4 tickets=1 reconnect=1 reco_delay=2" \ + 0 \ + -c "client hello, adding session ticket extension" \ + -s "found session ticket extension" \ + -s "server hello, adding session ticket extension" \ + -c "found session_ticket extension" \ + -c "parse new session ticket" \ + -S "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -S "a session has been resumed" \ + -C "a session has been resumed" + +run_test "Session resume using tickets #4 (openssl server)" \ + "$O_SRV" \ + "$P_CLI debug_level=4 tickets=1 reconnect=1" \ + 0 \ + -c "client hello, adding session ticket extension" \ + -c "found session_ticket extension" \ + -c "parse new session ticket" \ + -c "a session has been resumed" + +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)" \ + 0 \ + -s "found session ticket extension" \ + -s "server hello, adding session ticket extension" \ + -S "session successfully restored from cache" \ + -s "session successfully restored from ticket" \ + -s "a session has been resumed" + +# Tests for Session Resume based on session-ID and cache + +run_test "Session resume using cache #1 (tickets enabled on client)" \ + "$P_SRV debug_level=4 tickets=0" \ + "$P_CLI debug_level=4 tickets=1 reconnect=1" \ + 0 \ + -c "client hello, adding session ticket extension" \ + -s "found session ticket extension" \ + -S "server hello, adding session ticket extension" \ + -C "found session_ticket extension" \ + -C "parse new session ticket" \ + -s "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + +run_test "Session resume using cache #2 (tickets enabled on server)" \ + "$P_SRV debug_level=4 tickets=1" \ + "$P_CLI debug_level=4 tickets=0 reconnect=1" \ + 0 \ + -C "client hello, adding session ticket extension" \ + -S "found session ticket extension" \ + -S "server hello, adding session ticket extension" \ + -C "found session_ticket extension" \ + -C "parse new session ticket" \ + -s "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + +run_test "Session resume using cache #3 (cache_max=0)" \ + "$P_SRV debug_level=4 tickets=0 cache_max=0" \ + "$P_CLI debug_level=4 tickets=0 reconnect=1" \ + 0 \ + -S "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -S "a session has been resumed" \ + -C "a session has been resumed" + +run_test "Session resume using cache #4 (cache_max=1)" \ + "$P_SRV debug_level=4 tickets=0 cache_max=1" \ + "$P_CLI debug_level=4 tickets=0 reconnect=1" \ + 0 \ + -s "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + +run_test "Session resume using cache #5 (timemout > delay)" \ + "$P_SRV debug_level=4 tickets=0" \ + "$P_CLI debug_level=4 tickets=0 reconnect=1 reco_delay=0" \ + 0 \ + -s "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + +run_test "Session resume using cache #6 (timeout < delay)" \ + "$P_SRV debug_level=4 tickets=0 cache_timeout=1" \ + "$P_CLI debug_level=4 tickets=0 reconnect=1 reco_delay=2" \ + 0 \ + -S "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -S "a session has been resumed" \ + -C "a session has been resumed" + +run_test "Session resume using cache #7 (no timeout)" \ + "$P_SRV debug_level=4 tickets=0 cache_timeout=0" \ + "$P_CLI debug_level=4 tickets=0 reconnect=1 reco_delay=2" \ + 0 \ + -s "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + +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)" \ + 0 \ + -s "found session ticket extension" \ + -S "server hello, adding session ticket extension" \ + -s "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -s "a session has been resumed" + +run_test "Session resume using cache #9 (openssl server)" \ + "$O_SRV" \ + "$P_CLI debug_level=4 tickets=0 reconnect=1" \ + 0 \ + -C "found session_ticket extension" \ + -C "parse new session ticket" \ + -c "a session has been resumed" + +# Tests for Max Fragment Length extension + +run_test "Max fragment length #1" \ + "$P_SRV debug_level=4" \ + "$P_CLI debug_level=4" \ + 0 \ + -C "client hello, adding max_fragment_length extension" \ + -S "found max fragment length extension" \ + -S "server hello, max_fragment_length extension" \ + -C "found max_fragment_length extension" + +run_test "Max fragment length #2" \ + "$P_SRV debug_level=4" \ + "$P_CLI debug_level=4 max_frag_len=4096" \ + 0 \ + -c "client hello, adding max_fragment_length extension" \ + -s "found max fragment length extension" \ + -s "server hello, max_fragment_length extension" \ + -c "found max_fragment_length extension" + +run_test "Max fragment length #3" \ + "$P_SRV debug_level=4 max_frag_len=4096" \ + "$P_CLI debug_level=4" \ + 0 \ + -C "client hello, adding max_fragment_length extension" \ + -S "found max fragment length extension" \ + -S "server hello, max_fragment_length extension" \ + -C "found max_fragment_length extension" + +# Tests for renegotiation + +run_test "Renegotiation #0 (none)" \ + "$P_SRV debug_level=4" \ + "$P_CLI debug_level=4" \ + 0 \ + -C "client hello, adding renegotiation extension" \ + -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ + -S "found renegotiation extension" \ + -s "server hello, secure renegotiation extension" \ + -c "found renegotiation extension" \ + -C "=> renegotiate" \ + -S "=> renegotiate" \ + -S "write hello request" + +run_test "Renegotiation #1 (enabled, client-initiated)" \ + "$P_SRV debug_level=4" \ + "$P_CLI debug_level=4 renegotiate=1" \ + 0 \ + -c "client hello, adding renegotiation extension" \ + -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ + -s "found renegotiation extension" \ + -s "server hello, secure renegotiation extension" \ + -c "found renegotiation extension" \ + -c "=> renegotiate" \ + -s "=> renegotiate" \ + -S "write hello request" + +run_test "Renegotiation #2 (enabled, server-initiated)" \ + "$P_SRV debug_level=4 renegotiate=1" \ + "$P_CLI debug_level=4" \ + 0 \ + -c "client hello, adding renegotiation extension" \ + -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ + -s "found renegotiation extension" \ + -s "server hello, secure renegotiation extension" \ + -c "found renegotiation extension" \ + -c "=> renegotiate" \ + -s "=> renegotiate" \ + -s "write hello request" + +run_test "Renegotiation #3 (enabled, double)" \ + "$P_SRV debug_level=4 renegotiate=1" \ + "$P_CLI debug_level=4 renegotiate=1" \ + 0 \ + -c "client hello, adding renegotiation extension" \ + -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ + -s "found renegotiation extension" \ + -s "server hello, secure renegotiation extension" \ + -c "found renegotiation extension" \ + -c "=> renegotiate" \ + -s "=> renegotiate" \ + -s "write hello request" + +run_test "Renegotiation #4 (client-initiated, server-rejected)" \ + "$P_SRV debug_level=4 renegotiation=0" \ + "$P_CLI debug_level=4 renegotiate=1" \ + 1 \ + -c "client hello, adding renegotiation extension" \ + -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ + -S "found renegotiation extension" \ + -s "server hello, secure renegotiation extension" \ + -c "found renegotiation extension" \ + -c "=> renegotiate" \ + -S "=> renegotiate" \ + -S "write hello request" + +run_test "Renegotiation #5 (server-initiated, client-rejected)" \ + "$P_SRV debug_level=4 renegotiate=1" \ + "$P_CLI debug_level=4 renegotiation=0" \ + 0 \ + -C "client hello, adding renegotiation extension" \ + -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ + -S "found renegotiation extension" \ + -s "server hello, secure renegotiation extension" \ + -c "found renegotiation extension" \ + -C "=> renegotiate" \ + -S "=> renegotiate" \ + -s "write hello request" \ + -s "SSL - An unexpected message was received from our peer" \ + -s "failed" + +# Tests for auth_mode + +run_test "Authentication #1 (server badcert, client required)" \ + "$P_SRV crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + "$P_CLI debug_level=2 auth_mode=required" \ + 1 \ + -c "x509_verify_cert() returned" \ + -c "! self-signed or not signed by a trusted CA" \ + -c "! ssl_handshake returned" \ + -c "X509 - Certificate verification failed" + +run_test "Authentication #2 (server badcert, client optional)" \ + "$P_SRV crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + "$P_CLI debug_level=2 auth_mode=optional" \ + 0 \ + -c "x509_verify_cert() returned" \ + -c "! self-signed or not signed by a trusted CA" \ + -C "! ssl_handshake returned" \ + -C "X509 - Certificate verification failed" + +run_test "Authentication #3 (server badcert, client none)" \ + "$P_SRV crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + "$P_CLI debug_level=2 auth_mode=none" \ + 0 \ + -C "x509_verify_cert() returned" \ + -C "! self-signed or not signed by a trusted CA" \ + -C "! ssl_handshake returned" \ + -C "X509 - Certificate verification failed" + +run_test "Authentication #4 (client badcert, server required)" \ + "$P_SRV debug_level=4 auth_mode=required" \ + "$P_CLI debug_level=4 crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + 1 \ + -S "skip write certificate request" \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -C "skip write certificate" \ + -C "skip write certificate verify" \ + -S "skip parse certificate verify" \ + -s "x509_verify_cert() returned" \ + -S "! self-signed or not signed by a trusted CA" \ + -s "! ssl_handshake returned" \ + -c "! ssl_handshake returned" \ + -s "X509 - Certificate verification failed" + +run_test "Authentication #5 (client badcert, server optional)" \ + "$P_SRV debug_level=4 auth_mode=optional" \ + "$P_CLI debug_level=4 crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + 0 \ + -S "skip write certificate request" \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -C "skip write certificate" \ + -C "skip write certificate verify" \ + -S "skip parse certificate verify" \ + -s "x509_verify_cert() returned" \ + -s "! self-signed or not signed by a trusted CA" \ + -S "! ssl_handshake returned" \ + -C "! ssl_handshake returned" \ + -S "X509 - Certificate verification failed" + +run_test "Authentication #6 (client badcert, server none)" \ + "$P_SRV debug_level=4 auth_mode=none" \ + "$P_CLI debug_level=4 crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + 0 \ + -s "skip write certificate request" \ + -C "skip parse certificate request" \ + -c "got no certificate request" \ + -c "skip write certificate" \ + -c "skip write certificate verify" \ + -s "skip parse certificate verify" \ + -S "x509_verify_cert() returned" \ + -S "! self-signed or not signed by a trusted CA" \ + -S "! ssl_handshake returned" \ + -C "! ssl_handshake returned" \ + -S "X509 - Certificate verification failed" + +run_test "Authentication #7 (client no cert, server optional)" \ + "$P_SRV debug_level=4 auth_mode=optional" \ + "$P_CLI debug_level=4 crt_file=none key_file=none" \ + 0 \ + -S "skip write certificate request" \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -C "skip write certificate$" \ + -C "got no certificate to send" \ + -S "SSLv3 client has no certificate" \ + -c "skip write certificate verify" \ + -s "skip parse certificate verify" \ + -s "! no client certificate sent" \ + -S "! ssl_handshake returned" \ + -C "! ssl_handshake returned" \ + -S "X509 - Certificate verification failed" + +run_test "Authentication #8 (openssl client no cert, server optional)" \ + "$P_SRV debug_level=4 auth_mode=optional" \ + "$O_CLI" \ + 0 \ + -S "skip write certificate request" \ + -s "skip parse certificate verify" \ + -s "! no client certificate sent" \ + -S "! ssl_handshake returned" \ + -S "X509 - Certificate verification failed" + +run_test "Authentication #9 (client no cert, openssl server optional)" \ + "$O_SRV -verify 10" \ + "$P_CLI debug_level=4 crt_file=none key_file=none" \ + 0 \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -C "skip write certificate$" \ + -c "skip write certificate verify" \ + -C "! ssl_handshake returned" + +run_test "Authentication #10 (client no cert, ssl3)" \ + "$P_SRV debug_level=4 auth_mode=optional force_version=ssl3" \ + "$P_CLI debug_level=4 crt_file=none key_file=none" \ + 0 \ + -S "skip write certificate request" \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -C "skip write certificate$" \ + -c "skip write certificate verify" \ + -c "got no certificate to send" \ + -s "SSLv3 client has no certificate" \ + -s "skip parse certificate verify" \ + -s "! no client certificate sent" \ + -S "! ssl_handshake returned" \ + -C "! ssl_handshake returned" \ + -S "X509 - Certificate verification failed" + +# tests for SNI + +run_test "SNI #0 (no SNI callback)" \ + "$P_SRV debug_level=4 server_addr=127.0.0.1 \ + crt_file=data_files/server5.crt key_file=data_files/server5.key" \ + "$P_CLI debug_level=0 server_addr=127.0.0.1 \ + server_name=localhost" \ + 0 \ + -S "parse ServerName extension" \ + -c "issuer name *: C=NL, O=PolarSSL, CN=Polarssl Test EC CA" \ + -c "subject name *: C=NL, O=PolarSSL, CN=localhost" + +run_test "SNI #1 (matching cert 1)" \ + "$P_SRV debug_level=4 server_addr=127.0.0.1 \ + crt_file=data_files/server5.crt key_file=data_files/server5.key \ + sni='localhost,data_files/server2.crt,data_files/server2.key,PolarSSL Server 1,data_files/server1.crt,data_files/server1.key'" \ + "$P_CLI debug_level=0 server_addr=127.0.0.1 \ + server_name=localhost" \ + 0 \ + -s "parse ServerName extension" \ + -c "issuer name *: C=NL, O=PolarSSL, CN=PolarSSL Test CA" \ + -c "subject name *: C=NL, O=PolarSSL, CN=localhost" + +run_test "SNI #2 (matching cert 2)" \ + "$P_SRV debug_level=4 server_addr=127.0.0.1 \ + crt_file=data_files/server5.crt key_file=data_files/server5.key \ + sni='localhost,data_files/server2.crt,data_files/server2.key,PolarSSL Server 1,data_files/server1.crt,data_files/server1.key'" \ + "$P_CLI debug_level=0 server_addr=127.0.0.1 \ + server_name='PolarSSL Server 1'" \ + 0 \ + -s "parse ServerName extension" \ + -c "issuer name *: C=NL, O=PolarSSL, CN=PolarSSL Test CA" \ + -c "subject name *: C=NL, O=PolarSSL, CN=PolarSSL Server 1" + +run_test "SNI #3 (no matching cert)" \ + "$P_SRV debug_level=4 server_addr=127.0.0.1 \ + crt_file=data_files/server5.crt key_file=data_files/server5.key \ + sni='localhost,data_files/server2.crt,data_files/server2.key,PolarSSL Server 1,data_files/server1.crt,data_files/server1.key'" \ + "$P_CLI debug_level=0 server_addr=127.0.0.1 \ + server_name='PolarSSL Server 2'" \ + 1 \ + -s "parse ServerName extension" \ + -s "ssl_sni_wrapper() returned" \ + -s "ssl_handshake returned" \ + -c "ssl_handshake returned" \ + -c "SSL - A fatal alert message was received from our peer" + +# Tests for non-blocking I/O: exercise a variety of handshake flows + +run_test "Non-blocking I/O #1 (basic handshake)" \ + "$P_SRV nbio=2 tickets=0 auth_mode=none" \ + "$P_CLI nbio=2 tickets=0" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -c "Read from server: .* bytes read" + +run_test "Non-blocking I/O #2 (client auth)" \ + "$P_SRV nbio=2 tickets=0 auth_mode=required" \ + "$P_CLI nbio=2 tickets=0" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -c "Read from server: .* bytes read" + +run_test "Non-blocking I/O #3 (ticket)" \ + "$P_SRV nbio=2 tickets=1 auth_mode=none" \ + "$P_CLI nbio=2 tickets=1" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -c "Read from server: .* bytes read" + +run_test "Non-blocking I/O #4 (ticket + client auth)" \ + "$P_SRV nbio=2 tickets=1 auth_mode=required" \ + "$P_CLI nbio=2 tickets=1" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -c "Read from server: .* bytes read" + +run_test "Non-blocking I/O #5 (ticket + client auth + resume)" \ + "$P_SRV nbio=2 tickets=1 auth_mode=required" \ + "$P_CLI nbio=2 tickets=1 reconnect=1" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -c "Read from server: .* bytes read" + +run_test "Non-blocking I/O #6 (ticket + resume)" \ + "$P_SRV nbio=2 tickets=1 auth_mode=none" \ + "$P_CLI nbio=2 tickets=1 reconnect=1" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -c "Read from server: .* bytes read" + +run_test "Non-blocking I/O #7 (session-id resume)" \ + "$P_SRV nbio=2 tickets=0 auth_mode=none" \ + "$P_CLI nbio=2 tickets=0 reconnect=1" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -c "Read from server: .* bytes read" + +run_test "Version check #1 (all -> 1.2)" \ + "$P_SRV" \ + "$P_CLI" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -s "Protocol is TLSv1.2" \ + -c "Protocol is TLSv1.2" + +run_test "Version check #2 (cli max 1.1 -> 1.1)" \ + "$P_SRV" \ + "$P_CLI max_version=tls1_1" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -s "Protocol is TLSv1.1" \ + -c "Protocol is TLSv1.1" + +run_test "Version check #3 (srv max 1.1 -> 1.1)" \ + "$P_SRV max_version=tls1_1" \ + "$P_CLI" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -s "Protocol is TLSv1.1" \ + -c "Protocol is TLSv1.1" + +run_test "Version check #4 (cli+srv max 1.1 -> 1.1)" \ + "$P_SRV max_version=tls1_1" \ + "$P_CLI max_version=tls1_1" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -s "Protocol is TLSv1.1" \ + -c "Protocol is TLSv1.1" + +run_test "Version check #5 (cli max 1.1, srv min 1.1 -> 1.1)" \ + "$P_SRV min_version=tls1_1" \ + "$P_CLI max_version=tls1_1" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -s "Protocol is TLSv1.1" \ + -c "Protocol is TLSv1.1" + +run_test "Version check #6 (cli min 1.1, srv max 1.1 -> 1.1)" \ + "$P_SRV max_version=tls1_1" \ + "$P_CLI min_version=tls1_1" \ + 0 \ + -S "ssl_handshake returned" \ + -C "ssl_handshake returned" \ + -s "Protocol is TLSv1.1" \ + -c "Protocol is TLSv1.1" + +run_test "Version check #7 (cli min 1.2, srv max 1.1 -> fail)" \ + "$P_SRV max_version=tls1_1" \ + "$P_CLI min_version=tls1_2" \ + 1 \ + -s "ssl_handshake returned" \ + -c "ssl_handshake returned" \ + -c "SSL - Handshake protocol not within min/max boundaries" + +run_test "Version check #8 (srv min 1.2, cli max 1.1 -> fail)" \ + "$P_SRV min_version=tls1_2" \ + "$P_CLI max_version=tls1_1" \ + 1 \ + -s "ssl_handshake returned" \ + -c "ssl_handshake returned" \ + -s "SSL - Handshake protocol not within min/max boundaries" + +# Final report + +echo "------------------------------------------------------------------------" + +if [ $FAILS = 0 ]; then + echo -n "PASSED" +else + echo -n "FAILED" +fi +PASSES=`echo $TESTS - $FAILS | bc` +echo " ($PASSES / $TESTS tests)" + +exit $FAILS