1 /* 2 * Copyright (C) 2012 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 libcore.java.security.cert; 18 19 import static java.nio.charset.StandardCharsets.UTF_8; 20 21 import java.io.BufferedInputStream; 22 import java.io.BufferedReader; 23 import java.io.ByteArrayInputStream; 24 import java.io.ByteArrayOutputStream; 25 import java.io.DataInputStream; 26 import java.io.IOException; 27 import java.io.InputStream; 28 import java.io.InputStreamReader; 29 import java.io.ObjectInputStream; 30 import java.io.ObjectOutputStream; 31 import java.io.PrintStream; 32 import java.math.BigInteger; 33 import java.security.KeyFactory; 34 import java.security.KeyPair; 35 import java.security.KeyPairGenerator; 36 import java.security.Principal; 37 import java.security.Provider; 38 import java.security.PublicKey; 39 import java.security.Security; 40 import java.security.SignatureException; 41 import java.security.cert.Certificate; 42 import java.security.cert.CertificateException; 43 import java.security.cert.CertificateExpiredException; 44 import java.security.cert.CertificateFactory; 45 import java.security.cert.CertificateNotYetValidException; 46 import java.security.cert.CertificateParsingException; 47 import java.security.cert.X509Certificate; 48 import java.security.spec.X509EncodedKeySpec; 49 import java.text.SimpleDateFormat; 50 import java.util.ArrayList; 51 import java.util.Arrays; 52 import java.util.Calendar; 53 import java.util.Collection; 54 import java.util.Date; 55 import java.util.HashSet; 56 import java.util.List; 57 import java.util.Locale; 58 import java.util.Set; 59 import javax.security.auth.x500.X500Principal; 60 import junit.framework.TestCase; 61 import libcore.java.security.StandardNames; 62 63 import dalvik.system.VMRuntime; 64 import sun.security.jca.Providers; 65 import tests.support.resource.Support_Resources; 66 67 public class X509CertificateTest extends TestCase { 68 69 @Override 70 protected void setUp() throws Exception { 71 super.setUp(); 72 73 mX509Providers = Security.getProviders("CertificateFactory.X509"); 74 75 // Allow access to deprecated BC algorithms in this test, so we can ensure they 76 // continue to work 77 Providers.setMaximumAllowableApiLevelForBcDeprecation( 78 VMRuntime.getRuntime().getTargetSdkVersion()); 79 } 80 81 @Override 82 public void tearDown() throws Exception { 83 Providers.setMaximumAllowableApiLevelForBcDeprecation( 84 Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION); 85 super.tearDown(); 86 } 87 88 private Provider[] mX509Providers; 89 90 private static final String CERT_RSA = "x509/cert-rsa.der"; 91 92 private static final String CERT_DSA = "x509/cert-dsa.der"; 93 94 private static final String CERT_EC = "x509/cert-ec.der"; 95 96 private static final String CERT_KEYUSAGE_EXTRALONG = "x509/cert-keyUsage-extraLong.der"; 97 98 private static final String CERT_EXTENDEDKEYUSAGE = "x509/cert-extendedKeyUsage.der"; 99 100 private final static String CERT_RSA_TBS = "x509/cert-rsa-tbs.der"; 101 102 private final static String CERT_RSA_SIGNATURE = "x509/cert-rsa-sig.der"; 103 104 private static final String CERT_USERWITHPATHLEN = "x509/cert-userWithPathLen.der"; 105 106 private static final String CERT_CA = "x509/cert-ca.der"; 107 108 private static final String CERT_CAWITHPATHLEN = "x509/cert-caWithPathLen.der"; 109 110 private static final String CERT_INVALIDIP = "x509/cert-invalidip.der"; 111 112 private static final String CERT_IPV6 = "x509/cert-ipv6.der"; 113 114 private static final String CERT_ALT_OTHER = "x509/cert-alt-other.der"; 115 116 private static final String CERT_ALT_EMAIL = "x509/cert-alt-email.der"; 117 118 private static final String CERT_ALT_DNS = "x509/cert-alt-dns.der"; 119 120 private static final String CERT_ALT_DIRNAME = "x509/cert-alt-dirname.der"; 121 122 private static final String CERT_ALT_URI = "x509/cert-alt-uri.der"; 123 124 private static final String CERT_ALT_RID = "x509/cert-alt-rid.der"; 125 126 private static final String CERT_ALT_NONE = "x509/cert-alt-none.der"; 127 128 private static final String CERT_UNSUPPORTED = "x509/cert-unsupported.der"; 129 130 private static final String CERT_SIGOPT = "x509/cert-sigopt.der"; 131 132 private static final String CERTS_X509_PEM = "x509/certs.pem"; 133 134 private static final String CERTS_X509_DER = "x509/certs.der"; 135 136 private static final String CERTS_PKCS7_PEM = "x509/certs-pk7.pem"; 137 138 private static final String CERTS_PKCS7_DER = "x509/certs-pk7.der"; 139 140 /** A list of certs that are all slightly different. */ 141 private static final String[] VARIOUS_CERTS = new String[] { 142 CERT_RSA, CERT_DSA, CERT_EC, 143 }; 144 145 private final X509Certificate getCertificate(CertificateFactory f, String name) 146 throws Exception { 147 final InputStream is = Support_Resources.getStream(name); 148 assertNotNull("File does not exist: " + name, is); 149 try { 150 return (X509Certificate) f.generateCertificate(is); 151 } finally { 152 try { 153 is.close(); 154 } catch (IOException ignored) { 155 } 156 } 157 } 158 159 private final Collection<? extends X509Certificate> getCertificates(CertificateFactory f, String name) 160 throws Exception { 161 final InputStream is = Support_Resources.getStream(name); 162 assertNotNull("File does not exist: " + name, is); 163 try { 164 return (Collection<? extends X509Certificate>) f.generateCertificates(is); 165 } finally { 166 try { 167 is.close(); 168 } catch (IOException ignored) { 169 } 170 } 171 } 172 173 private PublicKey getRsaCertificatePublicKey() throws Exception { 174 final InputStream ris = Support_Resources.getStream("x509/cert-rsa-pubkey.der"); 175 try { 176 final int size = ris.available(); 177 final DataInputStream is = new DataInputStream(ris); 178 final byte[] keyBytes = new byte[size]; 179 is.readFully(keyBytes); 180 181 final KeyFactory kf = KeyFactory.getInstance("RSA"); 182 return kf.generatePublic(new X509EncodedKeySpec(keyBytes)); 183 } finally { 184 try { 185 ris.close(); 186 } catch (IOException ignored) { 187 } 188 } 189 } 190 191 private Date[] getRsaCertificateDates() throws Exception { 192 final InputStream ris = Support_Resources.getStream("x509/cert-rsa-dates.txt"); 193 try { 194 // notBefore=Dec 26 00:19:14 2012 GMT 195 final SimpleDateFormat sdf = 196 new SimpleDateFormat("MMM dd HH:mm:ss yyyy zzz", Locale.US); 197 198 final BufferedReader buf = new BufferedReader(new InputStreamReader(ris, UTF_8)); 199 String line = buf.readLine(); 200 int index = line.indexOf('='); 201 assertEquals("notBefore", line.substring(0, index)); 202 final Date startDate = sdf.parse(line.substring(index + 1)); 203 204 line = buf.readLine(); 205 index = line.indexOf('='); 206 assertEquals("notAfter", line.substring(0, index)); 207 final Date endDate = sdf.parse(line.substring(index + 1)); 208 209 assertTrue(startDate.before(endDate)); 210 assertTrue(endDate.after(startDate)); 211 212 return new Date[] { startDate, endDate }; 213 } finally { 214 try { 215 ris.close(); 216 } catch (IOException ignored) { 217 } 218 } 219 } 220 221 private BigInteger getRsaCertificateSerial() throws Exception { 222 final InputStream ris = Support_Resources.getStream("x509/cert-rsa-serial.txt"); 223 try { 224 final BufferedReader buf = new BufferedReader(new InputStreamReader(ris, UTF_8)); 225 226 String line = buf.readLine(); 227 int index = line.indexOf('='); 228 assertEquals("serial", line.substring(0, index)); 229 230 return new BigInteger(line.substring(index + 1), 16); 231 } finally { 232 try { 233 ris.close(); 234 } catch (IOException ignored) { 235 } 236 } 237 } 238 239 private byte[] getResourceAsBytes(String name) throws Exception { 240 final InputStream ris = Support_Resources.getStream(name); 241 try { 242 DataInputStream dis = new DataInputStream(ris); 243 byte[] buf = new byte[ris.available()]; 244 dis.readFully(buf); 245 return buf; 246 } finally { 247 try { 248 ris.close(); 249 } catch (IOException ignored) { 250 } 251 } 252 } 253 254 private byte[] getRsaCertificateSignature() throws Exception { 255 return getResourceAsBytes(CERT_RSA_SIGNATURE); 256 } 257 258 private byte[] getRsaCertificateTbs() throws Exception { 259 return getResourceAsBytes(CERT_RSA_TBS); 260 } 261 262 public void test_Provider() throws Exception { 263 final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream(); 264 PrintStream out = new PrintStream(errBuffer); 265 266 for (Provider p : mX509Providers) { 267 try { 268 CertificateFactory f = CertificateFactory.getInstance("X.509", p); 269 getPublicKey(f); 270 getType(f); 271 check_equals(f); 272 check_toString(f); 273 check_hashCode(f); 274 checkValidity(f); 275 getVersion(f); 276 getSerialNumber(f); 277 getIssuerDN(f); 278 getIssuerX500Principal(f); 279 getSubjectDN(f); 280 getSubjectUniqueID(f); 281 getSubjectX500Principal(f); 282 getNotBeforeAndNotAfterDates(f); 283 getSigAlgName(f); 284 getSigAlgOID(f); 285 getSigAlgParams(f); 286 getIssuerUniqueID(f); 287 getSubjectUniqueID(f); 288 getKeyUsage(f); 289 getExtendedKeyUsage(f); 290 getBasicConstraints(f); 291 getSubjectAlternativeNames(f); 292 getSubjectAlternativeNames_IPV6(f); 293 getSubjectAlternativeNames_InvalidIP(f); 294 getSubjectAlternativeNames_Other(f); 295 getSubjectAlternativeNames_Email(f); 296 getSubjectAlternativeNames_DNS(f); 297 getSubjectAlternativeNames_DirName(f); 298 getSubjectAlternativeNames_URI(f); 299 getSubjectAlternativeNames_RID(f); 300 getSubjectAlternativeNames_None(f); 301 getIssuerAlternativeNames(f); 302 getTBSCertificate(f); 303 getSignature(f); 304 hasUnsupportedCriticalExtension(f); 305 getEncoded(f); 306 verify(f); 307 generateCertificate_PEM_TrailingData(f); 308 generateCertificate_DER_TrailingData(f); 309 generateCertificates_X509_PEM(f); 310 generateCertificates_X509_DER(f); 311 generateCertificates_PKCS7_PEM(f); 312 generateCertificates_PKCS7_DER(f); 313 generateCertificates_Empty(f); 314 generateCertificates_X509_PEM_TrailingData(f); 315 generateCertificates_X509_DER_TrailingData(f); 316 generateCertificates_PKCS7_PEM_TrailingData(f); 317 generateCertificates_PKCS7_DER_TrailingData(f); 318 test_Serialization(f); 319 test_UnknownUnmappedKeyOID(f); 320 } catch (Throwable e) { 321 out.append("Error encountered checking " + p.getName() + "\n"); 322 e.printStackTrace(out); 323 } 324 } 325 326 out.flush(); 327 if (errBuffer.size() > 0) { 328 throw new Exception("Errors encountered:\n\n" + errBuffer.toString() + "\n\n"); 329 } 330 } 331 332 private void getPublicKey(CertificateFactory f) throws Exception { 333 X509Certificate c = getCertificate(f, CERT_RSA); 334 PublicKey expected = getRsaCertificatePublicKey(); 335 336 PublicKey actual = c.getPublicKey(); 337 assertEquals(expected, actual); 338 assertEquals(Arrays.toString(expected.getEncoded()), 339 Arrays.toString(actual.getEncoded())); 340 } 341 342 private void getType(CertificateFactory f) throws Exception { 343 X509Certificate c = getCertificate(f, CERT_RSA); 344 assertEquals("X.509", c.getType()); 345 } 346 347 private void verify(CertificateFactory f) throws Exception { 348 X509Certificate c = getCertificate(f, CERT_RSA); 349 PublicKey signer = getRsaCertificatePublicKey(); 350 351 c.verify(signer); 352 353 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 354 KeyPair pair = kpg.generateKeyPair(); 355 PublicKey invalidKey = pair.getPublic(); 356 357 try { 358 c.verify(invalidKey); 359 fail("RSA signature should not verify"); 360 } catch (SignatureException expected) { 361 } 362 363 Provider[] providers = Security.getProviders("Signature." + c.getSigAlgName()); 364 for (Provider p : providers) { 365 // Do not test AndroidKeyStore Provider. It does not accept vanilla public keys for 366 // signature verification. It's OKish not to test here because it's tested by 367 // cts/tests/tests/keystore. 368 if (p.getName().startsWith("AndroidKeyStore")) { 369 continue; 370 } 371 372 c.verify(signer, p.getName()); 373 374 try { 375 c.verify(invalidKey, p.getName()); 376 fail("RSA signature should not verify"); 377 } catch (SignatureException expected) { 378 } 379 } 380 } 381 382 private void check_equals(CertificateFactory f) throws Exception { 383 X509Certificate c1 = getCertificate(f, CERT_RSA); 384 X509Certificate c2 = getCertificate(f, CERT_RSA); 385 386 assertEquals(c1, c2); 387 388 X509Certificate c3 = getCertificate(f, CERT_DSA); 389 assertFalse(c1.equals(c3)); 390 assertFalse(c3.equals(c1)); 391 } 392 393 private void check_toString(CertificateFactory f) throws Exception { 394 X509Certificate c1 = getCertificate(f, CERT_RSA); 395 396 String output1 = c1.toString(); 397 assertNotNull(output1); 398 assertTrue(output1.length() > 0); 399 400 X509Certificate c2 = getCertificate(f, CERT_RSA); 401 assertEquals(c1.toString(), c2.toString()); 402 403 X509Certificate c3 = getCertificate(f, CERT_DSA); 404 assertFalse(c3.toString().equals(c1.toString())); 405 } 406 407 private void check_hashCode(CertificateFactory f) throws Exception { 408 X509Certificate c1 = getCertificate(f, CERT_RSA); 409 X509Certificate c2 = getCertificate(f, CERT_RSA); 410 411 assertEquals(c1.hashCode(), c2.hashCode()); 412 413 X509Certificate c3 = getCertificate(f, CERT_DSA); 414 assertFalse(c3.hashCode() == c1.hashCode()); 415 } 416 417 private void checkValidity(CertificateFactory f) throws Exception { 418 X509Certificate c = getCertificate(f, CERT_RSA); 419 Calendar cal = Calendar.getInstance(); 420 Date[] dates = getRsaCertificateDates(); 421 422 /* 423 * The certificate validity periods in the test certificate MUST lie 424 * within the tested period. The API doesn't appear to allow any other 425 * way to test this code path as an unprivileged user. 426 */ 427 Date now = new Date(); 428 assertTrue(now.after(dates[0])); 429 assertTrue(now.before(dates[1])); 430 431 /* This assumes the script makes a long-lived cert. */ 432 c.checkValidity(); 433 434 /* A day after the start date. */ 435 cal.setTime(dates[0]); 436 cal.add(Calendar.DAY_OF_MONTH, 1); 437 c.checkValidity(cal.getTime()); 438 439 /* A second before the start date. */ 440 cal.setTime(dates[1]); 441 cal.add(Calendar.SECOND, -1); 442 c.checkValidity(cal.getTime()); 443 444 try { 445 cal.setTime(dates[0]); 446 cal.add(Calendar.SECOND, -1); 447 c.checkValidity(cal.getTime()); 448 fail(); 449 } catch (CertificateNotYetValidException expected) { 450 } 451 452 try { 453 cal.setTime(dates[0]); 454 cal.add(Calendar.MONTH, -6); 455 c.checkValidity(cal.getTime()); 456 fail(); 457 } catch (CertificateNotYetValidException expected) { 458 } 459 460 try { 461 cal.setTime(dates[1]); 462 cal.add(Calendar.SECOND, 1); 463 c.checkValidity(cal.getTime()); 464 fail(); 465 } catch (CertificateExpiredException expected) { 466 } 467 468 try { 469 cal.setTime(dates[1]); 470 cal.add(Calendar.YEAR, 1); 471 c.checkValidity(cal.getTime()); 472 fail(); 473 } catch (CertificateExpiredException expected) { 474 } 475 } 476 477 private void getVersion(CertificateFactory f) throws Exception { 478 X509Certificate c = getCertificate(f, CERT_RSA); 479 assertEquals(3, c.getVersion()); 480 } 481 482 private void getSerialNumber(CertificateFactory f) throws Exception { 483 X509Certificate c = getCertificate(f, CERT_RSA); 484 BigInteger actual = getRsaCertificateSerial(); 485 486 assertEquals(actual, c.getSerialNumber()); 487 } 488 489 private void getIssuerDN(CertificateFactory f) throws Exception { 490 X509Certificate c = getCertificate(f, CERT_RSA); 491 492 Principal princ = c.getIssuerDN(); 493 if (StandardNames.IS_RI) { 494 assertEquals("OU=NetOps, O=Genius.com Inc, L=San Mateo, ST=California, C=US", 495 princ.getName()); 496 } else { 497 if ("BC".equals(f.getProvider().getName())) { 498 // TODO: is it acceptable to have this in reverse order? 499 assertEquals(f.getProvider().getName(), 500 "C=US,ST=California,L=San Mateo,O=Genius.com Inc,OU=NetOps", 501 princ.getName()); 502 } else { 503 assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", 504 princ.getName()); 505 } 506 } 507 508 X509Certificate c2 = getCertificate(f, CERT_RSA); 509 assertEquals(princ, c2.getIssuerDN()); 510 } 511 512 private void getIssuerX500Principal(CertificateFactory f) throws Exception { 513 X509Certificate c = getCertificate(f, CERT_RSA); 514 515 final byte[] expected = new byte[] { 516 0x30, 0x60, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 517 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 518 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 519 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x53, 520 0x61, 0x6e, 0x20, 0x4d, 0x61, 0x74, 0x65, 0x6f, 0x31, 0x17, 0x30, 0x15, 521 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x47, 0x65, 0x6e, 0x69, 0x75, 522 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x0f, 0x30, 523 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x06, 0x4e, 0x65, 0x74, 0x4f, 524 0x70, 0x73 525 }; 526 X500Principal princ = c.getIssuerX500Principal(); 527 assertEquals(Arrays.toString(expected), 528 Arrays.toString(princ.getEncoded())); 529 assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", 530 princ.getName()); 531 assertEquals("ou=netops,o=genius.com inc,l=san mateo,st=california,c=us", 532 princ.getName(X500Principal.CANONICAL)); 533 assertEquals("OU=NetOps, O=Genius.com Inc, L=San Mateo, ST=California, C=US", 534 princ.getName(X500Principal.RFC1779)); 535 assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", 536 princ.getName(X500Principal.RFC2253)); 537 538 X509Certificate c2 = getCertificate(f, CERT_RSA); 539 assertEquals(princ, c2.getIssuerX500Principal()); 540 } 541 542 private void getSubjectDN(CertificateFactory f) throws Exception { 543 X509Certificate c = getCertificate(f, CERT_RSA); 544 545 Principal princ = c.getSubjectDN(); 546 if (StandardNames.IS_RI) { 547 assertEquals("OU=NetOps, O=Genius.com Inc, L=San Mateo, ST=California, C=US", 548 princ.getName()); 549 } else { 550 if ("BC".equals(f.getProvider().getName())) { 551 // TODO: is it acceptable to have this in reverse order? 552 assertEquals(f.getProvider().getName(), 553 "C=US,ST=California,L=San Mateo,O=Genius.com Inc,OU=NetOps", 554 princ.getName()); 555 } else { 556 assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", 557 princ.getName()); 558 } 559 } 560 561 X509Certificate c2 = getCertificate(f, CERT_RSA); 562 assertEquals(princ, c2.getSubjectDN()); 563 } 564 565 private void getSubjectUniqueID(CertificateFactory f) throws Exception { 566 /* This certificate has no unique ID. */ 567 X509Certificate c = getCertificate(f, CERT_RSA); 568 assertNull(c.getSubjectUniqueID()); 569 570 // TODO: generate certificate that has a SubjectUniqueID field. 571 } 572 573 private void getIssuerUniqueID(CertificateFactory f) throws Exception { 574 /* This certificate has no unique ID. */ 575 X509Certificate c = getCertificate(f, CERT_RSA); 576 assertNull(c.getIssuerUniqueID()); 577 578 // TODO: generate certificate that has a IssuerUniqueID field. 579 } 580 581 private void getSubjectX500Principal(CertificateFactory f) throws Exception { 582 X509Certificate c = getCertificate(f, CERT_RSA); 583 584 final byte[] expected = new byte[] { 585 0x30, 0x60, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 586 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 587 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 588 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x53, 589 0x61, 0x6e, 0x20, 0x4d, 0x61, 0x74, 0x65, 0x6f, 0x31, 0x17, 0x30, 0x15, 590 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x47, 0x65, 0x6e, 0x69, 0x75, 591 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x0f, 0x30, 592 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x06, 0x4e, 0x65, 0x74, 0x4f, 593 0x70, 0x73 594 }; 595 X500Principal princ = c.getSubjectX500Principal(); 596 assertEquals(Arrays.toString(expected), 597 Arrays.toString(princ.getEncoded())); 598 assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", 599 princ.getName()); 600 assertEquals("ou=netops,o=genius.com inc,l=san mateo,st=california,c=us", 601 princ.getName(X500Principal.CANONICAL)); 602 assertEquals("OU=NetOps, O=Genius.com Inc, L=San Mateo, ST=California, C=US", 603 princ.getName(X500Principal.RFC1779)); 604 assertEquals("OU=NetOps,O=Genius.com Inc,L=San Mateo,ST=California,C=US", 605 princ.getName(X500Principal.RFC2253)); 606 607 X509Certificate c2 = getCertificate(f, CERT_RSA); 608 assertEquals(princ, c2.getSubjectX500Principal()); 609 } 610 611 private static void assertDateEquals(Date date1, Date date2) throws Exception { 612 SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss"); 613 614 String result1 = formatter.format(date1); 615 String result2 = formatter.format(date2); 616 617 assertEquals(result1, result2); 618 } 619 620 private void getNotBeforeAndNotAfterDates(CertificateFactory f) throws Exception { 621 X509Certificate c = getCertificate(f, CERT_RSA); 622 Date[] dates = getRsaCertificateDates(); 623 624 assertDateEquals(dates[0], c.getNotBefore()); 625 assertDateEquals(dates[1], c.getNotAfter()); 626 } 627 628 private void getSigAlgName(CertificateFactory f) throws Exception { 629 { 630 /* The test certificate is sha1WithRSAEncryption */ 631 X509Certificate c = getCertificate(f, CERT_RSA); 632 assertEquals("SHA1WITHRSA", c.getSigAlgName().toUpperCase(Locale.US)); 633 } 634 635 { 636 /* The test certificate is sha1WithRSAEncryption */ 637 X509Certificate c = getCertificate(f, CERT_DSA); 638 assertEquals("SHA1WITHDSA", c.getSigAlgName().toUpperCase(Locale.US)); 639 } 640 641 { 642 /* The test certificate is sha1WithRSAEncryption */ 643 X509Certificate c = getCertificate(f, CERT_EC); 644 assertEquals("SHA1WITHECDSA", c.getSigAlgName().toUpperCase(Locale.US)); 645 } 646 } 647 648 private void getSigAlgOID(CertificateFactory f) throws Exception { 649 { 650 /* The test certificate is sha1WithRSAEncryption */ 651 X509Certificate c = getCertificate(f, CERT_RSA); 652 assertEquals("1.2.840.113549.1.1.5", c.getSigAlgOID()); 653 } 654 655 { 656 /* The test certificate is sha1WithRSAEncryption */ 657 X509Certificate c = getCertificate(f, CERT_DSA); 658 assertEquals("1.2.840.10040.4.3", c.getSigAlgOID()); 659 } 660 661 { 662 /* The test certificate is sha1WithRSAEncryption */ 663 X509Certificate c = getCertificate(f, CERT_EC); 664 assertEquals("1.2.840.10045.4.1", c.getSigAlgOID()); 665 } 666 } 667 668 private void getSigAlgParams(CertificateFactory f) throws Exception { 669 { 670 X509Certificate c = getCertificate(f, CERT_RSA); 671 // RI appears to disagree 672 if (StandardNames.IS_RI) { 673 assertNull(f.getProvider().getName(), c.getSigAlgParams()); 674 } else { 675 assertNotNull(f.getProvider().getName(), c.getSigAlgParams()); 676 } 677 } 678 679 { 680 X509Certificate c = getCertificate(f, CERT_DSA); 681 assertNull(f.getProvider().getName(), c.getSigAlgParams()); 682 } 683 684 { 685 X509Certificate c = getCertificate(f, CERT_EC); 686 assertNull(f.getProvider().getName(), c.getSigAlgParams()); 687 } 688 689 { 690 X509Certificate c = getCertificate(f, CERT_SIGOPT); 691 692 /* SEQUENCE, INTEGER 1 */ 693 final byte[] expected = new byte[] { 694 /* SEQUENCE, constructed, len=5 */ 695 (byte) 0x30, (byte) 0x05, 696 /* Type=2, constructed, context-specific, len=3 */ 697 (byte) 0xA2, (byte) 0x03, 698 /* INTEGER, len=1, value=1 */ 699 (byte) 0x02, (byte) 0x01, (byte) 0x01, 700 }; 701 702 final byte[] params = c.getSigAlgParams(); 703 assertNotNull(f.getProvider().getName(), params); 704 assertEquals(Arrays.toString(expected), Arrays.toString(params)); 705 } 706 } 707 708 private void getKeyUsage(CertificateFactory f) throws Exception { 709 { 710 /* The test certificate is sha1WithRSAEncryption */ 711 X509Certificate c = getCertificate(f, CERT_RSA); 712 boolean[] expected = new boolean[] { 713 true, /* digitalSignature (0) */ 714 true, /* nonRepudiation (1) */ 715 true, /* keyEncipherment (2) */ 716 false, /* dataEncipherment (3) */ 717 false, /* keyAgreement (4) */ 718 false, /* keyCertSign (5) */ 719 false, /* cRLSign (6) */ 720 false, /* encipherOnly (7) */ 721 false, /* decipherOnly (8) */ 722 }; 723 assertEquals(Arrays.toString(expected), Arrays.toString(c.getKeyUsage())); 724 } 725 726 { 727 /* The test certificate is sha1WithRSAEncryption */ 728 X509Certificate c = getCertificate(f, CERT_DSA); 729 boolean[] expected = new boolean[] { 730 false, /* digitalSignature (0) */ 731 false, /* nonRepudiation (1) */ 732 true, /* keyEncipherment (2) */ 733 true, /* dataEncipherment (3) */ 734 false, /* keyAgreement (4) */ 735 true, /* keyCertSign (5) */ 736 true, /* cRLSign (6) */ 737 true, /* encipherOnly (7) */ 738 false, /* decipherOnly (8) */ 739 }; 740 boolean[] actual = c.getKeyUsage(); 741 assertEquals(9, actual.length); 742 assertEquals(Arrays.toString(expected), Arrays.toString(actual)); 743 } 744 745 { 746 /* The test certificate is sha1WithRSAEncryption */ 747 X509Certificate c = getCertificate(f, CERT_EC); 748 boolean[] expected = new boolean[] { 749 false, /* digitalSignature (0) */ 750 false, /* nonRepudiation (1) */ 751 false, /* keyEncipherment (2) */ 752 false, /* dataEncipherment (3) */ 753 true, /* keyAgreement (4) */ 754 false, /* keyCertSign (5) */ 755 false, /* cRLSign (6) */ 756 false, /* encipherOnly (7) */ 757 true, /* decipherOnly (8) */ 758 }; 759 boolean[] actual = c.getKeyUsage(); 760 assertEquals(9, actual.length); 761 assertEquals(Arrays.toString(expected), Arrays.toString(actual)); 762 } 763 764 { 765 /* All the bits are set in addition to some extra ones. */ 766 X509Certificate c = getCertificate(f, CERT_KEYUSAGE_EXTRALONG); 767 boolean[] expected = new boolean[] { 768 true, /* digitalSignature (0) */ 769 true, /* nonRepudiation (1) */ 770 true, /* keyEncipherment (2) */ 771 true, /* dataEncipherment (3) */ 772 true, /* keyAgreement (4) */ 773 true, /* keyCertSign (5) */ 774 true, /* cRLSign (6) */ 775 true, /* encipherOnly (7) */ 776 true, /* decipherOnly (8) */ 777 true, /* ????? (9) */ 778 true, /* ????? (10) */ 779 }; 780 boolean[] actual = c.getKeyUsage(); 781 assertEquals(11, actual.length); 782 assertEquals(Arrays.toString(expected), Arrays.toString(actual)); 783 } 784 } 785 786 private void getExtendedKeyUsage(CertificateFactory f) throws Exception { 787 { 788 /* No ExtendedKeyUsage section */ 789 final X509Certificate c = getCertificate(f, CERT_RSA); 790 List<String> actual = c.getExtendedKeyUsage(); 791 assertNull(actual); 792 } 793 794 { 795 /* ExtendedKeyUsage section with one entry of OID 1.2.3.4 */ 796 final X509Certificate c = getCertificate(f, CERT_EXTENDEDKEYUSAGE); 797 List<String> actual = c.getExtendedKeyUsage(); 798 assertNotNull(actual); 799 assertEquals(1, actual.size()); 800 assertEquals("1.2.3.4", actual.get(0)); 801 } 802 } 803 804 private void getBasicConstraints(CertificateFactory f) throws Exception { 805 /* Non-CA cert with no pathLenConstraint */ 806 { 807 final X509Certificate c = getCertificate(f, CERT_RSA); 808 assertEquals(f.getProvider().getName(), -1, c.getBasicConstraints()); 809 } 810 811 /* Non-CA cert with pathLenConstraint */ 812 { 813 final X509Certificate c = getCertificate(f, CERT_USERWITHPATHLEN); 814 assertEquals(f.getProvider().getName(), -1, c.getBasicConstraints()); 815 } 816 817 /* CA cert with no pathLenConstraint */ 818 { 819 final X509Certificate c = getCertificate(f, CERT_CA); 820 assertEquals(f.getProvider().getName(), Integer.MAX_VALUE, c.getBasicConstraints()); 821 } 822 823 /* CA cert with pathLenConstraint=10 */ 824 { 825 final X509Certificate c = getCertificate(f, CERT_CAWITHPATHLEN); 826 assertEquals(f.getProvider().getName(), 10, c.getBasicConstraints()); 827 } 828 } 829 830 /** Encoding of: OID:1.2.3.4, UTF8:test1 */ 831 private static byte[] getOIDTestBytes() { 832 if (StandardNames.IS_RI) { 833 return new byte[] { 0x30, 0x10, 0x06, 0x03, 0x2a, 0x03, 0x04, (byte) 0xa0, 834 0x09, (byte) 0xa0, 0x07, 0x0c, 0x05, 0x74, 0x65, 0x73, 0x74, 0x31 }; 835 } else { 836 return new byte[] { (byte) 0xa0, 0x0e, 0x06, 0x03, 0x2a, 0x03, 0x04, 837 (byte) 0xa0, 0x07, 0x0c, 0x05, 0x74, 0x65, 0x73, 0x74, 0x31 }; 838 } 839 } 840 841 private void getSubjectAlternativeNames(CertificateFactory f) throws Exception { 842 X509Certificate c = getCertificate(f, CERT_RSA); 843 Collection<List<?>> col = c.getSubjectAlternativeNames(); 844 845 checkAlternativeNames(f, col); 846 } 847 848 private void checkAlternativeNames(CertificateFactory f, Collection<List<?>> col) throws Exception { 849 assertNotNull(col); 850 851 /* Check to see that the Collection is unmodifiable. */ 852 { 853 try { 854 col.add(new ArrayList<Object>()); 855 fail("should be an unmodifiable list"); 856 } catch (UnsupportedOperationException expected) { 857 } 858 } 859 860 /* 861 * There should be 9 types of alternative names in this test 862 * certificate. 863 */ 864 boolean[] typesFound = new boolean[9]; 865 866 for (List<?> item : col) { 867 /* Check to see that the List is unmodifiable. */ 868 { 869 try { 870 item.remove(0); 871 fail("should be an unmodifiable list"); 872 } catch (UnsupportedOperationException expected) { 873 } 874 } 875 876 assertTrue(item.get(0) instanceof Integer); 877 int type = (Integer) item.get(0); 878 typesFound[type] = true; 879 880 switch (type) { 881 case 0: /* OtherName */ 882 final byte[] der = getOIDTestBytes(); 883 assertEquals(Arrays.toString(der), Arrays.toString((byte[]) item.get(1))); 884 break; 885 case 1: /* rfc822Name: IA5String */ 886 assertEquals("x509 (at) example.com", (String) item.get(1)); 887 break; 888 case 2: /* dNSName: IA5String */ 889 assertEquals("x509.example.com", (String) item.get(1)); 890 break; 891 case 3: /* x400Address: ORAddress */ 892 assertEquals("UNSUPPORTED", (String) item.get(1)); 893 break; 894 case 4: /* directoryName: Name */ 895 if ("BC".equals(f.getProvider().getName())) { 896 // Bouncycastle doesn't parse T61String as UTF-8 like the RI, libcore, or OpenSSL. 897 byte[] bytes = "CN=,OU=ber Frends,O=Awesome Dudes,C=US".getBytes("UTF-8"); 898 String string = new String(bytes, 0); 899 assertEquals(string, (String) item.get(1)); 900 } else { 901 assertEquals("CN=,OU=ber Frends,O=Awesome Dudes,C=US", (String) item.get(1)); 902 } 903 break; 904 case 5: /* ediPartyName */ 905 assertEquals("UNSUPPORTED", Arrays.toString((byte[]) item.get(1))); 906 break; 907 case 6: /* uniformResourceIdentifier: IA5String */ 908 assertEquals("http://www.example.com/?q=awesomeness", (String) item.get(1)); 909 break; 910 case 7: /* iPAddress */ 911 assertEquals("192.168.0.1", (String) item.get(1)); 912 break; 913 case 8: 914 assertEquals("1.2.3.4", (String) item.get(1)); 915 break; 916 } 917 } 918 919 Set<Integer> missing = new HashSet<Integer>(); 920 for (int i = 0; i < typesFound.length; i++) { 921 if (!typesFound[i]) { 922 missing.add(i); 923 } 924 } 925 926 // TODO: fix X.400 names and ediPartyName 927 missing.remove(3); 928 missing.remove(5); 929 930 if (!missing.isEmpty()) { 931 fail("Missing types: " + Arrays.toString(missing.toArray(new Integer[missing.size()]))); 932 } 933 } 934 935 private void getSubjectAlternativeNames_IPV6(CertificateFactory f) throws Exception { 936 X509Certificate c = getCertificate(f, CERT_IPV6); 937 Collection<List<?>> col = c.getSubjectAlternativeNames(); 938 939 assertNotNull(f.getProvider().getName(), col); 940 941 assertEquals(1, col.size()); 942 List<?> item = col.iterator().next(); 943 944 assertTrue(item.get(0) instanceof Integer); 945 assertTrue(7 == (Integer) item.get(0)); 946 947 assertTrue(item.get(1) instanceof String); 948 // RI doesn't apply all the IPv6 shortening rules 949 if (StandardNames.IS_RI) { 950 assertEquals("2001:db8:0:0:0:ff00:42:8329", (String) item.get(1)); 951 } else { 952 assertEquals("2001:db8::ff00:42:8329", (String) item.get(1)); 953 } 954 } 955 956 private void getSubjectAlternativeNames_InvalidIP(CertificateFactory f) throws Exception { 957 X509Certificate c = getCertificate(f, CERT_INVALIDIP); 958 Collection<List<?>> col = c.getSubjectAlternativeNames(); 959 assertNull(col); 960 } 961 962 private void getSubjectAlternativeNames_Other(CertificateFactory f) throws Exception { 963 X509Certificate c = getCertificate(f, CERT_ALT_OTHER); 964 Collection<List<?>> col = c.getSubjectAlternativeNames(); 965 966 assertNotNull(f.getProvider().getName(), col); 967 968 assertEquals(1, col.size()); 969 List<?> item = col.iterator().next(); 970 971 assertTrue(item.get(0) instanceof Integer); 972 assertTrue(0 == (Integer) item.get(0)); 973 974 /* OID:1.2.3.4, UTF8:test1 */ 975 final byte[] der = getOIDTestBytes(); 976 final byte[] actual = (byte[]) item.get(1); 977 assertEquals(Arrays.toString(der), Arrays.toString(actual)); 978 979 /* Make sure the byte[] array isn't modified by our test. */ 980 { 981 actual[0] ^= (byte) 0xFF; 982 byte[] actual2 = (byte[]) c.getSubjectAlternativeNames().iterator().next().get(1); 983 984 if (!StandardNames.IS_RI) { 985 assertEquals(Arrays.toString(der), Arrays.toString(actual2)); 986 } else { 987 /* RI is broken here. */ 988 assertEquals(Arrays.toString(actual), Arrays.toString(actual2)); 989 } 990 } 991 } 992 993 private void getSubjectAlternativeNames_Email(CertificateFactory f) throws Exception { 994 X509Certificate c = getCertificate(f, CERT_ALT_EMAIL); 995 Collection<List<?>> col = c.getSubjectAlternativeNames(); 996 997 assertNotNull(f.getProvider().getName(), col); 998 999 assertEquals(1, col.size()); 1000 List<?> item = col.iterator().next(); 1001 1002 assertTrue(item.get(0) instanceof Integer); 1003 assertTrue(1 == (Integer) item.get(0)); 1004 1005 assertTrue(item.get(1) instanceof String); 1006 assertEquals("x509 (at) example.com", (String) item.get(1)); 1007 } 1008 1009 private void getSubjectAlternativeNames_DNS(CertificateFactory f) throws Exception { 1010 X509Certificate c = getCertificate(f, CERT_ALT_DNS); 1011 Collection<List<?>> col = c.getSubjectAlternativeNames(); 1012 1013 assertNotNull(f.getProvider().getName(), col); 1014 1015 assertEquals(1, col.size()); 1016 List<?> item = col.iterator().next(); 1017 1018 assertTrue(item.get(0) instanceof Integer); 1019 assertTrue(2 == (Integer) item.get(0)); 1020 1021 assertTrue(item.get(1) instanceof String); 1022 assertEquals("x509.example.com", (String) item.get(1)); 1023 } 1024 1025 private void getSubjectAlternativeNames_DirName(CertificateFactory f) throws Exception { 1026 X509Certificate c = getCertificate(f, CERT_ALT_DIRNAME); 1027 Collection<List<?>> col = c.getSubjectAlternativeNames(); 1028 1029 assertNotNull(f.getProvider().getName(), col); 1030 1031 assertEquals(1, col.size()); 1032 List<?> item = col.iterator().next(); 1033 1034 assertTrue(item.get(0) instanceof Integer); 1035 assertTrue(String.valueOf((Integer) item.get(0)), 4 == (Integer) item.get(0)); 1036 1037 assertTrue(item.get(1) instanceof String); 1038 if ("BC".equals(f.getProvider().getName())) { 1039 // Bouncycastle doesn't parse T61String as UTF-8 like the RI, libcore, or OpenSSL. 1040 byte[] bytes = "CN=,OU=ber Frends,O=Awesome Dudes,C=US".getBytes("UTF-8"); 1041 String string = new String(bytes, 0); 1042 assertEquals(string, (String) item.get(1)); 1043 } else { 1044 assertEquals("CN=,OU=ber Frends,O=Awesome Dudes,C=US", (String) item.get(1)); 1045 } 1046 } 1047 1048 private void getSubjectAlternativeNames_URI(CertificateFactory f) throws Exception { 1049 X509Certificate c = getCertificate(f, CERT_ALT_URI); 1050 Collection<List<?>> col = c.getSubjectAlternativeNames(); 1051 1052 assertNotNull(f.getProvider().getName(), col); 1053 1054 assertEquals(1, col.size()); 1055 List<?> item = col.iterator().next(); 1056 1057 assertTrue(item.get(0) instanceof Integer); 1058 assertTrue(6 == (Integer) item.get(0)); 1059 1060 assertTrue(item.get(1) instanceof String); 1061 assertEquals("http://www.example.com/?q=awesomeness", (String) item.get(1)); 1062 } 1063 1064 private void getSubjectAlternativeNames_RID(CertificateFactory f) throws Exception { 1065 X509Certificate c = getCertificate(f, CERT_ALT_RID); 1066 Collection<List<?>> col = c.getSubjectAlternativeNames(); 1067 1068 assertNotNull(f.getProvider().getName(), col); 1069 1070 assertEquals(1, col.size()); 1071 List<?> item = col.iterator().next(); 1072 1073 assertTrue(item.get(0) instanceof Integer); 1074 assertTrue(8 == (Integer) item.get(0)); 1075 1076 assertTrue(item.get(1) instanceof String); 1077 assertEquals("1.2.3.4", (String) item.get(1)); 1078 } 1079 1080 private void getSubjectAlternativeNames_None(CertificateFactory f) throws Exception { 1081 X509Certificate c = getCertificate(f, CERT_ALT_NONE); 1082 Collection<List<?>> col = c.getSubjectAlternativeNames(); 1083 assertNull(col); 1084 } 1085 1086 private void getIssuerAlternativeNames(CertificateFactory f) throws Exception { 1087 X509Certificate c = getCertificate(f, CERT_RSA); 1088 Collection<List<?>> col = c.getIssuerAlternativeNames(); 1089 1090 checkAlternativeNames(f, col); 1091 } 1092 1093 private void getSignature(CertificateFactory f) throws Exception { 1094 X509Certificate c = getCertificate(f, CERT_RSA); 1095 1096 assertEquals(Arrays.toString(getRsaCertificateSignature()), 1097 Arrays.toString(c.getSignature())); 1098 } 1099 1100 private void getTBSCertificate(CertificateFactory f) throws Exception { 1101 X509Certificate c = getCertificate(f, CERT_RSA); 1102 1103 assertEquals(Arrays.toString(getRsaCertificateTbs()), 1104 Arrays.toString(c.getTBSCertificate())); 1105 } 1106 1107 private void hasUnsupportedCriticalExtension(CertificateFactory f) throws Exception { 1108 X509Certificate c = getCertificate(f, CERT_RSA); 1109 assertFalse(c.hasUnsupportedCriticalExtension()); 1110 1111 X509Certificate unsupported = getCertificate(f, CERT_UNSUPPORTED); 1112 assertTrue(unsupported.hasUnsupportedCriticalExtension()); 1113 } 1114 1115 private void getEncoded(CertificateFactory f) throws Exception { 1116 X509Certificate c = getCertificate(f, CERT_RSA); 1117 1118 byte[] cBytes = getResourceAsBytes(CERT_RSA); 1119 1120 assertEquals(Arrays.toString(cBytes), Arrays.toString(c.getEncoded())); 1121 } 1122 1123 private void generateCertificate_PEM_TrailingData(CertificateFactory f) throws Exception { 1124 byte[] certsBytes = getResourceAsBytes(CERTS_X509_PEM); 1125 byte[] certsTwice = new byte[certsBytes.length * 2]; 1126 System.arraycopy(certsBytes, 0, certsTwice, 0, certsBytes.length); 1127 System.arraycopy(certsBytes, 0, certsTwice, certsBytes.length, certsBytes.length); 1128 ByteArrayInputStream bais = new ByteArrayInputStream(certsTwice); 1129 1130 assertEquals(certsBytes.length * 2, bais.available()); 1131 X509Certificate cert1 = (X509Certificate) f.generateCertificate(bais); 1132 // TODO: If we had a single PEM certificate, we could know exact bytes. 1133 assertTrue(certsBytes.length < bais.available()); 1134 } 1135 1136 private void generateCertificate_DER_TrailingData(CertificateFactory f) throws Exception { 1137 byte[] cert1Bytes = getResourceAsBytes(CERT_RSA); 1138 byte[] cert1WithTrailing = new byte[cert1Bytes.length * 2]; 1139 System.arraycopy(cert1Bytes, 0, cert1WithTrailing, 0, cert1Bytes.length); 1140 System.arraycopy(cert1Bytes, 0, cert1WithTrailing, cert1Bytes.length, cert1Bytes.length); 1141 ByteArrayInputStream bais = new ByteArrayInputStream(cert1WithTrailing); 1142 1143 assertEquals(cert1Bytes.length * 2, bais.available()); 1144 X509Certificate cert1 = (X509Certificate) f.generateCertificate(bais); 1145 assertEquals(cert1Bytes.length, bais.available()); 1146 } 1147 1148 private void generateCertificates_X509_DER(CertificateFactory f) throws Exception { 1149 /* DER-encoded list of certificates */ 1150 Collection<? extends X509Certificate> certs = getCertificates(f, CERTS_X509_DER); 1151 assertNotNull(certs); 1152 assertEquals(2, certs.size()); 1153 } 1154 1155 private void generateCertificates_X509_PEM(CertificateFactory f) throws Exception { 1156 /* PEM-encoded list of certificates */ 1157 Collection<? extends X509Certificate> certs = getCertificates(f, CERTS_X509_PEM); 1158 assertNotNull(certs); 1159 assertEquals(2, certs.size()); 1160 } 1161 1162 private void generateCertificates_PKCS7_PEM(CertificateFactory f) throws Exception { 1163 /* PEM-encoded PKCS7 bag of certificates */ 1164 Collection<? extends X509Certificate> certs = getCertificates(f, CERTS_PKCS7_PEM); 1165 assertNotNull(certs); 1166 assertEquals(2, certs.size()); 1167 } 1168 1169 private void generateCertificates_PKCS7_DER(CertificateFactory f) throws Exception { 1170 /* DER-encoded PKCS7 bag of certificates */ 1171 Collection<? extends X509Certificate> certs = getCertificates(f, CERTS_PKCS7_DER); 1172 assertNotNull(certs); 1173 assertEquals(2, certs.size()); 1174 } 1175 1176 private void generateCertificates_Empty(CertificateFactory f) throws Exception { 1177 final InputStream is = new ByteArrayInputStream(new byte[0]); 1178 1179 final Collection<? extends Certificate> certs = f.generateCertificates(is); 1180 1181 assertNotNull(certs); 1182 assertEquals(0, certs.size()); 1183 } 1184 1185 private void generateCertificates_X509_PEM_TrailingData(CertificateFactory f) throws Exception { 1186 byte[] certBytes = getResourceAsBytes(CERTS_X509_PEM); 1187 byte[] certsPlusExtra = new byte[certBytes.length + 4096]; 1188 System.arraycopy(certBytes, 0, certsPlusExtra, 0, certBytes.length); 1189 ByteArrayInputStream bais = new ByteArrayInputStream(certsPlusExtra); 1190 1191 assertEquals(certsPlusExtra.length, bais.available()); 1192 1193 // RI is broken 1194 try { 1195 Collection<? extends X509Certificate> certs = (Collection<? extends X509Certificate>) 1196 f.generateCertificates(bais); 1197 if (StandardNames.IS_RI) { 1198 return; 1199 } 1200 } catch (CertificateParsingException e) { 1201 if (StandardNames.IS_RI) { 1202 return; 1203 } 1204 throw e; 1205 } 1206 1207 // Bouncycastle is broken 1208 if ("BC".equals(f.getProvider().getName())) { 1209 assertEquals(0, bais.available()); 1210 } else { 1211 assertEquals(4096, bais.available()); 1212 } 1213 } 1214 1215 private void generateCertificates_X509_DER_TrailingData(CertificateFactory f) throws Exception { 1216 byte[] certBytes = getResourceAsBytes(CERTS_X509_DER); 1217 byte[] certsPlusExtra = new byte[certBytes.length + 4096]; 1218 System.arraycopy(certBytes, 0, certsPlusExtra, 0, certBytes.length); 1219 ByteArrayInputStream bais = new ByteArrayInputStream(certsPlusExtra); 1220 1221 assertEquals(certsPlusExtra.length, bais.available()); 1222 1223 // RI is broken 1224 try { 1225 Collection<? extends X509Certificate> certs = (Collection<? extends X509Certificate>) 1226 f.generateCertificates(bais); 1227 if (StandardNames.IS_RI) { 1228 return; 1229 } 1230 } catch (CertificateParsingException e) { 1231 if (StandardNames.IS_RI) { 1232 return; 1233 } 1234 throw e; 1235 } 1236 1237 // Bouncycastle is broken 1238 if ("BC".equals(f.getProvider().getName())) { 1239 assertEquals(0, bais.available()); 1240 } else { 1241 assertEquals(4096, bais.available()); 1242 } 1243 } 1244 1245 private void generateCertificates_PKCS7_PEM_TrailingData(CertificateFactory f) throws Exception { 1246 byte[] certBytes = getResourceAsBytes(CERTS_PKCS7_PEM); 1247 byte[] certsPlusExtra = new byte[certBytes.length + 4096]; 1248 System.arraycopy(certBytes, 0, certsPlusExtra, 0, certBytes.length); 1249 ByteArrayInputStream bais = new ByteArrayInputStream(certsPlusExtra); 1250 1251 assertEquals(certsPlusExtra.length, bais.available()); 1252 Collection<? extends X509Certificate> certs = (Collection<? extends X509Certificate>) 1253 f.generateCertificates(bais); 1254 1255 assertEquals(4096, bais.available()); 1256 } 1257 1258 private void generateCertificates_PKCS7_DER_TrailingData(CertificateFactory f) throws Exception { 1259 byte[] certBytes = getResourceAsBytes(CERTS_PKCS7_DER); 1260 byte[] certsPlusExtra = new byte[certBytes.length + 4096]; 1261 System.arraycopy(certBytes, 0, certsPlusExtra, 0, certBytes.length); 1262 ByteArrayInputStream bais = new ByteArrayInputStream(certsPlusExtra); 1263 1264 assertEquals(certsPlusExtra.length, bais.available()); 1265 Collection<? extends X509Certificate> certs = (Collection<? extends X509Certificate>) 1266 f.generateCertificates(bais); 1267 1268 assertEquals(4096, bais.available()); 1269 } 1270 1271 private void test_Serialization(CertificateFactory f) throws Exception { 1272 for (String certName : VARIOUS_CERTS) { 1273 X509Certificate expected = getCertificate(f, certName); 1274 1275 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1276 ObjectOutputStream oos = new ObjectOutputStream(baos); 1277 try { 1278 oos.writeObject(expected); 1279 } finally { 1280 oos.close(); 1281 } 1282 1283 byte[] certBytes = baos.toByteArray(); 1284 1285 ByteArrayInputStream bais = new ByteArrayInputStream(certBytes); 1286 try { 1287 ObjectInputStream ois = new ObjectInputStream(bais); 1288 1289 X509Certificate actual = (X509Certificate) ois.readObject(); 1290 1291 assertEquals(certName, expected, actual); 1292 } finally { 1293 bais.close(); 1294 } 1295 } 1296 } 1297 1298 private void test_UnknownUnmappedKeyOID(CertificateFactory f) throws Exception { 1299 byte[] certBytes = generateFakeOidCertificate(); 1300 1301 { 1302 X509Certificate cert = (X509Certificate) f 1303 .generateCertificate(new ByteArrayInputStream(certBytes)); 1304 assertEquals(FakeOidProvider.SIGALG_OID, cert.getSigAlgOID()); 1305 assertEquals(FakeOidProvider.SIGALG_OID, cert.getSigAlgName()); 1306 } 1307 } 1308 1309 private byte[] generateFakeOidCertificate() throws IOException { 1310 byte[] certBytes; 1311 1312 // Read in the original cert. 1313 { 1314 InputStream is = null; 1315 try { 1316 is = Support_Resources.getStream(CERT_RSA); 1317 1318 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1319 byte[] buffer = new byte[2048]; 1320 int numRead; 1321 while ((numRead = is.read(buffer, 0, buffer.length)) != -1) { 1322 baos.write(buffer, 0, numRead); 1323 } 1324 certBytes = baos.toByteArray(); 1325 } finally { 1326 if (is != null) { 1327 try { 1328 is.close(); 1329 } catch (IOException ignored) { 1330 } 1331 } 1332 } 1333 } 1334 1335 // Fix the OID for the certificate. 1336 { 1337 int numFixed = 0; 1338 for (int i = 0; i < certBytes.length - 5; i++) { 1339 if (certBytes[i] == (byte) 0x2A && certBytes[i + 1] == (byte) 0x86 1340 && certBytes[i + 2] == (byte) 0x48 && certBytes[i + 3] == (byte) 0x86 1341 && certBytes[i + 4] == (byte) 0xF7) { 1342 certBytes[i + 1] = (byte) 0xFF; 1343 certBytes[i + 2] = (byte) 0xFF; 1344 certBytes[i + 3] = (byte) 0xFF; 1345 i += 4; 1346 numFixed++; 1347 } 1348 } 1349 assertEquals(3, numFixed); 1350 } 1351 return certBytes; 1352 } 1353 } 1354