diff --git a/ChangeLog.d/dev-random.txt b/ChangeLog.d/dev-random.txt new file mode 100644 index 0000000000..eff1352354 --- /dev/null +++ b/ChangeLog.d/dev-random.txt @@ -0,0 +1,11 @@ +Features + * The device for reading entropy on platforms without a dedicated system + call can now be configured with MBEDTLS_PLATFORM_DEV_RANDOM or + mbedtls_platform_dev_random. + +Security + * The default device for reading entropy on platforms without a dedicated + system call is now /dev/random instead of /dev/urandom. This is safer + on Linux in case the application runs early after the kernel boots, + but may block needlessly on Linux <= 5.6. Reported by supers1ngular + (BayLibre). diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 75eff2d89a..8fa445a132 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -1204,6 +1204,20 @@ * This is useful if your platform does not support * standards like the /dev/urandom or Windows CryptoAPI. * + * If you enable this macro, you will probably need to enable + * #MBEDTLS_ENTROPY_HARDWARE_ALT and provide a function + * mbedtls_hardware_poll(). + * + * \note The default platform entropy function supports the following + * sources: + * - getrandom() on Linux (if syscall() is available at compile time); + * - getrandom() on FreeBSD and DragonFlyBSD (if available at compile + * time); + * - `sysctl(KERN_ARND)` on FreeBSD and NetBSD; + * - #MBEDTLS_PLATFORM_DEV_RANDOM on Unix-like platforms + * (unless one of the above is used); + * - BCryptGenRandom() on Windows. + * * Uncomment this macro to disable the built-in platform entropy functions. */ //#define MBEDTLS_NO_PLATFORM_ENTROPY @@ -4140,6 +4154,37 @@ //#define MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO int64_t //#define MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO int64_t /**< Default milliseconds time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled. It must be signed, and at least 64 bits. If it is changed from the default, MBEDTLS_PRINTF_MS_TIME must be updated to match.*/ //#define MBEDTLS_PRINTF_MS_TIME PRId64 /**< Default fmt for printf. That's avoid compiler warning if mbedtls_ms_time_t is redefined */ +/** \def MBEDTLS_PLATFORM_DEV_RANDOM + * + * Path to a special file that returns cryptographic-quality random bytes + * when read. This is used by the default platform entropy source on + * non-Windows platforms unless a dedicated system call is available + * (see #MBEDTLS_NO_PLATFORM_ENTROPY). + * + * The default value is `/dev/random`, which is suitable on most platforms + * other than Linux. On Linux, either `/dev/random` or `/dev/urandom` + * may be the right choice, depending on the circumstances: + * + * - If possible, the library will use the getrandom() system call, + * which is preferable, and #MBEDTLS_PLATFORM_DEV_RANDOM is not used. + * - If there is a dedicated hardware entropy source (e.g. RDRAND on x86 + * processors), then both `/dev/random` and `/dev/urandom` are fine. + * - `/dev/random` is always secure. However, with kernels older than 5.6, + * `/dev/random` often blocks unnecessarily if there is no dedicated + * hardware entropy source. + * - `/dev/urandom` never blocks. However, it may return predictable data + * if it is used early after the kernel boots, especially on embedded + * devices without an interactive user. + * + * Thus you should change the value to `/dev/urandom` if your application + * definitely won't be used on a device running Linux without a dedicated + * entropy source early during or after boot. + * + * This is the default value of ::mbedtls_platform_dev_random, which + * can be changed at run time. + */ +//#define MBEDTLS_PLATFORM_DEV_RANDOM "/dev/random" + /** \def MBEDTLS_CHECK_RETURN * * This macro is used at the beginning of the declaration of a function diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h index de3d71d9dc..f1ec9975e8 100644 --- a/include/mbedtls/platform.h +++ b/include/mbedtls/platform.h @@ -385,6 +385,37 @@ int mbedtls_platform_set_exit(void (*exit_func)(int status)); #define MBEDTLS_EXIT_FAILURE 1 #endif +#if defined(MBEDTLS_ENTROPY_C) && \ + !defined(MBEDTLS_NO_PLATFORM_ENTROPY) && \ + !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) +/* Platforms where MBEDTLS_PLATFORM_DEV_RANDOM is used + * unless a dedicated system call is available both at + * compile time and at run time. */ +#define MBEDTLS_PLATFORM_HAVE_DEV_RANDOM +#endif + +#if !defined(MBEDTLS_PLATFORM_DEV_RANDOM) +#define MBEDTLS_PLATFORM_DEV_RANDOM "/dev/random" +#endif + +/* Arrange for mbedtls_platform_dev_random to always be visible to + * Doxygen, because it's linked from the documentation of + * MBEDTLS_PLATFORM_DEV_RANDOM and that documentation can be visible + * even in configurations where it isn't used. */ +#if defined(MBEDTLS_PLATFORM_HAVE_DEV_RANDOM) || defined(__DOXYGEN__) +/** + * Path to a special file that returns cryptographic-quality random bytes + * when read. + * + * This variable is only declared on platforms where it is used. + * It is available when the macro `MBEDTLS_PLATFORM_HAVE_DEV_RANDOM` is defined. + * + * The default value is #MBEDTLS_PLATFORM_DEV_RANDOM. + * See the documentation of this option for guidance. + */ +extern const char *mbedtls_platform_dev_random; +#endif + /* * The function pointers for reading from and writing a seed file to * Non-Volatile storage (NV) in a platform-independent way diff --git a/library/entropy_poll.c b/library/entropy_poll.c index 611768cd85..1c8a29d6e2 100644 --- a/library/entropy_poll.c +++ b/library/entropy_poll.c @@ -147,6 +147,8 @@ static int sysctl_arnd_wrapper(unsigned char *buf, size_t buflen) #include +const char *mbedtls_platform_dev_random = MBEDTLS_PLATFORM_DEV_RANDOM; + int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen) { @@ -180,7 +182,7 @@ int mbedtls_platform_entropy_poll(void *data, *olen = 0; - file = fopen("/dev/urandom", "rb"); + file = fopen(mbedtls_platform_dev_random, "rb"); if (file == NULL) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; }