Merge remote-tracking branch 'restricted/pr/418' into mbedtls-1.3-restricted
* restricted/pr/418:
RSA PSS: remove redundant check; changelog
RSA PSS: fix first byte check for keys of size 8N+1
RSA PSS: fix minimum length check for keys of size 8N+1
RSA: Fix another buffer overflow in PSS signature verification
RSA: Fix buffer overflow in PSS signature verification
diff --git a/ChangeLog b/ChangeLog
index 3de3184..af9fdd0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,6 @@
mbed TLS ChangeLog (Sorted per branch, date)
-= mbed TLS 1.3.x released xxxx-xx-xx
+= mbed TLS 1.3.22 branch released 2017-xx-xx
Security
* Fix buffer overflow in RSA-PSS verification when the hash is too
@@ -10,6 +10,17 @@
data is all zeros.
Bugfix
+ * Fix memory leak in ssl_set_hostname() when called multiple times.
+ Found by projectgus and jethrogb, #836.
+ * Fix usage help in ssl_server2 example. Found and fixed by Bei Lin.
+ * Fix Visual Studio implicit cast compilation warnings in the net.c and
+ x509.c modules and some sample applications.
+ * Parse signature algorithm extension when renegotiating. Previously,
+ renegotiated handshakes would only accept signatures using SHA-1
+ regardless of the peer's preferences, or fail if SHA-1 was disabled.
+ * Fix leap year calculation in x509_date_is_valid() to ensure that invalid
+ dates on leap years with 100 and 400 intervals are handled correctly. Found
+ by Nicholas Wilson. #694
* Fix some invalid RSA-PSS signatures with keys of size 8N+1 that were
accepted. Generating these signatures required the private key.
diff --git a/configs/README.txt b/configs/README.txt
index 4a0074c..76f0031 100644
--- a/configs/README.txt
+++ b/configs/README.txt
@@ -8,7 +8,7 @@
them, you can pick one of the following methods:
1. Replace the default file include/polarssl/config.h with the chosen one.
- (Depending on your compiler, you may need to ajust the line with
+ (Depending on your compiler, you may need to adjust the line with
#include "polarssl/check_config.h" then.)
2. Define POLARSSL_CONFIG_FILE and adjust the include path accordingly.
diff --git a/include/polarssl/asn1.h b/include/polarssl/asn1.h
index 0bfa929..5f236a5 100644
--- a/include/polarssl/asn1.h
+++ b/include/polarssl/asn1.h
@@ -60,7 +60,7 @@
/**
* \name DER constants
- * These constants comply with DER encoded the ANS1 type tags.
+ * These constants comply with the DER encoded ASN.1 type tags.
* DER encoding uses hexadecimal representation.
* An example DER sequence is:\n
* - 0x02 -- tag indicating INTEGER
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 4a01bbf..9a3fb8a 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -1398,15 +1398,23 @@
#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
/**
- * \brief Set hostname for ServerName TLS extension
- * (client-side only)
- *
+ * \brief Set or reset the hostname to check against the received
+ * server certificate. It sets the ServerName TLS extension,
+ * too, if that extension is enabled. (client-side only)
*
* \param ssl SSL context
- * \param hostname the server hostname
+ * \param hostname the server hostname, may be NULL to clear hostname
*
- * \return 0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED
- */
+ * \note Maximum hostname length SSL_MAX_HOST_NAME_LEN.
+ *
+ * \return 0 if successful, POLARSSL_ERR_SSL_MALLOC_FAILED on
+ * allocation failure, POLARSSL_ERR_BAD_INPUT_DATA on
+ * too long input hostname.
+ *
+ * \note Hostname set to the one provided on success (cleared
+ * when NULL). On allocation failure hostname is cleared.
+ * On too long input failure, old hostname is unchanged.
+*/
int ssl_set_hostname( ssl_context *ssl, const char *hostname );
/**
diff --git a/library/net.c b/library/net.c
index c7ce258..b42b86f 100644
--- a/library/net.c
+++ b/library/net.c
@@ -55,8 +55,8 @@
#endif
#endif /* _MSC_VER */
-#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
-#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
+#define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 )
+#define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 )
#define close(fd) closesocket(fd)
static int wsa_init_done = 0;
@@ -92,6 +92,14 @@
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+/* Some MS functions want int and MSVC warns if we pass size_t,
+ * but the standard functions use socklen_t, so cast only for MSVC */
+#if defined(_MSC_VER)
+#define MSVC_INT_CAST (int)
+#else
+#define MSVC_INT_CAST
+#endif
+
#include <stdlib.h>
#include <stdio.h>
@@ -202,7 +210,7 @@
continue;
}
- if( connect( *fd, cur->ai_addr, cur->ai_addrlen ) == 0 )
+ if( connect( *fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
{
ret = 0;
break;
@@ -299,7 +307,7 @@
continue;
}
- if( bind( *fd, cur->ai_addr, cur->ai_addrlen ) != 0 )
+ if( bind( *fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
{
close( *fd );
ret = POLARSSL_ERR_NET_BIND_FAILED;
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 146f283..0f0369a 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1675,10 +1675,6 @@
defined(POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED)
case TLS_EXT_SIG_ALG:
SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
- #if defined(POLARSSL_SSL_RENEGOTIATION)
- if( ssl->renegotiation == SSL_RENEGOTIATION )
- break;
- #endif
ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
if( ret != 0 )
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index bae8433..54867da 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -4230,26 +4230,51 @@
#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
int ssl_set_hostname( ssl_context *ssl, const char *hostname )
{
+ size_t hostname_len = 0;
+
+ /* Check if new hostname is valid before
+ * making any change to current one */
+
+ if( hostname != NULL )
+ {
+ hostname_len = strlen( hostname );
+
+ if( hostname_len > SSL_MAX_HOST_NAME_LEN )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ /* Now it's clear that we will overwrite the old hostname,
+ * so we can free it safely */
+
+ if( ssl->hostname != NULL )
+ {
+ polarssl_zeroize( ssl->hostname, ssl->hostname_len );
+ polarssl_free( ssl->hostname );
+ }
+
+ /* Passing NULL as hostname shall clear the old one */
+
if( hostname == NULL )
- return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+ {
+ ssl->hostname = NULL;
+ ssl->hostname_len = 0;
+ }
+ else
+ {
+ ssl->hostname = polarssl_malloc( hostname_len + 1 );
- ssl->hostname_len = strlen( hostname );
+ if( ssl->hostname == NULL )
+ {
+ ssl->hostname_len = 0;
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
- if( ssl->hostname_len + 1 == 0 )
- return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+ memcpy( ssl->hostname, (const unsigned char*) hostname,
+ hostname_len );
- if( ssl->hostname_len > SSL_MAX_HOST_NAME_LEN )
- return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
-
- ssl->hostname = polarssl_malloc( ssl->hostname_len + 1 );
-
- if( ssl->hostname == NULL )
- return( POLARSSL_ERR_SSL_MALLOC_FAILED );
-
- memcpy( ssl->hostname, (const unsigned char *) hostname,
- ssl->hostname_len );
-
- ssl->hostname[ssl->hostname_len] = '\0';
+ ssl->hostname[hostname_len] = '\0';
+ ssl->hostname_len = hostname_len;
+ }
return( 0 );
}
diff --git a/library/x509.c b/library/x509.c
index 5e6062b..cb6fc6c 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -480,19 +480,26 @@
}
}
-static int x509_parse_int(unsigned char **p, unsigned n, int *res){
+static int x509_parse_int( unsigned char **p, size_t n, int *res )
+{
*res = 0;
- for( ; n > 0; --n ){
- if( ( **p < '0') || ( **p > '9' ) ) return POLARSSL_ERR_X509_INVALID_DATE;
+
+ for( ; n > 0; --n )
+ {
+ if( ( **p < '0') || ( **p > '9' ) )
+ return( POLARSSL_ERR_X509_INVALID_DATE );
+
*res *= 10;
- *res += (*(*p)++ - '0');
+ *res += ( *(*p)++ - '0' );
}
- return 0;
+
+ return( 0 );
}
static int x509_date_is_valid(const x509_time *t)
{
int ret = POLARSSL_ERR_X509_INVALID_DATE;
+ int month_len;
CHECK_RANGE( 0, 9999, t->year );
CHECK_RANGE( 0, 23, t->hour );
@@ -502,17 +509,22 @@
switch( t->mon )
{
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
- CHECK_RANGE( 1, 31, t->day );
+ month_len = 31;
break;
case 4: case 6: case 9: case 11:
- CHECK_RANGE( 1, 30, t->day );
+ month_len = 30;
break;
case 2:
- CHECK_RANGE( 1, 28 + (t->year % 4 == 0), t->day );
+ if( ( !( t->year % 4 ) && t->year % 100 ) ||
+ !( t->year % 400 ) )
+ month_len = 29;
+ else
+ month_len = 28;
break;
default:
return( ret );
}
+ CHECK_RANGE( 1, month_len, t->day );
return( 0 );
}
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 1856cc4..af3b0d3 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -1267,7 +1267,7 @@
len = polarssl_snprintf( (char *) buf, sizeof(buf) - 1, GET_REQUEST,
opt.request_page );
- tail_len = strlen( GET_REQUEST_END );
+ tail_len = (int) strlen( GET_REQUEST_END );
/* Add padding to GET request to reach opt.request_size in length */
if( opt.request_size != DFL_REQUEST_SIZE &&
diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c
index 27c57a1..8a7850e 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -57,8 +57,10 @@
#include <unistd.h>
#else
#include <io.h>
-#define read _read
-#define write _write
+#define read(fd, buf, len) \
+ _read( fd, (void *)( buf ), (unsigned int)( len ) )
+#define write(fd, buf, len) \
+ _write( fd, (const void *)( buf ), (unsigned int)( len ) )
#endif
#if defined(_WIN32) || defined(_WIN32_WCE)
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 2c5d9eb..b99aeb6 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -254,7 +254,7 @@
#define USAGE \
"\n usage: ssl_server2 param=<>...\n" \
"\n acceptable parameters:\n" \
- " server_addr=%%d default: (all interfaces)\n" \
+ " server_addr=%%s 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" \
@@ -1791,7 +1791,7 @@
unsigned char *larger_buf;
ori_len = ret;
- extra_len = ssl_get_bytes_avail( &ssl );
+ extra_len = (int) ssl_get_bytes_avail( &ssl );
larger_buf = polarssl_malloc( ori_len + extra_len + 1 );
if( larger_buf == NULL )
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index ed695cb..0f97668 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -1099,6 +1099,40 @@
-s "=> renegotiate" \
-s "write hello request"
+# Checks that no Signature Algorithm with SHA-1 gets negotiated. Negotiating SHA-1 would mean that
+# the server did not parse the Signature Algorithm extension. This test is valid only if an MD
+# algorithm stronger than SHA-1 is enabled in config.h
+run_test "Renegotiation: Signature Algorithms parsing, client-initiated" \
+ "$P_SRV debug_level=3 exchanges=2 renegotiation=1 auth_mode=optional" \
+ "$P_CLI debug_level=3 exchanges=2 renegotiation=1 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" \
+ -S "client hello v3, signature_algorithm ext: 2" # Is SHA-1 negotiated?
+
+# Checks that no Signature Algorithm with SHA-1 gets negotiated. Negotiating SHA-1 would mean that
+# the server did not parse the Signature Algorithm extension. This test is valid only if an MD
+# algorithm stronger than SHA-1 is enabled in config.h
+run_test "Renegotiation: Signature Algorithms parsing, server-initiated" \
+ "$P_SRV debug_level=3 exchanges=2 renegotiation=1 auth_mode=optional renegotiate=1" \
+ "$P_CLI debug_level=3 exchanges=2 renegotiation=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" \
+ -S "client hello v3, signature_algorithm ext: 2" # Is SHA-1 negotiated?
+
run_test "Renegotiation: double" \
"$P_SRV debug_level=3 exchanges=2 renegotiation=1 renegotiate=1" \
"$P_CLI debug_level=3 exchanges=2 renegotiation=1 renegotiate=1" \
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 135ec60..4f6cfd5 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -1546,3 +1546,19 @@
X509 Get time (UTC invalid sec)
depends_on:POLARSSL_X509_USE_C
x509_get_time:ASN1_UTC_TIME:"001130235960Z":POLARSSL_ERR_X509_INVALID_DATE:0:0:0:0:0:0
+
+X509 Get time (Generalized Time, year multiple of 100 but not 400 is not a leap year)
+depends_on:POLARSSL_X509_USE_C
+x509_get_time:ASN1_GENERALIZED_TIME:"19000229000000Z":POLARSSL_ERR_X509_INVALID_DATE:0:0:0:0:0:0
+
+X509 Get time (Generalized Time, year multiple of 4 but not 100 is a leap year)
+depends_on:POLARSSL_X509_USE_C
+x509_get_time:ASN1_GENERALIZED_TIME:"19920229000000Z":0:1992:2:29:0:0:0
+
+X509 Get time (Generalized Time, year multiple of 400 is a leap year)
+depends_on:POLARSSL_X509_USE_C
+x509_get_time:ASN1_GENERALIZED_TIME:"20000229000000Z":0:2000:2:29:0:0:0
+
+X509 Get time (Generalized Time invalid leap year not multiple of 4, 100 or 400)
+depends_on:POLARSSL_X509_USE_C
+x509_get_time:ASN1_GENERALIZED_TIME:"19910229000000Z":POLARSSL_ERR_X509_INVALID_DATE:0:0:0:0:0:0