1 /*
   2  * Copyright (c) 2005, 2017, 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  *
  26  *
  27  * @summary Testing keytool
  28  * @author weijun.wang
  29  *
  30  * Run through autotest.sh and manualtest.sh
  31  *
  32  * Testing non-PKCS11 keystores:
  33  *       echo | java -Dfile KeyToolTest
  34  *
  35  * Testing NSS PKCS11 keystores:
  36  *       # testing NSS
  37  *       # make sure the NSS db files are in current directory and writable
  38  *       echo | java -Dnss -Dnss.lib=/path/to/libsoftokn3.so KeyToolTest
  39  *
  40  * Testing Solaris Cryptography Framework PKCS11 keystores:
  41  *       # make sure you've already run pktool and set test12 as pin
  42  *       echo | java -Dsolaris KeyToolTest
  43  *
  44  * ATTENTION:
  45  * Exception in thread "main" java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_KEY_SIZE_RANGE
  46  *       at sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:420)
  47  *       ...
  48  * Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_KEY_SIZE_RANGE
  49  *       at sun.security.pkcs11.wrapper.PKCS11.C_SignFinal(Native Method)
  50  *       at sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:391)
  51  *       ...
  52  * been observed. Possibly a Solaris bug
  53  *
  54  * ATTENTION:
  55  * NSS PKCS11 config file are changed, DSA not supported now.
  56  */
  57 
  58 import java.nio.file.Files;
  59 import java.nio.file.Paths;
  60 import java.security.KeyStore;
  61 import sun.security.x509.*;
  62 import java.io.*;
  63 import java.security.KeyPairGenerator;
  64 import java.security.NoSuchAlgorithmException;
  65 import java.util.*;
  66 import java.security.cert.X509Certificate;
  67 import sun.security.util.ObjectIdentifier;
  68 
  69 public class KeyToolTest {
  70 
  71     // The stdout and stderr outputs after a keytool run
  72     String out;
  73     String err;
  74 
  75     // the output of println() in KeyTool.run
  76     String ex;
  77 
  78     String lastInput = "", lastCommand = "";
  79     private static final boolean debug =
  80         System.getProperty("debug") != null;
  81 
  82     static final String NSS_P11_ARG =
  83             "-keystore NONE -storetype PKCS11 -providerName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt ";
  84     static final String NSS_SRC_P11_ARG =
  85             "-srckeystore NONE -srcstoretype PKCS11 -srcproviderName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt ";
  86     static final String NZZ_P11_ARG =
  87             "-keystore NONE -storetype PKCS11 -providerName SunPKCS11-nzz -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nzz.txt ";
  88     static final String NZZ_SRC_P11_ARG =
  89             "-srckeystore NONE -srcstoretype PKCS11 -srcproviderName SunPKCS11-nzz -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nzz.txt ";
  90     static final String SUN_P11_ARG = "-keystore NONE -storetype PKCS11 ";
  91     static final String SUN_SRC_P11_ARG = "-srckeystore NONE -srcstoretype PKCS11 ";
  92 
  93     String p11Arg, srcP11Arg;
  94 
  95     /** Creates a new instance of KeyToolTest */
  96     KeyToolTest() {
  97         // so that there is "Warning" and not translated into other language
  98         Locale.setDefault(Locale.US);
  99     }
 100 
 101     /**
 102      * Helper, removes a file
 103      */
 104     void remove(String filename) {
 105         if (debug) {
 106             System.err.println("Removing " + filename);
 107         }
 108         new File(filename).delete();
 109         if (new File(filename).exists()) {
 110             throw new RuntimeException("Error deleting " + filename);
 111         }
 112     }
 113 
 114     /**
 115      * Run a set of keytool command with given terminal input.
 116      * @param input the terminal inputs, the characters typed by human
 117      *        if <code>cmd</code> is running on a terminal
 118      * @param cmd the argument of a keytool command line
 119      * @throws if keytool goes wrong in some place
 120      */
 121     void test(String input, String cmd) throws Exception {
 122         lastInput = input;
 123         lastCommand = cmd;
 124 
 125         // "X" is appended so that we can precisely test how input is consumed
 126         HumanInputStream in = new HumanInputStream(input+"X");
 127         test(in, cmd);
 128         // make sure the input string is no more no less
 129         if(in.read() != 'X' || in.read() != -1)
 130             throw new Exception("Input not consumed exactly");
 131     }
 132 
 133     void test(InputStream in, String cmd) throws Exception {
 134 
 135         // save the original 3 streams
 136         if (debug) {
 137             System.err.println(cmd);
 138         } else {
 139             System.err.print(".");
 140         }
 141         PrintStream p1 = System.out;
 142         PrintStream p2 = System.err;
 143         InputStream i1 = System.in;
 144 
 145         ByteArrayOutputStream b1 = new ByteArrayOutputStream();
 146         ByteArrayOutputStream b2 = new ByteArrayOutputStream();
 147 
 148         try {
 149             System.setIn(in);
 150             System.setOut(new PrintStream(b1));
 151             System.setErr(new PrintStream(b2));
 152 
 153             // since System.in is overrided, the
 154             // sun.security.tools.keytool.Main.main() method will
 155             // never block at user input
 156 
 157             // use -debug so that main() will throw an Exception
 158             // instead of calling System.exit()
 159             sun.security.tools.keytool.Main.main(("-debug "+cmd).split("\\s+"));
 160         } finally {
 161             out = b1.toString();
 162             err = b2.toString();
 163             ex = out;   // now it goes to System.out
 164             System.setIn(i1);
 165             System.setOut(p1);
 166             System.setErr(p2);
 167         }
 168     }
 169 
 170     /**
 171      * Call this method if you expect test(input, cmd) should go OK
 172      */
 173     void testOK(String input, String cmd) throws Exception {
 174         try {
 175             // Workaround for "8057810: Make SHA256withDSA the default
 176             // jarsigner and keytool algorithm for DSA keys". Unfortunately
 177             // SunPKCS11-NSS does not support SHA256withDSA yet.
 178             if (cmd.contains("p11-nss.txt") && cmd.contains("-genkey")
 179                     && !cmd.contains("-keyalg")) {
 180                 cmd += " -sigalg SHA1withDSA -keysize 1024";
 181             }
 182             test(input, cmd);
 183         } catch(Exception e) {
 184             afterFail(input, cmd, "OK");
 185             throw e;
 186         }
 187     }
 188 
 189     /**
 190      * Call this method if you expect test(input, cmd) should fail and throw
 191      * an exception
 192      */
 193     void testFail(String input, String cmd) throws Exception {
 194         boolean ok;
 195         try {
 196             test(input, cmd);
 197             ok = true;
 198         } catch(Exception e) {
 199             if (e instanceof MissingResourceException) {
 200                 ok = true;
 201             } else {
 202                 ok = false;
 203             }
 204         }
 205         if(ok) {
 206             afterFail(input, cmd, "FAIL");
 207             throw new RuntimeException();
 208         }
 209     }
 210 
 211     /**
 212      * Call this method if you expect test(input, cmd) should go OK
 213      */
 214     void testOK(InputStream is, String cmd) throws Exception {
 215         try {
 216             test(is, cmd);
 217         } catch(Exception e) {
 218             afterFail("", cmd, "OK");
 219             throw e;
 220         }
 221     }
 222 
 223     /**
 224      * Call this method if you expect test(input, cmd) should fail and throw
 225      * an exception
 226      */
 227     void testFail(InputStream is, String cmd) throws Exception {
 228         boolean ok;
 229         try {
 230             test(is, cmd);
 231             ok = true;
 232         } catch(Exception e) {
 233             ok = false;
 234         }
 235         if(ok) {
 236             afterFail("", cmd, "FAIL");
 237             throw new RuntimeException();
 238         }
 239     }
 240 
 241     /**
 242      * Call this method if you just want to run the command and does
 243      * not care if it succeeds or fails.
 244      */
 245     void testAnyway(String input, String cmd) {
 246         try {
 247             test(input, cmd);
 248         } catch(Exception e) {
 249             ;
 250         }
 251     }
 252 
 253     /**
 254      * Helper method, print some output after a test does not do as expected
 255      */
 256     void afterFail(String input, String cmd, String should) {
 257         if (cmd.contains("p11-nss.txt")) {
 258             cmd = "-J-Dnss.lib=" + System.getProperty("nss.lib") + " " + cmd;
 259         }
 260         System.err.println("\nTest fails for the command ---\n" +
 261                 "keytool " + cmd + "\nOr its debug version ---\n" +
 262                 "keytool -debug " + cmd);
 263 
 264         System.err.println("The command result should be " + should +
 265                 ", but it's not. Try run the command manually and type" +
 266                 " these input into it: ");
 267         char[] inputChars = input.toCharArray();
 268 
 269         for (int i=0; i<inputChars.length; i++) {
 270             char ch = inputChars[i];
 271             if (ch == '\n') System.err.print("ENTER ");
 272             else if (ch == ' ') System.err.print("SPACE ");
 273             else System.err.print(ch + " ");
 274         }
 275         System.err.println("");
 276 
 277         System.err.println("ERR is:\n"+err);
 278         System.err.println("OUT is:\n"+out);
 279     }
 280 
 281     void assertTrue(boolean bool, String msg) {
 282         if (debug) {
 283             System.err.println("If not " + bool + ", " + msg);
 284         } else {
 285             System.err.print("v");
 286         }
 287         if(!bool) {
 288             afterFail(lastInput, lastCommand, "TRUE");
 289                 System.err.println(msg);
 290             throw new RuntimeException(msg);
 291         }
 292     }
 293 
 294     void assertTrue(boolean bool) {
 295         assertTrue(bool, "well...");
 296     }
 297     /**
 298      * Helper method, load a keystore
 299      * @param file file for keystore, null or "NONE" for PKCS11
 300      * @pass password for the keystore
 301      * @type keystore type
 302      * @returns the KeyStore object
 303      * @exception Exception if anything goes wrong
 304      */
 305     KeyStore loadStore(String file, String pass, String type) throws Exception {
 306         KeyStore ks = KeyStore.getInstance(type);
 307         FileInputStream is = null;
 308         if (file != null && !file.equals("NONE")) {
 309             is = new FileInputStream(file);
 310         }
 311         ks.load(is, pass.toCharArray());
 312         is.close();
 313         return ks;
 314     }
 315 
 316     /**
 317      * The test suite.
 318      * Maybe it's better to put this outside the KeyToolTest class
 319      */
 320     void testAll() throws Exception {
 321         KeyStore ks;
 322 
 323         remove("x.jks");
 324         remove("x.jceks");
 325         remove("x.p12");
 326         remove("x2.jceks");
 327         remove("x2.jks");
 328         remove("x.jks.p1.cert");
 329 
 330         // name changes: genkeypair, importcert, exportcert
 331         remove("x.jks");
 332         remove("x.jks.p1.cert");
 333         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -alias p1 -dname CN=olala");
 334         testOK("", "-keystore x.jks -storepass changeit -exportcert -alias p1 -file x.jks.p1.cert");
 335         ks = loadStore("x.jks", "changeit", "JKS");
 336         assertTrue(ks.getKey("p1", "changeit".toCharArray()) != null,
 337             "key not DSA");
 338         assertTrue(new File("x.jks.p1.cert").exists(), "p1 export err");
 339         testOK("", "-keystore x.jks -storepass changeit -delete -alias p1");
 340         testOK("y\n", "-keystore x.jks -storepass changeit -importcert -alias c1 -file x.jks.p1.cert");  // importcert, prompt for Yes/No
 341         testOK("", "-keystore x.jks -storepass changeit -importcert -alias c2 -file x.jks.p1.cert -noprompt"); // importcert, -noprompt
 342         ks = loadStore("x.jks", "changeit", "JKS");
 343         assertTrue(ks.getCertificate("c1") != null, "import c1 err");
 344 
 345         // v3
 346         byte[] encoded = ks.getCertificate("c1").getEncoded();
 347         X509CertImpl certImpl = new X509CertImpl(encoded);
 348         assertTrue(certImpl.getVersion() == 3, "Version is not 3");
 349 
 350         // changealias and keyclone
 351         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -alias p1 -dname CN=olala");
 352         testOK("changeit\n", "-keystore x.jks -changealias -alias p1 -destalias p11");
 353         testOK("changeit\n", "-keystore x.jks -changealias -alias c1 -destalias c11");
 354         testOK("changeit\n\n", "-keystore x.jks -keyclone -alias p11 -destalias p111"); // press ENTER when prompt for p111's keypass
 355         ks = loadStore("x.jks", "changeit", "JKS");
 356         assertTrue(!ks.containsAlias("p1"), "there is no p1");
 357         assertTrue(!ks.containsAlias("c1"), "there is no c1");
 358         assertTrue(ks.containsAlias("p11"), "there is p11");
 359         assertTrue(ks.containsAlias("c11"), "there is c11");
 360         assertTrue(ks.containsAlias("p111"), "there is p111");
 361 
 362         // genSecKey
 363         remove("x.jceks");
 364         testOK("changeit\nchangeit\n\n", "-keystore x.jceks -storetype JCEKS -genseckey -alias s1"); // DES, no need keysize
 365         testFail("changeit\n\n", "-keystore x.jceks -storetype JCEKS -genseckey -alias s11 -keysize 128"); // DES, keysize cannot be 128
 366         testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS -genseckey -keyalg DESede -alias s2"); // DESede. no need keysize
 367         testFail("changeit\n\n", "-keystore x.jceks -storetype AES -genseckey -keyalg Rijndael -alias s3"); // AES, need keysize
 368         testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS -genseckey -keyalg AES -alias s3 -keysize 128");
 369                 // about keypass
 370         testOK("\n", "-keystore x.jceks -storetype JCEKS -storepass changeit -genseckey -alias s4"); // can accept storepass
 371         testOK("keypass\nkeypass\n", "-keystore x.jceks -storetype JCEKS -storepass changeit -genseckey -alias s5"); // or a new one
 372         testOK("bad\n\bad\nkeypass\nkeypass\n", "-keystore x.jceks -storetype JCEKS -storepass changeit -genseckey -alias s6"); // keypass must be valid (prompt 3 times)
 373         testFail("bad\n\bad\nbad\n", "-keystore x.jceks -storetype JCEKS -storepass changeit -genseckey -alias s7"); // keypass must be valid (prompt 3 times)
 374         testFail("bad\n\bad\nbad\nkeypass\n", "-keystore x.jceks -storetype JCEKS -storepass changeit -genseckey -alias s7"); // keypass must be valid (prompt 3 times)
 375         ks = loadStore("x.jceks", "changeit", "JCEKS");
 376         assertTrue(ks.getKey("s1", "changeit".toCharArray()).getAlgorithm().equalsIgnoreCase("DES"), "s1 is DES");
 377         assertTrue(ks.getKey("s1", "changeit".toCharArray()).getEncoded().length == 8,  "DES is 56");
 378         assertTrue(ks.getKey("s2", "changeit".toCharArray()).getEncoded().length == 24,  "DESede is 168");
 379         assertTrue(ks.getKey("s2", "changeit".toCharArray()).getAlgorithm().equalsIgnoreCase("DESede"), "s2 is DESede");
 380         assertTrue(ks.getKey("s3", "changeit".toCharArray()).getAlgorithm().equalsIgnoreCase("AES"), "s3 is AES");
 381         assertTrue(ks.getKey("s4", "changeit".toCharArray()).getAlgorithm().equalsIgnoreCase("DES"), "s4 is DES");
 382         assertTrue(ks.getKey("s5", "keypass".toCharArray()).getAlgorithm().equalsIgnoreCase("DES"), "s5 is DES");
 383         assertTrue(ks.getKey("s6", "keypass".toCharArray()).getAlgorithm().equalsIgnoreCase("DES"), "s6 is DES");
 384         assertTrue(!ks.containsAlias("s7"), "s7 not created");
 385 
 386         // maybe we needn't test this, one day JKS will support SecretKey
 387         //testFail("changeit\nchangeit\n", "-keystore x.jks -genseckey -keyalg AES -alias s3 -keysize 128");
 388 
 389         // importKeyStore
 390         remove("x.jks");
 391         remove("x.jceks");
 392         testOK("changeit\nchangeit\n\n", "-keystore x.jceks -storetype JCEKS -genkeypair -alias p1 -dname CN=Olala"); // create 2 entries...
 393         testOK("", "-keystore x.jceks -storetype JCEKS -storepass changeit -importcert -alias c1 -file x.jks.p1.cert -noprompt"); // ...
 394         ks = loadStore("x.jceks", "changeit", "JCEKS");
 395         assertTrue(ks.size() == 2, "2 entries in JCEKS");
 396         // import, shouldn't mention destalias/srckeypass/destkeypass if srcalias is no given
 397         testFail("changeit\nchangeit\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -destalias pp");
 398         testFail("changeit\nchangeit\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srckeypass changeit");
 399         testFail("changeit\nchangeit\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -destkeypass changeit");
 400         // normal import
 401         testOK("changeit\nchangeit\nchangeit\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS");
 402         ks = loadStore("x.jks", "changeit", "JKS");
 403         assertTrue(ks.size() == 2, "2 entries in JKS");
 404         // import again, type yes to overwrite old entries
 405         testOK("changeit\nchangeit\ny\ny\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS");
 406         ks = loadStore("x.jks", "changeit", "JKS");
 407         // import again, specify -nopromt
 408         testOK("changeit\nchangeit\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -noprompt");
 409         assertTrue(err.indexOf("Warning") != -1, "noprompt will warn");
 410         ks = loadStore("x.jks", "changeit", "JKS");
 411         assertTrue(ks.size() == 2, "2 entries in JKS");
 412         // import again, type into new aliases when prompted
 413         testOK("changeit\nchangeit\n\ns1\n\ns2\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS");
 414         ks = loadStore("x.jks", "changeit", "JKS");
 415         assertTrue(ks.size() == 4, "4 entries in JKS");
 416 
 417         // importkeystore single
 418         remove("x.jks");
 419         testOK("changeit\nchangeit\nchangeit\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias p1"); // normal
 420         ks = loadStore("x.jks", "changeit", "JKS");
 421         assertTrue(ks.size() == 1, "1 entries in JKS");
 422         testOK("changeit\nchangeit\ny\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias p1"); // overwrite
 423         ks = loadStore("x.jks", "changeit", "JKS");
 424         assertTrue(ks.size() == 1, "1 entries in JKS");
 425         testOK("changeit\nchangeit\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias p1 -noprompt"); // noprompt
 426         ks = loadStore("x.jks", "changeit", "JKS");
 427         assertTrue(ks.size() == 1, "1 entries in JKS");
 428         testOK("changeit\nchangeit\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias p1 -destalias p2"); // rename
 429         ks = loadStore("x.jks", "changeit", "JKS");
 430         assertTrue(ks.size() == 2, "2 entries in JKS");
 431         testOK("changeit\nchangeit\n\nnewalias\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias p1"); // another rename
 432         ks = loadStore("x.jks", "changeit", "JKS");
 433         assertTrue(ks.size() == 3, "3 entries in JKS");
 434 
 435         // importkeystore single, different keypass
 436         remove("x.jks");
 437         testOK("changeit\nkeypass\nkeypass\n", "-keystore x.jceks -storetype JCEKS -genkeypair -alias p2 -dname CN=Olala"); // generate entry with different keypass
 438         testOK("changeit\nchangeit\nchangeit\nkeypass\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias p2"); // prompt
 439         ks = loadStore("x.jks", "changeit", "JKS");
 440         assertTrue(ks.size() == 1, "1 entries in JKS");
 441         testOK("changeit\nchangeit\nkeypass\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias p2 -destalias p3 -destkeypass keypass2"); // diff destkeypass
 442         ks = loadStore("x.jks", "changeit", "JKS");
 443         assertTrue(ks.size() == 2, "2 entries in JKS");
 444         assertTrue(ks.getKey("p2", "keypass".toCharArray()) != null, "p2 has old password");
 445         assertTrue(ks.getKey("p3", "keypass2".toCharArray()) != null, "p3 has new password");
 446 
 447         // importkeystore single, cert
 448         remove("x.jks");
 449         testOK("changeit\nchangeit\nchangeit\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias c1"); // normal
 450         testOK("changeit\n\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias c1 -destalias c2");   // in fact srcstorepass can be ignored
 451         assertTrue(err.indexOf("WARNING") != -1, "But will warn");
 452         testOK("changeit\n\ny\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias c1 -destalias c2");   // 2nd import, press y to overwrite ...
 453         testOK("changeit\n\n\nc3\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias c1 -destalias c2");   // ... or rename
 454         ks = loadStore("x.jks", "changeit", "JKS");
 455         assertTrue(ks.size() == 3, "3 entries in JKS"); // c1, c2, c3
 456 
 457         // importkeystore, secretkey
 458         remove("x.jks");
 459         testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS -genseckey -alias s1"); // create SecretKeyEntry
 460         testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS -genseckey -alias s2"); // create SecretKeyEntry
 461         testOK("changeit\n", "-keystore x.jceks -storetype JCEKS -delete -alias p2"); // remove the keypass!=storepass one
 462         ks = loadStore("x.jceks", "changeit", "JCEKS");
 463         assertTrue(ks.size() == 4, "4 entries in JCEKS");       // p1, c1, s1, s2
 464         testOK("changeit\nchangeit\nchangeit\n", "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS -srcalias s1"); // normal
 465         assertTrue(err.indexOf("not imported") != -1, "Not imported");
 466         assertTrue(err.indexOf("Cannot store non-PrivateKeys") != -1, "Not imported");
 467 
 468         // Importing a JCEKS keystore to a JKS one. Will warn for the 2 SecretKey entries
 469 
 470         remove("x.jks");
 471         // Two "no" answers to bypass warnings
 472         testOK("\n\n", "-srcstorepass changeit -deststorepass changeit -importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS"); // normal
 473         assertTrue(err.indexOf("s1 not") != -1, "s1 not");
 474         assertTrue(err.indexOf("s2 not") != -1, "s2 not");
 475         assertTrue(err.indexOf("c1 success") != -1, "c1 success");
 476         assertTrue(err.indexOf("p1 success") != -1, "p1 success");
 477         remove("x.jks");
 478         // One "yes" to stop
 479         testOK("yes\n", "-srcstorepass changeit -deststorepass changeit -importkeystore -srckeystore x.jceks -srcstoretype JCEKS -destkeystore x.jks -deststoretype JKS"); // normal
 480         // maybe c1 or p1 has been imported before s1 or s2 is touched, anyway we know yesNo is only asked once.
 481 
 482         // pkcs12
 483         remove("x.jks");
 484         testFail("changeit\nchangeit\n", "-keystore x.jks -genkeypair -alias p1 -dname CN=olala"); // JKS prompt for keypass
 485         remove("x.jks");
 486         testOK("changeit\nchangeit\n\n", "-keystore x.jks -genkeypair -alias p1 -dname CN=olala"); // just type ENTER means keypass=storepass
 487         remove("x.p12");
 488         testOK("", "-keystore x.p12 -storetype PKCS12 -storepass changeit -genkeypair -alias p0 -dname CN=olala"); // PKCS12 only need storepass
 489         testOK("changeit\n", "-keystore x.p12 -storetype PKCS12 -genkeypair -alias p1 -dname CN=olala");
 490         testOK("changeit\n", "-keystore x.p12 -keypass changeit -storetype PKCS12 -genkeypair -alias p3 -dname CN=olala"); // when specify keypass, make sure keypass==storepass...
 491         assertTrue(err.indexOf("Warning") == -1, "PKCS12 silent when keypass == storepass");
 492         testOK("changeit\n", "-keystore x.p12 -keypass another -storetype PKCS12 -genkeypair -alias p2 -dname CN=olala"); // otherwise, print a warning
 493         assertTrue(err.indexOf("Warning") != -1, "PKCS12 warning when keypass != storepass");
 494         testFail("", "-keystore x.p12 -storepass changeit -storetype PKCS12 -keypasswd -new changeit -alias p3"); // no -keypasswd for PKCS12
 495         testOK("", "-keystore x.p12 -storepass changeit -storetype PKCS12 -changealias -alias p3 -destalias p33");
 496         testOK("", "-keystore x.p12 -storepass changeit -storetype PKCS12 -keyclone -alias p33 -destalias p3");
 497 
 498         // pkcs12
 499         remove("x.p12");
 500         testOK("", "-keystore x.p12 -storetype PKCS12 -storepass changeit -genkeypair -alias p0 -dname CN=olala"); // PKCS12 only need storepass
 501         testOK("", "-storepass changeit -keystore x.p12 -storetype PKCS12 -genkeypair -alias p1 -dname CN=olala");
 502         testOK("", "-storepass changeit -keystore x.p12 -keypass changeit -storetype PKCS12 -genkeypair -alias p3 -dname CN=olala"); // when specify keypass, make sure keypass==storepass...
 503         assertTrue(err.indexOf("Warning") == -1, "PKCS12 silent when keypass == storepass");
 504         testOK("", "-storepass changeit -keystore x.p12 -keypass another -storetype PKCS12 -genkeypair -alias p2 -dname CN=olala"); // otherwise, print a warning
 505         assertTrue(err.indexOf("Warning") != -1, "PKCS12 warning when keypass != storepass");
 506 
 507         remove("x.jks");
 508         remove("x.jceks");
 509         remove("x.p12");
 510         remove("x2.jceks");
 511         remove("x2.jks");
 512         remove("x.jks.p1.cert");
 513     }
 514 
 515     void testPKCS11() throws Exception {
 516         KeyStore ks;
 517         // pkcs11, the password maybe different and maybe PKCS11 is not supported
 518 
 519         // in case last test is not executed successfully
 520         testAnyway("", p11Arg + "-storepass test12 -delete -alias p1");
 521         testAnyway("", p11Arg + "-storepass test12 -delete -alias p2");
 522         testAnyway("", p11Arg + "-storepass test12 -delete -alias p3");
 523         testAnyway("", p11Arg + "-storepass test12 -delete -alias nss");
 524 
 525         testOK("", p11Arg + "-storepass test12 -list");
 526         assertTrue(out.indexOf("Your keystore contains 0 entries") != -1, "*** MAKE SURE YOU HAVE NO ENTRIES IN YOUR PKCS11 KEYSTORE BEFORE THIS TEST ***");
 527 
 528         testOK("", p11Arg + "-storepass test12 -genkeypair -alias p1 -dname CN=olala");
 529         testOK("test12\n", p11Arg + "-genkeypair -alias p2 -dname CN=olala2");
 530         testFail("test12\n", p11Arg + "-keypass test12 -genkeypair -alias p3 -dname CN=olala3"); // cannot provide keypass for PKCS11
 531         testFail("test12\n", p11Arg + "-keypass nonsense -genkeypair -alias p3 -dname CN=olala3"); // cannot provide keypass for PKCS11
 532 
 533         testOK("", p11Arg + "-storepass test12 -list");
 534         assertTrue(out.indexOf("Your keystore contains 2 entries") != -1, "2 entries in p11");
 535 
 536         testOK("test12\n", p11Arg + "-alias p1 -changealias -destalias p3");
 537         testOK("", p11Arg + "-storepass test12 -list -alias p3");
 538         testFail("", p11Arg + "-storepass test12 -list -alias p1");
 539 
 540         testOK("test12\n", p11Arg + "-alias p3 -keyclone -destalias p1");
 541         testFail("", p11Arg + "-storepass test12 -list -alias p3");   // in PKCS11, keyclone will delete old
 542         testOK("", p11Arg + "-storepass test12 -list -alias p1");
 543 
 544         testFail("test12\n", p11Arg + "-alias p1 -keypasswd -new another"); // cannot change password for PKCS11
 545 
 546         testOK("", p11Arg + "-storepass test12 -list");
 547         assertTrue(out.indexOf("Your keystore contains 2 entries") != -1, "2 entries in p11");
 548 
 549         testOK("", p11Arg + "-storepass test12 -delete -alias p1");
 550         testOK("", p11Arg + "-storepass test12 -delete -alias p2");
 551 
 552         testOK("", p11Arg + "-storepass test12 -list");
 553         assertTrue(out.indexOf("Your keystore contains 0 entries") != -1, "*** MAKE SURE YOU HAVE NO ENTRIES IN YOUR PKCS11 KEYSTORE BEFORE THIS TEST ***");
 554     }
 555 
 556     void testPKCS11ImportKeyStore() throws Exception {
 557 
 558         KeyStore ks;
 559         testOK("", p11Arg + "-storepass test12 -genkeypair -alias p1 -dname CN=olala");
 560         testOK("test12\n", p11Arg + "-genkeypair -alias p2 -dname CN=olala2");
 561         // test importkeystore for pkcs11
 562 
 563         remove("x.jks");
 564         // pkcs11 -> jks
 565         testOK("changeit\nchangeit\ntest12\n", srcP11Arg + "-importkeystore -destkeystore x.jks -deststoretype JKS -srcalias p1");
 566         assertTrue(err.indexOf("not imported") != -1, "cannot import key without destkeypass");
 567         ks = loadStore("x.jks", "changeit", "JKS");
 568         assertTrue(!ks.containsAlias("p1"), "p1 is not imported");
 569 
 570         testOK("changeit\ntest12\n", srcP11Arg + "-importkeystore -destkeystore x.jks -deststoretype JKS -srcalias p1 -destkeypass changeit");
 571         testOK("changeit\ntest12\n", srcP11Arg + "-importkeystore -destkeystore x.jks -deststoretype JKS -srcalias p2 -destkeypass changeit");
 572         ks = loadStore("x.jks", "changeit", "JKS");
 573         assertTrue(ks.containsAlias("p1"), "p1 is imported");
 574         assertTrue(ks.containsAlias("p2"), "p2 is imported");
 575         // jks -> pkcs11
 576         testOK("", p11Arg + "-storepass test12 -delete -alias p1");
 577         testOK("", p11Arg + "-storepass test12 -delete -alias p2");
 578         testOK("test12\nchangeit\n", p11Arg + "-importkeystore -srckeystore x.jks -srcstoretype JKS");
 579         testOK("", p11Arg + "-storepass test12 -list -alias p1");
 580         testOK("", p11Arg + "-storepass test12 -list -alias p2");
 581         testOK("", p11Arg + "-storepass test12 -list");
 582         assertTrue(out.indexOf("Your keystore contains 2 entries") != -1, "2 entries in p11");
 583         // clean up
 584         testOK("", p11Arg + "-storepass test12 -delete -alias p1");
 585         testOK("", p11Arg + "-storepass test12 -delete -alias p2");
 586         testOK("", p11Arg + "-storepass test12 -list");
 587         assertTrue(out.indexOf("Your keystore contains 0 entries") != -1, "empty p11");
 588 
 589         remove("x.jks");
 590     }
 591 
 592     // The sqeTest reflects the test suggested by judy.gao and bill.situ at
 593     // /net/sqesvr-nfs/global/nfs/sec/ws_6.0_int/security/src/SecurityTools/Keytool
 594     //
 595     void sqeTest() throws Exception {
 596         FileOutputStream fos = new FileOutputStream("badkeystore");
 597         for (int i=0; i<100; i++) {
 598             fos.write(i);
 599         }
 600         fos.close();
 601 
 602         sqeCsrTest();
 603         sqePrintcertTest();
 604         sqeDeleteTest();
 605         sqeExportTest();
 606         sqeGenkeyTest();
 607         sqeImportTest();
 608         sqeKeyclonetest();
 609         sqeKeypasswdTest();
 610         sqeListTest();
 611         sqeSelfCertTest();
 612         sqeStorepassTest();
 613 
 614         remove("badkeystore");
 615     }
 616 
 617     // Import: cacert, prompt, trusted, non-trusted, bad chain, not match
 618     void sqeImportTest() throws Exception {
 619         KeyStore ks;
 620         remove("x.jks");
 621         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 622         testOK("", "-keystore x.jks -storepass changeit -exportcert -file x.jks.p1.cert");
 623         /* deleted */ testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 624         testOK("", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert -noprompt");
 625         /* deleted */ testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 626         testOK("yes\n", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert");
 627         ks = loadStore("x.jks", "changeit", "JKS");
 628         assertTrue(ks.containsAlias("mykey"), "imported");
 629         /* deleted */ testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 630         testOK("\n", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert");
 631         ks = loadStore("x.jks", "changeit", "JKS");
 632         assertTrue(!ks.containsAlias("mykey"), "imported");
 633         testOK("no\n", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert");
 634         ks = loadStore("x.jks", "changeit", "JKS");
 635         assertTrue(!ks.containsAlias("mykey"), "imported");
 636         testFail("no\n", "-keystore x.jks -storepass changeit -importcert -file nonexist");
 637         testFail("no\n", "-keystore x.jks -storepass changeit -importcert -file x.jks");
 638         remove("x.jks");
 639     }
 640     // keyclone: exist. nonexist err, cert err, dest exist, misc
 641     void sqeKeyclonetest() throws Exception {
 642         remove("x.jks");
 643         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 644         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -new newpass -keyclone -dest p0"); // new pass
 645         testOK("\n", "-keystore x.jks -storepass changeit -keypass changeit -keyclone -dest p1"); // new pass
 646         testOK("\n", "-keystore x.jks -storepass changeit -keyclone -dest p2");
 647         testFail("\n", "-keystore x.jks -storepass changeit -keyclone -dest p2");
 648         testFail("\n", "-keystore x.jks -storepass changeit -keyclone -dest p3 -alias noexist");
 649         // no cert
 650         testOK("", "-keystore x.jks -storepass changeit -exportcert -file x.jks.p1.cert");
 651         testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 652         testOK("", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert -noprompt");
 653         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -new newpass -keyclone -dest p0"); // new pass
 654         remove("x.jks");
 655     }
 656     // keypasswd: exist, short, nonexist err, cert err, misc
 657     void sqeKeypasswdTest() throws Exception {
 658         remove("x.jks");
 659         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 660         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -keypasswd -new newpass");
 661         /*change back*/ testOK("", "-keystore x.jks -storepass changeit -keypass newpass -keypasswd -new changeit");
 662         testOK("newpass\nnewpass\n", "-keystore x.jks -storepass changeit -keypass changeit -keypasswd");
 663         /*change back*/ testOK("", "-keystore x.jks -storepass changeit -keypass newpass -keypasswd -new changeit");
 664         testOK("new\nnew\nnewpass\nnewpass\n", "-keystore x.jks -storepass changeit -keypass changeit -keypasswd");
 665         /*change back*/ testOK("", "-keystore x.jks -storepass changeit -keypass newpass -keypasswd -new changeit");
 666         testOK("", "-keystore x.jks -storepass changeit -keypasswd -new newpass");
 667         /*change back*/ testOK("", "-keystore x.jks -storepass changeit -keypass newpass -keypasswd -new changeit");
 668         testOK("changeit\n", "-keystore x.jks -keypasswd -new newpass");
 669         /*change back*/ testOK("", "-keystore x.jks -storepass changeit -keypass newpass -keypasswd -new changeit");
 670         testFail("", "-keystore x.jks -storepass badpass -keypass changeit -keypasswd -new newpass");
 671         testFail("", "-keystore x.jks -storepass changeit -keypass bad -keypasswd -new newpass");
 672         // no cert
 673         testOK("", "-keystore x.jks -storepass changeit -exportcert -file x.jks.p1.cert");
 674         testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 675         testOK("", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert -noprompt");
 676         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -keypasswd -new newpass");
 677         // diff pass
 678         testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 679         testOK("", "-keystore x.jks -storepass changeit -keypass keypass -genkeypair -dname CN=olala");
 680         testFail("", "-keystore x.jks -storepass changeit -keypasswd -new newpass");
 681         testOK("keypass\n", "-keystore x.jks -storepass changeit -keypasswd -new newpass");
 682         // i hate those misc test
 683         remove("x.jks");
 684     }
 685     // list: -f -alias, exist, nonexist err; otherwise, check all shows, -rfc shows more, and misc
 686     void sqeListTest() throws Exception {
 687         remove("x.jks");
 688         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 689         testOK("", "-keystore x.jks -storepass changeit -list");
 690         testOK("", "-keystore x.jks -storepass changeit -list -alias mykey");
 691         testFail("", "-keystore x.jks -storepass changeit -list -alias notexist");
 692         testFail("", "-keystore x.jks -storepass badpass -list -alias mykey");
 693         testOK("", "-keystore x.jks -storepass changeit -keypass badpass -list -alias mykey");  // keypass ignore
 694         testOK("\n", "-keystore x.jks -list");
 695         assertTrue(err.indexOf("WARNING") != -1, "no storepass");
 696         testOK("changeit\n", "-keystore x.jks -list");
 697         assertTrue(err.indexOf("WARNING") == -1, "has storepass");
 698         testFail("badpass\n", "-keystore x.jks -list");
 699         // misc
 700         testFail("", "-keystore aa\\bb//cc -storepass changeit -list");
 701         testFail("", "-keystore nonexisting -storepass changeit -list");
 702         testFail("", "-keystore badkeystore -storepass changeit -list");
 703         remove("x.jks");
 704     }
 705     // selfcert: exist, non-exist err, cert err, sig..., dname, wrong keypass, misc
 706     void sqeSelfCertTest() throws Exception {
 707         remove("x.jks");
 708         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 709         testOK("", "-keystore x.jks -storepass changeit -selfcert");
 710         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -selfcert");
 711         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -selfcert -alias nonexisting"); // not exist
 712         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -selfcert -dname CN=NewName");
 713         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -selfcert -sigalg MD5withRSA"); // sig not compatible
 714         testFail("", "-keystore x.jks -storepass wrong -keypass changeit -selfcert"); // bad pass
 715         testFail("", "-keystore x.jks -storepass changeit -keypass wrong -selfcert"); // bad pass
 716         //misc
 717         testFail("", "-keystore nonexist -storepass changeit -keypass changeit -selfcert");
 718         testFail("", "-keystore aa//dd\\gg -storepass changeit -keypass changeit -selfcert");
 719         // diff pass
 720         remove("x.jks");
 721         testOK("", "-keystore x.jks -storepass changeit -keypass keypass -genkeypair -dname CN=olala");
 722         testFail("", "-keystore x.jks -storepass changeit -selfcert");
 723         testOK("keypass\n", "-keystore x.jks -storepass changeit -selfcert");
 724 
 725         testOK("", "-keystore x.jks -storepass changeit -exportcert -file x.jks.p1.cert");
 726         testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 727         testOK("", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert -noprompt");
 728         testFail("", "-keystore x.jks -storepass changeit -selfcert");  // certentry cannot do selfcert
 729         remove("x.jks");
 730     }
 731     // storepass: bad old, short new, misc
 732     void sqeStorepassTest() throws Exception {
 733         remove("x.jks");
 734         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 735         testOK("", "-storepasswd -keystore x.jks -storepass changeit -new newstore"); // all in arg
 736         /* Change back */ testOK("", "-storepasswd -keystore x.jks -storepass newstore -new changeit");
 737         testOK("changeit\nnewstore\nnewstore\n", "-storepasswd -keystore x.jks"); // all not in arg, new twice
 738         /* Change back */ testOK("", "-storepasswd -keystore x.jks -storepass newstore -new changeit");
 739         testOK("changeit\n", "-storepasswd -keystore x.jks -new newstore"); // new in arg
 740         /* Change back */ testOK("", "-storepasswd -keystore x.jks -storepass newstore -new changeit");
 741         testOK("newstore\nnewstore\n", "-storepasswd -keystore x.jks -storepass changeit"); // old in arg
 742         /* Change back */ testOK("", "-storepasswd -keystore x.jks -storepass newstore -new changeit");
 743         testOK("new\nnew\nnewstore\nnewstore\n", "-storepasswd -keystore x.jks -storepass changeit"); // old in arg
 744         /* Change back */ testOK("", "-storepasswd -keystore x.jks -storepass newstore -new changeit");
 745         testFail("", "-storepasswd -keystore x.jks -storepass badold -new newstore"); // bad old
 746         testFail("", "-storepasswd -keystore x.jks -storepass changeit -new new"); // short new
 747         // misc
 748         testFail("", "-storepasswd -keystore nonexist -storepass changeit -new newstore"); // non exist
 749         testFail("", "-storepasswd -keystore badkeystore -storepass changeit -new newstore"); // bad file
 750         testFail("", "-storepasswd -keystore aa\\bb//cc//dd -storepass changeit -new newstore"); // bad file
 751         remove("x.jks");
 752     }
 753 
 754     void sqeGenkeyTest() throws Exception {
 755 
 756         remove("x.jks");
 757         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 758         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 759         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -alias newentry");
 760         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -alias newentry");
 761         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg DSA -alias n1");
 762         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg RSA -alias n2");
 763         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg NoSuchAlg -alias n3");
 764         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keysize 56 -alias n4");
 765         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keysize 999 -alias n5");
 766         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keysize 512 -alias n6");
 767         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keysize 1024 -alias n7");
 768         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -sigalg NoSuchAlg -alias n8");
 769         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg RSA -sigalg MD2withRSA -alias n9");
 770         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg RSA -sigalg MD5withRSA -alias n10");
 771         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg RSA -sigalg SHA1withRSA -alias n11");
 772         testFail("", "-keystore aa\\bb//cc\\dd -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg RSA -sigalg NoSuchAlg -alias n12");
 773         testFail("", "-keystore badkeystore -storepass changeit -keypass changeit -genkeypair -dname CN=olala -alias n14");
 774         testFail("", "-keystore x.jks -storepass badpass -keypass changeit -genkeypair -dname CN=olala -alias n16");
 775         testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CNN=olala -alias n17");
 776         remove("x.jks");
 777     }
 778 
 779     void sqeExportTest() throws Exception {
 780         remove("x.jks");
 781         testFail("", "-keystore x.jks -storepass changeit -export -file mykey.cert -alias mykey"); // nonexist
 782         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 783         testOK("", "-keystore x.jks -storepass changeit -export -file mykey.cert -alias mykey");
 784         testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 785         testOK("", "-keystore x.jks -storepass changeit -import -file mykey.cert -noprompt -alias c1");
 786         testOK("", "-keystore x.jks -storepass changeit -export -file mykey.cert2 -alias c1");
 787         testFail("", "-keystore aa\\bb//cc\\dd -storepass changeit -export -file mykey.cert2 -alias c1");
 788         testFail("", "-keystore nonexistkeystore -storepass changeit -export -file mykey.cert2 -alias c1");
 789         testFail("", "-keystore badkeystore -storepass changeit -export -file mykey.cert2 -alias c1");
 790         testFail("", "-keystore x.jks -storepass badpass -export -file mykey.cert2 -alias c1");
 791         remove("mykey.cert");
 792         remove("mykey.cert2");
 793         remove("x.jks");
 794     }
 795 
 796     void sqeDeleteTest() throws Exception {
 797         remove("x.jks");
 798         testFail("", "-keystore x.jks -storepass changeit -delete -alias mykey"); // nonexist
 799         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 800         testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 801         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 802         testFail("", "-keystore aa\\bb//cc\\dd -storepass changeit -delete -alias mykey"); // keystore name illegal
 803         testFail("", "-keystore nonexistkeystore -storepass changeit -delete -alias mykey"); // keystore not exist
 804         testFail("", "-keystore badkeystore -storepass changeit -delete -alias mykey"); // keystore invalid
 805         testFail("", "-keystore x.jks -storepass xxxxxxxx -delete -alias mykey"); // wrong pass
 806         remove("x.jks");
 807     }
 808 
 809     void sqeCsrTest() throws Exception {
 810         remove("x.jks");
 811         remove("x.jks.p1.cert");
 812         remove("csr1");
 813         // PrivateKeyEntry can do certreq
 814         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keysize 1024");
 815         testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1 -alias mykey");
 816         testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1");
 817         testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1 -sigalg SHA1withDSA");
 818         testFail("", "-keystore x.jks -storepass changeit -certreq -file csr1 -sigalg MD5withRSA"); // unmatched sigalg
 819         // misc test
 820         testFail("", "-keystore x.jks -storepass badstorepass -certreq -file csr1"); // bad storepass
 821         testOK("changeit\n", "-keystore x.jks -certreq -file csr1"); // storepass from terminal
 822         testFail("\n", "-keystore x.jks -certreq -file csr1"); // must provide storepass
 823         testFail("", "-keystore x.jks -storepass changeit -keypass badkeypass -certreq -file csr1"); // bad keypass
 824         testFail("", "-keystore x.jks -storepass changeit -certreq -file aa\\bb//cc\\dd");  // bad filepath
 825         testFail("", "-keystore noexistks -storepass changeit -certreq -file csr1"); // non-existing keystore
 826         // Try the RSA private key
 827         testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 828         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg RSA");
 829         testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1 -alias mykey");
 830         testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1");
 831         testFail("", "-keystore x.jks -storepass changeit -certreq -file csr1 -sigalg SHA1withDSA"); // unmatched sigalg
 832         testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1 -sigalg MD5withRSA");
 833         // TrustedCertificateEntry cannot do certreq
 834         testOK("", "-keystore x.jks -storepass changeit -exportcert -file x.jks.p1.cert");
 835         testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
 836         testOK("", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert -noprompt");
 837         testFail("", "-keystore x.jks -storepass changeit -certreq -file csr1 -alias mykey");
 838         testFail("", "-keystore x.jks -storepass changeit -certreq -file csr1");
 839         remove("x.jks");
 840         remove("x.jks.p1.cert");
 841         remove("csr1");
 842     }
 843 
 844     void sqePrintcertTest() throws Exception {
 845         remove("x.jks");
 846         remove("mykey.cert");
 847         testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
 848         testOK("", "-keystore x.jks -storepass changeit -export -file mykey.cert -alias mykey");
 849         testFail("", "-printcert -file badkeystore");
 850         testFail("", "-printcert -file a/b/c/d");
 851         testOK("", "-printcert -file mykey.cert");
 852         FileInputStream fin = new FileInputStream("mykey.cert");
 853         testOK(fin, "-printcert");
 854         fin.close();
 855         remove("x.jks");
 856         remove("mykey.cert");
 857     }
 858 
 859     // 8074935: jdk8 keytool doesn't validate pem files for RFC 1421 correctness
 860     static void checkPem(String file) throws Exception {
 861         boolean maybeLast = false;
 862         for (String s: Files.readAllLines(Paths.get(file))) {
 863             if (s.isEmpty()) continue;
 864             if (s.startsWith("---")) continue;
 865             if (maybeLast) {
 866                 throw new Exception("Last line already seen");
 867             }
 868             if (s.length() > 64) {
 869                 throw new Exception(s);
 870             }
 871             if (s.length() < 64) {
 872                 maybeLast = true;
 873             }
 874         }
 875     }
 876 
 877     void v3extTest(String keyAlg) throws Exception {
 878         KeyStore ks;
 879         remove("x.jks");
 880         String simple = "-keystore x.jks -storepass changeit -keypass changeit -noprompt -keyalg " + keyAlg + " ";
 881         String pre = simple + "-genkeypair -dname CN=Olala -alias ";
 882 
 883         // Version and SKID
 884         testOK("", pre + "o1");
 885 
 886         ks = loadStore("x.jks", "changeit", "JKS");
 887         assertTrue(((X509Certificate)ks.getCertificate("o1")).getVersion() == 3);
 888         assertTrue(((X509CertImpl)ks.getCertificate("o1")).getSubjectKeyIdentifierExtension() != null);
 889 
 890         // BC
 891         testOK("", pre + "b1 -ext BC:critical");
 892         testOK("", pre + "b2 -ext BC");
 893         testOK("", pre + "b3 -ext bc");
 894         testOK("", pre + "b4 -ext BasicConstraints");
 895         testOK("", pre + "b5 -ext basicconstraints");
 896         testOK("", pre + "b6 -ext BC=ca:true,pathlen:12");
 897         testOK("", pre + "b7 -ext BC=ca:false");
 898         testOK("", pre + "b8 -ext BC:critical=ca:false");
 899         testOK("", pre + "b9 -ext BC=12");
 900 
 901         ks = loadStore("x.jks", "changeit", "JKS");
 902         assertTrue(((X509CertImpl)ks.getCertificate("b1")).getBasicConstraintsExtension().isCritical());
 903         assertTrue(!((X509CertImpl)ks.getCertificate("b2")).getBasicConstraintsExtension().isCritical());
 904         assertTrue(((X509CertImpl)ks.getCertificate("b8")).getBasicConstraintsExtension().isCritical());
 905         assertTrue(((X509Certificate)ks.getCertificate("b1")).getBasicConstraints() == Integer.MAX_VALUE);
 906         assertTrue(((X509Certificate)ks.getCertificate("b2")).getBasicConstraints() == Integer.MAX_VALUE);
 907         assertTrue(((X509Certificate)ks.getCertificate("b3")).getBasicConstraints() == Integer.MAX_VALUE);
 908         assertTrue(((X509Certificate)ks.getCertificate("b4")).getBasicConstraints() == Integer.MAX_VALUE);
 909         assertTrue(((X509Certificate)ks.getCertificate("b5")).getBasicConstraints() == Integer.MAX_VALUE);
 910         assertTrue(((X509Certificate)ks.getCertificate("b6")).getBasicConstraints() == 12);
 911         assertTrue(((X509Certificate)ks.getCertificate("b7")).getBasicConstraints() == -1);
 912         assertTrue(((X509Certificate)ks.getCertificate("b9")).getBasicConstraints() == 12);
 913 
 914         // KU
 915         testOK("", pre + "ku1 -ext KeyUsage:critical=digitalsignature");
 916         testOK("", pre + "ku2 -ext KU=digitalSignature");
 917         testOK("", pre + "ku3 -ext KU=ds");
 918         testOK("", pre + "ku4 -ext KU=dig");
 919         testFail("", pre + "ku5 -ext KU=d");    // ambigous value
 920         testFail("", pre + "ku6 -ext KU=cs");   // cRLSign cannot be cs
 921         testOK("", pre + "ku11 -ext KU=nr");
 922         testFail("", pre + "ku12 -ext KU=ke");  // ke also means keyAgreement
 923         testOK("", pre + "ku12 -ext KU=keyE");
 924         testFail("", pre + "ku13 -ext KU=de");  // de also means decipherOnly
 925         testOK("", pre + "ku13 -ext KU=dataE");
 926         testOK("", pre + "ku14 -ext KU=ka");
 927         testOK("", pre + "ku15 -ext KU=kcs");
 928         testOK("", pre + "ku16 -ext KU=crls");
 929         testOK("", pre + "ku17 -ext KU=eo");
 930         testOK("", pre + "ku18 -ext KU=do");
 931         testOK("", pre + "ku19 -ext KU=cc");
 932 
 933         testOK("", pre + "ku017 -ext KU=ds,cc,eo");
 934         testOK("", pre + "ku135 -ext KU=nr,dataEncipherment,keyCertSign");
 935         testOK("", pre + "ku246 -ext KU=keyEnc,cRL,keyA");
 936         testOK("", pre + "ku1234 -ext KU=ka,da,keyE,nonR");
 937 
 938         ks = loadStore("x.jks", "changeit", "JKS");
 939         class CheckKU {
 940             void check(KeyStore ks, String alias, int... pos) throws Exception {
 941                 System.err.print("x");
 942                 boolean[] bs = ((X509Certificate)ks.getCertificate(alias)).getKeyUsage();
 943                 bs = Arrays.copyOf(bs, 9);
 944                 for (int i=0; i<bs.length; i++) {
 945                     boolean found = false;
 946                     for (int p: pos) {
 947                         if (p == i) found = true;
 948                     }
 949                     if (!found ^ bs[i]) {
 950                         // OK
 951                     } else {
 952                         throw new RuntimeException("KU not match at " + i +
 953                                 ": " + found + " vs " + bs[i]);
 954                     }
 955                 }
 956             }
 957         }
 958         CheckKU c = new CheckKU();
 959         assertTrue(((X509CertImpl)ks.getCertificate("ku1")).getExtension(PKIXExtensions.KeyUsage_Id).isCritical());
 960         assertTrue(!((X509CertImpl)ks.getCertificate("ku2")).getExtension(PKIXExtensions.KeyUsage_Id).isCritical());
 961         c.check(ks, "ku1", 0);
 962         c.check(ks, "ku2", 0);
 963         c.check(ks, "ku3", 0);
 964         c.check(ks, "ku4", 0);
 965         c.check(ks, "ku11", 1);
 966         c.check(ks, "ku12", 2);
 967         c.check(ks, "ku13", 3);
 968         c.check(ks, "ku14", 4);
 969         c.check(ks, "ku15", 5);
 970         c.check(ks, "ku16", 6);
 971         c.check(ks, "ku17", 7);
 972         c.check(ks, "ku18", 8);
 973         c.check(ks, "ku19", 1);
 974         c.check(ks, "ku11", 1);
 975         c.check(ks, "ku11", 1);
 976         c.check(ks, "ku11", 1);
 977         c.check(ks, "ku017", 0, 1, 7);
 978         c.check(ks, "ku135", 1, 3, 5);
 979         c.check(ks, "ku246", 6, 2, 4);
 980         c.check(ks, "ku1234", 1, 2, 3, 4);
 981 
 982         // EKU
 983         testOK("", pre + "eku1 -ext EKU:critical=sa");
 984         testOK("", pre + "eku2 -ext ExtendedKeyUsage=ca");
 985         testOK("", pre + "eku3 -ext EKU=cs");
 986         testOK("", pre + "eku4 -ext EKU=ep");
 987         testOK("", pre + "eku8 -ext EKU=ts");
 988         testFail("", pre + "eku9 -ext EKU=os");
 989         testOK("", pre + "eku9 -ext EKU=ocsps");
 990         testOK("", pre + "eku10 -ext EKU=any");
 991         testOK("", pre + "eku11 -ext EKU=1.2.3.4,1.3.5.7,ep");
 992         testFail("", pre + "eku12 -ext EKU=c");
 993         testFail("", pre + "eku12 -ext EKU=nothing");
 994 
 995         ks = loadStore("x.jks", "changeit", "JKS");
 996         class CheckEKU {
 997             void check(KeyStore ks, String alias, String... pos) throws Exception {
 998                 System.err.print("x");
 999                 List<String> bs = ((X509Certificate)ks.getCertificate(alias)).getExtendedKeyUsage();
1000                 int found = 0;
1001                 for (String p: pos) {
1002                     if (bs.contains(p)) {
1003                         found++;
1004                     } else {
1005                         throw new RuntimeException("EKU: not included " + p);
1006                     }
1007                 }
1008                 if (found != bs.size()) {
1009                     throw new RuntimeException("EKU: more items than expected");
1010                 }
1011             }
1012         }
1013         CheckEKU cx = new CheckEKU();
1014         assertTrue(((X509CertImpl)ks.getCertificate("eku1")).getExtension(PKIXExtensions.ExtendedKeyUsage_Id).isCritical());
1015         assertTrue(!((X509CertImpl)ks.getCertificate("eku2")).getExtension(PKIXExtensions.ExtendedKeyUsage_Id).isCritical());
1016         cx.check(ks, "eku1", "1.3.6.1.5.5.7.3.1");
1017         cx.check(ks, "eku2", "1.3.6.1.5.5.7.3.2");
1018         cx.check(ks, "eku3", "1.3.6.1.5.5.7.3.3");
1019         cx.check(ks, "eku4", "1.3.6.1.5.5.7.3.4");
1020         cx.check(ks, "eku8", "1.3.6.1.5.5.7.3.8");
1021         cx.check(ks, "eku9", "1.3.6.1.5.5.7.3.9");
1022         cx.check(ks, "eku10", "2.5.29.37.0");
1023         cx.check(ks, "eku11", "1.3.6.1.5.5.7.3.4", "1.2.3.4", "1.3.5.7");
1024 
1025         // SAN
1026         testOK("", pre+"san1 -ext san:critical=email:me@me.org");
1027         testOK("", pre+"san2 -ext san=uri:http://me.org");
1028         testOK("", pre+"san3 -ext san=dns:me.org");
1029         testOK("", pre+"san4 -ext san=ip:192.168.0.1");
1030         testOK("", pre+"san5 -ext san=oid:1.2.3.4");
1031         testOK("", pre+"san6 -ext san=dns:1abc.com"); //begin with digit
1032         testOK("", pre+"san235 -ext san=uri:http://me.org,dns:me.org,oid:1.2.3.4");
1033 
1034         ks = loadStore("x.jks", "changeit", "JKS");
1035         class CheckSAN {
1036             // Please sort items with name type
1037             void check(KeyStore ks, String alias, int type, Object... items) throws Exception {
1038                 int pos = 0;
1039                 System.err.print("x");
1040                 Object[] names = null;
1041                 if (type == 0) names = ((X509Certificate)ks.getCertificate(alias)).getSubjectAlternativeNames().toArray();
1042                 else names = ((X509Certificate)ks.getCertificate(alias)).getIssuerAlternativeNames().toArray();
1043                 Arrays.sort(names, new Comparator() {
1044                     public int compare(Object o1, Object o2) {
1045                         int i1 = (Integer)((List)o1).get(0);
1046                         int i2 = (Integer)((List)o2).get(0);
1047                         return i1 - i2;
1048                     }
1049                 });
1050                 for (Object o: names) {
1051                     List l = (List)o;
1052                     for (Object o2: l) {
1053                         if (!items[pos++].equals(o2)) {
1054                             throw new RuntimeException("Not equals at " + pos
1055                                     + ": " + items[pos-1] + " vs " + o2);
1056                         }
1057                     }
1058                 }
1059                 if (pos != items.length) {
1060                     throw new RuntimeException("Extra items, pos is " + pos);
1061                 }
1062             }
1063         }
1064         CheckSAN csan = new CheckSAN();
1065         assertTrue(((X509CertImpl)ks.getCertificate("san1")).getSubjectAlternativeNameExtension().isCritical());
1066         assertTrue(!((X509CertImpl)ks.getCertificate("san2")).getSubjectAlternativeNameExtension().isCritical());
1067         csan.check(ks, "san1", 0, 1, "me@me.org");
1068         csan.check(ks, "san2", 0, 6, "http://me.org");
1069         csan.check(ks, "san3", 0, 2, "me.org");
1070         csan.check(ks, "san4", 0, 7, "192.168.0.1");
1071         csan.check(ks, "san5", 0, 8, "1.2.3.4");
1072         csan.check(ks, "san235", 0, 2, "me.org", 6, "http://me.org", 8, "1.2.3.4");
1073 
1074         // IAN
1075         testOK("", pre+"ian1 -ext ian:critical=email:me@me.org");
1076         testOK("", pre+"ian2 -ext ian=uri:http://me.org");
1077         testOK("", pre+"ian3 -ext ian=dns:me.org");
1078         testOK("", pre+"ian4 -ext ian=ip:192.168.0.1");
1079         testOK("", pre+"ian5 -ext ian=oid:1.2.3.4");
1080         testOK("", pre+"ian235 -ext ian=uri:http://me.org,dns:me.org,oid:1.2.3.4");
1081 
1082         ks = loadStore("x.jks", "changeit", "JKS");
1083         assertTrue(((X509CertImpl)ks.getCertificate("ian1")).getIssuerAlternativeNameExtension().isCritical());
1084         assertTrue(!((X509CertImpl)ks.getCertificate("ian2")).getIssuerAlternativeNameExtension().isCritical());
1085         csan.check(ks, "ian1", 1, 1, "me@me.org");
1086         csan.check(ks, "ian2", 1, 6, "http://me.org");
1087         csan.check(ks, "ian3", 1, 2, "me.org");
1088         csan.check(ks, "ian4", 1, 7, "192.168.0.1");
1089         csan.check(ks, "ian5", 1, 8, "1.2.3.4");
1090         csan.check(ks, "ian235", 1, 2, "me.org", 6, "http://me.org", 8, "1.2.3.4");
1091 
1092         // SIA
1093         testOK("", pre+"sia1 -ext sia=care:uri:ldap://ca.com/cn=CA");
1094         testOK("", pre+"sia2 -ext sia=ts:email:ts@ca.com");
1095         testFail("SIA never critical", pre+"sia3 -ext sia:critical=ts:email:ts@ca.com");
1096 
1097         ks = loadStore("x.jks", "changeit", "JKS");
1098         class CheckSia {
1099             void check(KeyStore ks, String alias, int type, Object... items) throws Exception {
1100                 int pos = 0;
1101                 System.err.print("x");
1102                 AccessDescription[] ads = null;
1103                 if (type == 0) {
1104                     SubjectInfoAccessExtension siae = (SubjectInfoAccessExtension)((X509CertImpl)ks.getCertificate(alias)).getExtension(PKIXExtensions.SubjectInfoAccess_Id);
1105                     ads = siae.getAccessDescriptions().toArray(new AccessDescription[0]);
1106                 } else {
1107                     AuthorityInfoAccessExtension aiae = (AuthorityInfoAccessExtension)((X509CertImpl)ks.getCertificate(alias)).getExtension(PKIXExtensions.AuthInfoAccess_Id);
1108                     ads = aiae.getAccessDescriptions().toArray(new AccessDescription[0]);
1109                 }
1110                 Arrays.sort(ads, new Comparator<AccessDescription>() {
1111                     @Override
1112                     public int compare(AccessDescription o1, AccessDescription o2) {
1113                         return o1.getAccessMethod().toString().compareTo(o2.getAccessMethod().toString());
1114                     }
1115                 });
1116                 for (AccessDescription ad: ads) {
1117                     if (!ad.getAccessMethod().equals(items[pos++]) ||
1118                             !new Integer(ad.getAccessLocation().getType()).equals(items[pos++])) {
1119                         throw new RuntimeException("Not same type at " + pos);
1120                     }
1121                     String name = null;
1122                     switch (ad.getAccessLocation().getType()) {
1123                         case 1:
1124                             name = ((RFC822Name)ad.getAccessLocation().getName()).getName();
1125                             break;
1126                         case 6:
1127                             name = ((URIName)ad.getAccessLocation().getName()).getURI().toString();
1128                             break;
1129                         default:
1130                             throw new RuntimeException("Not implemented: " + ad);
1131                     }
1132                     if (!name.equals(items[pos++])) {
1133                         throw new Exception("Name not same for " + ad + " at pos " + pos);
1134                     }
1135                 }
1136             }
1137         }
1138         CheckSia csia = new CheckSia();
1139         assertTrue(!((X509CertImpl)ks.getCertificate("sia1")).getExtension(PKIXExtensions.SubjectInfoAccess_Id).isCritical());
1140         csia.check(ks, "sia1", 0, AccessDescription.Ad_CAREPOSITORY_Id, 6, "ldap://ca.com/cn=CA");
1141         csia.check(ks, "sia2", 0, AccessDescription.Ad_TIMESTAMPING_Id, 1, "ts@ca.com");
1142 
1143         // AIA
1144         testOK("", pre+"aia1 -ext aia=cai:uri:ldap://ca.com/cn=CA");
1145         testOK("", pre+"aia2 -ext aia=ocsp:email:ocsp@ca.com");
1146         testFail("AIA never critical", pre+"aia3 -ext aia:critical=ts:email:ts@ca.com");
1147 
1148         ks = loadStore("x.jks", "changeit", "JKS");
1149         assertTrue(!((X509CertImpl)ks.getCertificate("aia1")).getExtension(PKIXExtensions.AuthInfoAccess_Id).isCritical());
1150         csia.check(ks, "aia1", 1, AccessDescription.Ad_CAISSUERS_Id, 6, "ldap://ca.com/cn=CA");
1151         csia.check(ks, "aia2", 1, AccessDescription.Ad_OCSP_Id, 1, "ocsp@ca.com");
1152 
1153         // OID
1154         testOK("", pre+"oid1 -ext 1.2.3:critical=0102");
1155         testOK("", pre+"oid2 -ext 1.2.3");
1156         testOK("", pre+"oid12 -ext 1.2.3 -ext 1.2.4=01:02:03");
1157 
1158         ks = loadStore("x.jks", "changeit", "JKS");
1159         class CheckOid {
1160             void check(KeyStore ks, String alias, String oid, byte[] value) throws Exception {
1161                 int pos = 0;
1162                 System.err.print("x");
1163                 Extension ex = ((X509CertImpl)ks.getCertificate(alias)).getExtension(new ObjectIdentifier(oid));
1164                 if (!Arrays.equals(value, ex.getValue())) {
1165                     throw new RuntimeException("Not same content in " + alias + " for " + oid);
1166                 }
1167             }
1168         }
1169         CheckOid coid = new CheckOid();
1170         assertTrue(((X509CertImpl)ks.getCertificate("oid1")).getExtension(new ObjectIdentifier("1.2.3")).isCritical());
1171         assertTrue(!((X509CertImpl)ks.getCertificate("oid2")).getExtension(new ObjectIdentifier("1.2.3")).isCritical());
1172         coid.check(ks, "oid1", "1.2.3", new byte[]{1,2});
1173         coid.check(ks, "oid2", "1.2.3", new byte[]{});
1174         coid.check(ks, "oid12", "1.2.3", new byte[]{});
1175         coid.check(ks, "oid12", "1.2.4", new byte[]{1,2,3});
1176 
1177         // honored
1178         testOK("", pre+"ca");
1179         testOK("", pre+"a");
1180         // request: BC,KU,1.2.3,1.2.4,1.2.5
1181         testOK("", simple+"-alias a -certreq " +
1182                 "-ext BC=1 -ext KU=crl " +
1183                 "-ext 1.2.3=01 -ext 1.2.4:critical=0102 -ext 1.2.5=010203 " +
1184                 "-rfc -file test.req");
1185         // printcertreq
1186         testOK("", "-printcertreq -file test.req");
1187         checkPem("test.req");
1188         // issue: deny KU, change criticality of 1.2.3 and 1.2.4,
1189         // change content of BC, add 2.3.4
1190         testOK("", simple+"-gencert -alias ca -infile test.req -ext " +
1191                 "honored=all,-KU,1.2.3:critical,1.2.4:non-critical " +
1192                 "-ext BC=2 -ext 2.3.4=01020304 " +
1193                 "-debug -rfc -outfile test.cert");
1194         checkPem("test.cert");
1195         testOK("", simple+"-importcert -file test.cert -alias a");
1196         ks = loadStore("x.jks", "changeit", "JKS");
1197         X509CertImpl a = (X509CertImpl)ks.getCertificate("a");
1198         assertTrue(a.getAuthorityKeyIdentifierExtension() != null);
1199         assertTrue(a.getSubjectKeyIdentifierExtension() != null);
1200         assertTrue(a.getKeyUsage() == null);
1201         assertTrue(a.getExtension(new ObjectIdentifier("1.2.3")).isCritical());
1202         assertTrue(!a.getExtension(new ObjectIdentifier("1.2.4")).isCritical());
1203         assertTrue(!a.getExtension(new ObjectIdentifier("1.2.5")).isCritical());
1204         assertTrue(a.getExtensionValue("1.2.3").length == 3);
1205         assertTrue(a.getExtensionValue("1.2.4").length == 4);
1206         assertTrue(a.getExtensionValue("1.2.5").length == 5);
1207         assertTrue(a.getBasicConstraints() == 2);
1208         assertTrue(!a.getExtension(new ObjectIdentifier("2.3.4")).isCritical());
1209         assertTrue(a.getExtensionValue("2.3.4").length == 6);
1210 
1211         remove("x.jks");
1212         remove("test.req");
1213         remove("test.cert");
1214     }
1215 
1216     void i18nTest() throws Exception {
1217         //   1.  keytool -help
1218         remove("x.jks");
1219         testOK("", "-help");
1220 
1221         //   2. keytool -genkey -v -keysize 512 Enter "a" for the keystore password. Check error (password too short). Enter "password" for the keystore password. Hit 'return' for "first and last name", "organizational unit", "City", "State", and "Country Code". Type "yes" when they ask you if everything is correct. Type 'return' for new key password.
1222         testOK("a\npassword\npassword\nMe\nHere\nNow\nPlace\nPlace\nUS\nyes\n\n", "-genkey -v -keysize 512 -keystore x.jks");
1223         //   3. keytool -list -v -storepass password
1224         testOK("", "-list -v -storepass password -keystore x.jks");
1225         //   4. keytool -list -v Type "a" for the keystore password. Check error (wrong keystore password).
1226         testFail("a\n", "-list -v -keystore x.jks");
1227         assertTrue(ex.indexOf("password was incorrect") != -1);
1228         //   5. keytool -genkey -v -keysize 512 Enter "password" as the password. Check error (alias 'mykey' already exists).
1229         testFail("password\n", "-genkey -v -keysize 512 -keystore x.jks");
1230         assertTrue(ex.indexOf("alias <mykey> already exists") != -1);
1231         //   6. keytool -genkey -v -keysize 512 -alias mykey2 -storepass password Hit 'return' for "first and last name", "organizational unit", "City", "State", and "Country Code". Type "yes" when they ask you if everything is correct. Type 'return' for new key password.
1232         testOK("\n\n\n\n\n\nyes\n\n", "-genkey -v -keysize 512 -alias mykey2 -storepass password -keystore x.jks");
1233         //   7. keytool -list -v Type 'password' for the store password.
1234         testOK("password\n", "-list -v -keystore x.jks");
1235         //   8. keytool -keypasswd -v -alias mykey2 -storepass password Type "a" for the new key password. Type "aaaaaa" for the new key password. Type "bbbbbb" when re-entering the new key password. Type "a" for the new key password. Check Error (too many failures).
1236         testFail("a\naaaaaa\nbbbbbb\na\n", "-keypasswd -v -alias mykey2 -storepass password -keystore x.jks");
1237         assertTrue(ex.indexOf("Too many failures - try later") != -1);
1238         //   9. keytool -keypasswd -v -alias mykey2 -storepass password Type "aaaaaa" for the new key password. Type "aaaaaa" when re-entering the new key password.
1239         testOK("aaaaaa\naaaaaa\n", "-keypasswd -v -alias mykey2 -storepass password -keystore x.jks");
1240         //  10. keytool -selfcert -v -alias mykey -storepass password
1241         testOK("", "-selfcert -v -alias mykey -storepass password -keystore x.jks");
1242         //  11. keytool -list -v -storepass password
1243         testOK("", "-list -v -storepass password -keystore x.jks");
1244         //  12. keytool -export -v -alias mykey -file cert -storepass password
1245         remove("cert");
1246         testOK("", "-export -v -alias mykey -file cert -storepass password -keystore x.jks");
1247         //  13. keytool -import -v -file cert -storepass password Check error (Certificate reply and cert are the same)
1248         testFail("", "-import -v -file cert -storepass password -keystore x.jks");
1249         assertTrue(ex.indexOf("Certificate reply and certificate in keystore are identical") != -1);
1250         //  14. keytool -printcert -file cert
1251         testOK("", "-printcert -file cert -keystore x.jks");
1252         remove("cert");
1253         //  15. keytool -list -storepass password -provider sun.security.provider.Sun
1254         testOK("", "-list -storepass password -provider sun.security.provider.Sun -keystore x.jks");
1255 
1256         //Error tests
1257 
1258         //   1. keytool -storepasswd -storepass password -new abc Check error (password too short)
1259         testFail("", "-storepasswd -storepass password -new abc");
1260         assertTrue(ex.indexOf("New password must be at least 6 characters") != -1);
1261         // Changed, no NONE needed now
1262         //   2. keytool -list -storetype PKCS11 Check error (-keystore must be NONE)
1263         //testFail("", "-list -storetype PKCS11");
1264         //assertTrue(err.indexOf("keystore must be NONE") != -1);
1265         //   3. keytool -storepasswd -storetype PKCS11 -keystore NONE Check error (unsupported operation)
1266         testFail("", "-storepasswd -storetype PKCS11 -keystore NONE");
1267         assertTrue(ex.indexOf("UnsupportedOperationException") != -1);
1268         //   4. keytool -keypasswd -storetype PKCS11 -keystore NONE Check error (unsupported operation)
1269         testFail("", "-keypasswd -storetype PKCS11 -keystore NONE");
1270         assertTrue(ex.indexOf("UnsupportedOperationException") != -1);
1271         //   5. keytool -list -protected -storepass password Check error (password can not be specified with -protected)
1272         testFail("", "-list -protected -storepass password -keystore x.jks");
1273         assertTrue(ex.indexOf("if -protected is specified, then") != -1);
1274         //   6. keytool -keypasswd -protected -keypass password Check error (password can not be specified with -protected)
1275         testFail("", "-keypasswd -protected -keypass password -keystore x.jks");
1276         assertTrue(ex.indexOf("if -protected is specified, then") != -1);
1277         //   7. keytool -keypasswd -protected -new password Check error (password can not be specified with -protected)
1278         testFail("", "-keypasswd -protected -new password -keystore x.jks");
1279         assertTrue(ex.indexOf("if -protected is specified, then") != -1);
1280         remove("x.jks");
1281     }
1282 
1283     void i18nPKCS11Test() throws Exception {
1284         //PKCS#11 tests
1285 
1286         //   1. sccs edit cert8.db key3.db
1287         //Runtime.getRuntime().exec("/usr/ccs/bin/sccs edit cert8.db key3.db");
1288         testOK("", p11Arg + "-storepass test12 -genkey -alias genkey -dname cn=genkey -keysize 512 -keyalg rsa");
1289         testOK("", p11Arg + "-storepass test12 -list");
1290         testOK("", p11Arg + "-storepass test12 -list -alias genkey");
1291         testOK("", p11Arg + "-storepass test12 -certreq -alias genkey -file genkey.certreq");
1292         testOK("", p11Arg + "-storepass test12 -export -alias genkey -file genkey.cert");
1293         testOK("", "-printcert -file genkey.cert");
1294         testOK("", p11Arg + "-storepass test12 -selfcert -alias genkey -dname cn=selfCert");
1295         testOK("", p11Arg + "-storepass test12 -list -alias genkey -v");
1296         assertTrue(out.indexOf("Owner: CN=selfCert") != -1);
1297         //(check that cert subject DN is [cn=selfCert])
1298         testOK("", p11Arg + "-storepass test12 -delete -alias genkey");
1299         testOK("", p11Arg + "-storepass test12 -list");
1300         assertTrue(out.indexOf("Your keystore contains 0 entries") != -1);
1301         //(check for empty database listing)
1302         //Runtime.getRuntime().exec("/usr/ccs/bin/sccs unedit cert8.db key3.db");
1303         remove("genkey.cert");
1304         remove("genkey.certreq");
1305         //  12. sccs unedit cert8.db key3.db
1306     }
1307 
1308     // tesing new option -srcProviderName
1309     void sszzTest() throws Exception {
1310         testAnyway("", NSS_P11_ARG+"-delete -alias nss -storepass test12");
1311         testAnyway("", NZZ_P11_ARG+"-delete -alias nss -storepass test12");
1312         testOK("", NSS_P11_ARG+"-genkeypair -dname CN=NSS -alias nss -storepass test12");
1313         testOK("", NSS_SRC_P11_ARG + NZZ_P11_ARG +
1314                 "-importkeystore -srcstorepass test12 -deststorepass test12");
1315         testAnyway("", NSS_P11_ARG+"-delete -alias nss -storepass test12");
1316         testAnyway("", NZZ_P11_ARG+"-delete -alias nss -storepass test12");
1317     }
1318 
1319     public static void main(String[] args) throws Exception {
1320         Locale reservedLocale = Locale.getDefault();
1321         try {
1322             // first test if HumanInputStream really acts like a human being
1323             HumanInputStream.test();
1324             KeyToolTest t = new KeyToolTest();
1325 
1326             if (System.getProperty("file") != null) {
1327                 t.sqeTest();
1328                 t.testAll();
1329                 t.i18nTest();
1330                 t.v3extTest("RSA");
1331                 t.v3extTest("DSA");
1332                 boolean testEC = true;
1333                 try {
1334                     KeyPairGenerator.getInstance("EC");
1335                 } catch (NoSuchAlgorithmException nae) {
1336                     testEC = false;
1337                 }
1338                 if (testEC) t.v3extTest("EC");
1339             }
1340 
1341             if (System.getProperty("nss") != null) {
1342                 t.srcP11Arg = NSS_SRC_P11_ARG;
1343                 t.p11Arg = NSS_P11_ARG;
1344 
1345                 t.testPKCS11();
1346 
1347                 // FAIL:
1348                 // 1. we still don't have srcprovidername yet
1349                 // 2. cannot store privatekey into NSS keystore
1350                 //    java.security.KeyStoreException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_TEMPLATE_INCOMPLETE.
1351                 //t.testPKCS11ImportKeyStore();
1352 
1353                 t.i18nPKCS11Test();
1354                 //FAIL: currently PKCS11-NSS does not support 2 NSS KeyStores to be loaded at the same time
1355                 //t.sszzTest();
1356             }
1357 
1358             if (System.getProperty("solaris") != null) {
1359                 // For Solaris Cryptography Framework
1360                 t.srcP11Arg = SUN_SRC_P11_ARG;
1361                 t.p11Arg = SUN_P11_ARG;
1362                 t.testPKCS11();
1363                 t.testPKCS11ImportKeyStore();
1364                 t.i18nPKCS11Test();
1365             }
1366 
1367             System.out.println("Test pass!!!");
1368         } finally {
1369             // restore the reserved locale
1370             Locale.setDefault(reservedLocale);
1371         }
1372     }
1373 }
1374 
1375 class TestException extends Exception {
1376     public TestException(String e) {
1377         super(e);
1378     }
1379 }
1380 
1381 /**
1382  * HumanInputStream tries to act like a human sitting in front of a computer
1383  * terminal typing on the keyboard while the keytool program is running.
1384  *
1385  * keytool has called InputStream.read() and BufferedReader.readLine() in
1386  * various places. a call to B.readLine() will try to buffer as much input as
1387  * possible. Thus, a trivial InputStream will find it impossible to feed
1388  * anything to I.read() after a B.readLine() call.
1389  *
1390  * This is why i create HumanInputStream, which will only send a single line
1391  * to B.readLine(), no more, no less, and the next I.read() can have a chance
1392  * to read the exact character right after "\n".
1393  *
1394  * I don't know why HumanInputStream works.
1395  */
1396 class HumanInputStream extends InputStream {
1397     byte[] src;
1398     int pos;
1399     int length;
1400     boolean inLine;
1401     int stopIt;
1402 
1403     public HumanInputStream(String input) {
1404         src = input.getBytes();
1405         pos = 0;
1406         length = src.length;
1407         stopIt = 0;
1408         inLine = false;
1409     }
1410 
1411     // the trick: when called through read(byte[], int, int),
1412     // return -1 twice after "\n"
1413 
1414     @Override public int read() throws IOException {
1415         int re;
1416         if(pos < length) {
1417             re = src[pos];
1418             if(inLine) {
1419                 if(stopIt > 0) {
1420                     stopIt--;
1421                     re = -1;
1422                 } else {
1423                     if(re == '\n') {
1424                         stopIt = 2;
1425                     }
1426                     pos++;
1427                 }
1428             } else {
1429                 pos++;
1430             }
1431         } else {
1432             re = -1;//throw new IOException("NO MORE TO READ");
1433         }
1434         //if (re < 32) System.err.printf("[%02d]", re);
1435         //else System.err.printf("[%c]", (char)re);
1436         return re;
1437     }
1438     @Override public int read(byte[] buffer, int offset, int len) {
1439         inLine = true;
1440         try {
1441             int re = super.read(buffer, offset, len);
1442             return re;
1443         } catch(Exception e) {
1444             throw new RuntimeException("HumanInputStream error");
1445         } finally {
1446             inLine = false;
1447         }
1448     }
1449     @Override public int available() {
1450         if(pos < length) return 1;
1451         return 0;
1452     }
1453 
1454     // test part
1455     static void assertTrue(boolean bool) {
1456         if(!bool)
1457             throw new RuntimeException();
1458     }
1459 
1460     public static void test() throws Exception {
1461 
1462         class Tester {
1463             HumanInputStream is;
1464             BufferedReader reader;
1465             Tester(String s) {
1466                 is = new HumanInputStream(s);
1467                 reader = new BufferedReader(new InputStreamReader(is));
1468             }
1469 
1470             // three kinds of test method
1471             // 1. read byte by byte from InputStream
1472             void testStreamReadOnce(int expection) throws Exception {
1473                 assertTrue(is.read() == expection);
1474             }
1475             void testStreamReadMany(String expection) throws Exception {
1476                 char[] keys = expection.toCharArray();
1477                 for(int i=0; i<keys.length; i++) {
1478                     assertTrue(is.read() == keys[i]);
1479                 }
1480             }
1481             // 2. read a line with a newly created Reader
1482             void testReaderReadline(String expection) throws Exception {
1483                 String s = new BufferedReader(new InputStreamReader(is)).readLine();
1484                 if(s == null) assertTrue(expection == null);
1485                 else assertTrue(s.equals(expection));
1486             }
1487             // 3. read a line with the old Reader
1488             void testReaderReadline2(String expection) throws Exception  {
1489                 String s = reader.readLine();
1490                 if(s == null) assertTrue(expection == null);
1491                 else assertTrue(s.equals(expection));
1492             }
1493         }
1494 
1495         Tester test;
1496 
1497         test = new Tester("111\n222\n\n444\n\n");
1498         test.testReaderReadline("111");
1499         test.testReaderReadline("222");
1500         test.testReaderReadline("");
1501         test.testReaderReadline("444");
1502         test.testReaderReadline("");
1503         test.testReaderReadline(null);
1504 
1505         test = new Tester("111\n222\n\n444\n\n");
1506         test.testReaderReadline2("111");
1507         test.testReaderReadline2("222");
1508         test.testReaderReadline2("");
1509         test.testReaderReadline2("444");
1510         test.testReaderReadline2("");
1511         test.testReaderReadline2(null);
1512 
1513         test = new Tester("111\n222\n\n444\n\n");
1514         test.testReaderReadline2("111");
1515         test.testReaderReadline("222");
1516         test.testReaderReadline2("");
1517         test.testReaderReadline2("444");
1518         test.testReaderReadline("");
1519         test.testReaderReadline2(null);
1520 
1521         test = new Tester("1\n2");
1522         test.testStreamReadMany("1\n2");
1523         test.testStreamReadOnce(-1);
1524 
1525         test = new Tester("12\n234");
1526         test.testStreamReadOnce('1');
1527         test.testReaderReadline("2");
1528         test.testStreamReadOnce('2');
1529         test.testReaderReadline2("34");
1530         test.testReaderReadline2(null);
1531 
1532         test = new Tester("changeit\n");
1533         test.testStreamReadMany("changeit\n");
1534         test.testReaderReadline(null);
1535 
1536         test = new Tester("changeit\nName\nCountry\nYes\n");
1537         test.testStreamReadMany("changeit\n");
1538         test.testReaderReadline("Name");
1539         test.testReaderReadline("Country");
1540         test.testReaderReadline("Yes");
1541         test.testReaderReadline(null);
1542 
1543         test = new Tester("Me\nHere\n");
1544         test.testReaderReadline2("Me");
1545         test.testReaderReadline2("Here");
1546     }
1547 }