Merge remote-tracking branch 'origin/pr/2499' into mbedtls-2.7

* origin/pr/2499:
  Fix default port number information
diff --git a/ChangeLog b/ChangeLog
index b29a474..54971ae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,45 @@
 
 = mbed TLS 2.7.x branch released xxxx-xx-xx
 
+Security
+   * Make mbedtls_ecdh_get_params return an error if the second key
+     belongs to a different group from the first. Before, if an application
+     passed keys that belonged to different group, the first key's data was
+     interpreted according to the second group, which could lead to either
+     an error or a meaningless output from mbedtls_ecdh_get_params. In the
+     latter case, this could expose at most 5 bits of the private key.
+
+Bugfix
+   * Server's RSA certificate in certs.c was SHA-1 signed. In the default
+     mbedTLS configuration only SHA-2 signed certificates are accepted.
+     This certificate is used in the demo server programs, which lead the
+     client programs to fail at the peer's certificate verification
+     due to an unacceptable hash signature. The certificate has been
+     updated to one that is SHA-256 signed. Fix contributed by
+     Illya Gerasymchuk.
+   * 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
+     provided SSL context is unset.
+   * Remove dead code from bignum.c in the default configuration.
+     Found by Coverity, reported and fixed by Peter Kolbus (Garmin). Fixes #2309.
+   * Add test for minimal value of MBEDTLS_MPI_WINDOW_SIZE to all.sh.
+     Contributed by Peter Kolbus (Garmin).
+
+= mbed TLS 2.7.10 branch released 2019-03-19
+
 Features
    * Add MBEDTLS_REMOVE_3DES_CIPHERSUITES to allow removing 3DES ciphersuites
      from the default list (enabled by default). See
@@ -20,18 +59,6 @@
      extensions in CSRs and CRTs that caused these bitstrings to not be encoded
      correctly as trailing zeroes were not accounted for as unused bits in the
      leading content octet. Fixes #1610.
-   * Server's RSA certificate in certs.c was SHA-1 signed. In the default
-     mbedTLS configuration only SHA-2 signed certificates are accepted.
-     This certificate is used in the demo server programs, which lead the
-     client programs to fail at the peer's certificate verification
-     due to an unacceptable hash signature. The certificate has been
-     updated to one that is SHA-256 signed. Fix contributed by
-     Illya Gerasymchuk.
-   * 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 incorrect default port number in ssl_mail_client example's usage.
-     Found and fixed by irwir. #2337
 
 Changes
    * Include configuration file in all header files that use configuration,
@@ -48,12 +75,6 @@
      underlying OS actually guarantees.
    * Ciphersuites based on 3DES now have the lowest priority by default when
      they are enabled.
-   * Return from various debugging routines immediately if the
-     provided SSL context is unset.
-   * Remove dead code from bignum.c in the default configuration.
-     Found by Coverity, reported and fixed by Peter Kolbus (Garmin). Fixes #2309.
-   * Add test for minimal value of MBEDTLS_MPI_WINDOW_SIZE to all.sh.
-     Contributed by Peter Kolbus (Garmin).
 
 = mbed TLS 2.7.9 branch released 2018-12-21
 
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/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index 0038615..c37ff6f 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -24,7 +24,7 @@
  */
 
 /**
- * @mainpage mbed TLS v2.7.9 source code documentation
+ * @mainpage mbed TLS v2.7.10 source code documentation
  *
  * This documentation describes the internal structure of mbed TLS.  It was
  * automatically generated from specially formatted comment blocks in
diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile
index 54e4463..eb8f134 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -28,7 +28,7 @@
 # identify the project. Note that if you do not use Doxywizard you need
 # to put quotes around the project name if it contains spaces.
 
-PROJECT_NAME           = "mbed TLS v2.7.9"
+PROJECT_NAME           = "mbed TLS v2.7.10"
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
 # This could be handy for archiving the generated documentation or
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index 36feff0..715bf21 100644
--- a/include/mbedtls/version.h
+++ b/include/mbedtls/version.h
@@ -40,16 +40,16 @@
  */
 #define MBEDTLS_VERSION_MAJOR  2
 #define MBEDTLS_VERSION_MINOR  7
-#define MBEDTLS_VERSION_PATCH  9
+#define MBEDTLS_VERSION_PATCH  10
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x02070900
-#define MBEDTLS_VERSION_STRING         "2.7.9"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.7.9"
+#define MBEDTLS_VERSION_NUMBER         0x02070A00
+#define MBEDTLS_VERSION_STRING         "2.7.10"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.7.10"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 3afdcc5..abe74fd 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -147,15 +147,15 @@
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
     add_library(mbedcrypto SHARED ${src_crypto})
-    set_target_properties(mbedcrypto PROPERTIES VERSION 2.7.9 SOVERSION 2)
+    set_target_properties(mbedcrypto PROPERTIES VERSION 2.7.10 SOVERSION 2)
     target_link_libraries(mbedcrypto ${libs})
 
     add_library(mbedx509 SHARED ${src_x509})
-    set_target_properties(mbedx509 PROPERTIES VERSION 2.7.9 SOVERSION 0)
+    set_target_properties(mbedx509 PROPERTIES VERSION 2.7.10 SOVERSION 0)
     target_link_libraries(mbedx509 ${libs} mbedcrypto)
 
     add_library(mbedtls SHARED ${src_tls})
-    set_target_properties(mbedtls PROPERTIES VERSION 2.7.9 SOVERSION 10)
+    set_target_properties(mbedtls PROPERTIES VERSION 2.7.10 SOVERSION 10)
     target_link_libraries(mbedtls ${libs} mbedx509)
 
     install(TARGETS mbedtls mbedx509 mbedcrypto
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/ecdh.c b/library/ecdh.c
index 61380b6..75630bd 100644
--- a/library/ecdh.c
+++ b/library/ecdh.c
@@ -179,8 +179,20 @@
 {
     int ret;
 
-    if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 )
-        return( ret );
+    if( ctx->grp.id == MBEDTLS_ECP_DP_NONE )
+    {
+        /* This is the first call to get_params(). Copy the group information
+         * into the context. */
+        if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 )
+            return( ret );
+    }
+    else
+    {
+        /* This is not the first call to get_params(). Check that the group
+         * is the same as the first time. */
+        if( ctx->grp.id != key->grp.id )
+            return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    }
 
     /* If it's not our key, just import the public part as Qp */
     if( side == MBEDTLS_ECDH_THEIRS )
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/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_ecdh.data b/tests/suites/test_suite_ecdh.data
index f7119de..4ed3221 100644
--- a/tests/suites/test_suite_ecdh.data
+++ b/tests/suites/test_suite_ecdh.data
@@ -37,3 +37,19 @@
 ECDH exchange #2
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
 ecdh_exchange:MBEDTLS_ECP_DP_SECP521R1
+
+ECDH calc_secret: ours first, SECP256R1 (RFC 5903)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdh_exchange_calc_secret:MBEDTLS_ECP_DP_SECP256R1:"c6ef9c5d78ae012a011164acb397ce2088685d8f06bf9be0b283ab46476bee53":"04dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":0:"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de"
+
+ECDH calc_secret: theirs first, SECP256R1 (RFC 5903)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdh_exchange_calc_secret:MBEDTLS_ECP_DP_SECP256R1:"c6ef9c5d78ae012a011164acb397ce2088685d8f06bf9be0b283ab46476bee53":"04dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":1:"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de"
+
+ECDH get_params with mismatched groups: our BP256R1, their SECP256R1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_BP256R1_ENABLED
+ecdh_exchange_get_params_fail:MBEDTLS_ECP_DP_BP256R1:"1234567812345678123456781234567812345678123456781234567812345678":MBEDTLS_ECP_DP_SECP256R1:"04dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":0:MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECDH get_params with mismatched groups: their SECP256R1, our BP256R1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_BP256R1_ENABLED
+ecdh_exchange_get_params_fail:MBEDTLS_ECP_DP_BP256R1:"1234567812345678123456781234567812345678123456781234567812345678":MBEDTLS_ECP_DP_SECP256R1:"04dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":1:MBEDTLS_ERR_ECP_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function
index 4c6a97b..0645ce7 100644
--- a/tests/suites/test_suite_ecdh.function
+++ b/tests/suites/test_suite_ecdh.function
@@ -1,5 +1,47 @@
 /* BEGIN_HEADER */
 #include "mbedtls/ecdh.h"
+
+static int load_public_key( int grp_id, const char *point_str,
+                            mbedtls_ecp_keypair *ecp )
+{
+    int ok = 0;
+    unsigned char point_buf[MBEDTLS_ECP_MAX_PT_LEN];
+    size_t point_len = unhexify( point_buf, point_str );
+
+    TEST_ASSERT( mbedtls_ecp_group_load( &ecp->grp, grp_id ) == 0 );
+    TEST_ASSERT( mbedtls_ecp_point_read_binary( &ecp->grp,
+                                                &ecp->Q,
+                                                point_buf,
+                                                point_len ) == 0 );
+    TEST_ASSERT( mbedtls_ecp_check_pubkey( &ecp->grp,
+                                           &ecp->Q ) == 0 );
+    ok = 1;
+exit:
+    return( ok );
+}
+
+static int load_private_key( int grp_id, const char *private_key_str,
+                             mbedtls_ecp_keypair *ecp,
+                             rnd_pseudo_info *rnd_info )
+{
+    int ok = 0;
+    unsigned char private_key_buf[MBEDTLS_ECP_MAX_BYTES];
+    size_t private_key_len = unhexify( private_key_buf, private_key_str );
+
+    TEST_ASSERT( mbedtls_ecp_group_load( &ecp->grp, grp_id ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &ecp->d,
+                                          private_key_buf,
+                                          private_key_len ) == 0 );
+    TEST_ASSERT( mbedtls_ecp_check_privkey( &ecp->grp, &ecp->d ) == 0 );
+    /* Calculate the public key from the private key. */
+    TEST_ASSERT( mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d,
+                                  &ecp->grp.G,
+                                  &rnd_pseudo_rand, rnd_info ) == 0 );
+    ok = 1;
+exit:
+    return( ok );
+}
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -158,3 +200,111 @@
     mbedtls_ecdh_free( &cli );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void ecdh_exchange_calc_secret( int grp_id,
+                                char *our_private_key,
+                                char *their_point,
+                                int ours_first,
+                                char *expected_str )
+{
+    rnd_pseudo_info rnd_info;
+    unsigned char expected_buf[MBEDTLS_ECP_MAX_BYTES];
+    size_t expected_len;
+    mbedtls_ecp_keypair our_key;
+    mbedtls_ecp_keypair their_key;
+    mbedtls_ecdh_context ecdh;
+    unsigned char shared_secret[MBEDTLS_ECP_MAX_BYTES];
+    size_t shared_secret_length = 0;
+
+    memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
+    mbedtls_ecdh_init( &ecdh );
+    mbedtls_ecp_keypair_init( &our_key );
+    mbedtls_ecp_keypair_init( &their_key );
+
+    expected_len = unhexify( expected_buf, expected_str );
+
+    if( ! load_private_key( grp_id, our_private_key, &our_key, &rnd_info ) )
+        goto exit;
+    if( ! load_public_key( grp_id, their_point, &their_key ) )
+        goto exit;
+
+    /* Import the keys to the ECDH calculation. */
+    if( ours_first )
+    {
+        TEST_ASSERT( mbedtls_ecdh_get_params(
+                         &ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 );
+        TEST_ASSERT( mbedtls_ecdh_get_params(
+                         &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 );
+    }
+    else
+    {
+        TEST_ASSERT( mbedtls_ecdh_get_params(
+                         &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 );
+        TEST_ASSERT( mbedtls_ecdh_get_params(
+                         &ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 );
+    }
+
+    /* Perform the ECDH calculation. */
+    TEST_ASSERT( mbedtls_ecdh_calc_secret(
+                     &ecdh,
+                     &shared_secret_length,
+                     shared_secret, sizeof( shared_secret ),
+                     &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( shared_secret_length == expected_len );
+    TEST_ASSERT( memcmp( expected_buf, shared_secret,
+                         shared_secret_length ) == 0 );
+
+exit:
+    mbedtls_ecdh_free( &ecdh );
+    mbedtls_ecp_keypair_free( &our_key );
+    mbedtls_ecp_keypair_free( &their_key );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void ecdh_exchange_get_params_fail( int our_grp_id,
+                                    char *our_private_key,
+                                    int their_grp_id,
+                                    char *their_point,
+                                    int ours_first,
+                                    int expected_ret )
+{
+    rnd_pseudo_info rnd_info;
+    mbedtls_ecp_keypair our_key;
+    mbedtls_ecp_keypair their_key;
+    mbedtls_ecdh_context ecdh;
+
+    memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
+    mbedtls_ecdh_init( &ecdh );
+    mbedtls_ecp_keypair_init( &our_key );
+    mbedtls_ecp_keypair_init( &their_key );
+
+    if( ! load_private_key( our_grp_id, our_private_key, &our_key, &rnd_info ) )
+        goto exit;
+    if( ! load_public_key( their_grp_id, their_point, &their_key ) )
+        goto exit;
+
+    if( ours_first )
+    {
+        TEST_ASSERT( mbedtls_ecdh_get_params(
+                         &ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 );
+        TEST_ASSERT( mbedtls_ecdh_get_params(
+                         &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) ==
+                     expected_ret );
+    }
+    else
+    {
+        TEST_ASSERT( mbedtls_ecdh_get_params(
+                         &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 );
+        TEST_ASSERT( mbedtls_ecdh_get_params(
+                         &ecdh, &our_key, MBEDTLS_ECDH_OURS ) ==
+                     expected_ret );
+    }
+
+exit:
+    mbedtls_ecdh_free( &ecdh );
+    mbedtls_ecp_keypair_free( &our_key );
+    mbedtls_ecp_keypair_free( &their_key );
+}
+/* END_CASE */
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] == '!' );
         }
     }
 
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index eafceb3..fe807fe 100644
--- a/tests/suites/test_suite_version.data
+++ b/tests/suites/test_suite_version.data
@@ -1,8 +1,8 @@
 Check compiletime library version
-check_compiletime_version:"2.7.9"
+check_compiletime_version:"2.7.10"
 
 Check runtime library version
-check_runtime_version:"2.7.9"
+check_runtime_version:"2.7.10"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0