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