softoken_gtest.cc (41943B)
1 #include "cert.h" 2 #include "certdb.h" 3 #include "nspr.h" 4 #include "nss.h" 5 #include "pk11pub.h" 6 #include "secmod.h" 7 #include "secerr.h" 8 9 #include "nss_scoped_ptrs.h" 10 #include "secmodt.h" 11 #include "secmodti.h" 12 #include "util.h" 13 14 #define GTEST_HAS_RTTI 0 15 #include "gtest/gtest.h" 16 #include "databuffer.h" 17 #include <fstream> 18 #include <chrono> 19 #include <sqlite3.h> 20 using namespace std::chrono; 21 22 #include "softoken_dh_vectors.h" 23 24 namespace nss_test { 25 class SoftokenTest : public ::testing::Test { 26 protected: 27 SoftokenTest() : mNSSDBDir("SoftokenTest.d-") {} 28 SoftokenTest(const std::string &prefix) : mNSSDBDir(prefix) {} 29 30 virtual void SetUp() { 31 std::string nssInitArg("sql:"); 32 nssInitArg.append(mNSSDBDir.GetUTF8Path()); 33 ASSERT_EQ(SECSuccess, NSS_Initialize(nssInitArg.c_str(), "", "", SECMOD_DB, 34 NSS_INIT_NOROOTINIT)); 35 } 36 37 virtual void TearDown() { 38 ASSERT_EQ(SECSuccess, NSS_Shutdown()); 39 const std::string &nssDBDirPath = mNSSDBDir.GetPath(); 40 ASSERT_EQ(0, unlink((nssDBDirPath + "/cert9.db").c_str())); 41 ASSERT_EQ(0, unlink((nssDBDirPath + "/key4.db").c_str())); 42 ASSERT_EQ(0, unlink((nssDBDirPath + "/pkcs11.txt").c_str())); 43 } 44 45 ScopedUniqueDirectory mNSSDBDir; 46 }; 47 48 TEST_F(SoftokenTest, CheckDefaultPbkdf2Iterations) { 49 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 50 ASSERT_TRUE(slot); 51 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 52 53 // Open key4.db and check encoded PBE algorithm and iteration count. 54 // Compare bytes against the expected values to avoid ASN.1 here. 55 std::string key_db = mNSSDBDir.GetPath() + "/key4.db"; 56 57 sqlite3 *sql_db = NULL; 58 ASSERT_EQ(SQLITE_OK, sqlite3_open(key_db.c_str(), &sql_db)); 59 60 char *query_str = sqlite3_mprintf("SELECT item2 FROM metaData;"); 61 ASSERT_NE(nullptr, query_str); 62 63 sqlite3_stmt *statement = NULL; 64 ASSERT_EQ(SQLITE_OK, 65 sqlite3_prepare_v2(sql_db, query_str, -1, &statement, NULL)); 66 ASSERT_EQ(SQLITE_ROW, sqlite3_step(statement)); 67 unsigned int len = sqlite3_column_bytes(statement, 0); 68 const unsigned char *reader = sqlite3_column_text(statement, 0); 69 70 ASSERT_NE(nullptr, reader); 71 ASSERT_EQ(133U, len); 72 73 // pkcs5PBES2, pkcs5PBKDF2 74 const uint8_t pkcs5_with_pbkdf2[] = { 75 0x30, 0x81, 0x82, 0x30, 0x6E, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 76 0xF7, 0x0D, 0x01, 0x05, 0x0D, 0x30, 0x61, 0x30, 0x42, 0x06, 0x09, 77 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0C, 0x30, 0x35}; 78 EXPECT_EQ(0, memcmp(reader, pkcs5_with_pbkdf2, sizeof(pkcs5_with_pbkdf2))); 79 reader += sizeof(pkcs5_with_pbkdf2); 80 81 // Skip over the 32B random salt 82 const uint8_t salt_prefix[] = {0x04, 0x20}; 83 EXPECT_EQ(0, memcmp(reader, salt_prefix, sizeof(salt_prefix))); 84 reader += sizeof(salt_prefix) + 0x20; 85 86 // Expect 10000 iterations 87 const uint8_t iterations[] = {0x02, 0x02, 0x27, 0x10}; 88 EXPECT_EQ(0, memcmp(reader, iterations, sizeof(iterations))); 89 reader += sizeof(iterations); 90 91 // hmacWithSHA256, aes256-CBC 92 const uint8_t oids[] = {0x02, 0x01, 0x20, 0x30, 0x0A, 0x06, 0x08, 93 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 94 0x09, 0x30, 0x1B, 0x06, 0x09, 0x60, 0x86, 95 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2A}; 96 EXPECT_EQ(0, memcmp(reader, oids, sizeof(oids))); 97 98 EXPECT_EQ(SQLITE_OK, sqlite3_finalize(statement)); 99 sqlite3_free(query_str); 100 sqlite3_close(sql_db); 101 } 102 103 TEST_F(SoftokenTest, ResetSoftokenEmptyPassword) { 104 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 105 ASSERT_TRUE(slot); 106 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr)); 107 EXPECT_EQ(SECSuccess, PK11_ResetToken(slot.get(), nullptr)); 108 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr)); 109 } 110 111 TEST_F(SoftokenTest, ResetSoftokenNonEmptyPassword) { 112 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 113 ASSERT_TRUE(slot); 114 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 115 EXPECT_EQ(SECSuccess, PK11_ResetToken(slot.get(), nullptr)); 116 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password2")); 117 } 118 119 // Test certificate to use in the CreateObject tests. 120 static const CK_OBJECT_CLASS cko_nss_trust = CKO_NSS_TRUST; 121 static const CK_BBOOL ck_false = CK_FALSE; 122 static const CK_BBOOL ck_true = CK_TRUE; 123 static const CK_TRUST ckt_nss_must_verify_trust = CKT_NSS_MUST_VERIFY_TRUST; 124 static const CK_TRUST ckt_nss_trusted_delegator = CKT_NSS_TRUSTED_DELEGATOR; 125 static const CK_ATTRIBUTE attributes[] = { 126 {CKA_CLASS, (void *)&cko_nss_trust, (PRUint32)sizeof(CK_OBJECT_CLASS)}, 127 {CKA_TOKEN, (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL)}, 128 {CKA_PRIVATE, (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL)}, 129 {CKA_MODIFIABLE, (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL)}, 130 {CKA_LABEL, 131 (void *)"Symantec Class 2 Public Primary Certification Authority - G4", 132 (PRUint32)61}, 133 {CKA_CERT_SHA1_HASH, 134 (void *)"\147\044\220\056\110\001\260\042\226\100\020\106\264\261\147\054" 135 "\251\165\375\053", 136 (PRUint32)20}, 137 {CKA_CERT_MD5_HASH, 138 (void *)"\160\325\060\361\332\224\227\324\327\164\337\276\355\150\336\226", 139 (PRUint32)16}, 140 {CKA_ISSUER, 141 (void *)"\060\201\224\061\013\060\011\006\003\125\004\006\023\002\125\123" 142 "\061\035\060\033\006\003\125\004\012\023\024\123\171\155\141\156" 143 "\164\145\143\040\103\157\162\160\157\162\141\164\151\157\156\061" 144 "\037\060\035\006\003\125\004\013\023\026\123\171\155\141\156\164" 145 "\145\143\040\124\162\165\163\164\040\116\145\164\167\157\162\153" 146 "\061\105\060\103\006\003\125\004\003\023\074\123\171\155\141\156" 147 "\164\145\143\040\103\154\141\163\163\040\062\040\120\165\142\154" 148 "\151\143\040\120\162\151\155\141\162\171\040\103\145\162\164\151" 149 "\146\151\143\141\164\151\157\156\040\101\165\164\150\157\162\151" 150 "\164\171\040\055\040\107\064", 151 (PRUint32)151}, 152 {CKA_SERIAL_NUMBER, 153 (void *)"\002\020\064\027\145\022\100\073\267\126\200\055\200\313\171\125" 154 "\246\036", 155 (PRUint32)18}, 156 {CKA_TRUST_SERVER_AUTH, (void *)&ckt_nss_must_verify_trust, 157 (PRUint32)sizeof(CK_TRUST)}, 158 {CKA_TRUST_EMAIL_PROTECTION, (void *)&ckt_nss_trusted_delegator, 159 (PRUint32)sizeof(CK_TRUST)}, 160 {CKA_TRUST_CODE_SIGNING, (void *)&ckt_nss_must_verify_trust, 161 (PRUint32)sizeof(CK_TRUST)}, 162 {CKA_TRUST_STEP_UP_APPROVED, (void *)&ck_false, 163 (PRUint32)sizeof(CK_BBOOL)}}; 164 165 TEST_F(SoftokenTest, GetInvalidAttribute) { 166 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 167 ASSERT_TRUE(slot); 168 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 169 ScopedPK11GenericObject obj(PK11_CreateGenericObject( 170 slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); 171 ASSERT_NE(nullptr, obj); 172 SECItem out = {siBuffer, nullptr, 0}; 173 SECStatus rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj.get(), 174 CKA_ALLOWED_MECHANISMS, &out); 175 EXPECT_EQ(SECFailure, rv); 176 // CKR_ATTRIBUTE_TYPE_INVALID maps to SEC_ERROR_BAD_DATA. 177 EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); 178 } 179 180 TEST_F(SoftokenTest, GetValidAttributes) { 181 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 182 ASSERT_TRUE(slot); 183 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 184 ScopedPK11GenericObject obj(PK11_CreateGenericObject( 185 slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); 186 ASSERT_NE(nullptr, obj); 187 188 CK_ATTRIBUTE template_attrs[] = { 189 {CKA_LABEL, NULL, 0}, 190 {CKA_CERT_SHA1_HASH, NULL, 0}, 191 {CKA_ISSUER, NULL, 0}, 192 }; 193 SECStatus rv = 194 PK11_ReadRawAttributes(nullptr, PK11_TypeGeneric, obj.get(), 195 template_attrs, PR_ARRAY_SIZE(template_attrs)); 196 EXPECT_EQ(SECSuccess, rv); 197 ASSERT_EQ(attributes[4].ulValueLen, template_attrs[0].ulValueLen); 198 EXPECT_EQ(0, memcmp(attributes[4].pValue, template_attrs[0].pValue, 199 template_attrs[0].ulValueLen)); 200 ASSERT_EQ(attributes[5].ulValueLen, template_attrs[1].ulValueLen); 201 EXPECT_EQ(0, memcmp(attributes[5].pValue, template_attrs[1].pValue, 202 template_attrs[1].ulValueLen)); 203 ASSERT_EQ(attributes[7].ulValueLen, template_attrs[2].ulValueLen); 204 EXPECT_EQ(0, memcmp(attributes[7].pValue, template_attrs[2].pValue, 205 template_attrs[2].ulValueLen)); 206 for (unsigned int i = 0; i < PR_ARRAY_SIZE(template_attrs); i++) { 207 PORT_Free(template_attrs[i].pValue); 208 } 209 } 210 211 TEST_F(SoftokenTest, GetOnlyInvalidAttributes) { 212 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 213 ASSERT_TRUE(slot); 214 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 215 ScopedPK11GenericObject obj(PK11_CreateGenericObject( 216 slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); 217 ASSERT_NE(nullptr, obj); 218 219 // Provide buffers of sufficient size, so that token 220 // will write the data. This is annoying, but PK11_GetAttributes 221 // won't allocate in the cases below when a single attribute 222 // is missing. So, just put them all on the stack. 223 unsigned char buf1[100]; 224 unsigned char buf2[100]; 225 CK_ATTRIBUTE template_attrs[] = {{0xffffffffUL, buf1, sizeof(buf1)}, 226 {0xfffffffeUL, buf2, sizeof(buf2)}}; 227 SECStatus rv = 228 PK11_ReadRawAttributes(nullptr, PK11_TypeGeneric, obj.get(), 229 template_attrs, PR_ARRAY_SIZE(template_attrs)); 230 EXPECT_EQ(SECFailure, rv); 231 EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); 232 233 // MSVC rewards -1UL with a C4146 warning... 234 ASSERT_EQ(0UL, template_attrs[0].ulValueLen + 1); 235 ASSERT_EQ(0UL, template_attrs[1].ulValueLen + 1); 236 } 237 238 TEST_F(SoftokenTest, GetAttributesInvalidInterspersed1) { 239 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 240 ASSERT_TRUE(slot); 241 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 242 ScopedPK11GenericObject obj(PK11_CreateGenericObject( 243 slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); 244 ASSERT_NE(nullptr, obj); 245 246 unsigned char buf1[100]; 247 unsigned char buf2[100]; 248 unsigned char buf3[200]; 249 CK_ATTRIBUTE template_attrs[] = {{0xffffffff, buf1, sizeof(buf1)}, 250 {CKA_CERT_SHA1_HASH, buf2, sizeof(buf2)}, 251 {CKA_ISSUER, buf3, sizeof(buf3)}}; 252 SECStatus rv = 253 PK11_ReadRawAttributes(nullptr, PK11_TypeGeneric, obj.get(), 254 template_attrs, PR_ARRAY_SIZE(template_attrs)); 255 EXPECT_EQ(SECFailure, rv); 256 EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); 257 ASSERT_EQ(0UL, template_attrs[0].ulValueLen + 1); 258 ASSERT_EQ(attributes[5].ulValueLen, template_attrs[1].ulValueLen); 259 EXPECT_EQ(0, memcmp(attributes[5].pValue, template_attrs[1].pValue, 260 template_attrs[1].ulValueLen)); 261 ASSERT_EQ(attributes[7].ulValueLen, template_attrs[2].ulValueLen); 262 EXPECT_EQ(0, memcmp(attributes[7].pValue, template_attrs[2].pValue, 263 template_attrs[2].ulValueLen)); 264 } 265 266 TEST_F(SoftokenTest, GetAttributesInvalidInterspersed2) { 267 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 268 ASSERT_TRUE(slot); 269 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 270 ScopedPK11GenericObject obj(PK11_CreateGenericObject( 271 slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); 272 ASSERT_NE(nullptr, obj); 273 274 unsigned char buf1[100]; 275 unsigned char buf2[100]; 276 unsigned char buf3[100]; 277 CK_ATTRIBUTE template_attrs[] = {{CKA_LABEL, buf1, sizeof(buf1)}, 278 {CKA_CERT_SHA1_HASH, buf2, sizeof(buf2)}, 279 {0xffffffffUL, buf3, sizeof(buf3)}}; 280 SECStatus rv = 281 PK11_ReadRawAttributes(nullptr, PK11_TypeGeneric, obj.get(), 282 template_attrs, PR_ARRAY_SIZE(template_attrs)); 283 EXPECT_EQ(SECFailure, rv); 284 EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); 285 ASSERT_EQ(attributes[4].ulValueLen, template_attrs[0].ulValueLen); 286 EXPECT_EQ(0, memcmp(attributes[4].pValue, template_attrs[0].pValue, 287 template_attrs[0].ulValueLen)); 288 ASSERT_EQ(attributes[5].ulValueLen, template_attrs[1].ulValueLen); 289 EXPECT_EQ(0, memcmp(attributes[5].pValue, template_attrs[1].pValue, 290 template_attrs[1].ulValueLen)); 291 ASSERT_EQ(0UL, template_attrs[2].ulValueLen + 1); 292 } 293 294 TEST_F(SoftokenTest, GetAttributesInvalidInterspersed3) { 295 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 296 ASSERT_TRUE(slot); 297 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 298 ScopedPK11GenericObject obj(PK11_CreateGenericObject( 299 slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); 300 ASSERT_NE(nullptr, obj); 301 302 unsigned char buf1[100]; 303 unsigned char buf2[100]; 304 unsigned char buf3[100]; 305 unsigned char buf4[100]; 306 unsigned char buf5[100]; 307 unsigned char buf6[200]; 308 CK_ATTRIBUTE template_attrs[6] = {{CKA_LABEL, buf1, sizeof(buf1)}, 309 {0xffffffffUL, buf2, sizeof(buf2)}, 310 {0xfffffffeUL, buf3, sizeof(buf3)}, 311 {CKA_CERT_SHA1_HASH, buf4, sizeof(buf4)}, 312 {0xfffffffdUL, buf5, sizeof(buf5)}, 313 {CKA_ISSUER, buf6, sizeof(buf6)}}; 314 SECStatus rv = 315 PK11_ReadRawAttributes(nullptr, PK11_TypeGeneric, obj.get(), 316 template_attrs, PR_ARRAY_SIZE(template_attrs)); 317 EXPECT_EQ(SECFailure, rv); 318 EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); 319 320 ASSERT_EQ(attributes[4].ulValueLen, template_attrs[0].ulValueLen); 321 EXPECT_EQ(0, memcmp(attributes[4].pValue, template_attrs[0].pValue, 322 template_attrs[0].ulValueLen)); 323 ASSERT_EQ(0UL, template_attrs[1].ulValueLen + 1); 324 ASSERT_EQ(0UL, template_attrs[2].ulValueLen + 1); 325 ASSERT_EQ(attributes[5].ulValueLen, template_attrs[3].ulValueLen); 326 EXPECT_EQ(0, memcmp(attributes[5].pValue, template_attrs[3].pValue, 327 template_attrs[3].ulValueLen)); 328 ASSERT_EQ(0UL, template_attrs[4].ulValueLen + 1); 329 ASSERT_EQ(attributes[7].ulValueLen, template_attrs[5].ulValueLen); 330 EXPECT_EQ(0, memcmp(attributes[7].pValue, template_attrs[5].pValue, 331 template_attrs[5].ulValueLen)); 332 } 333 334 TEST_F(SoftokenTest, CreateObjectNonEmptyPassword) { 335 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 336 ASSERT_TRUE(slot); 337 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 338 EXPECT_EQ(SECSuccess, PK11_Logout(slot.get())); 339 ScopedPK11GenericObject obj(PK11_CreateGenericObject( 340 slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); 341 EXPECT_EQ(nullptr, obj); 342 } 343 344 TEST_F(SoftokenTest, CreateObjectChangePassword) { 345 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 346 ASSERT_TRUE(slot); 347 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr)); 348 EXPECT_EQ(SECSuccess, PK11_ChangePW(slot.get(), "", "password")); 349 EXPECT_EQ(SECSuccess, PK11_Logout(slot.get())); 350 ScopedPK11GenericObject obj(PK11_CreateGenericObject( 351 slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); 352 EXPECT_EQ(nullptr, obj); 353 } 354 355 // The size limit for a password is 500 characters as defined in pkcs11i.h 356 TEST_F(SoftokenTest, CreateObjectChangeToBigPassword) { 357 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 358 ASSERT_TRUE(slot); 359 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr)); 360 EXPECT_EQ( 361 SECSuccess, 362 PK11_ChangePW(slot.get(), "", 363 "rUIFIFr2bxKnbJbitsfkyqttpk6vCJzlYMNxcxXcaN37gSZKbLk763X7iR" 364 "yeVNWZHQ02lSF69HYjzTyPW3318ZD0DBFMMbALZ8ZPZP73CIo5uIQlaowV" 365 "IbP8eOhRYtGUqoLGlcIFNEYogV8Q3GN58VeBMs0KxrIOvPQ9s8SnYYkqvt" 366 "zzgntmAvCgvk64x6eQf0okHwegd5wi6m0WVJytEepWXkP9J629FSa5kNT8" 367 "FvL3jvslkiImzTNuTvl32fQDXXMSc8vVk5Q3mH7trMZM0VDdwHWYERjHbz" 368 "kGxFgp0VhediHx7p9kkz6H6ac4et9sW4UkTnN7xhYc1Zr17wRSk2heQtcX" 369 "oZJGwuzhiKm8A8wkuVxms6zO56P4JORIk8oaUW6lyNTLo2kWWnTA")); 370 EXPECT_EQ(SECSuccess, PK11_Logout(slot.get())); 371 ScopedPK11GenericObject obj(PK11_CreateGenericObject( 372 slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); 373 EXPECT_EQ(nullptr, obj); 374 } 375 376 TEST_F(SoftokenTest, CreateObjectChangeToEmptyPassword) { 377 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 378 ASSERT_TRUE(slot); 379 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 380 EXPECT_EQ(SECSuccess, PK11_ChangePW(slot.get(), "password", "")); 381 // PK11_Logout returnes an error and SEC_ERROR_TOKEN_NOT_LOGGED_IN if the user 382 // is not "logged in". 383 EXPECT_EQ(SECFailure, PK11_Logout(slot.get())); 384 EXPECT_EQ(SEC_ERROR_TOKEN_NOT_LOGGED_IN, PORT_GetError()); 385 ScopedPK11GenericObject obj(PK11_CreateGenericObject( 386 slot.get(), attributes, PR_ARRAY_SIZE(attributes), true)); 387 // Because there's no password we can't logout and the operation should have 388 // succeeded. 389 EXPECT_NE(nullptr, obj); 390 } 391 392 // We should be able to read CRLF, LF and CR. 393 // During the Initialization of the NSS Database, is called a function to load 394 // PKCS11 modules defined in pkcs11.txt. This file is read to get the 395 // specifications, parse them and load the modules. Here we are ensuring that 396 // the parsing will work correctly, independent of the breaking line format of 397 // pkcs11.txt file, which could vary depending where it was created. 398 // If the parsing is not well interpreted, the database cannot initialize. 399 TEST_F(SoftokenTest, CreateObjectReadBreakLine) { 400 const std::string path = mNSSDBDir.GetPath(); 401 const std::string dbname_in = path + "/pkcs11.txt"; 402 const std::string dbname_out_cr = path + "/pkcs11_cr.txt"; 403 const std::string dbname_out_crlf = path + "/pkcs11_crlf.txt"; 404 const std::string dbname_out_lf = path + "/pkcs11_lf.txt"; 405 406 std::ifstream in(dbname_in); 407 ASSERT_TRUE(in); 408 std::ofstream out_cr(dbname_out_cr); 409 ASSERT_TRUE(out_cr); 410 std::ofstream out_crlf(dbname_out_crlf); 411 ASSERT_TRUE(out_crlf); 412 std::ofstream out_lf(dbname_out_lf); 413 ASSERT_TRUE(out_lf); 414 415 // Database should be correctly initialized by Setup() 416 ASSERT_TRUE(NSS_IsInitialized()); 417 ASSERT_EQ(SECSuccess, NSS_Shutdown()); 418 419 // Prepare the file formats with CR, CRLF and LF 420 for (std::string line; getline(in, line);) { 421 out_cr << line << "\r"; 422 out_crlf << line << "\r\n"; 423 out_lf << line << "\n"; 424 } 425 in.close(); 426 out_cr.close(); 427 out_crlf.close(); 428 out_lf.close(); 429 430 // Change the pkcs11.txt to CR format. 431 ASSERT_TRUE(!remove(dbname_in.c_str())); 432 ASSERT_TRUE(!rename(dbname_out_cr.c_str(), dbname_in.c_str())); 433 434 // Try to initialize with CR format. 435 std::string nssInitArg("sql:"); 436 nssInitArg.append(mNSSDBDir.GetUTF8Path()); 437 ASSERT_EQ(SECSuccess, NSS_Initialize(nssInitArg.c_str(), "", "", SECMOD_DB, 438 NSS_INIT_NOROOTINIT)); 439 ASSERT_TRUE(NSS_IsInitialized()); 440 ASSERT_EQ(SECSuccess, NSS_Shutdown()); 441 442 // Change the pkcs11.txt to CRLF format. 443 ASSERT_TRUE(!remove(dbname_in.c_str())); 444 ASSERT_TRUE(!rename(dbname_out_crlf.c_str(), dbname_in.c_str())); 445 446 // Try to initialize with CRLF format. 447 ASSERT_EQ(SECSuccess, NSS_Initialize(nssInitArg.c_str(), "", "", SECMOD_DB, 448 NSS_INIT_NOROOTINIT)); 449 ASSERT_TRUE(NSS_IsInitialized()); 450 ASSERT_EQ(SECSuccess, NSS_Shutdown()); 451 452 // Change the pkcs11.txt to LF format. 453 ASSERT_TRUE(!remove(dbname_in.c_str())); 454 ASSERT_TRUE(!rename(dbname_out_lf.c_str(), dbname_in.c_str())); 455 456 // Try to initialize with LF format. 457 ASSERT_EQ(SECSuccess, NSS_Initialize(nssInitArg.c_str(), "", "", SECMOD_DB, 458 NSS_INIT_NOROOTINIT)); 459 ASSERT_TRUE(NSS_IsInitialized()); 460 } 461 462 // Key IDs used for CreateKeyUnique test below 463 static unsigned char keyID1[16] = {0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 465 0x00, 0x00, 0x00, 0x01}; 466 static SECItem keyID1Item = {SECItemType::siBuffer, keyID1, sizeof(keyID1)}; 467 static unsigned char keyID2[16] = {0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 469 0x00, 0x00, 0x00, 0x02}; 470 static SECItem keyID2Item = {SECItemType::siBuffer, keyID2, sizeof(keyID2)}; 471 472 // Test that new keys added to the database are checked for uniqueness 473 // correctly. Any attempt to create a new key with the same ID and type of an 474 // existing key should just overwrite the existing key instead of creating a new 475 // key. 476 TEST_F(SoftokenTest, CreateKeyUnique) { 477 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 478 ASSERT_TRUE(slot); 479 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); 480 481 int aesKeySize = PK11_GetBestKeyLength(slot.get(), CKM_AES_CBC); 482 int des3KeySize = PK11_GetBestKeyLength(slot.get(), CKM_DES3_CBC); 483 484 ScopedPK11SymKey key1(PK11_TokenKeyGen(slot.get(), CKM_AES_CBC, 0, aesKeySize, 485 &keyID1Item, true, nullptr)); 486 487 // No new key should be generated here, as the ID and the type match. 488 ScopedPK11SymKey key2(PK11_TokenKeyGen(slot.get(), CKM_AES_CBC, 0, aesKeySize, 489 &keyID1Item, true, nullptr)); 490 EXPECT_EQ(key1->objectID, key2->objectID); 491 492 // This should generate a new key, as the type differs. 493 ScopedPK11SymKey key3(PK11_TokenKeyGen( 494 slot.get(), CKM_DES3_CBC, 0, des3KeySize, &keyID1Item, true, nullptr)); 495 EXPECT_NE(key1->objectID, key3->objectID); 496 497 // This should generate a new key, as the ID differs. 498 ScopedPK11SymKey key4(PK11_TokenKeyGen(slot.get(), CKM_AES_CBC, 0, aesKeySize, 499 &keyID2Item, true, nullptr)); 500 EXPECT_NE(key1->objectID, key4->objectID); 501 502 // This should generate a new key, as no ID is specified. 503 ScopedPK11SymKey key5(PK11_TokenKeyGen(slot.get(), CKM_AES_CBC, 0, aesKeySize, 504 NULL, true, nullptr)); 505 EXPECT_NE(key1->objectID, key5->objectID); 506 507 // The ID is not specified again. This should create a new key different from 508 // the previous one. 509 ScopedPK11SymKey key6(PK11_TokenKeyGen(slot.get(), CKM_AES_CBC, 0, aesKeySize, 510 NULL, true, nullptr)); 511 EXPECT_NE(key5->objectID, key6->objectID); 512 } 513 514 // Disabled on MacOS because of Bug 1962505 515 // (Skip test is insufficient because the error happens during 516 // test class construction) 517 #if !GTEST_OS_MAC 518 519 class SoftokenNonAsciiTest : public SoftokenTest { 520 protected: 521 SoftokenNonAsciiTest() : SoftokenTest("SoftokenTest.\xF7-") {} 522 }; 523 524 TEST_F(SoftokenNonAsciiTest, NonAsciiPathWorking) { 525 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 526 ASSERT_TRUE(slot); 527 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr)); 528 EXPECT_EQ(SECSuccess, PK11_ResetToken(slot.get(), nullptr)); 529 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr)); 530 } 531 #endif 532 533 // This is just any X509 certificate. Its contents don't matter. 534 static unsigned char certDER[] = { 535 0x30, 0x82, 0x01, 0xEF, 0x30, 0x82, 0x01, 0x94, 0xA0, 0x03, 0x02, 0x01, 536 0x02, 0x02, 0x14, 0x49, 0xC4, 0xC4, 0x4A, 0xB6, 0x86, 0x07, 0xA3, 0x06, 537 0xDC, 0x4D, 0xC8, 0xC3, 0xFE, 0xC7, 0x21, 0x3A, 0x2D, 0xE4, 0xDA, 0x30, 538 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 539 0x30, 0x0F, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 540 0x04, 0x74, 0x65, 0x73, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 541 0x35, 0x31, 0x31, 0x32, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 542 0x18, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 543 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x0F, 0x31, 0x0D, 0x30, 0x0B, 0x06, 544 0x03, 0x55, 0x04, 0x03, 0x0C, 0x04, 0x74, 0x65, 0x73, 0x74, 0x30, 0x82, 545 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 546 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 547 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBA, 0x88, 0x51, 0xA8, 0x44, 548 0x8E, 0x16, 0xD6, 0x41, 0xFD, 0x6E, 0xB6, 0x88, 0x06, 0x36, 0x10, 0x3D, 549 0x3C, 0x13, 0xD9, 0xEA, 0xE4, 0x35, 0x4A, 0xB4, 0xEC, 0xF5, 0x68, 0x57, 550 0x6C, 0x24, 0x7B, 0xC1, 0xC7, 0x25, 0xA8, 0xE0, 0xD8, 0x1F, 0xBD, 0xB1, 551 0x9C, 0x06, 0x9B, 0x6E, 0x1A, 0x86, 0xF2, 0x6B, 0xE2, 0xAF, 0x5A, 0x75, 552 0x6B, 0x6A, 0x64, 0x71, 0x08, 0x7A, 0xA5, 0x5A, 0xA7, 0x45, 0x87, 0xF7, 553 0x1C, 0xD5, 0x24, 0x9C, 0x02, 0x7E, 0xCD, 0x43, 0xFC, 0x1E, 0x69, 0xD0, 554 0x38, 0x20, 0x29, 0x93, 0xAB, 0x20, 0xC3, 0x49, 0xE4, 0xDB, 0xB9, 0x4C, 555 0xC2, 0x6B, 0x6C, 0x0E, 0xED, 0x15, 0x82, 0x0F, 0xF1, 0x7E, 0xAD, 0x69, 556 0x1A, 0xB1, 0xD3, 0x02, 0x3A, 0x8B, 0x2A, 0x41, 0xEE, 0xA7, 0x70, 0xE0, 557 0x0F, 0x0D, 0x8D, 0xFD, 0x66, 0x0B, 0x2B, 0xB0, 0x24, 0x92, 0xA4, 0x7D, 558 0xB9, 0x88, 0x61, 0x79, 0x90, 0xB1, 0x57, 0x90, 0x3D, 0xD2, 0x3B, 0xC5, 559 0xE0, 0xB8, 0x48, 0x1F, 0xA8, 0x37, 0xD3, 0x88, 0x43, 0xEF, 0x27, 0x16, 560 0xD8, 0x55, 0xB7, 0x66, 0x5A, 0xAA, 0x7E, 0x02, 0x90, 0x2F, 0x3A, 0x7B, 561 0x10, 0x80, 0x06, 0x24, 0xCC, 0x1C, 0x6C, 0x97, 0xAD, 0x96, 0x61, 0x5B, 562 0xB7, 0xE2, 0x96, 0x12, 0xC0, 0x75, 0x31, 0xA3, 0x0C, 0x91, 0xDD, 0xB4, 563 0xCA, 0xF7, 0xFC, 0xAD, 0x1D, 0x25, 0xD3, 0x09, 0xEF, 0xB9, 0x17, 0x0E, 564 0xA7, 0x68, 0xE1, 0xB3, 0x7B, 0x2F, 0x22, 0x6F, 0x69, 0xE3, 0xB4, 0x8A, 565 0x95, 0x61, 0x1D, 0xEE, 0x26, 0xD6, 0x25, 0x9D, 0xAB, 0x91, 0x08, 0x4E, 566 0x36, 0xCB, 0x1C, 0x24, 0x04, 0x2C, 0xBF, 0x16, 0x8B, 0x2F, 0xE5, 0xF1, 567 0x8F, 0x99, 0x17, 0x31, 0xB8, 0xB3, 0xFE, 0x49, 0x23, 0xFA, 0x72, 0x51, 568 0xC4, 0x31, 0xD5, 0x03, 0xAC, 0xDA, 0x18, 0x0A, 0x35, 0xED, 0x8D, 0x02, 569 0x03, 0x01, 0x00, 0x01, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 570 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 571 0x5C, 0x75, 0x51, 0x9F, 0x13, 0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 572 0xA3, 0xBC, 0x06, 0x30, 0x91, 0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 573 0xEC, 0xFD, 0xCB, 0x42, 0x80, 0x0A, 0x70, 0xE6, 0x02, 0x21, 0x00, 0x82, 574 0x12, 0xF7, 0xE5, 0xEA, 0x40, 0x27, 0xFD, 0xF7, 0xC0, 0x0E, 0x25, 0xF3, 575 0x3E, 0x34, 0x95, 0x80, 0xB9, 0xA3, 0x38, 0xE0, 0x56, 0x68, 0xDA, 0xE5, 576 0xC1, 0xF5, 0x37, 0xC7, 0xB5, 0xCE, 0x0D}; 577 578 struct PasswordPair { 579 const char *mInitialPassword; 580 const char *mSecondPassword; 581 }; 582 583 class SoftokenPasswordChangeTest 584 : public SoftokenTest, 585 public ::testing::WithParamInterface<PasswordPair> {}; 586 587 TEST_P(SoftokenPasswordChangeTest, KeepTrustAfterPasswordChange) { 588 const PasswordPair &passwords = GetParam(); 589 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 590 ASSERT_TRUE(slot); 591 // Set a password. 592 EXPECT_EQ(SECSuccess, 593 PK11_InitPin(slot.get(), nullptr, passwords.mInitialPassword)); 594 SECItem certDERItem = {siBuffer, certDER, sizeof(certDER)}; 595 // Import a certificate. 596 ScopedCERTCertificate cert(CERT_NewTempCertificate( 597 CERT_GetDefaultCertDB(), &certDERItem, nullptr, true, true)); 598 EXPECT_TRUE(cert); 599 SECStatus result = 600 PK11_ImportCert(slot.get(), cert.get(), CK_INVALID_HANDLE, "test", false); 601 EXPECT_EQ(SECSuccess, result); 602 // Set a trust value. 603 CERTCertTrust trust = {CERTDB_TRUSTED_CLIENT_CA | CERTDB_NS_TRUSTED_CA | 604 CERTDB_TRUSTED_CA | CERTDB_VALID_CA, 605 0, 0}; 606 result = CERT_ChangeCertTrust(nullptr, cert.get(), &trust); 607 EXPECT_EQ(SECSuccess, result); 608 // Release the certificate to ensure we get it from the DB rather than an 609 // in-memory cache, below. 610 cert = nullptr; 611 // Change the password. 612 result = PK11_ChangePW(slot.get(), passwords.mInitialPassword, 613 passwords.mSecondPassword); 614 EXPECT_EQ(SECSuccess, result); 615 // Look up the certificate again. 616 ScopedCERTCertificate newCert( 617 PK11_FindCertFromDERCertItem(slot.get(), &certDERItem, nullptr)); 618 EXPECT_TRUE(newCert.get()); 619 // The trust should be the same as before. 620 CERTCertTrust newTrust = {0, 0, 0}; 621 result = CERT_GetCertTrust(newCert.get(), &newTrust); 622 EXPECT_EQ(SECSuccess, result); 623 EXPECT_EQ(trust.sslFlags, newTrust.sslFlags); 624 EXPECT_EQ(trust.emailFlags, newTrust.emailFlags); 625 EXPECT_EQ(trust.objectSigningFlags, newTrust.objectSigningFlags); 626 } 627 628 static const PasswordPair PASSWORD_CHANGE_TESTS[] = { 629 {"password", ""}, // non-empty to empty password 630 {"", "password"}, // empty to non-empty password 631 {"password", "password2"}, // non-empty to non-empty password 632 }; 633 634 INSTANTIATE_TEST_SUITE_P(SoftokenPasswordChangeTests, 635 SoftokenPasswordChangeTest, 636 ::testing::ValuesIn(PASSWORD_CHANGE_TESTS)); 637 638 class SoftokenNoDBTest : public ::testing::Test {}; 639 640 TEST_F(SoftokenNoDBTest, NeedUserInitNoDB) { 641 ASSERT_EQ(SECSuccess, NSS_NoDB_Init(".")); 642 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 643 ASSERT_TRUE(slot); 644 EXPECT_EQ(PR_FALSE, PK11_NeedUserInit(slot.get())); 645 646 // When shutting down in here we have to release the slot first. 647 slot = nullptr; 648 ASSERT_EQ(SECSuccess, NSS_Shutdown()); 649 } 650 651 SECStatus test_dh_value(const PQGParams *params, const SECItem *pub_key_value, 652 PRBool genFailOK, time_t *time) { 653 SECKEYDHParams dh_params; 654 dh_params.base = params->base; 655 dh_params.prime = params->prime; 656 657 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 658 EXPECT_TRUE(slot); 659 if (!slot) return SECFailure; 660 661 /* create a private/public key pair in with the given params */ 662 SECKEYPublicKey *pub_tmp = nullptr; 663 ScopedSECKEYPrivateKey priv_key( 664 PK11_GenerateKeyPair(slot.get(), CKM_DH_PKCS_KEY_PAIR_GEN, &dh_params, 665 &pub_tmp, PR_FALSE, PR_TRUE, nullptr)); 666 if ((genFailOK) && ((priv_key.get() == nullptr) || (pub_tmp == nullptr))) { 667 return SECFailure; 668 } 669 EXPECT_NE(nullptr, priv_key.get()) 670 << "PK11_GenerateKeyPair failed: " << PORT_ErrorToName(PORT_GetError()); 671 EXPECT_NE(nullptr, pub_tmp); 672 if ((priv_key.get() == nullptr) || (pub_tmp == nullptr)) return SECFailure; 673 ScopedSECKEYPublicKey pub_key(pub_tmp); 674 ScopedSECKEYPublicKey peer_pub_key_manager(nullptr); 675 SECKEYPublicKey *peer_pub_key = pub_key.get(); 676 677 /* if a subprime has been given set it on the PKCS #11 key */ 678 if (params->subPrime.data != nullptr) { 679 SECStatus rv; 680 EXPECT_EQ(SECSuccess, rv = PK11_WriteRawAttribute( 681 PK11_TypePrivKey, priv_key.get(), CKA_SUBPRIME, 682 (SECItem *)¶ms->subPrime)) 683 << "PK11_WriteRawAttribute failed: " 684 << PORT_ErrorToString(PORT_GetError()); 685 if (rv != SECSuccess) { 686 return rv; 687 } 688 } 689 690 /* find if we weren't passed a public value in, use the 691 * one we just generated */ 692 if (pub_key_value && pub_key_value->data) { 693 peer_pub_key = SECKEY_CopyPublicKey(pub_key.get()); 694 EXPECT_NE(nullptr, peer_pub_key); 695 if (peer_pub_key == nullptr) { 696 return SECFailure; 697 } 698 peer_pub_key->u.dh.publicValue = *pub_key_value; 699 peer_pub_key_manager.reset(peer_pub_key); 700 } 701 702 /* now do the derive. time it and return the time if 703 * the caller requested it. */ 704 auto start = high_resolution_clock::now(); 705 ScopedPK11SymKey derivedKey(PK11_PubDerive( 706 priv_key.get(), peer_pub_key, PR_FALSE, nullptr, nullptr, 707 CKM_DH_PKCS_DERIVE, CKM_HKDF_DERIVE, CKA_DERIVE, 32, nullptr)); 708 auto stop = high_resolution_clock::now(); 709 if (!derivedKey) { 710 std::cerr << "PK11_PubDerive failed: " 711 << PORT_ErrorToString(PORT_GetError()) << std::endl; 712 } 713 714 if (time) { 715 auto duration = duration_cast<microseconds>(stop - start); 716 *time = duration.count(); 717 } 718 return derivedKey ? SECSuccess : SECFailure; 719 } 720 721 class SoftokenDhTest : public SoftokenTest { 722 protected: 723 SoftokenDhTest() : SoftokenTest("SoftokenDhTest.d-") {} 724 #ifdef NSS_USE_TIMING_CODE 725 time_t reference_time[CLASS_LAST] = {0}; 726 #endif 727 728 virtual void SetUp() { 729 SoftokenTest::SetUp(); 730 731 #ifdef NSS_USE_TIMING_CODE 732 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 733 ASSERT_TRUE(slot); 734 735 time_t time; 736 for (int i = CLASS_FIRST; i < CLASS_LAST; i++) { 737 PQGParams params; 738 params.prime.data = (unsigned char *)reference_prime[i]; 739 params.prime.len = reference_prime_len[i]; 740 params.base.data = (unsigned char *)g2; 741 params.base.len = sizeof(g2); 742 params.subPrime.data = nullptr; 743 params.subPrime.len = 0; 744 ASSERT_EQ(SECSuccess, test_dh_value(¶ms, nullptr, PR_FALSE, &time)); 745 reference_time[i] = time / 2 + 3 * time; 746 } 747 #endif 748 }; 749 }; 750 751 const char *param_value(DhParamType param_type) { 752 switch (param_type) { 753 case TLS_APPROVED: 754 return "TLS_APPROVED"; 755 case IKE_APPROVED: 756 return "IKE_APPROVED"; 757 case SAFE_PRIME: 758 return "SAFE_PRIME"; 759 case SAFE_PRIME_WITH_SUBPRIME: 760 return "SAFE_PRIME_WITH_SUBPRIME"; 761 case KNOWN_SUBPRIME: 762 return "KNOWN_SUBPRIME"; 763 case UNKNOWN_SUBPRIME: 764 return "UNKNOWN_SUBPRIME"; 765 case WRONG_SUBPRIME: 766 return "WRONG_SUBPRIME"; 767 case BAD_PUB_KEY: 768 return "BAD_PUB_KEY"; 769 } 770 return "**Invalid**"; 771 } 772 773 const char *key_value(DhKeyClass key_class) { 774 switch (key_class) { 775 case CLASS_1536: 776 return "CLASS_1536"; 777 case CLASS_2048: 778 return "CLASS_2048"; 779 case CLASS_3072: 780 return "CLASS_3072"; 781 case CLASS_4096: 782 return "CLASS_4096"; 783 case CLASS_6144: 784 return "CLASS_6144"; 785 case CLASS_8192: 786 return "CLASS_8192"; 787 case CLASS_LAST: 788 break; 789 } 790 return "**Invalid**"; 791 } 792 793 class SoftokenDhValidate : public SoftokenDhTest, 794 public ::testing::WithParamInterface<DhTestVector> { 795 }; 796 797 /* test the DH validation process. In non-fips mode, only BAD_PUB_KEY tests 798 * should fail */ 799 TEST_P(SoftokenDhValidate, DhVectors) { 800 const DhTestVector dhTestValues = GetParam(); 801 std::string testId = (char *)(dhTestValues.id); 802 std::string err = "Test(" + testId + ") failed"; 803 SECStatus rv; 804 time_t time; 805 806 PQGParams params; 807 params.prime = dhTestValues.p; 808 params.base = dhTestValues.g; 809 params.subPrime = dhTestValues.q; 810 811 std::cerr << "Test: " + testId << std::endl 812 << "param_type: " << param_value(dhTestValues.param_type) 813 << ", key_class: " << key_value(dhTestValues.key_class) << std::endl 814 << "p: " << DataBuffer(dhTestValues.p.data, dhTestValues.p.len) 815 << std::endl 816 << "g: " << DataBuffer(dhTestValues.g.data, dhTestValues.g.len) 817 << std::endl 818 << "q: " << DataBuffer(dhTestValues.q.data, dhTestValues.q.len) 819 << std::endl 820 << "pub_key: " 821 << DataBuffer(dhTestValues.pub_key.data, dhTestValues.pub_key.len) 822 << std::endl; 823 rv = test_dh_value(¶ms, &dhTestValues.pub_key, PR_FALSE, &time); 824 825 switch (dhTestValues.param_type) { 826 case TLS_APPROVED: 827 case IKE_APPROVED: 828 case SAFE_PRIME: 829 case UNKNOWN_SUBPRIME: 830 EXPECT_EQ(SECSuccess, rv) << err; 831 #ifdef NSS_USE_TIMING_CODE 832 EXPECT_LE(time, reference_time[dhTestValues.key_class]) << err; 833 #endif 834 break; 835 case KNOWN_SUBPRIME: 836 case SAFE_PRIME_WITH_SUBPRIME: 837 EXPECT_EQ(SECSuccess, rv) << err; 838 #ifdef NSS_USE_TIMING_CODE 839 EXPECT_GT(time, reference_time[dhTestValues.key_class]) << err; 840 #endif 841 break; 842 case WRONG_SUBPRIME: 843 case BAD_PUB_KEY: 844 EXPECT_EQ(SECFailure, rv) << err; 845 break; 846 } 847 } 848 849 INSTANTIATE_TEST_SUITE_P(DhValidateCases, SoftokenDhValidate, 850 ::testing::ValuesIn(DH_TEST_VECTORS)); 851 852 #ifndef NSS_FIPS_DISABLED 853 854 class SoftokenFipsTest : public SoftokenTest { 855 protected: 856 SoftokenFipsTest() : SoftokenTest("SoftokenFipsTest.d-") {} 857 SoftokenFipsTest(const std::string &prefix) : SoftokenTest(prefix) {} 858 859 virtual void SetUp() { 860 SoftokenTest::SetUp(); 861 862 // Turn on FIPS mode (code borrowed from FipsMode in modutil/pk11.c) 863 char *internal_name; 864 ASSERT_FALSE(PK11_IsFIPS()); 865 internal_name = PR_smprintf("%s", SECMOD_GetInternalModule()->commonName); 866 ASSERT_EQ(SECSuccess, SECMOD_DeleteInternalModule(internal_name)) 867 << PORT_ErrorToName(PORT_GetError()); 868 PR_smprintf_free(internal_name); 869 ASSERT_TRUE(PK11_IsFIPS()); 870 } 871 }; 872 873 class SoftokenFipsDhTest : public SoftokenFipsTest { 874 protected: 875 SoftokenFipsDhTest() : SoftokenFipsTest("SoftokenFipsDhTest.d-") {} 876 #ifdef NSS_USE_TIMING_CODE 877 time_t reference_time[CLASS_LAST] = {0}; 878 #endif 879 880 virtual void SetUp() { 881 SoftokenFipsTest::SetUp(); 882 883 ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); 884 ASSERT_TRUE(slot); 885 886 ASSERT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "")); 887 ASSERT_EQ(SECSuccess, PK11_Authenticate(slot.get(), PR_FALSE, nullptr)); 888 889 #ifdef NSS_USE_TIMING_CODE 890 time_t time; 891 for (int i = CLASS_FIRST; i < CLASS_LAST; i++) { 892 PQGParams params; 893 params.prime.data = (unsigned char *)reference_prime[i]; 894 params.prime.len = reference_prime_len[i]; 895 params.base.data = (unsigned char *)g2; 896 params.base.len = sizeof(g2); 897 params.subPrime.data = nullptr; 898 params.subPrime.len = 0; 899 ASSERT_EQ(SECSuccess, test_dh_value(¶ms, nullptr, PR_FALSE, &time)); 900 reference_time[i] = time / 2 + 3 * time; 901 } 902 #endif 903 }; 904 }; 905 906 const std::vector<std::string> kFipsPasswordCases[] = { 907 // FIPS level1 -> level1 -> level1 908 {"", "", ""}, 909 // FIPS level1 -> level1 -> level2 910 {"", "", "strong-_123"}, 911 // FIXME: this should work: FIPS level1 -> level2 -> level2 912 // {"", "strong-_123", "strong-_456"}, 913 // FIPS level2 -> level2 -> level2 914 {"strong-_123", "strong-_456", "strong-_123"}}; 915 916 const std::vector<std::string> kFipsPasswordBadCases[] = { 917 // FIPS level1 -> level2 -> level1 918 {"", "strong-_123", ""}, 919 // FIPS level2 -> level1 -> level1 920 {"strong-_123", ""}, 921 // FIPS level2 -> level2 -> level1 922 {"strong-_123", "strong-_456", ""}, 923 // initialize with a weak password 924 {"weak"}, 925 // FIPS level1 -> weak password 926 {"", "weak"}, 927 // FIPS level2 -> weak password 928 {"strong-_123", "weak"}}; 929 930 class SoftokenFipsPasswordTest 931 : public SoftokenFipsTest, 932 public ::testing::WithParamInterface<std::vector<std::string>> {}; 933 934 class SoftokenFipsBadPasswordTest 935 : public SoftokenFipsTest, 936 public ::testing::WithParamInterface<std::vector<std::string>> {}; 937 938 TEST_P(SoftokenFipsPasswordTest, SetPassword) { 939 const std::vector<std::string> &passwords = GetParam(); 940 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 941 ASSERT_TRUE(slot); 942 943 auto it = passwords.begin(); 944 auto prev_it = it; 945 EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, (*it).c_str())); 946 for (it++; it != passwords.end(); it++, prev_it++) { 947 EXPECT_EQ(SECSuccess, 948 PK11_ChangePW(slot.get(), (*prev_it).c_str(), (*it).c_str())); 949 } 950 } 951 952 TEST_P(SoftokenFipsBadPasswordTest, SetBadPassword) { 953 const std::vector<std::string> &passwords = GetParam(); 954 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 955 ASSERT_TRUE(slot); 956 957 auto it = passwords.begin(); 958 auto prev_it = it; 959 SECStatus rv = PK11_InitPin(slot.get(), nullptr, (*it).c_str()); 960 if (it + 1 == passwords.end()) 961 EXPECT_EQ(SECFailure, rv); 962 else 963 EXPECT_EQ(SECSuccess, rv); 964 for (it++; it != passwords.end(); it++, prev_it++) { 965 rv = PK11_ChangePW(slot.get(), (*prev_it).c_str(), (*it).c_str()); 966 if (it + 1 == passwords.end()) 967 EXPECT_EQ(SECFailure, rv); 968 else 969 EXPECT_EQ(SECSuccess, rv); 970 } 971 } 972 973 class SoftokenFipsDhValidate 974 : public SoftokenFipsDhTest, 975 public ::testing::WithParamInterface<DhTestVector> {}; 976 977 /* test the DH validation process. In fips mode, primes with unknown 978 * subprimes, and all sorts of bad public keys should fail */ 979 TEST_P(SoftokenFipsDhValidate, DhVectors) { 980 const DhTestVector dhTestValues = GetParam(); 981 std::string testId = (char *)(dhTestValues.id); 982 std::string err = "Test(" + testId + ") failed"; 983 time_t time; 984 PRBool genFailOK = PR_FALSE; 985 SECStatus rv; 986 987 PQGParams params; 988 params.prime = dhTestValues.p; 989 params.base = dhTestValues.g; 990 params.subPrime = dhTestValues.q; 991 std::cerr << "Test:" + testId << std::endl 992 << "param_type: " << param_value(dhTestValues.param_type) 993 << ", key_class: " << key_value(dhTestValues.key_class) << std::endl 994 << "p: " << DataBuffer(dhTestValues.p.data, dhTestValues.p.len) 995 << std::endl 996 << "g: " << DataBuffer(dhTestValues.g.data, dhTestValues.g.len) 997 << std::endl 998 << "q: " << DataBuffer(dhTestValues.q.data, dhTestValues.q.len) 999 << std::endl 1000 << "pub_key: " 1001 << DataBuffer(dhTestValues.pub_key.data, dhTestValues.pub_key.len) 1002 << std::endl; 1003 1004 if ((dhTestValues.param_type != TLS_APPROVED) && 1005 (dhTestValues.param_type != IKE_APPROVED)) { 1006 genFailOK = PR_TRUE; 1007 } 1008 rv = test_dh_value(¶ms, &dhTestValues.pub_key, genFailOK, &time); 1009 1010 switch (dhTestValues.param_type) { 1011 case TLS_APPROVED: 1012 case IKE_APPROVED: 1013 EXPECT_EQ(SECSuccess, rv) << err; 1014 #ifdef NSS_USE_TIMING_CODE 1015 EXPECT_LE(time, reference_time[dhTestValues.key_class]) << err; 1016 #endif 1017 break; 1018 case SAFE_PRIME: 1019 case SAFE_PRIME_WITH_SUBPRIME: 1020 case KNOWN_SUBPRIME: 1021 case UNKNOWN_SUBPRIME: 1022 case WRONG_SUBPRIME: 1023 case BAD_PUB_KEY: 1024 EXPECT_EQ(SECFailure, rv) << err; 1025 break; 1026 } 1027 } 1028 1029 INSTANTIATE_TEST_SUITE_P(FipsPasswordCases, SoftokenFipsPasswordTest, 1030 ::testing::ValuesIn(kFipsPasswordCases)); 1031 1032 INSTANTIATE_TEST_SUITE_P(BadFipsPasswordCases, SoftokenFipsBadPasswordTest, 1033 ::testing::ValuesIn(kFipsPasswordBadCases)); 1034 1035 INSTANTIATE_TEST_SUITE_P(FipsDhCases, SoftokenFipsDhValidate, 1036 ::testing::ValuesIn(DH_TEST_VECTORS)); 1037 #endif 1038 1039 } // namespace nss_test 1040 1041 int main(int argc, char **argv) { 1042 ::testing::InitGoogleTest(&argc, argv); 1043 1044 return RUN_ALL_TESTS(); 1045 }