1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/common/net/x509_certificate_model.h" 6 7 #include "base/files/file_path.h" 8 #include "base/path_service.h" 9 #include "net/base/test_data_directory.h" 10 #include "net/test/cert_test_util.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 13 #if defined(USE_NSS) 14 #include "crypto/scoped_test_nss_db.h" 15 #include "net/cert/nss_cert_database.h" 16 #endif 17 18 TEST(X509CertificateModelTest, GetCertNameOrNicknameAndGetTitle) { 19 scoped_refptr<net::X509Certificate> cert( 20 net::ImportCertFromFile(net::GetTestCertsDirectory(), 21 "root_ca_cert.pem")); 22 ASSERT_TRUE(cert.get()); 23 EXPECT_EQ( 24 "Test Root CA", 25 x509_certificate_model::GetCertNameOrNickname(cert->os_cert_handle())); 26 27 scoped_refptr<net::X509Certificate> punycode_cert( 28 net::ImportCertFromFile(net::GetTestCertsDirectory(), 29 "punycodetest.pem")); 30 ASSERT_TRUE(punycode_cert.get()); 31 EXPECT_EQ("xn--wgv71a119e.com (.com)", 32 x509_certificate_model::GetCertNameOrNickname( 33 punycode_cert->os_cert_handle())); 34 35 scoped_refptr<net::X509Certificate> no_cn_cert( 36 net::ImportCertFromFile(net::GetTestCertsDirectory(), 37 "no_subject_common_name_cert.pem")); 38 ASSERT_TRUE(no_cn_cert.get()); 39 #if defined(USE_OPENSSL) 40 EXPECT_EQ("emailAddress=wtc (at) google.com", 41 x509_certificate_model::GetCertNameOrNickname( 42 no_cn_cert->os_cert_handle())); 43 #else 44 // Temp cert has no nickname. 45 EXPECT_EQ("", 46 x509_certificate_model::GetCertNameOrNickname( 47 no_cn_cert->os_cert_handle())); 48 #endif 49 50 EXPECT_EQ("xn--wgv71a119e.com", 51 x509_certificate_model::GetTitle( 52 punycode_cert->os_cert_handle())); 53 54 #if defined(USE_OPENSSL) 55 EXPECT_EQ("emailAddress=wtc (at) google.com", 56 x509_certificate_model::GetTitle( 57 no_cn_cert->os_cert_handle())); 58 #else 59 EXPECT_EQ("E=wtc (at) google.com", 60 x509_certificate_model::GetTitle( 61 no_cn_cert->os_cert_handle())); 62 #endif 63 64 scoped_refptr<net::X509Certificate> no_cn_cert2(net::ImportCertFromFile( 65 net::GetTestCertsDirectory(), "ct-test-embedded-cert.pem")); 66 ASSERT_TRUE(no_cn_cert2.get()); 67 EXPECT_EQ("L=Erw Wen,ST=Wales,O=Certificate Transparency,C=GB", 68 x509_certificate_model::GetTitle(no_cn_cert2->os_cert_handle())); 69 } 70 71 TEST(X509CertificateModelTest, GetExtensions) { 72 { 73 scoped_refptr<net::X509Certificate> cert(net::ImportCertFromFile( 74 net::GetTestCertsDirectory(), "root_ca_cert.pem")); 75 ASSERT_TRUE(cert.get()); 76 77 x509_certificate_model::Extensions extensions; 78 x509_certificate_model::GetExtensions( 79 "critical", "notcrit", cert->os_cert_handle(), &extensions); 80 ASSERT_EQ(3U, extensions.size()); 81 82 EXPECT_EQ("Certificate Basic Constraints", extensions[0].name); 83 EXPECT_EQ( 84 "critical\nIs a Certification Authority\n" 85 "Maximum number of intermediate CAs: unlimited", 86 extensions[0].value); 87 88 EXPECT_EQ("Certificate Subject Key ID", extensions[1].name); 89 EXPECT_EQ( 90 "notcrit\nKey ID: BC F7 30 D1 3C C0 F2 79 FA EF 9F C9 6C 5C 93 F3\n8A " 91 "68 AB 83", 92 extensions[1].value); 93 94 EXPECT_EQ("Certificate Key Usage", extensions[2].name); 95 EXPECT_EQ("critical\nCertificate Signer\nCRL Signer", extensions[2].value); 96 } 97 98 { 99 scoped_refptr<net::X509Certificate> cert(net::ImportCertFromFile( 100 net::GetTestCertsDirectory(), "subjectAltName_sanity_check.pem")); 101 x509_certificate_model::Extensions extensions; 102 x509_certificate_model::GetExtensions( 103 "critical", "notcrit", cert->os_cert_handle(), &extensions); 104 ASSERT_EQ(2U, extensions.size()); 105 EXPECT_EQ("Certificate Subject Alternative Name", extensions[1].name); 106 EXPECT_EQ( 107 "notcrit\nIP Address: 127.0.0.2\nIP Address: fe80::1\nDNS Name: " 108 "test.example\nEmail Address: test (at) test.example\nOID.1.2.3.4: 0C 09 69 " 109 "67 6E 6F 72 65 20 6D 65\nX.500 Name: CN = 127.0.0.3\n\n", 110 extensions[1].value); 111 } 112 113 { 114 scoped_refptr<net::X509Certificate> cert(net::ImportCertFromFile( 115 net::GetTestCertsDirectory(), "foaf.me.chromium-test-cert.der")); 116 x509_certificate_model::Extensions extensions; 117 x509_certificate_model::GetExtensions( 118 "critical", "notcrit", cert->os_cert_handle(), &extensions); 119 ASSERT_EQ(5U, extensions.size()); 120 EXPECT_EQ("Netscape Certificate Comment", extensions[1].name); 121 EXPECT_EQ("notcrit\nOpenSSL Generated Certificate", extensions[1].value); 122 } 123 124 { 125 scoped_refptr<net::X509Certificate> cert(net::ImportCertFromFile( 126 net::GetTestCertsDirectory(), "2029_globalsign_com_cert.pem")); 127 x509_certificate_model::Extensions extensions; 128 x509_certificate_model::GetExtensions( 129 "critical", "notcrit", cert->os_cert_handle(), &extensions); 130 ASSERT_EQ(9U, extensions.size()); 131 132 EXPECT_EQ("Certificate Subject Key ID", extensions[0].name); 133 EXPECT_EQ( 134 "notcrit\nKey ID: 59 BC D9 69 F7 B0 65 BB C8 34 C5 D2 C2 EF 17 78\nA6 " 135 "47 1E 8B", 136 extensions[0].value); 137 138 EXPECT_EQ("Certification Authority Key ID", extensions[1].name); 139 EXPECT_EQ( 140 "notcrit\nKey ID: 8A FC 14 1B 3D A3 59 67 A5 3B E1 73 92 A6 62 91\n7F " 141 "E4 78 30\n", 142 extensions[1].value); 143 144 EXPECT_EQ("Authority Information Access", extensions[2].name); 145 EXPECT_EQ( 146 "notcrit\nCA Issuers: " 147 "URI: http://secure.globalsign.net/cacert/SHA256extendval1.crt\n", 148 extensions[2].value); 149 150 EXPECT_EQ("CRL Distribution Points", extensions[3].name); 151 EXPECT_EQ("notcrit\nURI: http://crl.globalsign.net/SHA256ExtendVal1.crl\n", 152 extensions[3].value); 153 154 EXPECT_EQ("Certificate Basic Constraints", extensions[4].name); 155 EXPECT_EQ("notcrit\nIs not a Certification Authority\n", 156 extensions[4].value); 157 158 EXPECT_EQ("Certificate Key Usage", extensions[5].name); 159 EXPECT_EQ( 160 "critical\nSigning\nNon-repudiation\nKey Encipherment\n" 161 "Data Encipherment", 162 extensions[5].value); 163 164 EXPECT_EQ("Extended Key Usage", extensions[6].name); 165 EXPECT_EQ( 166 "notcrit\nTLS WWW Server Authentication (OID.1.3.6.1.5.5.7.3.1)\n" 167 "TLS WWW Client Authentication (OID.1.3.6.1.5.5.7.3.2)\n", 168 extensions[6].value); 169 170 EXPECT_EQ("Certificate Policies", extensions[7].name); 171 EXPECT_EQ( 172 "notcrit\nOID.1.3.6.1.4.1.4146.1.1:\n" 173 " Certification Practice Statement Pointer:" 174 " http://www.globalsign.net/repository/\n", 175 extensions[7].value); 176 177 EXPECT_EQ("Netscape Certificate Type", extensions[8].name); 178 EXPECT_EQ("notcrit\nSSL Client Certificate\nSSL Server Certificate", 179 extensions[8].value); 180 } 181 182 { 183 scoped_refptr<net::X509Certificate> cert(net::ImportCertFromFile( 184 net::GetTestCertsDirectory(), "diginotar_public_ca_2025.pem")); 185 x509_certificate_model::Extensions extensions; 186 x509_certificate_model::GetExtensions( 187 "critical", "notcrit", cert->os_cert_handle(), &extensions); 188 ASSERT_EQ(7U, extensions.size()); 189 190 EXPECT_EQ("Authority Information Access", extensions[0].name); 191 EXPECT_EQ( 192 "notcrit\nOCSP Responder: " 193 "URI: http://validation.diginotar.nl\n", 194 extensions[0].value); 195 196 EXPECT_EQ("Certificate Basic Constraints", extensions[2].name); 197 EXPECT_EQ( 198 "critical\nIs a Certification Authority\n" 199 "Maximum number of intermediate CAs: 0", 200 extensions[2].value); 201 EXPECT_EQ("Certificate Policies", extensions[3].name); 202 EXPECT_EQ( 203 "notcrit\nOID.2.16.528.1.1001.1.1.1.1.5.2.6.4:\n" 204 " Certification Practice Statement Pointer:" 205 " http://www.diginotar.nl/cps\n" 206 " User Notice:\n" 207 " Conditions, as mentioned on our website (www.diginotar.nl), are " 208 "applicable to all our products and services.\n", 209 extensions[3].value); 210 } 211 } 212 213 TEST(X509CertificateModelTest, GetTypeCA) { 214 scoped_refptr<net::X509Certificate> cert( 215 net::ImportCertFromFile(net::GetTestCertsDirectory(), 216 "root_ca_cert.pem")); 217 ASSERT_TRUE(cert.get()); 218 219 #if defined(USE_OPENSSL) 220 // Remove this when OpenSSL build implements the necessary functions. 221 EXPECT_EQ(net::OTHER_CERT, 222 x509_certificate_model::GetType(cert->os_cert_handle())); 223 #else 224 EXPECT_EQ(net::CA_CERT, 225 x509_certificate_model::GetType(cert->os_cert_handle())); 226 227 crypto::ScopedTestNSSDB test_nssdb; 228 net::NSSCertDatabase db(crypto::ScopedPK11Slot(PK11_ReferenceSlot( 229 test_nssdb.slot())) /* public slot */, 230 crypto::ScopedPK11Slot(PK11_ReferenceSlot( 231 test_nssdb.slot())) /* private slot */); 232 233 // Test that explicitly distrusted CA certs are still returned as CA_CERT 234 // type. See http://crbug.com/96654. 235 EXPECT_TRUE(db.SetCertTrust( 236 cert.get(), net::CA_CERT, net::NSSCertDatabase::DISTRUSTED_SSL)); 237 238 EXPECT_EQ(net::CA_CERT, 239 x509_certificate_model::GetType(cert->os_cert_handle())); 240 #endif 241 } 242 243 TEST(X509CertificateModelTest, GetTypeServer) { 244 scoped_refptr<net::X509Certificate> cert( 245 net::ImportCertFromFile(net::GetTestCertsDirectory(), 246 "google.single.der")); 247 ASSERT_TRUE(cert.get()); 248 249 #if defined(USE_OPENSSL) 250 // Remove this when OpenSSL build implements the necessary functions. 251 EXPECT_EQ(net::OTHER_CERT, 252 x509_certificate_model::GetType(cert->os_cert_handle())); 253 #else 254 // Test mozilla_security_manager::GetCertType with server certs and default 255 // trust. Currently this doesn't work. 256 // TODO(mattm): make mozilla_security_manager::GetCertType smarter so we can 257 // tell server certs even if they have no trust bits set. 258 EXPECT_EQ(net::OTHER_CERT, 259 x509_certificate_model::GetType(cert->os_cert_handle())); 260 261 crypto::ScopedTestNSSDB test_nssdb; 262 net::NSSCertDatabase db(crypto::ScopedPK11Slot(PK11_ReferenceSlot( 263 test_nssdb.slot())) /* public slot */, 264 crypto::ScopedPK11Slot(PK11_ReferenceSlot( 265 test_nssdb.slot())) /* private slot */); 266 267 // Test GetCertType with server certs and explicit trust. 268 EXPECT_TRUE(db.SetCertTrust( 269 cert.get(), net::SERVER_CERT, net::NSSCertDatabase::TRUSTED_SSL)); 270 271 EXPECT_EQ(net::SERVER_CERT, 272 x509_certificate_model::GetType(cert->os_cert_handle())); 273 274 // Test GetCertType with server certs and explicit distrust. 275 EXPECT_TRUE(db.SetCertTrust( 276 cert.get(), net::SERVER_CERT, net::NSSCertDatabase::DISTRUSTED_SSL)); 277 278 EXPECT_EQ(net::SERVER_CERT, 279 x509_certificate_model::GetType(cert->os_cert_handle())); 280 #endif 281 } 282 283 // An X.509 v1 certificate with the version field omitted should get 284 // the default value v1. 285 TEST(X509CertificateModelTest, GetVersionOmitted) { 286 scoped_refptr<net::X509Certificate> cert( 287 net::ImportCertFromFile(net::GetTestCertsDirectory(), 288 "ndn.ca.crt")); 289 ASSERT_TRUE(cert.get()); 290 291 EXPECT_EQ("1", x509_certificate_model::GetVersion(cert->os_cert_handle())); 292 } 293 294 TEST(X509CertificateModelTest, GetCMSString) { 295 net::CertificateList certs = 296 CreateCertificateListFromFile(net::GetTestCertsDirectory(), 297 "multi-root-chain1.pem", 298 net::X509Certificate::FORMAT_AUTO); 299 300 net::X509Certificate::OSCertHandles cert_handles; 301 for (net::CertificateList::iterator i = certs.begin(); i != certs.end(); ++i) 302 cert_handles.push_back((*i)->os_cert_handle()); 303 ASSERT_EQ(4U, cert_handles.size()); 304 305 { 306 // Write the full chain. 307 std::string pkcs7_string = x509_certificate_model::GetCMSString( 308 cert_handles, 0, cert_handles.size()); 309 310 ASSERT_FALSE(pkcs7_string.empty()); 311 312 net::CertificateList decoded_certs = 313 net::X509Certificate::CreateCertificateListFromBytes( 314 pkcs7_string.data(), 315 pkcs7_string.size(), 316 net::X509Certificate::FORMAT_PKCS7); 317 318 ASSERT_EQ(certs.size(), decoded_certs.size()); 319 #if defined(USE_OPENSSL) 320 for (size_t i = 0; i < certs.size(); ++i) 321 EXPECT_TRUE(certs[i]->Equals(decoded_certs[i])); 322 #else 323 // NSS sorts the certs before writing the file. 324 EXPECT_TRUE(certs[0]->Equals(decoded_certs.back().get())); 325 for (size_t i = 1; i < certs.size(); ++i) 326 EXPECT_TRUE(certs[i]->Equals(decoded_certs[i - 1].get())); 327 #endif 328 } 329 330 { 331 // Write only the first cert. 332 std::string pkcs7_string = 333 x509_certificate_model::GetCMSString(cert_handles, 0, 1); 334 335 net::CertificateList decoded_certs = 336 net::X509Certificate::CreateCertificateListFromBytes( 337 pkcs7_string.data(), 338 pkcs7_string.size(), 339 net::X509Certificate::FORMAT_PKCS7); 340 341 ASSERT_EQ(1U, decoded_certs.size()); 342 EXPECT_TRUE(certs[0]->Equals(decoded_certs[0].get())); 343 } 344 } 345 346 TEST(X509CertificateModelTest, ProcessSecAlgorithms) { 347 { 348 scoped_refptr<net::X509Certificate> cert(net::ImportCertFromFile( 349 net::GetTestCertsDirectory(), "root_ca_cert.pem")); 350 ASSERT_TRUE(cert.get()); 351 EXPECT_EQ("PKCS #1 SHA-1 With RSA Encryption", 352 x509_certificate_model::ProcessSecAlgorithmSignature( 353 cert->os_cert_handle())); 354 EXPECT_EQ("PKCS #1 SHA-1 With RSA Encryption", 355 x509_certificate_model::ProcessSecAlgorithmSignatureWrap( 356 cert->os_cert_handle())); 357 EXPECT_EQ("PKCS #1 RSA Encryption", 358 x509_certificate_model::ProcessSecAlgorithmSubjectPublicKey( 359 cert->os_cert_handle())); 360 } 361 { 362 scoped_refptr<net::X509Certificate> cert(net::ImportCertFromFile( 363 net::GetTestCertsDirectory(), "weak_digest_md5_root.pem")); 364 ASSERT_TRUE(cert.get()); 365 EXPECT_EQ("PKCS #1 MD5 With RSA Encryption", 366 x509_certificate_model::ProcessSecAlgorithmSignature( 367 cert->os_cert_handle())); 368 EXPECT_EQ("PKCS #1 MD5 With RSA Encryption", 369 x509_certificate_model::ProcessSecAlgorithmSignatureWrap( 370 cert->os_cert_handle())); 371 EXPECT_EQ("PKCS #1 RSA Encryption", 372 x509_certificate_model::ProcessSecAlgorithmSubjectPublicKey( 373 cert->os_cert_handle())); 374 } 375 } 376 377 TEST(X509CertificateModelTest, ProcessSubjectPublicKeyInfo) { 378 { 379 scoped_refptr<net::X509Certificate> cert(net::ImportCertFromFile( 380 net::GetTestCertsDirectory(), "root_ca_cert.pem")); 381 ASSERT_TRUE(cert.get()); 382 EXPECT_EQ( 383 "Modulus (2048 bits):\n" 384 " B6 49 41 E3 42 01 51 A8 7F 3C 7A 71 D3 FB CD 91\n" 385 "35 17 84 1A 8E F6 36 C7 D1 70 1D FA 86 F3 6E BB\n" 386 "76 6F E8 32 2E 37 FD 38 92 3D 68 E4 8A 7D 42 33\n" 387 "14 46 1B DC 04 F6 91 6E 54 40 C4 0A 09 FD EC 2D\n" 388 "62 E2 5E E1 BA 2C 9C C1 B1 60 4C DA C7 F8 22 5C\n" 389 "82 20 65 42 1E 56 77 75 4F EB 90 2C 4A EA 57 0E\n" 390 "22 8D 6C 95 AC 11 EA CC D7 EE F6 70 0D 09 DD A6\n" 391 "35 61 5D C9 76 6D B0 F2 1E BF 30 86 D8 77 52 36\n" 392 "95 97 0E D1 46 C5 ED 81 3D 1B B0 F2 61 95 3C C1\n" 393 "40 38 EF 5F 5D BA 61 9F EF 2B 9C 9F 85 89 74 70\n" 394 "63 D5 76 E8 35 7E CE 01 E1 F3 11 11 90 1C 0D F5\n" 395 "FD 8D CE 10 6C AD 7C 55 1A 21 6F D7 2D F4 78 15\n" 396 "EA 2F 38 BD 91 9E 3C 1D 07 46 F5 43 C1 82 8B AF\n" 397 "12 53 65 19 8A 69 69 66 06 B2 DA 0B FA 2A 00 A1\n" 398 "2A 15 84 49 F1 01 BF 9B 30 06 D0 15 A0 1F 9D 51\n" 399 "91 47 E1 53 5F EF 5E EC C2 61 79 C2 14 9F C4 E3\n" 400 "\n" 401 #if defined(USE_OPENSSL) 402 " Public Exponent (17 bits):\n" 403 #else 404 " Public Exponent (24 bits):\n" 405 #endif 406 " 01 00 01", 407 x509_certificate_model::ProcessSubjectPublicKeyInfo( 408 cert->os_cert_handle())); 409 } 410 { 411 scoped_refptr<net::X509Certificate> cert(net::ImportCertFromFile( 412 net::GetTestCertsDirectory(), "prime256v1-ecdsa-intermediate.pem")); 413 ASSERT_TRUE(cert.get()); 414 EXPECT_EQ( 415 "04 DB 98 07 BC 61 DD 2D E6 B3 CC F7 D5 EA F7 A1\n" 416 "0D 28 DE F2 7C 26 97 CA EB D1 DB A3 1E C1 8F E9\n" 417 "E0 1E FE 31 BB AA 4A 5C 85 37 A6 FF 9E 2E 96 23\n" 418 "22 B8 30 5F 8F 22 AE B9 8B 6D 4F BD 4E F3 52 12\n" 419 "D4", 420 x509_certificate_model::ProcessSubjectPublicKeyInfo( 421 cert->os_cert_handle())); 422 } 423 } 424 425 TEST(X509CertificateModelTest, ProcessRawBitsSignatureWrap) { 426 scoped_refptr<net::X509Certificate> cert(net::ImportCertFromFile( 427 net::GetTestCertsDirectory(), "root_ca_cert.pem")); 428 ASSERT_TRUE(cert.get()); 429 EXPECT_EQ( 430 "57 07 29 FB 7F E8 FF B0 E6 D8 58 6A C3 90 A1 38\n" 431 "1C B4 F3 68 B1 EC E8 89 23 24 D7 A8 F2 21 C3 60\n" 432 "E4 A4 49 5C 00 BF DF C7 82 78 80 2B 18 F7 AD DD\n" 433 "D0 62 5E A7 B0 CC F0 AA B4 CE 70 12 59 65 67 76\n" 434 "05 00 18 9A FF C4 2A 17 E3 F1 55 D8 BE 5C 5E EB\n" 435 "CA CB 53 87 10 D5 09 32 36 A7 5E 41 F4 53 DA 7E\n" 436 "56 60 D2 7E 4E 9A A5 08 5F 5D 75 E9 E7 30 CB 22\n" 437 "E9 EF 19 49 83 A5 23 A1 F8 60 4C E5 36 D5 39 78\n" 438 "18 F1 5E BF CE AA 0B 53 81 2C 78 A9 0A 6B DB 13\n" 439 "10 21 14 7F 1B 70 3D 89 1A 40 8A 06 2C 5D 50 19\n" 440 "62 F9 C7 45 89 F2 3D 66 05 3D 7D 75 5B 55 1E 80\n" 441 "42 72 A1 9A 7C 6D 0A 74 F6 EE A6 21 6C 3A 98 FB\n" 442 "77 82 5F F2 6B 56 E6 DD 9B 8E 50 F0 C6 AE FD EA\n" 443 "A6 05 07 A9 26 06 56 B3 B2 D9 B2 37 A0 21 3E 79\n" 444 "06 1F B9 51 BE F4 B1 49 4D 90 B5 33 E5 0E C7 5E\n" 445 "5B 40 C5 6A 04 D1 43 7A 94 6A A4 4F 61 FC 82 E0", 446 x509_certificate_model::ProcessRawBitsSignatureWrap( 447 cert->os_cert_handle())); 448 } 449