Skip to content

Commit

Permalink
Uplift of #18340 (squashed) to beta
Browse files Browse the repository at this point in the history
  • Loading branch information
brave-builds committed May 8, 2023
1 parent f99664e commit 3a43f14
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 50 deletions.
6 changes: 5 additions & 1 deletion components/p3a/constellation_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ bool ConstellationHelper::ConstructFinalMessage(
const rust::Vec<constellation::VecU8>& resp_proofs,
std::string* output) {
auto* rnd_server_info = rand_meta_manager_.GetCachedRandomnessServerInfo();
DCHECK(rnd_server_info);
if (!rnd_server_info) {
LOG(ERROR) << "ConstellationHelper: failed to get server info while "
"constructing message";
return false;
}
auto msg_res = constellation::construct_message(
resp_points, resp_proofs, *randomness_request_state,
resp_proofs.empty() ? *null_public_key_ : *rnd_server_info->public_key,
Expand Down
2 changes: 1 addition & 1 deletion components/p3a/constellation_log_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ constexpr char kPrefName[] = "p3a.constellation_logs";
ConstellationLogStore::ConstellationLogStore(PrefService& local_state,
size_t keep_epoch_count)
: local_state_(local_state), keep_epoch_count_(keep_epoch_count) {
DCHECK_GT(keep_epoch_count, 0U);
CHECK_GT(keep_epoch_count, 0U);
}

ConstellationLogStore::~ConstellationLogStore() = default;
Expand Down
11 changes: 8 additions & 3 deletions components/p3a/message_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,9 @@ void MessageManager::DoConstellationRotation() {
return;
}
constellation_prep_scheduler_->Stop();
constellation_prep_log_store_->ResetUploadStamps();
VLOG(2) << "MessageManager doing Constellation rotation at "
<< base::Time::Now();
constellation_helper_->UpdateRandomnessServerInfo();
delegate_->OnRotation(MetricLogType::kTypical, true);
}

void MessageManager::OnLogUploadComplete(bool is_ok,
Expand Down Expand Up @@ -206,7 +204,14 @@ void MessageManager::OnRandomnessServerInfoReady(
if (server_info == nullptr || !features::IsConstellationEnabled()) {
return;
}
VLOG(2) << "MessageManager::OnRandomnessServerInfoReady";
VLOG(2) << "MessageManager::OnRandomnessServerInfoReady; epoch change = "
<< server_info->epoch_change_detected;
if (server_info->epoch_change_detected) {
// a detected epoch change means that we can rotate
// the preparation store
constellation_prep_log_store_->ResetUploadStamps();
delegate_->OnRotation(MetricLogType::kTypical, true);
}
constellation_send_log_store_->SetCurrentEpoch(server_info->current_epoch);
constellation_send_log_store_->LoadPersistedUnsentLogs();
constellation_prep_scheduler_->Start();
Expand Down
28 changes: 19 additions & 9 deletions components/p3a/nitro_utils/attestation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ namespace nitro_utils {

namespace {

constexpr char kHashPrefix[] = "sha256:";
constexpr size_t kHashPrefixLength = 7;
constexpr size_t kSHA256HashLength = 32;
constexpr size_t kUserDataMinLength = kSHA256HashLength + kHashPrefixLength;
constexpr size_t kAttestationBodyMaxSize = 16384;
constexpr net::SHA256HashValue kAWSRootCertFP{
.data = {0x64, 0x1A, 0x03, 0x21, 0xA3, 0xE2, 0x44, 0xEF, 0xE4, 0x56, 0x46,
Expand Down Expand Up @@ -81,19 +85,25 @@ bool VerifyNonce(const cbor::Value::MapValue& cose_map,

bool VerifyUserDataKey(scoped_refptr<net::X509Certificate> server_cert,
const cbor::Value::MapValue& cose_map) {
DCHECK(server_cert);
CHECK(server_cert);

const auto user_data_it = cose_map.find(cbor::Value("user_data"));
if (user_data_it == cose_map.end() || !user_data_it->second.is_bytestring() ||
user_data_it->second.GetBytestring().size() != 32) {
user_data_it->second.GetBytestring().size() < kUserDataMinLength) {
LOG(ERROR) << "Nitro verification: user data is missing or is not bstr "
<< "or is not 32 bytes";
<< "or is not at least " << kUserDataMinLength << " bytes";
return false;
}
if (memcmp(user_data_it->second.GetBytestring().data(), kHashPrefix,
kHashPrefixLength) != 0) {
LOG(ERROR) << "Nitro verification: user data is missing sha256 hash prefix";
return false;
}
const net::SHA256HashValue server_cert_fp =
net::X509Certificate::CalculateFingerprint256(server_cert->cert_buffer());
if (memcmp(server_cert_fp.data, user_data_it->second.GetBytestring().data(),
32) != 0) {
if (memcmp(server_cert_fp.data,
user_data_it->second.GetBytestring().data() + kHashPrefixLength,
kSHA256HashLength) != 0) {
LOG(ERROR)
<< "Nitro verification: server cert fp does not match user data fp, "
<< "user data = "
Expand Down Expand Up @@ -170,9 +180,10 @@ void ParseAndVerifyDocument(
return;
}

base::TrimString(*response_body, " ", response_body.get());
base::StringPiece trimmed_body =
base::TrimWhitespaceASCII(*response_body, base::TrimPositions::TRIM_ALL);
absl::optional<std::vector<uint8_t>> cose_encoded =
base::Base64Decode(*response_body);
base::Base64Decode(trimmed_body);
if (!cose_encoded.has_value()) {
LOG(ERROR) << "Nitro verification: Failed to decode base64 document";
std::move(result_callback).Run(scoped_refptr<net::X509Certificate>());
Expand All @@ -197,8 +208,7 @@ void ParseAndVerifyDocument(

const network::mojom::URLResponseHead* response_info =
url_loader->ResponseInfo();
DCHECK(response_info);
if (!response_info->ssl_info.has_value() ||
if (!response_info || !response_info->ssl_info.has_value() ||
response_info->ssl_info->cert == nullptr) {
LOG(ERROR) << "Nitro verification: ssl info is missing from response info";
std::move(result_callback).Run(scoped_refptr<net::X509Certificate>());
Expand Down
41 changes: 26 additions & 15 deletions components/p3a/nitro_utils/cose.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,22 @@ bool ConvertCoseSignatureToDER(const std::vector<uint8_t>& input,
}

BIGNUM* r_comp = BN_bin2bn(input.data(), kSignatureComponentSize, nullptr);
DCHECK(r_comp);
if (!r_comp) {
return false;
}
BIGNUM* s_comp = BN_bin2bn(input.data() + kSignatureComponentSize,
kSignatureComponentSize, nullptr);
DCHECK(s_comp);
if (!s_comp) {
BN_free(r_comp);
return false;
}

ECDSA_SIG* ecdsa_sig = ECDSA_SIG_new();
DCHECK(ecdsa_sig);
if (!ecdsa_sig) {
BN_free(r_comp);
BN_free(s_comp);
return false;
}

if (ECDSA_SIG_set0(ecdsa_sig, r_comp, s_comp) != 1) {
LOG(ERROR) << "COSE: Failed to construct ECDSA SIG struct";
Expand All @@ -53,7 +62,10 @@ bool ConvertCoseSignatureToDER(const std::vector<uint8_t>& input,
}

CBB sig_cbb;
DCHECK_EQ(CBB_init(&sig_cbb, 0), 1);
if (CBB_init(&sig_cbb, 0) != 1) {
ECDSA_SIG_free(ecdsa_sig);
return false;
}

if (ECDSA_SIG_marshal(&sig_cbb, ecdsa_sig) != 1) {
LOG(ERROR) << "COSE: Failed to marshal ECDSA SIG struct";
Expand Down Expand Up @@ -91,9 +103,9 @@ bool CoseSign1::DecodeFromBytes(const std::vector<uint8_t>& data) {
*(cbor_config.error_code_out));
return false;
}
DCHECK(decoded_val.has_value());

if (!decoded_val->is_array() || decoded_val->GetArray().size() != 4) {
if (!decoded_val.has_value() || !decoded_val->is_array() ||
decoded_val->GetArray().size() != 4) {
LOG(ERROR) << "COSE: root decoded cbor is not array, or has incorrect size";
return false;
}
Expand All @@ -117,9 +129,8 @@ bool CoseSign1::DecodeFromBytes(const std::vector<uint8_t>& data) {
*(cbor_config.error_code_out));
return false;
}
DCHECK(protected_decoded_val.has_value());

if (!protected_decoded_val->is_map()) {
if (!protected_decoded_val.has_value() || !protected_decoded_val->is_map()) {
LOG(ERROR) << "COSE: protected value is not a map";
return false;
}
Expand Down Expand Up @@ -156,14 +167,14 @@ bool CoseSign1::DecodeFromBytes(const std::vector<uint8_t>& data) {

absl::optional<cbor::Value> payload_dec_val =
cbor::Reader::Read(payload_encoded_.GetBytestring(), cbor_config);
if (cbor_config.error_code_out != nullptr &&
*cbor_config.error_code_out !=
cbor::Reader::DecoderError::CBOR_NO_ERROR) {
if (!payload_dec_val.has_value() ||
(cbor_config.error_code_out != nullptr &&
*cbor_config.error_code_out !=
cbor::Reader::DecoderError::CBOR_NO_ERROR)) {
LOG(ERROR) << "COSE: failed to read payload cbor: "
<< cbor::Reader::ErrorCodeToString(*cbor_config.error_code_out);
return false;
}
DCHECK(payload_dec_val.has_value());
payload_ = payload_dec_val->Clone();

const cbor::Value& signature_val = cose_arr[3];
Expand All @@ -177,10 +188,10 @@ bool CoseSign1::DecodeFromBytes(const std::vector<uint8_t>& data) {
}

bool CoseSign1::Verify(const net::ParsedCertificateList& cert_chain) {
DCHECK_GT(cert_chain.size(), 1U);
CHECK_GT(cert_chain.size(), 1U);

net::der::GeneralizedTime time_now;
DCHECK(net::der::EncodeTimeAsGeneralizedTime(base::Time::Now(), &time_now));
CHECK(net::der::EncodeTimeAsGeneralizedTime(base::Time::Now(), &time_now));

net::CertPathErrors cert_path_errors;

Expand All @@ -205,7 +216,7 @@ bool CoseSign1::Verify(const net::ParsedCertificateList& cert_chain) {

absl::optional<std::vector<uint8_t>> encoded_sig_data =
cbor::Writer::Write(sig_data);
DCHECK(encoded_sig_data.has_value());
CHECK(encoded_sig_data.has_value());

base::StringPiece low_cert_spki;
if (!net::asn1::ExtractSPKIFromDERCert(
Expand Down
10 changes: 10 additions & 0 deletions components/p3a/p3a_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "base/check.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "brave/components/p3a/buildflags.h"
#include "brave/components/p3a/switches.h"

Expand Down Expand Up @@ -119,6 +120,15 @@ P3AConfig P3AConfig::LoadFromCommandLine() {
cmdline, switches::kP3AExpressRotationIntervalSeconds,
std::move(config.json_rotation_intervals[MetricLogType::kExpress]));

if (cmdline->HasSwitch(switches::kP3AFakeStarEpoch)) {
unsigned fake_star_epoch;
if (base::StringToUint(
cmdline->GetSwitchValueASCII(switches::kP3AFakeStarEpoch),
&fake_star_epoch)) {
config.fake_star_epoch = fake_star_epoch;
}
}

config.p3a_json_upload_url =
MaybeOverrideURLFromCommandLine(cmdline, switches::kP3AJsonUploadUrl,
std::move(config.p3a_json_upload_url));
Expand Down
4 changes: 4 additions & 0 deletions components/p3a/p3a_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "base/containers/flat_map.h"
#include "base/time/time.h"
#include "brave/components/p3a/metric_log_type.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"

namespace p3a {
Expand All @@ -22,6 +23,9 @@ struct P3AConfig {
// Interval between rotations, only used for testing from the command line.
base::flat_map<MetricLogType, base::TimeDelta> json_rotation_intervals;

// Fake STAR epoch for testing purposes.
absl::optional<uint8_t> fake_star_epoch = absl::nullopt;

// Endpoint for uploading P3A metrics in JSON format
GURL p3a_json_upload_url;
// Endpoint for uploading NTP-SI/creative P3A metrics in JSON format
Expand Down
Loading

0 comments on commit 3a43f14

Please sign in to comment.