summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morrow <acm@mongodb.com>2015-09-07 16:29:54 -0400
committerAndrew Morrow <acm@mongodb.com>2015-09-15 10:27:28 -0400
commitfbf0437a55305c4f190831784c40470b29920419 (patch)
tree09a43ea6e410c96f474bcf6257f29a09887e2098
parentbb20f83281d25e566b4eb2c9984660d089204317 (diff)
downloadmongo-fbf0437a55305c4f190831784c40470b29920419.tar.gz
SERVER-17422 Use BCrypt API for secure random number generation on Windows
-rw-r--r--SConstruct23
-rw-r--r--src/mongo/platform/random.cpp49
-rw-r--r--src/mongo/platform/windows_basic.h14
3 files changed, 67 insertions, 19 deletions
diff --git a/SConstruct b/SConstruct
index 022a60cd094..36bcd4d3da3 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1333,15 +1333,20 @@ elif env.TargetOSIs('windows'):
# This gives 32-bit programs 4 GB of user address space in WOW64, ignored in 64-bit builds
env.Append( LINKFLAGS=["/LARGEADDRESSAWARE"] )
- env.Append(LIBS=['ws2_32.lib',
- 'kernel32.lib',
- 'advapi32.lib',
- 'Psapi.lib',
- 'DbgHelp.lib',
- 'shell32.lib',
- 'Iphlpapi.lib',
- 'winmm.lib',
- 'version.lib'])
+ env.Append(
+ LIBS=[
+ 'DbgHelp.lib',
+ 'Iphlpapi.lib',
+ 'Psapi.lib',
+ 'advapi32.lib',
+ 'bcrypt.lib',
+ 'kernel32.lib',
+ 'shell32.lib',
+ 'version.lib',
+ 'winmm.lib',
+ 'ws2_32.lib',
+ ],
+ )
# When building on visual studio, this sets the name of the debug symbols file
if env.ToolchainIs('msvc'):
diff --git a/src/mongo/platform/random.cpp b/src/mongo/platform/random.cpp
index 2ec9ddea610..c46747a4135 100644
--- a/src/mongo/platform/random.cpp
+++ b/src/mongo/platform/random.cpp
@@ -27,12 +27,18 @@
* then also delete it in the license file.
*/
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault
+
+#include "mongo/platform/basic.h"
+
#include "mongo/platform/random.h"
#include <stdio.h>
#include <string.h>
-#ifndef _WIN32
+#ifdef _WIN32
+#include <bcrypt.h>
+#else
#include <errno.h>
#endif
@@ -42,7 +48,8 @@
#include <fstream>
#include <limits>
-#include "mongo/platform/basic.h"
+#include <mongo/util/log.h>
+#include <mongo/util/assert_util.h>
namespace mongo {
@@ -99,17 +106,39 @@ SecureRandom::~SecureRandom() {}
#ifdef _WIN32
class WinSecureRandom : public SecureRandom {
- virtual ~WinSecureRandom() {}
- int64_t nextInt64() {
- uint32_t a, b;
- if (rand_s(&a)) {
- abort();
+public:
+ WinSecureRandom() {
+ auto ntstatus = ::BCryptOpenAlgorithmProvider(
+ &_algHandle, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
+ if (ntstatus != STATUS_SUCCESS) {
+ error() << "Failed to open crypto algorithm provider while creating secure random "
+ "object; NTSTATUS: " << ntstatus;
+ fassertFailed(28815);
}
- if (rand_s(&b)) {
- abort();
+ }
+
+ virtual ~WinSecureRandom() {
+ auto ntstatus = ::BCryptCloseAlgorithmProvider(_algHandle, 0);
+ if (ntstatus != STATUS_SUCCESS) {
+ warning() << "Failed to close crypto algorithm provider destroying secure random "
+ "object; NTSTATUS: " << ntstatus;
+ }
+ }
+
+ int64_t nextInt64() {
+ int64_t value;
+ auto ntstatus =
+ ::BCryptGenRandom(_algHandle, reinterpret_cast<PUCHAR>(&value), sizeof(value), 0);
+ if (ntstatus != STATUS_SUCCESS) {
+ error() << "Failed to generate random number from secure random object; NTSTATUS: "
+ << ntstatus;
+ fassertFailed(28814);
}
- return (static_cast<int64_t>(a) << 32) | b;
+ return value;
}
+
+private:
+ BCRYPT_ALG_HANDLE _algHandle;
};
SecureRandom* SecureRandom::create() {
diff --git a/src/mongo/platform/windows_basic.h b/src/mongo/platform/windows_basic.h
index 7e2b8ac17fc..ac6cb289dc8 100644
--- a/src/mongo/platform/windows_basic.h
+++ b/src/mongo/platform/windows_basic.h
@@ -82,10 +82,24 @@
// tell windows.h not to include a bunch of headers we don't need:
#define WIN32_LEAN_AND_MEAN
+// Tell windows.h not to define any NT status codes, so that we can
+// get the definitions from ntstatus.h, which has a more complete list.
+#define WIN32_NO_STATUS
+
#include <winsock2.h> //this must be included before the first windows.h include
#include <ws2tcpip.h>
#include <windows.h>
+#undef WIN32_NO_STATUS
+
+// Obtain a definition for the ntstatus type.
+#include <winternl.h>
+
+// Add back in the status definitions so that macro expansions for
+// things like STILL_ACTIVE and WAIT_OBJECT_O can be resolved (they
+// expand to STATUS_ codes).
+#include <ntstatus.h>
+
// Should come either from the command line, or if not set there, the inclusion of sdkddkver.h
// via windows.h above should set it based in _WIN32_WINNT, which is assuredly set by now.
#if !defined(NTDDI_VERSION)