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