CTR_DRBG: add mbedtls_ctr_drbg_update_ret
Deprecate mbedtls_ctr_drbg_update (which returns void) in favor of a
new function mbedtls_ctr_drbg_update_ret which reports error. The old
function is not officially marked as deprecated in this branch because
this is a stable maintenance branch.
diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h
index e554a0a..2b4dc73 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -227,14 +227,37 @@
*
* \param ctx The CTR_DRBG context.
* \param additional The data to update the state with.
- * \param add_len Length of \p additional data.
+ * \param add_len Length of \p additional in bytes. This must be at
+ * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
*
- * \note If \p add_len is greater than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT,
- * only the first #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
- * The remaining Bytes are silently discarded.
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if
+ * \p add_len is more than
+ * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
+ * \return An error from the underlying AES cipher on failure.
+ */
+int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t add_len );
+
+/**
+ * \brief This function updates the state of the CTR_DRBG context.
+ *
+ * \warning This function cannot report errors. You should use
+ * mbedtls_ctr_drbg_update_ret() instead.
+ *
+ * \note If \p add_len is greater than
+ * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first
+ * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
+ * The remaining Bytes are silently discarded.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param additional The data to update the state with.
+ * \param add_len Length of \p additional data.
*/
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
- const unsigned char *additional, size_t add_len );
+ const unsigned char *additional,
+ size_t add_len );
/**
* \brief This function updates a CTR_DRBG instance with additional
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index fc3188e..d7a9484 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -303,22 +303,36 @@
return( ret );
}
-void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
- const unsigned char *additional, size_t add_len )
+int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t add_len )
{
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
+ int ret;
- if( add_len > 0 )
- {
- /* MAX_INPUT would be more logical here, but we have to match
- * block_cipher_df()'s limits since we can't propagate errors */
- if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
- add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
+ if( add_len == 0 )
+ return( 0 );
- block_cipher_df( add_input, additional, add_len );
- ctr_drbg_update_internal( ctx, add_input );
- mbedtls_zeroize( add_input, sizeof( add_input ) );
- }
+ if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
+ goto exit;
+ if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedtls_zeroize( add_input, sizeof( add_input ) );
+ return( ret );
+}
+
+/* Deprecated function, kept for backward compatibility. */
+void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t add_len )
+{
+ /* MAX_INPUT would be more logical here, but we have to match
+ * block_cipher_df()'s limits since we can't propagate errors */
+ if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+ add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
+ (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
}
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
@@ -514,7 +528,7 @@
if( fread( buf, 1, n, f ) != n )
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
else
- mbedtls_ctr_drbg_update( ctx, buf, n );
+ ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
fclose( f );
diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function
index d8ffebe..f17bd3b 100644
--- a/tests/suites/test_suite_ctr_drbg.function
+++ b/tests/suites/test_suite_ctr_drbg.function
@@ -177,9 +177,11 @@
}
TEST_ASSERT( last_idx == test_offset_idx );
- /* Call update with too much data (sizeof entropy > MAX(_SEED)_INPUT)
- * (just make sure it doesn't cause memory corruption) */
- mbedtls_ctr_drbg_update( &ctx, entropy, sizeof( entropy ) );
+ /* Call update with too much data (sizeof entropy > MAX(_SEED)_INPUT).
+ * Make sure it's detected as an error and doesn't cause memory
+ * corruption. */
+ TEST_ASSERT( mbedtls_ctr_drbg_update_ret(
+ &ctx, entropy, sizeof( entropy ) ) != 0 );
/* Now enable PR, so the next few calls should all reseed */
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );