summary refs log tree commit diff stats
path: root/lib/std
diff options
context:
space:
mode:
authorflywind <xzsflywind@gmail.com>2021-03-15 21:07:27 +0800
committerGitHub <noreply@github.com>2021-03-15 14:07:27 +0100
commit51a04a3674d62707506774b11a4376a914735aeb (patch)
tree48462cc77fb79d8e87eb0fa03c76d59f0f279007 /lib/std
parent283d9abc84a9a71b88bb34b66f15157b1307e11c (diff)
downloadNim-51a04a3674d62707506774b11a4376a914735aeb.tar.gz
make std/sysrand better (#17360)
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/sysrand.nim48
1 files changed, 29 insertions, 19 deletions
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: