xref: /aosp_15_r20/external/cronet/net/cert/x509_util_apple_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2017 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/x509_util_apple.h"
6 
7 #include <string_view>
8 
9 #include "base/containers/span.h"
10 #include "build/build_config.h"
11 #include "net/cert/x509_certificate.h"
12 #include "net/cert/x509_util.h"
13 #include "net/test/cert_test_util.h"
14 #include "net/test/test_data_directory.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace net {
18 
19 namespace x509_util {
20 
21 namespace {
22 
BytesForSecCert(SecCertificateRef sec_cert)23 std::string BytesForSecCert(SecCertificateRef sec_cert) {
24   std::string result;
25   base::apple::ScopedCFTypeRef<CFDataRef> der_data(
26       SecCertificateCopyData(sec_cert));
27   if (!der_data) {
28     ADD_FAILURE();
29     return result;
30   }
31   result.assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data.get())),
32                 CFDataGetLength(der_data.get()));
33   return result;
34 }
35 
BytesForSecCert(const void * sec_cert)36 std::string BytesForSecCert(const void* sec_cert) {
37   return BytesForSecCert(
38       reinterpret_cast<SecCertificateRef>(const_cast<void*>(sec_cert)));
39 }
40 
41 }  // namespace
42 
TEST(X509UtilTest,CreateSecCertificateArrayForX509Certificate)43 TEST(X509UtilTest, CreateSecCertificateArrayForX509Certificate) {
44   scoped_refptr<X509Certificate> cert = CreateCertificateChainFromFile(
45       GetTestCertsDirectory(), "multi-root-chain1.pem",
46       X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
47   ASSERT_TRUE(cert);
48   EXPECT_EQ(3U, cert->intermediate_buffers().size());
49 
50   base::apple::ScopedCFTypeRef<CFMutableArrayRef> sec_certs(
51       CreateSecCertificateArrayForX509Certificate(cert.get()));
52   ASSERT_TRUE(sec_certs);
53   ASSERT_EQ(4, CFArrayGetCount(sec_certs.get()));
54   for (int i = 0; i < 4; ++i)
55     ASSERT_TRUE(CFArrayGetValueAtIndex(sec_certs.get(), i));
56 
57   EXPECT_EQ(x509_util::CryptoBufferAsStringPiece(cert->cert_buffer()),
58             BytesForSecCert(CFArrayGetValueAtIndex(sec_certs.get(), 0)));
59   EXPECT_EQ(x509_util::CryptoBufferAsStringPiece(
60                 cert->intermediate_buffers()[0].get()),
61             BytesForSecCert(CFArrayGetValueAtIndex(sec_certs.get(), 1)));
62   EXPECT_EQ(x509_util::CryptoBufferAsStringPiece(
63                 cert->intermediate_buffers()[1].get()),
64             BytesForSecCert(CFArrayGetValueAtIndex(sec_certs.get(), 2)));
65   EXPECT_EQ(x509_util::CryptoBufferAsStringPiece(
66                 cert->intermediate_buffers()[2].get()),
67             BytesForSecCert(CFArrayGetValueAtIndex(sec_certs.get(), 3)));
68 }
69 
TEST(X509UtilTest,CreateSecCertificateArrayForX509CertificateErrors)70 TEST(X509UtilTest, CreateSecCertificateArrayForX509CertificateErrors) {
71   scoped_refptr<X509Certificate> ok_cert(
72       ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"));
73   ASSERT_TRUE(ok_cert);
74 
75   bssl::UniquePtr<CRYPTO_BUFFER> bad_cert =
76       x509_util::CreateCryptoBuffer(std::string_view("invalid"));
77   ASSERT_TRUE(bad_cert);
78 
79   scoped_refptr<X509Certificate> ok_cert2(
80       ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem"));
81   ASSERT_TRUE(ok_cert);
82 
83   std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
84   intermediates.push_back(bssl::UpRef(bad_cert));
85   intermediates.push_back(bssl::UpRef(ok_cert2->cert_buffer()));
86   scoped_refptr<X509Certificate> cert_with_intermediates(
87       X509Certificate::CreateFromBuffer(bssl::UpRef(ok_cert->cert_buffer()),
88                                         std::move(intermediates)));
89   ASSERT_TRUE(cert_with_intermediates);
90   EXPECT_EQ(2U, cert_with_intermediates->intermediate_buffers().size());
91 
92   // With InvalidIntermediateBehavior::kIgnore, invalid intermediate certs
93   // should be silently dropped.
94   base::apple::ScopedCFTypeRef<CFMutableArrayRef> sec_certs(
95       CreateSecCertificateArrayForX509Certificate(
96           cert_with_intermediates.get(), InvalidIntermediateBehavior::kIgnore));
97   ASSERT_TRUE(sec_certs);
98   for (int i = 0; i < CFArrayGetCount(sec_certs.get()); ++i)
99     ASSERT_TRUE(CFArrayGetValueAtIndex(sec_certs.get(), i));
100 
101   if (CFArrayGetCount(sec_certs.get()) == 2) {
102     EXPECT_EQ(x509_util::CryptoBufferAsStringPiece(ok_cert->cert_buffer()),
103               BytesForSecCert(CFArrayGetValueAtIndex(sec_certs.get(), 0)));
104     EXPECT_EQ(x509_util::CryptoBufferAsStringPiece(ok_cert2->cert_buffer()),
105               BytesForSecCert(CFArrayGetValueAtIndex(sec_certs.get(), 1)));
106 
107     // Normal CreateSecCertificateArrayForX509Certificate should fail with
108     // invalid certs in chain.
109     EXPECT_FALSE(CreateSecCertificateArrayForX509Certificate(
110         cert_with_intermediates.get()));
111   } else if (CFArrayGetCount(sec_certs.get()) == 3) {
112     // On older macOS versions that do lazy parsing of SecCertificates, the
113     // invalid certificate may be accepted, which is okay. The test is just
114     // verifying that *if* creating a SecCertificate from one of the
115     // intermediates fails, that cert is ignored and the other certs are still
116     // returned.
117     EXPECT_EQ(x509_util::CryptoBufferAsStringPiece(ok_cert->cert_buffer()),
118               BytesForSecCert(CFArrayGetValueAtIndex(sec_certs.get(), 0)));
119     EXPECT_EQ(x509_util::CryptoBufferAsStringPiece(bad_cert.get()),
120               BytesForSecCert(CFArrayGetValueAtIndex(sec_certs.get(), 1)));
121     EXPECT_EQ(x509_util::CryptoBufferAsStringPiece(ok_cert2->cert_buffer()),
122               BytesForSecCert(CFArrayGetValueAtIndex(sec_certs.get(), 2)));
123 
124     // Normal CreateSecCertificateArrayForX509Certificate should also
125     // succeed in this case.
126     EXPECT_TRUE(CreateSecCertificateArrayForX509Certificate(
127         cert_with_intermediates.get()));
128   } else {
129     ADD_FAILURE() << "CFArrayGetCount(sec_certs.get()) = "
130                   << CFArrayGetCount(sec_certs.get());
131   }
132 }
133 
TEST(X509UtilTest,CreateSecCertificateFromBytesAndCreateX509CertificateFromSecCertificate)134 TEST(X509UtilTest,
135      CreateSecCertificateFromBytesAndCreateX509CertificateFromSecCertificate) {
136   CertificateList certs = CreateCertificateListFromFile(
137       GetTestCertsDirectory(), "multi-root-chain1.pem",
138       X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
139   ASSERT_EQ(4u, certs.size());
140 
141   std::string bytes_cert0(
142       x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer()));
143   std::string bytes_cert1(
144       x509_util::CryptoBufferAsStringPiece(certs[1]->cert_buffer()));
145   std::string bytes_cert2(
146       x509_util::CryptoBufferAsStringPiece(certs[2]->cert_buffer()));
147   std::string bytes_cert3(
148       x509_util::CryptoBufferAsStringPiece(certs[3]->cert_buffer()));
149 
150   base::apple::ScopedCFTypeRef<SecCertificateRef> sec_cert0(
151       CreateSecCertificateFromBytes(base::as_byte_span(bytes_cert0)));
152   ASSERT_TRUE(sec_cert0);
153   EXPECT_EQ(bytes_cert0, BytesForSecCert(sec_cert0.get()));
154 
155   base::apple::ScopedCFTypeRef<SecCertificateRef> sec_cert1(
156       CreateSecCertificateFromBytes(base::as_byte_span(bytes_cert1)));
157   ASSERT_TRUE(sec_cert1);
158   EXPECT_EQ(bytes_cert1, BytesForSecCert(sec_cert1.get()));
159 
160   base::apple::ScopedCFTypeRef<SecCertificateRef> sec_cert2(
161       CreateSecCertificateFromX509Certificate(certs[2].get()));
162   ASSERT_TRUE(sec_cert2);
163   EXPECT_EQ(bytes_cert2, BytesForSecCert(sec_cert2.get()));
164 
165   base::apple::ScopedCFTypeRef<SecCertificateRef> sec_cert3(
166       CreateSecCertificateFromX509Certificate(certs[3].get()));
167   ASSERT_TRUE(sec_cert3);
168   EXPECT_EQ(bytes_cert3, BytesForSecCert(sec_cert3.get()));
169 
170   scoped_refptr<X509Certificate> x509_cert_no_intermediates =
171       CreateX509CertificateFromSecCertificate(sec_cert0, {});
172   ASSERT_TRUE(x509_cert_no_intermediates);
173   EXPECT_EQ(0U, x509_cert_no_intermediates->intermediate_buffers().size());
174   EXPECT_EQ(bytes_cert0, x509_util::CryptoBufferAsStringPiece(
175                              x509_cert_no_intermediates->cert_buffer()));
176 
177   scoped_refptr<X509Certificate> x509_cert_one_intermediate =
178       CreateX509CertificateFromSecCertificate(sec_cert0, {sec_cert1});
179   ASSERT_TRUE(x509_cert_one_intermediate);
180   EXPECT_EQ(bytes_cert0, x509_util::CryptoBufferAsStringPiece(
181                              x509_cert_one_intermediate->cert_buffer()));
182   ASSERT_EQ(1U, x509_cert_one_intermediate->intermediate_buffers().size());
183   EXPECT_EQ(bytes_cert1,
184             x509_util::CryptoBufferAsStringPiece(
185                 x509_cert_one_intermediate->intermediate_buffers()[0].get()));
186 
187   scoped_refptr<X509Certificate> x509_cert_two_intermediates =
188       CreateX509CertificateFromSecCertificate(sec_cert0,
189                                               {sec_cert1, sec_cert2});
190   ASSERT_TRUE(x509_cert_two_intermediates);
191   EXPECT_EQ(bytes_cert0, x509_util::CryptoBufferAsStringPiece(
192                              x509_cert_two_intermediates->cert_buffer()));
193   ASSERT_EQ(2U, x509_cert_two_intermediates->intermediate_buffers().size());
194   EXPECT_EQ(bytes_cert1,
195             x509_util::CryptoBufferAsStringPiece(
196                 x509_cert_two_intermediates->intermediate_buffers()[0].get()));
197   EXPECT_EQ(bytes_cert2,
198             x509_util::CryptoBufferAsStringPiece(
199                 x509_cert_two_intermediates->intermediate_buffers()[1].get()));
200 }
201 
202 }  // namespace x509_util
203 
204 }  // namespace net
205