diff --git a/CMakeLists.txt b/CMakeLists.txt index 28e8ec27..e2c498a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -169,6 +169,7 @@ check_function_exists(getaddrinfo HAVE_GETADDRINFO) check_function_exists(strnlen HAVE_STRNLEN) check_function_exists(strrchr HAVE_STRRCHR) check_function_exists(getrandom HAVE_GETRANDOM) +check_function_exists(random HAVE_RANDOM) check_function_exists(if_nametoindex HAVE_IF_NAMETOINDEX) # check for symbols diff --git a/cmake_coap_config.h.in b/cmake_coap_config.h.in index c2f30c00..3c5b2a4b 100644 --- a/cmake_coap_config.h.in +++ b/cmake_coap_config.h.in @@ -125,6 +125,12 @@ /* Define to 1 if you have the `strrchr' function. */ #cmakedefine HAVE_STRRCHR @HAVE_STRRCHR@ +/* Define to 1 if you have the `getrandom' function. */ +#cmakedefine HAVE_GETRANDOM @HAVE_GETRANDOM@ + +/* Define to 1 if you have the `randon' function. */ +#cmakedefine HAVE_RANDOM @HAVE_RANDOM@ + /* Define to 1 if the system has the type `struct cmsghdr'. */ #cmakedefine HAVE_STRUCT_CMSGHDR @HAVE_STRUCT_CMSGHDR@ diff --git a/configure.ac b/configure.ac index 4cc490d0..9a0d1cd5 100644 --- a/configure.ac +++ b/configure.ac @@ -891,7 +891,7 @@ AC_TYPE_SSIZE_T # Checks for library functions. AC_CHECK_FUNCS([memset select socket strcasecmp strrchr getaddrinfo \ - strnlen malloc pthread_mutex_lock getrandom if_nametoindex]) + strnlen malloc pthread_mutex_lock getrandom random if_nametoindex]) # Check if -lsocket -lnsl is required (specifically Solaris) AC_SEARCH_LIBS([socket], [socket]) diff --git a/src/coap_prng.c b/src/coap_prng.c index 3e36c4d4..f386e93f 100644 --- a/src/coap_prng.c +++ b/src/coap_prng.c @@ -36,18 +36,19 @@ errno_t __cdecl rand_s( _Out_ unsigned int* _RandomValue ); */ COAP_STATIC_INLINE int coap_prng_impl( unsigned char *buf, size_t len ) { - while ( len != 0 ) { - uint32_t r = 0; - size_t i; - if ( rand_s( &r ) != 0 ) - return 0; - for ( i = 0; i < len && i < 4; i++ ) { - *buf++ = (uint8_t)r; - r >>= 8; - } - len -= i; - } - return 1; + while ( len != 0 ) { + uint32_t r = 0; + size_t i; + + if ( rand_s( &r ) != 0 ) + return 0; + for ( i = 0; i < len && i < 4; i++ ) { + *buf++ = (uint8_t)r; + r >>= 8; + } + len -= i; + } + return 1; } #endif /* _WIN32 */ @@ -61,20 +62,46 @@ coap_prng_default(void *buf, size_t len) { #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) /* mbedtls_hardware_poll() returns 0 on success */ return (mbedtls_hardware_poll(NULL, buf, len, NULL) ? 0 : 1); -#else /* !MBEDTLS_ENTROPY_HARDWARE_ALT */ -#ifdef HAVE_GETRANDOM + +#elif defined(HAVE_GETRANDOM) return (getrandom(buf, len, 0) > 0) ? 1 : 0; -#else /* !HAVE_GETRANDOM */ -#if defined(_WIN32) + +#elif defined(HAVE_RANDOM) +#define RAND_BYTES (RAND_MAX >= 0xffffff ? 3 : (RAND_MAX >= 0xffff ? 2 : 1)) + unsigned char *dst = (unsigned char *)buf; + + if (len) { + uint8_t byte_counter = RAND_BYTES; + uint32_t r_v = random(); + + while (1) { + *dst++ = r_v & 0xFF; + if (!--len) { + break; + } + if (--byte_counter) { + r_v >>= 8; + } else { + r_v = random(); + byte_counter = RAND_BYTES; + } + } + } + return 1; + +#elif defined(_WIN32) return coap_prng_impl(buf,len); -#else /* !_WIN32 */ + +#else /* !MBEDTLS_ENTROPY_HARDWARE_ALT && !HAVE_GETRANDOM && + !HAVE_RANDOM && !_WIN32 */ + #error "CVE-2021-34430: using rand() for crypto randoms is not secure!" + #error "Please update you C-library and rerun the auto-configuration." unsigned char *dst = (unsigned char *)buf; while (len--) *dst++ = rand() & 0xFF; return 1; -#endif /* !_WIN32 */ -#endif /* !HAVE_GETRANDOM */ -#endif /* !MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* !MBEDTLS_ENTROPY_HARDWARE_ALT && !HAVE_GETRANDOM && + !HAVE_RANDOM && !_WIN32 */ } static coap_rand_func_t rand_func = coap_prng_default; @@ -93,10 +120,11 @@ coap_set_prng(coap_rand_func_t rng) { void coap_prng_init(unsigned int seed) { #ifdef HAVE_GETRANDOM - /* No seed to seed the random source if getrandom() is used, - * see dtls_prng(). */ + /* No seed to seed the random source if getrandom() is used */ (void)seed; -#else /* !HAVE_GETRANDOM */ +#elif defined(HAVE_RANDOM) + srandom(seed); +#else /* !HAVE_GETRANDOM && !HAVE_RANDOM */ srand(seed); #endif /* !HAVE_GETRANDOM */ }