blob: b5d29b52e8bc9e38d2bf13aaf307a8bf1294a7c7 [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/os_crypt/app_bound_encryption_metrics_win.h"
#include <string>
#include "base/base64.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/win/com_init_util.h"
#include "base/win/windows_types.h"
#include "chrome/browser/os_crypt/app_bound_encryption_win.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
namespace os_crypt {
namespace prefs {
const char kOsCryptAppBoundFixedDataPrefName[] =
"os_crypt.app_bound_fixed_data";
} // namespace prefs
namespace {
// Rather than generate a random key here, use fixed data here for the purposes
// of measuring the performance, as the content itself does not matter.
const char kFixedData[] = "Fixed data used for metrics";
void DecryptAndRecordMetricsOnCOMThread(const std::string& encrypted_data) {
base::win::AssertComInitialized();
std::string decrypted_data;
DWORD last_error;
HRESULT hr;
{
SCOPED_UMA_HISTOGRAM_TIMER("OSCrypt.AppBoundEncryption.Decrypt.Time");
hr = DecryptAppBoundString(encrypted_data, decrypted_data, last_error);
}
if (FAILED(hr)) {
base::UmaHistogramSparse(
"OSCrypt.AppBoundEncryption.Decrypt.ResultLastError", last_error);
} else {
// Check if it returned success but the data was invalid. This should never
// happen. If it does, log a unique HRESULT to track it.
if (decrypted_data != kFixedData) {
const HRESULT kErrorWrongData =
MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA101);
hr = kErrorWrongData;
}
}
base::UmaHistogramSparse("OSCrypt.AppBoundEncryption.Decrypt.ResultCode", hr);
}
std::string EncryptAndRecordMetricsOnCOMThread() {
base::win::AssertComInitialized();
std::string encrypted_data;
DWORD last_error;
HRESULT hr;
{
SCOPED_UMA_HISTOGRAM_TIMER("OSCrypt.AppBoundEncryption.Encrypt.Time");
hr = EncryptAppBoundString(ProtectionLevel::PATH_VALIDATION, kFixedData,
encrypted_data, last_error);
}
base::UmaHistogramSparse("OSCrypt.AppBoundEncryption.Encrypt.ResultCode", hr);
if (FAILED(hr)) {
base::UmaHistogramSparse(
"OSCrypt.AppBoundEncryption.Encrypt.ResultLastError", last_error);
}
return encrypted_data;
}
void StorePrefOnUiThread(PrefService* local_state,
const std::string& encrypted_data) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (encrypted_data.empty())
return;
std::string base64_data;
base::Base64Encode(encrypted_data, &base64_data);
local_state->SetString(prefs::kOsCryptAppBoundFixedDataPrefName, base64_data);
}
} // namespace
void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(prefs::kOsCryptAppBoundFixedDataPrefName, {});
}
bool MeasureAppBoundEncryptionStatus(PrefService* local_state) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto com_runner = base::ThreadPool::CreateCOMSTATaskRunner(
{base::MayBlock(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::SingleThreadTaskRunnerThreadMode::SHARED);
if (local_state->HasPrefPath(prefs::kOsCryptAppBoundFixedDataPrefName)) {
const std::string base64_encrypted_data =
local_state->GetString(prefs::kOsCryptAppBoundFixedDataPrefName);
std::string encrypted_data;
// If this fails it will be caught later when trying to decrypt and logged
// above..
std::ignore = base::Base64Decode(base64_encrypted_data, &encrypted_data);
// Gather metrics for decrypt.
return com_runner->PostTask(
FROM_HERE,
base::BindOnce(&DecryptAndRecordMetricsOnCOMThread, encrypted_data));
}
return com_runner->PostTaskAndReplyWithResult(
FROM_HERE, base::BindOnce(&EncryptAndRecordMetricsOnCOMThread),
base::BindOnce(StorePrefOnUiThread, local_state));
}
} // namespace os_crypt