WSL/test/linux/unit_tests/random.c

272 lines
6.4 KiB
C

/*++
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <linux/random.h>
#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;
}