pk11_find_certs_unittest.cc (30190B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* vim: set ts=4 et sw=4 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include <string.h> 8 9 #include "nss.h" 10 #include "pk11pub.h" 11 #include "prenv.h" 12 #include "prerror.h" 13 #include "secmod.h" 14 15 #include "gtest/gtest.h" 16 #include "nss_scoped_ptrs.h" 17 #include "util.h" 18 19 namespace nss_test { 20 21 // These test certificates were generated using pycert/pykey from 22 // mozilla-central (https://hg.mozilla.org/mozilla-central/file/ ... 23 // 9968319230a74eb8c1953444a0e6973c7500a9f8/security/manager/ssl/ ... 24 // tests/unit/pycert.py). 25 26 // issuer:test cert 27 // subject:test cert 28 // issuerKey:secp256r1 29 // subjectKey:secp256r1 30 // serialNumber:1 31 const std::vector<uint8_t> kTestCert1DER = { 32 0x30, 0x82, 0x01, 0x1D, 0x30, 0x81, 0xC2, 0xA0, 0x03, 0x02, 0x01, 0x02, 33 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 34 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 35 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 36 0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, 37 0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18, 38 0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, 39 0x30, 0x30, 0x30, 0x5A, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 40 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, 41 0x72, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 42 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 43 0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8, 44 0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B, 45 0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45, 46 0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07, 47 0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B, 48 0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06, 49 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 50 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13, 51 0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91, 52 0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80, 53 0x0A, 0x70, 0xE6, 0x02, 0x20, 0x11, 0xFA, 0xA2, 0xCA, 0x06, 0xF3, 0xBC, 54 0x5F, 0x8A, 0xCA, 0x17, 0x63, 0x36, 0x87, 0xCF, 0x8D, 0x5C, 0xA0, 0x56, 55 0x84, 0x44, 0x61, 0xB2, 0x33, 0x42, 0x07, 0x58, 0x9F, 0x0C, 0x9E, 0x49, 56 0x83, 57 }; 58 59 // issuer:test cert 60 // subject:test cert 61 // issuerKey:secp256r1 62 // subjectKey:secp256r1 63 // serialNumber:2 64 const std::vector<uint8_t> kTestCert2DER = { 65 0x30, 0x82, 0x01, 0x1E, 0x30, 0x81, 0xC2, 0xA0, 0x03, 0x02, 0x01, 0x02, 66 0x02, 0x01, 0x02, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 67 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 68 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 69 0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, 70 0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18, 71 0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, 72 0x30, 0x30, 0x30, 0x5A, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 73 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, 74 0x72, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 75 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 76 0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8, 77 0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B, 78 0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45, 79 0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07, 80 0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B, 81 0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06, 82 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 83 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13, 84 0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91, 85 0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80, 86 0x0A, 0x70, 0xE6, 0x02, 0x21, 0x00, 0xF6, 0x5E, 0x42, 0xC7, 0x54, 0x40, 87 0x81, 0xE9, 0x4C, 0x16, 0x48, 0xB1, 0x39, 0x0A, 0xA0, 0xE2, 0x8C, 0x23, 88 0xAA, 0xC5, 0xBB, 0xAC, 0xEB, 0x9B, 0x15, 0x0B, 0x2F, 0xB7, 0xF5, 0x85, 89 0xB2, 0x54, 90 }; 91 92 const std::vector<uint8_t> kTestCertSubjectDER = { 93 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 94 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74, 95 }; 96 97 // issuer:test cert 98 // subject:unrelated subject DN 99 // issuerKey:secp256r1 100 // subjectKey:secp256r1 101 // serialNumber:3 102 const std::vector<uint8_t> kUnrelatedTestCertDER = { 103 0x30, 0x82, 0x01, 0x28, 0x30, 0x81, 0xCD, 0xA0, 0x03, 0x02, 0x01, 0x02, 104 0x02, 0x01, 0x03, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 105 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 106 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 107 0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, 108 0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18, 109 0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, 110 0x30, 0x30, 0x30, 0x5A, 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 111 0x55, 0x04, 0x03, 0x0C, 0x14, 0x75, 0x6E, 0x72, 0x65, 0x6C, 0x61, 0x74, 112 0x65, 0x64, 0x20, 0x73, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x44, 113 0x4E, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 114 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 115 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8, 0xF9, 116 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B, 0x42, 117 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45, 0x5C, 118 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07, 0x06, 119 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B, 0x2D, 120 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06, 0x09, 121 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 122 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13, 0x11, 123 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91, 0xFF, 124 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80, 0x0A, 125 0x70, 0xE6, 0x02, 0x20, 0x0F, 0x1A, 0x04, 0xC2, 0xF8, 0xBA, 0xC2, 0x94, 126 0x26, 0x6E, 0xBC, 0x91, 0x7D, 0xDB, 0x75, 0x7B, 0xE8, 0xA3, 0x4F, 0x69, 127 0x1B, 0xF3, 0x1F, 0x2C, 0xCE, 0x82, 0x67, 0xC9, 0x5B, 0xBB, 0xBA, 0x0A, 128 }; 129 130 class PK11FindCertsTestBase : public ::testing::Test { 131 protected: 132 PK11FindCertsTestBase() 133 : m_slot(nullptr), test_cert_db_dir_("PK11FindCertsTestBase-") {} 134 135 virtual void SetUp() { 136 std::string test_cert_db_path(test_cert_db_dir_.GetPath()); 137 const char* test_name = 138 ::testing::UnitTest::GetInstance()->current_test_info()->name(); 139 std::string mod_spec = "configDir='sql:"; 140 mod_spec.append(test_cert_db_path); 141 mod_spec.append("' tokenDescription='"); 142 mod_spec.append(test_name); 143 mod_spec.append("'"); 144 m_slot = SECMOD_OpenUserDB(mod_spec.c_str()); 145 ASSERT_NE(nullptr, m_slot); 146 } 147 148 virtual void TearDown() { 149 ASSERT_EQ(SECSuccess, SECMOD_CloseUserDB(m_slot)); 150 PK11_FreeSlot(m_slot); 151 std::string test_cert_db_path(test_cert_db_dir_.GetPath()); 152 ASSERT_EQ(0, unlink((test_cert_db_path + "/cert9.db").c_str())); 153 ASSERT_EQ(0, unlink((test_cert_db_path + "/key4.db").c_str())); 154 } 155 156 PK11SlotInfo* m_slot; 157 ScopedUniqueDirectory test_cert_db_dir_; 158 }; 159 160 class PK11FindRawCertsBySubjectTest : public PK11FindCertsTestBase {}; 161 162 TEST_F(PK11FindCertsTestBase, CertAddListWithData) { 163 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 164 ASSERT_TRUE(slot); 165 SECItem cert1_item = {siBuffer, const_cast<uint8_t*>(kTestCert1DER.data()), 166 (unsigned int)kTestCert1DER.size()}; 167 SECItem cert2_item = {siBuffer, const_cast<uint8_t*>(kTestCert2DER.data()), 168 (unsigned int)kTestCert2DER.size()}; 169 170 // Make certificates. ScopedCERTCertList will own. 171 ScopedCERTCertList list(CERT_NewCertList()); 172 ASSERT_TRUE(list); 173 CERTCertificate* cert1 = CERT_NewTempCertificate( 174 CERT_GetDefaultCertDB(), &cert1_item, nullptr, false, false); 175 CERTCertificate* cert2 = CERT_NewTempCertificate( 176 CERT_GetDefaultCertDB(), &cert2_item, nullptr, false, false); 177 ASSERT_NE(nullptr, cert1); 178 ASSERT_NE(nullptr, cert2); 179 ASSERT_NE(cert1, cert2); 180 181 SECStatus rv = CERT_AddCertToListHeadWithData(list.get(), cert1, cert1); 182 EXPECT_EQ(SECSuccess, rv); 183 rv = CERT_AddCertToListTailWithData(list.get(), cert2, cert2); 184 EXPECT_EQ(SECSuccess, rv); 185 186 CERTCertListNode* node = CERT_LIST_HEAD(list.get()); 187 ASSERT_NE(nullptr, node); 188 EXPECT_EQ(node->cert, cert1); 189 EXPECT_EQ(node->appData, cert1); 190 191 node = CERT_LIST_TAIL(list.get()); 192 ASSERT_NE(nullptr, node); 193 EXPECT_EQ(node->cert, cert2); 194 EXPECT_EQ(node->appData, cert2); 195 } 196 197 // If we don't have any certificates, we shouldn't get any when we search for 198 // them. 199 TEST_F(PK11FindRawCertsBySubjectTest, TestNoCertsImportedNoCertsFound) { 200 SECItem subject_item = { 201 siBuffer, const_cast<unsigned char*>(kTestCertSubjectDER.data()), 202 (unsigned int)kTestCertSubjectDER.size()}; 203 CERTCertificateList* certificates = nullptr; 204 SECStatus rv = 205 PK11_FindRawCertsWithSubject(m_slot, &subject_item, &certificates); 206 EXPECT_EQ(SECSuccess, rv); 207 EXPECT_EQ(nullptr, certificates); 208 } 209 210 // If we have one certificate but it has an unrelated subject DN, we shouldn't 211 // get it when we search. 212 TEST_F(PK11FindRawCertsBySubjectTest, TestOneCertImportedNoCertsFound) { 213 char cert_nickname[] = "Unrelated Cert"; 214 SECItem cert_item = {siBuffer, 215 const_cast<unsigned char*>(kUnrelatedTestCertDER.data()), 216 (unsigned int)kUnrelatedTestCertDER.size()}; 217 ASSERT_EQ(SECSuccess, 218 PK11_ImportDERCert(m_slot, &cert_item, CK_INVALID_HANDLE, 219 cert_nickname, false)); 220 221 SECItem subject_item = { 222 siBuffer, const_cast<unsigned char*>(kTestCertSubjectDER.data()), 223 (unsigned int)kTestCertSubjectDER.size()}; 224 CERTCertificateList* certificates = nullptr; 225 SECStatus rv = 226 PK11_FindRawCertsWithSubject(m_slot, &subject_item, &certificates); 227 EXPECT_EQ(SECSuccess, rv); 228 EXPECT_EQ(nullptr, certificates); 229 } 230 231 TEST_F(PK11FindRawCertsBySubjectTest, TestMultipleMatchingCertsFound) { 232 char cert1_nickname[] = "Test Cert 1"; 233 SECItem cert1_item = {siBuffer, 234 const_cast<unsigned char*>(kTestCert1DER.data()), 235 (unsigned int)kTestCert1DER.size()}; 236 ASSERT_EQ(SECSuccess, 237 PK11_ImportDERCert(m_slot, &cert1_item, CK_INVALID_HANDLE, 238 cert1_nickname, false)); 239 char cert2_nickname[] = "Test Cert 2"; 240 SECItem cert2_item = {siBuffer, 241 const_cast<unsigned char*>(kTestCert2DER.data()), 242 (unsigned int)kTestCert2DER.size()}; 243 ASSERT_EQ(SECSuccess, 244 PK11_ImportDERCert(m_slot, &cert2_item, CK_INVALID_HANDLE, 245 cert2_nickname, false)); 246 char unrelated_cert_nickname[] = "Unrelated Test Cert"; 247 SECItem unrelated_cert_item = { 248 siBuffer, const_cast<unsigned char*>(kUnrelatedTestCertDER.data()), 249 (unsigned int)kUnrelatedTestCertDER.size()}; 250 ASSERT_EQ(SECSuccess, 251 PK11_ImportDERCert(m_slot, &unrelated_cert_item, CK_INVALID_HANDLE, 252 unrelated_cert_nickname, false)); 253 254 CERTCertificateList* certificates = nullptr; 255 SECItem subject_item = { 256 siBuffer, const_cast<unsigned char*>(kTestCertSubjectDER.data()), 257 (unsigned int)kTestCertSubjectDER.size()}; 258 SECStatus rv = 259 PK11_FindRawCertsWithSubject(m_slot, &subject_item, &certificates); 260 EXPECT_EQ(SECSuccess, rv); 261 ASSERT_NE(nullptr, certificates); 262 ScopedCERTCertificateList scoped_certificates(certificates); 263 ASSERT_EQ(2, scoped_certificates->len); 264 265 std::vector<uint8_t> found_cert1( 266 scoped_certificates->certs[0].data, 267 scoped_certificates->certs[0].data + scoped_certificates->certs[0].len); 268 std::vector<uint8_t> found_cert2( 269 scoped_certificates->certs[1].data, 270 scoped_certificates->certs[1].data + scoped_certificates->certs[1].len); 271 EXPECT_TRUE(found_cert1 == kTestCert1DER || found_cert1 == kTestCert2DER); 272 EXPECT_TRUE(found_cert2 == kTestCert1DER || found_cert2 == kTestCert2DER); 273 EXPECT_TRUE(found_cert1 != found_cert2); 274 } 275 276 // If we try to search the internal slots, we won't find the certificate we just 277 // imported (because it's on a different slot). 278 TEST_F(PK11FindRawCertsBySubjectTest, TestNoCertsOnInternalSlots) { 279 char cert1_nickname[] = "Test Cert 1"; 280 SECItem cert1_item = {siBuffer, 281 const_cast<unsigned char*>(kTestCert1DER.data()), 282 (unsigned int)kTestCert1DER.size()}; 283 ASSERT_EQ(SECSuccess, 284 PK11_ImportDERCert(m_slot, &cert1_item, CK_INVALID_HANDLE, 285 cert1_nickname, false)); 286 287 SECItem subject_item = { 288 siBuffer, const_cast<unsigned char*>(kTestCertSubjectDER.data()), 289 (unsigned int)kTestCertSubjectDER.size()}; 290 CERTCertificateList* internal_key_slot_certificates = nullptr; 291 ScopedPK11SlotInfo internal_key_slot(PK11_GetInternalKeySlot()); 292 SECStatus rv = PK11_FindRawCertsWithSubject( 293 internal_key_slot.get(), &subject_item, &internal_key_slot_certificates); 294 EXPECT_EQ(SECSuccess, rv); 295 EXPECT_EQ(nullptr, internal_key_slot_certificates); 296 297 CERTCertificateList* internal_slot_certificates = nullptr; 298 ScopedPK11SlotInfo internal_slot(PK11_GetInternalSlot()); 299 rv = PK11_FindRawCertsWithSubject(internal_slot.get(), &subject_item, 300 &internal_slot_certificates); 301 EXPECT_EQ(SECSuccess, rv); 302 EXPECT_EQ(nullptr, internal_slot_certificates); 303 } 304 305 // issuer:test cert 306 // subject:(empty - this had to be done by hand as pycert doesn't support this) 307 // issuerKey:secp256r1 308 // subjectKey:secp256r1 309 // serialNumber:4 310 const std::vector<uint8_t> kEmptySubjectCertDER = { 311 0x30, 0x82, 0x01, 0x09, 0x30, 0x81, 0xAE, 0xA0, 0x03, 0x02, 0x01, 0x02, 312 0x02, 0x01, 0x04, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 313 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 314 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 315 0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, 316 0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18, 317 0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, 318 0x30, 0x30, 0x30, 0x5A, 0x30, 0x00, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 319 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 320 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 321 0xBB, 0x61, 0xE0, 0xF8, 0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 322 0xE2, 0xEC, 0x05, 0x0B, 0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 323 0x4F, 0x79, 0x4B, 0x45, 0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 324 0xC4, 0x11, 0x9D, 0x07, 0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 325 0xD7, 0x99, 0x1B, 0x7B, 0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 326 0xC0, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 327 0x01, 0x0B, 0x05, 0x00, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C, 328 0x75, 0x51, 0x9F, 0x13, 0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 329 0xBC, 0x06, 0x30, 0x91, 0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 330 0xFD, 0xCB, 0x42, 0x80, 0x0A, 0x70, 0xE6, 0x02, 0x20, 0x31, 0x1B, 0x92, 331 0xAA, 0xA8, 0xB7, 0x51, 0x52, 0x7B, 0x64, 0xD6, 0xF7, 0x2F, 0x0C, 0xFB, 332 0xBB, 0xD5, 0xDF, 0x86, 0xA3, 0x97, 0x96, 0x60, 0x42, 0xDA, 0xD4, 0xA8, 333 0x5F, 0x2F, 0xA4, 0xDE, 0x7C}; 334 335 std::vector<uint8_t> kEmptySubjectDER = {0x30, 0x00}; 336 337 // This certificate has the smallest possible subject. Finding it should work. 338 TEST_F(PK11FindRawCertsBySubjectTest, TestFindEmptySubject) { 339 char empty_subject_cert_nickname[] = "Empty Subject Cert"; 340 SECItem empty_subject_cert_item = { 341 siBuffer, const_cast<unsigned char*>(kEmptySubjectCertDER.data()), 342 (unsigned int)kEmptySubjectCertDER.size()}; 343 ASSERT_EQ(SECSuccess, PK11_ImportDERCert(m_slot, &empty_subject_cert_item, 344 CK_INVALID_HANDLE, 345 empty_subject_cert_nickname, false)); 346 347 SECItem subject_item = {siBuffer, 348 const_cast<unsigned char*>(kEmptySubjectDER.data()), 349 (unsigned int)kEmptySubjectDER.size()}; 350 CERTCertificateList* certificates = nullptr; 351 SECStatus rv = 352 PK11_FindRawCertsWithSubject(m_slot, &subject_item, &certificates); 353 EXPECT_EQ(SECSuccess, rv); 354 ASSERT_NE(nullptr, certificates); 355 ScopedCERTCertificateList scoped_certificates(certificates); 356 ASSERT_EQ(1, scoped_certificates->len); 357 358 std::vector<uint8_t> found_cert( 359 scoped_certificates->certs[0].data, 360 scoped_certificates->certs[0].data + scoped_certificates->certs[0].len); 361 EXPECT_EQ(kEmptySubjectCertDER, found_cert); 362 } 363 364 // Searching for a zero-length subject doesn't make sense (the minimum subject 365 // is the SEQUENCE tag followed by a length byte of 0), but it shouldn't cause 366 // problems. 367 TEST_F(PK11FindRawCertsBySubjectTest, TestSearchForNullSubject) { 368 char cert1_nickname[] = "Test Cert 1"; 369 SECItem cert1_item = {siBuffer, 370 const_cast<unsigned char*>(kTestCert1DER.data()), 371 (unsigned int)kTestCert1DER.size()}; 372 ASSERT_EQ(SECSuccess, 373 PK11_ImportDERCert(m_slot, &cert1_item, CK_INVALID_HANDLE, 374 cert1_nickname, false)); 375 376 SECItem subject_item = {siBuffer, nullptr, 0}; 377 CERTCertificateList* certificates = nullptr; 378 SECStatus rv = 379 PK11_FindRawCertsWithSubject(m_slot, &subject_item, &certificates); 380 EXPECT_EQ(SECSuccess, rv); 381 EXPECT_EQ(nullptr, certificates); 382 } 383 384 class PK11GetCertsMatchingPrivateKeyTest : public PK11FindCertsTestBase {}; 385 386 // This is the private secp256r1 key corresponding to the above test 387 // certificates. 388 const std::vector<uint8_t> kTestPrivateKeyInfoDER = { 389 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 390 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 391 0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, 392 0x21, 0x91, 0x40, 0x3d, 0x57, 0x10, 0xbf, 0x15, 0xa2, 0x65, 0x81, 0x8c, 393 0xd4, 0x2e, 0xd6, 0xfe, 0xdf, 0x09, 0xad, 0xd9, 0x2d, 0x78, 0xb1, 0x8e, 394 0x7a, 0x1e, 0x9f, 0xeb, 0x95, 0x52, 0x47, 0x02, 0xa1, 0x44, 0x03, 0x42, 395 0x00, 0x04, 0x4f, 0xbf, 0xbb, 0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 396 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 397 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 398 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 399 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3, 400 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 401 }; 402 403 // issuer:test cert (different key) 404 // subject:test cert (different key) 405 // issuerKey:secp256k1 406 // subjectKey:secp256k1 407 // serialNumber:1 408 const std::vector<uint8_t> kTestCertWithOtherKeyDER = { 409 0x30, 0x82, 0x01, 0x3a, 0x30, 0x81, 0xdf, 0xa0, 0x03, 0x02, 0x01, 0x02, 410 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 411 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x24, 0x31, 0x22, 0x30, 0x20, 412 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x74, 0x65, 0x73, 0x74, 0x20, 413 0x63, 0x65, 0x72, 0x74, 0x20, 0x28, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 414 0x65, 0x6e, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x30, 0x22, 0x18, 0x0f, 415 0x32, 0x30, 0x31, 0x37, 0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 416 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 417 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x24, 0x31, 0x22, 418 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x74, 0x65, 0x73, 419 0x74, 0x20, 0x63, 0x65, 0x72, 0x74, 0x20, 0x28, 0x64, 0x69, 0x66, 0x66, 420 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x30, 0x56, 421 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 422 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, 0x03, 0x42, 0x00, 0x04, 0x35, 0xee, 423 0x7c, 0x72, 0x89, 0xd8, 0xfe, 0xf7, 0xa8, 0x6a, 0xfe, 0x5d, 0xa6, 0x6d, 424 0x8b, 0xc2, 0xeb, 0xb6, 0xa8, 0x54, 0x3f, 0xd2, 0xfe, 0xad, 0x08, 0x9f, 425 0x45, 0xce, 0x7a, 0xcd, 0x0f, 0xa6, 0x43, 0x82, 0xa9, 0x50, 0x0c, 0x41, 426 0xda, 0xd7, 0x70, 0xff, 0xd4, 0xb5, 0x11, 0xbf, 0x4b, 0x49, 0x2e, 0xb1, 427 0x23, 0x88, 0x00, 0xc3, 0x2c, 0x4f, 0x76, 0xc7, 0x3a, 0x3f, 0x32, 0x94, 428 0xe7, 0xc5, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 429 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 430 0x63, 0x59, 0x02, 0x01, 0x89, 0xd7, 0x3e, 0x5b, 0xff, 0xd1, 0x16, 0x4e, 431 0xe3, 0xe2, 0x0a, 0xe0, 0x4a, 0xd8, 0x75, 0xaf, 0x77, 0x5c, 0x93, 0x60, 432 0xba, 0x10, 0x1f, 0x97, 0xdd, 0x27, 0x2d, 0x24, 0x02, 0x20, 0x1e, 0xa0, 433 0x7b, 0xee, 0x90, 0x9b, 0x5f, 0x2c, 0x49, 0xd6, 0x61, 0xda, 0x31, 0x14, 434 0xb1, 0xa4, 0x0d, 0x2d, 0x90, 0x2b, 0x70, 0xd8, 0x6b, 0x07, 0x64, 0x27, 435 0xa5, 0x2e, 0xfe, 0xca, 0x6e, 0xe6, 436 }; 437 438 // If there are no certs at all, we'll get back a null list. 439 TEST_F(PK11GetCertsMatchingPrivateKeyTest, TestNoCertsAtAll) { 440 SECItem private_key_info = { 441 siBuffer, 442 const_cast<unsigned char*>(kTestPrivateKeyInfoDER.data()), 443 (unsigned int)kTestPrivateKeyInfoDER.size(), 444 }; 445 SECKEYPrivateKey* priv_key = nullptr; 446 ASSERT_EQ(SECSuccess, PK11_ImportDERPrivateKeyInfoAndReturnKey( 447 m_slot, &private_key_info, nullptr, nullptr, false, 448 false, KU_ALL, &priv_key, nullptr)); 449 ASSERT_NE(nullptr, priv_key); 450 ScopedSECKEYPrivateKey scoped_priv_key(priv_key); 451 ScopedCERTCertList certs( 452 PK11_GetCertsMatchingPrivateKey(scoped_priv_key.get())); 453 ASSERT_TRUE(CERT_LIST_EMPTY(certs)); 454 } 455 456 // If there are no certs for the private key, we'll get back a null list. 457 TEST_F(PK11GetCertsMatchingPrivateKeyTest, TestNoCertsForKey) { 458 SECItem private_key_info = { 459 siBuffer, 460 const_cast<unsigned char*>(kTestPrivateKeyInfoDER.data()), 461 (unsigned int)kTestPrivateKeyInfoDER.size(), 462 }; 463 SECKEYPrivateKey* priv_key = nullptr; 464 ASSERT_EQ(SECSuccess, PK11_ImportDERPrivateKeyInfoAndReturnKey( 465 m_slot, &private_key_info, nullptr, nullptr, false, 466 false, KU_ALL, &priv_key, nullptr)); 467 ASSERT_NE(nullptr, priv_key); 468 ScopedSECKEYPrivateKey scoped_priv_key(priv_key); 469 470 char cert_nickname[] = "Test Cert With Other Key"; 471 SECItem cert_item = { 472 siBuffer, const_cast<unsigned char*>(kTestCertWithOtherKeyDER.data()), 473 (unsigned int)kTestCertWithOtherKeyDER.size()}; 474 ASSERT_EQ(SECSuccess, 475 PK11_ImportDERCert(m_slot, &cert_item, CK_INVALID_HANDLE, 476 cert_nickname, false)); 477 478 ScopedCERTCertList certs( 479 PK11_GetCertsMatchingPrivateKey(scoped_priv_key.get())); 480 ASSERT_TRUE(CERT_LIST_EMPTY(certs)); 481 } 482 483 void CheckCertListForSubjects( 484 ScopedCERTCertList& list, 485 const std::vector<const char*>& expected_subjects) { 486 ASSERT_NE(nullptr, list.get()); 487 ASSERT_NE(0ul, expected_subjects.size()); 488 for (const auto& expected_subject : expected_subjects) { 489 size_t list_length = 0; 490 bool found = false; 491 for (CERTCertListNode* n = CERT_LIST_HEAD(list); !CERT_LIST_END(n, list); 492 n = CERT_LIST_NEXT(n)) { 493 list_length++; 494 if (strcmp(n->cert->subjectName, expected_subject) == 0) { 495 ASSERT_FALSE(found); 496 found = true; 497 } 498 } 499 ASSERT_TRUE(found); 500 ASSERT_EQ(expected_subjects.size(), list_length); 501 } 502 } 503 504 // We should only get back certs that actually match the private key. 505 TEST_F(PK11GetCertsMatchingPrivateKeyTest, TestOneCertForKey) { 506 SECItem private_key_info = { 507 siBuffer, 508 const_cast<unsigned char*>(kTestPrivateKeyInfoDER.data()), 509 (unsigned int)kTestPrivateKeyInfoDER.size(), 510 }; 511 SECKEYPrivateKey* priv_key = nullptr; 512 ASSERT_EQ(SECSuccess, PK11_ImportDERPrivateKeyInfoAndReturnKey( 513 m_slot, &private_key_info, nullptr, nullptr, false, 514 false, KU_ALL, &priv_key, nullptr)); 515 ASSERT_NE(nullptr, priv_key); 516 ScopedSECKEYPrivateKey scoped_priv_key(priv_key); 517 518 char cert1_nickname[] = "Test Cert 1"; 519 SECItem cert1_item = {siBuffer, 520 const_cast<unsigned char*>(kTestCert1DER.data()), 521 (unsigned int)kTestCert1DER.size()}; 522 ASSERT_EQ(SECSuccess, 523 PK11_ImportDERCert(m_slot, &cert1_item, CK_INVALID_HANDLE, 524 cert1_nickname, false)); 525 526 char cert_nickname[] = "Test Cert With Other Key"; 527 SECItem cert_item = { 528 siBuffer, const_cast<unsigned char*>(kTestCertWithOtherKeyDER.data()), 529 (unsigned int)kTestCertWithOtherKeyDER.size()}; 530 ASSERT_EQ(SECSuccess, 531 PK11_ImportDERCert(m_slot, &cert_item, CK_INVALID_HANDLE, 532 cert_nickname, false)); 533 534 ScopedCERTCertList certs( 535 PK11_GetCertsMatchingPrivateKey(scoped_priv_key.get())); 536 CheckCertListForSubjects(certs, {"CN=test cert"}); 537 } 538 539 // We should be able to get back all certs that match the private key. 540 TEST_F(PK11GetCertsMatchingPrivateKeyTest, TestTwoCertsForKey) { 541 SECItem private_key_info = { 542 siBuffer, 543 const_cast<unsigned char*>(kTestPrivateKeyInfoDER.data()), 544 (unsigned int)kTestPrivateKeyInfoDER.size(), 545 }; 546 SECKEYPrivateKey* priv_key = nullptr; 547 ASSERT_EQ(SECSuccess, PK11_ImportDERPrivateKeyInfoAndReturnKey( 548 m_slot, &private_key_info, nullptr, nullptr, false, 549 false, KU_ALL, &priv_key, nullptr)); 550 ASSERT_NE(nullptr, priv_key); 551 ScopedSECKEYPrivateKey scoped_priv_key(priv_key); 552 553 char cert1_nickname[] = "Test Cert 1"; 554 SECItem cert1_item = {siBuffer, 555 const_cast<unsigned char*>(kTestCert1DER.data()), 556 (unsigned int)kTestCert1DER.size()}; 557 ASSERT_EQ(SECSuccess, 558 PK11_ImportDERCert(m_slot, &cert1_item, CK_INVALID_HANDLE, 559 cert1_nickname, false)); 560 char cert2_nickname[] = "Test Cert 2 (same key, different subject)"; 561 SECItem cert2_item = { 562 siBuffer, const_cast<unsigned char*>(kUnrelatedTestCertDER.data()), 563 (unsigned int)kUnrelatedTestCertDER.size()}; 564 ASSERT_EQ(SECSuccess, 565 PK11_ImportDERCert(m_slot, &cert2_item, CK_INVALID_HANDLE, 566 cert2_nickname, false)); 567 568 char cert_nickname[] = "Test Cert With Other Key"; 569 SECItem cert_item = { 570 siBuffer, const_cast<unsigned char*>(kTestCertWithOtherKeyDER.data()), 571 (unsigned int)kTestCertWithOtherKeyDER.size()}; 572 ASSERT_EQ(SECSuccess, 573 PK11_ImportDERCert(m_slot, &cert_item, CK_INVALID_HANDLE, 574 cert_nickname, false)); 575 576 ScopedCERTCertList certs( 577 PK11_GetCertsMatchingPrivateKey(scoped_priv_key.get())); 578 CheckCertListForSubjects(certs, {"CN=test cert", "CN=unrelated subject DN"}); 579 } 580 581 class PK11FindEncodedCertInSlotTest : public PK11FindCertsTestBase {}; 582 583 TEST_F(PK11FindEncodedCertInSlotTest, TestFindEncodedCert) { 584 char cert_nickname[] = "Test Cert"; 585 SECItem cert_item = {siBuffer, 586 const_cast<unsigned char*>(kTestCert1DER.data()), 587 (unsigned int)kTestCert1DER.size()}; 588 ASSERT_EQ(SECSuccess, 589 PK11_ImportDERCert(m_slot, &cert_item, CK_INVALID_HANDLE, 590 cert_nickname, false)); 591 592 // This certificate was just imported, so finding it by its encoded value 593 // should succeed. 594 CK_OBJECT_HANDLE cert_handle_in_slot = 595 PK11_FindEncodedCertInSlot(m_slot, &cert_item, nullptr); 596 // CK_INVALID_HANDLE is #defined to be the literal 0, which the compiler 597 // interprets as a signed value, which then causes a warning-as-an-error 598 // about comparing values of different signs. 599 ASSERT_NE(static_cast<CK_ULONG>(CK_INVALID_HANDLE), cert_handle_in_slot); 600 601 // The certificate should not exist on the internal slot, so this should 602 // return CK_INVALID_HANDLE. 603 ScopedPK11SlotInfo internal_slot(PK11_GetInternalSlot()); 604 ASSERT_NE(nullptr, internal_slot); 605 CK_OBJECT_HANDLE cert_handle_in_internal_slot = 606 PK11_FindEncodedCertInSlot(internal_slot.get(), &cert_item, nullptr); 607 ASSERT_EQ(static_cast<CK_ULONG>(CK_INVALID_HANDLE), 608 cert_handle_in_internal_slot); 609 610 // The certificate should not exist on the internal key slot, so this should 611 // return CK_INVALID_HANDLE. 612 ScopedPK11SlotInfo internal_key_slot(PK11_GetInternalKeySlot()); 613 ASSERT_NE(nullptr, internal_key_slot); 614 CK_OBJECT_HANDLE cert_handle_in_internal_key_slot = 615 PK11_FindEncodedCertInSlot(internal_key_slot.get(), &cert_item, nullptr); 616 ASSERT_EQ(static_cast<CK_ULONG>(CK_INVALID_HANDLE), 617 cert_handle_in_internal_key_slot); 618 619 // This certificate hasn't been imported to any token, so looking for it 620 // should return CK_INVALID_HANDLE. 621 SECItem unknown_cert_item = {siBuffer, 622 const_cast<unsigned char*>(kTestCert2DER.data()), 623 (unsigned int)kTestCert2DER.size()}; 624 CK_OBJECT_HANDLE unknown_cert_handle_in_slot = 625 PK11_FindEncodedCertInSlot(m_slot, &unknown_cert_item, nullptr); 626 ASSERT_EQ(static_cast<CK_ULONG>(CK_INVALID_HANDLE), 627 unknown_cert_handle_in_slot); 628 } 629 630 } // namespace nss_test