forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This CL adds the following events - Latency for create, restore from wrapped and sign message - Success/failure and algo for each action See: Latency: https://screenshot.googleplex.com/9zbPzLDsuPX7CEh Success: https://screenshot.googleplex.com/4WhUsF7chKeo9Q7 Bug: 1341286 Change-Id: I274480986332e97a3bfde22739e001df9d7842be Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3884723 Reviewed-by: Alex Ilin <alexilin@chromium.org> Reviewed-by: Adam Langley <agl@chromium.org> Commit-Queue: Kristian Monsen <kristianm@chromium.org> Cr-Commit-Position: refs/heads/main@{#1047569}
- Loading branch information
Kristian Monsen
authored and
Chromium LUCI CQ
committed
Sep 15, 2022
1 parent
5e150ee
commit d39acd1
Showing
8 changed files
with
320 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
// 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() { | ||
const 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// 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. | ||
|
||
#ifndef CRYPTO_UNEXPORTABLE_KEY_METRICS_H_ | ||
#define CRYPTO_UNEXPORTABLE_KEY_METRICS_H_ | ||
|
||
#include "crypto/crypto_export.h" | ||
|
||
namespace crypto { | ||
|
||
// Records UMA metrics of TPM availability, latency and successful usage. | ||
// Does the work on a new background task. | ||
CRYPTO_EXPORT void MaybeMeasureTpmOperations(); | ||
|
||
// internal namespace to be used by tests only | ||
namespace internal { | ||
|
||
// Note that values here are used in a recorded histogram. Don't change | ||
// the values of existing members. | ||
enum class TPMSupport { | ||
kNone = 0, | ||
kRSA = 1, | ||
kECDSA = 2, | ||
kMaxValue = 2, | ||
}; | ||
|
||
// Exported for testing | ||
CRYPTO_EXPORT void MeasureTpmOperationsInternalForTesting(); | ||
} // namespace internal | ||
|
||
} // namespace crypto | ||
|
||
#endif // CRYPTO_UNEXPORTABLE_KEY_METRICS_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// 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/test/metrics/histogram_tester.h" | ||
#include "crypto/scoped_mock_unexportable_key_provider.h" | ||
#include "crypto/signature_verifier.h" | ||
#include "testing/gtest/include/gtest/gtest.h" | ||
|
||
namespace { | ||
|
||
// Note mock provider only supports ECDSA | ||
TEST(UnexportableKeyMetricTest, GatherAllMetrics) { | ||
crypto::ScopedMockUnexportableKeyProvider scoped_mock_key_provider; | ||
|
||
base::HistogramTester histogram_tester; | ||
histogram_tester.ExpectTotalCount("Crypto.TPMSupport2", 0); | ||
histogram_tester.ExpectTotalCount("Crypto.TPMDuration.NewKeyCreationECDSA", | ||
0); | ||
histogram_tester.ExpectTotalCount( | ||
"Crypto.TPMDuration.WrappedKeyCreationECDSA", 0); | ||
histogram_tester.ExpectTotalCount("Crypto.TPMDuration.MessageSigningECDSA", | ||
0); | ||
histogram_tester.ExpectTotalCount("Crypto.TPMOperation.NewKeyCreation", 0); | ||
histogram_tester.ExpectTotalCount("Crypto.TPMOperation.WrappedKeyCreation", | ||
0); | ||
histogram_tester.ExpectTotalCount("Crypto.TPMOperation.MessageSigning", 0); | ||
histogram_tester.ExpectTotalCount("Crypto.TPMOperation.MessageVerify", 0); | ||
|
||
crypto::internal::MeasureTpmOperationsInternalForTesting(); | ||
|
||
EXPECT_THAT( | ||
histogram_tester.GetAllSamples("Crypto.TPMSupport2"), | ||
BucketsAre(base::Bucket(crypto::internal::TPMSupport::kECDSA, 1))); | ||
histogram_tester.ExpectTotalCount("Crypto.TPMDuration.NewKeyCreationECDSA", | ||
1); | ||
histogram_tester.ExpectTotalCount( | ||
"Crypto.TPMDuration.WrappedKeyCreationECDSA", 1); | ||
histogram_tester.ExpectTotalCount("Crypto.TPMDuration.MessageSigningECDSA", | ||
1); | ||
EXPECT_THAT( | ||
histogram_tester.GetAllSamples("Crypto.TPMOperation.NewKeyCreationECDSA"), | ||
BucketsAre(base::Bucket(true, 1))); | ||
EXPECT_THAT(histogram_tester.GetAllSamples( | ||
"Crypto.TPMOperation.WrappedKeyCreationECDSA"), | ||
BucketsAre(base::Bucket(true, 1))); | ||
EXPECT_THAT( | ||
histogram_tester.GetAllSamples("Crypto.TPMOperation.MessageSigningECDSA"), | ||
BucketsAre(base::Bucket(true, 1))); | ||
EXPECT_THAT( | ||
histogram_tester.GetAllSamples("Crypto.TPMOperation.MessageVerifyECDSA"), | ||
BucketsAre(base::Bucket(true, 1))); | ||
} | ||
|
||
} // namespace |
Oops, something went wrong.