From 3bf9df6b2785fa6d951086978a3e66f49427166a Mon Sep 17 00:00:00 2001 From: FluorescentCIAAfricanAmerican <0934gj3049fk@protonmail.com> Date: Wed, 22 Apr 2020 12:56:21 -0400 Subject: 1 --- engine/checksum_engine.cpp | 415 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100644 engine/checksum_engine.cpp (limited to 'engine/checksum_engine.cpp') diff --git a/engine/checksum_engine.cpp b/engine/checksum_engine.cpp new file mode 100644 index 0000000..9c06cd6 --- /dev/null +++ b/engine/checksum_engine.cpp @@ -0,0 +1,415 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Engine specific CRC functions +// +//=============================================================================// + + +#include "checksum_engine.h" +#include "bspfile.h" +#include "filesystem.h" +#include "filesystem_engine.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// Purpose: For proxy protecting +// Turns the passed data into a +// single byte block CRC based on current network sequence number. +// Input : *base - +// length - +// sequence - +// Output : byte COM_BlockSequenceCRCByte +//----------------------------------------------------------------------------- +byte COM_BlockSequenceCRCByte( byte *base, int length, int sequence ) +{ + CRC32_t crc; + byte *p; + byte chkb[60 + 4]; + + if (sequence < 0) + { + Sys_Error("sequence < 0, in COM_BlockSequenceCRCByte\n"); + } + + CRC32_t entry; + entry = CRC32_GetTableEntry( ( sequence + 1 ) % ( 256 * sizeof(CRC32_t) - 4 ) ); + p = (byte *)&entry; + + // Use up to the first 60 bytes of data and a 4 byte value from the + // CRC lookup table (divided into the sequence) + + if (length > 60) + { + length = 60; + } + + memcpy (chkb, base, length); + + chkb[length+0] = p[0]; + chkb[length+1] = p[1]; + chkb[length+2] = p[2]; + chkb[length+3] = p[3]; + + length += 4; + + // Compute a crc based on the buffer. + CRC32_Init(&crc); + CRC32_ProcessBuffer(&crc, chkb, length); + CRC32_Final(&crc); + + // Chop down to byte size + return (byte)(crc & 0xFF); +} + +// YWB: 5/18 +/* +=================== +bool CRC_File(unsigned short *crcvalue, char *pszFileName) + + Computes CRC for given file. If there is an error opening/reading the file, returns false, + otherwise returns true and sets the crc value passed to it. The value should be initialized + with CRC_Init + ================== + */ +bool CRC_File(CRC32_t *crcvalue, const char *pszFileName) +{ + // Always re-init the CRC buffer + CRC32_Init( crcvalue ); + + FileHandle_t fp; + byte chunk[1024]; + int nBytesRead; + + int nSize; + + nSize = COM_OpenFile(pszFileName, &fp); + if ( !fp || ( nSize == -1 ) ) + return FALSE; + + // Now read in 1K chunks + while (nSize > 0) + { + if (nSize > 1024) + nBytesRead = g_pFileSystem->Read(chunk, 1024, fp); + else + nBytesRead = g_pFileSystem->Read(chunk, nSize, fp); + + // If any data was received, CRC it. + if (nBytesRead > 0) + { + nSize -= nBytesRead; + CRC32_ProcessBuffer(crcvalue, chunk, nBytesRead); + } + + // We we are end of file, break loop and return + if ( g_pFileSystem->EndOfFile( fp ) ) + { + g_pFileSystem->Close( fp ); + fp = 0; + break; + } + // If there was a disk error, indicate failure. + else if ( nBytesRead <= 0 || !g_pFileSystem->IsOk(fp) ) + { + if ( fp ) + g_pFileSystem->Close(fp); + return FALSE; + } + } + + if ( fp ) + g_pFileSystem->Close(fp); + return TRUE; +} + +// YWB: 5/18 +/* +=================== +bool CRC_MapFile(unsigned short *crcvalue, char *pszFileName) + + Computes CRC for given map file. If there is an error opening/reading the file, returns false, + otherwise returns true and sets the crc value passed to it. The value should be initialized + with CRC_Init + + For map (.bsp) files, the entity lump is not included in the CRC. + //FIXME make this work + ================== + */ +bool CRC_MapFile(CRC32_t *crcvalue, const char *pszFileName) +{ + FileHandle_t fp; + byte chunk[1024]; + int i, l; + int nBytesRead; + dheader_t header; + int nSize; + lump_t *curLump; + long startOfs; + + nSize = COM_OpenFile(pszFileName, &fp); + if ( !fp || ( nSize == -1 ) ) + return false; + + startOfs = g_pFileSystem->Tell(fp); + + // Don't CRC the header. + if (g_pFileSystem->Read(&header, sizeof(dheader_t), fp) == 0) + { + ConMsg("Could not read BSP header for map [%s].\n", pszFileName); + g_pFileSystem->Close(fp); + return false; + } + + i = header.version; + if ( i < MINBSPVERSION || i > BSPVERSION ) + { + g_pFileSystem->Close(fp); + ConMsg("Map [%s] has incorrect BSP version (%i should be %i).\n", pszFileName, i, BSPVERSION); + return false; + } + + if ( IsX360() ) + { + // 360 bsp's store the pc checksum in the flags lump header + g_pFileSystem->Close(fp); + *crcvalue = header.lumps[LUMP_MAP_FLAGS].version; + return true; + } + + // CRC across all lumps except for the Entities lump + for (l = 0; l < HEADER_LUMPS; l++) + { + if (l == LUMP_ENTITIES) + continue; + + curLump = &header.lumps[l]; + nSize = curLump->filelen; + + g_pFileSystem->Seek( fp, startOfs + curLump->fileofs, FILESYSTEM_SEEK_HEAD ); + + // Now read in 1K chunks + while (nSize > 0) + { + if (nSize > 1024) + nBytesRead = g_pFileSystem->Read(chunk, 1024, fp); + else + nBytesRead = g_pFileSystem->Read(chunk, nSize, fp); + + // If any data was received, CRC it. + if (nBytesRead > 0) + { + nSize -= nBytesRead; + CRC32_ProcessBuffer(crcvalue, chunk, nBytesRead); + } + + // If there was a disk error, indicate failure. + if ( !g_pFileSystem->IsOk(fp) ) + { + if ( fp ) + g_pFileSystem->Close(fp); + return false; + } + } + } + + if ( fp ) + g_pFileSystem->Close(fp); + return true; +} + +bool MD5_MapFile(MD5Value_t *md5value, const char *pszFileName) +{ + FileHandle_t fp; + byte chunk[1024]; + int i, l; + int nBytesRead; + dheader_t header; + int nSize; + lump_t *curLump; + long startOfs; + + nSize = COM_OpenFile(pszFileName, &fp); + if ( !fp || ( nSize == -1 ) ) + return false; + + MD5Context_t ctx; + V_memset( &ctx, 0, sizeof(MD5Context_t) ); + MD5Init( &ctx ); + + startOfs = g_pFileSystem->Tell(fp); + + // Don't MD5 the header. + if (g_pFileSystem->Read(&header, sizeof(dheader_t), fp) == 0) + { + ConMsg("Could not read BSP header for map [%s].\n", pszFileName); + g_pFileSystem->Close(fp); + return false; + } + + i = header.version; + if ( i < MINBSPVERSION || i > BSPVERSION ) + { + g_pFileSystem->Close(fp); + ConMsg("Map [%s] has incorrect BSP version (%i should be %i).\n", pszFileName, i, BSPVERSION); + return false; + } + + if ( IsX360() ) + { + // 360 bsp's store the pc checksum in the flags lump header + g_pFileSystem->Close(fp); + char versionString[65] = {0}; + V_snprintf( versionString, ARRAYSIZE(versionString), "%d", header.lumps[LUMP_MAP_FLAGS].version ); + V_memcpy( md5value->bits, versionString, MD5_DIGEST_LENGTH ); + return true; + } + + // MD5 across all lumps except for the Entities lump + for (l = 0; l < HEADER_LUMPS; l++) + { + if (l == LUMP_ENTITIES) + continue; + + curLump = &header.lumps[l]; + nSize = curLump->filelen; + + g_pFileSystem->Seek( fp, startOfs + curLump->fileofs, FILESYSTEM_SEEK_HEAD ); + + // Now read in 1K chunks + while (nSize > 0) + { + if (nSize > 1024) + nBytesRead = g_pFileSystem->Read(chunk, 1024, fp); + else + nBytesRead = g_pFileSystem->Read(chunk, nSize, fp); + + // If any data was received, CRC it. + if (nBytesRead > 0) + { + nSize -= nBytesRead; + MD5Update( &ctx, chunk, nBytesRead ); + } + + // If there was a disk error, indicate failure. + if ( !g_pFileSystem->IsOk(fp) ) + { + if ( fp ) + g_pFileSystem->Close(fp); + return false; + } + } + } + + if ( fp ) + g_pFileSystem->Close(fp); + + MD5Final( md5value->bits, &ctx ); + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : digest[16] - +// *pszFileName - +// bSeed - +// seed[4] - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool MD5_Hash_File(unsigned char digest[16], const char *pszFileName, bool bSeed /* = FALSE */, unsigned int seed[4] /* = NULL */) +{ + FileHandle_t fp; + byte chunk[1024]; + int nBytesRead; + MD5Context_t ctx; + + int nSize; + + nSize = COM_OpenFile( pszFileName, &fp ); + if ( !fp || ( nSize == -1 ) ) + return false; + + memset(&ctx, 0, sizeof(MD5Context_t)); + + MD5Init(&ctx); + + if (bSeed) + { + // Seed the hash with the seed value + MD5Update( &ctx, (const unsigned char *)&seed[0], 16 ); + } + + // Now read in 1K chunks + while (nSize > 0) + { + if (nSize > 1024) + nBytesRead = g_pFileSystem->Read(chunk, 1024, fp); + else + nBytesRead = g_pFileSystem->Read(chunk, nSize, fp); + + // If any data was received, CRC it. + if (nBytesRead > 0) + { + nSize -= nBytesRead; + MD5Update(&ctx, chunk, nBytesRead); + } + + // We we are end of file, break loop and return + if ( g_pFileSystem->EndOfFile( fp ) ) + { + g_pFileSystem->Close( fp ); + fp = NULL; + break; + } + // If there was a disk error, indicate failure. + else if ( !g_pFileSystem->IsOk(fp) ) + { + if ( fp ) + g_pFileSystem->Close(fp); + return FALSE; + } + } + + if ( fp ) + g_pFileSystem->Close(fp); + + MD5Final(digest, &ctx); + + return TRUE; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool MD5_Hash_Buffer( unsigned char pDigest[16], const unsigned char *pBuffer, int nSize, bool bSeed /* = FALSE */, unsigned int seed[4] /* = NULL */ ) +{ + MD5Context_t ctx; + + if ( !pBuffer || !nSize ) + return false; + + memset( &ctx, 0, sizeof( MD5Context_t ) ); + MD5Init( &ctx ); + + if ( bSeed ) + { + // Seed the hash with the seed value + MD5Update( &ctx, (const unsigned char *)&seed[0], 16 ); + } + + // Now read in 1024 chunks + const unsigned char *pChunk = pBuffer; + while ( nSize > 0 ) + { + const int nChunkSize = MIN( 1024, nSize ); + MD5Update( &ctx, pChunk, nChunkSize ); + nSize -= nChunkSize; + pChunk += nChunkSize; AssertValidReadPtr( pChunk ); + } + + MD5Final( pDigest, &ctx ); + + return true; +} -- cgit v1.2.3