mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-03 18:56:09 +03:00
179 lines
5.8 KiB
C++
179 lines
5.8 KiB
C++
// Copyright 2022 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "crypto/unexportable_key_metrics.h"
|
|
|
|
#include "base/feature_list.h"
|
|
#include "base/metrics/histogram_functions.h"
|
|
#include "base/task/task_traits.h"
|
|
#include "base/task/thread_pool.h"
|
|
#include "base/timer/elapsed_timer.h"
|
|
#include "crypto/unexportable_key.h"
|
|
|
|
namespace crypto {
|
|
|
|
namespace {
|
|
|
|
enum class TPMOperation {
|
|
kMessageSigning,
|
|
kMessageVerify,
|
|
kWrappedKeyCreation,
|
|
kNewKeyCreation,
|
|
};
|
|
|
|
std::string GetHistogramSuffixForOperation(TPMOperation operation) {
|
|
switch (operation) {
|
|
case TPMOperation::kMessageSigning:
|
|
return "MessageSigning";
|
|
case TPMOperation::kMessageVerify:
|
|
return "MessageVerify";
|
|
case TPMOperation::kNewKeyCreation:
|
|
return "NewKeyCreation";
|
|
case TPMOperation::kWrappedKeyCreation:
|
|
return "WrappedKeyCreation";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
std::string GetHistogramSuffixForAlgo(internal::TPMSupport algo) {
|
|
switch (algo) {
|
|
case internal::TPMSupport::kECDSA:
|
|
return "ECDSA";
|
|
case internal::TPMSupport::kRSA:
|
|
return "RSA";
|
|
case internal::TPMSupport::kNone:
|
|
return "";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
void ReportUmaLatency(TPMOperation operation,
|
|
internal::TPMSupport algo,
|
|
base::TimeDelta latency) {
|
|
std::string histogram_name = "Crypto.TPMDuration." +
|
|
GetHistogramSuffixForOperation(operation) +
|
|
GetHistogramSuffixForAlgo(algo);
|
|
base::UmaHistogramMediumTimes(histogram_name, latency);
|
|
}
|
|
|
|
void ReportUmaOperationSuccess(TPMOperation operation,
|
|
internal::TPMSupport algo,
|
|
bool status) {
|
|
std::string histogram_name = "Crypto.TPMOperation." +
|
|
GetHistogramSuffixForOperation(operation) +
|
|
GetHistogramSuffixForAlgo(algo);
|
|
base::UmaHistogramBoolean(histogram_name, status);
|
|
}
|
|
|
|
void ReportUmaTpmOperation(TPMOperation operation,
|
|
internal::TPMSupport algo,
|
|
base::TimeDelta latency,
|
|
bool status) {
|
|
ReportUmaOperationSuccess(operation, algo, status);
|
|
if (status && operation != TPMOperation::kMessageVerify) {
|
|
// Only report latency for successful operations
|
|
// No latency reported for verification that is done outside of TPM
|
|
ReportUmaLatency(operation, algo, latency);
|
|
}
|
|
}
|
|
|
|
void MeasureTpmOperationsInternal() {
|
|
internal::TPMSupport supported_algo = internal::TPMSupport::kNone;
|
|
std::unique_ptr<UnexportableKeyProvider> provider =
|
|
GetUnexportableKeyProvider();
|
|
if (!provider) {
|
|
return;
|
|
}
|
|
|
|
const SignatureVerifier::SignatureAlgorithm kAllAlgorithms[] = {
|
|
SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256,
|
|
SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256,
|
|
};
|
|
|
|
auto algo = provider->SelectAlgorithm(kAllAlgorithms);
|
|
if (algo) {
|
|
switch (*algo) {
|
|
case SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256:
|
|
supported_algo = internal::TPMSupport::kECDSA;
|
|
break;
|
|
case SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256:
|
|
supported_algo = internal::TPMSupport::kRSA;
|
|
break;
|
|
case SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA1:
|
|
case SignatureVerifier::SignatureAlgorithm::RSA_PSS_SHA256:
|
|
// Not supported for this metric.
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Report if TPM is supported and best algo
|
|
base::UmaHistogramEnumeration("Crypto.TPMSupport2", supported_algo);
|
|
if (supported_algo == internal::TPMSupport::kNone) {
|
|
return;
|
|
}
|
|
|
|
base::ElapsedTimer key_creation_timer;
|
|
std::unique_ptr<UnexportableSigningKey> current_key =
|
|
provider->GenerateSigningKeySlowly(kAllAlgorithms);
|
|
ReportUmaTpmOperation(TPMOperation::kNewKeyCreation, supported_algo,
|
|
key_creation_timer.Elapsed(), current_key != nullptr);
|
|
if (!current_key) {
|
|
return;
|
|
}
|
|
|
|
base::ElapsedTimer wrapped_key_creation_timer;
|
|
std::unique_ptr<UnexportableSigningKey> wrapped_key =
|
|
provider->FromWrappedSigningKeySlowly(current_key->GetWrappedKey());
|
|
ReportUmaTpmOperation(TPMOperation::kWrappedKeyCreation, supported_algo,
|
|
wrapped_key_creation_timer.Elapsed(),
|
|
wrapped_key != nullptr);
|
|
|
|
const uint8_t msg[] = {1, 2, 3, 4};
|
|
base::ElapsedTimer message_signing_timer;
|
|
absl::optional<std::vector<uint8_t>> signed_bytes =
|
|
current_key->SignSlowly(msg);
|
|
ReportUmaTpmOperation(TPMOperation::kMessageSigning, supported_algo,
|
|
message_signing_timer.Elapsed(),
|
|
signed_bytes.has_value());
|
|
if (!signed_bytes.has_value()) {
|
|
return;
|
|
}
|
|
|
|
crypto::SignatureVerifier verifier;
|
|
bool verify_init =
|
|
verifier.VerifyInit(current_key->Algorithm(), signed_bytes.value(),
|
|
current_key->GetSubjectPublicKeyInfo());
|
|
if (verify_init) {
|
|
verifier.VerifyUpdate(msg);
|
|
bool verify_final = verifier.VerifyFinal();
|
|
ReportUmaOperationSuccess(TPMOperation::kMessageVerify, supported_algo,
|
|
verify_final);
|
|
} else {
|
|
ReportUmaOperationSuccess(TPMOperation::kMessageVerify, supported_algo,
|
|
verify_init);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace internal {
|
|
|
|
void MeasureTpmOperationsInternalForTesting() {
|
|
MeasureTpmOperationsInternal();
|
|
}
|
|
|
|
} // namespace internal
|
|
|
|
void MaybeMeasureTpmOperations() {
|
|
static BASE_FEATURE(kTpmLatencyMetrics, "TpmLatencyMetrics",
|
|
base::FEATURE_ENABLED_BY_DEFAULT);
|
|
if (base::FeatureList::IsEnabled(kTpmLatencyMetrics)) {
|
|
base::ThreadPool::PostTask(
|
|
FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
|
|
base::BindOnce(&MeasureTpmOperationsInternal));
|
|
}
|
|
}
|
|
|
|
} // namespace crypto
|