1 /*
   2  * Copyright (c) 2012, 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 7166570
  27  * @summary JSSE certificate validation has started to fail for
  28  *     certificate chains
  29  *
  30  *     SunJSSE does not support dynamic system properties, no way to re-use
  31  *     system properties in samevm/agentvm mode.
  32  * @run main/othervm BasicConstraints PKIX
  33  * @run main/othervm BasicConstraints SunX509
  34  */
  35 
  36 import java.net.*;
  37 import java.util.*;
  38 import java.io.*;
  39 import javax.net.ssl.*;
  40 import java.security.KeyStore;
  41 import java.security.KeyFactory;
  42 import java.security.cert.*;
  43 import java.security.spec.*;
  44 import java.security.interfaces.*;
  45 import java.math.BigInteger;
  46 
  47 import java.util.Base64;
  48 
  49 public class BasicConstraints {
  50 
  51     /*
  52      * =============================================================
  53      * Set the various variables needed for the tests, then
  54      * specify what tests to run on each side.
  55      */
  56 
  57     /*
  58      * Should we run the client or server in a separate thread?
  59      * Both sides can throw exceptions, but do you have a preference
  60      * as to which side should be the main thread.
  61      */
  62     static boolean separateServerThread = true;
  63 
  64     /*
  65      * Where do we find the keystores?
  66      */
  67     // Certificate information:
  68     // Issuer: C=US, O=Java, OU=SunJSSE Test Serivce
  69     // Validity
  70     //     Not Before: May  5 02:40:50 2012 GMT
  71     //     Not After : Apr 15 02:40:50 2033 GMT
  72     // Subject: C=US, O=Java, OU=SunJSSE Test Serivce
  73     // X509v3 Subject Key Identifier:
  74     //     DD:4E:8D:2A:11:C0:83:03:F0:AC:EB:A2:BF:F9:F2:7D:C8:69:1F:9B
  75     // X509v3 Authority Key Identifier:
  76     //     keyid:DD:4E:8D:2A:11:C0:83:03:F0:AC:EB:A2:BF:F9:F2:7D:C8:69:1F:9B
  77     //     DirName:/C=US/O=Java/OU=SunJSSE Test Serivce
  78     //     serial:00
  79     static String trusedCertStr =
  80         "-----BEGIN CERTIFICATE-----\n" +
  81         "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" +
  82         "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
  83         "MTIwNTA1MDI0MDUwWhcNMzMwNDE1MDI0MDUwWjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
  84         "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
  85         "KoZIhvcNAQEBBQADgY0AMIGJAoGBANtiq0AIJK+iVRwFrqcD7fYXTCbMYC5Qz/k6\n" +
  86         "AXBy7/1rI8wDhEJLE3m/+NSqiJwZcmdq2dNh/1fJFrwvzuURbc9+paOBWeHbN+Sc\n" +
  87         "x3huw91oPZme385VpoK3G13rSE114S/rF4DM9mz4EStFhSHXATjtdbskNOAYGLTV\n" +
  88         "x8uEy9GbAgMBAAGjgaUwgaIwHQYDVR0OBBYEFN1OjSoRwIMD8Kzror/58n3IaR+b\n" +
  89         "MGMGA1UdIwRcMFqAFN1OjSoRwIMD8Kzror/58n3IaR+boT+kPTA7MQswCQYDVQQG\n" +
  90         "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
  91         "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" +
  92         "BQADgYEAjjkJesQrkbr36N40egybaIxw7RcqT6iy5fkAGS1JYlBDk8uSCK1o6bCH\n" +
  93         "ls5EpYcGeEoabSS73WRdkO1lgeyWDduO4ef8cCCSpmpT6/YdZG0QS1PtcREeVig+\n" +
  94         "Zr25jNemS4ADHX0aaXP4kiV/G80cR7nX5t5XCUm4bYdbwM07NgI=\n" +
  95         "-----END CERTIFICATE-----";
  96     static String trustedPrivateKey = // Private key in the format of PKCS#8
  97         "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANtiq0AIJK+iVRwF\n" +
  98         "rqcD7fYXTCbMYC5Qz/k6AXBy7/1rI8wDhEJLE3m/+NSqiJwZcmdq2dNh/1fJFrwv\n" +
  99         "zuURbc9+paOBWeHbN+Scx3huw91oPZme385VpoK3G13rSE114S/rF4DM9mz4EStF\n" +
 100         "hSHXATjtdbskNOAYGLTVx8uEy9GbAgMBAAECgYEA2VjHkIiA0ABjkX+PqKeb+VLb\n" +
 101         "fxS7tSca5C8zfdRhLxAWRui0/3ihst0eCJNrBDuxvAOACovsDWyLuaUjtI2v2ysz\n" +
 102         "vz6SPyGy82PhQOFzyKQuQ814N6EpothpiZzF0yFchfKIGhUsdY89UrGs9nM7m6NT\n" +
 103         "rztYvgIu4avg2VPR2AECQQD+pFAqipR2BplQRIuuRSZfHRxvoEyDjT1xnHJsC6WP\n" +
 104         "I5hCLghL91MhQGWbP4EJMKYQOTRVukWlcp2Kycpf+P5hAkEA3I43gmVUAPEdyZdY\n" +
 105         "fatW7OaLlbbYJb6qEtpCZ1Rwe/BIvm6H6E3qSi/lpz7Ia7WDulpbF6BawHH3pRFq\n" +
 106         "CUY5ewJBAP3pUDqrRpBN0jB0uSeDslhjSciQ+dqvSpZv3rSYBHUvlBJhnkpJiy37\n" +
 107         "7ZUZhIxqYxyIPgRBolLwb+FFh7OdL+ECQCtldDic9WVmC+VheRDpCKZ+SlK/8lGi\n" +
 108         "7VXeShiIvcU1JysJFoa35fSI7hf1O3wt7+hX5PqGG7Un94EsJwACKEcCQQC1TWt6\n" +
 109         "ArKH6tRxKjOxFtqfs8fgEVYUaOr3j1jF4KBUuX2mtQtddZe3VfJ2wPsuKMMxmhkB\n" +
 110         "e7xWWZnJsErt2e+E";
 111 
 112     // Certificate information:
 113     // Issuer: C=US, O=Java, OU=SunJSSE Test Serivce
 114     // Validity
 115     //     Not Before: May  5 02:40:53 2012 GMT
 116     //     Not After : Jan 21 02:40:53 2032 GMT
 117     // Subject: C=US, O=Java, OU=SunJSSE Test Serivce, CN=casigner
 118     // X509v3 Subject Key Identifier:
 119     //     13:07:E0:11:07:DB:EB:33:23:87:31:D0:DB:7E:16:56:BE:11:90:0A
 120     // X509v3 Authority Key Identifier:
 121     //     keyid:DD:4E:8D:2A:11:C0:83:03:F0:AC:EB:A2:BF:F9:F2:7D:C8:69:1F:9B
 122     //     DirName:/C=US/O=Java/OU=SunJSSE Test Serivce
 123     //     serial:00
 124     static String caSignerStr =
 125         "-----BEGIN CERTIFICATE-----\n" +
 126         "MIICqDCCAhGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
 127         "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
 128         "MTIwNTA1MDI0MDUzWhcNMzIwMTIxMDI0MDUzWjBOMQswCQYDVQQGEwJVUzENMAsG\n" +
 129         "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxETAPBgNV\n" +
 130         "BAMTCGNhc2lnbmVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+x8+o7oM0\n" +
 131         "ct/LZmZLXBL4CQ8jrULD5P7NtEW0hg/zxBFZfBHf+44Oo2eMPYZj+7xaREOH5BmV\n" +
 132         "KRYlzRtONAaC5Ng4Mrm5UKNPcMIIUjUOvm7vWM4oSTMSfoEcSX+vp99uUAkw3w7Z\n" +
 133         "+frYDm1M4At/j0b+lLij71GFN2L8drpgPQIDAQABo4GoMIGlMB0GA1UdDgQWBBQT\n" +
 134         "B+ARB9vrMyOHMdDbfhZWvhGQCjBjBgNVHSMEXDBagBTdTo0qEcCDA/Cs66K/+fJ9\n" +
 135         "yGkfm6E/pD0wOzELMAkGA1UEBhMCVVMxDTALBgNVBAoTBEphdmExHTAbBgNVBAsT\n" +
 136         "FFN1bkpTU0UgVGVzdCBTZXJpdmNlggEAMBIGA1UdEwEB/wQIMAYBAf8CAQEwCwYD\n" +
 137         "VR0PBAQDAgEGMA0GCSqGSIb3DQEBBAUAA4GBAI+LXA/UCPkTANablUkt80JNPWsl\n" +
 138         "pS4XLNgPxWaN0bkRDs5oI4ooWAz1rwpeJ/nfetOvWlpmrVjSeovBFja5Hl+dUHTf\n" +
 139         "VfuyzkxXbhuNiJIpo1mVBpNsjwu9YRxuwX6UA2LTUQpgvtVJEE012x3zRvxBCbu2\n" +
 140         "Y/v1R5fZ4c+hXDfC\n" +
 141         "-----END CERTIFICATE-----";
 142     static String caSignerPrivateKey = // Private key in the format of PKCS#8
 143         "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL7Hz6jugzRy38tm\n" +
 144         "ZktcEvgJDyOtQsPk/s20RbSGD/PEEVl8Ed/7jg6jZ4w9hmP7vFpEQ4fkGZUpFiXN\n" +
 145         "G040BoLk2DgyublQo09wwghSNQ6+bu9YzihJMxJ+gRxJf6+n325QCTDfDtn5+tgO\n" +
 146         "bUzgC3+PRv6UuKPvUYU3Yvx2umA9AgMBAAECgYBYvu30cW8LONyt62Zua9hPFTe7\n" +
 147         "qt9B7QYyfkdmoG5PQMepTrOp84SzfoOukvgvDm0huFuJnSvhXQl2cCDhkgXskvFj\n" +
 148         "Hh7KBCFViVXokGdq5YoS0/KYMyQV0TZfJUvILBl51uc4/siQ2tClC/N4sa+1JhgW\n" +
 149         "a6dFGfRjiUKSSlmMwQJBAPWpIz3Q/c+DYMvoQr5OD8EaYwYIevlTdXb97RnJJh2b\n" +
 150         "UnhB9jrqesJiHYVzPmP0ukyPOXOwlp2T5Am4Kw0LFOkCQQDGz150NoHOp28Mvyc4\n" +
 151         "CTqz/zYzUhy2eCJESl196uyP4N65Y01VYQ3JDww4DlsXiU17tVSbgA9TCcfTYOzy\n" +
 152         "vyw1AkARUky+1hafZCcWGZljK8PmnMKwsTZikCTvL/Zg5BMA8Wu+OQBwpQnk3OAy\n" +
 153         "Aa87gw0DyvGFG8Vy9POWT9sRP1/JAkBqP0hrMvYMSs6+MSn0eHo2151PsAJIQcuO\n" +
 154         "U2/Da1khSzu8N6WMi2GiobgV/RYRbf9KrY2ZzMZjykZQYOxAjopBAkEAghCu38cN\n" +
 155         "aOsW6ueo24uzsWI1FTdE+qWNVEi3RSP120xXBCyhaBjIq4WVSlJK9K2aBaJpit3j\n" +
 156         "iQ5tl6zrLlxQhg==";
 157 
 158     // Certificate information:
 159     // Issuer: C=US, O=Java, OU=SunJSSE Test Serivce, CN=casigner
 160     // Validity
 161     //     Not Before: May  5 02:40:57 2012 GMT
 162     //     Not After : Jan 21 02:40:57 2032 GMT
 163     // Subject: C=US, O=Java, OU=SunJSSE Test Serivce, CN=certissuer
 164     // X509v3 Subject Key Identifier:
 165     //     39:0E:C6:33:B1:50:BC:73:07:31:E5:D8:04:F7:BB:97:55:CF:9B:C8
 166     // X509v3 Authority Key Identifier:
 167     //     keyid:13:07:E0:11:07:DB:EB:33:23:87:31:D0:DB:7E:16:56:BE:11:90:0A
 168     //     DirName:/C=US/O=Java/OU=SunJSSE Test Serivce
 169     //     serial:02
 170     static String certIssuerStr =
 171         "-----BEGIN CERTIFICATE-----\n" +
 172         "MIICvjCCAiegAwIBAgIBAzANBgkqhkiG9w0BAQQFADBOMQswCQYDVQQGEwJVUzEN\n" +
 173         "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxETAP\n" +
 174         "BgNVBAMTCGNhc2lnbmVyMB4XDTEyMDUwNTAyNDA1N1oXDTMyMDEyMTAyNDA1N1ow\n" +
 175         "UDELMAkGA1UEBhMCVVMxDTALBgNVBAoTBEphdmExHTAbBgNVBAsTFFN1bkpTU0Ug\n" +
 176         "VGVzdCBTZXJpdmNlMRMwEQYDVQQDEwpjZXJ0aXNzdWVyMIGfMA0GCSqGSIb3DQEB\n" +
 177         "AQUAA4GNADCBiQKBgQCyz55zinU6kNL/LeiTNiBI0QWYmDG0YTotuC4D75liBNqs\n" +
 178         "7Mmladsh2mTtQUAwmuGaGzaZV25a+cUax0DXZoyBwdbTI09u1bUYsZcaUUKbPoCC\n" +
 179         "HH26e4jLFL4olW13Sv4ZAd57tIYevMw+Fp5f4fLPFGegCJTFlv2Qjpmic/cuvQID\n" +
 180         "AQABo4GpMIGmMB0GA1UdDgQWBBQ5DsYzsVC8cwcx5dgE97uXVc+byDBjBgNVHSME\n" +
 181         "XDBagBQTB+ARB9vrMyOHMdDbfhZWvhGQCqE/pD0wOzELMAkGA1UEBhMCVVMxDTAL\n" +
 182         "BgNVBAoTBEphdmExHTAbBgNVBAsTFFN1bkpTU0UgVGVzdCBTZXJpdmNlggECMBMG\n" +
 183         "A1UdEwEB/wQJMAcBAf8CAgQAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQQFAAOB\n" +
 184         "gQCQTagenCdClT98C+oTJGJrw/dUBD9K3tE6ZJKPMc/2bUia8G5ei1C0eXj4mWG2\n" +
 185         "lu9umR6C90/A6qB050QB2h50qtqxSrkpu+ym1yypauZpg7U3nUY9wZWJNI1vqrQZ\n" +
 186         "pqUMRcXY3iQIVKx+Qj+4/Za1wwFQzpEoGmqRW31V1SdMEw==\n" +
 187         "-----END CERTIFICATE-----";
 188     static String certIssuerPrivateKey = // Private key in the format of PKCS#8
 189         "MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBALLPnnOKdTqQ0v8t\n" +
 190         "6JM2IEjRBZiYMbRhOi24LgPvmWIE2qzsyaVp2yHaZO1BQDCa4ZobNplXblr5xRrH\n" +
 191         "QNdmjIHB1tMjT27VtRixlxpRQps+gIIcfbp7iMsUviiVbXdK/hkB3nu0hh68zD4W\n" +
 192         "nl/h8s8UZ6AIlMWW/ZCOmaJz9y69AgMBAAECgYEAjtew2tgm4gxDojqIauF4VPM1\n" +
 193         "pzsdqd1p3pAdomNLgrQiBLZ8N7oiph6TNb1EjA+OXc+ThFgF/oM9ZDD8qZZwcvjN\n" +
 194         "qDZlpTkFs2TaGcyEZfUaMB45NHVs6Nn+pSkagSNwwy3xeyAct7sQEzGNTDlEwVv5\n" +
 195         "7V9LQutQtBd6xT48KzkCQQDpNRfv2OFNG/6GtzJoO68oJhpnpl2MsYNi4ntRkre/\n" +
 196         "6uXpiCYaDskcrPMRwOOs0m7mxG+Ev+uKnLnSoEMm1GCbAkEAxEmDtiD0Psb8Z9BL\n" +
 197         "ZRb83Jqho3xe2MCAh3xUfz9b/Mhae9dZ44o4OCgQZuwvW1mczF0NtpgZl93BmYa2\n" +
 198         "hTwHhwJBAKHrEj6ep/fA6x0gD2idoATRR94VfbiU+7NpqtO9ecVP0+gsdr/66hn1\n" +
 199         "3yLBeZLh3MxvMTrLgkAQh1i9m0JXjOcCQQClLXAHHegrw+u3uNMZeKTFR+Lp3sk6\n" +
 200         "AZSnbvr0Me9I45kxSeG81x3ENALJecvIRbrrRws5MvmmkNhQR8rkh8WVAkEAk6b+\n" +
 201         "aVtmBgUaTS5+FFlHGHJY9HFrfT1a1C/dwyMuqlmbC3YsBmZaMOlKli5TXNybLff8\n" +
 202         "5KMeGEpXMzgC7AscGA==";
 203 
 204     // Certificate information:
 205     // Issuer: C=US, O=Java, OU=SunJSSE Test Serivce, CN=certissuer
 206     // Validity
 207     //     Not Before: May  5 02:41:01 2012 GMT
 208     //     Not After : Jan 21 02:41:01 2032 GMT
 209     // Subject: C=US, O=Java, OU=SunJSSE Test Serivce, CN=localhost
 210     // X509v3 Subject Key Identifier:
 211     //     AD:C0:2C:4C:E4:C2:2E:A1:BB:5D:92:BE:66:E0:4E:E0:0D:2F:11:EF
 212     // X509v3 Authority Key Identifier:
 213     //     keyid:39:0E:C6:33:B1:50:BC:73:07:31:E5:D8:04:F7:BB:97:55:CF:9B:C8
 214     static String serverCertStr =
 215         "-----BEGIN CERTIFICATE-----\n" +
 216         "MIICjTCCAfagAwIBAgIBBDANBgkqhkiG9w0BAQQFADBQMQswCQYDVQQGEwJVUzEN\n" +
 217         "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEzAR\n" +
 218         "BgNVBAMTCmNlcnRpc3N1ZXIwHhcNMTIwNTA1MDI0MTAxWhcNMzIwMTIxMDI0MTAx\n" +
 219         "WjBPMQswCQYDVQQGEwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNT\n" +
 220         "RSBUZXN0IFNlcml2Y2UxEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0B\n" +
 221         "AQEFAAOBjQAwgYkCgYEAvwaUd7wmBSKqycEstYLWD26vkU08DM39EtaT8wL9HnQ0\n" +
 222         "fgPblwBFI4zdLa2cuYXRZcFUb04N8nrkcpR0D6kkE+AlFAoRWrrZF80B7JTbtEK4\n" +
 223         "1PIeurihXvUT+4MpzGLOojIihMfvM4ufelblD56SInso4WFHm7t4qCln88J1gjkC\n" +
 224         "AwEAAaN4MHYwCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBStwCxM5MIuobtdkr5m4E7g\n" +
 225         "DS8R7zAfBgNVHSMEGDAWgBQ5DsYzsVC8cwcx5dgE97uXVc+byDAnBgNVHSUEIDAe\n" +
 226         "BggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GB\n" +
 227         "AGfwcfdvEG/nSCiAn2MGbYHp34mgF3OA1SJLWUW0LvWJhwm2cn4AXlSoyvbwrkaB\n" +
 228         "IDDCwhJvvc0vUyL2kTx7sqVaFTq3mDs+ktlB/FfH0Pb+i8FE+g+7T42Iw/j0qxHL\n" +
 229         "YmgbrjBQf5WYN1AvBE/rrPt9aOtS3UsqtVGW574b0shW\n" +
 230         "-----END CERTIFICATE-----";
 231     static String serverPrivateKey = // Private key in the format of PKCS#8
 232         "MIICdAIBADANBgkqhkiG9w0BAQEFAASCAl4wggJaAgEAAoGBAL8GlHe8JgUiqsnB\n" +
 233         "LLWC1g9ur5FNPAzN/RLWk/MC/R50NH4D25cARSOM3S2tnLmF0WXBVG9ODfJ65HKU\n" +
 234         "dA+pJBPgJRQKEVq62RfNAeyU27RCuNTyHrq4oV71E/uDKcxizqIyIoTH7zOLn3pW\n" +
 235         "5Q+ekiJ7KOFhR5u7eKgpZ/PCdYI5AgMBAAECf3CscOYvFD3zNMnMJ5LomVqA7w3F\n" +
 236         "gKYM2jlCWAH+wU41PMEXhW6Lujw92jgXL1o+lERwxFzirVdZJWZwKgUSvzP1G0h3\n" +
 237         "fkucq1/UWnToK+8NSXNM/yS8hXbBgSEoJo5f7LKcIi1Ev6doBVofMxs+njzyWKbM\n" +
 238         "Nb7rOLHadghoon0CQQDgQzbzzSN8Dc1YmmylhI5v+0sQRHH0DL7D24k4Weh4vInG\n" +
 239         "EAbt4x8M7ZKEo8/dv0s4hbmNmAnJl93/RRxIyEqLAkEA2g87DiswSQam2pZ8GlrO\n" +
 240         "+w4Qg9mH8uxx8ou2rl0XlHzH1XiTNbkjfY0EZoL7L31BHFk9n11Fb2P85g6ws+Hy\n" +
 241         "ywJAM/xgyLNM/nzUlS128geAXUULaYH0SHaL4isJ7B4rXZGW/mrIsGxtzjlkNYsj\n" +
 242         "rGujrD6TfNc5rZmexIXowJZtcQJBAIww+pCzZ4mrgx5JXWQ8OZHiiu+ZrPOa2+9J\n" +
 243         "r5sOMpi+WGN/73S8oHqZbNjTINZ5OqEVJq8MchWZPQBTNXuQql0CQHEjUzzkCQa3\n" +
 244         "j6JTa2KAdqyvLOx0XF9zcc1gA069uNQI2gPUHS8V215z57f/gMGnDNhVfLs/vMKz\n" +
 245         "sFkVZ3zg7As=";
 246 
 247     // Certificate information:
 248     // Issuer: C=US, O=Java, OU=SunJSSE Test Serivce, CN=certissuer
 249     // Validity
 250     //     Not Before: May  5 02:41:02 2012 GMT
 251     //     Not After : Jan 21 02:41:02 2032 GMT
 252     // Subject: C=US, O=Java, OU=SunJSSE Test Serivce, CN=InterOp Tester
 253     // X509v3 Subject Key Identifier:
 254     //     57:7D:E2:33:33:60:DF:DD:5E:ED:81:3F:EB:F2:1B:59:7F:50:9C:99
 255     // X509v3 Authority Key Identifier:
 256     //     keyid:39:0E:C6:33:B1:50:BC:73:07:31:E5:D8:04:F7:BB:97:55:CF:9B:C8
 257     static String clientCertStr =
 258         "-----BEGIN CERTIFICATE-----\n" +
 259         "MIICaTCCAdKgAwIBAgIBBTANBgkqhkiG9w0BAQQFADBQMQswCQYDVQQGEwJVUzEN\n" +
 260         "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEzAR\n" +
 261         "BgNVBAMTCmNlcnRpc3N1ZXIwHhcNMTIwNTA1MDI0MTAyWhcNMzIwMTIxMDI0MTAy\n" +
 262         "WjBUMQswCQYDVQQGEwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNT\n" +
 263         "RSBUZXN0IFNlcml2Y2UxFzAVBgNVBAMTDkludGVyT3AgVGVzdGVyMIGfMA0GCSqG\n" +
 264         "SIb3DQEBAQUAA4GNADCBiQKBgQC1pA71nDg1KhhnHjRdi/eVDUa7uFZAtN8R9huu\n" +
 265         "pTwFoyqSX8lDMz8jDawOMmaI9dVZLjTh3hnf4KBEqQOearFVz45yBOjlgPLBuI4F\n" +
 266         "D/ORhgmDaIu2NK+c1yj6YQlyiO0DPwh55GtPLVG3iuEpejU7gQyaMuTaddoXrO7s\n" +
 267         "xwzanQIDAQABo08wTTALBgNVHQ8EBAMCA+gwHQYDVR0OBBYEFFd94jMzYN/dXu2B\n" +
 268         "P+vyG1l/UJyZMB8GA1UdIwQYMBaAFDkOxjOxULxzBzHl2AT3u5dVz5vIMA0GCSqG\n" +
 269         "SIb3DQEBBAUAA4GBAHTgB5W7wnl7Jnb4wNQcb6JdR8FRHIdslcRfnReFfZBHZZux\n" +
 270         "ChpA1lf62KIzYohKoxQXXMul86vnVSHnXq5xctHEmxCBnALEnoAcCOv6wfWqEA7g\n" +
 271         "2rX+ydmu+0ArbqKhSOypZ7K3ame0UOJJ6HDxdsgBYJuotmSou4KKq9e8GF+d\n" +
 272         "-----END CERTIFICATE-----";
 273     static String clientPrivateKey = // Private key in the format of PKCS#8
 274         "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALWkDvWcODUqGGce\n" +
 275         "NF2L95UNRru4VkC03xH2G66lPAWjKpJfyUMzPyMNrA4yZoj11VkuNOHeGd/goESp\n" +
 276         "A55qsVXPjnIE6OWA8sG4jgUP85GGCYNoi7Y0r5zXKPphCXKI7QM/CHnka08tUbeK\n" +
 277         "4Sl6NTuBDJoy5Np12hes7uzHDNqdAgMBAAECgYEAjLwygwapXjfhdHQoqpp6F9iT\n" +
 278         "h3sKCVSaybXgOO75lHyZzZO9wv1/288KEm3mmBOxXEm6245UievnAYvaq/GKt93O\n" +
 279         "pj2zRefBzZjGbz0v84fmna/MN6zUUYX1PcVRMKWLx9HKKmQihzwoXdBX0o9PPXdi\n" +
 280         "LfzujNa/q8/mpI5PmEECQQDZwLSaL7OReWZTY4NoQuNzwhx5IKJUOtCFQfmHKZSW\n" +
 281         "wtXntZf+E5W9tGaDY5wjpq5cilKDAHdEAlFWxDe1PoE1AkEA1YuTBpctOLBfquFn\n" +
 282         "Y/S3lzGVlnIHDk3dj4bFglkoJ2bCdlwRNUyBSjAjBDcbYhper8S7GlEN5SiEdz9I\n" +
 283         "3OjIyQJBAKEPMgYhZjYhjxf6sQV7A/VpC9pj0u1uGzGVXNUmYisorUKXRHa/UbBh\n" +
 284         "MLnaAXE1Jh54iRMwUwbQmA0PUQ0T0EkCQQCcr6/umwhkWw2nHYK2Vf5LoudGn15M\n" +
 285         "AZg7UsEjVnXfC0hOfllmCT+ohs96rVCbWAv33lsHAUg3x9YChV3aMbf5AkAj1kuV\n" +
 286         "jUTgFKjediyQC6uof7YdLn+gQGiXK1XE0GBN4WMkzcLiS0jC+MFTgKfFnFdh9K0y\n" +
 287         "fswYKdTA/o8RKaa5";
 288 
 289     static char passphrase[] = "passphrase".toCharArray();
 290 
 291     /*
 292      * Is the server ready to serve?
 293      */
 294     volatile static boolean serverReady = false;
 295 
 296     /*
 297      * Turn on SSL debugging?
 298      */
 299     static boolean debug = false;
 300 
 301     /*
 302      * Define the server side of the test.
 303      *
 304      * If the server prematurely exits, serverReady will be set to true
 305      * to avoid infinite hangs.
 306      */
 307     void doServerSide() throws Exception {
 308         SSLContext context = getSSLContext(true);
 309         SSLServerSocketFactory sslssf = context.getServerSocketFactory();
 310 
 311         SSLServerSocket sslServerSocket =
 312             (SSLServerSocket)sslssf.createServerSocket(serverPort);
 313         serverPort = sslServerSocket.getLocalPort();
 314         SSLSocket sslSocket = null;
 315         try {
 316             /*
 317              * Signal Client, we're ready for his connect.
 318              */
 319             serverReady = true;
 320 
 321             sslSocket = (SSLSocket) sslServerSocket.accept();
 322             sslSocket.setNeedClientAuth(true);
 323 
 324             InputStream sslIS = sslSocket.getInputStream();
 325             OutputStream sslOS = sslSocket.getOutputStream();
 326 
 327             sslIS.read();
 328             sslOS.write(85);
 329             sslOS.flush();
 330         } finally {
 331             if (sslSocket != null) {
 332                 sslSocket.close();
 333             }
 334             sslServerSocket.close();
 335         }
 336     }
 337 
 338     /*
 339      * Define the client side of the test.
 340      *
 341      * If the server prematurely exits, serverReady will be set to true
 342      * to avoid infinite hangs.
 343      */
 344     void doClientSide() throws Exception {
 345         /*
 346          * Wait for server to get started.
 347          */
 348         while (!serverReady) {
 349             Thread.sleep(50);
 350         }
 351 
 352         SSLContext context = getSSLContext(false);
 353         SSLSocketFactory sslsf = context.getSocketFactory();
 354 
 355         SSLSocket sslSocket =
 356             (SSLSocket)sslsf.createSocket("localhost", serverPort);
 357         try {
 358             InputStream sslIS = sslSocket.getInputStream();
 359             OutputStream sslOS = sslSocket.getOutputStream();
 360 
 361             sslOS.write(280);
 362             sslOS.flush();
 363             sslIS.read();
 364         } finally {
 365             sslSocket.close();
 366         }
 367     }
 368 
 369     // get the ssl context
 370     private static SSLContext getSSLContext(boolean isServer) throws Exception {
 371 
 372         // generate certificate from cert string
 373         CertificateFactory cf = CertificateFactory.getInstance("X.509");
 374 
 375         // create a key store
 376         KeyStore ks = KeyStore.getInstance("JKS");
 377         ks.load(null, null);
 378 
 379         // import the trused cert
 380         ByteArrayInputStream is =
 381             new ByteArrayInputStream(trusedCertStr.getBytes());
 382         Certificate trusedCert = cf.generateCertificate(is);
 383         is.close();
 384 
 385         ks.setCertificateEntry("SunJSSE Test Serivce", trusedCert);
 386 
 387         // import the certificate chain and key
 388         Certificate[] chain = new Certificate[3];
 389 
 390         is = new ByteArrayInputStream(caSignerStr.getBytes());
 391         Certificate caSignerCert = cf.generateCertificate(is);
 392         is.close();
 393         chain[2] = caSignerCert;
 394 
 395         is = new ByteArrayInputStream(certIssuerStr.getBytes());
 396         Certificate certIssuerCert = cf.generateCertificate(is);
 397         is.close();
 398         chain[1] = certIssuerCert;
 399 
 400         PKCS8EncodedKeySpec priKeySpec = null;
 401         if (isServer) {
 402             priKeySpec = new PKCS8EncodedKeySpec(
 403                             Base64.getMimeDecoder().decode(serverPrivateKey));
 404             is = new ByteArrayInputStream(serverCertStr.getBytes());
 405         } else {
 406             priKeySpec = new PKCS8EncodedKeySpec(
 407                             Base64.getMimeDecoder().decode(clientPrivateKey));
 408             is = new ByteArrayInputStream(clientCertStr.getBytes());
 409         }
 410         KeyFactory kf = KeyFactory.getInstance("RSA");
 411         RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec);
 412         Certificate keyCert = cf.generateCertificate(is);
 413         is.close();
 414         chain[0] = keyCert;
 415 
 416         ks.setKeyEntry("End Entity", priKey, passphrase, chain);
 417 
 418         // check the certification path
 419         PKIXParameters paras = new PKIXParameters(ks);
 420         paras.setRevocationEnabled(false);
 421         CertPath path = cf.generateCertPath(Arrays.asList(chain));
 422         CertPathValidator cv = CertPathValidator.getInstance("PKIX");
 423         cv.validate(path, paras);
 424 
 425         // create SSL context
 426         TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
 427         tmf.init(ks);
 428 
 429         SSLContext ctx = SSLContext.getInstance("TLS");
 430         KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
 431         kmf.init(ks, passphrase);
 432 
 433         ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
 434         ks = null;
 435 
 436         return ctx;
 437     }
 438 
 439     private static String tmAlgorithm;        // trust manager
 440 
 441     private static void parseArguments(String[] args) {
 442         tmAlgorithm = args[0];
 443     }
 444 
 445     /*
 446      * =============================================================
 447      * The remainder is just support stuff
 448      */
 449 
 450     // use any free port by default
 451     volatile int serverPort = 0;
 452 
 453     volatile Exception serverException = null;
 454     volatile Exception clientException = null;
 455 
 456     public static void main(String args[]) throws Exception {
 457         if (debug)
 458             System.setProperty("javax.net.debug", "all");
 459 
 460 
 461         /*
 462          * Get the customized arguments.
 463          */
 464         parseArguments(args);
 465 
 466         /*
 467          * Start the tests.
 468          */
 469         new BasicConstraints();
 470     }
 471 
 472     Thread clientThread = null;
 473     Thread serverThread = null;
 474     /*
 475      * Primary constructor, used to drive remainder of the test.
 476      *
 477      * Fork off the other side, then do your work.
 478      */
 479     BasicConstraints() throws Exception {
 480         if (separateServerThread) {
 481             startServer(true);
 482             startClient(false);
 483         } else {
 484             startClient(true);
 485             startServer(false);
 486         }
 487 
 488         /*
 489          * Wait for other side to close down.
 490          */
 491         if (separateServerThread) {
 492             serverThread.join();
 493         } else {
 494             clientThread.join();
 495         }
 496 
 497         /*
 498          * When we get here, the test is pretty much over.
 499          *
 500          * If the main thread excepted, that propagates back
 501          * immediately.  If the other thread threw an exception, we
 502          * should report back.
 503          */
 504         if (serverException != null)
 505             throw serverException;
 506         if (clientException != null)
 507             throw clientException;
 508     }
 509 
 510     void startServer(boolean newThread) throws Exception {
 511         if (newThread) {
 512             serverThread = new Thread() {
 513                 public void run() {
 514                     try {
 515                         doServerSide();
 516                     } catch (Exception e) {
 517                         /*
 518                          * Our server thread just died.
 519                          *
 520                          * Release the client, if not active already...
 521                          */
 522                         System.err.println("Server died...");
 523                         serverReady = true;
 524                         serverException = e;
 525                     }
 526                 }
 527             };
 528             serverThread.start();
 529         } else {
 530             doServerSide();
 531         }
 532     }
 533 
 534     void startClient(boolean newThread) throws Exception {
 535         if (newThread) {
 536             clientThread = new Thread() {
 537                 public void run() {
 538                     try {
 539                         doClientSide();
 540                     } catch (Exception e) {
 541                         /*
 542                          * Our client thread just died.
 543                          */
 544                         System.err.println("Client died...");
 545                         clientException = e;
 546                     }
 547                 }
 548             };
 549             clientThread.start();
 550         } else {
 551             doClientSide();
 552         }
 553     }
 554 
 555 }