RTR3DECL(int) RTSha256Digest(void* pvBuf, size_t cbBuf, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser) { /* Validate input */ AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); AssertPtrReturn(ppszDigest, VERR_INVALID_POINTER); AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_PARAMETER); int rc = VINF_SUCCESS; *ppszDigest = NULL; /* Initialize the hash context. */ RTSHA256CONTEXT Ctx; RTSha256Init(&Ctx); /* Buffer size for progress callback */ double rdMulti = 100.0 / (cbBuf ? cbBuf : 1); /* Working buffer */ char *pvTmp = (char*)pvBuf; /* Process the memory in blocks */ size_t cbReadTotal = 0; for (;;) { size_t cbRead = RT_MIN(cbBuf - cbReadTotal, _1M); RTSha256Update(&Ctx, pvTmp, cbRead); cbReadTotal += cbRead; pvTmp += cbRead; /* Call the progress callback if one is defined */ if (pfnProgressCallback) { rc = pfnProgressCallback((unsigned)(cbReadTotal * rdMulti), pvUser); if (RT_FAILURE(rc)) break; /* canceled */ } /* Finished? */ if (cbReadTotal == cbBuf) break; } if (RT_SUCCESS(rc)) { /* Finally calculate & format the SHA256 sum */ uint8_t abHash[RTSHA256_HASH_SIZE]; RTSha256Final(&Ctx, abHash); char *pszDigest; rc = RTStrAllocEx(&pszDigest, RTSHA256_DIGEST_LEN + 1); if (RT_SUCCESS(rc)) { rc = RTSha256ToString(abHash, pszDigest, RTSHA256_DIGEST_LEN + 1); if (RT_SUCCESS(rc)) *ppszDigest = pszDigest; else RTStrFree(pszDigest); } } return rc; }
/** * Benchmark RTCrc routines potentially relevant for SSM or PGM - All in one go. * * @param pabSrc Pointer to the test data. * @param cbSrc The size of the test data. */ static void tstBenchmarkCRCsAllInOne(uint8_t const *pabSrc, size_t cbSrc) { RTPrintf("Algorithm Speed Time Digest\n" "------------------------------------------------------------------------------\n"); uint64_t NanoTS = RTTimeNanoTS(); uint32_t u32Crc = RTCrc32(pabSrc, cbSrc); NanoTS = RTTimeNanoTS() - NanoTS; unsigned uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024); RTPrintf("CRC-32 %'9u KB/s %'15llu ns - %08x\n", uSpeed, NanoTS, u32Crc); NanoTS = RTTimeNanoTS(); uint64_t u64Crc = RTCrc64(pabSrc, cbSrc); NanoTS = RTTimeNanoTS() - NanoTS; uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024); RTPrintf("CRC-64 %'9u KB/s %'15llu ns - %016llx\n", uSpeed, NanoTS, u64Crc); NanoTS = RTTimeNanoTS(); u32Crc = RTCrcAdler32(pabSrc, cbSrc); NanoTS = RTTimeNanoTS() - NanoTS; uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024); RTPrintf("Adler-32 %'9u KB/s %'15llu ns - %08x\n", uSpeed, NanoTS, u32Crc); NanoTS = RTTimeNanoTS(); uint8_t abMd5Hash[RTMD5HASHSIZE]; RTMd5(pabSrc, cbSrc, abMd5Hash); NanoTS = RTTimeNanoTS() - NanoTS; uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024); char szDigest[257]; RTMd5ToString(abMd5Hash, szDigest, sizeof(szDigest)); RTPrintf("MD5 %'9u KB/s %'15llu ns - %s\n", uSpeed, NanoTS, szDigest); NanoTS = RTTimeNanoTS(); uint8_t abSha1Hash[RTSHA1_HASH_SIZE]; RTSha1(pabSrc, cbSrc, abSha1Hash); NanoTS = RTTimeNanoTS() - NanoTS; uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024); RTSha1ToString(abSha1Hash, szDigest, sizeof(szDigest)); RTPrintf("SHA-1 %'9u KB/s %'15llu ns - %s\n", uSpeed, NanoTS, szDigest); NanoTS = RTTimeNanoTS(); uint8_t abSha256Hash[RTSHA256_HASH_SIZE]; RTSha256(pabSrc, cbSrc, abSha256Hash); NanoTS = RTTimeNanoTS() - NanoTS; uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024); RTSha256ToString(abSha256Hash, szDigest, sizeof(szDigest)); RTPrintf("SHA-256 %'9u KB/s %'15llu ns - %s\n", uSpeed, NanoTS, szDigest); NanoTS = RTTimeNanoTS(); uint8_t abSha512Hash[RTSHA512_HASH_SIZE]; RTSha512(pabSrc, cbSrc, abSha512Hash); NanoTS = RTTimeNanoTS() - NanoTS; uSpeed = (unsigned)(cbSrc / (long double)NanoTS * 1000000000.0 / 1024); RTSha512ToString(abSha512Hash, szDigest, sizeof(szDigest)); RTPrintf("SHA-512 %'9u KB/s %'15llu ns - %s\n", uSpeed, NanoTS, szDigest); }
/** * Adds the hashes to a manifest entry. * * @returns IPRT status code. * @param pHashes The hashes structure. * @param hManifest The manifest to add them to. * @param pszEntry The entry name. */ static int rtManifestHashesSetAttrs(PRTMANIFESTHASHES pHashes, RTMANIFEST hManifest, const char *pszEntry) { char szValue[RTSHA512_DIGEST_LEN + 8]; int rc = VINF_SUCCESS; int rc2; if (pHashes->fAttrs & RTMANIFEST_ATTR_SIZE) { RTStrPrintf(szValue, sizeof(szValue), "%RU64", (uint64_t)pHashes->cbStream); rc2 = RTManifestEntrySetAttr(hManifest, pszEntry, "SIZE", szValue, RTMANIFEST_ATTR_SIZE); if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) rc = rc2; } if (pHashes->fAttrs & RTMANIFEST_ATTR_MD5) { rc2 = RTMd5ToString(pHashes->abMd5Digest, szValue, sizeof(szValue)); if (RT_SUCCESS(rc2)) rc2 = RTManifestEntrySetAttr(hManifest, pszEntry, "MD5", szValue, RTMANIFEST_ATTR_MD5); if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) rc = rc2; } if (pHashes->fAttrs & RTMANIFEST_ATTR_SHA1) { rc2 = RTSha1ToString(pHashes->abSha1Digest, szValue, sizeof(szValue)); if (RT_SUCCESS(rc2)) rc2 = RTManifestEntrySetAttr(hManifest, pszEntry, "SHA1", szValue, RTMANIFEST_ATTR_SHA1); if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) rc = rc2; } if (pHashes->fAttrs & RTMANIFEST_ATTR_SHA256) { rc2 = RTSha256ToString(pHashes->abSha256Digest, szValue, sizeof(szValue)); if (RT_SUCCESS(rc2)) rc2 = RTManifestEntrySetAttr(hManifest, pszEntry, "SHA256", szValue, RTMANIFEST_ATTR_SHA256); if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) rc = rc2; } if (pHashes->fAttrs & RTMANIFEST_ATTR_SHA512) { rc2 = RTSha512ToString(pHashes->abSha512Digest, szValue, sizeof(szValue)); if (RT_SUCCESS(rc2)) rc2 = RTManifestEntrySetAttr(hManifest, pszEntry, "SHA512", szValue, RTMANIFEST_ATTR_SHA512); if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) rc = rc2; } return rc; }
void UIDownloaderExtensionPack::handleDownloadedObject(UINetworkReply *pReply) { /* Read received data into the buffer: */ QByteArray receivedData(pReply->readAll()); /* Serialize that buffer into the file: */ while (true) { /* Try to open file for writing: */ QFile file(target()); if (file.open(QIODevice::WriteOnly)) { /* Write buffer into the file: */ file.write(receivedData); file.close(); /* Calc the SHA-256 on the bytes, creating a string: */ uint8_t abHash[RTSHA256_HASH_SIZE]; RTSha256(receivedData.constData(), receivedData.length(), abHash); char szDigest[RTSHA256_DIGEST_LEN + 1]; int rc = RTSha256ToString(abHash, szDigest, sizeof(szDigest)); if (RT_FAILURE(rc)) { AssertRC(rc); szDigest[0] = '\0'; } /* Warn the listener about extension-pack was downloaded: */ emit sigDownloadFinished(source().toString(), target(), &szDigest[0]); break; } /* Warn the user about extension-pack was downloaded but was NOT saved: */ msgCenter().warnAboutExtentionPackCantBeSaved(GUI_ExtPackName, source().toString(), QDir::toNativeSeparators(target())); /* Ask the user for another location for the extension-pack file: */ QString strTarget = QIFileDialog::getExistingDirectory(QFileInfo(target()).absolutePath(), msgCenter().networkManagerOrMainWindowShown(), tr("Select folder to save %1 to").arg(GUI_ExtPackName), true); /* Check if user had really set a new target: */ if (!strTarget.isNull()) setTarget(QDir(strTarget).absoluteFilePath(QFileInfo(target()).fileName())); else break; } }
int main(int argc, char **argv) { RTR3InitExe(argc, &argv, 0); enum { kDigestType_NotSpecified, kDigestType_CRC32, kDigestType_CRC64, kDigestType_MD5, kDigestType_SHA1, kDigestType_SHA256, kDigestType_SHA512 } enmDigestType = kDigestType_NotSpecified; enum { kMethod_Full, kMethod_Block, kMethod_File } enmMethod = kMethod_Block; static const RTGETOPTDEF s_aOptions[] = { { "--type", 't', RTGETOPT_REQ_STRING }, { "--method", 'm', RTGETOPT_REQ_STRING }, { "--help", 'h', RTGETOPT_REQ_NOTHING }, }; int ch; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case 't': if (!RTStrICmp(ValueUnion.psz, "crc32")) enmDigestType = kDigestType_CRC32; else if (!RTStrICmp(ValueUnion.psz, "crc64")) enmDigestType = kDigestType_CRC64; else if (!RTStrICmp(ValueUnion.psz, "md5")) enmDigestType = kDigestType_MD5; else if (!RTStrICmp(ValueUnion.psz, "sha1")) enmDigestType = kDigestType_SHA1; else if (!RTStrICmp(ValueUnion.psz, "sha256")) enmDigestType = kDigestType_SHA256; else if (!RTStrICmp(ValueUnion.psz, "sha512")) enmDigestType = kDigestType_SHA512; else { Error("Invalid digest type: %s\n", ValueUnion.psz); return 1; } break; case 'm': if (!RTStrICmp(ValueUnion.psz, "full")) enmMethod = kMethod_Full; else if (!RTStrICmp(ValueUnion.psz, "block")) enmMethod = kMethod_Block; else if (!RTStrICmp(ValueUnion.psz, "file")) enmMethod = kMethod_File; else { Error("Invalid digest method: %s\n", ValueUnion.psz); return 1; } break; case 'h': RTPrintf("syntax: tstRTDigest -t <digest-type> file [file2 [..]]\n"); return 1; case VINF_GETOPT_NOT_OPTION: { if (enmDigestType == kDigestType_NotSpecified) return Error("No digest type was specified\n"); switch (enmMethod) { case kMethod_Full: return Error("Full file method is not implemented\n"); case kMethod_File: switch (enmDigestType) { case kDigestType_SHA1: { char *pszDigest; int rc = RTSha1DigestFromFile(ValueUnion.psz, &pszDigest, NULL, NULL); if (RT_FAILURE(rc)) return Error("RTSha1Digest(%s,) -> %Rrc\n", ValueUnion.psz, rc); RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); RTStrFree(pszDigest); break; } case kDigestType_SHA256: { char *pszDigest; int rc = RTSha256DigestFromFile(ValueUnion.psz, &pszDigest, NULL, NULL); if (RT_FAILURE(rc)) return Error("RTSha256Digest(%s,) -> %Rrc\n", ValueUnion.psz, rc); RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); RTStrFree(pszDigest); break; } default: return Error("The file method isn't implemented for this digest\n"); } break; case kMethod_Block: { RTFILE hFile; int rc = RTFileOpen(&hFile, ValueUnion.psz, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) return Error("RTFileOpen(,%s,) -> %Rrc\n", ValueUnion.psz, rc); size_t cbRead; uint8_t abBuf[_64K]; char *pszDigest = (char *)&abBuf[0]; switch (enmDigestType) { case kDigestType_CRC32: { uint32_t uCRC32 = RTCrc32Start(); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; uCRC32 = RTCrc32Process(uCRC32, abBuf, cbRead); } uCRC32 = RTCrc32Finish(uCRC32); RTStrPrintf(pszDigest, sizeof(abBuf), "%08RX32", uCRC32); break; } case kDigestType_CRC64: { uint64_t uCRC64 = RTCrc64Start(); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; uCRC64 = RTCrc64Process(uCRC64, abBuf, cbRead); } uCRC64 = RTCrc64Finish(uCRC64); RTStrPrintf(pszDigest, sizeof(abBuf), "%016RX64", uCRC64); break; } case kDigestType_MD5: { RTMD5CONTEXT Ctx; RTMd5Init(&Ctx); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTMd5Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTMD5HASHSIZE]; RTMd5Final(abDigest, &Ctx); RTMd5ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case kDigestType_SHA1: { RTSHA1CONTEXT Ctx; RTSha1Init(&Ctx); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTSha1Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA1_HASH_SIZE]; RTSha1Final(&Ctx, abDigest); RTSha1ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case kDigestType_SHA256: { RTSHA256CONTEXT Ctx; RTSha256Init(&Ctx); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTSha256Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA256_HASH_SIZE]; RTSha256Final(&Ctx, abDigest); RTSha256ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case kDigestType_SHA512: { RTSHA512CONTEXT Ctx; RTSha512Init(&Ctx); for (;;) { rc = RTFileRead(hFile, abBuf, sizeof(abBuf), &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTSha512Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA512_HASH_SIZE]; RTSha512Final(&Ctx, abDigest); RTSha512ToString(abDigest, pszDigest, sizeof(abBuf)); break; } default: return Error("Internal error #1\n"); } RTFileClose(hFile); if (RT_FAILURE(rc) && rc != VERR_EOF) { RTPrintf("Partial: %s %s\n", pszDigest, ValueUnion.psz); return Error("RTFileRead(%s) -> %Rrc\n", ValueUnion.psz, rc); } RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); break; } default: return Error("Internal error #2\n"); } break; } default: return RTGetOptPrintError(ch, &ValueUnion); } } return 0; }
int main(int argc, char **argv) { RTR3InitExe(argc, &argv, 0); RTDIGESTTYPE enmDigestType = RTDIGESTTYPE_INVALID; const char *pszDigestType = "NotSpecified"; enum { kMethod_Full, kMethod_Block, kMethod_File, kMethod_CVAS } enmMethod = kMethod_Block; uint64_t offStart = 0; uint64_t cbMax = UINT64_MAX; bool fTestcase = false; static const RTGETOPTDEF s_aOptions[] = { { "--type", 't', RTGETOPT_REQ_STRING }, { "--method", 'm', RTGETOPT_REQ_STRING }, { "--help", 'h', RTGETOPT_REQ_NOTHING }, { "--length", 'l', RTGETOPT_REQ_UINT64 }, { "--offset", 'o', RTGETOPT_REQ_UINT64 }, { "--testcase", 'x', RTGETOPT_REQ_NOTHING }, }; int ch; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); while ((ch = RTGetOpt(&GetState, &ValueUnion))) { switch (ch) { case 't': if (!RTStrICmp(ValueUnion.psz, "crc32")) { pszDigestType = "CRC32"; enmDigestType = RTDIGESTTYPE_CRC32; } else if (!RTStrICmp(ValueUnion.psz, "crc64")) { pszDigestType = "CRC64"; enmDigestType = RTDIGESTTYPE_CRC64; } else if (!RTStrICmp(ValueUnion.psz, "md2")) { pszDigestType = "MD2"; enmDigestType = RTDIGESTTYPE_MD2; } else if (!RTStrICmp(ValueUnion.psz, "md5")) { pszDigestType = "MD5"; enmDigestType = RTDIGESTTYPE_MD5; } else if (!RTStrICmp(ValueUnion.psz, "sha1")) { pszDigestType = "SHA-1"; enmDigestType = RTDIGESTTYPE_SHA1; } else if (!RTStrICmp(ValueUnion.psz, "sha224")) { pszDigestType = "SHA-224"; enmDigestType = RTDIGESTTYPE_SHA224; } else if (!RTStrICmp(ValueUnion.psz, "sha256")) { pszDigestType = "SHA-256"; enmDigestType = RTDIGESTTYPE_SHA256; } else if (!RTStrICmp(ValueUnion.psz, "sha384")) { pszDigestType = "SHA-384"; enmDigestType = RTDIGESTTYPE_SHA384; } else if (!RTStrICmp(ValueUnion.psz, "sha512")) { pszDigestType = "SHA-512"; enmDigestType = RTDIGESTTYPE_SHA512; } else if (!RTStrICmp(ValueUnion.psz, "sha512/224")) { pszDigestType = "SHA-512/224"; enmDigestType = RTDIGESTTYPE_SHA512T224; } else if (!RTStrICmp(ValueUnion.psz, "sha512/256")) { pszDigestType = "SHA-512/256"; enmDigestType = RTDIGESTTYPE_SHA512T256; } else { Error("Invalid digest type: %s\n", ValueUnion.psz); return 1; } break; case 'm': if (!RTStrICmp(ValueUnion.psz, "full")) enmMethod = kMethod_Full; else if (!RTStrICmp(ValueUnion.psz, "block")) enmMethod = kMethod_Block; else if (!RTStrICmp(ValueUnion.psz, "file")) enmMethod = kMethod_File; else if (!RTStrICmp(ValueUnion.psz, "cvas")) enmMethod = kMethod_CVAS; else { Error("Invalid digest method: %s\n", ValueUnion.psz); return 1; } break; case 'l': cbMax = ValueUnion.u64; break; case 'o': offStart = ValueUnion.u64; break; case 'x': fTestcase = true; break; case 'h': RTPrintf("usage: tstRTDigest -t <digest-type> [-o <offset>] [-l <length>] [-x] file [file2 [..]]\n"); return 1; case VINF_GETOPT_NOT_OPTION: { if (enmDigestType == RTDIGESTTYPE_INVALID) return Error("No digest type was specified\n"); switch (enmMethod) { case kMethod_Full: return Error("Full file method is not implemented\n"); case kMethod_File: if (offStart != 0 || cbMax != UINT64_MAX) return Error("The -l and -o options do not work with the 'file' method."); switch (enmDigestType) { case RTDIGESTTYPE_SHA1: { char *pszDigest; int rc = RTSha1DigestFromFile(ValueUnion.psz, &pszDigest, NULL, NULL); if (RT_FAILURE(rc)) return Error("RTSha1Digest(%s,) -> %Rrc\n", ValueUnion.psz, rc); RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); RTStrFree(pszDigest); break; } case RTDIGESTTYPE_SHA256: { char *pszDigest; int rc = RTSha256DigestFromFile(ValueUnion.psz, &pszDigest, NULL, NULL); if (RT_FAILURE(rc)) return Error("RTSha256Digest(%s,) -> %Rrc\n", ValueUnion.psz, rc); RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); RTStrFree(pszDigest); break; } default: return Error("The file method isn't implemented for this digest\n"); } break; case kMethod_Block: { RTFILE hFile; int rc = RTFileOpen(&hFile, ValueUnion.psz, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) return Error("RTFileOpen(,%s,) -> %Rrc\n", ValueUnion.psz, rc); if (offStart != 0) { rc = RTFileSeek(hFile, offStart, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) return Error("RTFileSeek(%s,%ull) -> %Rrc\n", ValueUnion.psz, offStart, rc); } uint64_t cbMaxLeft = cbMax; size_t cbRead; uint8_t abBuf[_64K]; char *pszDigest = (char *)&abBuf[0]; switch (enmDigestType) { case RTDIGESTTYPE_CRC32: { uint32_t uCRC32 = RTCrc32Start(); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; uCRC32 = RTCrc32Process(uCRC32, abBuf, cbRead); } uCRC32 = RTCrc32Finish(uCRC32); RTStrPrintf(pszDigest, sizeof(abBuf), "%08RX32", uCRC32); break; } case RTDIGESTTYPE_CRC64: { uint64_t uCRC64 = RTCrc64Start(); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; uCRC64 = RTCrc64Process(uCRC64, abBuf, cbRead); } uCRC64 = RTCrc64Finish(uCRC64); RTStrPrintf(pszDigest, sizeof(abBuf), "%016RX64", uCRC64); break; } case RTDIGESTTYPE_MD2: { RTMD2CONTEXT Ctx; RTMd2Init(&Ctx); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; RTMd2Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTMD2_HASH_SIZE]; RTMd2Final(&Ctx, abDigest); RTMd2ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case RTDIGESTTYPE_MD5: { RTMD5CONTEXT Ctx; RTMd5Init(&Ctx); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; RTMd5Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTMD5HASHSIZE]; RTMd5Final(abDigest, &Ctx); RTMd5ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case RTDIGESTTYPE_SHA1: { RTSHA1CONTEXT Ctx; RTSha1Init(&Ctx); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; RTSha1Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA1_HASH_SIZE]; RTSha1Final(&Ctx, abDigest); RTSha1ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case RTDIGESTTYPE_SHA256: { RTSHA256CONTEXT Ctx; RTSha256Init(&Ctx); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; RTSha256Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA256_HASH_SIZE]; RTSha256Final(&Ctx, abDigest); RTSha256ToString(abDigest, pszDigest, sizeof(abBuf)); break; } case RTDIGESTTYPE_SHA512: { RTSHA512CONTEXT Ctx; RTSha512Init(&Ctx); for (;;) { rc = MyReadFile(hFile, abBuf, sizeof(abBuf), &cbRead, &cbMaxLeft); if (RT_FAILURE(rc) || !cbRead) break; RTSha512Update(&Ctx, abBuf, cbRead); } uint8_t abDigest[RTSHA512_HASH_SIZE]; RTSha512Final(&Ctx, abDigest); RTSha512ToString(abDigest, pszDigest, sizeof(abBuf)); break; } default: return Error("Internal error #1\n"); } RTFileClose(hFile); if (RT_FAILURE(rc) && rc != VERR_EOF) { RTPrintf("Partial: %s %s\n", pszDigest, ValueUnion.psz); return Error("RTFileRead(%s) -> %Rrc\n", ValueUnion.psz, rc); } if (!fTestcase) RTPrintf("%s %s\n", pszDigest, ValueUnion.psz); else if (offStart) RTPrintf(" { &g_abRandom72KB[%#4llx], %5llu, \"%s\", \"%s %llu bytes @%llu\" },\n", offStart, cbMax - cbMaxLeft, pszDigest, pszDigestType, offStart, cbMax - cbMaxLeft); else RTPrintf(" { &g_abRandom72KB[0], %5llu, \"%s\", \"%s %llu bytes\" },\n", cbMax - cbMaxLeft, pszDigest, pszDigestType, cbMax - cbMaxLeft); break; } /* * Process a SHS response file: * http://csrc.nist.gov/groups/STM/cavp/index.html#03 */ case kMethod_CVAS: { RTCRDIGEST hDigest; int rc = RTCrDigestCreateByType(&hDigest, enmDigestType); if (RT_FAILURE(rc)) return Error("Failed to create digest calculator for %s: %Rrc", pszDigestType, rc); uint32_t const cbDigest = RTCrDigestGetHashSize(hDigest); if (!cbDigest || cbDigest >= _1K) return Error("Unexpected hash size: %#x\n", cbDigest); PRTSTREAM pFile; rc = RTStrmOpen(ValueUnion.psz, "r", &pFile); if (RT_FAILURE(rc)) return Error("Failed to open CVAS file '%s': %Rrc", ValueUnion.psz, rc); /* * Parse the input file. * ASSUME order: Len, Msg, MD. */ static char s_szLine[_256K]; char *psz; uint32_t cPassed = 0; uint32_t cErrors = 0; uint32_t iLine = 1; for (;;) { psz = MyGetNextSignificantLine(pFile, s_szLine, sizeof(s_szLine), &iLine, &rc); if (!psz) break; /* Skip [L = 20] stuff. */ if (*psz == '[') continue; /* Message length. */ uint64_t cMessageBits; if (RTStrNICmp(psz, RT_STR_TUPLE("Len ="))) return Error("%s(%d): Expected 'Len =' found '%.10s...'", ValueUnion.psz, iLine, psz); psz = RTStrStripL(psz + 5); rc = RTStrToUInt64Full(psz, 0, &cMessageBits); if (rc != VINF_SUCCESS) return Error("%s(%d): Error parsing length '%s': %Rrc\n", ValueUnion.psz, iLine, psz, rc); /* The message text. */ psz = MyGetNextSignificantLine(pFile, s_szLine, sizeof(s_szLine), &iLine, &rc); if (!psz) return Error("%s(%d): Expected message text not EOF.", ValueUnion.psz, iLine); if (RTStrNICmp(psz, RT_STR_TUPLE("Msg ="))) return Error("%s(%d): Expected 'Msg =' found '%.10s...'", ValueUnion.psz, iLine, psz); psz = RTStrStripL(psz + 5); size_t const cbMessage = (cMessageBits + 7) / 8; static uint8_t s_abMessage[sizeof(s_szLine) / 2]; if (cbMessage > 0) { rc = RTStrConvertHexBytes(psz, s_abMessage, cbMessage, 0 /*fFlags*/); if (rc != VINF_SUCCESS) return Error("%s(%d): Error parsing message '%.10s...': %Rrc\n", ValueUnion.psz, iLine, psz, rc); } /* The message digest. */ psz = MyGetNextSignificantLine(pFile, s_szLine, sizeof(s_szLine), &iLine, &rc); if (!psz) return Error("%s(%d): Expected message digest not EOF.", ValueUnion.psz, iLine); if (RTStrNICmp(psz, RT_STR_TUPLE("MD ="))) return Error("%s(%d): Expected 'MD =' found '%.10s...'", ValueUnion.psz, iLine, psz); psz = RTStrStripL(psz + 4); static uint8_t s_abExpectedDigest[_1K]; rc = RTStrConvertHexBytes(psz, s_abExpectedDigest, cbDigest, 0 /*fFlags*/); if (rc != VINF_SUCCESS) return Error("%s(%d): Error parsing message digest '%.10s...': %Rrc\n", ValueUnion.psz, iLine, psz, rc); /* * Do the testing. */ rc = RTCrDigestReset(hDigest); if (rc != VINF_SUCCESS) return Error("RTCrDigestReset failed: %Rrc", rc); rc = RTCrDigestUpdate(hDigest, s_abMessage, cbMessage); if (rc != VINF_SUCCESS) return Error("RTCrDigestUpdate failed: %Rrc", rc); static uint8_t s_abActualDigest[_1K]; rc = RTCrDigestFinal(hDigest, s_abActualDigest, cbDigest); if (rc != VINF_SUCCESS) return Error("RTCrDigestFinal failed: %Rrc", rc); if (memcmp(s_abActualDigest, s_abExpectedDigest, cbDigest) == 0) cPassed++; else { Error("%s(%d): Message digest mismatch. Expected %.*RThxs, got %.*RThxs.", ValueUnion.psz, iLine, cbDigest, s_abExpectedDigest, cbDigest, s_abActualDigest); cErrors++; } } RTStrmClose(pFile); if (cErrors > 0) return Error("Failed: %u error%s (%u passed)", cErrors, cErrors == 1 ? "" : "s", cPassed); RTPrintf("Passed %u test%s.\n", cPassed, cPassed == 1 ? "" : "s"); if (RT_FAILURE(rc)) return Error("Failed: %Rrc", rc); break; } default: return Error("Internal error #2\n"); } break; } default: return RTGetOptPrintError(ch, &ValueUnion); } } return 0; }
RTR3DECL(int) RTSha256DigestFromFile(const char *pszFile, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser) { /* Validate input */ AssertPtrReturn(pszFile, VERR_INVALID_POINTER); AssertPtrReturn(ppszDigest, VERR_INVALID_POINTER); AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_PARAMETER); *ppszDigest = NULL; /* Initialize the hash context. */ RTSHA256CONTEXT Ctx; RTSha256Init(&Ctx); /* Open the file to calculate a SHA256 sum of */ RTFILE hFile; int rc = RTFileOpen(&hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) return rc; /* Fetch the file size. Only needed if there is a progress callback. */ double rdMulti = 0; if (pfnProgressCallback) { uint64_t cbFile; rc = RTFileGetSize(hFile, &cbFile); if (RT_FAILURE(rc)) { RTFileClose(hFile); return rc; } rdMulti = 100.0 / (cbFile ? cbFile : 1); } /* Allocate a reasonably large buffer, fall back on a tiny one. */ void *pvBufFree; size_t cbBuf = _1M; void *pvBuf = pvBufFree = RTMemTmpAlloc(cbBuf); if (!pvBuf) { cbBuf = 0x1000; pvBuf = alloca(cbBuf); } /* Read that file in blocks */ size_t cbReadTotal = 0; for (;;) { size_t cbRead; rc = RTFileRead(hFile, pvBuf, cbBuf, &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTSha256Update(&Ctx, pvBuf, cbRead); cbReadTotal += cbRead; /* Call the progress callback if one is defined */ if (pfnProgressCallback) { rc = pfnProgressCallback((unsigned)(cbReadTotal * rdMulti), pvUser); if (RT_FAILURE(rc)) break; /* canceled */ } } RTMemTmpFree(pvBufFree); RTFileClose(hFile); if (RT_FAILURE(rc)) return rc; /* Finally calculate & format the SHA256 sum */ uint8_t abHash[RTSHA256_HASH_SIZE]; RTSha256Final(&Ctx, abHash); char *pszDigest; rc = RTStrAllocEx(&pszDigest, RTSHA256_DIGEST_LEN + 1); if (RT_SUCCESS(rc)) { rc = RTSha256ToString(abHash, pszDigest, RTSHA256_DIGEST_LEN + 1); if (RT_SUCCESS(rc)) *ppszDigest = pszDigest; else RTStrFree(pszDigest); } return rc; }
static int shaCloseCallback(void *pvUser, void *pvStorage) { /* Validate input. */ AssertPtrReturn(pvUser, VERR_INVALID_POINTER); AssertPtrReturn(pvStorage, VERR_INVALID_POINTER); PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser; PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces); AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)pvStorage; DEBUG_PRINT_FLOW(); int rc = VINF_SUCCESS; /* Make sure all pending writes are flushed */ rc = shaFlushCurBuf(pInt); if (pInt->pWorkerThread) { /* Signal the worker thread to end himself */ rc = shaSignalManifestThread(pInt, STATUS_END); /* Worker thread stopped? */ rc = RTThreadWait(pInt->pWorkerThread, RT_INDEFINITE_WAIT, 0); } if ( RT_SUCCESS(rc) && pShaStorage->fCreateDigest) { /* Finally calculate & format the SHA1/SHA256 sum */ unsigned char auchDig[RTSHA256_HASH_SIZE]; char *pszDigest; size_t cbDigest; if (pShaStorage->fSha256) { RTSha256Final(&pInt->ctx.Sha256, auchDig); cbDigest = RTSHA256_DIGEST_LEN; } else { RTSha1Final(&pInt->ctx.Sha1, auchDig); cbDigest = RTSHA1_DIGEST_LEN; } rc = RTStrAllocEx(&pszDigest, cbDigest + 1); if (RT_SUCCESS(rc)) { if (pShaStorage->fSha256) rc = RTSha256ToString(auchDig, pszDigest, cbDigest + 1); else rc = RTSha1ToString(auchDig, pszDigest, cbDigest + 1); if (RT_SUCCESS(rc)) pShaStorage->strDigest = pszDigest; RTStrFree(pszDigest); } } /* Close the file */ rc = vdIfIoFileClose(pIfIo, pInt->pvStorage); // RTPrintf("%lu %lu\n", pInt->calls, pInt->waits); /* Cleanup */ if (pInt->workFinishedEvent) RTSemEventDestroy(pInt->workFinishedEvent); if (pInt->newStatusEvent) RTSemEventDestroy(pInt->newStatusEvent); if (pInt->pCircBuf) RTCircBufDestroy(pInt->pCircBuf); if (pInt->pvZeroBuf) RTMemFree(pInt->pvZeroBuf); RTMemFree(pInt); return rc; }