Skip to content

Allow multiple DLL hashes #1732

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions analytics/src/analytics_desktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,15 @@ void Initialize(const App& app) {

#if defined(_WIN32)
if (!g_analytics_module) {
std::vector<std::vector<unsigned char>> allowed_hashes;
std::vector<unsigned char> current_hash;
current_hash.assign(FirebaseAnalytics_WindowsDllHash,
FirebaseAnalytics_WindowsDllHash + sizeof(FirebaseAnalytics_WindowsDllHash));
allowed_hashes.push_back(current_hash);

g_analytics_module =
firebase::analytics::internal::VerifyAndLoadAnalyticsLibrary(
ANALYTICS_DLL_FILENAME, FirebaseAnalytics_WindowsDllHash,
sizeof(FirebaseAnalytics_WindowsDllHash));
ANALYTICS_DLL_FILENAME, allowed_hashes);

if (g_analytics_module) {
int num_loaded = FirebaseAnalytics_LoadDynamicFunctions(
Expand Down
35 changes: 22 additions & 13 deletions analytics/src/analytics_windows.cc
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,13 @@ static std::vector<BYTE> CalculateFileSha256(HANDLE hFile) {
}

HMODULE VerifyAndLoadAnalyticsLibrary(
const wchar_t* library_filename, // This is expected to be just the DLL
// filename e.g. "analytics_win.dll"
const unsigned char* expected_hash, size_t expected_hash_size) {
const wchar_t* library_filename,
const std::vector<std::vector<unsigned char>>& allowed_hashes) {
if (library_filename == nullptr || library_filename[0] == L'\0') {
LogError(LOG_TAG "Invalid arguments.");
return nullptr;
}
if (expected_hash == nullptr || expected_hash_size == 0) {
if (allowed_hashes.empty()) {
// Don't check the hash, just load the library.
LogWarning(LOG_TAG "No hash provided, using unverified Analytics DLL.");
return LoadLibraryW(library_filename);
Expand Down Expand Up @@ -251,15 +250,23 @@ HMODULE VerifyAndLoadAnalyticsLibrary(
if (calculated_hash.empty()) {
LogError(LOG_TAG "Hash failed for Analytics DLL.");
} else {
if (calculated_hash.size() != expected_hash_size) {
LogError(LOG_TAG
"Hash size mismatch for Analytics DLL. Expected: %zu, "
"Calculated: %zu.",
expected_hash_size, calculated_hash.size());
} else if (memcmp(calculated_hash.data(), expected_hash,
expected_hash_size) != 0) {
LogError(LOG_TAG "Hash mismatch for Analytics DLL.");
} else {
bool hash_matched = false;
for (const auto& expected_hash : allowed_hashes) {
if (calculated_hash.size() != expected_hash.size()) {
LogDebug(LOG_TAG
"Hash size mismatch for Analytics DLL. Expected: %zu, "
"Calculated: %zu. Trying next allowed hash.",
expected_hash.size(), calculated_hash.size());
continue;
}
if (memcmp(calculated_hash.data(), expected_hash.data(),
expected_hash.size()) == 0) {
hash_matched = true;
break;
}
}

if (hash_matched) {
LogDebug(LOG_TAG "Successfully verified Analytics DLL.");
// Load the library. When loading with a full path string, other
// directories are not searched.
Expand All @@ -269,6 +276,8 @@ HMODULE VerifyAndLoadAnalyticsLibrary(
LogError(LOG_TAG "Library load failed for Analytics DLL. Error: %u",
dwError);
}
} else {
LogError(LOG_TAG "Hash mismatch for Analytics DLL.");
}
}

Expand Down
8 changes: 5 additions & 3 deletions analytics/src/analytics_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@

#include <windows.h>

#include <vector>

namespace firebase {
namespace analytics {
namespace internal {

HMODULE VerifyAndLoadAnalyticsLibrary(const wchar_t* library_filename,
const unsigned char* expected_hash,
size_t expected_hash_size);
HMODULE VerifyAndLoadAnalyticsLibrary(
const wchar_t* library_filename,
const std::vector<std::vector<unsigned char>>& allowed_hashes);

} // namespace internal
} // namespace analytics
Expand Down
Loading