Repository navigation
Use the Windows CSPRNG to get a random seed for Stdlib.Random - #13578
Conversation
bd33c80 to
98667dc
Compare
0a998c6 to
b1d8f66
Compare
| BCRYPT_USE_SYSTEM_PREFERRED_RNG); | ||
| if (NT_SUCCESS(st)) | ||
| nread = 12; | ||
| while (nread > 0) data[n++] = buffer[--nread]; |
There was a problem hiding this comment.
Why not memcpy(data, buffer, sizeof(buffer))?
Also, this loop can be put under the if above, and be made to follow by the "return" below (always unde the if).
There was a problem hiding this comment.
Why not
memcpy(data, buffer, sizeof(buffer))?
The function doesn't return the number of random bytes written to data, it returns the number of intnats that have random unsigned char in their low-byte. If I do a memcpy and then return 12, the final OCaml seed array will have 12 intnats, of which the first 12 bytes will be random data, and the rest (I guess) the stack values that were there (or zeroes?).
| data[3] = pc.LowPart; | ||
| data[4] = pc.HighPart; | ||
| return 5; | ||
| if (n < 16) data[n++] = t.dwLowDateTime; |
There was a problem hiding this comment.
n is always zero if you reach here, or am I missing something?
There was a problem hiding this comment.
Yes, you're right. BCryptGenRandom either writes 12 bytes and succeeds; or fails and n will be zero.
|
I agree with your comments @nojb. The idea behind the change was to copy the existing Lines 628 to 668 in 6e80aa0 One thing that surprised me with this code is that we don't fill the In the end this function is a bit of a headache... so I went with the easy way, which was to copy |
6a7d739 to
c763cf1
Compare
nojb
left a comment
There was a problem hiding this comment.
As far as I can see, the patch is correct. The changes to sys.c could have been omitted or put in a separate PR, but am not strongly opposed to them.
I am "informally" approving this PR, as the code is tricky, so a second pair of eyes would be appreciated before merging.
LGTM
c763cf1 to
6f7997a
Compare
|
I remember that using bcrypt.lib was considered a long time ago, but rejected because it's a big library and linking with it would penalize all OCaml programs. (Not sure I remember correctly.)
|
I see an increase of 1-2KB on the ocaml*.exe files when building this PR.
I think not, my intent was to have better parity with Unix which does use a CSPRNG to seed A 'wontfix' is a reasonable answer here, in which case I'll just update the comments. |
|
Thanks for the measurement. Searching the Web a bit, I see that Microsoft's crypto API and its implementation changed several times in the past, so my vague recollection of a possible code size problem with a crypto PRNG is certainly outdated, if not plain wrong. I also see that there's a |
6f7997a to
ee64582
Compare
Not sure why or how I missed this one. I've changed my patch to use |
| nread += sizeof(unsigned int); | ||
|
|
||
| while (nread > 0) data[n++] = buffer[--nread]; | ||
| /* If the kernel provided enough entropy, we now have 96 bits |
There was a problem hiding this comment.
Nitpicking: it's OK to spread the 3 4-byte random integers over the first 12 integers of data, one byte at a time. But you could just as well write the return values of rand_s into data[0], data[1] and data[2], and stop there if the 3 calls to rand_s succeeded. In both cases you have 96 bits of entropy, and the Random module will make good use of these bits, no matter how they are spread over the elements of the data array.
There was a problem hiding this comment.
I've implemented your suggestion, I hope correctly.
ee64582 to
3fe7f70
Compare
- use the buffer size instead of a magic constant; - remove unused _WIN32 guards around getpid/getppid, Windows has its own caml_win32_random_seed.
3fe7f70 to
bc89d7b
Compare
xavierleroy
left a comment
There was a problem hiding this comment.
You didn't have to change the code, but thanks for having changed it, the result is short and sweet.
I ran a chi^2 test on the output of caml_sys_random_seed. It passes with the new code using rand_s , and fails on the old code, which is as expected, and a confirmation that the new code is good.
Now merging...
Windows (since Vista SP2 / Server 2008) provides a CSPRNG as the
BCryptGenRandomfunction. Use it to generateStdlib.Randomdefault seed, mimicking the use ofgetentropyor/dev/urandomon Unix-like systems. See the Unix counter-partcaml_unix_random_seed:ocaml/runtime/sys.c
Lines 604 to 644 in 9caaced