Random.lean
Entropy Syscalls
Defines the Linux AArch64 getrandom syscall number (SYS_GETRANDOM = 278), GRND_* flag constants (include/), and handler execGetrandom (drivers/).
@[expose] public sectionnamespace Arm64def SYS_GETRANDOM
Linux AArch64 getrandom syscall number (__NR_getrandom = 278, include/, drivers/).
def SYS_GETRANDOM : BitVec 64 := 278#64def GRND_NONBLOCK
Linux getrandom flags (include/).
def GRND_NONBLOCK : BitVec 32 := 0x0001#32def GRND_RANDOM
def GRND_RANDOM : BitVec 32 := 0x0002#32def GRND_INSECURE
def GRND_INSECURE : BitVec 32 := 0x0004#32def GRND_KNOWN_MASK
def GRND_KNOWN_MASK : BitVec 32 := GRND_NONBLOCK ||| GRND_RANDOM ||| GRND_INSECUREdef execGetrandom
getrandom(buf, count, flags) (__NR_getrandom = 278, drivers/):
-
flagsisunsigned int(W2): rejects bits outsideGRND_KNOWN_MASK(0x7) and the mutually exclusive combinationGRND_INSECURE|GRND_RANDOM(0x6) with-EINVAL. -
count >
MAX_RW_COUNT(0x7ffff000) returns-EINVALwithout writing memory or advancingoracleIdx(Linux clampscounttoMAX_RW_COUNTfor a short read). -
Assumes an initialized kernel CRNG, so
GRND_NONBLOCKnever returns-EAGAINand valid requests fillcountbytes froms..oracle. getrandom s. oracleIdx -
Checks
flagsbefore checkings.(mem. canWrite buf count. toNat copy_to_user).
def execGetrandom (s : State) : State :=
let buf := s.readReg64 Reg.x0
let count := s.readReg64 Reg.x1
let flags := s.readReg32 Reg.x2
if (flags &&& ~~~GRND_KNOWN_MASK) != 0#32 ||
(flags &&& (GRND_RANDOM ||| GRND_INSECURE)) == (GRND_RANDOM ||| GRND_INSECURE) ||
count.toNat > MAX_RW_COUNT then
(s.writeReg64 Reg.x0 (-EINVAL)).advancePC
else if !s.mem.canWrite buf count.toNat then
(s.writeReg64 Reg.x0 EFAULT_RET).advancePC
else
let bytes := (List.range count.toNat).map (s.oracle.getrandom s.oracleIdx)
(((s.setMem (s.mem.writeBytes buf bytes)).nextOracle).writeReg64 Reg.x0 count).advancePCend Arm64