verify_using_cert_verify_proc.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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/verify_using_cert_verify_proc.h"
  5. #include <iostream>
  6. #include "base/cxx17_backports.h"
  7. #include "base/strings/strcat.h"
  8. #include "base/strings/string_util.h"
  9. #include "base/strings/stringprintf.h"
  10. #include "crypto/sha2.h"
  11. #include "net/base/net_errors.h"
  12. #include "net/cert/cert_verifier.h"
  13. #include "net/cert/cert_verify_proc.h"
  14. #include "net/cert/cert_verify_result.h"
  15. #include "net/cert/test_root_certs.h"
  16. #include "net/cert/x509_certificate.h"
  17. #include "net/cert/x509_util.h"
  18. #include "net/log/net_log_with_source.h"
  19. #include "net/tools/cert_verify_tool/cert_verify_tool_util.h"
  20. namespace {
  21. // Associates a printable name with an integer constant. Useful for providing
  22. // human-readable decoding of bitmask values.
  23. struct StringToConstant {
  24. const char* name;
  25. const int constant;
  26. };
  27. const StringToConstant kCertStatusFlags[] = {
  28. #define CERT_STATUS_FLAG(label, value) {#label, value},
  29. #include "net/cert/cert_status_flags_list.h"
  30. #undef CERT_STATUS_FLAG
  31. };
  32. // Writes a PEM-encoded file of |cert| and its chain.
  33. bool DumpX509CertificateChain(const base::FilePath& file_path,
  34. const net::X509Certificate* cert) {
  35. std::vector<std::string> pem_encoded;
  36. if (!cert->GetPEMEncodedChain(&pem_encoded)) {
  37. std::cerr << "ERROR: X509Certificate::GetPEMEncodedChain failed.\n";
  38. return false;
  39. }
  40. return WriteToFile(file_path, base::StrCat(pem_encoded));
  41. }
  42. void PrintCertStatus(int cert_status) {
  43. std::cout << base::StringPrintf("CertStatus: 0x%x\n", cert_status);
  44. for (const auto& flag : kCertStatusFlags) {
  45. if ((cert_status & flag.constant) == flag.constant)
  46. std::cout << " " << flag.name << "\n";
  47. }
  48. }
  49. } // namespace
  50. void PrintCertVerifyResult(const net::CertVerifyResult& result) {
  51. PrintDebugData(&result);
  52. PrintCertStatus(result.cert_status);
  53. if (result.has_sha1)
  54. std::cout << "has_sha1\n";
  55. if (result.has_sha1_leaf)
  56. std::cout << "has_sha1_leaf\n";
  57. if (result.is_issued_by_known_root)
  58. std::cout << "is_issued_by_known_root\n";
  59. if (result.is_issued_by_additional_trust_anchor)
  60. std::cout << "is_issued_by_additional_trust_anchor\n";
  61. if (result.verified_cert) {
  62. std::cout << "chain:\n "
  63. << FingerPrintCryptoBuffer(result.verified_cert->cert_buffer())
  64. << " " << SubjectFromX509Certificate(result.verified_cert.get())
  65. << "\n";
  66. for (const auto& intermediate :
  67. result.verified_cert->intermediate_buffers()) {
  68. std::cout << " " << FingerPrintCryptoBuffer(intermediate.get()) << " "
  69. << SubjectFromCryptoBuffer(intermediate.get()) << "\n";
  70. }
  71. }
  72. }
  73. bool VerifyUsingCertVerifyProc(
  74. net::CertVerifyProc* cert_verify_proc,
  75. const CertInput& target_der_cert,
  76. const std::string& hostname,
  77. const std::vector<CertInput>& intermediate_der_certs,
  78. const std::vector<CertInput>& root_der_certs,
  79. net::CRLSet* crl_set,
  80. const base::FilePath& dump_path) {
  81. std::vector<base::StringPiece> der_cert_chain;
  82. der_cert_chain.push_back(target_der_cert.der_cert);
  83. for (const auto& cert : intermediate_der_certs)
  84. der_cert_chain.push_back(cert.der_cert);
  85. scoped_refptr<net::X509Certificate> x509_target_and_intermediates =
  86. net::X509Certificate::CreateFromDERCertChain(der_cert_chain);
  87. if (!x509_target_and_intermediates) {
  88. std::cerr
  89. << "ERROR: X509Certificate::CreateFromDERCertChain failed on one or "
  90. "more of:\n";
  91. PrintCertError(" (target)", target_der_cert);
  92. for (const auto& cert : intermediate_der_certs)
  93. PrintCertError(" (intermediate)", cert);
  94. return false;
  95. }
  96. net::CertificateList x509_additional_trust_anchors;
  97. for (const auto& cert : root_der_certs) {
  98. scoped_refptr<net::X509Certificate> x509_root =
  99. net::X509Certificate::CreateFromBytes(
  100. base::as_bytes(base::make_span(cert.der_cert)));
  101. if (!x509_root)
  102. PrintCertError("ERROR: X509Certificate::CreateFromBytes failed:", cert);
  103. else
  104. x509_additional_trust_anchors.push_back(x509_root);
  105. }
  106. // TODO(mattm): add command line flags to configure VerifyFlags.
  107. int flags = 0;
  108. // Not all platforms support providing additional trust anchors to the
  109. // verifier. To workaround this, use TestRootCerts to modify the
  110. // system trust store globally.
  111. net::TestRootCerts* test_root_certs = net::TestRootCerts::GetInstance();
  112. CHECK(test_root_certs->IsEmpty());
  113. net::ScopedTestRoot scoped_test_roots;
  114. if (!x509_additional_trust_anchors.empty() &&
  115. !cert_verify_proc->SupportsAdditionalTrustAnchors()) {
  116. std::cerr << "NOTE: Additional trust anchors not supported on this "
  117. "platform. Using TestRootCerts instead.\n";
  118. scoped_test_roots.Reset(x509_additional_trust_anchors);
  119. x509_additional_trust_anchors.clear();
  120. }
  121. // TODO(crbug.com/634484): use a real netlog and print the results?
  122. net::CertVerifyResult result;
  123. int rv = cert_verify_proc->Verify(
  124. x509_target_and_intermediates.get(), hostname,
  125. /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags,
  126. crl_set, x509_additional_trust_anchors, &result, net::NetLogWithSource());
  127. std::cout << "CertVerifyProc result: " << net::ErrorToShortString(rv) << "\n";
  128. PrintCertVerifyResult(result);
  129. if (!dump_path.empty() && result.verified_cert) {
  130. if (!DumpX509CertificateChain(dump_path, result.verified_cert.get())) {
  131. return false;
  132. }
  133. }
  134. return rv == net::OK;
  135. }