/*++ Copyright (c) Microsoft. All rights reserved. Module Name: random.c Abstract: This file is a test for the getrandom system call and the /dev/random and /dev/urandom devices. --*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lxtcommon.h" #include "unittests.h" #define DEV_RANDOM "/dev/random" #define DEV_RANDOM_MAX_BYTES (512) #define DEV_URANDOM "/dev/urandom" #define DEV_URANDOM_MAX_BYTES (0x1FFFFFF) #define PROC_SYS_KERNEL_RANDOM "/proc/sys/kernel/random" #define PROC_SYS_KERNEL_RANDOM_BOOTID PROC_SYS_KERNEL_RANDOM "/boot_id" #define PROC_SYS_KERNEL_RANDOM_ENTROPY_AVAIL PROC_SYS_KERNEL_RANDOM "/entropy_avail" #define PROC_SYS_KERNEL_RANDOM_POOLSIZE PROC_SYS_KERNEL_RANDOM "/poolsize" #define PROC_SYS_KERNEL_RANDOM_UUID PROC_SYS_KERNEL_RANDOM "/uuid" #define PROC_SYS_KERNEL_RANDOM_BYTES 37 #define LXT_NAME "random" int GetrandomSyscall(PLXT_ARGS Args); int DevRandomDevice(PLXT_ARGS Args); int DevUrandomDevice(PLXT_ARGS Args); int ProcfsRandom(PLXT_ARGS Args); static const LXT_VARIATION g_LxtVariations[] = { {"getrandom syscall", GetrandomSyscall}, {"/dev/random device", DevRandomDevice}, {"/dev/urandom device", DevUrandomDevice}, {"/proc/sys/kernel/random", ProcfsRandom}}; int RandomTestEntry(int Argc, char* Argv[]) { LXT_ARGS Args; int Result; LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME)); LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations))); ErrorExit: LxtUninitialize(); return 0; } int GetrandomSyscall(PLXT_ARGS Args) { char* Buffer; size_t BufferSize; size_t Result; BufferSize = DEV_URANDOM_MAX_BYTES + 1; Buffer = malloc(BufferSize); if (Buffer == NULL) { Result = LXT_RESULT_FAILURE; LxtLogError("malloc failed"); goto ErrorExit; } // // Valid parameter variations. // LxtCheckResult(LxtGetrandom(NULL, 0, 0)); LxtCheckEqual(Result, 0, "%Iu"); LxtCheckResult(LxtGetrandom(NULL, 0, GRND_RANDOM)); LxtCheckResult(LxtGetrandom(NULL, 0, GRND_NONBLOCK)); LxtCheckResult(LxtGetrandom(NULL, 0, (GRND_RANDOM | GRND_NONBLOCK))); LxtCheckResult(LxtGetrandom(Buffer, BufferSize, 0)); if (Result > DEV_URANDOM_MAX_BYTES) { Result = LXT_RESULT_FAILURE; LxtLogError("BytesRead %Iu greater than expected %Iu", Result, DEV_URANDOM_MAX_BYTES); goto ErrorExit; } LxtCheckResult(LxtGetrandom(Buffer, BufferSize, GRND_RANDOM)); if (Result > DEV_RANDOM_MAX_BYTES) { Result = LXT_RESULT_FAILURE; LxtLogError("BytesRead %Iu greater than expected %Iu", Result, DEV_RANDOM_MAX_BYTES); goto ErrorExit; } // // Invalid parameter variations. // LxtCheckErrnoFailure(LxtGetrandom(NULL, 0, ((GRND_RANDOM | GRND_NONBLOCK) + 1)), EINVAL); LxtCheckErrnoFailure(LxtGetrandom(NULL, 0, -1), EINVAL); LxtCheckErrnoFailure(LxtGetrandom(NULL, 1, 0), EFAULT); LxtCheckErrnoFailure(LxtGetrandom(-1, 1, 0), EFAULT); ErrorExit: if (Buffer != NULL) { free(Buffer); } return Result; } int DevRandomDevice(PLXT_ARGS Args) { char Buffer[DEV_RANDOM_MAX_BYTES + 1]; int BytesRead; int Fd; int Result; Fd = -1; LxtCheckResult(Fd = open(DEV_RANDOM, O_RDONLY)); LxtCheckResult(BytesRead = read(Fd, Buffer, LXT_COUNT_OF(Buffer))); if (BytesRead > DEV_RANDOM_MAX_BYTES) { Result = LXT_RESULT_FAILURE; LxtLogError("BytesRead %d greater than expected %d", BytesRead, DEV_RANDOM_MAX_BYTES); goto ErrorExit; } Result = LXT_RESULT_SUCCESS; ErrorExit: if (Fd != -1) { LxtClose(Fd); } return Result; } int DevUrandomDevice(PLXT_ARGS Args) { char* Buffer; size_t BufferSize; int BytesRead; int Fd; int Result; BufferSize = DEV_URANDOM_MAX_BYTES + 1; Fd = -1; Buffer = malloc(BufferSize); if (Buffer == NULL) { Result = LXT_RESULT_FAILURE; LxtLogError("malloc failed"); goto ErrorExit; } LxtCheckResult(Fd = open(DEV_URANDOM, O_RDONLY)); LxtCheckResult(BytesRead = read(Fd, Buffer, BufferSize)); if (BytesRead > DEV_URANDOM_MAX_BYTES) { Result = LXT_RESULT_FAILURE; LxtLogError("BytesRead %d greater than expected %d", BytesRead, DEV_URANDOM_MAX_BYTES); goto ErrorExit; } Result = LXT_RESULT_SUCCESS; ErrorExit: if (Buffer != NULL) { free(Buffer); } if (Fd != -1) { LxtClose(Fd); } return Result; } int ProcfsRandom(PLXT_ARGS Args) { char Buffer[PROC_SYS_KERNEL_RANDOM_BYTES]; int BytesRead; int Fd; int Result; // // Test /proc/sys/kernel/random/uuid. // LxtCheckResult(Fd = open(PROC_SYS_KERNEL_RANDOM_UUID, O_RDONLY)); LxtCheckResult(BytesRead = read(Fd, Buffer, sizeof(Buffer))); LxtCheckEqual(PROC_SYS_KERNEL_RANDOM_BYTES, BytesRead, "%d"); LxtClose(Fd); Fd = -1; // // Test /proc/sys/kernel/random/boot_id. // LxtCheckResult(Fd = open(PROC_SYS_KERNEL_RANDOM_BOOTID, O_RDONLY)); LxtCheckResult(BytesRead = read(Fd, Buffer, sizeof(Buffer))); LxtCheckEqual(PROC_SYS_KERNEL_RANDOM_BYTES, BytesRead, "%d"); LxtClose(Fd); Fd = -1; // // Test /proc/sys/kernel/random/entropy_avail. // LxtCheckResult(Fd = open(PROC_SYS_KERNEL_RANDOM_ENTROPY_AVAIL, O_RDONLY)); LxtCheckResult(BytesRead = read(Fd, Buffer, (sizeof(Buffer) - 1))); LxtCheckEqual(5, BytesRead, "%d"); LxtClose(Fd); Fd = -1; // // Test /proc/sys/kernel/random/poolsize. // LxtCheckResult(Fd = open(PROC_SYS_KERNEL_RANDOM_POOLSIZE, O_RDONLY)); LxtCheckResult(BytesRead = read(Fd, Buffer, (sizeof(Buffer) - 1))); LxtCheckEqual(5, BytesRead, "%d"); Buffer[BytesRead] = '\0'; LxtCheckStringEqual(Buffer, "4096\n"); LxtClose(Fd); Fd = -1; ErrorExit: if (Fd != -1) { LxtClose(Fd); } return Result; }