Merge remote-tracking branch 'public/pr/2282' into development
diff --git a/include/mbedtls/blowfish.h b/include/mbedtls/blowfish.h
index 922d8f8..f01573d 100644
--- a/include/mbedtls/blowfish.h
+++ b/include/mbedtls/blowfish.h
@@ -76,40 +76,53 @@
 #endif /* MBEDTLS_BLOWFISH_ALT */
 
 /**
- * \brief          Initialize Blowfish context
+ * \brief          Initialize a Blowfish context.
  *
- * \param ctx      Blowfish context to be initialized
+ * \param ctx      The Blowfish context to be initialized.
+ *                 This must not be \c NULL.
  */
 void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx );
 
 /**
- * \brief          Clear Blowfish context
+ * \brief          Clear a Blowfish context.
  *
- * \param ctx      Blowfish context to be cleared
+ * \param ctx      The Blowfish context to be cleared.
+ *                 This may be \c NULL, in which case this function
+ *                 returns immediately. If it is not \c NULL, it must
+ *                 point to an initialized Blowfish context.
  */
 void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx );
 
 /**
- * \brief          Blowfish key schedule
+ * \brief          Perform a Blowfish key schedule operation.
  *
- * \param ctx      Blowfish context to be initialized
- * \param key      encryption key
- * \param keybits  must be between 32 and 448 bits
+ * \param ctx      The Blowfish context to perform the key schedule on.
+ * \param key      The encryption key. This must be a readable buffer of
+ *                 length \p keybits Bits.
+ * \param keybits  The length of \p key in Bits. This must be between
+ *                 \c 32 and \c 448 and a multiple of \c 8.
  *
- * \return         0 if successful, or MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA
+ * \return         \c 0 if successful.
+ * \return         A negative error code on failure.
  */
 int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key,
                      unsigned int keybits );
 
 /**
- * \brief          Blowfish-ECB block encryption/decryption
+ * \brief          Perform a Blowfish-ECB block encryption/decryption operation.
  *
- * \param ctx      Blowfish context
- * \param mode     MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT
- * \param input    8-byte input block
- * \param output   8-byte output block
+ * \param ctx      The Blowfish context to use. This must be initialized
+ *                 and bound to a key.
+ * \param mode     The mode of operation. Possible values are
+ *                 #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
+ *                 #MBEDTLS_BLOWFISH_DECRYPT for decryption.
+ * \param input    The input block. This must be a readable buffer
+ *                 of size \c 8 Bytes.
+ * \param output   The output block. This must be a writable buffer
+ *                 of size \c 8 Bytes.
  *
- * \return         0 if successful
+ * \return         \c 0 if successful.
+ * \return         A negative error code on failure.
  */
 int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx,
                         int mode,
@@ -118,9 +131,7 @@
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 /**
- * \brief          Blowfish-CBC buffer encryption/decryption
- *                 Length should be a multiple of the block
- *                 size (8 bytes)
+ * \brief          Perform a Blowfish-CBC buffer encryption/decryption operation.
  *
  * \note           Upon exit, the content of the IV is updated so that you can
  *                 call the function same function again on the following
@@ -130,15 +141,22 @@
  *                 IV, you should either save it manually or use the cipher
  *                 module instead.
  *
- * \param ctx      Blowfish context
- * \param mode     MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT
- * \param length   length of the input data
- * \param iv       initialization vector (updated after use)
- * \param input    buffer holding the input data
- * \param output   buffer holding the output data
+ * \param ctx      The Blowfish context to use. This must be initialized
+ *                 and bound to a key.
+ * \param mode     The mode of operation. Possible values are
+ *                 #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
+ *                 #MBEDTLS_BLOWFISH_DECRYPT for decryption.
+ * \param length   The length of the input data in Bytes. This must be
+ *                 multiple of \c 8.
+ * \param iv       The initialization vector. This must be a read/write buffer
+ *                 of length \c 8 Bytes. It is updated by this function.
+ * \param input    The input data. This must be a readable buffer of length
+ *                 \p length Bytes.
+ * \param output   The output data. This must be a writable buffer of length
+ *                 \p length Bytes.
  *
- * \return         0 if successful, or
- *                 MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH
+ * \return         \c 0 if successful.
+ * \return         A negative error code on failure.
  */
 int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx,
                         int mode,
@@ -150,7 +168,7 @@
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
 /**
- * \brief          Blowfish CFB buffer encryption/decryption.
+ * \brief          Perform a Blowfish CFB buffer encryption/decryption operation.
  *
  * \note           Upon exit, the content of the IV is updated so that you can
  *                 call the function same function again on the following
@@ -160,15 +178,25 @@
  *                 IV, you should either save it manually or use the cipher
  *                 module instead.
  *
- * \param ctx      Blowfish context
- * \param mode     MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT
- * \param length   length of the input data
- * \param iv_off   offset in IV (updated after use)
- * \param iv       initialization vector (updated after use)
- * \param input    buffer holding the input data
- * \param output   buffer holding the output data
+ * \param ctx      The Blowfish context to use. This must be initialized
+ *                 and bound to a key.
+ * \param mode     The mode of operation. Possible values are
+ *                 #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
+ *                 #MBEDTLS_BLOWFISH_DECRYPT for decryption.
+ * \param length   The length of the input data in Bytes.
+ * \param iv_off   The offset in the initialiation vector.
+ *                 The value pointed to must be smaller than \c 8 Bytes.
+ *                 It is updated by this function to support the aforementioned
+ *                 streaming usage.
+ * \param iv       The initialization vector. This must be a read/write buffer
+ *                 of size \c 8 Bytes. It is updated after use.
+ * \param input    The input data. This must be a readable buffer of length
+ *                 \p length Bytes.
+ * \param output   The output data. This must be a writable buffer of length
+ *                 \p length Bytes.
  *
- * \return         0 if successful
+ * \return         \c 0 if successful.
+ * \return         A negative error code on failure.
  */
 int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
                           int mode,
@@ -181,7 +209,7 @@
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 /**
- * \brief               Blowfish-CTR buffer encryption/decryption
+ * \brief      Perform a Blowfish-CTR buffer encryption/decryption operation.
  *
  * \warning    You must never reuse a nonce value with the same key. Doing so
  *             would void the encryption for the two messages encrypted with
@@ -224,18 +252,24 @@
  *             content must not be written to insecure storage and should be
  *             securely discarded as soon as it's no longer needed.
  *
- * \param ctx           Blowfish context
- * \param length        The length of the data
+ * \param ctx           The Blowfish context to use. This must be initialized
+ *                      and bound to a key.
+ * \param length        The length of the input data in Bytes.
  * \param nc_off        The offset in the current stream_block (for resuming
- *                      within current cipher stream). The offset pointer to
- *                      should be 0 at the start of a stream.
- * \param nonce_counter The 64-bit nonce and counter.
- * \param stream_block  The saved stream-block for resuming. Is overwritten
- *                      by the function.
- * \param input         The input data stream
- * \param output        The output data stream
+ *                      within current cipher stream). The offset pointer
+ *                      should be \c 0 at the start of a stream and must be
+ *                      smaller than \c 8. It is updated by this function.
+ * \param nonce_counter The 64-bit nonce and counter. This must point to a
+ *                      read/write buffer of length \c 8 Bytes.
+ * \param stream_block  The saved stream-block for resuming. This must point to
+ *                      a read/write buffer of length \c 8 Bytes.
+ * \param input         The input data. This must be a readable buffer of
+ *                      length \p length Bytes.
+ * \param output        The output data. This must be a writable buffer of
+ *                      length \p length Bytes.
  *
- * \return         0 if successful
+ * \return              \c 0 if successful.
+ * \return              A negative error code on failure.
  */
 int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx,
                         size_t length,
diff --git a/library/blowfish.c b/library/blowfish.c
index b3448c2..cbf9238 100644
--- a/library/blowfish.c
+++ b/library/blowfish.c
@@ -40,6 +40,12 @@
 
 #if !defined(MBEDTLS_BLOWFISH_ALT)
 
+/* Parameter validation macros */
+#define BLOWFISH_VALIDATE_RET( cond )                                       \
+    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA )
+#define BLOWFISH_VALIDATE( cond )                                           \
+    MBEDTLS_INTERNAL_VALIDATE( cond )
+
 /*
  * 32-bit integer manipulation macros (big endian)
  */
@@ -153,6 +159,7 @@
 
 void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx )
 {
+    BLOWFISH_VALIDATE( ctx != NULL );
     memset( ctx, 0, sizeof( mbedtls_blowfish_context ) );
 }
 
@@ -167,14 +174,18 @@
 /*
  * Blowfish key schedule
  */
-int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key,
-                     unsigned int keybits )
+int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx,
+                             const unsigned char *key,
+                             unsigned int keybits )
 {
     unsigned int i, j, k;
     uint32_t data, datal, datar;
+    BLOWFISH_VALIDATE_RET( ctx != NULL );
+    BLOWFISH_VALIDATE_RET( key != NULL );
 
-    if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS ||
-        ( keybits % 8 ) )
+    if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS    ||
+        keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS    ||
+        keybits % 8 != 0 )
     {
         return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
     }
@@ -231,6 +242,11 @@
                     unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] )
 {
     uint32_t X0, X1;
+    BLOWFISH_VALIDATE_RET( ctx != NULL );
+    BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
+                           mode == MBEDTLS_BLOWFISH_DECRYPT );
+    BLOWFISH_VALIDATE_RET( input  != NULL );
+    BLOWFISH_VALIDATE_RET( output != NULL );
 
     GET_UINT32_BE( X0, input,  0 );
     GET_UINT32_BE( X1, input,  4 );
@@ -263,6 +279,12 @@
 {
     int i;
     unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE];
+    BLOWFISH_VALIDATE_RET( ctx != NULL );
+    BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
+                           mode == MBEDTLS_BLOWFISH_DECRYPT );
+    BLOWFISH_VALIDATE_RET( iv != NULL );
+    BLOWFISH_VALIDATE_RET( length == 0 || input  != NULL );
+    BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
 
     if( length % MBEDTLS_BLOWFISH_BLOCKSIZE )
         return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH );
@@ -317,7 +339,19 @@
                        unsigned char *output )
 {
     int c;
-    size_t n = *iv_off;
+    size_t n;
+
+    BLOWFISH_VALIDATE_RET( ctx != NULL );
+    BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
+                           mode == MBEDTLS_BLOWFISH_DECRYPT );
+    BLOWFISH_VALIDATE_RET( iv     != NULL );
+    BLOWFISH_VALIDATE_RET( iv_off != NULL );
+    BLOWFISH_VALIDATE_RET( length == 0 || input  != NULL );
+    BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
+
+    n = *iv_off;
+    if( n >= 8 )
+        return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
 
     if( mode == MBEDTLS_BLOWFISH_DECRYPT )
     {
@@ -365,7 +399,17 @@
                        unsigned char *output )
 {
     int c, i;
-    size_t n = *nc_off;
+    size_t n;
+    BLOWFISH_VALIDATE_RET( ctx != NULL );
+    BLOWFISH_VALIDATE_RET( nonce_counter != NULL );
+    BLOWFISH_VALIDATE_RET( stream_block  != NULL );
+    BLOWFISH_VALIDATE_RET( nc_off != NULL );
+    BLOWFISH_VALIDATE_RET( length == 0 || input  != NULL );
+    BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
+
+    n = *nc_off;
+    if( n >= 8 )
+        return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
 
     while( length-- )
     {
diff --git a/tests/suites/test_suite_blowfish.data b/tests/suites/test_suite_blowfish.data
index d4e8791..fd172d3 100644
--- a/tests/suites/test_suite_blowfish.data
+++ b/tests/suites/test_suite_blowfish.data
@@ -1,3 +1,9 @@
+BLOWFISH - Valid parameters
+blowfish_valid_param:
+
+BLOWFISH - Invalid parameters
+blowfish_invalid_param:
+
 BLOWFISH-ECB Encrypt SSLeay reference #1
 blowfish_encrypt_ecb:"0000000000000000":"0000000000000000":"4ef997456198dd78":0
 
diff --git a/tests/suites/test_suite_blowfish.function b/tests/suites/test_suite_blowfish.function
index 189e23d..7a93cd1 100644
--- a/tests/suites/test_suite_blowfish.function
+++ b/tests/suites/test_suite_blowfish.function
@@ -8,6 +8,164 @@
  */
 
 /* BEGIN_CASE */
+void blowfish_valid_param( )
+{
+    TEST_VALID_PARAM( mbedtls_blowfish_free( NULL ) );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_CHECK_PARAMS:!MBEDTLS_PARAM_FAILED_ALT */
+void blowfish_invalid_param( )
+{
+    mbedtls_blowfish_context ctx;
+    unsigned char buf[16] = { 0 };
+    size_t const valid_keylength = sizeof( buf ) * 8;
+    size_t valid_mode = MBEDTLS_BLOWFISH_ENCRYPT;
+    size_t invalid_mode = 42;
+    size_t off;
+    ((void) off);
+
+    TEST_INVALID_PARAM( mbedtls_blowfish_init( NULL ) );
+    TEST_VALID_PARAM( mbedtls_blowfish_free( NULL ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_setkey( NULL,
+                                                     buf,
+                                                     valid_keylength ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_setkey( &ctx,
+                                                     NULL,
+                                                     valid_keylength ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_ecb( NULL,
+                                                     valid_mode,
+                                                     buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_ecb( &ctx,
+                                                        invalid_mode,
+                                                        buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_ecb( &ctx,
+                                                        valid_mode,
+                                                        NULL, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_ecb( &ctx,
+                                                        valid_mode,
+                                                        buf, NULL ) );
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cbc( NULL,
+                                                        valid_mode,
+                                                        sizeof( buf ),
+                                                        buf, buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cbc( &ctx,
+                                                        invalid_mode,
+                                                        sizeof( buf ),
+                                                        buf, buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cbc( &ctx,
+                                                        valid_mode,
+                                                        sizeof( buf ),
+                                                        NULL, buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cbc( &ctx,
+                                                        valid_mode,
+                                                        sizeof( buf ),
+                                                        buf, NULL, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cbc( &ctx,
+                                                        valid_mode,
+                                                        sizeof( buf ),
+                                                        buf, buf, NULL ) );
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cfb64( NULL,
+                                                          valid_mode,
+                                                          sizeof( buf ),
+                                                          &off, buf,
+                                                          buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cfb64( &ctx,
+                                                          invalid_mode,
+                                                          sizeof( buf ),
+                                                          &off, buf,
+                                                          buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cfb64( &ctx,
+                                                          valid_mode,
+                                                          sizeof( buf ),
+                                                          NULL, buf,
+                                                          buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cfb64( &ctx,
+                                                          valid_mode,
+                                                          sizeof( buf ),
+                                                          &off, NULL,
+                                                          buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cfb64( &ctx,
+                                                          valid_mode,
+                                                          sizeof( buf ),
+                                                          &off, buf,
+                                                          NULL, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_cfb64( &ctx,
+                                                          valid_mode,
+                                                          sizeof( buf ),
+                                                          &off, buf,
+                                                          buf, NULL ) );
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_ctr( NULL,
+                                                        sizeof( buf ),
+                                                        &off,
+                                                        buf, buf,
+                                                        buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_ctr( &ctx,
+                                                        sizeof( buf ),
+                                                        NULL,
+                                                        buf, buf,
+                                                        buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_ctr( &ctx,
+                                                        sizeof( buf ),
+                                                        &off,
+                                                        NULL, buf,
+                                                        buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_ctr( &ctx,
+                                                        sizeof( buf ),
+                                                        &off,
+                                                        buf, NULL,
+                                                        buf, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_ctr( &ctx,
+                                                        sizeof( buf ),
+                                                        &off,
+                                                        buf, buf,
+                                                        NULL, buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA,
+                            mbedtls_blowfish_crypt_ctr( &ctx,
+                                                        sizeof( buf ),
+                                                        &off,
+                                                        buf, buf,
+                                                        buf, NULL ) );
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+exit:
+    return;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void blowfish_encrypt_ecb( data_t * key_str, data_t * src_str,
                            data_t * hex_dst_string, int setkey_result )
 {