Refactor sysrand to remove `result` usage and fix style check issues. (#57)
* Refactor sysrand to remove `result` usage and fix style check issues. * Fix duplicated imports.
This commit is contained in:
parent
4a0633dc0b
commit
b41129f955
|
@ -55,7 +55,7 @@
|
||||||
## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D
|
## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D
|
||||||
## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D
|
## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D
|
||||||
## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D
|
## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D
|
||||||
import hash, utils
|
import utils
|
||||||
import sha, sha2, ripemd, keccak, blake2, hash
|
import sha, sha2, ripemd, keccak, blake2, hash
|
||||||
export sha, sha2, ripemd, keccak, blake2, hash
|
export sha, sha2, ripemd, keccak, blake2, hash
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
## ``Windows`` using BCryptGenRandom (if available),
|
## ``Windows`` using BCryptGenRandom (if available),
|
||||||
## CryptGenRandom(PROV_INTEL_SEC) (if available), RtlGenRandom.
|
## CryptGenRandom(PROV_INTEL_SEC) (if available), RtlGenRandom.
|
||||||
##
|
##
|
||||||
## RtlGenRandom (available from Windows XP)
|
## RtlGenRandom (available since Windows XP)
|
||||||
## BCryptGenRandom (available from Windows Vista SP1)
|
## BCryptGenRandom (available since Windows Vista SP1)
|
||||||
## CryptGenRandom(PROV_INTEL_SEC) (only when Intel SandyBridge
|
## CryptGenRandom(PROV_INTEL_SEC) (only when Intel SandyBridge
|
||||||
## CPU is available).
|
## CPU is available).
|
||||||
##
|
##
|
||||||
|
@ -25,60 +25,63 @@
|
||||||
## ``NetBSD``, ``FreeBSD``, ``MacOS``, ``Solaris`` using `/dev/urandom`.
|
## ``NetBSD``, ``FreeBSD``, ``MacOS``, ``Solaris`` using `/dev/urandom`.
|
||||||
|
|
||||||
{.deadCodeElim:on.}
|
{.deadCodeElim:on.}
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
import os, posix
|
import os, posix
|
||||||
|
|
||||||
proc urandomRead(pbytes: pointer, nbytes: int): int =
|
proc urandomRead(pbytes: pointer, nbytes: int): int =
|
||||||
result = -1
|
|
||||||
var st: Stat
|
var st: Stat
|
||||||
let fd = posix.open("/dev/urandom", posix.O_RDONLY)
|
let fd = posix.open("/dev/urandom", posix.O_RDONLY)
|
||||||
if fd != -1:
|
if fd == -1:
|
||||||
if posix.fstat(fd, st) != -1 and S_ISCHR(st.st_mode):
|
return -1
|
||||||
result = 0
|
if posix.fstat(fd, st) == -1 or not(S_ISCHR(st.st_mode)):
|
||||||
while result < nbytes:
|
|
||||||
var p = cast[pointer](cast[uint]((pbytes)) + uint(result))
|
|
||||||
var res = posix.read(fd, p, nbytes - result)
|
|
||||||
if res > 0:
|
|
||||||
result += res
|
|
||||||
elif res == 0:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if osLastError().int32 != EINTR:
|
|
||||||
result = -1
|
|
||||||
break
|
|
||||||
discard posix.close(fd)
|
discard posix.close(fd)
|
||||||
|
return -1
|
||||||
|
|
||||||
|
var res = 0
|
||||||
|
while res < nbytes:
|
||||||
|
var p = cast[pointer](cast[uint]((pbytes)) + uint(res))
|
||||||
|
var bytesRead = posix.read(fd, p, nbytes - res)
|
||||||
|
if bytesRead > 0:
|
||||||
|
res += bytesRead
|
||||||
|
elif bytesRead == 0:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if osLastError() != OSErrorCode(EINTR):
|
||||||
|
break
|
||||||
|
discard posix.close(fd)
|
||||||
|
res
|
||||||
|
|
||||||
when defined(openbsd):
|
when defined(openbsd):
|
||||||
import posix, os
|
|
||||||
|
|
||||||
proc getentropy(pBytes: pointer, nBytes: int): cint
|
proc getentropy(pbytes: pointer, nbytes: int): cint
|
||||||
{.importc: "getentropy", header: "<unistd.h>".}
|
{.importc: "getentropy", header: "<unistd.h>".}
|
||||||
|
|
||||||
proc randomBytes*(pbytes: pointer, nbytes: int): int =
|
proc randomBytes*(pbytes: pointer, nbytes: int): int =
|
||||||
var p: pointer
|
var p: pointer
|
||||||
while result < nbytes:
|
var res = 0
|
||||||
p = cast[pointer](cast[uint](pbytes) + uint(result))
|
while res < nbytes:
|
||||||
let res = getentropy(p, nbytes - result)
|
p = cast[pointer](cast[uint](pbytes) + uint(res))
|
||||||
if res > 0:
|
let bytesRead = getentropy(p, nbytes - res)
|
||||||
result += res
|
if bytesRead > 0:
|
||||||
elif res == 0:
|
res += bytesRead
|
||||||
|
elif bytesRead == 0:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if osLastError().int32 != EINTR:
|
if osLastError() != OSErrorCode(EINTR):
|
||||||
result = -1
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if result == -1:
|
if res <= 0:
|
||||||
result = urandomRead(pbytes, nbytes)
|
res = urandomRead(pbytes, nbytes)
|
||||||
elif result < nbytes:
|
elif res < nbytes:
|
||||||
p = cast[pointer](cast[uint](pbytes) + uint(result))
|
p = cast[pointer](cast[uint](pbytes) + uint(res))
|
||||||
let res = urandomRead(p, nbytes - result)
|
let bytesRead = urandomRead(p, nbytes - res)
|
||||||
if res != -1:
|
if bytesRead != -1:
|
||||||
result += res
|
res += bytesRead
|
||||||
|
res
|
||||||
|
|
||||||
elif defined(linux):
|
elif defined(linux):
|
||||||
import posix, os
|
|
||||||
when defined(i386):
|
when defined(i386):
|
||||||
const SYS_getrandom = 355
|
const SYS_getrandom = 355
|
||||||
elif defined(powerpc64) or defined(powerpc64el) or defined(powerpc):
|
elif defined(powerpc64) or defined(powerpc64el) or defined(powerpc):
|
||||||
|
@ -109,47 +112,50 @@ elif defined(linux):
|
||||||
|
|
||||||
var gSystemRng {.threadvar.}: SystemRng ## System thread global RNG
|
var gSystemRng {.threadvar.}: SystemRng ## System thread global RNG
|
||||||
|
|
||||||
proc newSystemRNG(): SystemRng =
|
proc newSystemRng(): SystemRng =
|
||||||
result = SystemRng()
|
var rng = SystemRng()
|
||||||
|
|
||||||
if SYS_getrandom != 0:
|
if SYS_getrandom != 0:
|
||||||
var data: int
|
var data: int
|
||||||
result.getRandomPresent = true
|
rng.getRandomPresent = true
|
||||||
let res = syscall(SYS_getrandom, addr data, 1, GRND_NONBLOCK)
|
let res = syscall(SYS_getrandom, addr data, 1, GRND_NONBLOCK)
|
||||||
if res == -1:
|
if res == -1:
|
||||||
let err = osLastError().int32
|
let err = osLastError()
|
||||||
if err == ENOSYS or err == EPERM:
|
if err == OSErrorCode(ENOSYS) or err == OSErrorCode(EPERM):
|
||||||
result.getRandomPresent = false
|
rng.getRandomPresent = false
|
||||||
|
rng
|
||||||
|
|
||||||
proc getSystemRNG(): SystemRng =
|
proc getSystemRng(): SystemRng =
|
||||||
if gSystemRng.isNil: gSystemRng = newSystemRng()
|
if isNil(gSystemRng):
|
||||||
result = gSystemRng
|
gSystemRng = newSystemRng()
|
||||||
|
gSystemRng
|
||||||
|
|
||||||
proc randomBytes*(pbytes: pointer, nbytes: int): int =
|
proc randomBytes*(pbytes: pointer, nbytes: int): int =
|
||||||
var p: pointer
|
var p: pointer
|
||||||
let srng = getSystemRNG()
|
let srng = getSystemRng()
|
||||||
|
|
||||||
if srng.getRandomPresent:
|
if srng.getRandomPresent:
|
||||||
while result < nbytes:
|
var res = 0
|
||||||
p = cast[pointer](cast[uint](pbytes) + uint(result))
|
while res < nbytes:
|
||||||
let res = syscall(SYS_getrandom, pBytes, nBytes - result, 0)
|
p = cast[pointer](cast[uint](pbytes) + uint(res))
|
||||||
if res > 0:
|
let bytesRead = syscall(SYS_getrandom, pbytes, nbytes - res, 0)
|
||||||
result += res
|
if bytesRead > 0:
|
||||||
elif res == 0:
|
res += bytesRead
|
||||||
|
elif bytesRead == 0:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if osLastError().int32 != EINTR:
|
if osLastError().int32 != EINTR:
|
||||||
result = -1
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if result == -1:
|
if res <= 0:
|
||||||
result = urandomRead(pbytes, nbytes)
|
res = urandomRead(pbytes, nbytes)
|
||||||
elif result < nbytes:
|
elif res < nbytes:
|
||||||
p = cast[pointer](cast[uint](pbytes) + uint(result))
|
p = cast[pointer](cast[uint](pbytes) + uint(res))
|
||||||
let res = urandomRead(p, nbytes - result)
|
let bytesRead = urandomRead(p, nbytes - res)
|
||||||
if res != -1:
|
if bytesRead != -1:
|
||||||
result += res
|
res += bytesRead
|
||||||
|
res
|
||||||
else:
|
else:
|
||||||
result = urandomRead(pbytes, nbytes)
|
urandomRead(pbytes, nbytes)
|
||||||
|
|
||||||
elif defined(windows):
|
elif defined(windows):
|
||||||
import os, winlean, dynlib
|
import os, winlean, dynlib
|
||||||
|
@ -219,71 +225,73 @@ elif defined(windows):
|
||||||
|
|
||||||
proc isEqualOrHigher(major: int, minor: int, servicePack: int): bool =
|
proc isEqualOrHigher(major: int, minor: int, servicePack: int): bool =
|
||||||
var mask = 0'u64
|
var mask = 0'u64
|
||||||
var ov = OSVERSIONINFOEXW()
|
var ov = OSVERSIONINFOEXW(
|
||||||
ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW).DWORD
|
dwOSVersionInfoSize: DWORD(sizeof(OSVERSIONINFOEXW)),
|
||||||
ov.dwMajorVersion = major.DWORD
|
dwMajorVersion: DWORD(major),
|
||||||
ov.dwMinorVersion = minor.DWORD
|
dwMinorVersion: DWORD(minor),
|
||||||
ov.wServicePackMajor = servicePack.uint16
|
wServicePackMajor: uint16(servicePack),
|
||||||
ov.wServicePackMinor = 0
|
wServicePackMinor: 0
|
||||||
var typeMask = (VER_MAJORVERSION or VER_MINORVERSION or
|
)
|
||||||
VER_SERVICEPACKMAJOR or VER_SERVICEPACKMINOR).DWORD
|
let typeMask =
|
||||||
|
DWORD(VER_MAJORVERSION or VER_MINORVERSION or
|
||||||
|
VER_SERVICEPACKMAJOR or VER_SERVICEPACKMINOR)
|
||||||
mask = verSetConditionMask(mask, VER_MAJORVERSION, VER_GREATER_EQUAL)
|
mask = verSetConditionMask(mask, VER_MAJORVERSION, VER_GREATER_EQUAL)
|
||||||
mask = verSetConditionMask(mask, VER_MINORVERSION, VER_GREATER_EQUAL)
|
mask = verSetConditionMask(mask, VER_MINORVERSION, VER_GREATER_EQUAL)
|
||||||
mask = verSetConditionMask(mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL)
|
mask = verSetConditionMask(mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL)
|
||||||
mask = verSetConditionMask(mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL)
|
mask = verSetConditionMask(mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL)
|
||||||
return (verifyVersionInfo(addr ov, typeMask, mask) == 1)
|
verifyVersionInfo(addr ov, typeMask, mask) == 1
|
||||||
|
|
||||||
proc newSystemRNG(): SystemRng =
|
proc newSystemRng(): SystemRng =
|
||||||
result = SystemRng()
|
var rng = SystemRng()
|
||||||
if isEqualOrHigher(6, 0, 0):
|
if isEqualOrHigher(6, 0, 0):
|
||||||
if isEqualOrHigher(6, 0, 1):
|
if isEqualOrHigher(6, 0, 1):
|
||||||
let lib = loadLib("bcrypt.dll")
|
let lib = loadLib("bcrypt.dll")
|
||||||
if lib != nil:
|
if lib != nil:
|
||||||
var lProc = cast[BCGRMPROC](symAddr(lib, "BCryptGenRandom"))
|
var lProc = cast[BCGRMPROC](symAddr(lib, "BCryptGenRandom"))
|
||||||
if not isNil(lProc):
|
if not isNil(lProc):
|
||||||
result.bCryptGenRandom = lProc
|
rng.bCryptGenRandom = lProc
|
||||||
|
|
||||||
var hp: HCRYPTPROV = 0
|
var hp: HCRYPTPROV = 0
|
||||||
let intelDef = newWideCString(INTEL_DEF_PROV)
|
let intelDef = newWideCString(INTEL_DEF_PROV)
|
||||||
let res1 = cryptAcquireContext(addr hp, nil, intelDef, PROV_INTEL_SEC,
|
let res = cryptAcquireContext(addr hp, nil, intelDef, PROV_INTEL_SEC,
|
||||||
CRYPT_VERIFYCONTEXT or CRYPT_SILENT).bool
|
CRYPT_VERIFYCONTEXT or CRYPT_SILENT).bool
|
||||||
if res1:
|
if res:
|
||||||
result.hIntel = hp
|
rng.hIntel = hp
|
||||||
|
rng
|
||||||
|
|
||||||
proc getSystemRNG(): SystemRng =
|
proc getSystemRng(): SystemRng =
|
||||||
if gSystemRng.isNil: gSystemRng = newSystemRng()
|
if isNil(gSystemRng):
|
||||||
result = gSystemRng
|
gSystemRng = newSystemRng()
|
||||||
|
gSystemRng
|
||||||
|
|
||||||
proc randomBytes*(pbytes: pointer, nbytes: int): int =
|
proc randomBytes*(pbytes: pointer, nbytes: int): int =
|
||||||
let srng = getSystemRNG()
|
let srng = getSystemRng()
|
||||||
result = -1
|
|
||||||
if not isNil(srng.bCryptGenRandom):
|
if not isNil(srng.bCryptGenRandom):
|
||||||
if srng.bCryptGenRandom(nil, pbytes, nbytes.ULONG,
|
if srng.bCryptGenRandom(nil, pbytes, ULONG(nbytes),
|
||||||
BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0:
|
BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0:
|
||||||
result = nbytes
|
return nbytes
|
||||||
|
if srng.hIntel != 0:
|
||||||
if srng.hIntel != 0 and result == -1:
|
if cryptGenRandom(srng.hIntel, DWORD(nbytes), pbytes) != 0:
|
||||||
if cryptGenRandom(srng.hIntel, nbytes.DWORD, pbytes) != 0:
|
return nbytes
|
||||||
result = nbytes
|
if rtlGenRandom(pbytes, ULONG(nbytes)) != 0:
|
||||||
|
return nbytes
|
||||||
if result == -1:
|
-1
|
||||||
if rtlGenRandom(pBytes, nbytes.ULONG) != 0:
|
|
||||||
result = nbytes
|
|
||||||
|
|
||||||
proc randomClose*() =
|
proc randomClose*() =
|
||||||
let srng = getSystemRNG()
|
let srng = getSystemRng()
|
||||||
if srng.hIntel != 0:
|
if srng.hIntel != 0:
|
||||||
if cryptReleaseContext(srng.hIntel, 0) == 0:
|
discard cryptReleaseContext(srng.hIntel, 0)
|
||||||
raiseOsError(osLastError())
|
|
||||||
else:
|
|
||||||
import posix
|
|
||||||
|
|
||||||
|
else:
|
||||||
proc randomBytes*(pbytes: pointer, nbytes: int): int =
|
proc randomBytes*(pbytes: pointer, nbytes: int): int =
|
||||||
result = urandomRead(pbytes, nbytes)
|
urandomRead(pbytes, nbytes)
|
||||||
|
|
||||||
proc randomBytes*[T](bytes: var openArray[T]): int =
|
proc randomBytes*[T](bytes: var openArray[T]): int =
|
||||||
let length = len(bytes) * sizeof(T)
|
let length = len(bytes) * sizeof(T)
|
||||||
if length > 0:
|
if length == 0:
|
||||||
result = randomBytes(addr bytes[0], length)
|
return 0
|
||||||
if result != -1:
|
let res = randomBytes(addr bytes[0], length)
|
||||||
result = result div sizeof(T)
|
if res != -1:
|
||||||
|
res div sizeof(T)
|
||||||
|
else:
|
||||||
|
res
|
||||||
|
|
Loading…
Reference in New Issue