예제 #1
0
// Very simple/stupid MD5-based RNG that samples "entropy" from various PS2 control registers
static unsigned long rng_ps2(unsigned char *buf, unsigned long len, 
                             void (*callback)(void))
{
  static unsigned long lastx[2] = { 0xaab7cb4b2fd3b2b9, 0xcec58aff72afe49f }; // md5sum of bits.c
  unsigned long j;
  unsigned int samples[10];  // number of sample data sources
  int l;
  hash_state md;

  for (j = 0; j < len; j += sizeof(lastx)) {
    md5_init(&md);
    samples[0] = *T2_COUNT;
    samples[1] = *T3_COUNT;
    samples[2] = *IPU_TOP;
    samples[3] = *GIF_TAG0;
    samples[4] = *GIF_TAG1;
    samples[5] = *GIF_TAG2;
    samples[6] = *VIF1_CODE;
    samples[7] = *VIF0_CODE;
    samples[8] = *D0_MADR;
    samples[9] = *D1_MADR;
    md5_process(&md, (unsigned char *)(&samples[0]), sizeof(samples));
    // include previous round
    md5_process(&md, (unsigned char *)(&lastx[0]), sizeof(lastx));
    md5_done(&md, (unsigned char *)(&lastx[0]));
    l = min(sizeof(lastx), len-j);
    memcpy(buf+j, &lastx[0], l); //min(sizeof(lastx), len-j));
  }
  return len;
}
예제 #2
0
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) {
    const md5_byte_t *p = data;
    int        left     = nbytes;
    int        offset   = (pms->count[0] >> 3) & 63;
    md5_word_t nbits    = (md5_word_t)(nbytes << 3);

    if (nbytes <= 0)
        return;

    /* Update the message length. */
    pms->count[1] += nbytes >> 29;
    pms->count[0] += nbits;
    if (pms->count[0] < nbits)
        pms->count[1]++;

    /* Process an initial partial block. */
    if (offset) {
        int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);

        memcpy(pms->buf + offset, p, copy);
        if (offset + copy < 64)
            return;
        p    += copy;
        left -= copy;
        md5_process(pms, pms->buf);
    }

    /* Process full blocks. */
    for ( ; left >= 64; p += 64, left -= 64)
        md5_process(pms, p);

    /* Process a final partial block. */
    if (left)
        memcpy(pms->buf, p, left);
}
예제 #3
0
void md5_update( md5_context *ctx, uint8_t *input, uint32_t length )
{
    if(0 == length){
		return;
	}
    uint32_t left = ctx->total[0] & 0x3F;
    uint32_t fill = 64 - left;

    ctx->total[0] += length;
    ctx->total[0] &= 0xFFFFFFFF;

    if(ctx->total[0] < length){
        ctx->total[1]++;
	}

    if(left && length >= fill){
        ::memcpy((void*)(ctx->buffer + left), (void*)input, fill);
        md5_process(ctx, ctx->buffer);
        length -= fill;
        input += fill;
        left = 0;
    }

    while(length >= 64){
        md5_process(ctx, input);
        length -= 64;
        input  += 64;
    }

    if(length){
        ::memcpy((void*)(ctx->buffer + left), (void*)input, length);
    }
}
static int ApplyMpqPatch(
    TMPQFile * hf,
    TPatchHeader * pPatchHeader)
{
    unsigned char md5_digest[MD5_DIGEST_SIZE];
    hash_state md5_state;
    int nError = ERROR_SUCCESS;

    // Verify the original file before patching
    if(pPatchHeader->dwSizeBeforePatch != 0)
    {
        md5_init(&md5_state);
        md5_process(&md5_state, hf->pbFileData, hf->cbFileData);
        md5_done(&md5_state, md5_digest);
        if(memcmp(pPatchHeader->md5_before_patch, md5_digest, MD5_DIGEST_SIZE))
            nError = ERROR_FILE_CORRUPT;
    }

    // Apply the patch
    if(nError == ERROR_SUCCESS)
    {
        switch(pPatchHeader->dwPatchType)
        {
            case 0x59504f43:    // 'COPY'
                nError = ApplyMpqPatch_COPY(hf, pPatchHeader);
                break;

            case 0x30445342:    // 'BSD0'
                nError = ApplyMpqPatch_BSD0(hf, pPatchHeader);
                break;

            default:
                nError = ERROR_FILE_CORRUPT;
                break;
        }
    }

    // Verify MD5 after patch
    if(nError == ERROR_SUCCESS && pPatchHeader->dwSizeAfterPatch != 0)
    {
        // Verify the patched file
        md5_init(&md5_state);
        md5_process(&md5_state, hf->pbFileData, hf->cbFileData);
        md5_done(&md5_state, md5_digest);
        if(memcmp(pPatchHeader->md5_after_patch, md5_digest, MD5_DIGEST_SIZE))
            nError = ERROR_FILE_CORRUPT;
    }

    return nError;
}
예제 #5
0
파일: md5.c 프로젝트: 0xcc/pyston
void
md5_append(md5_state_t *pms, const md5_byte_t *data, unsigned int nbytes)
{
    const md5_byte_t *p = data;
    unsigned int left = nbytes;
    unsigned int offset = (pms->count[0] >> 3) & 63;
    md5_word_t nbits = (md5_word_t)(nbytes << 3);

    if (nbytes <= 0)
        return;

    /* this special case is handled recursively */
    if (nbytes > INT_MAX - offset) {
        unsigned int overlap;

        /* handle the append in two steps to prevent overflow */
        overlap = 64 - offset;

        md5_append(pms, data, overlap);
        md5_append(pms, data + overlap, nbytes - overlap);
        return;
    }

    /* Update the message length. */
    pms->count[1] += nbytes >> 29;
    pms->count[0] += nbits;
    if (pms->count[0] < nbits)
        pms->count[1]++;

    /* Process an initial partial block. */
    if (offset) {
        unsigned int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);

        memcpy(pms->buf + offset, p, copy);
        if (offset + copy < 64)
            return;
        p += copy;
        left -= copy;
        md5_process(pms, pms->buf);
    }

    /* Process full blocks. */
    for (; left >= 64; p += 64, left -= 64)
        md5_process(pms, p);

    /* Process a final partial block. */
    if (left)
        memcpy(pms->buf, p, left);
}
예제 #6
0
파일: md5.c 프로젝트: ksherlock/mpw-tools
int process(int fd, const char *name, int fork) {

	static unsigned char buffer[4096];
	hash_state md;
	unsigned char hash[16];

	md5_init(&md);


	for(;;) {
		long l = read(fd, buffer, sizeof(buffer));
		if (l == 0) break;
		if (l < 0) {
			if (errno == EINTR) continue;
			perror("read");
			return -1;
		}
		md5_process(&md, buffer, l);
	}


	md5_done(&md, hash);
	fprintf(stdout, "MD5 (%s%s) = %s\n",
		name, fork ? "+" : "", unhash(hash));
	return 0;
}
예제 #7
0
// Creates a MD5 hash from a file specified in "filename" and returns it as string 
// (based on Ronald L. Rivest's code from RFC1321 "The MD5 Message-Digest Algorithm") 
string getHashFromFile(const string &filename)	
{
   const S32 ChunkSize = 1024;

	unsigned int len;
  	unsigned char buffer[ChunkSize], digest[16];

	// Open file
   FILE *file = fopen (filename.c_str(), "rb");
   if(!file)
		return "-1";

	// Init md5
   hash_state md;
   md5_init(&md);

	// Read the file
	while( (len = (unsigned int)fread (buffer, 1, ChunkSize, file)) )
	   md5_process(&md, buffer, len);

	// Generate hash, close the file, and return the hash as string
   md5_done(&md, digest);
 	fclose (file);

	return convToString(digest);
}
예제 #8
0
// Add another line of content to the hash
void IncrementalHasher::add(const string &line)
{
   // The (bitwise) contents of the string don't change if the characters
   // are interpreted as unsigned chars instead of signed chars, so we can
   // use a reinterpret_cast to get our string of unsigned chars.

   md5_process(&mHashState, reinterpret_cast<const unsigned char *>(line.c_str()), line.length());
}
예제 #9
0
string PHPBB3Password::md5(string data) {
	unsigned char hash[16];
	hash_state state;
	md5_init(&state);

	md5_process(&state, (const unsigned char *)data.c_str(), data.length());
	md5_done(&state, hash);
	string ret;
	for (int i=0; i<16; i++) ret += hash[i];
	return ret;
}
예제 #10
0
/*
 * Read in from stdin and run MD5 on the input
 */
static	void	read_file(const char *filename)
{
  unsigned char	sig[MD5_SIZE];
  char		buffer[4096];
  md5_t		md5;
  int		ret;
  FILE		*stream;
  
  if (strcmp(filename, "-") == 0) {
    stream = stdin;
  }
  else {
    stream = fopen(filename, "r");
    if (stream == NULL) {
      perror(filename);
      exit(1);
    }
  }
  
  md5_init(&md5);
  
  /* iterate over file */
  while (1) {
    
    /* read in from our file */
    ret = fread(buffer, sizeof(char), sizeof(buffer), stream);
    if (ret <= 0)
      break;
    
    /* process our buffer buffer */
    md5_process(&md5, buffer, ret);
  }
  
  md5_finish(&md5, sig); 
  
  if (stream != stdin) {
    (void)fclose(stream);
  }
  
  (void)printf("%25s '", "Resulting signature:");
  print_sig(sig);
  (void)printf("'\n");

  /* convert to string to print */
  md5_sig_to_string(sig, buffer, sizeof(buffer));
  (void)printf("%25s '%s'\n", "Results of md5_to_string:", buffer);
  
  /* now we convert it from string back into the sig */
  md5_sig_from_string(sig, buffer);
  
  (void)printf("%25s '", "After md5_from_string:");
  print_sig(sig);
  (void)printf("'\n");
}
예제 #11
0
파일: md5.c 프로젝트: ksherlock/mpw-tools
// from md5_test
int test() {

	static const struct {
		char *msg;
		unsigned char hash[16];
	} tests[] = {
		{ "",
			{ 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 
			0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
		{ "a",
			{0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 
			0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
		{ "abc",
			{ 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 
			0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
		{ "message digest", 
			{ 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 
			0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, 
		{ "abcdefghijklmnopqrstuvwxyz",
			{ 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 
			0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
		{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
			{ 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 
			0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
		{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
			{ 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 
			0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, 
		{ NULL, { 0 } }
	};


	unsigned i;
	unsigned ok;
	hash_state md;
	unsigned char hash[16];

	for (i = 0; tests[i].msg != NULL; i++) {
		md5_init(&md);
		md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
		md5_done(&md, hash);

		ok = !memcmp(hash, tests[i].hash, 16);

		printf("MD5 (\"%s\") = %s - %s\n",
			tests[i].msg, unhash(hash),
			ok ? "verified correct" : "INCORRECT RESULT!");

		if (!ok) return -1;
	}


	return 0;
}
예제 #12
0
// Internal hash function, calling the basic methods from md5.h
static string hash(const string &text)
{
   unsigned char outBuffer[16] = "";
   hash_state md;

   md5_init(&md);
   md5_process(&md, (unsigned char*)text.c_str(), (unsigned int)text.length());
   md5_done(&md, outBuffer);

	// Convert the hash to a string and return it
	return convToString(outBuffer);
}
예제 #13
0
파일: md5.c 프로젝트: vni/programming
static void processFile(int fd, const char *filename)
{
	md5_ctx_t md5;
	byte bigbuf[4096];
	int n;

	md5_init(&md5);

	while ((n = read(fd, bigbuf, sizeof(bigbuf))) > 0)
		md5_process(&md5, bigbuf, n);
	if (n == -1) {
		fprintf(stderr, "Error occured during reading the file: %s\n", strerror(errno));
		return;
	}

	md5_finish(&md5);
	for (n=0; n<16; n++)
		printf("%02x", md5.buf[n]);
	printf("  %s\n", filename);
}
예제 #14
0
void CNWNXODBC::WriteScorcoData(char *param, BYTE* pData, int Length)
{
	// This function either stores the object or computes a hash value of it
	if (strcmp(param, "HASH") == 0) 	
	{
		unsigned char out[16];
		hash_state md;
		md5_init(&md);
		md5_process(&md, pData, Length);
		md5_done(&md, out);
		for (int j = 0; j < 16; j += 4)
		{
			sprintf(&lastHash[j*2], "%.2x%.2x%.2x%.2x", out[j], out[j+1], out[j+2], out[j+3]);
		}
		Log("* MD5 hash (writescorcodata, length): %s, %d\n", lastHash, Length);
	}
	else if (Length > 0)
	{
		//Log ("o Writing scorco data.\n");
		if (!db->WriteScorcoData(scorcoSQL, pData, Length))
			if (logLevel > logNothing)
				Log ("! SQL Error: %s\n", db->GetErrorMessage ());
	}
}
예제 #15
0
static bool CalculateMpqHashMd5(
    TMPQArchive * ha,
    PMPQ_SIGNATURE_INFO pSI,
    LPBYTE pMd5Digest)
{
    hash_state md5_state;
    ULONGLONG BeginBuffer;
    ULONGLONG EndBuffer;
    LPBYTE pbDigestBuffer = NULL;

    // Allocate buffer for creating the MPQ digest.
    pbDigestBuffer = ALLOCMEM(BYTE, MPQ_DIGEST_UNIT_SIZE);
    if(pbDigestBuffer == NULL)
        return false;

    // Initialize the MD5 hash state
    md5_init(&md5_state);

    // Set the byte offset of begin of the data
    BeginBuffer = pSI->BeginMpqData;

    // Create the digest
    for(;;)
    {
        ULONGLONG BytesRemaining;
        LPBYTE pbSigBegin = NULL;
        LPBYTE pbSigEnd = NULL;
        DWORD dwToRead = MPQ_DIGEST_UNIT_SIZE;

        // Check the number of bytes remaining
        BytesRemaining = pSI->EndMpqData - BeginBuffer;
        if(BytesRemaining < MPQ_DIGEST_UNIT_SIZE)
            dwToRead = (DWORD)BytesRemaining;
        if(dwToRead == 0)
            break;

        // Read the next chunk 
        if(!FileStream_Read(ha->pStream, &BeginBuffer, pbDigestBuffer, dwToRead))
        {
            FREEMEM(pbDigestBuffer);
            return false;
        }

        // Move the current byte offset
        EndBuffer = BeginBuffer + dwToRead;

        // Check if the signature is within the loaded digest
        if(BeginBuffer <= pSI->BeginExclude && pSI->BeginExclude < EndBuffer)
            pbSigBegin = pbDigestBuffer + (size_t)(pSI->BeginExclude - BeginBuffer);
        if(BeginBuffer <= pSI->EndExclude && pSI->EndExclude < EndBuffer)
            pbSigEnd = pbDigestBuffer + (size_t)(pSI->EndExclude - BeginBuffer);

        // Zero the part that belongs to the signature
        if(pbSigBegin != NULL || pbSigEnd != NULL)
        {
            if(pbSigBegin == NULL)
                pbSigBegin = pbDigestBuffer;
            if(pbSigEnd == NULL)
                pbSigEnd = pbDigestBuffer + dwToRead;

            memset(pbSigBegin, 0, (pbSigEnd - pbSigBegin));
        }

        // Pass the buffer to the hashing function
        md5_process(&md5_state, pbDigestBuffer, dwToRead);

        // Move pointers
        BeginBuffer += dwToRead;
    }

    // Finalize the MD5 hash
    md5_done(&md5_state, pMd5Digest);
    FREEMEM(pbDigestBuffer);
    return true;
}
예제 #16
0
static int WriteDataToMpqFile(
    TMPQArchive * ha,
    TMPQFile * hf,
    LPBYTE pbFileData,
    DWORD dwDataSize,
    DWORD dwCompression)
{
    TFileEntry * pFileEntry = hf->pFileEntry;
    ULONGLONG ByteOffset;
    LPBYTE pbCompressed = NULL;         // Compressed (target) data
    LPBYTE pbToWrite = NULL;            // Data to write to the file
    int nCompressionLevel = -1;         // ADPCM compression level (only used for wave files)
    int nError = ERROR_SUCCESS;

    // If the caller wants ADPCM compression, we will set wave compression level to 4,
    // which corresponds to medium quality
    if(dwCompression & LOSSY_COMPRESSION_MASK)
        nCompressionLevel = 4;

    // Make sure that the caller won't overrun the previously initiated file size
    assert(hf->dwFilePos + dwDataSize <= pFileEntry->dwFileSize);
    assert(hf->dwSectorCount != 0);
    assert(hf->pbFileSector != NULL);
    if((hf->dwFilePos + dwDataSize) > pFileEntry->dwFileSize)
        return ERROR_DISK_FULL;
    pbToWrite = hf->pbFileSector;

    // Now write all data to the file sector buffer
    if(nError == ERROR_SUCCESS)
    {
        DWORD dwBytesInSector = hf->dwFilePos % hf->dwSectorSize;
        DWORD dwSectorIndex = hf->dwFilePos / hf->dwSectorSize;
        DWORD dwBytesToCopy;

        // Process all data. 
        while(dwDataSize != 0)
        {
            dwBytesToCopy = dwDataSize;
                
            // Check for sector overflow
            if(dwBytesToCopy > (hf->dwSectorSize - dwBytesInSector))
                dwBytesToCopy = (hf->dwSectorSize - dwBytesInSector);

            // Copy the data to the file sector
            memcpy(hf->pbFileSector + dwBytesInSector, pbFileData, dwBytesToCopy);
            dwBytesInSector += dwBytesToCopy;
            pbFileData += dwBytesToCopy;
            dwDataSize -= dwBytesToCopy;

            // Update the file position
            hf->dwFilePos += dwBytesToCopy;

            // If the current sector is full, or if the file is already full,
            // then write the data to the MPQ
            if(dwBytesInSector >= hf->dwSectorSize || hf->dwFilePos >= pFileEntry->dwFileSize)
            {
                // Set the position in the file
                ByteOffset = hf->RawFilePos + pFileEntry->dwCmpSize;

                // Update CRC32 and MD5 of the file
                md5_process((hash_state *)hf->hctx, hf->pbFileSector, dwBytesInSector);
                hf->dwCrc32 = crc32(hf->dwCrc32, hf->pbFileSector, dwBytesInSector);

                // Compress the file sector, if needed
                if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED)
                {
                    int nOutBuffer = (int)dwBytesInSector;
                    int nInBuffer = (int)dwBytesInSector;

                    // If the file is compressed, allocate buffer for the compressed data.
                    // Note that we allocate buffer that is a bit longer than sector size,
                    // for case if the compression method performs a buffer overrun
                    if(pbCompressed == NULL)
                    {
                        pbToWrite = pbCompressed = STORM_ALLOC(BYTE, hf->dwSectorSize + 0x100);
                        if(pbCompressed == NULL)
                        {
                            nError = ERROR_NOT_ENOUGH_MEMORY;
                            break;
                        }
                    }

                    //
                    // Note that both SCompImplode and SCompCompress give original buffer,
                    // if they are unable to comperss the data.
                    //

                    if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE)
                    {
                        SCompImplode((char *)pbCompressed,
                                            &nOutBuffer,
                                     (char *)hf->pbFileSector,
                                             nInBuffer);
                    }

                    if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS)
                    {
                        SCompCompress((char *)pbCompressed,
                                             &nOutBuffer,
                                      (char *)hf->pbFileSector,
                                              nInBuffer,
                                    (unsigned)dwCompression,
                                              0,
                                              nCompressionLevel);
                    }

                    // Update sector positions
                    dwBytesInSector = nOutBuffer;
                    if(hf->SectorOffsets != NULL)
                        hf->SectorOffsets[dwSectorIndex+1] = hf->SectorOffsets[dwSectorIndex] + dwBytesInSector;

                    // We have to calculate sector CRC, if enabled
                    if(hf->SectorChksums != NULL)
                        hf->SectorChksums[dwSectorIndex] = adler32(0, pbCompressed, nOutBuffer);
                }                 

                // Encrypt the sector, if necessary
                if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
                {
                    BSWAP_ARRAY32_UNSIGNED(pbToWrite, dwBytesInSector);
                    EncryptMpqBlock(pbToWrite, dwBytesInSector, hf->dwFileKey + dwSectorIndex);
                    BSWAP_ARRAY32_UNSIGNED(pbToWrite, dwBytesInSector);
                }

                // Write the file sector
                if(!FileStream_Write(ha->pStream, &ByteOffset, pbToWrite, dwBytesInSector))
                {
                    nError = GetLastError();
                    break;
                }

                // Call the compact callback, if any
                if(AddFileCB != NULL)
                    AddFileCB(pvUserData, hf->dwFilePos, hf->dwDataSize, false);

                // Update the compressed file size
                pFileEntry->dwCmpSize += dwBytesInSector;
                dwBytesInSector = 0;
                dwSectorIndex++;
            }
        }
    }

    // Cleanup
    if(pbCompressed != NULL)
        STORM_FREE(pbCompressed);
    return nError;
}
예제 #17
0
int FindFixCRC(ECU_info* dllECUinfo, int FixCRC)
{
	 DWORD Buffer1 = (DWORD)dllECUinfo->EcuBuffer;
	 unsigned char* Buffer= (unsigned char*)(Buffer1);
	 unsigned int FindOffset, EcuSubType, StartAdr1, EndAdr1, ChkSumAdr1, CS_off, CS_count;
	 unsigned int r2_base=0x5C9FF0;
	 unsigned int ChkSumm1=0, CalcSumm1, TotalSumm=0, BadSumm=0, MultCSAdr;
	 //Signature Block CheckSumm
	 unsigned char EcuBlockSig1[]={0x81, 0x43, 0x00, 0x00, 0x81, 0x23, 0x00, 0x04, 0x7C, 0x0A, 0x48, 0x40, 0x41, 0x81, 0x00, 0x18};
	 unsigned int EcuHexCount1=16;

	 md5_t	md5;
	 unsigned char	MD5CalcSig[MD5_SIZE], MD5DecodedSig[MD5_SIZE];
	 unsigned int MD5_StartAdr, MD5_EndAdr, MD5BlkStart, MD5BlkEnd, md5sum, RSAModulus, RSASignature, RSAExponent, RSAFix;
	 //Signature for MD5
	 unsigned char MD5Sig1[]={0x7D, 0x4A, 0x5B, 0x78, 0x7D, 0x9D, 0xF8, 0xAE, 0x7D, 0x4A, 0x63, 0x78, 0x7D, 0x5E, 0xF9, 0x2E};
	 unsigned char MD5Sig2[]={0x39, 0x00, 0x00, 0x00, 0x3B, 0xE0, 0x00, 0x7F, 0x2C, 0x1F, 0x00, 0x00, 0x41, 0x80, 0x00, 0x64};
	 unsigned int MD5HexCount1=16;
	 unsigned int MD5HexCount2=16;
	 unsigned int RSAPubExp=0x03;
	 unsigned char RSABuf[0x80];
	 unsigned char RSAPubModulus[]={
									0x79, 0xD3, 0xD0, 0x1A, 0xB7, 0xE3, 0x6C, 0x98,
									0x4B, 0xBB, 0x54, 0xF5, 0x1C, 0x69, 0xA4, 0x91,
									0xF7, 0xD6, 0xD6, 0x82, 0xA4, 0xC6, 0x8B, 0x77,
									0x0D, 0x2F, 0xEE, 0xFA, 0x3D, 0x43, 0xFF, 0x4C,
									0x6B, 0xED, 0xF6, 0xA7, 0x1F, 0xE1, 0xF8, 0xB3,
									0x54, 0x66, 0x1E, 0x5D, 0x0E, 0x54, 0x87, 0xB6,
									0x66, 0x2B, 0x60, 0x9A, 0x25, 0x07, 0xA9, 0xBC,
									0x8F, 0x3C, 0xFA, 0x56, 0xDE, 0xAE, 0xD7, 0x83,
									0x9E, 0xBF, 0x74, 0xBB, 0x94, 0x22, 0x5C, 0x7D,
									0xB7, 0x2C, 0x3D, 0x1E, 0x6A, 0xDE, 0xC9, 0xB7,
									0x87, 0xA6, 0xF2, 0x2E, 0xFD, 0x87, 0x12, 0x46,
									0x4E, 0xDE, 0xA5, 0x46, 0x2C, 0x22, 0x45, 0x61,
									0x97, 0x07, 0x08, 0x99, 0x21, 0x44, 0x64, 0x36,
									0xDF, 0x53, 0xA1, 0x84, 0xA6, 0x34, 0xC4, 0xF5,
									0x98, 0x6F, 0xE6, 0x23, 0x5C, 0xF2, 0x1D, 0x7E,
									0x7A, 0x25, 0xA0, 0x52, 0xFB, 0xDA, 0x48, 0xB3
									};
	 unsigned char RSAPrivExp[]={
								0x51, 0x37, 0xE0, 0x11, 0xCF, 0xEC, 0xF3, 0x10,
								0x32, 0x7C, 0xE3, 0x4E, 0x12, 0xF1, 0x18, 0x61,
								0x4F, 0xE4, 0x8F, 0x01, 0xC3, 0x2F, 0x07, 0xA4,
								0xB3, 0x75, 0x49, 0xFC, 0x28, 0xD7, 0xFF, 0x88,
								0x47, 0xF3, 0xF9, 0xC4, 0xBF, 0xEB, 0xFB, 0x22,
								0x38, 0x44, 0x14, 0x3E, 0x09, 0x8D, 0xAF, 0xCE,
								0xEE, 0xC7, 0x95, 0xBC, 0x18, 0xAF, 0xC6, 0x7D,
								0xB4, 0xD3, 0x51, 0x8F, 0x3F, 0x1F, 0x3A, 0x56,
								0xCF, 0x8E, 0xE4, 0x2D, 0x8A, 0x89, 0x30, 0x51,
								0x9F, 0x4B, 0x89, 0xF9, 0x87, 0xAF, 0x55, 0xA1,
								0x3A, 0x86, 0x61, 0x4A, 0xC2, 0xA9, 0x9B, 0x74,
								0x24, 0xA3, 0xC1, 0x8C, 0x4D, 0x22, 0xDE, 0xCF,
								0x0C, 0xB6, 0xA9, 0x0E, 0x30, 0xDB, 0xA1, 0x22,
								0x4C, 0xFD, 0xC3, 0xDC, 0x5E, 0x41, 0xC2, 0x58,
								0xE2, 0x61, 0xCE, 0xEF, 0xDE, 0x44, 0x0E, 0x36,
								0xC8, 0x5B, 0x34, 0x38, 0xBB, 0x43, 0x41, 0x2B
								};
	 mpz_t PubExp, PrivExp, Modulus, CalcSig, DecodeSig, Sig;

		//CRC32 and RSA
		 CS_off=FindHexStr(0, dllECUinfo->EcuFileSize, (unsigned char*)Buffer , MD5Sig1, MD5HexCount1);
		 if (CS_off!=0xFFFFFFFF)
			{
			 MD5BlkEnd=*(Buffer+CS_off+0x47)+(*(Buffer+CS_off+0x46)<<8)+(*(Buffer+CS_off+0x43)<<16)+(*(Buffer+CS_off+0x42)<<24);
			 if (*(Buffer+CS_off+0x46)& 0x80) { MD5BlkEnd-=0x10000;}
			 MD5BlkStart=*(Buffer+CS_off+0x4F)+(*(Buffer+CS_off+0x4E)<<8)+(*(Buffer+CS_off+0x4B)<<16)+(*(Buffer+CS_off+0x4A)<<24);
			 if (*(Buffer+CS_off+0x4E)& 0x80) { MD5BlkStart-=0x10000;}
			}
		 else
			{
				 return 0;
			}
		 //Calc MD5
		 md5_init(&md5);
		 MD5_StartAdr=Read4ByteMot(Buffer+MD5BlkStart);
		 MD5_EndAdr=Read4ByteMot(Buffer+MD5BlkEnd);
		 md5_process(&md5, Buffer+MD5_StartAdr, MD5_EndAdr-MD5_StartAdr+1);
		 md5_finish (&md5, MD5CalcSig);

		 CS_off=FindHexStr(0, dllECUinfo->EcuFileSize, (unsigned char*)Buffer , MD5Sig2, MD5HexCount2);
		 if (CS_off!=0xFFFFFFFF)
			{
			 RSASignature=*(Buffer+CS_off-0x09)+(*(Buffer+CS_off-0x0A)<<8)+(*(Buffer+CS_off-0x0D)<<16)+(*(Buffer+CS_off-0x0E)<<24);
			 if (*(Buffer+CS_off-0x0A)& 0x80) { RSASignature-=0x10000;}
			 RSAModulus=*(Buffer+CS_off+0x97)+(*(Buffer+CS_off+0x96)<<8)+r2_base-0x400000;
			 if (*(Buffer+CS_off+0x96)& 0x80) { RSAModulus-=0x10000;}
			 RSAExponent=*(Buffer+CS_off+0x137)+(*(Buffer+CS_off+0x136)<<8)+r2_base-0x400000;
			 if (*(Buffer+CS_off+0x136)& 0x80) { RSAExponent-=0x10000;}
			}
		 else
			{
				 return 0;
			}
		 //Decode RSA Signature
		 RSAFix=0;
		 mpz_init (PubExp);
		 mpz_init (Modulus);
		 mpz_init (DecodeSig);
		 mpz_init (Sig);
		 mpz_import (Sig, 0x80, 1, 1, 0, 0, Buffer+RSASignature);
		 mpz_import (Modulus, 0x80, 1, 1, 0, 0, Buffer+RSAModulus);
		 mpz_import (PubExp, 4, 1, 1, 0, 0, Buffer+RSAExponent);
		 mpz_powm (DecodeSig, Sig, PubExp, Modulus);
		 size_t rsa_size;
		 rsa_size=mpz_sizeinbase(DecodeSig, 2);
		 rsa_size=rsa_size/8+1;
		 memset(RSABuf, 0x00, 0x80);
		 mpz_export(RSABuf+0x80-rsa_size, &rsa_size, 1, 1, 0, 0, DecodeSig);
		 memcpy(MD5DecodedSig, RSABuf+0x70, 0x10);
		 mpz_clear (PubExp);
		 mpz_clear (Modulus);
		 mpz_clear (DecodeSig);
		 mpz_clear (Sig);

		 TotalSumm++;
			 if (memcmp(MD5CalcSig, MD5DecodedSig, 0x10))
				{
					if (FixCRC)
						{
							 //Update Modulus, Exponent, recalc MD5 and RSA
						 *(Buffer+RSAExponent)=0;
						 *(Buffer+RSAExponent+1)=0;
						 *(Buffer+RSAExponent+2)=0;
						 *(Buffer+RSAExponent+3)=RSAPubExp;
						 memcpy(Buffer+RSAModulus, RSAPubModulus, 0x80);
						 RSAFix=1;//Flag for recalc RSA
						 md5_init(&md5);
						 md5_process(&md5, Buffer+MD5_StartAdr, MD5_EndAdr-MD5_StartAdr+1);
						 md5_finish (&md5, MD5CalcSig);
						 //Encode new RSA Signature
						 mpz_init (PrivExp);
						 mpz_init (Modulus);
						 mpz_init (CalcSig);
						 mpz_init (Sig);
						 RSABuf[0]=0x00;
						 RSABuf[1]=0x01;
						 memset (RSABuf+2, 0xFF, 0x6D);
						 RSABuf[0x6F]=0x00;
						 memcpy(RSABuf+0x70, MD5CalcSig, 0x10);
						 mpz_import (Sig, 0x80, 1, 1, 0, 0, RSABuf);
						 mpz_import (Modulus, 0x80, 1, 1, 0, 0, RSAPubModulus);
						 mpz_import (PrivExp, 0x80, 1, 1, 0, 0, RSAPrivExp);
						 mpz_powm (CalcSig, Sig, PrivExp, Modulus);
						 rsa_size=mpz_sizeinbase(CalcSig, 2);
						 rsa_size=rsa_size/8+1;
						 mpz_export(RSABuf, &rsa_size, 1, 1, 0, 0, CalcSig);
						 mpz_clear (PrivExp);
						 mpz_clear (Modulus);
						 mpz_clear (CalcSig);
						 mpz_clear (Sig);
						 memcpy(Buffer+RSASignature, RSABuf, 0x80);
						}
					BadSumm++;
				}

		 //First CS Block
		 CS_off=FindHexStr(0, dllECUinfo->EcuFileSize, (unsigned char*)Buffer , EcuBlockSig1, EcuHexCount1);
		 if (CS_off!=0xFFFFFFFF)
			{
			 MultCSAdr=*(Buffer+CS_off-0x0D)+(*(Buffer+CS_off-0x0E)<<8)+(*(Buffer+CS_off-0x11)<<16)+(*(Buffer+CS_off-0x12)<<24);
			 if (*(Buffer+CS_off-0x0E)& 0x80) { MultCSAdr-=0x10000;}
			}
		 else
			{
				 return 0;
			}

			TotalSumm++;

				StartAdr1=Read4ByteMot(Buffer+MultCSAdr);
				EndAdr1=Read4ByteMot(Buffer+MultCSAdr+4);
				ChkSumm1= Read4ByteMot(Buffer+MultCSAdr+8);
				CalcSumm1=SummInt16Mot(StartAdr1, EndAdr1, Buffer);
				 if (ChkSumm1==(Read4ByteMot(Buffer+MultCSAdr+12)^0xFFFFFFFF))
					{
					 if (ChkSumm1!=CalcSumm1)
						{
							if (FixCRC)
								{
									Write4ByteMot(CalcSumm1, Buffer+MultCSAdr+8);
									Write4ByteMot(CalcSumm1^0xFFFFFFFF, Buffer+MultCSAdr+12);
								}
							BadSumm++;
						}
					 }
				 else
				 {
					if (FixCRC)
						{
							Write4ByteMot(CalcSumm1, Buffer+MultCSAdr+8);
							Write4ByteMot(CalcSumm1^0xFFFFFFFF, Buffer+MultCSAdr+12);
						}
					BadSumm++;
				 }

		 //Second CS Block
		 CS_off=FindHexStr(CS_off+16, dllECUinfo->EcuFileSize, (unsigned char*)Buffer , EcuBlockSig1, EcuHexCount1);
		 if (CS_off!=0xFFFFFFFF)
			{
			 MultCSAdr=*(Buffer+CS_off-0x0D)+(*(Buffer+CS_off-0x0E)<<8)+(*(Buffer+CS_off-0x11)<<16)+(*(Buffer+CS_off-0x12)<<24);
			 if (*(Buffer+CS_off-0x0E)& 0x80) { MultCSAdr-=0x10000;}
			}
		 else
			{
				 return 0;
			}

			MultCSAdr+=0x10; //Correct Adress with CS number :)

		  for (CS_count = 0; CS_count < 4; CS_count++)
		  {
				TotalSumm++;

				StartAdr1=Read4ByteMot(Buffer+MultCSAdr);
				EndAdr1=Read4ByteMot(Buffer+MultCSAdr+4);
				ChkSumm1= Read4ByteMot(Buffer+MultCSAdr+8);
				CalcSumm1=SummInt16Mot(StartAdr1, EndAdr1, Buffer);
				 if (ChkSumm1==(Read4ByteMot(Buffer+MultCSAdr+12)^0xFFFFFFFF))
					{
					 if (ChkSumm1!=CalcSumm1)
						{
							if (FixCRC)
								{
									Write4ByteMot(CalcSumm1, Buffer+MultCSAdr+8);
									Write4ByteMot(CalcSumm1^0xFFFFFFFF, Buffer+MultCSAdr+12);
								}
							BadSumm++;
						}
					 }
				 else
				 {
					if (FixCRC)
						{
							Write4ByteMot(CalcSumm1, Buffer+MultCSAdr+8);
							Write4ByteMot(CalcSumm1^0xFFFFFFFF, Buffer+MultCSAdr+12);
						}
					BadSumm++;
				 }
            MultCSAdr+=0x10;
		  }

		 //Third CS Block
		 CS_off=FindHexStr(CS_off+16, dllECUinfo->EcuFileSize, (unsigned char*)Buffer , EcuBlockSig1, EcuHexCount1);
		 if (CS_off!=0xFFFFFFFF)
			{
			 MultCSAdr=*(Buffer+CS_off-0x0D)+(*(Buffer+CS_off-0x0E)<<8)+r2_base-0x400000;
			 if (*(Buffer+CS_off-0x0E)& 0x80) { MultCSAdr-=0x10000;}
			}
		 else
			{
				 return 0;
			}

			MultCSAdr+=0x40; //Correct Adress with CS number :)

		  for (CS_count = 0; CS_count < 6; CS_count++)
		  {
				TotalSumm++;

				StartAdr1=Read4ByteMot(Buffer+MultCSAdr)-0x400000;
				EndAdr1=Read4ByteMot(Buffer+MultCSAdr+4)-0x400000;
				ChkSumm1= Read4ByteMot(Buffer+MultCSAdr+8);
				CalcSumm1=SummInt16Mot(StartAdr1, EndAdr1, Buffer);
				 if (ChkSumm1==(Read4ByteMot(Buffer+MultCSAdr+12)^0xFFFFFFFF))
					{
					 if (ChkSumm1!=CalcSumm1)
						{
							if (FixCRC)
								{
									Write4ByteMot(CalcSumm1, Buffer+MultCSAdr+8);
									Write4ByteMot(CalcSumm1^0xFFFFFFFF, Buffer+MultCSAdr+12);
								}
							BadSumm++;
						}
					 }
				 else
				 {
					if (FixCRC)
						{
							Write4ByteMot(CalcSumm1, Buffer+MultCSAdr+8);
							Write4ByteMot(CalcSumm1^0xFFFFFFFF, Buffer+MultCSAdr+12);
						}
					BadSumm++;
				 }
			MultCSAdr+=0x10;
		  }

			if (RSAFix) //Recalc RSA after CS block fix
				{
				 md5_init(&md5);
				 md5_process(&md5, Buffer+MD5_StartAdr, MD5_EndAdr-MD5_StartAdr+1);
				 md5_finish (&md5, MD5CalcSig);
				 //Encode new RSA Signature
				 mpz_init (PrivExp);
				 mpz_init (Modulus);
				 mpz_init (CalcSig);
				 mpz_init (Sig);
				 RSABuf[0]=0x00;
				 RSABuf[1]=0x01;
				 memset (RSABuf+2, 0xFF, 0x6D);
				 RSABuf[0x6F]=0x00;
				 memcpy(RSABuf+0x70, MD5CalcSig, 0x10);
				 mpz_import (Sig, 0x80, 1, 1, 0, 0, RSABuf);
				 mpz_import (Modulus, 0x80, 1, 1, 0, 0, RSAPubModulus);
				 mpz_import (PrivExp, 0x80, 1, 1, 0, 0, RSAPrivExp);
				 mpz_powm (CalcSig, Sig, PrivExp, Modulus);
				 rsa_size=mpz_sizeinbase(CalcSig, 2);
				 rsa_size=rsa_size/8+1;
				 mpz_export(RSABuf, &rsa_size, 1, 1, 0, 0, CalcSig);
				 mpz_clear (PrivExp);
				 mpz_clear (Modulus);
				 mpz_clear (CalcSig);
				 mpz_clear (Sig);
				 memcpy(Buffer+RSASignature, RSABuf, 0x80);
				}


		 //Fourth CS Block
		 CS_off=FindHexStr(CS_off+16, dllECUinfo->EcuFileSize, (unsigned char*)Buffer , EcuBlockSig1, EcuHexCount1);
		 CS_off=FindHexStr(CS_off+16, dllECUinfo->EcuFileSize, (unsigned char*)Buffer , EcuBlockSig1, EcuHexCount1);
		 CS_off=FindHexStr(CS_off+16, dllECUinfo->EcuFileSize, (unsigned char*)Buffer , EcuBlockSig1, EcuHexCount1);
		 if (CS_off!=0xFFFFFFFF)
			{
			 MultCSAdr=*(Buffer+CS_off-0x0D)+(*(Buffer+CS_off-0x0E)<<8)+(*(Buffer+CS_off-0x11)<<16)+(*(Buffer+CS_off-0x12)<<24);
			 if (*(Buffer+CS_off-0x0E)& 0x80) { MultCSAdr-=0x10000;}
			}
		 else
			{
				 return 0;
			}

			MultCSAdr+=0x90; //Correct Adress with CS number :)

		  for (CS_count = 0; CS_count < 55; CS_count++)
		  {
				TotalSumm++;

				StartAdr1=Read4ByteMot(Buffer+MultCSAdr);
				EndAdr1=Read4ByteMot(Buffer+MultCSAdr+4);
				ChkSumm1= Read4ByteMot(Buffer+MultCSAdr+8);
				CalcSumm1=SummInt16Mot(StartAdr1, EndAdr1, Buffer);
				 if (ChkSumm1==(Read4ByteMot(Buffer+MultCSAdr+12)^0xFFFFFFFF))
					{
					 if (ChkSumm1!=CalcSumm1)
						{
							if (FixCRC)
								{
									Write4ByteMot(CalcSumm1, Buffer+MultCSAdr+8);
									Write4ByteMot(CalcSumm1^0xFFFFFFFF, Buffer+MultCSAdr+12);
								}
							BadSumm++;
						}
					 }
				 else
				 {
					if (FixCRC)
						{
							Write4ByteMot(CalcSumm1, Buffer+MultCSAdr+8);
							Write4ByteMot(CalcSumm1^0xFFFFFFFF, Buffer+MultCSAdr+12);
						}
					BadSumm++;
				 }
			MultCSAdr+=0x10;
		  }



	 dllECUinfo->BadChkSumNumber=BadSumm;  //Bad CheckSumm number in dump
	 dllECUinfo->ChkSumNumber=TotalSumm;  //CheckSumm number in dump
	 return 1;
}
예제 #18
0
파일: jackstart.c 프로젝트: Llefjord/jack1
static int check_binary (const char *binpath)
{
	struct stat status;
	FILE *binstream;

	if (lstat(jackd_bin_path, &status)) {
		fprintf (stderr, "jackstart: could not stat %s: %s\n",
			 binpath, strerror(errno));
		return -1;
	}
	if (!(S_ISREG(status.st_mode))) {
		fprintf (stderr, "jackstart: %s is not a regular file\n",
			 binpath);
		return -1;
	}
	if (status.st_uid != 0) {
		fprintf (stderr, "jackstart: %s is not owned by root\n",
			 binpath);
		return -1;
	}
	if ((status.st_mode & 022) != 0) {
		fprintf (stderr,
			 "jackstart: %s mode %o writeable by non-root users\n",
			 binpath, status.st_mode & 07777);
		return -1;
	}
	if ((binstream = fopen (binpath, "r")) == NULL) {
		fprintf (stderr, "jackstart: can't open %s for reading: %s\n", 
			 binpath, strerror(errno));
		return -1;
	} else {
		/* md5sum the executable file, check man evp for more details */
		size_t sum;
		md5_t ctx;
		char buffer[READ_BLOCKSIZE + 72];
		unsigned char md_value[MD5_SIZE];
		char md_string[3];
		int i, j;

		md5_init(&ctx);
		while (1) {
			size_t n;
			sum = 0;
			do {
				n = fread (buffer + sum, 1, READ_BLOCKSIZE - sum, binstream);
				sum += n;
			} while (sum < READ_BLOCKSIZE && n != 0);
			if (n == 0 && ferror (binstream)) {
				fprintf (stderr, "jackstart: error while reading %s: %s\n", binpath, strerror(errno));
				return -1;
			}
			if (n == 0) {
				break;
			}
			md5_process(&ctx, buffer, READ_BLOCKSIZE);
		}
		if (sum > 0)
			md5_process(&ctx, buffer, sum);
		if (fclose (binstream)) {
			fprintf (stderr, "jackstart: could not close %s after reading: %s\n", binpath, strerror(errno));
		}
		md5_finish(&ctx, md_value);
		for(i = 0, j = 0; i < sizeof(md_value); i++, j+=2) {
			sprintf(md_string, "%02x", md_value[i]);
			if (md_string[0] != jackd_md5_sum[j] ||
			    md_string[1] != jackd_md5_sum[j+1]) {
				fprintf (stderr, "jackstart: md5 checksum for %s does not match\n", binpath);
				return -1;
			}
		}
	}
	return 0;
}
예제 #19
0
DWORD WINAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags)
{
    hash_state md5_state;
    unsigned char md5[MD5_DIGEST_SIZE];
    TFileEntry * pFileEntry;
    TMPQFile * hf;
    BYTE Buffer[0x1000];
    HANDLE hFile = NULL;
    DWORD dwVerifyResult = 0;
    DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ;
    DWORD dwTotalBytes = 0;
    DWORD dwBytesRead;
    DWORD dwCrc32;

    // Fix the open type for patched archives
    if (SFileIsPatchedArchive(hMpq))
        dwSearchScope = SFILE_OPEN_PATCHED_FILE;

    // Attempt to open the file
    if (SFileOpenFileEx(hMpq, szFileName, dwSearchScope, &hFile))
    {
        // Get the file size
        hf = (TMPQFile *)hFile;
        pFileEntry = hf->pFileEntry;
        dwTotalBytes = SFileGetFileSize(hFile, NULL);

        // Initialize the CRC32 and MD5 contexts
        md5_init(&md5_state);
        dwCrc32 = crc32(0, Z_NULL, 0);

        // Also turn on sector checksum verification
        hf->bCheckSectorCRCs = true;

        // Go through entire file and update both CRC32 and MD5
        for (;;)
        {
            // Read data from file
            SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
            if (dwBytesRead == 0)
            {
                if (GetLastError() == ERROR_CHECKSUM_ERROR)
                    dwVerifyResult |= VERIFY_SECTOR_CHECKSUM_ERROR;
                break;
            }

            // Update CRC32 value
            if (dwFlags & MPQ_ATTRIBUTE_CRC32)
                dwCrc32 = crc32(dwCrc32, Buffer, dwBytesRead);

            // Update MD5 value
            if (dwFlags & MPQ_ATTRIBUTE_MD5)
                md5_process(&md5_state, Buffer, dwBytesRead);

            // Decrement the total size
            dwTotalBytes -= dwBytesRead;
        }

        // If the file has sector checksums, indicate it in the flags
        if ((hf->pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) && hf->SectorChksums != NULL && hf->SectorChksums[0] != 0)
            dwVerifyResult |= VERIFY_SECTORS_HAVE_CHECKSUM;

        // Check if the entire file has been read
        // No point in checking CRC32 and MD5 if not
        // Skip checksum checks if the file has patches
        if (dwTotalBytes == 0)
        {
            // Check CRC32 and MD5 only if there is no patches
            if (hf->hfPatchFile == NULL)
            {
                // Check if the CRC32 matches.
                if (dwFlags & MPQ_ATTRIBUTE_CRC32)
                {
                    // Some files may have their CRC zeroed
                    if (pFileEntry->dwCrc32 != 0)
                    {
                        dwVerifyResult |= VERIFY_FILE_HAS_CHECKSUM;
                        if (dwCrc32 != pFileEntry->dwCrc32)
                            dwVerifyResult |= VERIFY_FILE_CHECKSUM_ERROR;
                    }
                }

                // Check if MD5 matches
                if (dwFlags & MPQ_ATTRIBUTE_MD5)
                {
                    md5_done(&md5_state, md5);

                    // Some files have the MD5 zeroed. Don't check MD5 in that case
                    if (is_valid_md5(pFileEntry->md5))
                    {
                        dwVerifyResult |= VERIFY_FILE_HAS_MD5;
                        if (memcmp(md5, pFileEntry->md5, MD5_DIGEST_SIZE))
                            dwVerifyResult |= VERIFY_FILE_MD5_ERROR;
                    }
                }
            }
            else
            {
                // Patched files are MD5-checked automatically
                dwVerifyResult |= VERIFY_FILE_HAS_MD5;
            }
        }
        else
        {
            dwVerifyResult |= VERIFY_READ_ERROR;
        }

        SFileCloseFile(hFile);
    }
    else
    {
        // Remember that the file couldn't be open
        dwVerifyResult |= VERIFY_OPEN_ERROR;
    }

    return dwVerifyResult;
}
예제 #20
0
static DWORD VerifyFile(
    HANDLE hMpq,
    const char * szFileName,
    LPDWORD pdwCrc32,
    char * pMD5,
    DWORD dwFlags)
{
    hash_state md5_state;
    unsigned char * pFileMd5;
    unsigned char md5[MD5_DIGEST_SIZE];
    TFileEntry * pFileEntry;
    TMPQFile * hf;
    BYTE Buffer[0x1000];
    HANDLE hFile = NULL;
    DWORD dwVerifyResult = 0;
    DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ;
    DWORD dwTotalBytes = 0;
    DWORD dwBytesRead;
    DWORD dwCrc32 = 0;

    // Fix the open type for patched archives
    if(SFileIsPatchedArchive(hMpq))
        dwSearchScope = SFILE_OPEN_PATCHED_FILE;

    // Attempt to open the file
    if(SFileOpenFileEx(hMpq, szFileName, dwSearchScope, &hFile))
    {
        // Get the file size
        hf = (TMPQFile *)hFile;
        pFileEntry = hf->pFileEntry;
        dwTotalBytes = SFileGetFileSize(hFile, NULL);

        // Initialize the CRC32 and MD5 contexts
        md5_init(&md5_state);
        dwCrc32 = crc32(0, Z_NULL, 0);

        // If we have to verify raw data MD5, do it
        if(dwFlags & SFILE_VERIFY_RAW_MD5)
        {
            if(hf->ha->pHeader->dwRawChunkSize != 0)
            {
                // Note: we have to open the file from the MPQ where it was open from
                if(VerifyRawMpqData(hf->ha, pFileEntry->ByteOffset, pFileEntry->dwCmpSize) != ERROR_SUCCESS)
                    dwVerifyResult |= VERIFY_FILE_RAW_MD5_ERROR;
                dwVerifyResult |= VERIFY_FILE_HAS_RAW_MD5;
            }
        }

        // Also turn on sector checksum verification
        if(dwFlags & SFILE_VERIFY_SECTOR_CRC)
            hf->bCheckSectorCRCs = true;

        // Go through entire file and update both CRC32 and MD5
        for(;;)
        {
            // Read data from file
            SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
            if(dwBytesRead == 0)
            {
                if(GetLastError() == ERROR_CHECKSUM_ERROR)
                    dwVerifyResult |= VERIFY_FILE_SECTOR_CRC_ERROR;
                break;
            }

            // Update CRC32 value
            if(dwFlags & SFILE_VERIFY_FILE_CRC)
                dwCrc32 = crc32(dwCrc32, Buffer, dwBytesRead);
            
            // Update MD5 value
            if(dwFlags & SFILE_VERIFY_FILE_MD5)
                md5_process(&md5_state, Buffer, dwBytesRead);

            // Decrement the total size
            dwTotalBytes -= dwBytesRead;
        }

        // If the file has sector checksums, indicate it in the flags
        if(dwFlags & SFILE_VERIFY_SECTOR_CRC)
        {
            if((hf->pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) && hf->SectorChksums != NULL && hf->SectorChksums[0] != 0)
                dwVerifyResult |= VERIFY_FILE_HAS_SECTOR_CRC;
        }

        // Check if the entire file has been read
        // No point in checking CRC32 and MD5 if not
        // Skip checksum checks if the file has patches
        if(dwTotalBytes == 0)
        {
            // Check CRC32 and MD5 only if there is no patches
            if(hf->hfPatchFile == NULL)
            {
                // Check if the CRC32 matches.
                if(dwFlags & SFILE_VERIFY_FILE_CRC)
                {
                    // Only check the CRC32 if it is valid
                    if(pFileEntry->dwCrc32 != 0)
                    {
                        dwVerifyResult |= VERIFY_FILE_HAS_CHECKSUM;
                        if(dwCrc32 != pFileEntry->dwCrc32)
                            dwVerifyResult |= VERIFY_FILE_CHECKSUM_ERROR;
                    }
                }

                // Check if MD5 matches
                if(dwFlags & SFILE_VERIFY_FILE_MD5)
                {
                    // Patch files have their MD5 saved in the patch info
                    pFileMd5 = (hf->pPatchInfo != NULL) ? hf->pPatchInfo->md5 : pFileEntry->md5;
                    md5_done(&md5_state, md5);

                    // Only check the MD5 if it is valid
                    if(is_valid_md5(pFileMd5))
                    {
                        dwVerifyResult |= VERIFY_FILE_HAS_MD5;
                        if(memcmp(md5, pFileMd5, MD5_DIGEST_SIZE))
                            dwVerifyResult |= VERIFY_FILE_MD5_ERROR;
                    }
                }
            }
            else
            {
                // Patched files are MD5-checked automatically
                dwVerifyResult |= VERIFY_FILE_HAS_MD5;
            }
        }
        else
        {
            dwVerifyResult |= VERIFY_READ_ERROR;
        }

        SFileCloseFile(hFile);
    }
    else
    {
        // Remember that the file couldn't be open
        dwVerifyResult |= VERIFY_OPEN_ERROR;
    }

    // If the caller required CRC32 and/or MD5, give it to him
    if(pdwCrc32 != NULL)
        *pdwCrc32 = dwCrc32;
    if(pMD5 != NULL)
        memcpy(pMD5, md5, MD5_DIGEST_SIZE); 

    return dwVerifyResult;
}
예제 #21
0
static int VerifyRawMpqData(
    TMPQArchive * ha,
    ULONGLONG ByteOffset,
    DWORD dwDataSize)
{
    hash_state md5_state;
    ULONGLONG DataOffset = ha->MpqPos + ByteOffset;
    LPBYTE pbDataChunk;
    LPBYTE pbMD5Array1;                 // Calculated MD5 array
    LPBYTE pbMD5Array2;                 // MD5 array loaded from the MPQ
    DWORD dwBytesInChunk;
    DWORD dwChunkCount;
    DWORD dwChunkSize = ha->pHeader->dwRawChunkSize;
    DWORD dwMD5Size;
    int nError = ERROR_SUCCESS;

    // Get the number of data chunks to calculate MD5
    assert(dwChunkSize != 0);
    dwChunkCount = dwDataSize / dwChunkSize;
    if(dwDataSize % dwChunkSize)
        dwChunkCount++;
    dwMD5Size = dwChunkCount * MD5_DIGEST_SIZE;

    // Allocate space for data chunk and for the MD5 array
    pbDataChunk = ALLOCMEM(BYTE, dwChunkSize);
    if(pbDataChunk == NULL)
        return ERROR_NOT_ENOUGH_MEMORY;

    // Allocate space for MD5 array
    pbMD5Array1 = ALLOCMEM(BYTE, dwMD5Size);
    pbMD5Array2 = ALLOCMEM(BYTE, dwMD5Size);
    if(pbMD5Array1 == NULL || pbMD5Array2 == NULL)
        nError = ERROR_NOT_ENOUGH_MEMORY;

    // Calculate MD5 of each data chunk
    if(nError == ERROR_SUCCESS)
    {
        LPBYTE pbMD5 = pbMD5Array1;

        for(DWORD i = 0; i < dwChunkCount; i++)
        {
            // Get the number of bytes in the chunk
            dwBytesInChunk = STORMLIB_MIN(dwChunkSize, dwDataSize);

            // Read the data chunk
            if(!FileStream_Read(ha->pStream, &DataOffset, pbDataChunk, dwBytesInChunk))
            {
                nError = ERROR_FILE_CORRUPT;
                break;
            }

            // Calculate MD5
            md5_init(&md5_state);
            md5_process(&md5_state, pbDataChunk, dwBytesInChunk);
            md5_done(&md5_state, pbMD5);

            // Move pointers and offsets
            DataOffset += dwBytesInChunk;
            dwDataSize -= dwBytesInChunk;
            pbMD5 += MD5_DIGEST_SIZE;
        }
    }

    // Read the MD5 array
    if(nError == ERROR_SUCCESS)
    {
        // Read the array of MD5
        if(!FileStream_Read(ha->pStream, &DataOffset, pbMD5Array2, dwMD5Size))
            nError = GetLastError();
    }

    // Compare the array of MD5
    if(nError == ERROR_SUCCESS)
    {
        // Compare the MD5
        if(memcmp(pbMD5Array1, pbMD5Array2, dwMD5Size))
            nError = ERROR_FILE_CORRUPT;
    }

    // Free memory and return result
    if(pbMD5Array2 != NULL)
        FREEMEM(pbMD5Array2);
    if(pbMD5Array1 != NULL)
        FREEMEM(pbMD5Array1);
    if(pbDataChunk != NULL)
        FREEMEM(pbDataChunk);
    return nError;
}
예제 #22
0
static void md5_process_wrap( void *ctx, const unsigned char *data )
{
    md5_process( (md5_context *) ctx, data );
}
예제 #23
0
void Organizer::md5(Doublon *d)
{
    hash_state md;
    unsigned char *out = new unsigned char[16];
    unsigned char buf[4096];
    unsigned int nbLu=0;

    QSqlQuery query;

    query.prepare("SELECT md5 FROM fic WHERE path=:path");
    query.bindValue(":path",d->getPath());
    query.exec();

    bool update = true;

    if (query.next() && query.value(0).toString().length() > 0)
    {
        update= false;
        memcpy((unsigned char*)out,query.value(0).toString().toStdString().c_str(),sizeof(unsigned char)*16);
    }
    else
    {
        try {
            int fd;
            fd = open(d->getPath(),O_RDONLY);
            if (fd == -1)
            {
                throw -1 ;
            }

            md5_init(&md);


            while (nbLu != boost::filesystem::file_size(d->getPath()))
            {
                unsigned int tmp;
                tmp = read(fd,buf,sizeof(buf));
                md5_process(&md,buf, tmp);
                nbLu += tmp;
            }

            md5_done(&md, out);

            close(fd);
        }
        catch (int i) {
            perror("open");

        }
    }

    d->setKey(out);

    if (update)
    {
        query.prepare("UPDATE fic SET md5=:md5 WHERE path=:path");
        query.bindValue(":md5",d->getKey()->toString().c_str());
        query.bindValue(":path",d->getPath());
        query.exec();
    }
}