Merge remote-tracking branch 'public/pr/2299' into development
diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h
index cbd4841..05b2b03 100644
--- a/include/mbedtls/ecdh.h
+++ b/include/mbedtls/ecdh.h
@@ -149,11 +149,16 @@
  *
  * \see             ecp.h
  *
- * \param grp       The ECP group.
+ * \param grp       The ECP group to use. This must be initialized and have
+ *                  domain parameters loaded, for example through
+ *                  mbedtls_ecp_load() or mbedtls_ecp_tls_read_group().
  * \param d         The destination MPI (private key).
+ *                  This must be initialized.
  * \param Q         The destination point (public key).
- * \param f_rng     The RNG function.
- * \param p_rng     The RNG context.
+ *                  This must be initialized.
+ * \param f_rng     The RNG function to use. This must not be \c NULL.
+ * \param p_rng     The RNG context to be passed to \p f_rng. This may be
+ *                  \c NULL in case \p f_rng doesn't need a context argument.
  *
  * \return          \c 0 on success.
  * \return          Another \c MBEDTLS_ERR_ECP_XXX or
@@ -176,12 +181,22 @@
  *                  countermeasures against side-channel attacks.
  *                  For more information, see mbedtls_ecp_mul().
  *
- * \param grp       The ECP group.
+ * \param grp       The ECP group to use. This must be initialized and have
+ *                  domain parameters loaded, for example through
+ *                  mbedtls_ecp_load() or mbedtls_ecp_tls_read_group().
  * \param z         The destination MPI (shared secret).
+ *                  This must be initialized.
  * \param Q         The public key from another party.
+ *                  This must be initialized.
  * \param d         Our secret exponent (private key).
- * \param f_rng     The RNG function.
- * \param p_rng     The RNG context.
+ *                  This must be initialized.
+ * \param f_rng     The RNG function. This may be \c NULL if randomization
+ *                  of intermediate results during the ECP computations is
+ *                  not needed (discouraged). See the documentation of
+ *                  mbedtls_ecp_mul() for more.
+ * \param p_rng     The RNG context to be passed to \p f_rng. This may be
+ *                  \c NULL if \p f_rng is \c NULL or doesn't need a
+ *                  context argument.
  *
  * \return          \c 0 on success.
  * \return          Another \c MBEDTLS_ERR_ECP_XXX or
@@ -195,7 +210,7 @@
 /**
  * \brief           This function initializes an ECDH context.
  *
- * \param ctx       The ECDH context to initialize.
+ * \param ctx       The ECDH context to initialize. This must not be \c NULL.
  */
 void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx );
 
@@ -210,39 +225,42 @@
  *                  This is the first function used by a TLS server for ECDHE
  *                  ciphersuites.
  *
- * \param ctx       The ECDH context to set up.
+ * \param ctx       The ECDH context to set up. This must be initialized.
  * \param grp_id    The group id of the group to set up the context for.
  *
  * \return          \c 0 on success.
  */
-int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id );
+int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx,
+                        mbedtls_ecp_group_id grp_id );
 
 /**
  * \brief           This function frees a context.
  *
- * \param ctx       The context to free.
+ * \param ctx       The context to free. This may be \c NULL, in which
+ *                  case this function does nothing. If it is not \c NULL,
+ *                  it must point to an initialized ECDH context.
  */
 void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx );
 
 /**
- * \brief           This function generates a public key and a TLS
- *                  ServerKeyExchange payload.
+ * \brief           This function generates an EC key pair and exports its
+ *                  in the format used in a TLS ServerKeyExchange handshake
+ *                  message.
  *
  *                  This is the second function used by a TLS server for ECDHE
  *                  ciphersuites. (It is called after mbedtls_ecdh_setup().)
  *
- * \note            This function assumes that the ECP group (grp) of the
- *                  \p ctx context has already been properly set,
- *                  for example, using mbedtls_ecp_group_load().
- *
  * \see             ecp.h
  *
- * \param ctx       The ECDH context.
- * \param olen      The number of characters written.
- * \param buf       The destination buffer.
- * \param blen      The length of the destination buffer.
- * \param f_rng     The RNG function.
- * \param p_rng     The RNG context.
+ * \param ctx       The ECDH context to use. This must be initialized
+ *                  and bound to a group, for example via mbedtls_ecdh_setup().
+ * \param olen      The address at which to store the number of Bytes written.
+ * \param buf       The destination buffer. This must be a writable buffer of
+ *                  length \p blen Bytes.
+ * \param blen      The length of the destination buffer \p buf in Bytes.
+ * \param f_rng     The RNG function to use. This must not be \c NULL.
+ * \param p_rng     The RNG context to be passed to \p f_rng. This may be
+ *                  \c NULL in case \p f_rng doesn't need a context argument.
  *
  * \return          \c 0 on success.
  * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
@@ -255,24 +273,32 @@
                       void *p_rng );
 
 /**
- * \brief           This function parses and processes a TLS ServerKeyExhange
- *                  payload.
+ * \brief           This function parses the ECDHE parameters in a
+ *                  TLS ServerKeyExchange handshake message.
  *
- *                  This is the first function used by a TLS client for ECDHE
- *                  ciphersuites.
+ * \note            In a TLS handshake, this is the how the client
+ *                  sets up its ECDHE context from the server's public
+ *                  ECDHE key material.
  *
  * \see             ecp.h
  *
- * \param ctx       The ECDH context.
- * \param buf       The pointer to the start of the input buffer.
- * \param end       The address for one Byte past the end of the buffer.
+ * \param ctx       The ECDHE context to use. This must be initialized.
+ * \param buf       On input, \c *buf must be the start of the input buffer.
+ *                  On output, \c *buf is updated to point to the end of the
+ *                  data that has been read. On success, this is the first byte
+ *                  past the end of the ServerKeyExchange parameters.
+ *                  On error, this is the point at which an error has been
+ *                  detected, which is usually not useful except to debug
+ *                  failures.
+ * \param end       The end of the input buffer.
  *
  * \return          \c 0 on success.
  * \return          An \c MBEDTLS_ERR_ECP_XXX error code on failure.
  *
  */
 int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
-                      const unsigned char **buf, const unsigned char *end );
+                              const unsigned char **buf,
+                              const unsigned char *end );
 
 /**
  * \brief           This function sets up an ECDH context from an EC key.
@@ -283,33 +309,40 @@
  *
  * \see             ecp.h
  *
- * \param ctx       The ECDH context to set up.
- * \param key       The EC key to use.
- * \param side      Defines the source of the key: 1: Our key, or
- *                  0: The key of the peer.
+ * \param ctx       The ECDH context to set up. This must be initialized.
+ * \param key       The EC key to use. This must be initialized.
+ * \param side      Defines the source of the key. Possible values are:
+ *                  - #MBEDTLS_ECDH_OURS: The key is ours.
+ *                  - #MBEDTLS_ECDH_THEIRS: The key is that of the peer.
  *
  * \return          \c 0 on success.
  * \return          Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
  *
  */
-int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key,
-                     mbedtls_ecdh_side side );
+int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
+                             const mbedtls_ecp_keypair *key,
+                             mbedtls_ecdh_side side );
 
 /**
- * \brief           This function generates a public key and a TLS
- *                  ClientKeyExchange payload.
+ * \brief           This function generates a public key and exports it
+ *                  as a TLS ClientKeyExchange payload.
  *
  *                  This is the second function used by a TLS client for ECDH(E)
  *                  ciphersuites.
  *
  * \see             ecp.h
  *
- * \param ctx       The ECDH context.
- * \param olen      The number of Bytes written.
- * \param buf       The destination buffer.
- * \param blen      The size of the destination buffer.
- * \param f_rng     The RNG function.
- * \param p_rng     The RNG context.
+ * \param ctx       The ECDH context to use. This must be initialized
+ *                  and bound to a group, the latter usually by
+ *                  mbedtls_ecdh_read_params().
+ * \param olen      The address at which to store the number of Bytes written.
+ *                  This must not be \c NULL.
+ * \param buf       The destination buffer. This must be a writable buffer
+ *                  of length \p blen Bytes.
+ * \param blen      The size of the destination buffer \p buf in Bytes.
+ * \param f_rng     The RNG function to use. This must not be \c NULL.
+ * \param p_rng     The RNG context to be passed to \p f_rng. This may be
+ *                  \c NULL in case \p f_rng doesn't need a context argument.
  *
  * \return          \c 0 on success.
  * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
@@ -322,8 +355,8 @@
                       void *p_rng );
 
 /**
- * \brief       This function parses and processes a TLS ClientKeyExchange
- *              payload.
+ * \brief       This function parses and processes the ECDHE payload of a
+ *              TLS ClientKeyExchange message.
  *
  *              This is the third function used by a TLS server for ECDH(E)
  *              ciphersuites. (It is called after mbedtls_ecdh_setup() and
@@ -331,15 +364,17 @@
  *
  * \see         ecp.h
  *
- * \param ctx   The ECDH context.
- * \param buf   The start of the input buffer.
- * \param blen  The length of the input buffer.
+ * \param ctx   The ECDH context to use. This must be initialized
+ *              and bound to a group, for example via mbedtls_ecdh_setup().
+ * \param buf   The pointer to the ClientKeyExchange payload. This must
+ *              be a readable buffer of length \p blen Bytes.
+ * \param blen  The length of the input buffer \p buf in Bytes.
  *
  * \return      \c 0 on success.
  * \return      An \c MBEDTLS_ERR_ECP_XXX error code on failure.
  */
 int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
-                      const unsigned char *buf, size_t blen );
+                              const unsigned char *buf, size_t blen );
 
 /**
  * \brief           This function derives and exports the shared secret.
@@ -352,13 +387,19 @@
  *                  For more information, see mbedtls_ecp_mul().
  *
  * \see             ecp.h
- *
- * \param ctx       The ECDH context.
- * \param olen      The number of Bytes written.
- * \param buf       The destination buffer.
- * \param blen      The length of the destination buffer.
- * \param f_rng     The RNG function.
- * \param p_rng     The RNG context.
+
+ * \param ctx       The ECDH context to use. This must be initialized
+ *                  and have its own private key generated and the peer's
+ *                  public key imported.
+ * \param olen      The address at which to store the total number of
+ *                  Bytes written on success. This must not be \c NULL.
+ * \param buf       The buffer to write the generated shared key to. This
+ *                  must be a writable buffer of size \p blen Bytes.
+ * \param blen      The length of the destination buffer \p buf in Bytes.
+ * \param f_rng     The RNG function, for blinding purposes. This may
+ *                  b \c NULL if blinding isn't needed.
+ * \param p_rng     The RNG context. This may be \c NULL if \p f_rng
+ *                  doesn't need a context argument.
  *
  * \return          \c 0 on success.
  * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
@@ -381,7 +422,7 @@
  *                  computations once enabled, except by free-ing the context,
  *                  which cancels possible in-progress operations.
  *
- * \param ctx       The ECDH context.
+ * \param ctx       The ECDH context to use. This must be initialized.
  */
 void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx );
 #endif /* MBEDTLS_ECP_RESTARTABLE */
diff --git a/library/ecdh.c b/library/ecdh.c
index d68db8a..da95c60 100644
--- a/library/ecdh.c
+++ b/library/ecdh.c
@@ -35,9 +35,16 @@
 #if defined(MBEDTLS_ECDH_C)
 
 #include "mbedtls/ecdh.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
+/* Parameter validation macros based on platform_util.h */
+#define ECDH_VALIDATE_RET( cond )    \
+    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
+#define ECDH_VALIDATE( cond )        \
+    MBEDTLS_INTERNAL_VALIDATE( cond )
+
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
 typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
 #endif
@@ -78,6 +85,10 @@
                      int (*f_rng)(void *, unsigned char *, size_t),
                      void *p_rng )
 {
+    ECDH_VALIDATE_RET( grp != NULL );
+    ECDH_VALIDATE_RET( d != NULL );
+    ECDH_VALIDATE_RET( Q != NULL );
+    ECDH_VALIDATE_RET( f_rng != NULL );
     return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
 }
 #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
@@ -123,6 +134,10 @@
                          int (*f_rng)(void *, unsigned char *, size_t),
                          void *p_rng )
 {
+    ECDH_VALIDATE_RET( grp != NULL );
+    ECDH_VALIDATE_RET( Q != NULL );
+    ECDH_VALIDATE_RET( d != NULL );
+    ECDH_VALIDATE_RET( z != NULL );
     return( ecdh_compute_shared_restartable( grp, z, Q, d,
                                              f_rng, p_rng, NULL ) );
 }
@@ -146,6 +161,8 @@
  */
 void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
 {
+    ECDH_VALIDATE( ctx != NULL );
+
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
     ecdh_init_internal( ctx );
     mbedtls_ecp_point_init( &ctx->Vi  );
@@ -181,8 +198,7 @@
  */
 int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
 {
-    if( ctx == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    ECDH_VALIDATE_RET( ctx != NULL );
 
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
     return( ecdh_setup_internal( ctx, grp_id ) );
@@ -218,8 +234,7 @@
  */
 void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
 {
-    if( ctx == NULL )
-        return;
+    ECDH_VALIDATE( ctx != NULL );
 
     ctx->restart_enabled = 1;
 }
@@ -318,9 +333,10 @@
                               void *p_rng )
 {
     int restart_enabled = 0;
-
-    if( ctx == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    ECDH_VALIDATE_RET( ctx != NULL );
+    ECDH_VALIDATE_RET( olen != NULL );
+    ECDH_VALIDATE_RET( buf != NULL );
+    ECDH_VALIDATE_RET( f_rng != NULL );
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     restart_enabled = ctx->restart_enabled;
@@ -366,9 +382,10 @@
 {
     int ret;
     mbedtls_ecp_group_id grp_id;
-
-    if( ctx == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    ECDH_VALIDATE_RET( ctx != NULL );
+    ECDH_VALIDATE_RET( buf != NULL );
+    ECDH_VALIDATE_RET( *buf != NULL );
+    ECDH_VALIDATE_RET( end != NULL );
 
     if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
             != 0 )
@@ -420,9 +437,10 @@
                              mbedtls_ecdh_side side )
 {
     int ret;
-
-    if( ctx == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    ECDH_VALIDATE_RET( ctx != NULL );
+    ECDH_VALIDATE_RET( key != NULL );
+    ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
+                       side == MBEDTLS_ECDH_THEIRS );
 
     if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
         return( ret );
@@ -488,9 +506,10 @@
                               void *p_rng )
 {
     int restart_enabled = 0;
-
-    if( ctx == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    ECDH_VALIDATE_RET( ctx != NULL );
+    ECDH_VALIDATE_RET( olen != NULL );
+    ECDH_VALIDATE_RET( buf != NULL );
+    ECDH_VALIDATE_RET( f_rng != NULL );
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     restart_enabled = ctx->restart_enabled;
@@ -535,8 +554,8 @@
 int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
                               const unsigned char *buf, size_t blen )
 {
-    if( ctx == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    ECDH_VALIDATE_RET( ctx != NULL );
+    ECDH_VALIDATE_RET( buf != NULL );
 
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
     return( ecdh_read_public_internal( ctx, buf, blen ) );
@@ -607,9 +626,9 @@
                               void *p_rng )
 {
     int restart_enabled = 0;
-
-    if( ctx == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    ECDH_VALIDATE_RET( ctx != NULL );
+    ECDH_VALIDATE_RET( olen != NULL );
+    ECDH_VALIDATE_RET( buf != NULL );
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     restart_enabled = ctx->restart_enabled;
diff --git a/tests/suites/test_suite_ecdh.data b/tests/suites/test_suite_ecdh.data
index 89e5e3a..fe24ed4 100644
--- a/tests/suites/test_suite_ecdh.data
+++ b/tests/suites/test_suite_ecdh.data
@@ -1,3 +1,9 @@
+ECDH - Valid parameters
+ecdh_valid_param:
+
+ECDH - Invalid parameters
+ecdh_invalid_param:
+
 ECDH primitive random #1
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 ecdh_primitive_random:MBEDTLS_ECP_DP_SECP192R1
diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function
index 7144763..08a1686 100644
--- a/tests/suites/test_suite_ecdh.function
+++ b/tests/suites/test_suite_ecdh.function
@@ -8,6 +8,148 @@
  */
 
 /* BEGIN_CASE */
+void ecdh_valid_param( )
+{
+    TEST_VALID_PARAM( mbedtls_ecdh_free( NULL ) );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_CHECK_PARAMS:!MBEDTLS_PARAM_FAILED_ALT */
+void ecdh_invalid_param( )
+{
+    mbedtls_ecp_group grp;
+    mbedtls_ecdh_context ctx;
+    mbedtls_mpi m;
+    mbedtls_ecp_point P;
+    mbedtls_ecp_keypair kp;
+    size_t olen;
+    unsigned char buf[42] = { 0 };
+    const unsigned char *buf_null = NULL;
+    size_t const buflen = sizeof( buf );
+    int invalid_side = 42;
+    mbedtls_ecp_group_id valid_grp = MBEDTLS_ECP_DP_SECP192R1;
+
+    TEST_INVALID_PARAM( mbedtls_ecdh_init( NULL ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    TEST_INVALID_PARAM( mbedtls_ecdh_enable_restart( NULL ) );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_gen_public( NULL, &m, &P,
+                                                     rnd_std_rand, NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_gen_public( &grp, NULL, &P,
+                                                     rnd_std_rand, NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_gen_public( &grp, &m, NULL,
+                                                     rnd_std_rand, NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_gen_public( &grp, &m, &P,
+                                                     NULL, NULL ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_compute_shared( NULL, &m, &P, &m,
+                                                         rnd_std_rand, NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_compute_shared( &grp, NULL, &P, &m,
+                                                         rnd_std_rand, NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_compute_shared( &grp, &m, NULL, &m,
+                                                         rnd_std_rand, NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_compute_shared( &grp, &m, &P, NULL,
+                                                         rnd_std_rand, NULL ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_setup( NULL, valid_grp ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_make_params( NULL, &olen,
+                                                      buf, buflen,
+                                                      rnd_std_rand, NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_make_params( &ctx, NULL,
+                                                      buf, buflen,
+                                                      rnd_std_rand, NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_make_params( &ctx, &olen,
+                                                      NULL, buflen,
+                                                      rnd_std_rand, NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_make_params( &ctx, &olen,
+                                                      buf, buflen,
+                                                      NULL, NULL ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_read_params( NULL,
+                                                  (const unsigned char**) &buf,
+                                                  buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_read_params( &ctx, &buf_null,
+                                                      buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_read_params( &ctx, NULL, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_read_params( &ctx,
+                                                  (const unsigned char**) &buf,
+                                                  NULL ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_get_params( NULL, &kp,
+                                                     MBEDTLS_ECDH_OURS ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_get_params( &ctx, NULL,
+                                                     MBEDTLS_ECDH_OURS ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_get_params( &ctx, &kp,
+                                                     invalid_side ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_make_public( NULL, &olen,
+                                                      buf, buflen,
+                                                      rnd_std_rand,
+                                                      NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_make_public( &ctx, NULL,
+                                                      buf, buflen,
+                                                      rnd_std_rand,
+                                                      NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_make_public( &ctx, &olen,
+                                                      NULL, buflen,
+                                                      rnd_std_rand,
+                                                      NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_make_public( &ctx, &olen,
+                                                      buf, buflen,
+                                                      NULL,
+                                                      NULL ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_read_public( NULL, buf, buflen ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_read_public( &ctx, NULL, buflen ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_calc_secret( NULL, &olen, buf, buflen,
+                                                      rnd_std_rand,
+                                                      NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_calc_secret( &ctx, NULL, buf, buflen,
+                                                      rnd_std_rand,
+                                                      NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecdh_calc_secret( &ctx, &olen, NULL, buflen,
+                                                      rnd_std_rand,
+                                                      NULL ) );
+
+exit:
+    return;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void ecdh_primitive_random( int id )
 {
     mbedtls_ecp_group grp;