Merge remote-tracking branch 'origin/pr/2554' into mbedtls-2.7
* origin/pr/2554:
Remove ssl_cert_test sample app
diff --git a/.travis.yml b/.travis.yml
index 4d23652..b4f21a3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,7 +24,8 @@
- tests/scripts/travis-log-failure.sh
env:
global:
- secure: "barHldniAfXyoWOD/vcO+E6/Xm4fmcaUoC9BeKW+LwsHqlDMLvugaJnmLXkSpkbYhVL61Hzf3bo0KPJn88AFc5Rkf8oYHPjH4adMnVXkf3B9ghHCgznqHsAH3choo6tnPxaFgOwOYmLGb382nQxfE5lUdvnM/W/psQjWt66A1+k="
+ - SEED=1
+ - secure: "barHldniAfXyoWOD/vcO+E6/Xm4fmcaUoC9BeKW+LwsHqlDMLvugaJnmLXkSpkbYhVL61Hzf3bo0KPJn88AFc5Rkf8oYHPjH4adMnVXkf3B9ghHCgznqHsAH3choo6tnPxaFgOwOYmLGb382nQxfE5lUdvnM/W/psQjWt66A1+k="
addons:
apt:
diff --git a/ChangeLog b/ChangeLog
index 2c031a1..54971ae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -21,6 +21,15 @@
* Fix private key DER output in the key_app_writer example. File contents
were shifted by one byte, creating an invalid ASN.1 tag. Fixed by
Christian Walther in #2239.
+ * Fix potential memory leak in X.509 self test. Found and fixed by
+ Junhwan Park, #2106.
+ * Fix 1-byte buffer overflow in mbedtls_mpi_write_string() when
+ used with negative inputs. Found by Guido Vranken in #2404.
+ * Fix bugs in the AEAD test suite which would be exposed by ciphers which
+ either used both encrypt and decrypt key schedules, or which perform padding.
+ GCM and CCM were not affected. Fixed by Jack Lloyd.
+ * Fix incorrect default port number in ssl_mail_client example's usage.
+ Found and fixed by irwir. #2337
Changes
* Return from various debugging routines immediately if the
diff --git a/circle.yml b/circle.yml
deleted file mode 100644
index eaed02a..0000000
--- a/circle.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-# Purpose:
-# - To test and prove that a new commit in the mbed TLS repository builds
-# and integrates with mbed-os properly.
-# AND
-# - To test and prove that the current development head of mbed TLS builds
-# and integrates with the current mbed-os master branch.
-#
-# The script fetches all the prerequisites and builds the mbed TLS 'tls-client'
-# example. This script is triggered by every commit and once each night and the
-# exact behaviour depends on how it was triggered:
-# - If it is a nightly build then it builds the mbed TLS development head with
-# mbed-os master.
-# - If it was triggered by the commit, then it builds the example with mbed TLS
-# at that commit and mbed-os at the commit pointed by mbed-os.lib in the
-# example repository.
-
-test:
- override:
- - cd ../mbed-os-example-tls/tls-client/ && mbed compile -m K64F -t GCC_ARM -c
-
-dependencies:
- pre:
- # Install gcc-arm
- - cd .. && wget "https://launchpad.net/gcc-arm-embedded/4.9/4.9-2015-q3-update/+download/gcc-arm-none-eabi-4_9-2015q3-20150921-linux.tar.bz2"
- - cd .. && tar -xvjf gcc-arm-none-eabi-4_9-2015q3-20150921-linux.tar.bz2
- - ln -s ../gcc-arm-none-eabi-4_9-2015q3/bin/* ../bin/
- # Install mbed-cli
- - cd ../ && git clone https://github.com/ARMmbed/mbed-cli.git
- - cd ../mbed-cli && sudo -H pip install -e .
- # Get the sample application
- - cd ../ && git clone git@github.com:ARMmbed/mbed-os-example-tls.git
- # Get mbed-os
- - cd ../mbed-os-example-tls/tls-client && mbed deploy
- # Update mbed-os to master only if it is a nightly build
- - >
- if [ -n "${RUN_NIGHTLY_BUILD}" ]; then
- cd ../mbed-os-example-tls/tls-client/mbed-os/ && mbed update master;
- fi
- # Import mbedtls current revision
- - ln -s ../../../../../../../mbedtls/ ../mbed-os-example-tls/tls-client/mbed-os/features/mbedtls/importer/TARGET_IGNORE/mbedtls
- - cd ../mbed-os-example-tls/tls-client/mbed-os/features/mbedtls/importer/ && make
- override:
- # Install the missing python packages
- - cd ../mbed-os-example-tls/tls-client/mbed-os/ && sudo -H pip install -r requirements.txt
diff --git a/library/bignum.c b/library/bignum.c
index f6e50b9..d142fe6 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -552,15 +552,20 @@
if( radix < 2 || radix > 16 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
- n = mbedtls_mpi_bitlen( X );
- if( radix >= 4 ) n >>= 1;
- if( radix >= 16 ) n >>= 1;
- /*
- * Round up the buffer length to an even value to ensure that there is
- * enough room for hexadecimal values that can be represented in an odd
- * number of digits.
- */
- n += 3 + ( ( n + 1 ) & 1 );
+ n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
+ if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present
+ * `n`. If radix > 4, this might be a strict
+ * overapproximation of the number of
+ * radix-adic digits needed to present `n`. */
+ if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to
+ * present `n`. */
+
+ n += 1; /* Terminating null byte */
+ n += 1; /* Compensate for the divisions above, which round down `n`
+ * in case it's not even. */
+ n += 1; /* Potential '-'-sign. */
+ n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
+ * which always uses an even number of hex-digits. */
if( buflen < n )
{
@@ -572,7 +577,10 @@
mbedtls_mpi_init( &T );
if( X->s == -1 )
+ {
*p++ = '-';
+ buflen--;
+ }
if( radix == 16 )
{
diff --git a/library/x509.c b/library/x509.c
index 264c7fb..cba6a38 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -1032,8 +1032,8 @@
*/
int mbedtls_x509_self_test( int verbose )
{
+ int ret = 0;
#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C)
- int ret;
uint32_t flags;
mbedtls_x509_crt cacert;
mbedtls_x509_crt clicert;
@@ -1041,6 +1041,7 @@
if( verbose != 0 )
mbedtls_printf( " X.509 certificate load: " );
+ mbedtls_x509_crt_init( &cacert );
mbedtls_x509_crt_init( &clicert );
ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
@@ -1050,11 +1051,9 @@
if( verbose != 0 )
mbedtls_printf( "failed\n" );
- return( ret );
+ goto cleanup;
}
- mbedtls_x509_crt_init( &cacert );
-
ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt,
mbedtls_test_ca_crt_len );
if( ret != 0 )
@@ -1062,7 +1061,7 @@
if( verbose != 0 )
mbedtls_printf( "failed\n" );
- return( ret );
+ goto cleanup;
}
if( verbose != 0 )
@@ -1074,20 +1073,19 @@
if( verbose != 0 )
mbedtls_printf( "failed\n" );
- return( ret );
+ goto cleanup;
}
if( verbose != 0 )
mbedtls_printf( "passed\n\n");
+cleanup:
mbedtls_x509_crt_free( &cacert );
mbedtls_x509_crt_free( &clicert );
-
- return( 0 );
#else
((void) verbose);
- return( 0 );
#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */
+ return( ret );
}
#endif /* MBEDTLS_SELF_TEST */
diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c
index 7214dc2..8ec6079 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -104,9 +104,9 @@
#if defined(MBEDTLS_BASE64_C)
#define USAGE_AUTH \
- " authentication=%%d default: 0 (disabled)\n" \
- " user_name=%%s default: \"user\"\n" \
- " user_pwd=%%s default: \"password\"\n"
+ " authentication=%%d default: 0 (disabled)\n" \
+ " user_name=%%s default: \"" DFL_USER_NAME "\"\n" \
+ " user_pwd=%%s default: \"" DFL_USER_PWD "\"\n"
#else
#define USAGE_AUTH \
" authentication options disabled. (Require MBEDTLS_BASE64_C)\n"
@@ -123,17 +123,17 @@
#endif /* MBEDTLS_FS_IO */
#define USAGE \
- "\n usage: ssl_mail_client param=<>...\n" \
- "\n acceptable parameters:\n" \
- " server_name=%%s default: localhost\n" \
- " server_port=%%d default: 4433\n" \
- " debug_level=%%d default: 0 (disabled)\n" \
+ "\n usage: ssl_mail_client param=<>...\n" \
+ "\n acceptable parameters:\n" \
+ " server_name=%%s default: " DFL_SERVER_NAME "\n" \
+ " server_port=%%d default: " DFL_SERVER_PORT "\n" \
+ " debug_level=%%d default: 0 (disabled)\n" \
" mode=%%d default: 0 (SSL/TLS) (1 for STARTTLS)\n" \
- USAGE_AUTH \
- " mail_from=%%s default: \"\"\n" \
- " mail_to=%%s default: \"\"\n" \
- USAGE_IO \
- " force_ciphersuite=<name> default: all enabled\n"\
+ USAGE_AUTH \
+ " mail_from=%%s default: \"\"\n" \
+ " mail_to=%%s default: \"\"\n" \
+ USAGE_IO \
+ " force_ciphersuite=<name> default: all enabled\n" \
" acceptable ciphersuite names:\n"
/*
@@ -306,7 +306,7 @@
mbedtls_printf("\n%s", buf);
if( len && ( ret = mbedtls_net_send( sock_fd, buf, len ) ) <= 0 )
{
- mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
+ mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret );
return -1;
}
@@ -318,7 +318,7 @@
if( ret <= 0 )
{
- mbedtls_printf( "failed\n ! read returned %d\n\n", ret );
+ mbedtls_printf( "failed\n ! mbedtls_net_recv returned %d\n\n", ret );
return -1;
}
diff --git a/tests/scripts/check-files.py b/tests/scripts/check-files.py
index 7ea321f..0bf0120 100755
--- a/tests/scripts/check-files.py
+++ b/tests/scripts/check-files.py
@@ -19,14 +19,23 @@
import sys
-class IssueTracker(object):
- """Base class for issue tracking. Issues should inherit from this and
- overwrite either issue_with_line if they check the file line by line, or
- overwrite check_file_for_issue if they check the file as a whole."""
+class FileIssueTracker(object):
+ """Base class for file-wide issue tracking.
+
+ To implement a checker that processes a file as a whole, inherit from
+ this class and implement `check_file_for_issue` and define ``heading``.
+
+ ``files_exemptions``: files whose name ends with a string in this set
+ will not be checked.
+
+ ``heading``: human-readable description of the issue
+ """
+
+ files_exemptions = frozenset()
+ # heading must be defined in derived classes.
+ # pylint: disable=no-member
def __init__(self):
- self.heading = ""
- self.files_exemptions = []
self.files_with_issues = {}
def should_check_file(self, filepath):
@@ -35,23 +44,14 @@
return False
return True
- def issue_with_line(self, line):
- raise NotImplementedError
-
def check_file_for_issue(self, filepath):
- with open(filepath, "rb") as f:
- for i, line in enumerate(iter(f.readline, b"")):
- self.check_file_line(filepath, line, i + 1)
+ raise NotImplementedError
def record_issue(self, filepath, line_number):
if filepath not in self.files_with_issues.keys():
self.files_with_issues[filepath] = []
self.files_with_issues[filepath].append(line_number)
- def check_file_line(self, filepath, line, line_number):
- if self.issue_with_line(line):
- self.record_issue(filepath, line_number)
-
def output_file_issues(self, logger):
if self.files_with_issues.values():
logger.info(self.heading)
@@ -64,24 +64,44 @@
logger.info(filename)
logger.info("")
+class LineIssueTracker(FileIssueTracker):
+ """Base class for line-by-line issue tracking.
-class PermissionIssueTracker(IssueTracker):
+ To implement a checker that processes files line by line, inherit from
+ this class and implement `line_with_issue`.
+ """
- def __init__(self):
- super().__init__()
- self.heading = "Incorrect permissions:"
+ def issue_with_line(self, line, filepath):
+ raise NotImplementedError
+
+ def check_file_line(self, filepath, line, line_number):
+ if self.issue_with_line(line, filepath):
+ self.record_issue(filepath, line_number)
def check_file_for_issue(self, filepath):
- if not (os.access(filepath, os.X_OK) ==
- filepath.endswith((".sh", ".pl", ".py"))):
+ with open(filepath, "rb") as f:
+ for i, line in enumerate(iter(f.readline, b"")):
+ self.check_file_line(filepath, line, i + 1)
+
+class PermissionIssueTracker(FileIssueTracker):
+ """Track files with bad permissions.
+
+ Files that are not executable scripts must not be executable."""
+
+ heading = "Incorrect permissions:"
+
+ def check_file_for_issue(self, filepath):
+ is_executable = os.access(filepath, os.X_OK)
+ should_be_executable = filepath.endswith((".sh", ".pl", ".py"))
+ if is_executable != should_be_executable:
self.files_with_issues[filepath] = None
-class EndOfFileNewlineIssueTracker(IssueTracker):
+class EndOfFileNewlineIssueTracker(FileIssueTracker):
+ """Track files that end with an incomplete line
+ (no newline character at the end of the last line)."""
- def __init__(self):
- super().__init__()
- self.heading = "Missing newline at end of file:"
+ heading = "Missing newline at end of file:"
def check_file_for_issue(self, filepath):
with open(filepath, "rb") as f:
@@ -89,11 +109,11 @@
self.files_with_issues[filepath] = None
-class Utf8BomIssueTracker(IssueTracker):
+class Utf8BomIssueTracker(FileIssueTracker):
+ """Track files that start with a UTF-8 BOM.
+ Files should be ASCII or UTF-8. Valid UTF-8 does not start with a BOM."""
- def __init__(self):
- super().__init__()
- self.heading = "UTF-8 BOM present:"
+ heading = "UTF-8 BOM present:"
def check_file_for_issue(self, filepath):
with open(filepath, "rb") as f:
@@ -101,77 +121,76 @@
self.files_with_issues[filepath] = None
-class LineEndingIssueTracker(IssueTracker):
+class LineEndingIssueTracker(LineIssueTracker):
+ """Track files with non-Unix line endings (i.e. files with CR)."""
- def __init__(self):
- super().__init__()
- self.heading = "Non Unix line endings:"
+ heading = "Non Unix line endings:"
- def issue_with_line(self, line):
+ def issue_with_line(self, line, _filepath):
return b"\r" in line
-class TrailingWhitespaceIssueTracker(IssueTracker):
+class TrailingWhitespaceIssueTracker(LineIssueTracker):
+ """Track lines with trailing whitespace."""
- def __init__(self):
- super().__init__()
- self.heading = "Trailing whitespace:"
- self.files_exemptions = [".md"]
+ heading = "Trailing whitespace:"
+ files_exemptions = frozenset(".md")
- def issue_with_line(self, line):
+ def issue_with_line(self, line, _filepath):
return line.rstrip(b"\r\n") != line.rstrip()
-class TabIssueTracker(IssueTracker):
+class TabIssueTracker(LineIssueTracker):
+ """Track lines with tabs."""
- def __init__(self):
- super().__init__()
- self.heading = "Tabs present:"
- self.files_exemptions = [
- "Makefile", "generate_visualc_files.pl"
- ]
+ heading = "Tabs present:"
+ files_exemptions = frozenset([
+ "Makefile",
+ "generate_visualc_files.pl",
+ ])
- def issue_with_line(self, line):
+ def issue_with_line(self, line, _filepath):
return b"\t" in line
-class MergeArtifactIssueTracker(IssueTracker):
+class MergeArtifactIssueTracker(LineIssueTracker):
+ """Track lines with merge artifacts.
+ These are leftovers from a ``git merge`` that wasn't fully edited."""
- def __init__(self):
- super().__init__()
- self.heading = "Merge artifact:"
+ heading = "Merge artifact:"
- def issue_with_line(self, filepath, line):
+ def issue_with_line(self, line, _filepath):
# Detect leftover git conflict markers.
if line.startswith(b'<<<<<<< ') or line.startswith(b'>>>>>>> '):
return True
if line.startswith(b'||||||| '): # from merge.conflictStyle=diff3
return True
if line.rstrip(b'\r\n') == b'=======' and \
- not filepath.endswith('.md'):
+ not _filepath.endswith('.md'):
return True
return False
- def check_file_line(self, filepath, line, line_number):
- if self.issue_with_line(filepath, line):
- self.record_issue(filepath, line_number)
+class TodoIssueTracker(LineIssueTracker):
+ """Track lines containing ``TODO``."""
-class TodoIssueTracker(IssueTracker):
+ heading = "TODO present:"
+ files_exemptions = frozenset([
+ os.path.basename(__file__),
+ "benchmark.c",
+ "pull_request_template.md",
+ ])
- def __init__(self):
- super().__init__()
- self.heading = "TODO present:"
- self.files_exemptions = [
- __file__, "benchmark.c", "pull_request_template.md"
- ]
-
- def issue_with_line(self, line):
+ def issue_with_line(self, line, _filepath):
return b"todo" in line.lower()
class IntegrityChecker(object):
+ """Sanity-check files under the current directory."""
def __init__(self, log_file):
+ """Instantiate the sanity checker.
+ Check files under the current directory.
+ Write a report of issues to log_file."""
self.check_repo_path()
self.logger = None
self.setup_logger(log_file)
@@ -196,7 +215,8 @@
TodoIssueTracker(),
]
- def check_repo_path(self):
+ @staticmethod
+ def check_repo_path():
if not all(os.path.isdir(d) for d in ["include", "library", "tests"]):
raise Exception("Must be run from Mbed TLS root")
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index 343dd78..2518ba5 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -627,6 +627,9 @@
TEST_ASSERT( memcmp( output, clear, clear_len ) == 0 );
/* then encrypt the clear and make sure we get the same ciphertext and tag */
+ TEST_ASSERT( 0 == mbedtls_cipher_setkey( &ctx, key, 8 * key_len,
+ MBEDTLS_ENCRYPT ) );
+
memset( output, 0xFF, sizeof( output ) );
outlen = 0;
@@ -635,8 +638,8 @@
my_tag, tag_len );
TEST_ASSERT( ret == 0 );
- TEST_ASSERT( outlen == clear_len );
- TEST_ASSERT( memcmp( output, cipher, clear_len ) == 0 );
+ TEST_ASSERT( outlen == cipher_len );
+ TEST_ASSERT( memcmp( output, cipher, cipher_len ) == 0 );
TEST_ASSERT( memcmp( my_tag, tag, tag_len ) == 0 );
/* make sure we didn't overwrite */
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index 2960641..b8d7ad1 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -19,6 +19,9 @@
Base test mpi_read_write_string #3 (Negative decimal)
mpi_read_write_string:16:"-23":16:"-23":100:0:0
+Base test mpi_read_write_string #4 (Buffer just fits)
+mpi_read_write_string:16:"-4":4:"-10":4:0:0
+
Test mpi_read_write_string #1 (Invalid character)
mpi_read_write_string:10:"a28":0:"":100:MBEDTLS_ERR_MPI_INVALID_CHARACTER:0
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index 04dca0f..aa3c332 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -81,6 +81,8 @@
mbedtls_mpi_init( &X );
+ memset( str, '!', sizeof( str ) );
+
TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == result_read );
if( result_read == 0 )
{
@@ -88,6 +90,7 @@
if( result_write == 0 )
{
TEST_ASSERT( strcasecmp( str, input_A ) == 0 );
+ TEST_ASSERT( str[len] == '!' );
}
}