-
Notifications
You must be signed in to change notification settings - Fork 16
Get random data from OS APIs #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
88aac41
to
655496f
Compare
source/mir/random/engine/test.d
Outdated
mov RDX, arg2[RBP]; | ||
syscall; | ||
mov ret, RAX; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@9il Is dmd
guaranteed to execute the asm
block in one go?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got the inspiration to use this syscall
style from here: https://github.com/kubo39/syscall-d/blob/master/source/syscalld/arch/syscall_x86_64.d
Hence also the synchronized
statements, but afaict we don't need it - e.g.:
https://wiki.dlang.org/LDC_inline_assembly_expressions#X86-64
fc776c3
to
0c14f5a
Compare
0c14f5a
to
8c12586
Compare
I accidentally came by two other implementation in the D ecosystem: https://github.com/LightBender/SecureD/blob/master/source/random.d (the latter is interesting as it uses quite a bunch of entropy sources) |
Awesome! |
But do not spent much time on deprecated targets ;) |
@wilzbach do you need help with this PR? |
be9bb7c
to
cb955a8
Compare
Oh sorry for letting this get stalled. As discussed this exposes two different functions with C-style like interface, but with D-guarantees in terms of
The difference between these two functions is that the @9il please let me know if there's sth. missing for this PR. About Blocking behavior:tl;dr: only useful on Linux.
And for the newer
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each public function should be extern(C)
and starts with mir_random_
. mir_random_genRandomBlocking
. An alias can be added: genRandomBlocking = mir_random_genRandomBlocking
. Please replace get*
with gen*
.
source/mir/random/engine/package.d
Outdated
k ^= k >> 33; | ||
return cast(size_t)k; | ||
size_t seed; | ||
//getRandomBlocking(&seed, seed.sizeof); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Lets preserve old version if
getRandomBlocking
returns -1 - and uncomment this line)
source/mir/random/engine/package.d
Outdated
import core.sys.posix.sys.utsname : utsname; | ||
|
||
// druntime isn't properly annotated | ||
extern(C) int uname(utsname* __name) @nogc nothrow; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private
source/mir/random/engine/package.d
Outdated
return false; | ||
} | ||
|
||
extern(C) int syscall(size_t ident, size_t n, size_t arg1, size_t arg2) @nogc nothrow; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private
source/mir/random/engine/package.d
Outdated
{ | ||
auto res = syscall(GETRANDOM, cast(size_t) ptr + genBytes, len - genBytes, 0); | ||
if (res >= 0) | ||
genBytes -= res; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bug.
Just move ptr and reduce length, instead of genBytes
variable
source/mir/random/engine/package.d
Outdated
import core.stdc.stdio : fclose, feof, ferror, fopen, fread; | ||
alias IOType = typeof(fopen("a", "b")); | ||
static private IOType fdRandom; | ||
static private IOType fdURandom; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__gshared
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private
source/mir/random/engine/package.d
Outdated
static private IOType fdRandom; | ||
static private IOType fdURandom; | ||
|
||
shared static ~this() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extern(C)
source/mir/random/engine/package.d
Outdated
extern(Windows) BOOL CryptGenRandom(HCRYPTPROV, DWORD, PBYTE) @nogc @safe nothrow; | ||
extern(Windows) BOOL CryptAcquireContextA(HCRYPTPROV*, LPCSTR, LPCSTR, DWORD, DWORD) @nogc nothrow; | ||
extern(Windows) BOOL CryptAcquireContextW(HCRYPTPROV*, LPCWSTR, LPCWSTR, DWORD, DWORD) @nogc nothrow; | ||
extern(Windows) BOOL CryptReleaseContext(HCRYPTPROV, ULONG_PTR) @nogc nothrow; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private
source/mir/random/engine/package.d
Outdated
return 0; | ||
} | ||
|
||
shared static ~this() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extern(C)
source/mir/random/engine/package.d
Outdated
extern(Windows) BOOL CryptAcquireContextW(HCRYPTPROV*, LPCWSTR, LPCWSTR, DWORD, DWORD) @nogc nothrow; | ||
extern(Windows) BOOL CryptReleaseContext(HCRYPTPROV, ULONG_PTR) @nogc nothrow; | ||
|
||
private static ULONG_PTR hProvider; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__gshared
Ok - questions:
I assume I can't use any locking in betterC?
We could provide a special |
source/mir/random/engine/package.d
Outdated
if (initGetRandom != 0) | ||
return -1; | ||
|
||
while(!CryptGenRandom(hProvider, len, cast(PBYTE) ptr)) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Windows all error codes of CryptGenRandom
seem unrecoverable, so the loop here doesn't seem very useful. I think we should directly yield the error here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
no
This should be a part of documentation.
Yes, but |
|
Hey @wilzbach , could you please finalise this PR? |
Sorry that I left this pending for such a long time.
Added :) |
2c4208c
to
01597d6
Compare
@wilzbach please convert all private functions to templates and add |
Based on code originally written by @wilzbach libmir/mir-random#13
Based on code originally written by @wilzbach libmir/mir-random#13
Based on code originally written by @wilzbach libmir/mir-random#13
Based on code originally written by @wilzbach libmir/mir-random#13
So I managed to find the issue in the Windows API. It was due to wrong API headers in druntime - for 64-bit pointers need to have 8 bytes.
Let me summarize:
Current Behavior
CryptGenRandom
>= 3.17
->getrandom
system call, intro article/dev/(u)?random
(see e.g./dev/random
vs./dev/urandom
)/dev/(u)?random
(see e.g./dev/random
vs./dev/urandom
)Todo
Future work
getentropy
(Not implemented as I don't have a OpenBSD atm - anyone?)References
C++ API: http://en.cppreference.com/w/cpp/numeric/random/random_device
LLVM stdcxx: https://github.com/llvm-mirror/libcxx/blob/master/src/random.cpp
G++: https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/src/c%2B%2B11/random.cc
Python
urandom
: https://github.com/python/cpython/blob/master/Python/random.cVibe.d
cryptorand
: https://github.com/rejectedsoftware/vibe.d/blob/master/crypto/vibe/crypto/cryptorand.dpycrypto
: https://github.com/dlitz/pycrypto/blob/master/src/winrand.c