Home | History | Annotate | Download | only in cert
      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