cert_verify_tool_util.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/tools/cert_verify_tool/cert_verify_tool_util.h"
  5. #include <iostream>
  6. #include "base/files/file_util.h"
  7. #include "base/logging.h"
  8. #include "base/strings/string_number_conversions.h"
  9. #include "base/strings/stringprintf.h"
  10. #include "build/build_config.h"
  11. #include "net/cert/pem.h"
  12. #include "net/cert/x509_certificate.h"
  13. #include "net/cert/x509_util.h"
  14. #if BUILDFLAG(IS_MAC)
  15. #include <Security/Security.h>
  16. #include "base/strings/sys_string_conversions.h"
  17. #include "net/cert/cert_verify_proc_mac.h"
  18. #include "net/cert/internal/trust_store_mac.h"
  19. #endif
  20. namespace {
  21. // The PEM block header used for PEM-encoded DER certificates.
  22. const char kCertificateHeader[] = "CERTIFICATE";
  23. // Parses |data_string| as a single DER cert or a PEM certificate list.
  24. // This is an alternative to X509Certificate::CreateFrom[...] which
  25. // is designed to decouple the file input and decoding from the DER Certificate
  26. // parsing.
  27. void ExtractCertificatesFromData(const std::string& data_string,
  28. const base::FilePath& file_path,
  29. std::vector<CertInput>* certs) {
  30. net::PEMTokenizer pem_tokenizer(data_string, {kCertificateHeader});
  31. int block = 0;
  32. while (pem_tokenizer.GetNext()) {
  33. CertInput cert;
  34. cert.der_cert = pem_tokenizer.data();
  35. cert.source_file_path = file_path;
  36. cert.source_details =
  37. base::StringPrintf("%s block %i", kCertificateHeader, block);
  38. certs->push_back(cert);
  39. ++block;
  40. }
  41. // If it was a PEM file, return the extracted results.
  42. if (block)
  43. return;
  44. std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> pkcs7_cert_buffers;
  45. if (net::x509_util::CreateCertBuffersFromPKCS7Bytes(
  46. base::as_bytes(base::make_span(data_string)), &pkcs7_cert_buffers)) {
  47. int n = 0;
  48. for (const auto& cert_buffer : pkcs7_cert_buffers) {
  49. CertInput cert;
  50. cert.der_cert = std::string(
  51. net::x509_util::CryptoBufferAsStringPiece(cert_buffer.get()));
  52. cert.source_file_path = file_path;
  53. cert.source_details = base::StringPrintf("PKCS #7 cert %i", n);
  54. certs->push_back(cert);
  55. ++n;
  56. }
  57. return;
  58. }
  59. // Otherwise, assume it is a single DER cert.
  60. CertInput cert;
  61. cert.der_cert = data_string;
  62. cert.source_file_path = file_path;
  63. certs->push_back(cert);
  64. }
  65. #if BUILDFLAG(IS_MAC)
  66. std::string SecErrorStr(OSStatus err) {
  67. base::ScopedCFTypeRef<CFStringRef> cfstr(
  68. SecCopyErrorMessageString(err, nullptr));
  69. return base::StringPrintf("%d(%s)", err,
  70. base::SysCFStringRefToUTF8(cfstr).c_str());
  71. }
  72. std::string TrustResultStr(uint32_t trust_result) {
  73. switch (trust_result) {
  74. case kSecTrustResultInvalid:
  75. return "kSecTrustResultInvalid";
  76. case kSecTrustResultProceed:
  77. return "kSecTrustResultProceed";
  78. case 2: // kSecTrustResultConfirm SEC_DEPRECATED_ATTRIBUTE = 2,
  79. return "kSecTrustResultConfirm";
  80. case kSecTrustResultDeny:
  81. return "kSecTrustResultDeny";
  82. case kSecTrustResultUnspecified:
  83. return "kSecTrustResultUnspecified";
  84. case kSecTrustResultRecoverableTrustFailure:
  85. return "kSecTrustResultRecoverableTrustFailure";
  86. case kSecTrustResultFatalTrustFailure:
  87. return "kSecTrustResultFatalTrustFailure";
  88. case kSecTrustResultOtherError:
  89. return "kSecTrustResultOtherError";
  90. default:
  91. return "UNKNOWN";
  92. }
  93. }
  94. #endif
  95. } // namespace
  96. bool ReadCertificatesFromFile(const base::FilePath& file_path,
  97. std::vector<CertInput>* certs) {
  98. std::string file_data;
  99. if (!ReadFromFile(file_path, &file_data))
  100. return false;
  101. ExtractCertificatesFromData(file_data, file_path, certs);
  102. return true;
  103. }
  104. bool ReadChainFromFile(const base::FilePath& file_path,
  105. CertInput* target,
  106. std::vector<CertInput>* intermediates) {
  107. std::vector<CertInput> tmp_certs;
  108. if (!ReadCertificatesFromFile(file_path, &tmp_certs))
  109. return false;
  110. if (tmp_certs.empty())
  111. return true;
  112. *target = tmp_certs.front();
  113. intermediates->insert(intermediates->end(), ++tmp_certs.begin(),
  114. tmp_certs.end());
  115. return true;
  116. }
  117. bool ReadFromFile(const base::FilePath& file_path, std::string* file_data) {
  118. if (!base::ReadFileToString(file_path, file_data)) {
  119. std::cerr << "ERROR: ReadFileToString " << file_path.value() << ": "
  120. << strerror(errno) << "\n";
  121. return false;
  122. }
  123. return true;
  124. }
  125. bool WriteToFile(const base::FilePath& file_path, const std::string& data) {
  126. if (base::WriteFile(file_path, data.data(), data.size()) < 0) {
  127. std::cerr << "ERROR: WriteFile " << file_path.value() << ": "
  128. << strerror(errno) << "\n";
  129. return false;
  130. }
  131. return true;
  132. }
  133. void PrintCertError(const std::string& error, const CertInput& cert) {
  134. std::cerr << error << " " << cert.source_file_path.value();
  135. if (!cert.source_details.empty())
  136. std::cerr << " (" << cert.source_details << ")";
  137. std::cerr << "\n";
  138. }
  139. void PrintDebugData(const base::SupportsUserData* debug_data) {
  140. #if BUILDFLAG(IS_MAC)
  141. auto* mac_platform_debug_info =
  142. net::CertVerifyProcMac::ResultDebugData::Get(debug_data);
  143. if (mac_platform_debug_info) {
  144. std::cout << base::StringPrintf(
  145. "CertVerifyProcMac::ResultDebugData: trust_result=%u(%s) "
  146. "result_code=%s\n",
  147. mac_platform_debug_info->trust_result(),
  148. TrustResultStr(mac_platform_debug_info->trust_result()).c_str(),
  149. SecErrorStr(mac_platform_debug_info->result_code()).c_str());
  150. for (size_t i = 0; i < mac_platform_debug_info->status_chain().size();
  151. ++i) {
  152. const auto& cert_info = mac_platform_debug_info->status_chain()[i];
  153. std::string status_codes_str;
  154. for (const auto code : cert_info.status_codes) {
  155. if (!status_codes_str.empty())
  156. status_codes_str += ',';
  157. status_codes_str += SecErrorStr(code);
  158. }
  159. std::cout << base::StringPrintf(
  160. " cert %zu: status_bits=0x%x status_codes=%s\n", i,
  161. cert_info.status_bits, status_codes_str.c_str());
  162. }
  163. }
  164. auto* mac_trust_debug_info =
  165. net::TrustStoreMac::ResultDebugData::Get(debug_data);
  166. if (mac_trust_debug_info) {
  167. std::cout << base::StringPrintf(
  168. "TrustStoreMac::ResultDebugData::combined_trust_debug_info: 0x%x\n",
  169. mac_trust_debug_info->combined_trust_debug_info());
  170. }
  171. #endif
  172. }
  173. std::string FingerPrintCryptoBuffer(const CRYPTO_BUFFER* cert_handle) {
  174. net::SHA256HashValue hash =
  175. net::X509Certificate::CalculateFingerprint256(cert_handle);
  176. return base::HexEncode(hash.data, std::size(hash.data));
  177. }
  178. std::string SubjectFromX509Certificate(const net::X509Certificate* cert) {
  179. return cert->subject().GetDisplayName();
  180. }
  181. std::string SubjectFromCryptoBuffer(CRYPTO_BUFFER* cert_handle) {
  182. scoped_refptr<net::X509Certificate> cert =
  183. net::X509Certificate::CreateFromBuffer(bssl::UpRef(cert_handle), {});
  184. if (!cert)
  185. return std::string();
  186. return SubjectFromX509Certificate(cert.get());
  187. }