tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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