1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.conscrypt; 18 19 import java.io.File; 20 import java.io.FileOutputStream; 21 import java.io.OutputStream; 22 import java.security.KeyStore; 23 import java.security.PrivateKey; 24 import java.security.PublicKey; 25 import java.security.cert.X509Certificate; 26 import java.util.Arrays; 27 import java.util.HashSet; 28 import java.util.List; 29 import java.util.Random; 30 import java.util.Set; 31 import javax.security.auth.x500.X500Principal; 32 import junit.framework.TestCase; 33 import libcore.java.security.TestKeyStore; 34 35 public class TrustedCertificateStoreTest extends TestCase { 36 private static final Random tempFileRandom = new Random(); 37 38 private final File dirTest = new File(System.getProperty("java.io.tmpdir", "."), 39 "cert-store-test" + tempFileRandom.nextInt()); 40 private final File dirSystem = new File(dirTest, "system"); 41 private final File dirAdded = new File(dirTest, "added"); 42 private final File dirDeleted = new File(dirTest, "removed"); 43 44 private static X509Certificate CA1; 45 private static X509Certificate CA2; 46 47 private static KeyStore.PrivateKeyEntry PRIVATE; 48 private static X509Certificate[] CHAIN; 49 50 private static X509Certificate CA3_WITH_CA1_SUBJECT; 51 private static String ALIAS_SYSTEM_CA1; 52 private static String ALIAS_SYSTEM_CA2; 53 private static String ALIAS_USER_CA1; 54 private static String ALIAS_USER_CA2; 55 56 private static String ALIAS_SYSTEM_CHAIN0; 57 private static String ALIAS_SYSTEM_CHAIN1; 58 private static String ALIAS_SYSTEM_CHAIN2; 59 private static String ALIAS_USER_CHAIN0; 60 private static String ALIAS_USER_CHAIN1; 61 private static String ALIAS_USER_CHAIN2; 62 63 private static String ALIAS_SYSTEM_CA3; 64 private static String ALIAS_SYSTEM_CA3_COLLISION; 65 private static String ALIAS_USER_CA3; 66 private static String ALIAS_USER_CA3_COLLISION; 67 getCa1()68 private static X509Certificate getCa1() { 69 initCerts(); 70 return CA1; 71 } getCa2()72 private static X509Certificate getCa2() { 73 initCerts(); 74 return CA2; 75 } 76 getPrivate()77 private static KeyStore.PrivateKeyEntry getPrivate() { 78 initCerts(); 79 return PRIVATE; 80 } getChain()81 private static X509Certificate[] getChain() { 82 initCerts(); 83 return CHAIN; 84 } 85 getCa3WithCa1Subject()86 private static X509Certificate getCa3WithCa1Subject() { 87 initCerts(); 88 return CA3_WITH_CA1_SUBJECT; 89 } 90 getAliasSystemCa1()91 private static String getAliasSystemCa1() { 92 initCerts(); 93 return ALIAS_SYSTEM_CA1; 94 } getAliasSystemCa2()95 private static String getAliasSystemCa2() { 96 initCerts(); 97 return ALIAS_SYSTEM_CA2; 98 } getAliasUserCa1()99 private static String getAliasUserCa1() { 100 initCerts(); 101 return ALIAS_USER_CA1; 102 } getAliasUserCa2()103 private static String getAliasUserCa2() { 104 initCerts(); 105 return ALIAS_USER_CA2; 106 } 107 getAliasSystemChain0()108 private static String getAliasSystemChain0() { 109 initCerts(); 110 return ALIAS_SYSTEM_CHAIN0; 111 } getAliasSystemChain1()112 private static String getAliasSystemChain1() { 113 initCerts(); 114 return ALIAS_SYSTEM_CHAIN1; 115 } getAliasSystemChain2()116 private static String getAliasSystemChain2() { 117 initCerts(); 118 return ALIAS_SYSTEM_CHAIN2; 119 } getAliasUserChain0()120 private static String getAliasUserChain0() { 121 initCerts(); 122 return ALIAS_USER_CHAIN0; 123 } getAliasUserChain1()124 private static String getAliasUserChain1() { 125 initCerts(); 126 return ALIAS_USER_CHAIN1; 127 } getAliasUserChain2()128 private static String getAliasUserChain2() { 129 initCerts(); 130 return ALIAS_USER_CHAIN2; 131 } 132 getAliasSystemCa3()133 private static String getAliasSystemCa3() { 134 initCerts(); 135 return ALIAS_SYSTEM_CA3; 136 } getAliasSystemCa3Collision()137 private static String getAliasSystemCa3Collision() { 138 initCerts(); 139 return ALIAS_SYSTEM_CA3_COLLISION; 140 } getAliasUserCa3()141 private static String getAliasUserCa3() { 142 initCerts(); 143 return ALIAS_USER_CA3; 144 } getAliasUserCa3Collision()145 private static String getAliasUserCa3Collision() { 146 initCerts(); 147 return ALIAS_USER_CA3_COLLISION; 148 } 149 150 /** 151 * Lazily create shared test certificates. 152 */ initCerts()153 private static synchronized void initCerts() { 154 if (CA1 != null) { 155 return; 156 } 157 try { 158 CA1 = TestKeyStore.getClient().getRootCertificate("RSA"); 159 CA2 = TestKeyStore.getClientCA2().getRootCertificate("RSA"); 160 PRIVATE = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); 161 CHAIN = (X509Certificate[]) PRIVATE.getCertificateChain(); 162 CA3_WITH_CA1_SUBJECT = new TestKeyStore.Builder() 163 .aliasPrefix("unused") 164 .subject(CA1.getSubjectX500Principal()) 165 .ca(true) 166 .build().getRootCertificate("RSA"); 167 168 169 ALIAS_SYSTEM_CA1 = alias(false, CA1, 0); 170 ALIAS_SYSTEM_CA2 = alias(false, CA2, 0); 171 ALIAS_USER_CA1 = alias(true, CA1, 0); 172 ALIAS_USER_CA2 = alias(true, CA2, 0); 173 174 ALIAS_SYSTEM_CHAIN0 = alias(false, getChain()[0], 0); 175 ALIAS_SYSTEM_CHAIN1 = alias(false, getChain()[1], 0); 176 ALIAS_SYSTEM_CHAIN2 = alias(false, getChain()[2], 0); 177 ALIAS_USER_CHAIN0 = alias(true, getChain()[0], 0); 178 ALIAS_USER_CHAIN1 = alias(true, getChain()[1], 0); 179 ALIAS_USER_CHAIN2 = alias(true, getChain()[2], 0); 180 181 ALIAS_SYSTEM_CA3 = alias(false, CA3_WITH_CA1_SUBJECT, 0); 182 ALIAS_SYSTEM_CA3_COLLISION = alias(false, CA3_WITH_CA1_SUBJECT, 1); 183 ALIAS_USER_CA3 = alias(true, CA3_WITH_CA1_SUBJECT, 0); 184 ALIAS_USER_CA3_COLLISION = alias(true, CA3_WITH_CA1_SUBJECT, 1); 185 } catch (Exception e) { 186 throw new RuntimeException(e); 187 } 188 } 189 190 private TrustedCertificateStore store; 191 setUp()192 @Override protected void setUp() { 193 setupStore(); 194 } 195 setupStore()196 private void setupStore() { 197 dirSystem.mkdirs(); 198 cleanStore(); 199 createStore(); 200 } 201 createStore()202 private void createStore() { 203 store = new TrustedCertificateStore(dirSystem, dirAdded, dirDeleted); 204 } 205 tearDown()206 @Override protected void tearDown() { 207 cleanStore(); 208 } 209 cleanStore()210 private void cleanStore() { 211 for (File dir : new File[] { dirSystem, dirAdded, dirDeleted, dirTest }) { 212 File[] files = dir.listFiles(); 213 if (files == null) { 214 continue; 215 } 216 for (File file : files) { 217 assertTrue("Should delete " + file.getPath(), file.delete()); 218 } 219 } 220 store = null; 221 } 222 resetStore()223 private void resetStore() { 224 cleanStore(); 225 setupStore(); 226 } 227 testEmptyDirectories()228 public void testEmptyDirectories() throws Exception { 229 assertEmpty(); 230 } 231 testOneSystemOneDeleted()232 public void testOneSystemOneDeleted() throws Exception { 233 install(getCa1(), getAliasSystemCa1()); 234 store.deleteCertificateEntry(getAliasSystemCa1()); 235 assertEmpty(); 236 assertDeleted(getCa1(), getAliasSystemCa1()); 237 } 238 testTwoSystemTwoDeleted()239 public void testTwoSystemTwoDeleted() throws Exception { 240 install(getCa1(), getAliasSystemCa1()); 241 store.deleteCertificateEntry(getAliasSystemCa1()); 242 install(getCa2(), getAliasSystemCa2()); 243 store.deleteCertificateEntry(getAliasSystemCa2()); 244 assertEmpty(); 245 assertDeleted(getCa1(), getAliasSystemCa1()); 246 assertDeleted(getCa2(), getAliasSystemCa2()); 247 } 248 testPartialFileIsIgnored()249 public void testPartialFileIsIgnored() throws Exception { 250 File file = file(getAliasSystemCa1()); 251 file.getParentFile().mkdirs(); 252 OutputStream os = new FileOutputStream(file); 253 os.write(0); 254 os.close(); 255 assertTrue(file.exists()); 256 assertEmpty(); 257 assertTrue(file.exists()); 258 } 259 assertEmpty()260 private void assertEmpty() throws Exception { 261 try { 262 store.getCertificate(null); 263 fail(); 264 } catch (NullPointerException expected) { 265 } 266 assertNull(store.getCertificate("")); 267 268 try { 269 store.getCreationDate(null); 270 fail(); 271 } catch (NullPointerException expected) { 272 } 273 assertNull(store.getCreationDate("")); 274 275 Set<String> s = store.aliases(); 276 assertNotNull(s); 277 assertTrue(s.isEmpty()); 278 assertAliases(); 279 280 Set<String> u = store.userAliases(); 281 assertNotNull(u); 282 assertTrue(u.isEmpty()); 283 284 try { 285 store.containsAlias(null); 286 fail(); 287 } catch (NullPointerException expected) { 288 } 289 assertFalse(store.containsAlias("")); 290 291 assertNull(store.getCertificateAlias(null)); 292 assertNull(store.getCertificateAlias(getCa1())); 293 294 try { 295 store.getTrustAnchor(null); 296 fail(); 297 } catch (NullPointerException expected) { 298 } 299 assertNull(store.getTrustAnchor(getCa1())); 300 301 try { 302 store.findIssuer(null); 303 fail(); 304 } catch (NullPointerException expected) { 305 } 306 assertNull(store.findIssuer(getCa1())); 307 308 try { 309 store.installCertificate(null); 310 fail(); 311 } catch (NullPointerException expected) { 312 } 313 314 store.deleteCertificateEntry(null); 315 store.deleteCertificateEntry(""); 316 317 String[] userFiles = dirAdded.list(); 318 assertTrue(userFiles == null || userFiles.length == 0); 319 } 320 testTwoSystem()321 public void testTwoSystem() throws Exception { 322 testTwo(getCa1(), getAliasSystemCa1(), 323 getCa2(), getAliasSystemCa2()); 324 } 325 testTwoUser()326 public void testTwoUser() throws Exception { 327 testTwo(getCa1(), getAliasUserCa1(), 328 getCa2(), getAliasUserCa2()); 329 } 330 testOneSystemOneUser()331 public void testOneSystemOneUser() throws Exception { 332 testTwo(getCa1(), getAliasSystemCa1(), 333 getCa2(), getAliasUserCa2()); 334 } 335 testTwoSystemSameSubject()336 public void testTwoSystemSameSubject() throws Exception { 337 testTwo(getCa1(), getAliasSystemCa1(), 338 getCa3WithCa1Subject(), getAliasSystemCa3Collision()); 339 } 340 testTwoUserSameSubject()341 public void testTwoUserSameSubject() throws Exception { 342 testTwo(getCa1(), getAliasUserCa1(), 343 getCa3WithCa1Subject(), getAliasUserCa3Collision()); 344 345 store.deleteCertificateEntry(getAliasUserCa1()); 346 assertDeleted(getCa1(), getAliasUserCa1()); 347 assertTombstone(getAliasUserCa1()); 348 assertRootCa(getCa3WithCa1Subject(), getAliasUserCa3Collision()); 349 assertAliases(getAliasUserCa3Collision()); 350 351 store.deleteCertificateEntry(getAliasUserCa3Collision()); 352 assertDeleted(getCa3WithCa1Subject(), getAliasUserCa3Collision()); 353 assertNoTombstone(getAliasUserCa3Collision()); 354 assertNoTombstone(getAliasUserCa1()); 355 assertEmpty(); 356 } 357 testOneSystemOneUserSameSubject()358 public void testOneSystemOneUserSameSubject() throws Exception { 359 testTwo(getCa1(), getAliasSystemCa1(), 360 getCa3WithCa1Subject(), getAliasUserCa3()); 361 testTwo(getCa1(), getAliasUserCa1(), 362 getCa3WithCa1Subject(), getAliasSystemCa3()); 363 } 364 testTwo(X509Certificate x1, String alias1, X509Certificate x2, String alias2)365 private void testTwo(X509Certificate x1, String alias1, 366 X509Certificate x2, String alias2) { 367 install(x1, alias1); 368 install(x2, alias2); 369 assertRootCa(x1, alias1); 370 assertRootCa(x2, alias2); 371 assertAliases(alias1, alias2); 372 } 373 374 testOneSystemOneUserOneDeleted()375 public void testOneSystemOneUserOneDeleted() throws Exception { 376 install(getCa1(), getAliasSystemCa1()); 377 store.installCertificate(getCa2()); 378 store.deleteCertificateEntry(getAliasSystemCa1()); 379 assertDeleted(getCa1(), getAliasSystemCa1()); 380 assertRootCa(getCa2(), getAliasUserCa2()); 381 assertAliases(getAliasUserCa2()); 382 } 383 testOneSystemOneUserOneDeletedSameSubject()384 public void testOneSystemOneUserOneDeletedSameSubject() throws Exception { 385 install(getCa1(), getAliasSystemCa1()); 386 store.installCertificate(getCa3WithCa1Subject()); 387 store.deleteCertificateEntry(getAliasSystemCa1()); 388 assertDeleted(getCa1(), getAliasSystemCa1()); 389 assertRootCa(getCa3WithCa1Subject(), getAliasUserCa3()); 390 assertAliases(getAliasUserCa3()); 391 } 392 testUserMaskingSystem()393 public void testUserMaskingSystem() throws Exception { 394 install(getCa1(), getAliasSystemCa1()); 395 install(getCa1(), getAliasUserCa1()); 396 assertMasked(getCa1(), getAliasSystemCa1()); 397 assertRootCa(getCa1(), getAliasUserCa1()); 398 assertAliases(getAliasSystemCa1(), getAliasUserCa1()); 399 } 400 testChain()401 public void testChain() throws Exception { 402 testChain(getAliasSystemChain1(), getAliasSystemChain2()); 403 testChain(getAliasSystemChain1(), getAliasUserChain2()); 404 testChain(getAliasUserChain1(), getAliasSystemCa1()); 405 testChain(getAliasUserChain1(), getAliasUserChain2()); 406 } 407 testChain(String alias1, String alias2)408 private void testChain(String alias1, String alias2) throws Exception { 409 install(getChain()[1], alias1); 410 install(getChain()[2], alias2); 411 assertIntermediateCa(getChain()[1], alias1); 412 assertRootCa(getChain()[2], alias2); 413 assertAliases(alias1, alias2); 414 assertEquals(getChain()[2], store.findIssuer(getChain()[1])); 415 assertEquals(getChain()[1], store.findIssuer(getChain()[0])); 416 417 X509Certificate[] expected = getChain(); 418 List<X509Certificate> actualList = store.getCertificateChain(expected[0]); 419 420 assertEquals("Generated CA list should be same length", expected.length, actualList.size()); 421 for (int i = 0; i < expected.length; i++) { 422 assertEquals("Chain value should be the same for position " + i, expected[i], 423 actualList.get(i)); 424 } 425 resetStore(); 426 } 427 testMissingSystemDirectory()428 public void testMissingSystemDirectory() throws Exception { 429 cleanStore(); 430 createStore(); 431 assertEmpty(); 432 } 433 testWithExistingUserDirectories()434 public void testWithExistingUserDirectories() throws Exception { 435 dirAdded.mkdirs(); 436 dirDeleted.mkdirs(); 437 install(getCa1(), getAliasSystemCa1()); 438 assertRootCa(getCa1(), getAliasSystemCa1()); 439 assertAliases(getAliasSystemCa1()); 440 } 441 testIsTrustAnchorWithReissuedgetCa()442 public void testIsTrustAnchorWithReissuedgetCa() throws Exception { 443 PublicKey publicKey = getPrivate().getCertificate().getPublicKey(); 444 PrivateKey privateKey = getPrivate().getPrivateKey(); 445 String name = "CN=CA4"; 446 X509Certificate ca1 = TestKeyStore.createCa(publicKey, privateKey, name); 447 Thread.sleep(1 * 1000); // wait to ensure CAs vary by expiration 448 X509Certificate ca2 = TestKeyStore.createCa(publicKey, privateKey, name); 449 assertFalse(ca1.equals(ca2)); 450 451 String systemAlias = alias(false, ca1, 0); 452 install(ca1, systemAlias); 453 assertRootCa(ca1, systemAlias); 454 assertEquals(ca1, store.getTrustAnchor(ca2)); 455 assertEquals(ca1, store.findIssuer(ca2)); 456 resetStore(); 457 458 String userAlias = alias(true, ca1, 0); 459 store.installCertificate(ca1); 460 assertRootCa(ca1, userAlias); 461 assertNotNull(store.getTrustAnchor(ca2)); 462 assertEquals(ca1, store.findIssuer(ca2)); 463 resetStore(); 464 } 465 testInstallEmpty()466 public void testInstallEmpty() throws Exception { 467 store.installCertificate(getCa1()); 468 assertRootCa(getCa1(), getAliasUserCa1()); 469 assertAliases(getAliasUserCa1()); 470 471 // reinstalling should not change anything 472 store.installCertificate(getCa1()); 473 assertRootCa(getCa1(), getAliasUserCa1()); 474 assertAliases(getAliasUserCa1()); 475 } 476 testInstallEmptySystemExists()477 public void testInstallEmptySystemExists() throws Exception { 478 install(getCa1(), getAliasSystemCa1()); 479 assertRootCa(getCa1(), getAliasSystemCa1()); 480 assertAliases(getAliasSystemCa1()); 481 482 // reinstalling should not affect system CA 483 store.installCertificate(getCa1()); 484 assertRootCa(getCa1(), getAliasSystemCa1()); 485 assertAliases(getAliasSystemCa1()); 486 487 } 488 testInstallEmptyDeletedSystemExists()489 public void testInstallEmptyDeletedSystemExists() throws Exception { 490 install(getCa1(), getAliasSystemCa1()); 491 store.deleteCertificateEntry(getAliasSystemCa1()); 492 assertEmpty(); 493 assertDeleted(getCa1(), getAliasSystemCa1()); 494 495 // installing should restore deleted system CA 496 store.installCertificate(getCa1()); 497 assertRootCa(getCa1(), getAliasSystemCa1()); 498 assertAliases(getAliasSystemCa1()); 499 } 500 testDeleteEmpty()501 public void testDeleteEmpty() throws Exception { 502 store.deleteCertificateEntry(getAliasSystemCa1()); 503 assertEmpty(); 504 assertDeleted(getCa1(), getAliasSystemCa1()); 505 } 506 testDeleteUser()507 public void testDeleteUser() throws Exception { 508 store.installCertificate(getCa1()); 509 assertRootCa(getCa1(), getAliasUserCa1()); 510 assertAliases(getAliasUserCa1()); 511 512 store.deleteCertificateEntry(getAliasUserCa1()); 513 assertEmpty(); 514 assertDeleted(getCa1(), getAliasUserCa1()); 515 assertNoTombstone(getAliasUserCa1()); 516 } 517 testDeleteSystem()518 public void testDeleteSystem() throws Exception { 519 install(getCa1(), getAliasSystemCa1()); 520 assertRootCa(getCa1(), getAliasSystemCa1()); 521 assertAliases(getAliasSystemCa1()); 522 523 store.deleteCertificateEntry(getAliasSystemCa1()); 524 assertEmpty(); 525 assertDeleted(getCa1(), getAliasSystemCa1()); 526 527 // deleting again should not change anything 528 store.deleteCertificateEntry(getAliasSystemCa1()); 529 assertEmpty(); 530 assertDeleted(getCa1(), getAliasSystemCa1()); 531 } 532 testIsUserAddedCertificate()533 public void testIsUserAddedCertificate() throws Exception { 534 assertFalse(store.isUserAddedCertificate(getCa1())); 535 assertFalse(store.isUserAddedCertificate(getCa2())); 536 install(getCa1(), getAliasSystemCa1()); 537 assertFalse(store.isUserAddedCertificate(getCa1())); 538 assertFalse(store.isUserAddedCertificate(getCa2())); 539 install(getCa1(), getAliasUserCa1()); 540 assertTrue(store.isUserAddedCertificate(getCa1())); 541 assertFalse(store.isUserAddedCertificate(getCa2())); 542 install(getCa2(), getAliasUserCa2()); 543 assertTrue(store.isUserAddedCertificate(getCa1())); 544 assertTrue(store.isUserAddedCertificate(getCa2())); 545 store.deleteCertificateEntry(getAliasUserCa1()); 546 assertFalse(store.isUserAddedCertificate(getCa1())); 547 assertTrue(store.isUserAddedCertificate(getCa2())); 548 store.deleteCertificateEntry(getAliasUserCa2()); 549 assertFalse(store.isUserAddedCertificate(getCa1())); 550 assertFalse(store.isUserAddedCertificate(getCa2())); 551 } 552 assertRootCa(X509Certificate x, String alias)553 private void assertRootCa(X509Certificate x, String alias) { 554 assertIntermediateCa(x, alias); 555 assertEquals(x, store.findIssuer(x)); 556 } 557 assertTrusted(X509Certificate x, String alias)558 private void assertTrusted(X509Certificate x, String alias) { 559 assertEquals(x, store.getCertificate(alias)); 560 assertEquals(file(alias).lastModified(), store.getCreationDate(alias).getTime()); 561 assertTrue(store.containsAlias(alias)); 562 assertEquals(x, store.getTrustAnchor(x)); 563 } 564 assertIntermediateCa(X509Certificate x, String alias)565 private void assertIntermediateCa(X509Certificate x, String alias) { 566 assertTrusted(x, alias); 567 assertEquals(alias, store.getCertificateAlias(x)); 568 } 569 assertMasked(X509Certificate x, String alias)570 private void assertMasked(X509Certificate x, String alias) { 571 assertTrusted(x, alias); 572 assertFalse(alias.equals(store.getCertificateAlias(x))); 573 } 574 assertDeleted(X509Certificate x, String alias)575 private void assertDeleted(X509Certificate x, String alias) { 576 assertNull(store.getCertificate(alias)); 577 assertFalse(store.containsAlias(alias)); 578 assertNull(store.getCertificateAlias(x)); 579 assertNull(store.getTrustAnchor(x)); 580 assertEquals(store.allSystemAliases().contains(alias), 581 store.getCertificate(alias, true) != null); 582 } 583 assertTombstone(String alias)584 private void assertTombstone(String alias) { 585 assertTrue(TrustedCertificateStore.isUser(alias)); 586 File file = file(alias); 587 assertTrue(file.exists()); 588 assertEquals(0, file.length()); 589 } 590 assertNoTombstone(String alias)591 private void assertNoTombstone(String alias) { 592 assertTrue(TrustedCertificateStore.isUser(alias)); 593 assertFalse(file(alias).exists()); 594 } 595 assertAliases(String... aliases)596 private void assertAliases(String... aliases) { 597 Set<String> expected = new HashSet<String>(Arrays.asList(aliases)); 598 Set<String> actual = new HashSet<String>(); 599 for (String alias : store.aliases()) { 600 boolean system = TrustedCertificateStore.isSystem(alias); 601 boolean user = TrustedCertificateStore.isUser(alias); 602 if (system || user) { 603 assertEquals(system, store.allSystemAliases().contains(alias)); 604 assertEquals(user, store.userAliases().contains(alias)); 605 actual.add(alias); 606 } else { 607 throw new AssertionError(alias); 608 } 609 } 610 assertEquals(expected, actual); 611 } 612 613 /** 614 * format a certificate alias 615 */ alias(boolean user, X509Certificate x, int index)616 private static String alias(boolean user, X509Certificate x, int index) { 617 String prefix = user ? "user:" : "system:"; 618 619 X500Principal subject = x.getSubjectX500Principal(); 620 int intHash = NativeCrypto.X509_NAME_hash_old(subject); 621 String strHash = IntegralToString.intToHexString(intHash, false, 8); 622 623 return prefix + strHash + '.' + index; 624 } 625 626 /** 627 * Install certificate under specified alias 628 */ install(X509Certificate x, String alias)629 private void install(X509Certificate x, String alias) { 630 try { 631 File file = file(alias); 632 file.getParentFile().mkdirs(); 633 OutputStream out = new FileOutputStream(file); 634 out.write(x.getEncoded()); 635 out.close(); 636 } catch (Exception e) { 637 throw new RuntimeException(e); 638 } 639 } 640 641 /** 642 * Compute file for an alias 643 */ file(String alias)644 private File file(String alias) { 645 File dir; 646 if (TrustedCertificateStore.isSystem(alias)) { 647 dir = dirSystem; 648 } else if (TrustedCertificateStore.isUser(alias)) { 649 dir = dirAdded; 650 } else { 651 throw new IllegalArgumentException(alias); 652 } 653 654 int index = alias.lastIndexOf(":"); 655 if (index == -1) { 656 throw new IllegalArgumentException(alias); 657 } 658 String filename = alias.substring(index+1); 659 660 return new File(dir, filename); 661 } 662 } 663