Skip to content

Commit 57e7ed7

Browse files
tniessentargos
authored andcommitted
src: fix CSPRNG when length exceeds INT_MAX
CSPRNG implicitly casts the size_t length argument to a signed int when calling RAND_bytes(), which leaves it up to the caller to ensure that the length argument actually fits into such a signed int. However, not all call sites explicitly ensure that, which could lead to subtle bugs. In OpenSSL 3, use RAND_bytes_ex() instead, which does not require casting the length to a signed int. In OpenSSL 1.1.1, RAND_bytes_ex() is not supported, thus we have to process blocks of size INT_MAX one by one. PR-URL: #47515 Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 35e8b3b commit 57e7ed7

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

src/crypto/crypto_util.cc

+12-2
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,20 @@ int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
6161
}
6262

6363
MUST_USE_RESULT CSPRNGResult CSPRNG(void* buffer, size_t length) {
64+
unsigned char* buf = static_cast<unsigned char*>(buffer);
6465
do {
65-
if (1 == RAND_status())
66-
if (1 == RAND_bytes(static_cast<unsigned char*>(buffer), length))
66+
if (1 == RAND_status()) {
67+
#if OPENSSL_VERSION_MAJOR >= 3
68+
if (1 == RAND_bytes_ex(nullptr, buf, length, 0)) return {true};
69+
#else
70+
while (length > INT_MAX && 1 == RAND_bytes(buf, INT_MAX)) {
71+
buf += INT_MAX;
72+
length -= INT_MAX;
73+
}
74+
if (length <= INT_MAX && 1 == RAND_bytes(buf, static_cast<int>(length)))
6775
return {true};
76+
#endif
77+
}
6878
#if OPENSSL_VERSION_MAJOR >= 3
6979
const auto code = ERR_peek_last_error();
7080
// A misconfigured OpenSSL 3 installation may report 1 from RAND_poll()

0 commit comments

Comments
 (0)