Commit c209bfbf authored by Matt Mueller's avatar Matt Mueller Committed by Commit Bot

Record debug data from net::CertVerifyProcMac, plumb it into...

Record debug data from net::CertVerifyProcMac, plumb it into TrialComparisonCertVerifier error reports.

Bug: 991247
Change-Id: I59227f0544b4d05312eaab3df09a8121fa39c3c4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1856625Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarRyan Sleevi <rsleevi@chromium.org>
Commit-Queue: Matt Mueller <mattm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706037}
parent 82e6f94c
......@@ -184,6 +184,28 @@ message CertLoggerRequest {
repeated CertStatus cert_status = 14;
};
message MacCertEvidenceInfo {
// A bitfield indicating various status of the cert, defined in
// cssmapple.h
optional uint32 status_bits = 1;
// CSSM_RETURN status codes for the cert, defined in cssmtype.h, values in
// cssmerr.h and cssmErrorStrings.h.
repeated int32 status_codes = 2;
}
message MacPlatformDebugInfo {
// The SecTrustResultType result from SecTrustEvaluate.
optional uint32 trust_result = 1;
// The OSStatus resultCode from SecTrustGetCssmResultCode.
optional int32 result_code = 2;
// The CSSM_TP_APPLE_EVIDENCE_INFO statusChain from SecTrustGetResult. Each
// entry corresponds to one of the certs in the verified chain (leaf first).
repeated MacCertEvidenceInfo status_chain = 3;
}
// Contains the results of verification by the trial verifier. All fields
// have the same meaning as those of the same name in CertLoggerRequest.
message TrialVerificationInfo {
......@@ -239,4 +261,7 @@ message TrialVerificationInfo {
// The GeneralizedTime encoded time when the trial verifier attempted to
// verify the chain.
optional string trial_der_verification_time = 9;
// Debug information from CertVerifyProcMac (if it was the primary verifier).
optional MacPlatformDebugInfo mac_platform_debug_info = 10;
}
......@@ -126,6 +126,25 @@ void AddMacTrustFlagsToReport(
#undef COPY_TRUST_FLAGS
}
void AddMacPlatformDebugInfoToReport(
const network::mojom::MacPlatformVerifierDebugInfoPtr&
mac_platform_debug_info,
chrome_browser_ssl::TrialVerificationInfo* trial_report) {
if (!mac_platform_debug_info)
return;
chrome_browser_ssl::MacPlatformDebugInfo* report_info =
trial_report->mutable_mac_platform_debug_info();
report_info->set_trust_result(mac_platform_debug_info->trust_result);
report_info->set_result_code(mac_platform_debug_info->result_code);
for (const auto& cert_info : mac_platform_debug_info->status_chain) {
chrome_browser_ssl::MacCertEvidenceInfo* report_cert_info =
report_info->add_status_chain();
report_cert_info->set_status_bits(cert_info->status_bits);
for (auto code : cert_info->status_codes)
report_cert_info->add_status_codes(code);
}
}
#endif // defined(OS_MACOSX)
#endif // BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
......@@ -189,6 +208,8 @@ CertificateErrorReport::CertificateErrorReport(
enable_sha1_local_anchors, disable_symantec_enforcement,
trial_report->mutable_verify_flags());
#if defined(OS_MACOSX)
AddMacPlatformDebugInfoToReport(debug_info->mac_platform_debug_info,
trial_report);
AddMacTrustFlagsToReport(
debug_info->mac_combined_trust_debug_info,
trial_report->mutable_mac_combined_trust_debug_info());
......
......@@ -348,6 +348,24 @@ TEST(ErrorReportTest, TrialDebugInfo) {
network::mojom::CertVerifierDebugInfoPtr debug_info =
network::mojom::CertVerifierDebugInfo::New();
#if defined(OS_MACOSX)
debug_info->mac_platform_debug_info =
network::mojom::MacPlatformVerifierDebugInfo::New();
debug_info->mac_platform_debug_info->trust_result = 1;
debug_info->mac_platform_debug_info->result_code = 20;
network::mojom::MacCertEvidenceInfoPtr info =
network::mojom::MacCertEvidenceInfo::New();
info->status_bits = 30;
info->status_codes = {40, 41};
debug_info->mac_platform_debug_info->status_chain.push_back(std::move(info));
info = network::mojom::MacCertEvidenceInfo::New();
info->status_bits = 50;
info->status_codes = {};
debug_info->mac_platform_debug_info->status_chain.push_back(std::move(info));
info = network::mojom::MacCertEvidenceInfo::New();
info->status_bits = 70;
info->status_codes = {80, 81, 82};
debug_info->mac_platform_debug_info->status_chain.push_back(std::move(info));
debug_info->mac_combined_trust_debug_info =
net::TrustStoreMac::TRUST_SETTINGS_DICT_CONTAINS_APPLICATION |
net::TrustStoreMac::TRUST_SETTINGS_DICT_CONTAINS_RESULT;
......@@ -369,6 +387,36 @@ TEST(ErrorReportTest, TrialDebugInfo) {
parsed.features_info().trial_verification_info();
#if defined(OS_MACOSX)
ASSERT_TRUE(trial_info.has_mac_platform_debug_info());
EXPECT_EQ(1U, trial_info.mac_platform_debug_info().trust_result());
EXPECT_EQ(20, trial_info.mac_platform_debug_info().result_code());
ASSERT_EQ(3, trial_info.mac_platform_debug_info().status_chain_size());
EXPECT_EQ(30U,
trial_info.mac_platform_debug_info().status_chain(0).status_bits());
ASSERT_EQ(
2,
trial_info.mac_platform_debug_info().status_chain(0).status_codes_size());
EXPECT_EQ(
40, trial_info.mac_platform_debug_info().status_chain(0).status_codes(0));
EXPECT_EQ(
41, trial_info.mac_platform_debug_info().status_chain(0).status_codes(1));
EXPECT_EQ(50U,
trial_info.mac_platform_debug_info().status_chain(1).status_bits());
EXPECT_EQ(
0,
trial_info.mac_platform_debug_info().status_chain(1).status_codes_size());
EXPECT_EQ(70U,
trial_info.mac_platform_debug_info().status_chain(2).status_bits());
ASSERT_EQ(
3,
trial_info.mac_platform_debug_info().status_chain(2).status_codes_size());
EXPECT_EQ(
80, trial_info.mac_platform_debug_info().status_chain(2).status_codes(0));
EXPECT_EQ(
81, trial_info.mac_platform_debug_info().status_chain(2).status_codes(1));
EXPECT_EQ(
82, trial_info.mac_platform_debug_info().status_chain(2).status_codes(2));
ASSERT_EQ(2, trial_info.mac_combined_trust_debug_info_size());
EXPECT_EQ(chrome_browser_ssl::TrialVerificationInfo::
MAC_TRUST_SETTINGS_DICT_CONTAINS_APPLICATION,
......
......@@ -59,6 +59,8 @@ namespace net {
namespace {
const void* kResultDebugDataKey = &kResultDebugDataKey;
typedef OSStatus (*SecTrustCopyExtendedResultFuncPtr)(SecTrustRef,
CFDictionaryRef*);
......@@ -404,6 +406,27 @@ void AppendPublicKeyHashesAndUpdateKnownRoot(CFArrayRef chain,
std::reverse(hashes->begin(), hashes->end());
}
void UpdateDebugData(SecTrustResultType trust_result,
OSStatus cssm_result,
CFIndex chain_length,
const CSSM_TP_APPLE_EVIDENCE_INFO* chain_info,
base::SupportsUserData* debug_data) {
std::vector<CertVerifyProcMac::ResultDebugData::CertEvidenceInfo>
status_chain;
for (CFIndex i = 0; i < chain_length; ++i) {
CertVerifyProcMac::ResultDebugData::CertEvidenceInfo info;
info.status_bits = chain_info[i].StatusBits;
for (uint32_t status_code_index = 0;
status_code_index < chain_info[i].NumStatusCodes;
++status_code_index) {
info.status_codes.push_back(chain_info[i].StatusCodes[status_code_index]);
}
status_chain.push_back(std::move(info));
}
CertVerifyProcMac::ResultDebugData::Create(
trust_result, cssm_result, std::move(status_chain), debug_data);
}
enum CRLSetResult {
kCRLSetOk,
kCRLSetRevoked,
......@@ -919,6 +942,9 @@ int VerifyWithGivenFlags(X509Certificate* cert,
// Evaluate the results
OSStatus cssm_result;
status = SecTrustGetCssmResultCode(trust_ref, &cssm_result);
if (status)
return NetErrorFromOSStatus(status);
switch (trust_result) {
case kSecTrustResultUnspecified:
case kSecTrustResultProceed:
......@@ -935,9 +961,6 @@ int VerifyWithGivenFlags(X509Certificate* cert,
case kSecTrustResultRecoverableTrustFailure:
// Certificate chain has a failure that can be overridden by the user.
status = SecTrustGetCssmResultCode(trust_ref, &cssm_result);
if (status)
return NetErrorFromOSStatus(status);
if (cssm_result == CSSMERR_TP_VERIFY_ACTION_FAILED) {
policy_failed = true;
} else {
......@@ -1013,9 +1036,6 @@ int VerifyWithGivenFlags(X509Certificate* cert,
break;
default:
status = SecTrustGetCssmResultCode(trust_ref, &cssm_result);
if (status)
return NetErrorFromOSStatus(status);
verify_result->cert_status |= CertStatusFromOSStatus(cssm_result);
if (!IsCertStatusError(verify_result->cert_status)) {
LOG(WARNING) << "trust_result=" << trust_result;
......@@ -1037,6 +1057,9 @@ int VerifyWithGivenFlags(X509Certificate* cert,
completed_chain, &verify_result->public_key_hashes,
&verify_result->is_issued_by_known_root);
UpdateDebugData(trust_result, cssm_result, CFArrayGetCount(completed_chain),
chain_info, verify_result);
if (IsCertStatusError(verify_result->cert_status))
return MapCertStatusToNetError(verify_result->cert_status);
......@@ -1045,9 +1068,55 @@ int VerifyWithGivenFlags(X509Certificate* cert,
} // namespace
CertVerifyProcMac::CertVerifyProcMac() {}
CertVerifyProcMac::ResultDebugData::CertEvidenceInfo::CertEvidenceInfo() =
default;
CertVerifyProcMac::ResultDebugData::CertEvidenceInfo::~CertEvidenceInfo() =
default;
CertVerifyProcMac::ResultDebugData::CertEvidenceInfo::CertEvidenceInfo(
const CertEvidenceInfo&) = default;
CertVerifyProcMac::ResultDebugData::CertEvidenceInfo::CertEvidenceInfo(
CertEvidenceInfo&&) = default;
CertVerifyProcMac::ResultDebugData::ResultDebugData(
uint32_t trust_result,
int32_t result_code,
std::vector<CertEvidenceInfo> status_chain)
: trust_result_(trust_result),
result_code_(result_code),
status_chain_(std::move(status_chain)) {}
CertVerifyProcMac::ResultDebugData::~ResultDebugData() = default;
CertVerifyProcMac::ResultDebugData::ResultDebugData(const ResultDebugData&) =
default;
// static
const CertVerifyProcMac::ResultDebugData*
CertVerifyProcMac::ResultDebugData::Get(
const base::SupportsUserData* debug_data) {
return static_cast<ResultDebugData*>(
debug_data->GetUserData(kResultDebugDataKey));
}
// static
void CertVerifyProcMac::ResultDebugData::Create(
uint32_t trust_result,
int32_t result_code,
std::vector<CertEvidenceInfo> status_chain,
base::SupportsUserData* debug_data) {
debug_data->SetUserData(kResultDebugDataKey,
std::make_unique<ResultDebugData>(
trust_result, result_code, status_chain));
}
std::unique_ptr<base::SupportsUserData::Data>
CertVerifyProcMac::ResultDebugData::Clone() {
return std::make_unique<ResultDebugData>(*this);
}
CertVerifyProcMac::CertVerifyProcMac() = default;
CertVerifyProcMac::~CertVerifyProcMac() {}
CertVerifyProcMac::~CertVerifyProcMac() = default;
bool CertVerifyProcMac::SupportsAdditionalTrustAnchors() const {
return false;
......
......@@ -5,6 +5,7 @@
#ifndef NET_CERT_CERT_VERIFY_PROC_MAC_H_
#define NET_CERT_CERT_VERIFY_PROC_MAC_H_
#include "base/supports_user_data.h"
#include "net/base/net_export.h"
#include "net/cert/cert_verify_proc.h"
......@@ -14,6 +15,53 @@ namespace net {
// Security.framework.
class NET_EXPORT_PRIVATE CertVerifyProcMac : public CertVerifyProc {
public:
class ResultDebugData : public base::SupportsUserData::Data {
public:
struct CertEvidenceInfo {
CertEvidenceInfo();
~CertEvidenceInfo();
CertEvidenceInfo(const CertEvidenceInfo&);
CertEvidenceInfo(CertEvidenceInfo&&);
// A bitfield indicating various status of the cert, defined in
// cssmapple.h
uint32_t status_bits;
// CSSM_RETURN status codes for the cert, defined in cssmtype.h, values in
// cssmerr.h and cssmErrorStrings.h.
std::vector<int32_t> status_codes;
};
ResultDebugData(uint32_t trust_result,
int32_t result_code,
std::vector<CertEvidenceInfo> status_chain);
~ResultDebugData() override;
ResultDebugData(const ResultDebugData&);
static const ResultDebugData* Get(const base::SupportsUserData* debug_data);
static void Create(uint32_t trust_result,
int32_t result_code,
std::vector<CertEvidenceInfo> status_chain,
base::SupportsUserData* debug_data);
// base::SupportsUserData::Data implementation:
std::unique_ptr<Data> Clone() override;
uint32_t trust_result() const { return trust_result_; }
int32_t result_code() const { return result_code_; }
const std::vector<CertEvidenceInfo>& status_chain() const {
return status_chain_;
}
private:
// The SecTrustResultType result from SecTrustEvaluate.
uint32_t trust_result_;
// The OSStatus resultCode from SecTrustGetCssmResultCode.
int32_t result_code_;
// The CSSM_TP_APPLE_EVIDENCE_INFO statusChain from SecTrustGetResult. Each
// entry corresponds to one of the certs in the verified chain (leaf first).
std::vector<CertEvidenceInfo> status_chain_;
};
CertVerifyProcMac();
bool SupportsAdditionalTrustAnchors() const override;
......
......@@ -12,6 +12,10 @@
#include "net/cert/pem_tokenizer.h"
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include <Security/Security.h>
#include "base/strings/sys_string_conversions.h"
#include "net/cert/cert_verify_proc_mac.h"
#include "net/cert/internal/trust_store_mac.h"
#endif
......@@ -51,6 +55,38 @@ void ExtractCertificatesFromData(const std::string& data_string,
certs->push_back(cert);
}
#if defined(OS_MACOSX) && !defined(OS_IOS)
std::string SecErrorStr(OSStatus err) {
base::ScopedCFTypeRef<CFStringRef> cfstr(
SecCopyErrorMessageString(err, nullptr));
return base::StringPrintf("%d(%s)", err,
base::SysCFStringRefToUTF8(cfstr).c_str());
}
std::string TrustResultStr(uint32_t trust_result) {
switch (trust_result) {
case kSecTrustResultInvalid:
return "kSecTrustResultInvalid";
case kSecTrustResultProceed:
return "kSecTrustResultProceed";
case 2: // kSecTrustResultConfirm SEC_DEPRECATED_ATTRIBUTE = 2,
return "kSecTrustResultConfirm";
case kSecTrustResultDeny:
return "kSecTrustResultDeny";
case kSecTrustResultUnspecified:
return "kSecTrustResultUnspecified";
case kSecTrustResultRecoverableTrustFailure:
return "kSecTrustResultRecoverableTrustFailure";
case kSecTrustResultFatalTrustFailure:
return "kSecTrustResultFatalTrustFailure";
case kSecTrustResultOtherError:
return "kSecTrustResultOtherError";
default:
return "UNKNOWN";
}
}
#endif
} // namespace
bool ReadCertificatesFromFile(const base::FilePath& file_path,
......@@ -106,6 +142,30 @@ void PrintCertError(const std::string& error, const CertInput& cert) {
void PrintDebugData(const base::SupportsUserData* debug_data) {
#if defined(OS_MACOSX) && !defined(OS_IOS)
auto* mac_platform_debug_info =
net::CertVerifyProcMac::ResultDebugData::Get(debug_data);
if (mac_platform_debug_info) {
std::cout << base::StringPrintf(
"CertVerifyProcMac::ResultDebugData: trust_result=%u(%s) "
"result_code=%s\n",
mac_platform_debug_info->trust_result(),
TrustResultStr(mac_platform_debug_info->trust_result()).c_str(),
SecErrorStr(mac_platform_debug_info->result_code()).c_str());
for (size_t i = 0; i < mac_platform_debug_info->status_chain().size();
++i) {
const auto& cert_info = mac_platform_debug_info->status_chain()[i];
std::string status_codes_str;
for (const auto code : cert_info.status_codes) {
if (!status_codes_str.empty())
status_codes_str += ',';
status_codes_str += SecErrorStr(code);
}
std::cout << base::StringPrintf(
" cert %zu: status_bits=0x%x status_codes=%s\n", i,
cert_info.status_bits, status_codes_str.c_str());
}
}
auto* mac_trust_debug_info =
net::TrustStoreMac::ResultDebugData::Get(debug_data);
if (mac_trust_debug_info) {
......
......@@ -18,6 +18,29 @@ interface TrialComparisonCertVerifierConfigClient {
OnTrialConfigUpdated(bool allowed);
};
[EnableIf=is_mac]
struct MacCertEvidenceInfo {
// A bitfield indicating various status of the cert, defined in cssmapple.h
uint32 status_bits;
// CSSM_RETURN status codes for the cert, defined in cssmtype.h, values in
// cssmerr.h and cssmErrorStrings.h.
array<int32> status_codes;
};
[EnableIf=is_mac]
struct MacPlatformVerifierDebugInfo {
// The SecTrustResultType result from SecTrustEvaluate.
uint32 trust_result;
// The OSStatus resultCode from SecTrustGetCssmResultCode.
int32 result_code;
// The CSSM_TP_APPLE_EVIDENCE_INFO statusChain from SecTrustGetResult. Each
// entry corresponds to one of the certs in the verified chain (leaf first).
array<MacCertEvidenceInfo> status_chain;
};
// Contains additional debugging data about the verification. This information
// does not change the meaning of the results.
struct CertVerifierDebugInfo {
......@@ -26,6 +49,9 @@ struct CertVerifierDebugInfo {
[EnableIf=is_mac]
int32 mac_combined_trust_debug_info;
[EnableIf=is_mac]
MacPlatformVerifierDebugInfo? mac_platform_debug_info;
// The time as seen by CertVerifyProcBuiltin, in raw timestamp and in
// exploded & encoded GeneralizedTime string.
mojo_base.mojom.Time trial_verification_time;
......
......@@ -14,6 +14,7 @@
#include "net/der/parse_values.h"
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include "net/cert/cert_verify_proc_mac.h"
#include "net/cert/internal/trust_store_mac.h"
#endif
......@@ -72,6 +73,25 @@ void TrialComparisonCertVerifierMojo::OnSendTrialReport(
network::mojom::CertVerifierDebugInfoPtr debug_info =
network::mojom::CertVerifierDebugInfo::New();
#if defined(OS_MACOSX) && !defined(OS_IOS)
auto* mac_platform_debug_info =
net::CertVerifyProcMac::ResultDebugData::Get(&primary_result);
if (mac_platform_debug_info) {
debug_info->mac_platform_debug_info =
network::mojom::MacPlatformVerifierDebugInfo::New();
debug_info->mac_platform_debug_info->trust_result =
mac_platform_debug_info->trust_result();
debug_info->mac_platform_debug_info->result_code =
mac_platform_debug_info->result_code();
for (const auto& cert_info : mac_platform_debug_info->status_chain()) {
network::mojom::MacCertEvidenceInfoPtr info =
network::mojom::MacCertEvidenceInfo::New();
info->status_bits = cert_info.status_bits;
info->status_codes = cert_info.status_codes;
debug_info->mac_platform_debug_info->status_chain.push_back(
std::move(info));
}
}
auto* mac_trust_debug_info =
net::TrustStoreMac::ResultDebugData::Get(&trial_result);
if (mac_trust_debug_info) {
......
......@@ -15,6 +15,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include "net/cert/cert_verify_proc_mac.h"
#include "net/cert/internal/trust_store_mac.h"
#endif
......@@ -97,6 +98,25 @@ TEST(TrialComparisonCertVerifierMojoTest, SendReportDebugInfo) {
trial_result.verified_cert = chain2;
#if defined(OS_MACOSX) && !defined(OS_IOS)
constexpr uint32_t kExpectedTrustResult = 4;
constexpr int32_t kExpectedResultCode = -12345;
std::vector<net::CertVerifyProcMac::ResultDebugData::CertEvidenceInfo>
expected_status_chain;
net::CertVerifyProcMac::ResultDebugData::CertEvidenceInfo info;
info.status_bits = 23456;
expected_status_chain.push_back(info);
info.status_bits = 34567;
info.status_codes.push_back(-4567);
info.status_codes.push_back(-56789);
expected_status_chain.push_back(info);
info.status_bits = 45678;
info.status_codes.clear();
info.status_codes.push_back(-97261);
expected_status_chain.push_back(info);
net::CertVerifyProcMac::ResultDebugData::Create(
kExpectedTrustResult, kExpectedResultCode, expected_status_chain,
&primary_result);
constexpr int kExpectedTrustDebugInfo = 0xABCD;
auto* mac_trust_debug_info =
net::TrustStoreMac::ResultDebugData::GetOrCreate(&trial_result);
......@@ -138,6 +158,22 @@ TEST(TrialComparisonCertVerifierMojoTest, SendReportDebugInfo) {
ASSERT_TRUE(report.debug_info);
#if defined(OS_MACOSX) && !defined(OS_IOS)
ASSERT_TRUE(report.debug_info->mac_platform_debug_info);
EXPECT_EQ(kExpectedTrustResult,
report.debug_info->mac_platform_debug_info->trust_result);
EXPECT_EQ(kExpectedResultCode,
report.debug_info->mac_platform_debug_info->result_code);
ASSERT_EQ(expected_status_chain.size(),
report.debug_info->mac_platform_debug_info->status_chain.size());
for (size_t i = 0; i < expected_status_chain.size(); ++i) {
EXPECT_EQ(expected_status_chain[i].status_bits,
report.debug_info->mac_platform_debug_info->status_chain[i]
->status_bits);
EXPECT_EQ(expected_status_chain[i].status_codes,
report.debug_info->mac_platform_debug_info->status_chain[i]
->status_codes);
}
EXPECT_EQ(kExpectedTrustDebugInfo,
report.debug_info->mac_combined_trust_debug_info);
#endif
......
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