Merge remote-tracking branch 'public/pr/2292' into development
diff --git a/include/mbedtls/ecjpake.h b/include/mbedtls/ecjpake.h
index 59d12f0..b967af8 100644
--- a/include/mbedtls/ecjpake.h
+++ b/include/mbedtls/ecjpake.h
@@ -92,28 +92,33 @@
 #endif /* MBEDTLS_ECJPAKE_ALT */
 
 /**
- * \brief           Initialize a context
- *                  (just makes it ready for setup() or free()).
+ * \brief           Initialize an ECJPAKE context.
  *
- * \param ctx       context to initialize
+ * \param ctx       The ECJPAKE context to initialize.
+ *                  This must not be \c NULL.
  */
 void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx );
 
 /**
- * \brief           Set up a context for use
+ * \brief           Set up an ECJPAKE context for use.
  *
  * \note            Currently the only values for hash/curve allowed by the
- *                  standard are MBEDTLS_MD_SHA256/MBEDTLS_ECP_DP_SECP256R1.
+ *                  standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1.
  *
- * \param ctx       context to set up
- * \param role      Our role: client or server
- * \param hash      hash function to use (MBEDTLS_MD_XXX)
- * \param curve     elliptic curve identifier (MBEDTLS_ECP_DP_XXX)
- * \param secret    pre-shared secret (passphrase)
- * \param len       length of the shared secret
+ * \param ctx       The ECJPAKE context to set up. This must be initialized.
+ * \param role      The role of the caller. This must be either
+ *                  #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER.
+ * \param hash      The identifier of the hash function to use,
+ *                  for example #MBEDTLS_MD_SHA256.
+ * \param curve     The identifier of the elliptic curve to use,
+ *                  for example #MBEDTLS_ECP_DP_SECP256R1.
+ * \param secret    The pre-shared secret (passphrase). This must be
+ *                  a readable buffer of length \p len Bytes. It need
+ *                  only be valid for the duration of this call.
+ * \param len       The length of the pre-shared secret \p secret.
  *
- * \return          0 if successfull,
- *                  a negative error code otherwise
+ * \return          \c 0 if successful.
+ * \return          A negative error code on failure.
  */
 int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
                            mbedtls_ecjpake_role role,
@@ -123,29 +128,34 @@
                            size_t len );
 
 /**
- * \brief           Check if a context is ready for use
+ * \brief           Check if an ECJPAKE context is ready for use.
  *
- * \param ctx       Context to check
+ * \param ctx       The ECJPAKE context to check. This must be
+ *                  initialized.
  *
- * \return          0 if the context is ready for use,
- *                  MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise
+ * \return          \c 0 if the context is ready for use.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise.
  */
 int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx );
 
 /**
  * \brief           Generate and write the first round message
  *                  (TLS: contents of the Client/ServerHello extension,
- *                  excluding extension type and length bytes)
+ *                  excluding extension type and length bytes).
  *
- * \param ctx       Context to use
- * \param buf       Buffer to write the contents to
- * \param len       Buffer size
- * \param olen      Will be updated with the number of bytes written
- * \param f_rng     RNG function
- * \param p_rng     RNG parameter
+ * \param ctx       The ECJPAKE context to use. This must be
+ *                  initialized and set up.
+ * \param buf       The buffer to write the contents to. This must be a
+ *                  writable buffer of length \p len Bytes.
+ * \param len       The length of \p buf in Bytes.
+ * \param olen      The address at which to store the total number
+ *                  of Bytes written to \p buf. This must not be \c NULL.
+ * \param f_rng     The RNG function to use. This must not be \c NULL.
+ * \param p_rng     The RNG parameter to be passed to \p f_rng. This
+ *                  may be \c NULL if \p f_rng doesn't use a context.
  *
- * \return          0 if successfull,
- *                  a negative error code otherwise
+ * \return          \c 0 if successful.
+ * \return          A negative error code on failure.
  */
 int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
                             unsigned char *buf, size_t len, size_t *olen,
@@ -155,14 +165,16 @@
 /**
  * \brief           Read and process the first round message
  *                  (TLS: contents of the Client/ServerHello extension,
- *                  excluding extension type and length bytes)
+ *                  excluding extension type and length bytes).
  *
- * \param ctx       Context to use
- * \param buf       Pointer to extension contents
- * \param len       Extension length
+ * \param ctx       The ECJPAKE context to use. This must be initialized
+ *                  and set up.
+ * \param buf       The buffer holding the first round message. This must
+ *                  be a readable buffer of length \p len Bytes.
+ * \param len       The length in Bytes of \p buf.
  *
- * \return          0 if successfull,
- *                  a negative error code otherwise
+ * \return          \c 0 if successful.
+ * \return          A negative error code on failure.
  */
 int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
                                     const unsigned char *buf,
@@ -170,17 +182,21 @@
 
 /**
  * \brief           Generate and write the second round message
- *                  (TLS: contents of the Client/ServerKeyExchange)
+ *                  (TLS: contents of the Client/ServerKeyExchange).
  *
- * \param ctx       Context to use
- * \param buf       Buffer to write the contents to
- * \param len       Buffer size
- * \param olen      Will be updated with the number of bytes written
- * \param f_rng     RNG function
- * \param p_rng     RNG parameter
+ * \param ctx       The ECJPAKE context to use. This must be initialized,
+ *                  set up, and already have performed round one.
+ * \param buf       The buffer to write the round two contents to.
+ *                  This must be a writable buffer of length \p len Bytes.
+ * \param len       The size of \p buf in Bytes.
+ * \param olen      The address at which to store the total number of Bytes
+ *                  written to \p buf. This must not be \c NULL.
+ * \param f_rng     The RNG function to use. This must not be \c NULL.
+ * \param p_rng     The RNG parameter to be passed to \p f_rng. This
+ *                  may be \c NULL if \p f_rng doesn't use a context.
  *
- * \return          0 if successfull,
- *                  a negative error code otherwise
+ * \return          \c 0 if successful.
+ * \return          A negative error code on failure.
  */
 int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
                             unsigned char *buf, size_t len, size_t *olen,
@@ -189,14 +205,16 @@
 
 /**
  * \brief           Read and process the second round message
- *                  (TLS: contents of the Client/ServerKeyExchange)
+ *                  (TLS: contents of the Client/ServerKeyExchange).
  *
- * \param ctx       Context to use
- * \param buf       Pointer to the message
- * \param len       Message length
+ * \param ctx       The ECJPAKE context to use. This must be initialized
+ *                  and set up and already have performed round one.
+ * \param buf       The buffer holding the second round message. This must
+ *                  be a readable buffer of length \p len Bytes.
+ * \param len       The length in Bytes of \p buf.
  *
- * \return          0 if successfull,
- *                  a negative error code otherwise
+ * \return          \c 0 if successful.
+ * \return          A negative error code on failure.
  */
 int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
                                     const unsigned char *buf,
@@ -204,17 +222,21 @@
 
 /**
  * \brief           Derive the shared secret
- *                  (TLS: Pre-Master Secret)
+ *                  (TLS: Pre-Master Secret).
  *
- * \param ctx       Context to use
- * \param buf       Buffer to write the contents to
- * \param len       Buffer size
- * \param olen      Will be updated with the number of bytes written
- * \param f_rng     RNG function
- * \param p_rng     RNG parameter
+ * \param ctx       The ECJPAKE context to use. This must be initialized,
+ *                  set up and have performed both round one and two.
+ * \param buf       The buffer to write the derived secret to. This must
+ *                  be a writable buffer of length \p len Bytes.
+ * \param len       The length of \p buf in Bytes.
+ * \param olen      The address at which to store the total number of Bytes
+ *                  written to \p buf. This must not be \c NULL.
+ * \param f_rng     The RNG function to use. This must not be \c NULL.
+ * \param p_rng     The RNG parameter to be passed to \p f_rng. This
+ *                  may be \c NULL if \p f_rng doesn't use a context.
  *
- * \return          0 if successfull,
- *                  a negative error code otherwise
+ * \return          \c 0 if successful.
+ * \return          A negative error code on failure.
  */
 int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
                             unsigned char *buf, size_t len, size_t *olen,
@@ -222,14 +244,15 @@
                             void *p_rng );
 
 /**
- * \brief           Free a context's content
+ * \brief           This clears an ECJPAKE context and frees any
+ *                  embedded data structure.
  *
- * \param ctx       context to free
+ * \param ctx       The ECJPAKE 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 ECJPAKE context.
  */
 void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx );
 
-
-
 #if defined(MBEDTLS_SELF_TEST)
 
 /**
diff --git a/library/ecjpake.c b/library/ecjpake.c
index ec5a400..be941b1 100644
--- a/library/ecjpake.c
+++ b/library/ecjpake.c
@@ -33,11 +33,18 @@
 #if defined(MBEDTLS_ECJPAKE_C)
 
 #include "mbedtls/ecjpake.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
 #if !defined(MBEDTLS_ECJPAKE_ALT)
 
+/* Parameter validation macros based on platform_util.h */
+#define ECJPAKE_VALIDATE_RET( cond )    \
+    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
+#define ECJPAKE_VALIDATE( cond )        \
+    MBEDTLS_INTERNAL_VALIDATE( cond )
+
 /*
  * Convert a mbedtls_ecjpake_role to identifier string
  */
@@ -54,8 +61,7 @@
  */
 void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
 {
-    if( ctx == NULL )
-        return;
+    ECJPAKE_VALIDATE( ctx != NULL );
 
     ctx->md_info = NULL;
     mbedtls_ecp_group_init( &ctx->grp );
@@ -106,6 +112,11 @@
 {
     int ret;
 
+    ECJPAKE_VALIDATE_RET( ctx != NULL );
+    ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
+                          role == MBEDTLS_ECJPAKE_SERVER );
+    ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
+
     ctx->role = role;
 
     if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
@@ -127,6 +138,8 @@
  */
 int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
 {
+    ECJPAKE_VALIDATE_RET( ctx != NULL );
+
     if( ctx->md_info == NULL ||
         ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
         ctx->s.p == NULL )
@@ -504,6 +517,9 @@
                                     const unsigned char *buf,
                                     size_t len )
 {
+    ECJPAKE_VALIDATE_RET( ctx != NULL );
+    ECJPAKE_VALIDATE_RET( buf != NULL );
+
     return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
                                &ctx->grp.G,
                                &ctx->Xp1, &ctx->Xp2, ID_PEER,
@@ -518,6 +534,11 @@
                             int (*f_rng)(void *, unsigned char *, size_t),
                             void *p_rng )
 {
+    ECJPAKE_VALIDATE_RET( ctx   != NULL );
+    ECJPAKE_VALIDATE_RET( buf   != NULL );
+    ECJPAKE_VALIDATE_RET( olen  != NULL );
+    ECJPAKE_VALIDATE_RET( f_rng != NULL );
+
     return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
                                 &ctx->grp.G,
                                 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
@@ -560,6 +581,9 @@
     mbedtls_ecp_group grp;
     mbedtls_ecp_point G;    /* C: GB, S: GA */
 
+    ECJPAKE_VALIDATE_RET( ctx != NULL );
+    ECJPAKE_VALIDATE_RET( buf != NULL );
+
     mbedtls_ecp_group_init( &grp );
     mbedtls_ecp_point_init( &G );
 
@@ -652,6 +676,11 @@
     const unsigned char *end = buf + len;
     size_t ec_len;
 
+    ECJPAKE_VALIDATE_RET( ctx   != NULL );
+    ECJPAKE_VALIDATE_RET( buf   != NULL );
+    ECJPAKE_VALIDATE_RET( olen  != NULL );
+    ECJPAKE_VALIDATE_RET( f_rng != NULL );
+
     mbedtls_ecp_point_init( &G );
     mbedtls_ecp_point_init( &Xm );
     mbedtls_mpi_init( &xm );
@@ -727,6 +756,11 @@
     unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
     size_t x_bytes;
 
+    ECJPAKE_VALIDATE_RET( ctx   != NULL );
+    ECJPAKE_VALIDATE_RET( buf   != NULL );
+    ECJPAKE_VALIDATE_RET( olen  != NULL );
+    ECJPAKE_VALIDATE_RET( f_rng != NULL );
+
     *olen = mbedtls_md_get_size( ctx->md_info );
     if( len < *olen )
         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
diff --git a/tests/suites/test_suite_ecjpake.data b/tests/suites/test_suite_ecjpake.data
index 1a772a9..84c99c9 100644
--- a/tests/suites/test_suite_ecjpake.data
+++ b/tests/suites/test_suite_ecjpake.data
@@ -1,3 +1,6 @@
+ECJPAKE parameter validation
+ecjpake_invalid_param:
+
 ECJPAKE selftest
 ecjpake_selftest:
 
diff --git a/tests/suites/test_suite_ecjpake.function b/tests/suites/test_suite_ecjpake.function
index 9e4f7a3..d267295 100644
--- a/tests/suites/test_suite_ecjpake.function
+++ b/tests/suites/test_suite_ecjpake.function
@@ -98,6 +98,137 @@
  * END_DEPENDENCIES
  */
 
+/* BEGIN_CASE depends_on:MBEDTLS_CHECK_PARAMS:!MBEDTLS_PARAM_FAILED_ALT */
+void ecjpake_invalid_param( )
+{
+    mbedtls_ecjpake_context ctx;
+    unsigned char buf[42] = { 0 };
+    size_t olen;
+    size_t const len = sizeof( buf );
+    mbedtls_ecjpake_role valid_role = MBEDTLS_ECJPAKE_SERVER;
+    mbedtls_ecjpake_role invalid_role = (mbedtls_ecjpake_role) 42;
+    mbedtls_md_type_t valid_md = MBEDTLS_MD_SHA256;
+    mbedtls_ecp_group_id valid_group = MBEDTLS_ECP_DP_SECP256R1;
+
+    TEST_INVALID_PARAM( mbedtls_ecjpake_init( NULL ) );
+    TEST_VALID_PARAM( mbedtls_ecjpake_free( NULL ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_setup( NULL,
+                                                   valid_role,
+                                                   valid_md,
+                                                   valid_group,
+                                                   buf, len ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_setup( &ctx,
+                                                   invalid_role,
+                                                   valid_md,
+                                                   valid_group,
+                                                   buf, len ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_setup( &ctx,
+                                                   valid_role,
+                                                   valid_md,
+                                                   valid_group,
+                                                   NULL, len ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_check( NULL ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_write_round_one( NULL,
+                                                             buf, len,
+                                                             &olen,
+                                                             rnd_std_rand,
+                                                             NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_write_round_one( &ctx,
+                                                             NULL, len,
+                                                             &olen,
+                                                             rnd_std_rand,
+                                                             NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_write_round_one( &ctx,
+                                                             buf, len,
+                                                             NULL,
+                                                             rnd_std_rand,
+                                                             NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_write_round_one( &ctx,
+                                                             buf, len,
+                                                             &olen,
+                                                             NULL,
+                                                             NULL ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_write_round_two( NULL,
+                                                             buf, len,
+                                                             &olen,
+                                                             rnd_std_rand,
+                                                             NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_write_round_two( &ctx,
+                                                             NULL, len,
+                                                             &olen,
+                                                             rnd_std_rand,
+                                                             NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_write_round_two( &ctx,
+                                                             buf, len,
+                                                             NULL,
+                                                             rnd_std_rand,
+                                                             NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_write_round_two( &ctx,
+                                                             buf, len,
+                                                             &olen,
+                                                             NULL,
+                                                             NULL ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_read_round_one( NULL,
+                                                            buf, len ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_read_round_one( &ctx,
+                                                            NULL, len ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_read_round_two( NULL,
+                                                            buf, len ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_read_round_two( &ctx,
+                                                            NULL, len ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_derive_secret( NULL,
+                                                           buf, len,
+                                                           &olen,
+                                                           rnd_std_rand,
+                                                           NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_derive_secret( &ctx,
+                                                           NULL, len,
+                                                           &olen,
+                                                           rnd_std_rand,
+                                                           NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_derive_secret( &ctx,
+                                                           buf, len,
+                                                           NULL,
+                                                           rnd_std_rand,
+                                                           NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                            mbedtls_ecjpake_derive_secret( &ctx,
+                                                           buf, len,
+                                                           &olen,
+                                                           NULL,
+                                                           NULL ) );
+
+exit:
+    return;
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
 void ecjpake_selftest(  )
 {