Commit c9ffcf56 authored by Leonid Baraz's avatar Leonid Baraz Committed by Chromium LUCI CQ

Signature verification by the client.

Uses well-known public key for verification.
For the time being only DEV key is verified.

Bug: b:170054326
Bug: b:177569962
Change-Id: I16c2b9c730f1dbc39a725c958a284863d55921d2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2630426Reviewed-by: default avatarZach Trudo <zatrudo@google.com>
Commit-Queue: Leonid Baraz <lbaraz@chromium.org>
Auto-Submit: Leonid Baraz <lbaraz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843802}
parent b51d52ad
...@@ -9,6 +9,33 @@ ...@@ -9,6 +9,33 @@
namespace reporting { namespace reporting {
namespace {
// Well-known public signature verification keys.
constexpr uint8_t kProdVerificationKey[ED25519_PUBLIC_KEY_LEN] = {
0x51, 0x2D, 0x53, 0xA3, 0xF5, 0xEB, 0x01, 0xCE, 0xDA, 0xFC, 0x8E,
0x79, 0xE7, 0x0F, 0xE1, 0x65, 0xDC, 0x14, 0x86, 0x53, 0x8B, 0x97,
0x5A, 0x2D, 0x70, 0x08, 0xCB, 0xCA, 0x60, 0xC3, 0x55, 0xE6};
constexpr uint8_t kDevVerificationKey[ED25519_PUBLIC_KEY_LEN] = {
0xC6, 0x2C, 0x4D, 0x25, 0x9E, 0x3E, 0x99, 0xA0, 0x2E, 0x08, 0x15,
0x8C, 0x38, 0xB7, 0x6C, 0x08, 0xDF, 0xE7, 0x6E, 0x3A, 0xD6, 0x5A,
0xC5, 0x58, 0x09, 0xE4, 0xAB, 0x89, 0x3A, 0x31, 0x53, 0x07};
} // namespace
// static
base::StringPiece SignatureVerifier::VerificationKey() {
return base::StringPiece(reinterpret_cast<const char*>(kProdVerificationKey),
ED25519_PUBLIC_KEY_LEN);
}
// static
base::StringPiece SignatureVerifier::VerificationKeyDev() {
return base::StringPiece(reinterpret_cast<const char*>(kDevVerificationKey),
ED25519_PUBLIC_KEY_LEN);
}
SignatureVerifier::SignatureVerifier(base::StringPiece verification_public_key) SignatureVerifier::SignatureVerifier(base::StringPiece verification_public_key)
: verification_public_key_(verification_public_key) {} : verification_public_key_(verification_public_key) {}
......
...@@ -16,6 +16,12 @@ namespace reporting { ...@@ -16,6 +16,12 @@ namespace reporting {
// the server. It uses boringssl implementation available on the client. // the server. It uses boringssl implementation available on the client.
class SignatureVerifier { class SignatureVerifier {
public: public:
// Well-known public signature verification keys that is used to verify
// that signed data is indeed originating from reporting server.
// Exists in two flavors: PROD and DEV.
static base::StringPiece VerificationKey();
static base::StringPiece VerificationKeyDev();
// Ed25519 |verification_public_key| must consist of ED25519_PUBLIC_KEY_LEN // Ed25519 |verification_public_key| must consist of ED25519_PUBLIC_KEY_LEN
// bytes. // bytes.
explicit SignatureVerifier(base::StringPiece verification_public_key); explicit SignatureVerifier(base::StringPiece verification_public_key);
......
...@@ -100,5 +100,55 @@ TEST_F(VerificationTest, SignAndFailBadPublicKey) { ...@@ -100,5 +100,55 @@ TEST_F(VerificationTest, SignAndFailBadPublicKey) {
EXPECT_THAT(status.message(), HasSubstr("Verification failed")); EXPECT_THAT(status.message(), HasSubstr("Verification failed"));
} }
TEST_F(VerificationTest, ValidateFixedKey) {
// |dev_data_to_sign| is signed on DEV server, producing
// |dev_server_signature|.
static constexpr uint8_t dev_data_to_sign[]{
0x4D, 0x22, 0x5C, 0x4C, 0x74, 0x23, 0x82, 0x80, 0x58, 0xA2, 0x31, 0xA2,
0xC6, 0xE2, 0x6D, 0xDA, 0x48, 0x82, 0x7A, 0x9C, 0xF7, 0xD0, 0x4A, 0xF2,
0xFD, 0x19, 0x03, 0x7F, 0xC5, 0x6F, 0xBB, 0x49, 0xAF, 0x91, 0x7B, 0x74};
static constexpr uint8_t dev_server_signature[ED25519_SIGNATURE_LEN] = {
0x0C, 0xA4, 0xAF, 0xE3, 0x27, 0x06, 0xD1, 0x4F, 0x0E, 0x05, 0x44,
0x74, 0x0D, 0x4F, 0xA0, 0x4C, 0x26, 0xB1, 0x0C, 0x44, 0x92, 0x0F,
0x96, 0xAF, 0x5A, 0x7E, 0x45, 0xED, 0x61, 0xB7, 0x87, 0xA8, 0xA3,
0x98, 0x52, 0x97, 0x8D, 0x56, 0xA3, 0xED, 0xF7, 0x9B, 0x54, 0x17,
0x61, 0x32, 0x6C, 0x06, 0x29, 0xBF, 0x30, 0x4E, 0x88, 0x72, 0xAB,
0xE3, 0x60, 0xDA, 0xF0, 0x37, 0xEB, 0x56, 0x28, 0x0B};
// Validate the signature using known DEV public key.
SignatureVerifier dev_verifier(SignatureVerifier::VerificationKeyDev());
const auto dev_result = dev_verifier.Verify(
std::string(reinterpret_cast<const char*>(dev_data_to_sign),
sizeof(dev_data_to_sign)),
std::string(reinterpret_cast<const char*>(dev_server_signature),
ED25519_SIGNATURE_LEN));
EXPECT_OK(dev_result) << dev_result;
// |prod_data_to_sign| is signed on PROD server, producing
// |prod_server_signature|.
static constexpr uint8_t prod_data_to_sign[] = {
0x4D, 0x22, 0x5C, 0x4C, 0x74, 0x23, 0x82, 0x80, 0x58, 0xA2, 0x31, 0xA2,
0xC6, 0xE2, 0x6D, 0xDA, 0x48, 0x82, 0x7A, 0x9C, 0xF7, 0xD0, 0x4A, 0xF2,
0xFD, 0x19, 0x03, 0x7F, 0xC5, 0x6F, 0xBB, 0x49, 0xAF, 0x91, 0x7B, 0x74};
static constexpr uint8_t prod_server_signature[ED25519_SIGNATURE_LEN] = {
0x0C, 0xA4, 0xAF, 0xE3, 0x27, 0x06, 0xD1, 0x4F, 0x0E, 0x05, 0x44,
0x74, 0x0D, 0x4F, 0xA0, 0x4C, 0x26, 0xB1, 0x0C, 0x44, 0x92, 0x0F,
0x96, 0xAF, 0x5A, 0x7E, 0x45, 0xED, 0x61, 0xB7, 0x87, 0xA8, 0xA3,
0x98, 0x52, 0x97, 0x8D, 0x56, 0xA3, 0xED, 0xF7, 0x9B, 0x54, 0x17,
0x61, 0x32, 0x6C, 0x06, 0x29, 0xBF, 0x30, 0x4E, 0x88, 0x72, 0xAB,
0xE3, 0x60, 0xDA, 0xF0, 0x37, 0xEB, 0x56, 0x28, 0x0B};
// Validate the signature using known PROD public key.
SignatureVerifier prod_verifier(SignatureVerifier::VerificationKey());
const auto prod_result = prod_verifier.Verify(
std::string(reinterpret_cast<const char*>(prod_data_to_sign),
sizeof(prod_data_to_sign)),
std::string(reinterpret_cast<const char*>(prod_server_signature),
ED25519_SIGNATURE_LEN));
// TODO(b/177569962): Replace |prod_data_to_sign| and |prod_server_signature|,
// revert EXPECTs to EXPECT_OK once PROD key is rolled out.
EXPECT_THAT(prod_result.code(), Eq(error::INVALID_ARGUMENT)) << prod_result;
EXPECT_THAT(prod_result.message(), HasSubstr("Verification failed"));
}
} // namespace } // namespace
} // namespace reporting } // namespace reporting
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/policy/messaging_layer/encryption/verification.h"
#include "chrome/browser/policy/messaging_layer/public/report_queue.h" #include "chrome/browser/policy/messaging_layer/public/report_queue.h"
#include "chrome/browser/policy/messaging_layer/public/report_queue_configuration.h" #include "chrome/browser/policy/messaging_layer/public/report_queue_configuration.h"
#include "chrome/browser/policy/messaging_layer/storage/storage_configuration.h" #include "chrome/browser/policy/messaging_layer/storage/storage_configuration.h"
...@@ -427,7 +428,10 @@ void ReportingClient::InitializingContext::ConfigureStorageModule() { ...@@ -427,7 +428,10 @@ void ReportingClient::InitializingContext::ConfigureStorageModule() {
base::FilePath reporting_path = user_data_dir.Append(kReportingDirectory); base::FilePath reporting_path = user_data_dir.Append(kReportingDirectory);
StorageModule::Create( StorageModule::Create(
StorageOptions().set_directory(reporting_path), StorageOptions()
.set_directory(reporting_path)
.set_signature_verification_public_key(
SignatureVerifier::VerificationKey()),
std::move(start_upload_cb_), base::MakeRefCounted<EncryptionModule>(), std::move(start_upload_cb_), base::MakeRefCounted<EncryptionModule>(),
base::BindOnce( base::BindOnce(
&ReportingClient::InitializingContext::OnStorageModuleConfigured, &ReportingClient::InitializingContext::OnStorageModuleConfigured,
......
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