// 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; }
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); }
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; }
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); }
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; }
// 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); }
// 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()); }
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; }
/* * 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"); }
// 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; }
// 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); }
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); }
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 ()); } }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
static void md5_process_wrap( void *ctx, const unsigned char *data ) { md5_process( (md5_context *) ctx, data ); }
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(); } }