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