[libcxx] random_device for Windows needs more storage

I’m trying to implement random_device for Windows using the CryptGenRandom API, as in the attached non-working code.

The trouble is, I need to store a crypto handle sized 64 bits in random_device whereas it has only an int (likely less than 64 bits) private member for storage.

Is it OK to modify the private member _f type from int to uint64_t?

A uint64_t it can hold both the crypto handle on Windows and file handles on Linux.

Yaron

random.cpp (1.92 KB)

In article <CANa4zJo+YND+HH3vz1Y-JymaLCjR2-QJkdLgFCWW27AYbP0YyA@mail.gmail.com>,
    Yaron Keren <yaron.keren@gmail.com> writes:

Is it OK to modify the private member __f_ type from int to uint64_t?

Wouldn't intptr_t or uintptr_t be more appropriate?

"Handles" in Windows are more likely to be pointers masquerading as an
integer for opacity purposes.

The actual data type is typedef ULONG_PTR HCRYPTPROV;
I found two conflicting descriptions in microsoft.com for ULONG_PTR:

The first http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx says it’s always 64 bits:

#if defined(_WIN64)
 typedef unsigned __int64 ULONG_PTR;
#else
 typedef unsigned long ULONG_PTR;
#endif

There's no need for CryptGenRandom and its overhead here. RtlGenRandom is just fine for random_device. MSVCRT does the same.

-Nico

Nick, I have seen RtlGenRandom, but I didn’t initally use it since Microsoft is recommending to use CryptGenRandom instead:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694(v=vs.85).aspx

[The RtlGenRandom function is available for use in the operating systems specified in the Requirements section. It may be altered or unavailable in subsequent versions. Instead, use the CryptGenRandom function.]

Due to backward compatibility it’s very low chance RtlGenRandom will actually go away, I’ll use it.

Yaron

I don't believe we should be using this function. Technically, the
documentation states this is available for use with the operating
systems listed in the Requirements section, which only lists XP and
Server 2003. Relying on this outside of those platforms is not only
bad form, but to boot, in order to use them, you need to dynamically
load SystemFunction036 from AdvApi32.dll.

~Aaron

Hi,

Just found out both Visual C++ and MingW supply the rand_s() function (implemented in MSVCRT), which wraps one of the above functions in a very easy to use and version:

http://msdn.microsoft.com/en-us/library/sxtz2fa8.aspx

Microsoft own random_device uses it,

Yaron

rand_s() is a much better solution. :slight_smile:

~Aaron

For newer SDKs, when targeting XP and up (_WIN32_WINNT >= 0x0501), ntsecapi.h defines it as a macro to SystemFunction036 so it works without any additional steps. And the documentation lists the minimum required OS version.

-Nico

Did I miss something? Long is 32-bits on win32 (and on win64, which breaks a lot of code that assumes that you can round trip pointers through long, because even though the standard has never guaranteed this it's been possible on pretty much every system that isn't an IBM mainframe for decades). On Win32, long is the size of a pointer, on Win64, __int64 is the size of a pointer.

David

Hi David,

You are correct, I was under the wrong impression that longs are 64 bit on Win32. So indeed all references above map (with differing typdefs) HCRYPTPROV to 32 bits on Win32 and 64 bits on Win64.

In any case, I submitted a patch using rand_s() from MSVCRT.

Yaron

unsigned long is always 32 bits on Microsoft’s compiler. Sebastian

Thanks, Sebastian, David Chisnall corrected me.
random_device() was finally implemented based on rand_s() from MSVCRT.

Yaron