Add setbuf platform function

Add a platform function mbedtls_setbuf(), defaulting to setbuf().

The intent is to allow disabling stdio buffering when reading or writing
files with sensitive data, because this exposes the sensitive data to a
subsequent memory disclosure vulnerability.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index a598434..bad442e 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -91,6 +91,9 @@
 #if !defined(MBEDTLS_PLATFORM_STD_FREE)
 #define MBEDTLS_PLATFORM_STD_FREE       free /**< The default \c free function to use. */
 #endif
+#if !defined(MBEDTLS_PLATFORM_STD_SETBUF)
+#define MBEDTLS_PLATFORM_STD_SETBUF   setbuf /**< The default \c setbuf function to use. */
+#endif
 #if !defined(MBEDTLS_PLATFORM_STD_EXIT)
 #define MBEDTLS_PLATFORM_STD_EXIT      exit /**< The default \c exit function to use. */
 #endif
@@ -277,6 +280,58 @@
 #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
 
 /*
+ * The function pointers for setbuf
+ */
+#if defined(MBEDTLS_PLATFORM_SETBUF_ALT)
+#include <stdio.h>
+/**
+ * \brief                  Function pointer to call for `setbuf()` functionality
+ *                         (changing the internal buffering on stdio calls).
+ *
+ * \note                   The library calls this function to disable
+ *                         buffering when reading or writing sensitive data,
+ *                         to avoid having extra copies of sensitive data
+ *                         remaining in stdio buffers after the file is
+ *                         closed. If this is not a concern, for example if
+ *                         your platform's stdio doesn't have any buffering,
+ *                         you can set mbedtls_setbuf to a function that
+ *                         does nothing.
+ *
+ * \param   setbuf_func    The \c setbuf function implementation.
+ *                         It is always called with `buf` equal to `NULL`.
+ *
+ * \return                 \c 0 on success, negative on error.
+ */
+extern void (*mbedtls_setbuf)( FILE *stream, char *buf );
+
+/**
+ * \brief                  Dynamically configure the function that is called
+ *                         when the mbedtls_setbuf() function is called by the
+ *                         library.
+ *
+ * \param   setbuf_func   The \c setbuf function implementation
+ *
+ * \return                 \c 0
+ */
+int mbedtls_platform_set_setbuf( void (*setbuf_func)(
+                                     FILE *stream, char *buf ) );
+#elif defined(MBEDTLS_PLATFORM_SETBUF_MACRO)
+/**
+ * \brief                  Macro defining the function for the library to
+ *                         call for `setbuf` functionality (changing the
+ *                         internal buffering on stdio calls).
+ *
+ * \note                   See extra comments on the mbedtls_setbuf() function
+ *                         pointer above.
+ *
+ * \return                 \c 0 on success, negative on error.
+ */
+#define mbedtls_setbuf    MBEDTLS_PLATFORM_SETBUF_MACRO
+#else
+#define mbedtls_setbuf    setbuf
+#endif /* MBEDTLS_PLATFORM_SETBUF_ALT / MBEDTLS_PLATFORM_SETBUF_MACRO */
+
+/*
  * The function pointers for exit
  */
 #if defined(MBEDTLS_PLATFORM_EXIT_ALT)