some system-specific adjustments for RNG routines

move some system-specific seed-related stuff from hacklib.c to
a system-specific source file and #define SYS_RANDOM_SEED to
utilize it during build.

Windows changes for random seed generation using
crypto next gen (CNG) api routines.

Corresponding vms changes due to disentangling of VMS and
unix when the unix seed bits got moved (untested).
This commit is contained in:
nhmall
2019-01-13 20:54:11 -05:00
committed by Patric Mueller
parent f9433b2a87
commit 6c114640f5
11 changed files with 161 additions and 58 deletions

View File

@@ -2106,6 +2106,7 @@ E void FDECL(genl_outrip, (winid, int, time_t));
#ifdef USE_ISAAC64
E void FDECL(init_isaac64, (unsigned long));
E long NDECL(nhrand);
#endif
E int FDECL(rn2, (int));
E int FDECL(rnl, (int));

View File

@@ -8,37 +8,46 @@
#define INTEGER_H
#if defined(__STDC__) && __STDC_VERSION__ >= 199101L
/* The compiler claims to conform to C99. Use stdint.h */
#include <stdint.h>
#define SKIP_STDINT_WORKAROUND
#else
# if defined(HAS_STDINT_H)
/* Some compilers have stdint.h but don't conform to all of C99. */
#include <stdint.h>
#define SKIP_STDINT_WORKAROUND
# endif
#endif
#ifndef SKIP_STDINT_WORKAROUND /* !C99 */
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
#if defined(__WATCOMC__) && !defined(__386__)
/* Open Watcom providing a 16 bit build for MS-DOS or OS/2 */
/* int is 16 bits; use long for 32 bits */
typedef long int32_t;
typedef unsigned long uint32_t;
#else
/* Otherwise, assume either a 32- or 64-bit compiler */
/* long may be 64 bits; use int for 32 bits */
typedef int int32_t;
typedef unsigned int uint32_t;
#endif
typedef long long int64_t;
typedef unsigned long long uint64_t;
#endif /* !C99 */
/* Provide uint8, int16, uint16, int32, uint32, int64 and uint64 */
typedef uint8_t uint8;
typedef int16_t int16;
typedef uint16_t uint16;
typedef int32_t int32;
typedef uint32_t uint32;
#else /* !C99 */
/* Provide uint8, int16, uint16, int32 and uint32 */
typedef unsigned char uint8;
typedef short int16;
typedef unsigned short uint16;
#if defined(__WATCOMC__) && !defined(__386__)
/* Open Watcom providing a 16 bit build for MS-DOS or OS/2 */
/* int is 16 bits; use long for 32 bits */
typedef long int32;
typedef unsigned long uint32;
#else
/* Otherwise, assume either a 32- or 64-bit compiler */
/* long may be 64 bits; use int for 32 bits */
typedef int int32;
typedef unsigned int uint32;
#endif
typedef unsigned long uint32_t;
typedef unsigned long long uint64_t;
#endif /* !C99 */
typedef int64_t int64;
typedef uint64_t uint64;
#endif /* INTEGER_H */

View File

@@ -7,7 +7,9 @@
/* #define SHELL */ /* nt use of pcsys routines caused a hang */
#define RANDOM /* have Berkeley random(3) */
/* #define RANDOM */ /* have Berkeley random(3) */
#define USE_ISAAC64
#define TEXTCOLOR /* Color text */
#define EXEPATH /* Allow .exe location to be used as HACKDIR */
@@ -25,8 +27,7 @@
game */
#define SYSCF /* Use a global configuration */
#define SYSCF_FILE "sysconf" /* Use a file to hold the SYSCF configuration \
*/
#define SYSCF_FILE "sysconf" /* Use a file to hold the SYSCF configuration */
#define DUMPLOG /* Enable dumplog files */
/*#define DUMPLOG_FILE "nethack-%n-%d.log"*/
@@ -35,9 +36,9 @@
#define USER_SOUNDS
/*#define CHANGE_COLOR*/ /* allow palette changes */
#define SELECTSAVED /* Provide menu of saved games to choose from at start \
*/
#define SELECTSAVED /* Provide menu of saved games to choose from at start */
#define SYS_RANDOM_SEED /* Use random seed derived from CNG */
/*
* -----------------------------------------------------------------
* The remaining code shouldn't need modification.
@@ -131,6 +132,7 @@ extern void FDECL(interject, (int));
/* suppress a warning in cppregex.cpp */
#pragma warning(disable : 4101) /* unreferenced local variable */
#endif
#define HAS_STDINT_H /* force include of stdint.h in integer.h */
#endif /* _MSC_VER */
/* The following is needed for prototypes of certain functions */

View File

@@ -420,6 +420,7 @@
# define DEV_RANDOM "/dev/random"
# endif
#endif
#define SYS_RANDOM_SEED
#endif /* UNIXCONF_H */
#endif /* UNIX */

View File

@@ -255,6 +255,7 @@ typedef __mode_t mode_t;
#else
#define Rand() rand()
#endif
#define SYS_RANDOM_SEED
#ifndef __GNUC__
#ifndef bcopy

View File

@@ -51,6 +51,8 @@
boolean fuzzymatch (const char *, const char *,
const char *, boolean)
void setrandom (void)
void init_random (void)
void reseed_random (void)
time_t getnow (void)
int getyear (void)
char * yymmdd (time_t)
@@ -848,34 +850,20 @@ extern struct tm *FDECL(localtime, (time_t *));
#endif
STATIC_DCL struct tm *NDECL(getlt);
#ifdef SYS_RANDOM_SEED
extern unsigned long NDECL(sys_random_seed);
#endif
/* Returns a number suitable as seed for the random number generator. */
static unsigned long
get_random_seed()
{
unsigned long seed = 0;
#ifdef DEV_RANDOM
FILE *fptr = NULL;
fptr = fopen(DEV_RANDOM, "r");
if (fptr) {
fread(&seed, sizeof(long), 1, fptr);
}
fclose(fptr);
#ifdef SYS_RANDOM_SEED
/* Platform-specific seed if one is provided */
seed = sys_random_seed();
#else
seed = (unsigned long) getnow(); /* time((TIME_type) 0) */
# if defined(UNIX) || defined(VMS)
{
unsigned long pid = (unsigned long) getpid();
/* Quick dirty band-aid to prevent PRNG prediction */
if (pid) {
if (!(pid & 3L))
pid -= 1L;
seed *= pid;
}
}
# endif
#endif
return seed;
}
@@ -927,7 +915,7 @@ reseed_random()
{
/* only reseed if we are certain that the seed generation is unguessable
* by the players. */
#ifdef DEV_RANDOM
#if defined(SYS_RANDOM_SEED)
init_random();
#endif
}

View File

@@ -27,6 +27,7 @@ RND(int x)
{
return (isaac64_next_uint64(&rng_state) % x);
}
#else
/* "Rand()"s definition is determined by [OS]conf.h */
#if defined(LINT) && defined(UNIX) /* rand() is long... */

View File

@@ -765,4 +765,31 @@ error:
}
#endif
#ifdef SYS_RANDOM_SEED
unsigned long
sys_random_seed()
{
unsigned long seed;
unsigned long pid = (unsigned long) getpid();
#ifdef DEV_RANDOM
FILE *fptr = NULL;
fptr = fopen(DEV_RANDOM, "r");
if (fptr) {
fread(&seed, sizeof(long), 1, fptr);
}
fclose(fptr);
#else
seed = (unsigned long) getnow(); /* time((TIME_type) 0) */
/* Quick dirty band-aid to prevent PRNG prediction */
if (pid) {
if (!(pid & 3L))
pid -= 1L;
seed *= pid;
}
#endif
return seed;
}
#endif /* SYS_RANDOM_SEED */
/*unixmain.c*/

View File

@@ -465,4 +465,22 @@ wd_message()
You("are in non-scoring explore/discovery mode.");
}
#ifdef SYS_RANDOM_SEED
unsigned long
sys_random_seed()
{
unsigned long seed;
unsigned long pid = (unsigned long) getpid();
seed = (unsigned long) getnow(); /* time((TIME_type) 0) */
/* Quick dirty band-aid to prevent PRNG prediction */
if (pid) {
if (!(pid & 3L))
pid -= 1L;
seed *= pid;
}
return seed;
}
#endif
/*vmsmain.c*/

View File

@@ -73,8 +73,8 @@ DEBUGINFO = Y
# PDCurses header (.h) files and PDCURSES_C to the location
# of your PDCurses C files.
#
#ADD_CURSES=Y
#PDCURSES_TOP=..\..\pdcurses
ADD_CURSES=Y
PDCURSES_TOP=..\..\pdcurses
#
#==============================================================================
# This marks the end of the BUILD DECISIONS section.
@@ -129,9 +129,13 @@ OBJ = o
# (see pcconf.h). Set to nothing if not used.
#
RANDOM = $(OBJ)\random.o
RANDOM = $(OBJ)\isaac64.o
#RANDOM = $(OBJ)\random.o
#RANDOM =
BCRYPT=
! IF ("$(RANDOM)"=="$(OBJ)\isaac64.o")
BCRYPT=bcrypt.lib
! ENDIF
WINPFLAG= -DTILES -DMSWIN_GRAPHICS -DWIN32CON
# To store all the level files,
@@ -801,7 +805,7 @@ $(GAMEDIR)\NetHack.exe : $(O)gamedir.tag $(PDCLIB) $(O)tile.o $(O)nttty.o $(O)gu
@if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR)
@echo Linking $(@:\=/)
$(link) $(lflagsBuild) $(conlflags) /STACK:2048 /PDB:$(GAMEDIR)\$(@B).PDB /MAP:$(O)$(@B).MAP \
$(LIBS) $(PDCLIB) $(conlibs) -out:$@ @<<$(@B).lnk
$(LIBS) $(PDCLIB) $(conlibs) $(BCRYPT) -out:$@ @<<$(@B).lnk
$(GAMEOBJ)
$(TTYOBJ)
$(O)nttty.o
@@ -824,7 +828,7 @@ $(GAMEDIR)\NetHackW.exe : $(O)gamedir.tag $(O)tile.o $(O)ttystub.o \
@if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR)
@echo Linking $(@:\=/)
$(link) $(lflagsBuild) $(guilflags) /STACK:2048 /PDB:$(GAMEDIR)\$(@B).PDB \
/MAP:$(O)$(@B).MAP $(LIBS) $(PDCLIB) $(guilibs) $(COMCTRL) -out:$@ @<<$(@B).lnk
/MAP:$(O)$(@B).MAP $(LIBS) $(PDCLIB) $(guilibs) $(COMCTRL) $(BCRYPT) -out:$@ @<<$(@B).lnk
$(GAMEOBJ)
$(GUIOBJ)
$(O)tile.o
@@ -1514,6 +1518,8 @@ $(O)tos.o: ..\sys\atari\tos.c $(HACK_H) $(INCL)\tcap.h
@$(CC) $(cflagsBuild) -Fo$@ ..\sys\atari\tos.c
$(O)pctty.o: ..\sys\share\pctty.c $(HACK_H)
@$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\pctty.c
$(O)isaac64.o: ..\src\isaac64.c $(HACK_H) $(INCL)\isaac64.h $(INCL)\integer.h
@$(CC) $(cflagsBuild) -Fo$@ ..\src\isaac64.c
$(O)random.o: ..\sys\share\random.c $(HACK_H)
@$(CC) $(cflagsBuild) -Fo$@ ..\sys\share\random.c
$(O)ioctl.o: ..\sys\share\ioctl.c $(HACK_H) $(INCL)\tcap.h

View File

@@ -680,6 +680,55 @@ char *name;
}
return;
}
#ifdef SYS_RANDOM_SEED
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS 0
#endif
#ifndef STATUS_NOT_FOUND
#define STATUS_NOT_FOUND 0xC0000225
#endif
#ifndef STATUS_UNSUCCESSFUL
#define STATUS_UNSUCCESSFUL 0xC0000001
#endif
#include <bcrypt.h> /* Windows Crypto Next Gen (CNG) */
unsigned long
sys_random_seed(VOID_ARGS)
{
unsigned long ourseed = 0UL;
BCRYPT_ALG_HANDLE hRa = (BCRYPT_ALG_HANDLE) 0;
NTSTATUS status = STATUS_UNSUCCESSFUL;
boolean Plan_B = TRUE;
status = BCryptOpenAlgorithmProvider(&hRa, BCRYPT_RNG_ALGORITHM,
(LPCWSTR) 0, 0);
if (hRa && status == STATUS_SUCCESS) {
status = BCryptGenRandom(hRa, (PUCHAR) &ourseed,
(ULONG) sizeof ourseed, 0);
if (status == STATUS_SUCCESS) {
BCryptCloseAlgorithmProvider(hRa,0);
Plan_B = FALSE;
}
}
if (Plan_B) {
time_t datetime = 0;
const char *emsg;
if (status == STATUS_NOT_FOUND)
emsg = "BCRYPT_RNG_ALGORITHM not avail, falling back";
else
emsg = "Other failure than algorithm not avail";
paniclog("sys_random_seed", emsg); /* leaves clue, doesn't exit */
(void) time(&datetime);
ourseed = (unsigned long) datetime;
}
return ourseed;
}
#endif /* SYS_RANDOM_SEED */
#endif /* WIN32 */
/*winnt.c*/