tor-browser

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

pk11_module_unittest.cc (7749B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 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 <memory>
      8 #include "nss.h"
      9 #include "pk11pub.h"
     10 #include "prerror.h"
     11 #include "prsystem.h"
     12 #include "secoid.h"
     13 
     14 #include "nss_scoped_ptrs.h"
     15 #include "gtest/gtest.h"
     16 #include "databuffer.h"
     17 
     18 namespace nss_test {
     19 
     20 class Pkcs11ModuleTest : public ::testing::Test {
     21 public:
     22  Pkcs11ModuleTest() {}
     23 
     24  void SetUp() override {
     25    ASSERT_EQ(SECSuccess, SECMOD_AddNewModule(
     26                              "Pkcs11ModuleTest",
     27                              DLL_PREFIX "pkcs11testmodule." DLL_SUFFIX, 0, 0))
     28        << PORT_ErrorToName(PORT_GetError());
     29  }
     30 
     31  void TearDown() override {
     32    int type;
     33    ASSERT_EQ(SECSuccess, SECMOD_DeleteModule("Pkcs11ModuleTest", &type));
     34    ASSERT_EQ(SECMOD_EXTERNAL, type);
     35  }
     36 };
     37 
     38 TEST_F(Pkcs11ModuleTest, LoadUnload) {
     39  ScopedSECMODModule module(SECMOD_FindModule("Pkcs11ModuleTest"));
     40  EXPECT_NE(nullptr, module);
     41 }
     42 
     43 TEST_F(Pkcs11ModuleTest, ListSlots) {
     44  ScopedPK11SlotList slots(
     45      PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, nullptr));
     46  ASSERT_NE(nullptr, slots);
     47 
     48  PK11SlotListElement *element = PK11_GetFirstSafe(slots.get());
     49  ASSERT_NE(nullptr, element);
     50 
     51  // These tokens are always present.
     52  const std::vector<std::string> kSlotsWithToken = {
     53      "NSS Internal Cryptographic Services",
     54      "NSS User Private Key and Certificate Services",
     55      "Test PKCS11 Public Certs Slot", "Test PKCS11 Slot 二"};
     56  std::vector<std::string> foundSlots;
     57 
     58  do {
     59    std::string name = PK11_GetSlotName(element->slot);
     60    foundSlots.push_back(name);
     61    std::cerr << "loaded slot: " << name << std::endl;
     62  } while ((element = PK11_GetNextSafe(slots.get(), element, PR_FALSE)) !=
     63           nullptr);
     64 
     65  std::sort(foundSlots.begin(), foundSlots.end());
     66  EXPECT_TRUE(std::equal(kSlotsWithToken.begin(), kSlotsWithToken.end(),
     67                         foundSlots.begin()));
     68 }
     69 
     70 TEST_F(Pkcs11ModuleTest, PublicCertificatesToken) {
     71  const std::string kRegularToken = "Test PKCS11 Tokeñ 2 Label";
     72  const std::string kPublicCertificatesToken = "Test PKCS11 Public Certs Token";
     73 
     74  ScopedPK11SlotInfo slot1(PK11_FindSlotByName(kRegularToken.c_str()));
     75  ASSERT_NE(nullptr, slot1);
     76  EXPECT_FALSE(PK11_IsFriendly(slot1.get()));
     77 
     78  ScopedPK11SlotInfo slot2(
     79      PK11_FindSlotByName(kPublicCertificatesToken.c_str()));
     80  ASSERT_NE(nullptr, slot2);
     81  EXPECT_TRUE(PK11_IsFriendly(slot2.get()));
     82 }
     83 
     84 TEST_F(Pkcs11ModuleTest, PublicCertificatesTokenLookup) {
     85  const std::string kCertUrl =
     86      "pkcs11:id=%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f";
     87 
     88  ScopedCERTCertList certsByUrl(
     89      PK11_FindCertsFromURI(kCertUrl.c_str(), nullptr));
     90  EXPECT_NE(nullptr, certsByUrl.get());
     91 
     92  size_t count = 0;
     93  CERTCertificate *certByUrl = nullptr;
     94  for (CERTCertListNode *node = CERT_LIST_HEAD(certsByUrl);
     95       !CERT_LIST_END(node, certsByUrl); node = CERT_LIST_NEXT(node)) {
     96    if (count == 0) {
     97      certByUrl = node->cert;
     98    }
     99    count++;
    100  }
    101  EXPECT_EQ(1UL, count);
    102  EXPECT_NE(nullptr, certByUrl);
    103 
    104  EXPECT_EQ(
    105      0, strcmp(certByUrl->nickname, "Test PKCS11 Public Certs Token:cert2"));
    106 }
    107 
    108 TEST_F(Pkcs11ModuleTest, PublicCertificatesTokenLookupNoMatch) {
    109  const std::string kCertUrl =
    110      "pkcs11:id=%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0e";
    111 
    112  ScopedCERTCertList certsByUrl(
    113      PK11_FindCertsFromURI(kCertUrl.c_str(), nullptr));
    114  EXPECT_EQ(nullptr, certsByUrl.get());
    115 }
    116 
    117 #if defined(_WIN32)
    118 #include <windows.h>
    119 
    120 class Pkcs11NonAsciiTest : public ::testing::Test {
    121  WCHAR nonAsciiModuleName[MAX_PATH];
    122 
    123 public:
    124  Pkcs11NonAsciiTest() {}
    125 
    126  void SetUp() override {
    127    WCHAR originalModuleName[MAX_PATH];
    128    LPWSTR filePart;
    129    DWORD count = SearchPathW(NULL, L"pkcs11testmodule.dll", NULL, MAX_PATH,
    130                              nonAsciiModuleName, &filePart);
    131    ASSERT_TRUE(count);
    132    wcscpy(originalModuleName, nonAsciiModuleName);
    133    wcscpy(filePart, L"pkcs11testmodule\u2665.dll");
    134    BOOL result = CopyFileW(originalModuleName, nonAsciiModuleName, TRUE);
    135    ASSERT_TRUE(result);
    136    ASSERT_EQ(SECSuccess,
    137              SECMOD_AddNewModule(
    138                  "Pkcs11NonAsciiTest",
    139                  DLL_PREFIX "pkcs11testmodule\xE2\x99\xA5." DLL_SUFFIX, 0, 0))
    140        << PORT_ErrorToName(PORT_GetError());
    141  }
    142 
    143  void TearDown() override {
    144    int type;
    145    ASSERT_EQ(SECSuccess, SECMOD_DeleteModule("Pkcs11NonAsciiTest", &type));
    146    ASSERT_EQ(SECMOD_EXTERNAL, type);
    147    BOOL result = DeleteFileW(nonAsciiModuleName);
    148    ASSERT_TRUE(result);
    149  }
    150 };
    151 
    152 TEST_F(Pkcs11NonAsciiTest, LoadUnload) {
    153  ScopedSECMODModule module(SECMOD_FindModule("Pkcs11NonAsciiTest"));
    154  EXPECT_NE(nullptr, module);
    155 }
    156 #endif  // defined(_WIN32)
    157 
    158 class Pkcs11ModuleLoadFunctionTest : public ::testing::Test {
    159 public:
    160  Pkcs11ModuleLoadFunctionTest() { library = NULL; };
    161 
    162  void TearDown() override {
    163    if (library != NULL) {
    164      PR_UnloadLibrary(library);
    165    }
    166  }
    167  PRLibrary *library;
    168 };
    169 
    170 CK_RV NotSuppoted_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) {
    171  return CKR_FUNCTION_NOT_SUPPORTED;
    172 }
    173 
    174 CK_RV SupportedButNull(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) {
    175  ppFunctionList = NULL;
    176  return CKR_OK;
    177 }
    178 
    179 TEST_F(Pkcs11ModuleLoadFunctionTest, LoadModuleWithNullFunc) {
    180  ScopedSECMODModule userModule(
    181      SECMOD_LoadUserModuleWithFunction("LoadFunctionModule", NULL));
    182  EXPECT_NE(userModule, nullptr);
    183  EXPECT_FALSE(userModule->loaded);
    184 }
    185 
    186 TEST_F(Pkcs11ModuleLoadFunctionTest, LoadModuleWithUnsupportedFunc) {
    187  ScopedSECMODModule userModule(SECMOD_LoadUserModuleWithFunction(
    188      "LoadFunctionModule", &NotSuppoted_GetFunctionList));
    189  EXPECT_FALSE(userModule->loaded);
    190 }
    191 
    192 TEST_F(Pkcs11ModuleLoadFunctionTest, LoadModuleWithEmptyFunctionList) {
    193  ScopedSECMODModule userModule(SECMOD_LoadUserModuleWithFunction(
    194      "LoadFunctionModule", &SupportedButNull));
    195  EXPECT_NE(userModule, nullptr);
    196  EXPECT_FALSE(userModule->loaded);
    197 }
    198 
    199 TEST_F(Pkcs11ModuleLoadFunctionTest, SuccessLoadModuleWithFunction) {
    200  library = PR_LoadLibrary(DLL_PREFIX "pkcs11testmodule." DLL_SUFFIX);
    201  EXPECT_NE(nullptr, library);
    202 
    203  CK_C_GetFunctionList fentry = NULL;
    204  fentry = (CK_C_GetFunctionList)PR_FindSymbol(library, "C_GetFunctionList");
    205  EXPECT_NE(nullptr, fentry);
    206 
    207  ScopedSECMODModule userModule(
    208      SECMOD_LoadUserModuleWithFunction("LoadFunctionModule", fentry));
    209  EXPECT_NE(nullptr, userModule);
    210  EXPECT_EQ(userModule->loaded, PR_TRUE);
    211 
    212  /* We can find the module*/
    213  ScopedSECMODModule module(SECMOD_FindModule("LoadFunctionModule"));
    214  EXPECT_NE(nullptr, module);
    215 
    216  CK_INFO info;
    217  EXPECT_EQ(SECSuccess, PK11_GetModInfo(userModule.get(), &info));
    218  /* See pkcs11testmodule.cpp */
    219  CK_VERSION expectedCryptokiVersion = {2, 2};
    220  CK_VERSION expectedLibraryVersion = {0, 0};
    221  EXPECT_EQ(info.cryptokiVersion.minor, expectedCryptokiVersion.minor);
    222  EXPECT_EQ(info.cryptokiVersion.major, expectedCryptokiVersion.major);
    223 
    224  EXPECT_EQ(
    225      0, PORT_Memcmp((char *)info.manufacturerID, "Test PKCS11 Manufacturer ID",
    226                     sizeof("Test PKCS11 Manufacturer ID") - 1));
    227  EXPECT_EQ(info.flags, 0UL);
    228 
    229  EXPECT_EQ(0,
    230            PORT_Memcmp((char *)info.libraryDescription, "Test PKCS11 Library",
    231                        sizeof("Test PKCS11 Library") - 1));
    232  EXPECT_EQ(info.libraryVersion.minor, expectedLibraryVersion.minor);
    233  EXPECT_EQ(info.libraryVersion.major, expectedLibraryVersion.major);
    234 
    235  EXPECT_EQ(SECSuccess, SECMOD_UnloadUserModule(userModule.get()));
    236 }
    237 
    238 }  // namespace nss_test