diff --git a/include/nhmd4.h b/include/nhmd4.h new file mode 100644 index 000000000..42b29ea2d --- /dev/null +++ b/include/nhmd4.h @@ -0,0 +1,34 @@ +/* NetHack 3.7 nhmd4.h $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */ +/*- Copyright (c) Kenneth Lorber, Kensington, Maryland, 2024 */ +/* NetHack may be freely redistributed. See license for details. */ + +// Derived from: +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, + * Inc. MD4 Message-Digest Algorithm. + * + * Written by Solar Designer in 2001, and placed in + * the public domain. See md4.c for more information. + */ + +#ifndef __NHMD4_H +#define __NHMD4_H + +#define NHMD4_DIGEST_LENGTH 128 +#define NHMD4_RESULTLEN (128/8) + +typedef uint32_t quint32; + +struct nhmd4_context { + quint32 lo, hi; + quint32 a, b, c, d; + unsigned char buffer[64]; + quint32 block[NHMD4_RESULTLEN]; +}; +typedef struct nhmd4_context NHMD4_CTX; + +extern void nhmd4_init(struct nhmd4_context *ctx); +extern void nhmd4_update(struct nhmd4_context *ctx, const unsigned char *data, size_t size); +extern void nhmd4_final(struct nhmd4_context *ctx, unsigned char result[NHMD4_RESULTLEN]); + +#endif diff --git a/src/end.c b/src/end.c index 0e7561666..9289db604 100644 --- a/src/end.c +++ b/src/end.c @@ -264,16 +264,16 @@ NH_abort(char *why USED_FOR_CRASHREPORT) # endif # endif # ifdef __linux__ -# include +# include "nhmd4.h" # define HASH_CONTEXTPTR(CTXP) \ - unsigned char tmp[MD4_DIGEST_LENGTH]; \ - MD4_CTX CTXP ## _; \ - MD4_CTX *CTXP = &CTXP ## _ -# define HASH_INIT(ctxp) !MD4_Init(ctxp) -# define HASH_UPDATE(ctx, ptr, len) !MD4_Update(ctx, ptr, len) -# define HASH_FINISH(ctxp) !MD4_Final(tmp, ctxp) -# define HASH_RESULT_SIZE(ctxp) MD4_DIGEST_LENGTH -# define HASH_RESULT(ctx, inp) *inp = (unsigned char *)ctx + unsigned char tmp[NHMD4_DIGEST_LENGTH]; \ + NHMD4_CTX CTXP ## _; \ + NHMD4_CTX *CTXP = &CTXP ## _ +# define HASH_INIT(ctxp) (nhmd4_init(ctxp),0) +# define HASH_UPDATE(ctx, ptr, len) (nhmd4_update(ctx, ptr, len),0) +# define HASH_FINISH(ctxp) (nhmd4_final(ctxp, tmp),0) +# define HASH_RESULT_SIZE(ctxp) NHMD4_RESULTLEN +# define HASH_RESULT(ctx, inp) *inp = tmp # define HASH_CLEANUP(ctxp) # define HASH_OFLAGS O_RDONLY # define HASH_BINFILE_DECL char binfile[PATH_MAX+1]; diff --git a/src/nhmd4.c b/src/nhmd4.c new file mode 100644 index 000000000..a6f14896e --- /dev/null +++ b/src/nhmd4.c @@ -0,0 +1,268 @@ +/* NetHack 3.7 nhmd4.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */ +/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2024 */ +/* NetHack may be freely redistributed. See license for details. */ + +// Derived from: +/* + * MD4 (RFC-1320) message digest. + * Modified from MD5 code by Andrey Panin + * + * Written by Solar Designer in 2001, and placed in + * the public domain. There's absolutely no warranty. + * + * This differs from Colin Plumb's older public domain implementation in + * that no 32-bit integer data type is required, there's no compile-time + * endianness configuration, and the function prototypes match OpenSSL's. + * The primary goals are portability and ease of use. + * + * This implementation is meant to be fast, but not as fast as possible. + * Some known optimizations are not included to reduce source code size + * and avoid compile-time configuration. + */ +#include "hack.h" +#ifdef CRASHREPORT + +#include "nhmd4.h" + +/* + * The basic MD4 functions. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* + * The MD4 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, s) \ + (a) += f((b), (c), (d)) + (x); \ + (a) = ((a) << (s)) | ((a) >> (32 - (s))) + + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures which tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) +#define SET(n) \ + (*(const quint32 *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (quint32)ptr[(n) * 4] | \ + ((quint32)ptr[(n) * 4 + 1] << 8) | \ + ((quint32)ptr[(n) * 4 + 2] << 16) | \ + ((quint32)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There're no alignment requirements. + */ +static const unsigned char *body(struct nhmd4_context *ctx, const unsigned char *data, size_t size) +{ + const unsigned char *ptr; + quint32 a, b, c, d; + quint32 saved_a, saved_b, saved_c, saved_d; + + ptr = data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET( 0), 3); + STEP(F, d, a, b, c, SET( 1), 7); + STEP(F, c, d, a, b, SET( 2), 11); + STEP(F, b, c, d, a, SET( 3), 19); + + STEP(F, a, b, c, d, SET( 4), 3); + STEP(F, d, a, b, c, SET( 5), 7); + STEP(F, c, d, a, b, SET( 6), 11); + STEP(F, b, c, d, a, SET( 7), 19); + + STEP(F, a, b, c, d, SET( 8), 3); + STEP(F, d, a, b, c, SET( 9), 7); + STEP(F, c, d, a, b, SET(10), 11); + STEP(F, b, c, d, a, SET(11), 19); + + STEP(F, a, b, c, d, SET(12), 3); + STEP(F, d, a, b, c, SET(13), 7); + STEP(F, c, d, a, b, SET(14), 11); + STEP(F, b, c, d, a, SET(15), 19); +/* Round 2 */ + STEP(G, a, b, c, d, GET( 0) + 0x5A827999, 3); + STEP(G, d, a, b, c, GET( 4) + 0x5A827999, 5); + STEP(G, c, d, a, b, GET( 8) + 0x5A827999, 9); + STEP(G, b, c, d, a, GET(12) + 0x5A827999, 13); + + STEP(G, a, b, c, d, GET( 1) + 0x5A827999, 3); + STEP(G, d, a, b, c, GET( 5) + 0x5A827999, 5); + STEP(G, c, d, a, b, GET( 9) + 0x5A827999, 9); + STEP(G, b, c, d, a, GET(13) + 0x5A827999, 13); + + STEP(G, a, b, c, d, GET( 2) + 0x5A827999, 3); + STEP(G, d, a, b, c, GET( 6) + 0x5A827999, 5); + STEP(G, c, d, a, b, GET(10) + 0x5A827999, 9); + STEP(G, b, c, d, a, GET(14) + 0x5A827999, 13); + + STEP(G, a, b, c, d, GET( 3) + 0x5A827999, 3); + STEP(G, d, a, b, c, GET( 7) + 0x5A827999, 5); + STEP(G, c, d, a, b, GET(11) + 0x5A827999, 9); + STEP(G, b, c, d, a, GET(15) + 0x5A827999, 13); +/* Round 3 */ + STEP(H, a, b, c, d, GET( 0) + 0x6ED9EBA1, 3); + STEP(H, d, a, b, c, GET( 8) + 0x6ED9EBA1, 9); + STEP(H, c, d, a, b, GET( 4) + 0x6ED9EBA1, 11); + STEP(H, b, c, d, a, GET(12) + 0x6ED9EBA1, 15); + + STEP(H, a, b, c, d, GET( 2) + 0x6ED9EBA1, 3); + STEP(H, d, a, b, c, GET(10) + 0x6ED9EBA1, 9); + STEP(H, c, d, a, b, GET( 6) + 0x6ED9EBA1, 11); + STEP(H, b, c, d, a, GET(14) + 0x6ED9EBA1, 15); + + STEP(H, a, b, c, d, GET( 1) + 0x6ED9EBA1, 3); + STEP(H, d, a, b, c, GET( 9) + 0x6ED9EBA1, 9); + STEP(H, c, d, a, b, GET( 5) + 0x6ED9EBA1, 11); + STEP(H, b, c, d, a, GET(13) + 0x6ED9EBA1, 15); + + STEP(H, a, b, c, d, GET( 3) + 0x6ED9EBA1, 3); + STEP(H, d, a, b, c, GET(11) + 0x6ED9EBA1, 9); + STEP(H, c, d, a, b, GET( 7) + 0x6ED9EBA1, 11); + STEP(H, b, c, d, a, GET(15) + 0x6ED9EBA1, 15); + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +void nhmd4_init(struct nhmd4_context *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +void nhmd4_update(struct nhmd4_context *ctx, const unsigned char *data, size_t size) +{ + /* @UNSAFE */ + quint32 saved_lo; + unsigned long used, free; + + saved_lo = ctx->lo; + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += (quint32)(size >> 29); + + used = saved_lo & 0x3f; + + if (used) { + free = 64 - used; + + if (size < free) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, free); + data = (const unsigned char *) data + free; + size -= free; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +void nhmd4_final(struct nhmd4_context *ctx, unsigned char result[NHMD4_RESULTLEN]) +{ + /* @UNSAFE */ + unsigned long used, free; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + free = 64 - used; + + if (free < 8) { + memset(&ctx->buffer[used], 0, free); + body(ctx, ctx->buffer, 64); + used = 0; + free = 64; + } + + memset(&ctx->buffer[used], 0, free - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = ctx->lo; + ctx->buffer[57] = ctx->lo >> 8; + ctx->buffer[58] = ctx->lo >> 16; + ctx->buffer[59] = ctx->lo >> 24; + ctx->buffer[60] = ctx->hi; + ctx->buffer[61] = ctx->hi >> 8; + ctx->buffer[62] = ctx->hi >> 16; + ctx->buffer[63] = ctx->hi >> 24; + + body(ctx, ctx->buffer, 64); + + result[0] = ctx->a; + result[1] = ctx->a >> 8; + result[2] = ctx->a >> 16; + result[3] = ctx->a >> 24; + result[4] = ctx->b; + result[5] = ctx->b >> 8; + result[6] = ctx->b >> 16; + result[7] = ctx->b >> 24; + result[8] = ctx->c; + result[9] = ctx->c >> 8; + result[10] = ctx->c >> 16; + result[11] = ctx->c >> 24; + result[12] = ctx->d; + result[13] = ctx->d >> 8; + result[14] = ctx->d >> 16; + result[15] = ctx->d >> 24; + + memset(ctx, 0, sizeof(*ctx)); +} + +#undef F +#undef G +#undef H + +#endif diff --git a/sys/unix/Makefile.src b/sys/unix/Makefile.src index 3615da20c..06570fe2b 100644 --- a/sys/unix/Makefile.src +++ b/sys/unix/Makefile.src @@ -501,7 +501,7 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ lock.c mail.c makemon.c mcastu.c mdlib.c mhitm.c \ mhitu.c minion.c mklev.c mkmap.c mkmaze.c mkobj.c mkroom.c mon.c \ mondata.c monmove.c monst.c mplayer.c mthrowu.c muse.c music.c \ - nhlua.c nhlsel.c nhlobj.c o_init.c objects.c objnam.c \ + nhlua.c nhlsel.c nhlobj.c nhmd4.c o_init.c objects.c objnam.c \ options.c pager.c pickup.c pline.c polyself.c potion.c pray.c \ priest.c quest.c questpgr.c read.c rect.c region.c restore.c \ rip.c rnd.c role.c rumors.c save.c sfstruct.c \ @@ -550,7 +550,7 @@ HACKINCL = align.h artifact.h artilist.h attrib.h botl.h \ display.h dlb.h dungeon.h engrave.h extern.h flag.h fnamesiz.h \ func_tab.h global.h warnings.h hack.h lint.h mextra.h mfndpos.h \ micro.h mkroom.h monattk.h mondata.h monflag.h monst.h monsters.h \ - obj.h objects.h objclass.h optlist.h patchlevel.h pcconf.h \ + nhmd4.h obj.h objects.h objclass.h optlist.h patchlevel.h pcconf.h \ permonst.h prop.h rect.h region.h sym.h defsym.h rm.h sp_lev.h \ spell.h sndprocs.h seffects.h sys.h tcap.h timeout.h \ tradstdc.h trap.h unixconf.h vision.h vmsconf.h wintty.h wincurs.h \ @@ -586,7 +586,8 @@ HOBJ = $(TARGETPFX)allmain.o $(TARGETPFX)alloc.o \ $(TARGETPFX)mondata.o $(TARGETPFX)monmove.o $(TARGETPFX)monst.o \ $(TARGETPFX)mplayer.o $(TARGETPFX)mthrowu.o $(TARGETPFX)muse.o \ $(TARGETPFX)music.o $(TARGETPFX)nhlua.o $(TARGETPFX)nhlsel.o \ - $(TARGETPFX)nhlobj.o $(TARGETPFX)objects.o $(TARGETPFX)o_init.o \ + $(TARGETPFX)nhlobj.o $(TARGETPFX)nhmd4.o \ + $(TARGETPFX)objects.o $(TARGETPFX)o_init.o \ $(TARGETPFX)objnam.o $(TARGETPFX)options.o $(TARGETPFX)pager.o \ $(TARGETPFX)pickup.o $(TARGETPFX)pline.o $(TARGETPFX)polyself.o \ $(TARGETPFX)potion.o $(TARGETPFX)pray.o $(TARGETPFX)priest.o \ diff --git a/sys/unix/hints/linux.370 b/sys/unix/hints/linux.370 index 88acf06df..b32d26fc0 100755 --- a/sys/unix/hints/linux.370 +++ b/sys/unix/hints/linux.370 @@ -110,30 +110,6 @@ endif #HAVE_NCURSESW endif #MAKEFILE_SRC endif #USE_CURSESLIB -# autodetect missing openssl header needed for CRASHREPORT -# Note: makedefs isn't ready if we're cross-compiling. -# Also note: mdgrep.h _really_ needs to be up-to-date to -# get through this correctly if makedefs does exist. - -CRTEST=$(shell ls ../util/makedefs 2>/dev/null | wc -l) -ifeq "$(CRTEST)" "0" - # If makedefs doesn't exist, force the tests to fail -CRI=9 -CRC=9 -else - # If makedefs does exist, see if we can handle CRASHREPORT -CRI=$(shell ls /usr/include/openssl/md4.h 2>/dev/null | wc -l ) -CRC=$(shell (../util/makedefs --grep-defined CROSSCOMPILE && echo 1 ) || echo 0) -endif - -ifeq "$(CRI)$(CRC)" "10" - # If we can handle CRASHREPORT, see if it's been requested -AUTOLIBS=$(shell (../util/makedefs --grep-defined CRASHREPORT && echo "-lcrypto" ) || true ) -else - # Otherwise force it off regardless of config.h -NHCFLAGS+=-DNOCRASHREPORT -endif - # NetHack sources control NHCFLAGS+=-DDLB NHCFLAGS+=-DHACKDIR=\"$(HACKDIR)\" @@ -351,13 +327,6 @@ endif #?WANT_SOURCE_INSTALL INSTDIR=$(HACKDIR) VARDIR = $(HACKDIR) -#======= XXX can this go away? -#POSTINSTALL+= cp -n sys/unix/sysconf $(INSTDIR)/sysconf; \ -# $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; \ -# $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; \ -# chmod $(VARFILEPERM) $(INSTDIR)/sysconf; -#>>>>>>> keni-wincw2 - ifneq "$(CCISCLANG)" "" # gdb may not be installed if clang is chosen compiler so the game # won't start in that case due to a sysconf error. Comment out