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