• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/cert/internal/test_helpers.h"
11 
12 #include "base/base_paths.h"
13 #include "base/files/file_util.h"
14 #include "base/path_service.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/boringssl/src/include/openssl/pool.h"
17 #include "third_party/boringssl/src/pki/cert_errors.h"
18 #include "third_party/boringssl/src/pki/pem.h"
19 
20 namespace net {
21 
ReadTestDataFromPemFile(const std::string & file_path_ascii,const PemBlockMapping * mappings,size_t mappings_length)22 ::testing::AssertionResult ReadTestDataFromPemFile(
23     const std::string& file_path_ascii,
24     const PemBlockMapping* mappings,
25     size_t mappings_length) {
26   std::string file_data = ReadTestFileToString(file_path_ascii);
27 
28   // mappings_copy is used to keep track of which mappings have already been
29   // satisfied (by nulling the |value| field). This is used to track when
30   // blocks are multiply defined.
31   std::vector<PemBlockMapping> mappings_copy(mappings,
32                                              mappings + mappings_length);
33 
34   // Build the |pem_headers| vector needed for PEMTokenzier.
35   std::vector<std::string> pem_headers;
36   for (const auto& mapping : mappings_copy) {
37     pem_headers.push_back(mapping.block_name);
38   }
39 
40   bssl::PEMTokenizer pem_tokenizer(file_data, pem_headers);
41   while (pem_tokenizer.GetNext()) {
42     for (auto& mapping : mappings_copy) {
43       // Find the mapping for this block type.
44       if (pem_tokenizer.block_type() == mapping.block_name) {
45         if (!mapping.value) {
46           return ::testing::AssertionFailure()
47                  << "PEM block defined multiple times: " << mapping.block_name;
48         }
49 
50         // Copy the data to the result.
51         mapping.value->assign(pem_tokenizer.data());
52 
53         // Mark the mapping as having been satisfied.
54         mapping.value = nullptr;
55       }
56     }
57   }
58 
59   // Ensure that all specified blocks were found.
60   for (const auto& mapping : mappings_copy) {
61     if (mapping.value && !mapping.optional) {
62       return ::testing::AssertionFailure()
63              << "PEM block missing: " << mapping.block_name;
64     }
65   }
66 
67   return ::testing::AssertionSuccess();
68 }
69 
ReadCertChainFromFile(const std::string & file_path_ascii,bssl::ParsedCertificateList * chain)70 bool ReadCertChainFromFile(const std::string& file_path_ascii,
71                            bssl::ParsedCertificateList* chain) {
72   // Reset all the out parameters to their defaults.
73   chain->clear();
74 
75   std::string file_data = ReadTestFileToString(file_path_ascii);
76   if (file_data.empty()) {
77     return false;
78   }
79 
80   std::vector<std::string> pem_headers = {"CERTIFICATE"};
81 
82   bssl::PEMTokenizer pem_tokenizer(file_data, pem_headers);
83   while (pem_tokenizer.GetNext()) {
84     const std::string& block_data = pem_tokenizer.data();
85 
86     bssl::CertErrors errors;
87     if (!bssl::ParsedCertificate::CreateAndAddToVector(
88             bssl::UniquePtr<CRYPTO_BUFFER>(CRYPTO_BUFFER_new(
89                 reinterpret_cast<const uint8_t*>(block_data.data()),
90                 block_data.size(), nullptr)),
91             {}, chain, &errors)) {
92       ADD_FAILURE() << errors.ToDebugString();
93       return false;
94     }
95   }
96 
97   return true;
98 }
99 
ReadCertFromFile(const std::string & file_path_ascii)100 std::shared_ptr<const bssl::ParsedCertificate> ReadCertFromFile(
101     const std::string& file_path_ascii) {
102   bssl::ParsedCertificateList chain;
103   if (!ReadCertChainFromFile(file_path_ascii, &chain)) {
104     return nullptr;
105   }
106   if (chain.size() != 1) {
107     return nullptr;
108   }
109   return chain[0];
110 }
111 
ReadTestFileToString(const std::string & file_path_ascii)112 std::string ReadTestFileToString(const std::string& file_path_ascii) {
113   // Compute the full path, relative to the src/ directory.
114   base::FilePath src_root;
115   base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &src_root);
116   base::FilePath filepath = src_root.AppendASCII(file_path_ascii);
117 
118   // Read the full contents of the file.
119   std::string file_data;
120   if (!base::ReadFileToString(filepath, &file_data)) {
121     ADD_FAILURE() << "Couldn't read file: " << filepath.value();
122     return std::string();
123   }
124 
125   return file_data;
126 }
127 
128 }  // namespace net
129