1 // Copyright 2013 The Chromium Authors. All rights reserved. 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/ssl/client_cert_store_chromeos.h" 6 7 #include "base/bind.h" 8 #include "base/callback.h" 9 #include "base/file_util.h" 10 #include "base/run_loop.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "crypto/nss_util.h" 13 #include "crypto/nss_util_internal.h" 14 #include "net/cert/nss_cert_database.h" 15 #include "net/ssl/client_cert_store_unittest-inl.h" 16 17 namespace net { 18 19 class ClientCertStoreChromeOSTestDelegate { 20 public: 21 ClientCertStoreChromeOSTestDelegate() 22 : store_("usernamehash", 23 ClientCertStoreChromeOS::PasswordDelegateFactory()) { 24 store_.InitForTesting( 25 crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot()), 26 crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot())); 27 } 28 29 bool SelectClientCerts(const CertificateList& input_certs, 30 const SSLCertRequestInfo& cert_request_info, 31 CertificateList* selected_certs) { 32 return store_.SelectClientCertsForTesting( 33 input_certs, cert_request_info, selected_certs); 34 } 35 36 private: 37 ClientCertStoreChromeOS store_; 38 }; 39 40 class ClientCertStoreChromeOSTest : public ::testing::Test { 41 public: 42 scoped_refptr<X509Certificate> ImportCertForUser( 43 const std::string& username_hash, 44 const std::string& filename, 45 const std::string& password) { 46 crypto::ScopedPK11Slot slot( 47 crypto::GetPublicSlotForChromeOSUser(username_hash)); 48 EXPECT_TRUE(slot.get()); 49 if (!slot.get()) 50 return NULL; 51 52 net::CertificateList cert_list; 53 54 base::FilePath p12_path = GetTestCertsDirectory().AppendASCII(filename); 55 std::string p12_data; 56 if (!base::ReadFileToString(p12_path, &p12_data)) { 57 EXPECT_TRUE(false); 58 return NULL; 59 } 60 61 scoped_refptr<net::CryptoModule> module( 62 net::CryptoModule::CreateFromHandle(slot.get())); 63 int rv = NSSCertDatabase::GetInstance()->ImportFromPKCS12( 64 module.get(), p12_data, base::UTF8ToUTF16(password), false, &cert_list); 65 66 EXPECT_EQ(0, rv); 67 EXPECT_EQ(1U, cert_list.size()); 68 if (rv || cert_list.size() != 1) 69 return NULL; 70 71 return cert_list[0]; 72 } 73 }; 74 75 // TODO(mattm): Do better testing of cert_authorities matching below. Update 76 // net/data/ssl/scripts/generate-client-certificates.sh so that it actually 77 // saves the .p12 files, and regenerate them. 78 79 TEST_F(ClientCertStoreChromeOSTest, WaitForNSSInit) { 80 crypto::ScopedTestNSSChromeOSUser user("scopeduser"); 81 ASSERT_TRUE(user.constructed_successfully()); 82 ClientCertStoreChromeOS store( 83 user.username_hash(), ClientCertStoreChromeOS::PasswordDelegateFactory()); 84 scoped_refptr<X509Certificate> cert_1( 85 ImportCertForUser(user.username_hash(), "client.p12", "12345")); 86 scoped_refptr<X509Certificate> cert_2( 87 ImportCertForUser(user.username_hash(), "websocket_client_cert.p12", "")); 88 89 std::vector<std::string> authority_1( 90 1, 91 std::string(reinterpret_cast<const char*>(kAuthority1DN), 92 sizeof(kAuthority1DN))); 93 scoped_refptr<SSLCertRequestInfo> request_1(new SSLCertRequestInfo()); 94 request_1->cert_authorities = authority_1; 95 96 scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo()); 97 98 base::RunLoop run_loop_1; 99 base::RunLoop run_loop_all; 100 store.GetClientCerts( 101 *request_1, &request_1->client_certs, run_loop_1.QuitClosure()); 102 store.GetClientCerts( 103 *request_all, &request_all->client_certs, run_loop_all.QuitClosure()); 104 105 // Callbacks won't be run until nss_util init finishes for the user. 106 user.FinishInit(); 107 108 run_loop_1.Run(); 109 run_loop_all.Run(); 110 111 ASSERT_EQ(0u, request_1->client_certs.size()); 112 ASSERT_EQ(2u, request_all->client_certs.size()); 113 } 114 115 TEST_F(ClientCertStoreChromeOSTest, NSSAlreadyInitialized) { 116 crypto::ScopedTestNSSChromeOSUser user("scopeduser"); 117 ASSERT_TRUE(user.constructed_successfully()); 118 user.FinishInit(); 119 120 ClientCertStoreChromeOS store( 121 user.username_hash(), ClientCertStoreChromeOS::PasswordDelegateFactory()); 122 scoped_refptr<X509Certificate> cert_1( 123 ImportCertForUser(user.username_hash(), "client.p12", "12345")); 124 scoped_refptr<X509Certificate> cert_2( 125 ImportCertForUser(user.username_hash(), "websocket_client_cert.p12", "")); 126 127 std::vector<std::string> authority_1( 128 1, 129 std::string(reinterpret_cast<const char*>(kAuthority1DN), 130 sizeof(kAuthority1DN))); 131 scoped_refptr<SSLCertRequestInfo> request_1(new SSLCertRequestInfo()); 132 request_1->cert_authorities = authority_1; 133 134 scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo()); 135 136 base::RunLoop run_loop_1; 137 base::RunLoop run_loop_all; 138 store.GetClientCerts( 139 *request_1, &request_1->client_certs, run_loop_1.QuitClosure()); 140 store.GetClientCerts( 141 *request_all, &request_all->client_certs, run_loop_all.QuitClosure()); 142 143 run_loop_1.Run(); 144 run_loop_all.Run(); 145 146 ASSERT_EQ(0u, request_1->client_certs.size()); 147 ASSERT_EQ(2u, request_all->client_certs.size()); 148 } 149 150 TEST_F(ClientCertStoreChromeOSTest, TwoUsers) { 151 crypto::ScopedTestNSSChromeOSUser user1("scopeduser1"); 152 ASSERT_TRUE(user1.constructed_successfully()); 153 crypto::ScopedTestNSSChromeOSUser user2("scopeduser2"); 154 ASSERT_TRUE(user2.constructed_successfully()); 155 ClientCertStoreChromeOS store1( 156 user1.username_hash(), 157 ClientCertStoreChromeOS::PasswordDelegateFactory()); 158 ClientCertStoreChromeOS store2( 159 user2.username_hash(), 160 ClientCertStoreChromeOS::PasswordDelegateFactory()); 161 scoped_refptr<X509Certificate> cert_1( 162 ImportCertForUser(user1.username_hash(), "client.p12", "12345")); 163 scoped_refptr<X509Certificate> cert_2(ImportCertForUser( 164 user2.username_hash(), "websocket_client_cert.p12", "")); 165 166 scoped_refptr<SSLCertRequestInfo> request_1(new SSLCertRequestInfo()); 167 scoped_refptr<SSLCertRequestInfo> request_2(new SSLCertRequestInfo()); 168 169 base::RunLoop run_loop_1; 170 base::RunLoop run_loop_2; 171 store1.GetClientCerts( 172 *request_1, &request_1->client_certs, run_loop_1.QuitClosure()); 173 store2.GetClientCerts( 174 *request_2, &request_2->client_certs, run_loop_2.QuitClosure()); 175 176 // Callbacks won't be run until nss_util init finishes for the user. 177 user1.FinishInit(); 178 user2.FinishInit(); 179 180 run_loop_1.Run(); 181 run_loop_2.Run(); 182 183 ASSERT_EQ(1u, request_1->client_certs.size()); 184 EXPECT_TRUE(cert_1->Equals(request_1->client_certs[0])); 185 // TODO(mattm): Request for second user will have zero results due to 186 // crbug.com/315285. Update the test once that is fixed. 187 } 188 189 } // namespace net 190