diff --git a/include/extern.h b/include/extern.h index 9bc4e5a24..24df9cd6a 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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)); diff --git a/include/integer.h b/include/integer.h index d340e4177..9f16a592d 100644 --- a/include/integer.h +++ b/include/integer.h @@ -8,37 +8,46 @@ #define INTEGER_H #if defined(__STDC__) && __STDC_VERSION__ >= 199101L - /* The compiler claims to conform to C99. Use stdint.h */ #include +#define SKIP_STDINT_WORKAROUND +#else +# if defined(HAS_STDINT_H) +/* Some compilers have stdint.h but don't conform to all of C99. */ +#include +#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 */ diff --git a/include/ntconf.h b/include/ntconf.h index 6859d52b0..b681680d2 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -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 */ diff --git a/include/unixconf.h b/include/unixconf.h index 3e4748ea2..e4c23cd8d 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -420,6 +420,7 @@ # define DEV_RANDOM "/dev/random" # endif #endif +#define SYS_RANDOM_SEED #endif /* UNIXCONF_H */ #endif /* UNIX */ diff --git a/include/vmsconf.h b/include/vmsconf.h index 7674e8558..dfee1cb42 100644 --- a/include/vmsconf.h +++ b/include/vmsconf.h @@ -255,6 +255,7 @@ typedef __mode_t mode_t; #else #define Rand() rand() #endif +#define SYS_RANDOM_SEED #ifndef __GNUC__ #ifndef bcopy diff --git a/src/hacklib.c b/src/hacklib.c index 74a326efd..f70a4440f 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -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 } diff --git a/src/rnd.c b/src/rnd.c index 9745d9ef2..67f2e4012 100644 --- a/src/rnd.c +++ b/src/rnd.c @@ -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... */ diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index f798fa163..ac6d3c290 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -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*/ diff --git a/sys/vms/vmsmain.c b/sys/vms/vmsmain.c index 75f321cb0..b3be6e4d1 100644 --- a/sys/vms/vmsmain.c +++ b/sys/vms/vmsmain.c @@ -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*/ diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index 6dcd10d4d..e41dcac05 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -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 diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index 035ea7457..b1f5b2b4d 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -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 /* 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*/