test/jdk/sun/security/validator/PKIXValAndRevCheckTests.java
changeset 57849 e1269de19aa5
equal deleted inserted replaced
57847:bc14eec6f4bc 57849:e1269de19aa5
       
     1 /*
       
     2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 /**
       
    25  * @test
       
    26  * @bug 8225436
       
    27  * @summary Stapled OCSPResponses should be added to PKIXRevocationChecker
       
    28  *          irrespective of revocationEnabled flag
       
    29  * @library /test/lib
       
    30  * @modules java.base/sun.security.validator
       
    31  * @build jdk.test.lib.Convert
       
    32  * @run main PKIXValAndRevCheckTests
       
    33  */
       
    34 
       
    35 import java.io.ByteArrayInputStream;
       
    36 import java.io.UnsupportedEncodingException;
       
    37 import java.security.cert.CertPathValidator;
       
    38 import java.security.cert.CertPathValidatorException;
       
    39 import java.security.cert.CertPathValidatorException.BasicReason;
       
    40 import java.security.cert.CertificateException;
       
    41 import java.security.cert.CertificateFactory;
       
    42 import java.security.cert.PKIXBuilderParameters;
       
    43 import java.security.cert.PKIXRevocationChecker;
       
    44 import java.security.cert.TrustAnchor;
       
    45 import java.security.cert.X509Certificate;
       
    46 import java.util.Base64;
       
    47 import java.util.Collections;
       
    48 import java.util.Date;
       
    49 import java.util.List;
       
    50 import java.util.Map;
       
    51 import java.util.Set;
       
    52 import sun.security.validator.Validator;
       
    53 
       
    54 public class PKIXValAndRevCheckTests {
       
    55 
       
    56     // subject: CN=Good Server,O=TestPKI
       
    57     // issuer: CN=CA1 Intermediate,O=TestPKI
       
    58     // serial: 01000015
       
    59     // notBefore: Aug 16 02:42:32 2019 GMT
       
    60     // notAfter: Aug 15 02:42:32 2020 GMT
       
    61     static final String GOOD_SERVER_PEM =
       
    62         "-----BEGIN CERTIFICATE-----\n" +
       
    63         "MIIDjTCCAnWgAwIBAgIEAQAAFTANBgkqhkiG9w0BAQsFADAtMRAwDgYDVQQKDAdU\n" +
       
    64         "ZXN0UEtJMRkwFwYDVQQDDBBDQTEgSW50ZXJtZWRpYXRlMB4XDTE5MDgxNjAyNDIz\n" +
       
    65         "MloXDTIwMDgxNTAyNDIzMlowKDEQMA4GA1UECgwHVGVzdFBLSTEUMBIGA1UEAwwL\n" +
       
    66         "R29vZCBTZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSQSUF\n" +
       
    67         "L5th5P21Vijy5pm0WnC0AWCSHX5003f9um70k/IdaAg2rsj/aKHnsm+r4xXGD236\n" +
       
    68         "S7DxBR2w8NTnAofgRWlsAn74lWQhV2p3SU/JKEtFbJV1YAnNOUPKsCnVKDfe3Gev\n" +
       
    69         "zxOLpZ/VKSx9u20bOUbh6QxqlIdIuJ6AW/cgyjdvuN16sIWGWzl17lm81T1cy89x\n" +
       
    70         "TvvsHHqfAh+y3jMwqvIRxoaNQoOjcmxSldRnCwBfhg8xHxB4wKa4z+6Y3gndzne1\n" +
       
    71         "Ms0itbtdYlSF3ADOtwoBrftYDpvsG8VhA4x4QqFAAKx1FPO6OJBYGNfZvnoDDi9g\n" +
       
    72         "i0PgDNftm0l/6FGlAgMBAAGjgbkwgbYwHQYDVR0OBBYEFJNBzLRxgb0znmeuYXc3\n" +
       
    73         "UaFGd9m3MB8GA1UdIwQYMBaAFJraQNM+W62lwqzcSEc6VjNXAaSaMA4GA1UdDwEB\n" +
       
    74         "/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEwYDVR0RBAww\n" +
       
    75         "CoIIdGVyaXlha2kwMAYIKwYBBQUHAQEEJDAiMCAGCCsGAQUFBzABhhRodHRwOi8v\n" +
       
    76         "dGVyaXlha2k6NTIwMDANBgkqhkiG9w0BAQsFAAOCAQEAadl0EQdBJw6dBBelxtox\n" +
       
    77         "id18HMt+MsXssHun1nx8My0VZ3uQBNJ4GgKipNFa+s8nPZIzRr0Ls65dIUiBcg3R\n" +
       
    78         "ep0he/gnkaowRRxGqMkALl3VzUz8INSRzdCIVm0EBeDCaHGLzE6G3uIqWwldei8k\n" +
       
    79         "IOHtiVLESAJvCvSEOAnoJHRVD8+tbEIxRsSFkoKGqc5U7bsCVC5uSXOkiHEP/3zm\n" +
       
    80         "6YixiT+hLk6QKegkQxQPZ+irGBeN2q2PAq5vTh1hJDciwqE3h8GxZ15iR3WIedc8\n" +
       
    81         "6EHJ7+N27nWZLtFgcLKNXEsm1Eh/YNIrpeN0OQBGSLD3lIju5IO0mD3oQfA4miqT\n" +
       
    82         "wQ==\n" +
       
    83         "-----END CERTIFICATE-----";
       
    84 
       
    85     // subject: CN=Bad Server,O=TestPKI
       
    86     // issuer: CN=CA1 Intermediate,O=TestPKI
       
    87     // serial: 01000016
       
    88     // notBefore: Aug 16 02:43:11 2019 GMT
       
    89     // notAfter: Aug 15 02:43:11 2020 GMT
       
    90     static final String BAD_SERVER_PEM =
       
    91         "-----BEGIN CERTIFICATE-----\n" +
       
    92         "MIIDjDCCAnSgAwIBAgIEAQAAFjANBgkqhkiG9w0BAQsFADAtMRAwDgYDVQQKDAdU\n" +
       
    93         "ZXN0UEtJMRkwFwYDVQQDDBBDQTEgSW50ZXJtZWRpYXRlMB4XDTE5MDgxNjAyNDMx\n" +
       
    94         "MVoXDTIwMDgxNTAyNDMxMVowJzEQMA4GA1UECgwHVGVzdFBLSTETMBEGA1UEAwwK\n" +
       
    95         "QmFkIFNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9syEok\n" +
       
    96         "K/8E/hm8Q/cLhSwirDIGFC9nqS8p1bVNTClkMsqxkQAcQptP1zLZiMBdgLjOH3cF\n" +
       
    97         "60UAaz2Y+7WYU5MB6AE8IloDgUUKKUTUmXHzM31OiSVu21+ooo59XzV/cCEu+Qlu\n" +
       
    98         "AiaDuTDhIEtM58zs/3RZN0h+v8M2NXUU4bwYmYVeqP8UW9BEjgznIIrvGpqpHKz5\n" +
       
    99         "EwctL+u/h5Z/DoCOnVq3irMCpInY5/VbIuxfkdfawsFROzUWl6fZ3+CTfQfHhKSM\n" +
       
   100         "sz1/zY/BtQLDTKY120M2FaLmmIoOLrqZo8Pi+JL8IVentNfSHvUX5rrnPKB2/JVS\n" +
       
   101         "8Jc2qvLPk4PWbwECAwEAAaOBuTCBtjAdBgNVHQ4EFgQU8z9qWpJ/FDmKOgQI2vY7\n" +
       
   102         "0OwCNFEwHwYDVR0jBBgwFoAUmtpA0z5braXCrNxIRzpWM1cBpJowDgYDVR0PAQH/\n" +
       
   103         "BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjATBgNVHREEDDAK\n" +
       
   104         "ggh0ZXJpeWFraTAwBggrBgEFBQcBAQQkMCIwIAYIKwYBBQUHMAGGFGh0dHA6Ly90\n" +
       
   105         "ZXJpeWFraTo1MjAwMA0GCSqGSIb3DQEBCwUAA4IBAQBzi8U/3b6hfGwE/przqyha\n" +
       
   106         "Y40Nhh1uCm1rz4bZ27z2Q3vzlg2ay4V3I2NaR4eY/wsuO8AW0qdBJExmYqgi+l9U\n" +
       
   107         "S6i9WqyI22jAKUPsx9WmCZltyU589VDU40h2g6C4+8VnOZm6OKKKTjkKrDn/IFJF\n" +
       
   108         "jU4yIvXrEBHNJr/tcQW0+dF2okIBAnVLUNs8CZZJyWesQtu6J0OBj4tE8s0ET4ep\n" +
       
   109         "XC/3mZkGjziEZw8/dDZ0/+CQbrkDP2vs6iNjz/LUIA9dVXUs9sNeqW+VEHI3vZvJ\n" +
       
   110         "gYVDJn5tWZSIY/O2zV97dz9VeDH3aukuoEm5aAxxhazxRDntcnl2DYrrr2bGuS2Y\n" +
       
   111         "-----END CERTIFICATE-----";
       
   112 
       
   113     // subject: CN=CA1 Intermediate,O=TestPKI
       
   114     // issuer: CN=TestRoot,O=TestPKI
       
   115     // serial: 0100
       
   116     // notBefore: May  6 06:00:00 2015 GMT
       
   117     // notAfter: Jan 21 12:00:00 2025 GMT
       
   118     static final String INT_CA_PEM =
       
   119         "-----BEGIN CERTIFICATE-----\n" +
       
   120         "MIIEbTCCAlWgAwIBAgICAQAwDQYJKoZIhvcNAQELBQAwJTEQMA4GA1UECgwHVGVz\n" +
       
   121         "dFBLSTERMA8GA1UEAwwIVGVzdFJvb3QwHhcNMTUwNTA2MDYwMDAwWhcNMjUwMTIx\n" +
       
   122         "MTIwMDAwWjAtMRAwDgYDVQQKDAdUZXN0UEtJMRkwFwYDVQQDDBBDQTEgSW50ZXJt\n" +
       
   123         "ZWRpYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtdKjBpeuJJEv\n" +
       
   124         "di4wMGHE5y7inXuDvMCjkjFRv9XOH20BVAIDMTMeIByk6NQJYeeaTRGXTawZN8/c\n" +
       
   125         "aXtQuqsRGz/q2va/I+A5HIvtu+vujdVksu2baafGM0Ql8Gdzj8MdLGb+kGFji/FX\n" +
       
   126         "f+2PL8UfpnmUikLN728lF9bzcA046I8B43SriFJeYOlLPfE/yjNg5eccdMPDBw7h\n" +
       
   127         "KQPVbXfpcmWRJm/vGlCR38Rd7ceYF3/ctf/0J8Dab7q98ITpH9q5NFD+o2NJZoFq\n" +
       
   128         "7HBPdGTIJ73m3WPzLRrU+JPD7xs9wgmuuRq6hU/lPSd5IJSkJ/cyXkma1RwBO4Lm\n" +
       
   129         "rU2aWDGhNwIDAQABo4GeMIGbMB0GA1UdDgQWBBSa2kDTPlutpcKs3EhHOlYzVwGk\n" +
       
   130         "mjAfBgNVHSMEGDAWgBTwWIIuUEAneAXJeud3ioakmTg32zAPBgNVHRMBAf8EBTAD\n" +
       
   131         "AQH/MA4GA1UdDwEB/wQEAwIBhjA4BggrBgEFBQcBAQQsMCowKAYIKwYBBQUHMAGG\n" +
       
   132         "HGh0dHA6Ly9qaWFuLm9zdGFwbGUub3JnOjcxMDAwDQYJKoZIhvcNAQELBQADggIB\n" +
       
   133         "ADRoginKFigLOKz1NJN86w66eP3r4D/5Qq8+G9DiasmThLQfaVYBvuaR9kL3D9Vr\n" +
       
   134         "1EEXRGmCxMTHetW0SQ/SsMeRbBf8Ihck4MOeAC9cMysvtNfjpwxaAh6zF5bX4pjj\n" +
       
   135         "33gJpjPLNAZru09rSF0GIo9CxPh9rBOkmttrnPDX7rLR9962i/P4KHyHknGM7gY0\n" +
       
   136         "U88ddugkANiFIiAfBRGFz3AqMiMi3VP5STCP0k0ab/frkev6C/qq3th4gQ/Bog/5\n" +
       
   137         "YaoWvzGAs7QoQ7+r0BIRZhG71WQKD4Yx1a43RnG3tFPLFznk0odeh8sr/CI3H/+b\n" +
       
   138         "eyyJLd02ApujZoAfMHzTcq/27mO1ZvA5qSt4wsb7gswnIYwXbJZBBRoixGFD7VP0\n" +
       
   139         "NEXREljpEuGIIy2lkHb5wNV3OEMmAmoKwx1GXWXRfQRHqn1f2/XLYInDg0u9u+G6\n" +
       
   140         "UX3edn6rwP+vlIX2Cx4qC/yX4zg7YxMXCwrol91/7wugkUGPjmU6qmK+TtuwZNQG\n" +
       
   141         "2wtCB4FJXa0YZyDd7U/FH7nWZtG9BgzpLit90hC4+m5V4E/7I6slvwxpkE7y0Nju\n" +
       
   142         "tjy/qcuil6imrOR/apuwT1ecAmyjm1UmpKPLLzYnE6AtSKOTndGa2iNyPDrseFLy\n" +
       
   143         "7TUF/fg/dvZ46OmouSX3upAFRnvpXYXwSQRQ2S+wEnbp\n" +
       
   144         "-----END CERTIFICATE-----";
       
   145 
       
   146     // subject: CN=TestRoot,O=TestPKI
       
   147     // issuer: CN=TestRoot,O=TestPKI
       
   148     // serial: 01
       
   149     // notBefore: May  6 00:36:03 2015 GMT
       
   150     // notAfter: Jan 21 00:36:03 2035 GMT
       
   151     static final String ROOT_CA_PEM =
       
   152         "-----BEGIN CERTIFICATE-----\n" +
       
   153         "MIIFKDCCAxCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAlMRAwDgYDVQQKDAdUZXN0\n" +
       
   154         "UEtJMREwDwYDVQQDDAhUZXN0Um9vdDAeFw0xNTA1MDYwMDM2MDNaFw0zNTAxMjEw\n" +
       
   155         "MDM2MDNaMCUxEDAOBgNVBAoMB1Rlc3RQS0kxETAPBgNVBAMMCFRlc3RSb290MIIC\n" +
       
   156         "IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuLCcVhyIaPV5CHjvnyAvK978\n" +
       
   157         "TUC2YY5wZ8e21L8C+SvxCoE5U66H+wMsNIC90i1ynlz49G4oKR67GXcijJpVD1fA\n" +
       
   158         "Dq3Hpc3WDY9/5jRKWZOC0qLmXMPEF8wrwyC3aQ81sytDJOhEfxEf3KvwFDI9NUQb\n" +
       
   159         "tFdWB+IDEvaDCTJgOt/jIJAzLTxzvwPBzP/JHdRCwKdmlQStRp20AmDtpgIlm2RH\n" +
       
   160         "v8ywabI/UqncZHe/LVYdmDNxztziM98Zs1I7vsO2/yebWE/QH3g3k9ZgaT6UnBAq\n" +
       
   161         "gvV2TQhZOGMmps7RrfNdVEHeeRXmJTFAtmbi/o6Ou7xli+3bDuY5Faxk7uOpC54H\n" +
       
   162         "iyyH2Htoyc9A0M9qwkwnrKxlWe594uD9LbWMNBMMTv4nUtf1ZE1swHg/L9XATDa/\n" +
       
   163         "ZB5hL6p/oS2CxloLL982CIbSuV1TcI6s4naTyZ3HxnIKCaOijAK+IDo9qbTFkt9w\n" +
       
   164         "4toc09fWGRV/pgm3p6YptP48JDYTHQK8GvjzQIdALXee28BmM496cV49uo1O6ia0\n" +
       
   165         "Ht1MFMDKav2g9Cr5SYKIFkpZjJ2T0aJ4dLeft+nQCwDP4odHRBTQbqK9oMw6qYav\n" +
       
   166         "PVuZJWwW3ilZtke2D28N4bF2X1nMYFM2obnB/TLkpreNSiyV6M0D2DW8tpGLTXOp\n" +
       
   167         "yZEJqAx2dEhfxRNE7sECAwEAAaNjMGEwHQYDVR0OBBYEFPBYgi5QQCd4Bcl653eK\n" +
       
   168         "hqSZODfbMB8GA1UdIwQYMBaAFPBYgi5QQCd4Bcl653eKhqSZODfbMA8GA1UdEwEB\n" +
       
   169         "/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBjCVYc\n" +
       
   170         "0PmSjzxYGfXtR6+JaDrA/1jhkTPTVTqVniKV4beqoX90BE9krvic7nfvxoYecNux\n" +
       
   171         "b1ZZkXMZ0NVadjxySaFmHo9E5eoPWp2N0Jb5rV+imlofz+U9/lANTb9QJ4L+qUwL\n" +
       
   172         "s40zai1i5yvt4ZcowBRy2BohF2qgaFy8rd+amqVd8LnG06HIOJjZYKgKd2EJyQR6\n" +
       
   173         "F6SPPuSfK5wpkBnkTUvtsvx4+8MKUfKRThGQkovSbXxfusAWehe9XT5hCgG2s04J\n" +
       
   174         "7rL1LVrviBXPFaQgbIGov0PubCJM6V6GFwNJxqVLxbFS0mN+z9M6JzJM5SRF/Ki5\n" +
       
   175         "daczIOGNELVbCct/4aaWeHYwXfnJo/EghAdbS2DPvESXQhNsuW6KYTl6Qhzu3UHw\n" +
       
   176         "yaEIOh2LYENhKJq91Ww6Xhk9seGuwIsj6HXS30lrRztDM+GPU44WQxhmSUwY0C9g\n" +
       
   177         "+KydH1c71eH5vBG3ODKsqBtFkHVD0qhm3Oa33uyUOdvNeRyIQzXSH9QJPXbJURqD\n" +
       
   178         "TRNWmLG4eEIGIFCYyuaBSeCKrvPyiUXR0p9XQjOJVuCQPr8pfW483/BtlzAa6v3r\n" +
       
   179         "jDOoB5v4FaC57HFt8aMrf/B3KGtH/PBpdRSAAIWAIwt9sbTq8nzhCIFhxJTiRWxQ\n" +
       
   180         "uvSM40WEaUsmfpxU+tF2LJvWmNNbDDtEmbFsQQ==\n" +
       
   181         "-----END CERTIFICATE-----";
       
   182 
       
   183     // OCSP Response Status: successful (0x0)
       
   184     // Response Type: Basic OCSP Response
       
   185     // Version: 1 (0x0)
       
   186     // Responder Id: O = TestPKI, CN = TestRoot
       
   187     // Produced At: Aug 16 06:06:27 2019 GMT
       
   188     // Responses:
       
   189     // Certificate ID:
       
   190     //   Hash Algorithm: sha1
       
   191     //   Issuer Name Hash: 622C4B816C42E2E99FF41B5CED388DAA33A6B9B3
       
   192     //   Issuer Key Hash: F058822E5040277805C97AE7778A86A4993837DB
       
   193     //   Serial Number: 0100
       
   194     // Cert Status: good
       
   195     // This Update: Aug 16 06:06:27 2019 GMT
       
   196     // Next Update: Aug 17 06:06:27 2019 GMT
       
   197     static final String INT_CA_OCSP_PEM =
       
   198         "MIIILwoBAKCCCCgwgggkBgkrBgEFBQcwAQEEgggVMIIIETCBxqEnMCUxEDAOBgNV\n" +
       
   199         "BAoMB1Rlc3RQS0kxETAPBgNVBAMMCFRlc3RSb290GA8yMDE5MDgxNjA2MDYyN1ow\n" +
       
   200         "ZTBjMDswCQYFKw4DAhoFAAQUYixLgWxC4umf9Btc7TiNqjOmubMEFPBYgi5QQCd4\n" +
       
   201         "Bcl653eKhqSZODfbAgIBAIAAGA8yMDE5MDgxNjA2MDYyN1qgERgPMjAxOTA4MTcw\n" +
       
   202         "NjA2MjdaoSMwITAfBgkrBgEFBQcwAQIEEgQQwlXs/KMVtgxAfc/QGVpHojANBgkq\n" +
       
   203         "hkiG9w0BAQsFAAOCAgEAsDp1oTacP+wZ5ryFzM+j5AaMJ9k7Gmer4QqecszG2YzS\n" +
       
   204         "eM4TUoB2xh3VyQy7OdIDeEsPIwSs/tzJ15/QfJz9WZ6iEUJRj9rnkwdAdRr13AIr\n" +
       
   205         "I7G2jwp7Mbm3h/jluT84tE8+DGohsUq0JGsv1pviT0HL0x40OqfDcOjwvrFCAid1\n" +
       
   206         "ZZwlCWMeybFdX9+GLeHWnyzotajChw52iMK/EHwEWAD2gVX1WbuByGLRy4Oy9HPY\n" +
       
   207         "QbZHjRwlDD29gv9eWK+sFGKV7aBAYTqPkAAvp+GA0xnVUKCuTSHMp53pDA2lkOMp\n" +
       
   208         "z5Hi7SMmkxckTDQI+2By0qwxLymEDbHaALO+XdSD5F5Kysjp6GnfjNcYZQgbxtrC\n" +
       
   209         "ZJOud/hPtBqVEJg42KLLdcYq7uTdNxuQmsu5MK+TTlM37eOWhtbRAozIn2j17QT0\n" +
       
   210         "GV9s+BZWyku8la5+yFUuel5FbNQQTP5av+dKCS3BD/29XFOG4EfK0MEZknA3QKSG\n" +
       
   211         "cI0kd8q5I4fEtsxGW6afra1YBj1TWcnsbHGL/PGHBR0WBr5DXo48dXLHCxEeiAiq\n" +
       
   212         "4lZMcgL4od+hyIOK21evO20sH/Ec73Z0/tXykYp8Y92uv56hRj4/y+WnueyrTOIH\n" +
       
   213         "cwXSvyNTcf0fyZuWEsmUAQmchNPLsEmAolDTcUJsMWOzmYk8cr1WYFrcLWgbOvag\n" +
       
   214         "ggUwMIIFLDCCBSgwggMQoAMCAQICAQEwDQYJKoZIhvcNAQELBQAwJTEQMA4GA1UE\n" +
       
   215         "CgwHVGVzdFBLSTERMA8GA1UEAwwIVGVzdFJvb3QwHhcNMTUwNTA2MDAzNjAzWhcN\n" +
       
   216         "MzUwMTIxMDAzNjAzWjAlMRAwDgYDVQQKDAdUZXN0UEtJMREwDwYDVQQDDAhUZXN0\n" +
       
   217         "Um9vdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALiwnFYciGj1eQh4\n" +
       
   218         "758gLyve/E1AtmGOcGfHttS/Avkr8QqBOVOuh/sDLDSAvdItcp5c+PRuKCkeuxl3\n" +
       
   219         "IoyaVQ9XwA6tx6XN1g2Pf+Y0SlmTgtKi5lzDxBfMK8Mgt2kPNbMrQyToRH8RH9yr\n" +
       
   220         "8BQyPTVEG7RXVgfiAxL2gwkyYDrf4yCQMy08c78Dwcz/yR3UQsCnZpUErUadtAJg\n" +
       
   221         "7aYCJZtkR7/MsGmyP1Kp3GR3vy1WHZgzcc7c4jPfGbNSO77Dtv8nm1hP0B94N5PW\n" +
       
   222         "YGk+lJwQKoL1dk0IWThjJqbO0a3zXVRB3nkV5iUxQLZm4v6Ojru8ZYvt2w7mORWs\n" +
       
   223         "ZO7jqQueB4ssh9h7aMnPQNDPasJMJ6ysZVnufeLg/S21jDQTDE7+J1LX9WRNbMB4\n" +
       
   224         "Py/VwEw2v2QeYS+qf6EtgsZaCy/fNgiG0rldU3COrOJ2k8mdx8ZyCgmjoowCviA6\n" +
       
   225         "Pam0xZLfcOLaHNPX1hkVf6YJt6emKbT+PCQ2Ex0CvBr480CHQC13ntvAZjOPenFe\n" +
       
   226         "PbqNTuomtB7dTBTAymr9oPQq+UmCiBZKWYydk9GieHS3n7fp0AsAz+KHR0QU0G6i\n" +
       
   227         "vaDMOqmGrz1bmSVsFt4pWbZHtg9vDeGxdl9ZzGBTNqG5wf0y5Ka3jUoslejNA9g1\n" +
       
   228         "vLaRi01zqcmRCagMdnRIX8UTRO7BAgMBAAGjYzBhMB0GA1UdDgQWBBTwWIIuUEAn\n" +
       
   229         "eAXJeud3ioakmTg32zAfBgNVHSMEGDAWgBTwWIIuUEAneAXJeud3ioakmTg32zAP\n" +
       
   230         "BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOC\n" +
       
   231         "AgEAYwlWHND5ko88WBn17UeviWg6wP9Y4ZEz01U6lZ4ileG3qqF/dARPZK74nO53\n" +
       
   232         "78aGHnDbsW9WWZFzGdDVWnY8ckmhZh6PROXqD1qdjdCW+a1foppaH8/lPf5QDU2/\n" +
       
   233         "UCeC/qlMC7ONM2otYucr7eGXKMAUctgaIRdqoGhcvK3fmpqlXfC5xtOhyDiY2WCo\n" +
       
   234         "CndhCckEehekjz7knyucKZAZ5E1L7bL8ePvDClHykU4RkJKL0m18X7rAFnoXvV0+\n" +
       
   235         "YQoBtrNOCe6y9S1a74gVzxWkIGyBqL9D7mwiTOlehhcDScalS8WxUtJjfs/TOicy\n" +
       
   236         "TOUkRfyouXWnMyDhjRC1WwnLf+Gmlnh2MF35yaPxIIQHW0tgz7xEl0ITbLluimE5\n" +
       
   237         "ekIc7t1B8MmhCDodi2BDYSiavdVsOl4ZPbHhrsCLI+h10t9Ja0c7QzPhj1OOFkMY\n" +
       
   238         "ZklMGNAvYPisnR9XO9Xh+bwRtzgyrKgbRZB1Q9KoZtzmt97slDnbzXkciEM10h/U\n" +
       
   239         "CT12yVEag00TVpixuHhCBiBQmMrmgUngiq7z8olF0dKfV0IziVbgkD6/KX1uPN/w\n" +
       
   240         "bZcwGur964wzqAeb+BWguexxbfGjK3/wdyhrR/zwaXUUgACFgCMLfbG06vJ84QiB\n" +
       
   241         "YcSU4kVsULr0jONFhGlLJn6cVPrRdiyb1pjTWww7RJmxbEE=";
       
   242 
       
   243     // OCSP Response Status: successful (0x0)
       
   244     // Response Type: Basic OCSP Response
       
   245     // Version: 1 (0x0)
       
   246     // Responder Id: O = TestPKI, CN = CA1 Intermediate
       
   247     // Produced At: Aug 16 05:03:09 2019 GMT
       
   248     // Responses:
       
   249     // Certificate ID:
       
   250     //   Hash Algorithm: sha1
       
   251     //   Issuer Name Hash: FE48D59BAF624773549AE209AA14FD20DCE6B8F4
       
   252     //   Issuer Key Hash: 9ADA40D33E5BADA5C2ACDC48473A56335701A49A
       
   253     //   Serial Number: 01000015
       
   254     // Cert Status: good
       
   255     // This Update: Aug 16 05:03:09 2019 GMT
       
   256     // Next Update: Aug 17 05:03:09 2019 GMT
       
   257     static final String GOOD_GUY_OCSP_PEM =
       
   258         "MIIGfgoBAKCCBncwggZzBgkrBgEFBQcwAQEEggZkMIIGYDCB0KEvMC0xEDAOBgNV\n" +
       
   259         "BAoMB1Rlc3RQS0kxGTAXBgNVBAMMEENBMSBJbnRlcm1lZGlhdGUYDzIwMTkwODE2\n" +
       
   260         "MDUwMzA5WjBnMGUwPTAJBgUrDgMCGgUABBT+SNWbr2JHc1Sa4gmqFP0g3Oa49AQU\n" +
       
   261         "mtpA0z5braXCrNxIRzpWM1cBpJoCBAEAABWAABgPMjAxOTA4MTYwNTAzMDlaoBEY\n" +
       
   262         "DzIwMTkwODE3MDUwMzA5WqEjMCEwHwYJKwYBBQUHMAECBBIEEN087n3ef92+4d2K\n" +
       
   263         "+XaudDUwDQYJKoZIhvcNAQELBQADggEBAErIOOkLGwbDWgrpl3lQbsnaoVY6YNYV\n" +
       
   264         "x1bfJ89S8twBouei6a/HmAIDqUPmlVF7gm8sNvgANXuZGkWXmqadSpWxLA36ZT4d\n" +
       
   265         "70iRLmdTaPnKVpUEO5dYMg7nWW+D4hp9wupkPaB3PsEPb4pwrcTOUH1FAi3pZ+hF\n" +
       
   266         "oeNDaE3jHQGEz4dVK1XgK2pxFNf4aTIgj+w40xN5yaCcTYicbLmumNGCzrGwnRqh\n" +
       
   267         "tyoiz27+rTxFrEeWGnNslJfScD9O4oe/KhvYBusurNVrFgG4VcxB5NNemrCW4/cf\n" +
       
   268         "dehv8z50FaZvq1xklqkZ4hgbjNxtI8lAHp+wYDQJub0mhXWmb9K/4kOgggR1MIIE\n" +
       
   269         "cTCCBG0wggJVoAMCAQICAgEAMA0GCSqGSIb3DQEBCwUAMCUxEDAOBgNVBAoMB1Rl\n" +
       
   270         "c3RQS0kxETAPBgNVBAMMCFRlc3RSb290MB4XDTE1MDUwNjA2MDAwMFoXDTI1MDEy\n" +
       
   271         "MTEyMDAwMFowLTEQMA4GA1UECgwHVGVzdFBLSTEZMBcGA1UEAwwQQ0ExIEludGVy\n" +
       
   272         "bWVkaWF0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALXSowaXriSR\n" +
       
   273         "L3YuMDBhxOcu4p17g7zAo5IxUb/Vzh9tAVQCAzEzHiAcpOjUCWHnmk0Rl02sGTfP\n" +
       
   274         "3Gl7ULqrERs/6tr2vyPgORyL7bvr7o3VZLLtm2mnxjNEJfBnc4/DHSxm/pBhY4vx\n" +
       
   275         "V3/tjy/FH6Z5lIpCze9vJRfW83ANOOiPAeN0q4hSXmDpSz3xP8ozYOXnHHTDwwcO\n" +
       
   276         "4SkD1W136XJlkSZv7xpQkd/EXe3HmBd/3LX/9CfA2m+6vfCE6R/auTRQ/qNjSWaB\n" +
       
   277         "auxwT3RkyCe95t1j8y0a1PiTw+8bPcIJrrkauoVP5T0neSCUpCf3Ml5JmtUcATuC\n" +
       
   278         "5q1NmlgxoTcCAwEAAaOBnjCBmzAdBgNVHQ4EFgQUmtpA0z5braXCrNxIRzpWM1cB\n" +
       
   279         "pJowHwYDVR0jBBgwFoAU8FiCLlBAJ3gFyXrnd4qGpJk4N9swDwYDVR0TAQH/BAUw\n" +
       
   280         "AwEB/zAOBgNVHQ8BAf8EBAMCAYYwOAYIKwYBBQUHAQEELDAqMCgGCCsGAQUFBzAB\n" +
       
   281         "hhxodHRwOi8vamlhbi5vc3RhcGxlLm9yZzo3MTAwMA0GCSqGSIb3DQEBCwUAA4IC\n" +
       
   282         "AQA0aIIpyhYoCzis9TSTfOsOunj96+A/+UKvPhvQ4mrJk4S0H2lWAb7mkfZC9w/V\n" +
       
   283         "a9RBF0RpgsTEx3rVtEkP0rDHkWwX/CIXJODDngAvXDMrL7TX46cMWgIesxeW1+KY\n" +
       
   284         "4994CaYzyzQGa7tPa0hdBiKPQsT4fawTpJrba5zw1+6y0ffetovz+Ch8h5JxjO4G\n" +
       
   285         "NFPPHXboJADYhSIgHwURhc9wKjIjIt1T+Ukwj9JNGm/365Hr+gv6qt7YeIEPwaIP\n" +
       
   286         "+WGqFr8xgLO0KEO/q9ASEWYRu9VkCg+GMdWuN0Zxt7RTyxc55NKHXofLK/wiNx//\n" +
       
   287         "m3ssiS3dNgKbo2aAHzB803Kv9u5jtWbwOakreMLG+4LMJyGMF2yWQQUaIsRhQ+1T\n" +
       
   288         "9DRF0RJY6RLhiCMtpZB2+cDVdzhDJgJqCsMdRl1l0X0ER6p9X9v1y2CJw4NLvbvh\n" +
       
   289         "ulF93nZ+q8D/r5SF9gseKgv8l+M4O2MTFwsK6Jfdf+8LoJFBj45lOqpivk7bsGTU\n" +
       
   290         "BtsLQgeBSV2tGGcg3e1PxR+51mbRvQYM6S4rfdIQuPpuVeBP+yOrJb8MaZBO8tDY\n" +
       
   291         "7rY8v6nLopeopqzkf2qbsE9XnAJso5tVJqSjyy82JxOgLUijk53Rmtojcjw67HhS\n" +
       
   292         "8u01Bf34P3b2eOjpqLkl97qQBUZ76V2F8EkEUNkvsBJ26Q==";
       
   293 
       
   294     // OCSP Response Status: successful (0x0)
       
   295     // Response Type: Basic OCSP Response
       
   296     // Version: 1 (0x0)
       
   297     // Responder Id: O = TestPKI, CN = CA1 Intermediate
       
   298     // Produced At: Aug 16 05:03:27 2019 GMT
       
   299     // Responses:
       
   300     // Certificate ID:
       
   301     //   Hash Algorithm: sha1
       
   302     //   Issuer Name Hash: FE48D59BAF624773549AE209AA14FD20DCE6B8F4
       
   303     //   Issuer Key Hash: 9ADA40D33E5BADA5C2ACDC48473A56335701A49A
       
   304     //   Serial Number: 01000016
       
   305     // Cert Status: revoked
       
   306     // Revocation Time: Aug 16 04:59:31 2019 GMT
       
   307     // Revocation Reason: keyCompromise (0x1)
       
   308     // This Update: Aug 16 05:03:27 2019 GMT
       
   309     // Next Update: Aug 17 05:03:27 2019 GMT
       
   310     static final String BAD_GUY_OCSP_PEM =
       
   311         "MIIGlAoBAKCCBo0wggaJBgkrBgEFBQcwAQEEggZ6MIIGdjCB5qEvMC0xEDAOBgNV\n" +
       
   312         "BAoMB1Rlc3RQS0kxGTAXBgNVBAMMEENBMSBJbnRlcm1lZGlhdGUYDzIwMTkwODE2\n" +
       
   313         "MDUwMzI3WjB9MHswPTAJBgUrDgMCGgUABBT+SNWbr2JHc1Sa4gmqFP0g3Oa49AQU\n" +
       
   314         "mtpA0z5braXCrNxIRzpWM1cBpJoCBAEAABahFhgPMjAxOTA4MTYwNDU5MzFaoAMK\n" +
       
   315         "AQEYDzIwMTkwODE2MDUwMzI3WqARGA8yMDE5MDgxNzA1MDMyN1qhIzAhMB8GCSsG\n" +
       
   316         "AQUFBzABAgQSBBBbPvAp5xnQ39vLywYMAWbPMA0GCSqGSIb3DQEBCwUAA4IBAQBX\n" +
       
   317         "Ii5GX3Nu9Jqk5ARv+hXlYoJMia+cy02AcVcQiPE250dtNu7tfkX4FhtCDtN+HqqB\n" +
       
   318         "xYUEBk95KPXZiLt7Dla9B38KC5i5gscGBPUW2tGa2wFyqXkG+blPasOc+O5DlvUU\n" +
       
   319         "294HpH3QIVKnZioGpfIHR8h5sa0CGaXykEK4qyjw7IWD7mf5xQZflwE50Ez/0nDi\n" +
       
   320         "NhN+MOp8kfHNfgQmzbx3dLL8LT1j5qdQ9cdkdXwn+DF6v6SJXwn/hOdFDUr4eZ7L\n" +
       
   321         "RAzgaAKvL6DbOGWtnw7fifx++agTzQWkjAto4ekTkzyHK74mqBuyT/6vkgppcPuD\n" +
       
   322         "osE9qhBxWJYQsqWNydXEoIIEdTCCBHEwggRtMIICVaADAgECAgIBADANBgkqhkiG\n" +
       
   323         "9w0BAQsFADAlMRAwDgYDVQQKDAdUZXN0UEtJMREwDwYDVQQDDAhUZXN0Um9vdDAe\n" +
       
   324         "Fw0xNTA1MDYwNjAwMDBaFw0yNTAxMjExMjAwMDBaMC0xEDAOBgNVBAoMB1Rlc3RQ\n" +
       
   325         "S0kxGTAXBgNVBAMMEENBMSBJbnRlcm1lZGlhdGUwggEiMA0GCSqGSIb3DQEBAQUA\n" +
       
   326         "A4IBDwAwggEKAoIBAQC10qMGl64kkS92LjAwYcTnLuKde4O8wKOSMVG/1c4fbQFU\n" +
       
   327         "AgMxMx4gHKTo1Alh55pNEZdNrBk3z9xpe1C6qxEbP+ra9r8j4Dkci+276+6N1WSy\n" +
       
   328         "7Ztpp8YzRCXwZ3OPwx0sZv6QYWOL8Vd/7Y8vxR+meZSKQs3vbyUX1vNwDTjojwHj\n" +
       
   329         "dKuIUl5g6Us98T/KM2Dl5xx0w8MHDuEpA9Vtd+lyZZEmb+8aUJHfxF3tx5gXf9y1\n" +
       
   330         "//QnwNpvur3whOkf2rk0UP6jY0lmgWrscE90ZMgnvebdY/MtGtT4k8PvGz3CCa65\n" +
       
   331         "GrqFT+U9J3kglKQn9zJeSZrVHAE7guatTZpYMaE3AgMBAAGjgZ4wgZswHQYDVR0O\n" +
       
   332         "BBYEFJraQNM+W62lwqzcSEc6VjNXAaSaMB8GA1UdIwQYMBaAFPBYgi5QQCd4Bcl6\n" +
       
   333         "53eKhqSZODfbMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMDgGCCsG\n" +
       
   334         "AQUFBwEBBCwwKjAoBggrBgEFBQcwAYYcaHR0cDovL2ppYW4ub3N0YXBsZS5vcmc6\n" +
       
   335         "NzEwMDANBgkqhkiG9w0BAQsFAAOCAgEANGiCKcoWKAs4rPU0k3zrDrp4/evgP/lC\n" +
       
   336         "rz4b0OJqyZOEtB9pVgG+5pH2QvcP1WvUQRdEaYLExMd61bRJD9Kwx5FsF/wiFyTg\n" +
       
   337         "w54AL1wzKy+01+OnDFoCHrMXltfimOPfeAmmM8s0Bmu7T2tIXQYij0LE+H2sE6Sa\n" +
       
   338         "22uc8NfustH33raL8/gofIeScYzuBjRTzx126CQA2IUiIB8FEYXPcCoyIyLdU/lJ\n" +
       
   339         "MI/STRpv9+uR6/oL+qre2HiBD8GiD/lhqha/MYCztChDv6vQEhFmEbvVZAoPhjHV\n" +
       
   340         "rjdGcbe0U8sXOeTSh16Hyyv8Ijcf/5t7LIkt3TYCm6NmgB8wfNNyr/buY7Vm8Dmp\n" +
       
   341         "K3jCxvuCzCchjBdslkEFGiLEYUPtU/Q0RdESWOkS4YgjLaWQdvnA1Xc4QyYCagrD\n" +
       
   342         "HUZdZdF9BEeqfV/b9ctgicODS7274bpRfd52fqvA/6+UhfYLHioL/JfjODtjExcL\n" +
       
   343         "CuiX3X/vC6CRQY+OZTqqYr5O27Bk1AbbC0IHgUldrRhnIN3tT8UfudZm0b0GDOku\n" +
       
   344         "K33SELj6blXgT/sjqyW/DGmQTvLQ2O62PL+py6KXqKas5H9qm7BPV5wCbKObVSak\n" +
       
   345         "o8svNicToC1Io5Od0ZraI3I8Oux4UvLtNQX9+D929njo6ai5Jfe6kAVGe+ldhfBJ\n" +
       
   346         "BFDZL7ASduk=";
       
   347 
       
   348     // Saturday, August 17, 2019 2:00:00 AM GMT
       
   349     static final Date VALID_DATE = new Date(1566007200000L);
       
   350 
       
   351     public static void main(String[] args) throws Exception {
       
   352         CertificateFactory certFac = CertificateFactory.getInstance("X.509");
       
   353         CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
       
   354         X509Certificate goodGuyCert = getCert(certFac, GOOD_SERVER_PEM);
       
   355         X509Certificate badGuyCert = getCert(certFac, BAD_SERVER_PEM);
       
   356         X509Certificate intCACert = getCert(certFac, INT_CA_PEM);
       
   357         X509Certificate rootCACert = getCert(certFac, ROOT_CA_PEM);
       
   358         byte[] goodOcspDer = pemToDer(GOOD_GUY_OCSP_PEM);
       
   359         byte[] badOcspDer = pemToDer(BAD_GUY_OCSP_PEM);
       
   360         byte[] intCAOcspDer = pemToDer(INT_CA_OCSP_PEM);
       
   361         Set<TrustAnchor> trustAnchors =
       
   362                 Set.of(new TrustAnchor(rootCACert, null));
       
   363         PKIXRevocationChecker pkrc;
       
   364         PKIXBuilderParameters pkixParams;
       
   365 
       
   366         X509Certificate[] goodPath = { goodGuyCert, intCACert,
       
   367             rootCACert };
       
   368         X509Certificate[] badPath = { badGuyCert, intCACert,
       
   369             rootCACert };
       
   370 
       
   371         List<byte[]> goodResponses = List.of(goodOcspDer, intCAOcspDer);
       
   372         List<byte[]> badResponses = List.of(badOcspDer, intCAOcspDer);
       
   373 
       
   374         // Test 1: Path validation with revocation explicitly turned
       
   375         // off, expected to pass.
       
   376         pkixParams = new PKIXBuilderParameters(trustAnchors, null);
       
   377         pkixParams.setRevocationEnabled(false);
       
   378         validatePath(goodPath, Collections.emptyList(), pkixParams, null);
       
   379 
       
   380         // Test 2: Path validation with revocation turned on using the
       
   381         // good path.  Should fail due to no responses.
       
   382         pkixParams = new PKIXBuilderParameters(trustAnchors, null);
       
   383         pkixParams.setDate(VALID_DATE);
       
   384         validatePath(goodPath, Collections.emptyList(), pkixParams,
       
   385             new CertPathValidatorException("KABOOM! No OCSP Responses!", null,
       
   386             certFac.generateCertPath(List.of(goodGuyCert, intCACert)), 1,
       
   387             BasicReason.UNDETERMINED_REVOCATION_STATUS));
       
   388 
       
   389         // Test 3: Path validation of the good path with revocation turned
       
   390         // on and available valid OCSP responses delivered through the
       
   391         // List<byte[]> rather than via the PKIXRevocationChecker.
       
   392         pkixParams = new PKIXBuilderParameters(trustAnchors, null);
       
   393         pkixParams.setDate(VALID_DATE);
       
   394         pkrc = (PKIXRevocationChecker)cpv.getRevocationChecker();
       
   395         pkixParams.addCertPathChecker(pkrc);
       
   396         validatePath(goodPath, goodResponses, pkixParams, null);
       
   397 
       
   398         // Test 4: Path validation of the bad path with revocation explicitly
       
   399         // disabled and valid OCSP responses provided through the PKIXRevocationChecker
       
   400         // indicating a revoked certificate.  Even with the
       
   401         // setRevocationEnabled method set to false this should perform
       
   402         // revocation checking and catch the revoked certificate.
       
   403         pkixParams = new PKIXBuilderParameters(trustAnchors, null);
       
   404         pkixParams.setDate(VALID_DATE);
       
   405         pkixParams.setRevocationEnabled(false);
       
   406         pkrc = (PKIXRevocationChecker)cpv.getRevocationChecker();
       
   407         pkrc.setOcspResponses(Map.of(badGuyCert, badOcspDer,
       
   408                 intCACert, intCAOcspDer));
       
   409         pkixParams.addCertPathChecker(pkrc);
       
   410         validatePath(badPath, Collections.emptyList(), pkixParams,
       
   411                 new CertPathValidatorException("Ouch!", null,
       
   412                 certFac.generateCertPath(List.of(badGuyCert, intCACert)), 0,
       
   413                 BasicReason.REVOKED));
       
   414 
       
   415         // Test 5: This is the same basic setup as test 4, but instead of
       
   416         // delivering the OCSP responses via the PKIXRevocationChecker use
       
   417         // the third parameter (List<byte[]>) for the Validator.validate()
       
   418         // call.  Revocation checking should be performed.
       
   419         pkixParams = new PKIXBuilderParameters(trustAnchors, null);
       
   420         pkixParams.setDate(VALID_DATE);
       
   421         pkixParams.setRevocationEnabled(false);
       
   422         pkrc = (PKIXRevocationChecker)cpv.getRevocationChecker();
       
   423         pkixParams.addCertPathChecker(pkrc);
       
   424         validatePath(badPath, badResponses, pkixParams,
       
   425                 new CertPathValidatorException("Ouch!", null,
       
   426                 certFac.generateCertPath(List.of(badGuyCert, intCACert)), 0,
       
   427                 BasicReason.REVOKED));
       
   428     }
       
   429 
       
   430     static void validatePath(X509Certificate[] path, List<byte[]> responses,
       
   431             PKIXBuilderParameters params, Exception expectedExc) {
       
   432         try {
       
   433             Validator val = Validator.getInstance(Validator.TYPE_PKIX,
       
   434                     Validator.VAR_TLS_SERVER, params);
       
   435             val.validate(path, null, responses, null, "RSA");
       
   436             if (expectedExc != null) {
       
   437                 // We expected to receive an exception here
       
   438                 throw new RuntimeException("Did not receive expected " +
       
   439                         expectedExc.getClass().getName());
       
   440             }
       
   441         } catch (CertificateException certExc) {
       
   442             if (expectedExc == null) {
       
   443                 // This test was supposed to pass, so wrap it in a Runtime
       
   444                 throw new RuntimeException("Received unexpected exception: ",
       
   445                         certExc);
       
   446             } else {
       
   447                 Throwable cause = certExc.getCause();
       
   448                 if (cause == null) {
       
   449                     throw new RuntimeException("Missing expected cause: " +
       
   450                             expectedExc.getClass().getName(),
       
   451                             certExc);
       
   452                 } else {
       
   453                     verifyCause(cause, expectedExc);
       
   454                 }
       
   455             }
       
   456         }
       
   457     }
       
   458 
       
   459     static void verifyCause(Throwable cause, Throwable expectedExc) {
       
   460         if (cause.getClass() != expectedExc.getClass()) {
       
   461             throw new RuntimeException("Exception class mismatch: expected = " +
       
   462                     expectedExc.getClass().getName() + ", actual = " +
       
   463                     cause.getClass().getName());
       
   464         } else if (cause instanceof CertPathValidatorException) {
       
   465             CertPathValidatorException actual =
       
   466                     (CertPathValidatorException)cause;
       
   467             CertPathValidatorException expected =
       
   468                     (CertPathValidatorException)expectedExc;
       
   469             // The failure index and reason should be the same
       
   470             if (actual.getIndex() != expected.getIndex() ||
       
   471                     actual.getReason() != expected.getReason()) {
       
   472                 throw new RuntimeException("CertPathValidatorException " +
       
   473                         "differs from expected.  Expected: index = " +
       
   474                         expected.getIndex() + ", reason = " +
       
   475                         expected.getReason() + ", Actual: index = " +
       
   476                         actual.getIndex() + ", reason = " +
       
   477                         actual.getReason(), actual);
       
   478             }
       
   479         }
       
   480     }
       
   481 
       
   482     static X509Certificate getCert(CertificateFactory fac, String pemCert) {
       
   483         try {
       
   484             ByteArrayInputStream bais =
       
   485                     new ByteArrayInputStream(pemCert.getBytes("UTF-8"));
       
   486             return (X509Certificate)fac.generateCertificate(bais);
       
   487         } catch (UnsupportedEncodingException | CertificateException exc) {
       
   488             throw new RuntimeException(exc);
       
   489         }
       
   490     }
       
   491 
       
   492     static byte[] pemToDer(String pemData) {
       
   493         Base64.Decoder b64Dec = Base64.getMimeDecoder();
       
   494         return b64Dec.decode(pemData);
       
   495     }
       
   496 }