diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2017-10-12 21:58:51 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2017-11-11 08:10:58 +0000 |
commit | 4502999ff054f16aab1fdd99fbd9256b22ecadf9 (patch) | |
tree | 758114fb7bdffd9aaca01b30d796556104d7a9c2 /src/corelib/global/qrandom.cpp | |
parent | 19b0ce5daa31e2ffebfcf2701143742302f1deb4 (diff) |
QRandomGenerator: remove the per-thread buffer
Since we're adding a deterministic generator that inherently does not
use syscalls, and people should really use that one by default, there is
no point in optimizing the secure generator wrt syscalls. Besides,
keeping the random data in memory for longer than needed is likely
inadviseable.
Change-Id: Ib17dde1a1dbb49a7bba8fffd14ed0871117fe930
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/global/qrandom.cpp')
-rw-r--r-- | src/corelib/global/qrandom.cpp | 72 |
1 files changed, 8 insertions, 64 deletions
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 9abb9ece7f..17f25ead86 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -129,7 +129,6 @@ namespace { class SystemRandom { public: - enum { EfficientBufferFill = true }; static qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW { // getentropy can read at most 256 bytes, so break the reading @@ -217,7 +216,6 @@ qssize_t SystemRandom::fillBuffer(void *buffer, qssize_t count) class SystemRandom { public: - enum { EfficientBufferFill = true }; static qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW { auto RtlGenRandom = SystemFunction036; @@ -228,7 +226,6 @@ public: class SystemRandom { public: - enum { EfficientBufferFill = false }; static qssize_t fillBuffer(void *, qssize_t) Q_DECL_NOTHROW { // always use the fallback @@ -362,9 +359,15 @@ static qssize_t fill_cpu(quint32 *buffer, qssize_t count) Q_DECL_NOTHROW return 0; } -static void fill_internal(quint32 *buffer, qssize_t count) - Q_DECL_NOEXCEPT_EXPR(noexcept(SystemRandom::fillBuffer(buffer, count))) +static Q_NEVER_INLINE void fill(void *begin, void *end) + Q_DECL_NOEXCEPT_EXPR(noexcept(SystemRandom::fillBuffer(nullptr, 1))) { + // Verify that the pointers are properly aligned for 32-bit + Q_ASSERT(quintptr(begin) % sizeof(quint32) == 0); + Q_ASSERT(quintptr(end) % sizeof(quint32) == 0); + quint32 *buffer = reinterpret_cast<quint32 *>(begin); + qssize_t count = reinterpret_cast<quint32 *>(end) - buffer; + if (Q_UNLIKELY(uint(qt_randomdevice_control) & SetRandomData)) { uint value = uint(qt_randomdevice_control) & RandomDataMask; std::fill_n(buffer, count, value); @@ -386,65 +389,6 @@ static void fill_internal(quint32 *buffer, qssize_t count) } } -static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd) - Q_DECL_NOEXCEPT_EXPR(noexcept(fill_internal(static_cast<quint32 *>(buffer), 1))) -{ - struct ThreadState { - enum { - DesiredBufferByteSize = 32, - BufferCount = DesiredBufferByteSize / sizeof(quint32) - }; - quint32 buffer[BufferCount]; - int idx = BufferCount; - }; - - // Verify that the pointers are properly aligned for 32-bit - Q_ASSERT(quintptr(buffer) % sizeof(quint32) == 0); - Q_ASSERT(quintptr(bufferEnd) % sizeof(quint32) == 0); - - quint32 *ptr = reinterpret_cast<quint32 *>(buffer); - quint32 * const end = reinterpret_cast<quint32 *>(bufferEnd); - -#if defined(Q_COMPILER_THREAD_LOCAL) && !defined(QT_BOOTSTRAPPED) - if (SystemRandom::EfficientBufferFill && (end - ptr) < ThreadState::BufferCount - && uint(qt_randomdevice_control) == 0) { - thread_local ThreadState state; - qssize_t itemsAvailable = ThreadState::BufferCount - state.idx; - - // copy as much as we already have - qssize_t itemsToCopy = qMin(qssize_t(end - ptr), itemsAvailable); - memcpy(ptr, state.buffer + state.idx, size_t(itemsToCopy) * sizeof(*ptr)); - ptr += itemsToCopy; - - if (ptr != end) { - // refill the buffer and try again - fill_internal(state.buffer, ThreadState::BufferCount); - state.idx = 0; - - itemsToCopy = end - ptr; - memcpy(ptr, state.buffer + state.idx, size_t(itemsToCopy) * sizeof(*ptr)); - ptr = end; - } - - // erase what we copied and advance -# ifdef Q_OS_WIN - // Microsoft recommends this - SecureZeroMemory(state.buffer + state.idx, size_t(itemsToCopy) * sizeof(*ptr)); -# else - // We're quite confident the compiler will not optimize this out because - // we're writing to a thread-local buffer - memset(state.buffer + state.idx, 0, size_t(itemsToCopy) * sizeof(*ptr)); -# endif - state.idx += itemsToCopy; - } -#endif // Q_COMPILER_THREAD_LOCAL && !QT_BOOTSTRAPPED - - if (ptr != end) { - // fill directly in the user buffer - fill_internal(ptr, end - ptr); - } -} - /*! \class QRandomGenerator \inmodule QtCore |