From 51a04a3674d62707506774b11a4376a914735aeb Mon Sep 17 00:00:00 2001 From: flywind Date: Mon, 15 Mar 2021 21:07:27 +0800 Subject: make std/sysrand better (#17360) --- lib/std/sysrand.nim | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'lib/std') diff --git a/lib/std/sysrand.nim b/lib/std/sysrand.nim index 603c132e8..c9908143c 100644 --- a/lib/std/sysrand.nim +++ b/lib/std/sysrand.nim @@ -258,26 +258,28 @@ else: # see: https://www.2uo.de/myths-about-urandom/ which justifies using urandom instead of random let fd = posix.open("/dev/urandom", O_RDONLY) - defer: discard posix.close(fd) - - if fd > 0: - var stat: Stat - if fstat(fd, stat) != -1 and S_ISCHR(stat.st_mode): - let - chunks = (size - 1) div batchSize - left = size - chunks * batchSize - - for i in 0 ..< chunks: - let readBytes = posix.read(fd, addr dest[result], batchSize) - if readBytes < 0: - return readBytes - inc(result, batchSize) - - result = posix.read(fd, addr dest[result], left) - else: - result = -1 - else: + + if fd < 0: result = -1 + else: + try: + var stat: Stat + if fstat(fd, stat) != -1 and S_ISCHR(stat.st_mode): + let + chunks = (size - 1) div batchSize + left = size - chunks * batchSize + + for i in 0 ..< chunks: + let readBytes = posix.read(fd, addr dest[result], batchSize) + if readBytes < 0: + return readBytes + inc(result, batchSize) + + result = posix.read(fd, addr dest[result], left) + else: + result = -1 + finally: + discard posix.close(fd) proc urandomInternalImpl(dest: var openArray[byte]): int {.inline.} = when batchImplOS: @@ -291,6 +293,10 @@ proc urandom*(dest: var openArray[byte]): bool = ## ## If `dest` is empty, `urandom` immediately returns success, ## without calling underlying operating system api. + ## + ## .. warning:: The code hasn't been audited by cryptography experts and + ## is provided as-is without guarantees. Use at your own risks. For production + ## systems we advise you to request an external audit. result = true when defined(js): discard urandomInternalImpl(dest) else: @@ -304,6 +310,10 @@ proc urandom*(dest: var openArray[byte]): bool = proc urandom*(size: Natural): seq[byte] {.inline.} = ## Returns random bytes suitable for cryptographic use. + ## + ## .. warning:: The code hasn't been audited by cryptography experts and + ## is provided as-is without guarantees. Use at your own risks. For production + ## systems we advise you to request an external audit. result = newSeq[byte](size) when defined(js): discard urandomInternalImpl(result) else: -- cgit 1.4.1-2-gfad0