Repository: cossacklabs/themis (language: rust)

Issue:
soter_rand(): cast size_t -> int -> size_t unnecessary and potentially lossy

In https://github.com/cossacklabs/themis/blob/master/src/soter/boringssl/soter_rand.c#L21, `soter_rand()` takes a `size_t` and casts it to `int` to pass it to `RAND_bytes(*, size_t)`; unlike OpenSSL, boringSSL's  `RAND_bytes()` takes a `size_t` length and not an `int`. If more than ~4GB are requested then the call will therefore fail to return the right amount.

Likewise, the OpenSSL counterpart may check for overflows in the (needed) cast https://github.com/cossacklabs/themis/blob/master/src/soter/openssl/soter_rand.c. 


Discussion / hints:
thank you, makes sense :)
will fix.

Fix patch:
diff --git a/src/soter/boringssl/soter_rand.c b/src/soter/boringssl/soter_rand.c
index c276121a3..a24c8e738 100644
--- a/src/soter/boringssl/soter_rand.c
+++ b/src/soter/boringssl/soter_rand.c
@@ -20,14 +20,18 @@
 
 soter_status_t soter_rand(uint8_t* buffer, size_t length)
 {
-    if ((!buffer) || (!length)) {
+    int result;
+
+    if (!buffer || !length) {
         return SOTER_INVALID_PARAMETER;
     }
 
-    if (RAND_bytes(buffer, (int)length)) {
-        return SOTER_SUCCESS;
+    /* BoringSSL's RAND_bytes() accepts size_t, no need to cast */
+    result = RAND_bytes(buffer, length);
+
+    if (result < 0) {
+        return SOTER_NOT_SUPPORTED;
     }
 
-    /* For some reason OpenSSL generator failed */
-    return SOTER_FAIL;
+    return (result == 1) ? SOTER_SUCCESS : SOTER_FAIL;
 }
diff --git a/src/soter/openssl/soter_rand.c b/src/soter/openssl/soter_rand.c
index c276121a3..0a447fcae 100644
--- a/src/soter/openssl/soter_rand.c
+++ b/src/soter/openssl/soter_rand.c
@@ -16,18 +16,23 @@
 
 #include "soter/soter_rand.h"
 
+#include <limits.h>
+
 #include <openssl/rand.h>
 
 soter_status_t soter_rand(uint8_t* buffer, size_t length)
 {
-    if ((!buffer) || (!length)) {
+    int result;
+
+    if (!buffer || !length || length > INT_MAX) {
         return SOTER_INVALID_PARAMETER;
     }
 
-    if (RAND_bytes(buffer, (int)length)) {
-        return SOTER_SUCCESS;
+    result = RAND_bytes(buffer, (int)length);
+
+    if (result < 0) {
+        return SOTER_NOT_SUPPORTED;
     }
 
-    /* For some reason OpenSSL generator failed */
-    return SOTER_FAIL;
+    return (result == 1) ? SOTER_SUCCESS : SOTER_FAIL;
 }
diff --git a/src/soter/soter_rand.h b/src/soter/soter_rand.h
index 564ad12de..f1c561c82 100644
--- a/src/soter/soter_rand.h
+++ b/src/soter/soter_rand.h
@@ -28,8 +28,8 @@
 /**
  * @addtogroup SOTER
  * @{
- * @defgroup SOTER_RAND random bits generator
- * @brief Routine for rundom bits generation
+ * @defgroup SOTER_RAND generating random data
+ * @brief Routines for generating random data
  * @{
  */
 #ifdef __cplusplus
@@ -37,13 +37,17 @@ extern "C" {
 #endif
 
 /**
- * @brief Generates random bits
+ * @brief Generates pseudo-random bytes
  *
- * @param [out] buffer pointer to a buffer for random bits
- * @param [in] length length of the buffer
+ * @param [out] buffer pointer to the output buffer for random data
+ * @param [in]  length length of the buffer
  * @return success code
  *
- * This function generates random bits and puts them in memory pointed by buffer.
+ * This function generates cryptographically strong pseudo-random bytes
+ * and fills the provided buffer with them.
+ *
+ * SOTER_FAIL indicates that there is not enough entropy available
+ * to fill the entire buffer. Please try again later.
  */
 SOTER_API
 soter_status_t soter_rand(uint8_t* buffer, size_t length);


Test patch: