From 1f85bf954e92d9a13c3ac501d8efb55a2687ba10 Mon Sep 17 00:00:00 2001 From: TheTank20 Date: Mon, 9 Jun 2025 22:22:45 -0500 Subject: [PATCH] RNG bugfix for DOS (DJGPP) --- .github/workflows/dos-djgpp.yml | 4 +- src/cli.cpp | 4 +- src/libumskt/libumskt.cpp | 75 +++++++++++++++++++++++++++++++ src/libumskt/libumskt.h | 20 ++++++++- src/libumskt/pidgen3/BINK1998.cpp | 2 +- src/libumskt/pidgen3/BINK2002.cpp | 2 +- 6 files changed, 100 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dos-djgpp.yml b/.github/workflows/dos-djgpp.yml index 4a6d7a6..881e377 100644 --- a/.github/workflows/dos-djgpp.yml +++ b/.github/workflows/dos-djgpp.yml @@ -64,8 +64,8 @@ jobs: git clone https://github.com/UMSKT/openssl.git openssl pushd openssl source ${{ github.workspace }}/djgpp/setenv - ./Configure no-threads -DOPENSSL_DEV_NO_ATOMICS --prefix=${{ github.workspace }}/djgpp DJGPP - make && make install + ./Configure no-threads no-tests -DOPENSSL_DEV_NO_ATOMICS --prefix=${{ github.workspace }}/djgpp DJGPP + make && make install_sw popd - name: Build diff --git a/src/cli.cpp b/src/cli.cpp index d4ba941..1401392 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -423,7 +423,7 @@ int CLI::BINK1998Generate() { } else { // generate a random number to use as a serial BIGNUM *bnrand = BN_new(); - BN_rand(bnrand, 19, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY); + UMSKT::umskt_bn_rand(bnrand, 19, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY); int oRaw; char *cRaw = BN_bn2dec(bnrand); @@ -484,7 +484,7 @@ int CLI::BINK2002Generate() { // generate a key for (int i = 0; i < this->total; i++) { DWORD pAuthInfo; - RAND_bytes((BYTE *)&pAuthInfo, 4); + UMSKT::umskt_rand_bytes((BYTE *)&pAuthInfo, 4); pAuthInfo &= BITMASK(10); if (this->options.verbose) { diff --git a/src/libumskt/libumskt.cpp b/src/libumskt/libumskt.cpp index a41244c..753b2f7 100644 --- a/src/libumskt/libumskt.cpp +++ b/src/libumskt/libumskt.cpp @@ -58,3 +58,78 @@ FNEXPORT int PIDGEN2_GenerateRetail(char* channelID, char* &keyout) { FNEXPORT int PIDGEN2_GenerateOEM(char* year, char* day, char* oem, char* keyout) { return PIDGEN2::GenerateOEM(year, day, oem, keyout); } + +// RNG utility functions +int UMSKT::umskt_rand_bytes(unsigned char *buf, int num) { +#if UMSKT_RNG_DJGPP + // DOS-compatible RNG using DJGPP's random() function + static bool initialized = false; + if (!initialized) { + // Get initial seed from multiple sources for better entropy + struct timeval tv; + gettimeofday(&tv, NULL); + + // Combine microseconds with BIOS timer ticks + unsigned long ticks = *(volatile unsigned long *)0x0040001CL; + int seed = (int)((tv.tv_sec ^ tv.tv_usec) ^ (ticks * 100000)); + + // Initialize both random() and rand() with different seeds + srandom(seed); + srand(seed ^ 0x1234ABCD); // Use a different seed for rand + + initialized = true; + } + + for (int i = 0; i < num; i++) { + // Use random() for better randomness, especially in lower bits + buf[i] = (unsigned char)(random() & 0xFF); + + // Mix in rand() as an additional source + buf[i] ^= (unsigned char)(rand() & 0xFF); + } + return 1; +#else + // Use OpenSSL's RAND_bytes for non-DOS systems + return RAND_bytes(buf, num); +#endif +} + +int UMSKT::umskt_bn_rand(BIGNUM *rnd, int bits, int top, int bottom) { +#if UMSKT_RNG_DJGPP + // DOS-compatible RNG implementation for BIGNUMs + unsigned char *buf = (unsigned char *)malloc((bits + 7) / 8); + if (!buf) return 0; + + // Generate random bytes + umskt_rand_bytes(buf, (bits + 7) / 8); + + // Convert to BIGNUM + if (!BN_bin2bn(buf, (bits + 7) / 8, rnd)) { + free(buf); + return 0; + } + + free(buf); + + // Apply top/bottom constraints like BN_rand does + if (top != -1) { + if (top) { + if (bits == 0) { + BN_zero(rnd); + return 1; + } + BN_set_bit(rnd, bits - 1); + } + BN_mask_bits(rnd, bits); + } + + if (bottom) { + BN_set_bit(rnd, 0); + } + + return 1; +#else + // Use OpenSSL's BN_rand for non-DOS systems + return BN_rand(rnd, bits, top, bottom); +#endif +} diff --git a/src/libumskt/libumskt.h b/src/libumskt/libumskt.h index e01d768..293ca0a 100644 --- a/src/libumskt/libumskt.h +++ b/src/libumskt/libumskt.h @@ -38,6 +38,10 @@ #include #include +#ifdef __DJGPP__ +#include +#endif + // Algorithm macros #define PK_LENGTH 25 #define NULL_TERMINATOR 1 @@ -59,6 +63,17 @@ #define BYDWORD(n) (DWORD)(*((n) + 0) | *((n) + 1) << 8 | *((n) + 2) << 16 | *((n) + 3) << 24) #define BITMASK(n) ((1ULL << (n)) - 1) +// RNG utility functions +#ifdef __DJGPP__ +#define UMSKT_RNG_DJGPP 1 +extern "C" { + long int random(void); + int srandom(int seed); +} +#else +#define UMSKT_RNG_DJGPP 0 +#endif + class UMSKT { public: static std::FILE* debug; @@ -67,7 +82,10 @@ public: class ConfigurationID; static void setDebugOutput(std::FILE* input); + + // RNG utility functions + static int umskt_rand_bytes(unsigned char *buf, int num); + static int umskt_bn_rand(BIGNUM *rnd, int bits, int top, int bottom); }; - #endif //UMSKT_LIBUMSKT_H diff --git a/src/libumskt/pidgen3/BINK1998.cpp b/src/libumskt/pidgen3/BINK1998.cpp index dc40cbb..81c1736 100644 --- a/src/libumskt/pidgen3/BINK1998.cpp +++ b/src/libumskt/pidgen3/BINK1998.cpp @@ -201,7 +201,7 @@ void PIDGEN3::BINK1998::Generate( EC_POINT *r = EC_POINT_new(eCurve); // Generate a random number c consisting of 384 bits without any constraints. - BN_rand(c, FIELD_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY); + UMSKT::umskt_bn_rand(c, FIELD_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY); // Pick a random derivative of the base point on the elliptic curve. // R = cG; diff --git a/src/libumskt/pidgen3/BINK2002.cpp b/src/libumskt/pidgen3/BINK2002.cpp index 2246f97..73b6e07 100644 --- a/src/libumskt/pidgen3/BINK2002.cpp +++ b/src/libumskt/pidgen3/BINK2002.cpp @@ -236,7 +236,7 @@ void PIDGEN3::BINK2002::Generate( EC_POINT *r = EC_POINT_new(eCurve); // Generate a random number c consisting of 512 bits without any constraints. - BN_rand(c, FIELD_BITS_2003, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY); + UMSKT::umskt_bn_rand(c, FIELD_BITS_2003, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY); // R = cG EC_POINT_mul(eCurve, r, nullptr, basePoint, c, numContext);