Commit ab071858 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

wintrust: Add support for the PE image hash in CryptCATAdminCalcHashFromFileHandle().

parent 61b88ebd
......@@ -214,11 +214,84 @@ HCATINFO WINAPI CryptCATAdminAddCatalog(HCATADMIN catAdmin, PWSTR catalogFile,
return ci;
}
static BOOL pe_image_hash( HANDLE file, HCRYPTHASH hash )
{
UINT32 size, offset, file_size, sig_pos;
HANDLE mapping;
BYTE *view;
IMAGE_NT_HEADERS *nt;
BOOL ret = FALSE;
if ((file_size = GetFileSize( file, NULL )) == INVALID_FILE_SIZE) return FALSE;
if ((mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL )) == INVALID_HANDLE_VALUE)
return FALSE;
if (!(view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 )) || !(nt = ImageNtHeader( view ))) goto done;
if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
const IMAGE_NT_HEADERS64 *nt64 = (const IMAGE_NT_HEADERS64 *)nt;
/* offset from start of file to checksum */
offset = (BYTE *)&nt64->OptionalHeader.CheckSum - view;
/* area between checksum and security directory entry */
size = FIELD_OFFSET( IMAGE_OPTIONAL_HEADER64, DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] ) -
FIELD_OFFSET( IMAGE_OPTIONAL_HEADER64, Subsystem );
if (nt64->OptionalHeader.NumberOfRvaAndSizes < IMAGE_FILE_SECURITY_DIRECTORY + 1) goto done;
sig_pos = nt64->OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY].VirtualAddress;
}
else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
{
const IMAGE_NT_HEADERS32 *nt32 = (const IMAGE_NT_HEADERS32 *)nt;
/* offset from start of file to checksum */
offset = (BYTE *)&nt32->OptionalHeader.CheckSum - view;
/* area between checksum and security directory entry */
size = FIELD_OFFSET( IMAGE_OPTIONAL_HEADER32, DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] ) -
FIELD_OFFSET( IMAGE_OPTIONAL_HEADER32, Subsystem );
if (nt32->OptionalHeader.NumberOfRvaAndSizes < IMAGE_FILE_SECURITY_DIRECTORY + 1) goto done;
sig_pos = nt32->OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY].VirtualAddress;
}
else goto done;
if (!CryptHashData( hash, view, offset, 0 )) goto done;
offset += sizeof(DWORD); /* skip checksum */
if (!CryptHashData( hash, view + offset, size, 0 )) goto done;
offset += size + sizeof(IMAGE_DATA_DIRECTORY); /* skip security entry */
if (offset > file_size) goto done;
if (sig_pos)
{
if (sig_pos < offset) goto done;
if (sig_pos > file_size) goto done;
size = sig_pos - offset; /* exclude signature */
}
else size = file_size - offset;
if (!CryptHashData( hash, view + offset, size, 0 )) goto done;
ret = TRUE;
if (!sig_pos && (size = file_size % 8))
{
static const BYTE pad[7];
ret = CryptHashData( hash, pad, 8 - size, 0 );
}
done:
UnmapViewOfFile( view );
CloseHandle( mapping );
return ret;
}
/***********************************************************************
* CryptCATAdminCalcHashFromFileHandle (WINTRUST.@)
*/
BOOL WINAPI CryptCATAdminCalcHashFromFileHandle(HANDLE hFile, DWORD* pcbHash,
BYTE* pbHash, DWORD dwFlags )
BOOL WINAPI CryptCATAdminCalcHashFromFileHandle(HANDLE hFile, DWORD *pcbHash, BYTE *pbHash, DWORD dwFlags)
{
BOOL ret = FALSE;
......@@ -262,9 +335,13 @@ BOOL WINAPI CryptCATAdminCalcHashFromFileHandle(HANDLE hFile, DWORD* pcbHash,
CryptReleaseContext(prov, 0);
return FALSE;
}
while ((ret = ReadFile(hFile, buffer, 4096, &bytes_read, NULL)) && bytes_read)
if (!(ret = pe_image_hash(hFile, hash)))
{
CryptHashData(hash, buffer, bytes_read, 0);
while ((ret = ReadFile(hFile, buffer, 4096, &bytes_read, NULL)) && bytes_read)
{
CryptHashData(hash, buffer, bytes_read, 0);
}
}
if (ret) ret = CryptGetHashParam(hash, HP_HASHVAL, pbHash, pcbHash, 0);
......
......@@ -1892,6 +1892,39 @@ static void test_multiple_signatures(void)
DeleteFileW(pathW);
}
static BOOL (WINAPI *pCryptCATAdminCalcHashFromFileHandle)(HANDLE,DWORD*,BYTE*,DWORD);
static void test_pe_image_hash(void)
{
static const char expected[] =
{0x8a,0xd5,0x45,0x53,0x3d,0x67,0xdf,0x2f,0x78,0xe0,0x55,0x0a,0xe0,0xd9,0x7a,0x28,0x3e,0xbf,0x45,0x2b};
WCHAR path[MAX_PATH];
HANDLE file;
BYTE sha1[20];
DWORD size, count;
HMODULE wintrust = GetModuleHandleA("wintrust.dll");
BOOL ret;
pCryptCATAdminCalcHashFromFileHandle = (void *)GetProcAddress(wintrust, "CryptCATAdminCalcHashFromFileHandle");
if (!pCryptCATAdminCalcHashFromFileHandle)
{
win_skip("hash function missing\n");
return;
}
file = create_temp_file(path);
WriteFile(file, &bin, sizeof(bin), &count, NULL);
size = sizeof(sha1);
memset(sha1, 0, sizeof(sha1));
ret = pCryptCATAdminCalcHashFromFileHandle(file, &size, sha1, 0);
ok(ret, "got %lu\n", GetLastError());
ok(!memcmp(sha1, expected, sizeof(sha1)), "wrong hash\n");
CloseHandle(file);
DeleteFileW(path);
}
START_TEST(softpub)
{
InitFunctionPtrs();
......@@ -1901,4 +1934,5 @@ START_TEST(softpub)
test_wintrust_digest();
test_get_known_usages();
test_multiple_signatures();
test_pe_image_hash();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment