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+"san235 -ext san=uri:http://me.org,dns:me.org,oid:1.2.3.4");
1032 
1033         ks = loadStore("x.jks", "changeit", "JKS");
1034         class CheckSAN {
1035             // Please sort items with name type
1036             void check(KeyStore ks, String alias, int type, Object... items) throws Exception {
1037                 int pos = 0;
1038                 System.err.print("x");
1039                 Object[] names = null;
1040                 if (type == 0) names = ((X509Certificate)ks.getCertificate(alias)).getSubjectAlternativeNames().toArray();
1041                 else names = ((X509Certificate)ks.getCertificate(alias)).getIssuerAlternativeNames().toArray();
1042                 Arrays.sort(names, new Comparator() {
1043                     public int compare(Object o1, Object o2) {
1044                         int i1 = (Integer)((List)o1).get(0);
1045                         int i2 = (Integer)((List)o2).get(0);
1046                         return i1 - i2;
1047                     }
1048                 });
1049                 for (Object o: names) {
1050                     List l = (List)o;
1051                     for (Object o2: l) {
1052                         if (!items[pos++].equals(o2)) {
1053                             throw new RuntimeException("Not equals at " + pos
1054                                     + ": " + items[pos-1] + " vs " + o2);
1055                         }
1056                     }
1057                 }
1058                 if (pos != items.length) {
1059                     throw new RuntimeException("Extra items, pos is " + pos);
1060                 }
1061             }
1062         }
1063         CheckSAN csan = new CheckSAN();
1064         assertTrue(((X509CertImpl)ks.getCertificate("san1")).getSubjectAlternativeNameExtension().isCritical());
1065         assertTrue(!((X509CertImpl)ks.getCertificate("san2")).getSubjectAlternativeNameExtension().isCritical());
1066         csan.check(ks, "san1", 0, 1, "me@me.org");
1067         csan.check(ks, "san2", 0, 6, "http://me.org");
1068         csan.check(ks, "san3", 0, 2, "me.org");
1069         csan.check(ks, "san4", 0, 7, "192.168.0.1");
1070         csan.check(ks, "san5", 0, 8, "1.2.3.4");
1071         csan.check(ks, "san235", 0, 2, "me.org", 6, "http://me.org", 8, "1.2.3.4");
1072 
1073         // IAN
1074         testOK("", pre+"ian1 -ext ian:critical=email:me@me.org");
1075         testOK("", pre+"ian2 -ext ian=uri:http://me.org");
1076         testOK("", pre+"ian3 -ext ian=dns:me.org");
1077         testOK("", pre+"ian4 -ext ian=ip:192.168.0.1");
1078         testOK("", pre+"ian5 -ext ian=oid:1.2.3.4");
1079         testOK("", pre+"ian235 -ext ian=uri:http://me.org,dns:me.org,oid:1.2.3.4");
1080 
1081         ks = loadStore("x.jks", "changeit", "JKS");
1082         assertTrue(((X509CertImpl)ks.getCertificate("ian1")).getIssuerAlternativeNameExtension().isCritical());
1083         assertTrue(!((X509CertImpl)ks.getCertificate("ian2")).getIssuerAlternativeNameExtension().isCritical());
1084         csan.check(ks, "ian1", 1, 1, "me@me.org");
1085         csan.check(ks, "ian2", 1, 6, "http://me.org");
1086         csan.check(ks, "ian3", 1, 2, "me.org");
1087         csan.check(ks, "ian4", 1, 7, "192.168.0.1");
1088         csan.check(ks, "ian5", 1, 8, "1.2.3.4");
1089         csan.check(ks, "ian235", 1, 2, "me.org", 6, "http://me.org", 8, "1.2.3.4");
1090 
1091         // SIA
1092         testOK("", pre+"sia1 -ext sia=care:uri:ldap://ca.com/cn=CA");
1093         testOK("", pre+"sia2 -ext sia=ts:email:ts@ca.com");
1094         testFail("SIA never critical", pre+"sia3 -ext sia:critical=ts:email:ts@ca.com");
1095 
1096         ks = loadStore("x.jks", "changeit", "JKS");
1097         class CheckSia {
1098             void check(KeyStore ks, String alias, int type, Object... items) throws Exception {
1099                 int pos = 0;
1100                 System.err.print("x");
1101                 AccessDescription[] ads = null;
1102                 if (type == 0) {
1103                     SubjectInfoAccessExtension siae = (SubjectInfoAccessExtension)((X509CertImpl)ks.getCertificate(alias)).getExtension(PKIXExtensions.SubjectInfoAccess_Id);
1104                     ads = siae.getAccessDescriptions().toArray(new AccessDescription[0]);
1105                 } else {
1106                     AuthorityInfoAccessExtension aiae = (AuthorityInfoAccessExtension)((X509CertImpl)ks.getCertificate(alias)).getExtension(PKIXExtensions.AuthInfoAccess_Id);
1107                     ads = aiae.getAccessDescriptions().toArray(new AccessDescription[0]);
1108                 }
1109                 Arrays.sort(ads, new Comparator<AccessDescription>() {
1110                     @Override
1111                     public int compare(AccessDescription o1, AccessDescription o2) {
1112                         return o1.getAccessMethod().toString().compareTo(o2.getAccessMethod().toString());
1113                     }
1114                 });
1115                 for (AccessDescription ad: ads) {
1116                     if (!ad.getAccessMethod().equals(items[pos++]) ||
1117                             !new Integer(ad.getAccessLocation().getType()).equals(items[pos++])) {
1118                         throw new RuntimeException("Not same type at " + pos);
1119                     }
1120                     String name = null;
1121                     switch (ad.getAccessLocation().getType()) {
1122                         case 1:
1123                             name = ((RFC822Name)ad.getAccessLocation().getName()).getName();
1124                             break;
1125                         case 6:
1126                             name = ((URIName)ad.getAccessLocation().getName()).getURI().toString();
1127                             break;
1128                         default:
1129                             throw new RuntimeException("Not implemented: " + ad);
1130                     }
1131                     if (!name.equals(items[pos++])) {
1132                         throw new Exception("Name not same for " + ad + " at pos " + pos);
1133                     }
1134                 }
1135             }
1136         }
1137         CheckSia csia = new CheckSia();
1138         assertTrue(!((X509CertImpl)ks.getCertificate("sia1")).getExtension(PKIXExtensions.SubjectInfoAccess_Id).isCritical());
1139         csia.check(ks, "sia1", 0, AccessDescription.Ad_CAREPOSITORY_Id, 6, "ldap://ca.com/cn=CA");
1140         csia.check(ks, "sia2", 0, AccessDescription.Ad_TIMESTAMPING_Id, 1, "ts@ca.com");
1141 
1142         // AIA
1143         testOK("", pre+"aia1 -ext aia=cai:uri:ldap://ca.com/cn=CA");
1144         testOK("", pre+"aia2 -ext aia=ocsp:email:ocsp@ca.com");
1145         testFail("AIA never critical", pre+"aia3 -ext aia:critical=ts:email:ts@ca.com");
1146 
1147         ks = loadStore("x.jks", "changeit", "JKS");
1148         assertTrue(!((X509CertImpl)ks.getCertificate("aia1")).getExtension(PKIXExtensions.AuthInfoAccess_Id).isCritical());
1149         csia.check(ks, "aia1", 1, AccessDescription.Ad_CAISSUERS_Id, 6, "ldap://ca.com/cn=CA");
1150         csia.check(ks, "aia2", 1, AccessDescription.Ad_OCSP_Id, 1, "ocsp@ca.com");
1151 
1152         // OID
1153         testOK("", pre+"oid1 -ext 1.2.3:critical=0102");
1154         testOK("", pre+"oid2 -ext 1.2.3");
1155         testOK("", pre+"oid12 -ext 1.2.3 -ext 1.2.4=01:02:03");
1156 
1157         ks = loadStore("x.jks", "changeit", "JKS");
1158         class CheckOid {
1159             void check(KeyStore ks, String alias, String oid, byte[] value) throws Exception {
1160                 int pos = 0;
1161                 System.err.print("x");
1162                 Extension ex = ((X509CertImpl)ks.getCertificate(alias)).getExtension(new ObjectIdentifier(oid));
1163                 if (!Arrays.equals(value, ex.getValue())) {
1164                     throw new RuntimeException("Not same content in " + alias + " for " + oid);
1165                 }
1166             }
1167         }
1168         CheckOid coid = new CheckOid();
1169         assertTrue(((X509CertImpl)ks.getCertificate("oid1")).getExtension(new ObjectIdentifier("1.2.3")).isCritical());
1170         assertTrue(!((X509CertImpl)ks.getCertificate("oid2")).getExtension(new ObjectIdentifier("1.2.3")).isCritical());
1171         coid.check(ks, "oid1", "1.2.3", new byte[]{1,2});
1172         coid.check(ks, "oid2", "1.2.3", new byte[]{});
1173         coid.check(ks, "oid12", "1.2.3", new byte[]{});
1174         coid.check(ks, "oid12", "1.2.4", new byte[]{1,2,3});
1175 
1176         // honored
1177         testOK("", pre+"ca");
1178         testOK("", pre+"a");
1179         // request: BC,KU,1.2.3,1.2.4,1.2.5
1180         testOK("", simple+"-alias a -certreq " +
1181                 "-ext BC=1 -ext KU=crl " +
1182                 "-ext 1.2.3=01 -ext 1.2.4:critical=0102 -ext 1.2.5=010203 " +
1183                 "-rfc -file test.req");
1184         // printcertreq
1185         testOK("", "-printcertreq -file test.req");
1186         checkPem("test.req");
1187         // issue: deny KU, change criticality of 1.2.3 and 1.2.4,
1188         // change content of BC, add 2.3.4
1189         testOK("", simple+"-gencert -alias ca -infile test.req -ext " +
1190                 "honored=all,-KU,1.2.3:critical,1.2.4:non-critical " +
1191                 "-ext BC=2 -ext 2.3.4=01020304 " +
1192                 "-debug -rfc -outfile test.cert");
1193         checkPem("test.cert");
1194         testOK("", simple+"-importcert -file test.cert -alias a");
1195         ks = loadStore("x.jks", "changeit", "JKS");
1196         X509CertImpl a = (X509CertImpl)ks.getCertificate("a");
1197         assertTrue(a.getAuthorityKeyIdentifierExtension() != null);
1198         assertTrue(a.getSubjectKeyIdentifierExtension() != null);
1199         assertTrue(a.getKeyUsage() == null);
1200         assertTrue(a.getExtension(new ObjectIdentifier("1.2.3")).isCritical());
1201         assertTrue(!a.getExtension(new ObjectIdentifier("1.2.4")).isCritical());
1202         assertTrue(!a.getExtension(new ObjectIdentifier("1.2.5")).isCritical());
1203         assertTrue(a.getExtensionValue("1.2.3").length == 3);
1204         assertTrue(a.getExtensionValue("1.2.4").length == 4);
1205         assertTrue(a.getExtensionValue("1.2.5").length == 5);
1206         assertTrue(a.getBasicConstraints() == 2);
1207         assertTrue(!a.getExtension(new ObjectIdentifier("2.3.4")).isCritical());
1208         assertTrue(a.getExtensionValue("2.3.4").length == 6);
1209 
1210         remove("x.jks");
1211         remove("test.req");
1212         remove("test.cert");
1213     }
1214 
1215     void i18nTest() throws Exception {
1216         //   1.  keytool -help
1217         remove("x.jks");
1218         testOK("", "-help");
1219 
1220         //   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.
1221         testOK("a\npassword\npassword\nMe\nHere\nNow\nPlace\nPlace\nUS\nyes\n\n", "-genkey -v -keysize 512 -keystore x.jks");
1222         //   3. keytool -list -v -storepass password
1223         testOK("", "-list -v -storepass password -keystore x.jks");
1224         //   4. keytool -list -v Type "a" for the keystore password. Check error (wrong keystore password).
1225         testFail("a\n", "-list -v -keystore x.jks");
1226         assertTrue(ex.indexOf("password was incorrect") != -1);
1227         //   5. keytool -genkey -v -keysize 512 Enter "password" as the password. Check error (alias 'mykey' already exists).
1228         testFail("password\n", "-genkey -v -keysize 512 -keystore x.jks");
1229         assertTrue(ex.indexOf("alias <mykey> already exists") != -1);
1230         //   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.
1231         testOK("\n\n\n\n\n\nyes\n\n", "-genkey -v -keysize 512 -alias mykey2 -storepass password -keystore x.jks");
1232         //   7. keytool -list -v Type 'password' for the store password.
1233         testOK("password\n", "-list -v -keystore x.jks");
1234         //   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).
1235         testFail("a\naaaaaa\nbbbbbb\na\n", "-keypasswd -v -alias mykey2 -storepass password -keystore x.jks");
1236         assertTrue(ex.indexOf("Too many failures - try later") != -1);
1237         //   9. keytool -keypasswd -v -alias mykey2 -storepass password Type "aaaaaa" for the new key password. Type "aaaaaa" when re-entering the new key password.
1238         testOK("aaaaaa\naaaaaa\n", "-keypasswd -v -alias mykey2 -storepass password -keystore x.jks");
1239         //  10. keytool -selfcert -v -alias mykey -storepass password
1240         testOK("", "-selfcert -v -alias mykey -storepass password -keystore x.jks");
1241         //  11. keytool -list -v -storepass password
1242         testOK("", "-list -v -storepass password -keystore x.jks");
1243         //  12. keytool -export -v -alias mykey -file cert -storepass password
1244         remove("cert");
1245         testOK("", "-export -v -alias mykey -file cert -storepass password -keystore x.jks");
1246         //  13. keytool -import -v -file cert -storepass password Check error (Certificate reply and cert are the same)
1247         testFail("", "-import -v -file cert -storepass password -keystore x.jks");
1248         assertTrue(ex.indexOf("Certificate reply and certificate in keystore are identical") != -1);
1249         //  14. keytool -printcert -file cert
1250         testOK("", "-printcert -file cert -keystore x.jks");
1251         remove("cert");
1252         //  15. keytool -list -storepass password -provider sun.security.provider.Sun
1253         testOK("", "-list -storepass password -provider sun.security.provider.Sun -keystore x.jks");
1254 
1255         //Error tests
1256 
1257         //   1. keytool -storepasswd -storepass password -new abc Check error (password too short)
1258         testFail("", "-storepasswd -storepass password -new abc");
1259         assertTrue(ex.indexOf("New password must be at least 6 characters") != -1);
1260         // Changed, no NONE needed now
1261         //   2. keytool -list -storetype PKCS11 Check error (-keystore must be NONE)
1262         //testFail("", "-list -storetype PKCS11");
1263         //assertTrue(err.indexOf("keystore must be NONE") != -1);
1264         //   3. keytool -storepasswd -storetype PKCS11 -keystore NONE Check error (unsupported operation)
1265         testFail("", "-storepasswd -storetype PKCS11 -keystore NONE");
1266         assertTrue(ex.indexOf("UnsupportedOperationException") != -1);
1267         //   4. keytool -keypasswd -storetype PKCS11 -keystore NONE Check error (unsupported operation)
1268         testFail("", "-keypasswd -storetype PKCS11 -keystore NONE");
1269         assertTrue(ex.indexOf("UnsupportedOperationException") != -1);
1270         //   5. keytool -list -protected -storepass password Check error (password can not be specified with -protected)
1271         testFail("", "-list -protected -storepass password -keystore x.jks");
1272         assertTrue(ex.indexOf("if -protected is specified, then") != -1);
1273         //   6. keytool -keypasswd -protected -keypass password Check error (password can not be specified with -protected)
1274         testFail("", "-keypasswd -protected -keypass password -keystore x.jks");
1275         assertTrue(ex.indexOf("if -protected is specified, then") != -1);
1276         //   7. keytool -keypasswd -protected -new password Check error (password can not be specified with -protected)
1277         testFail("", "-keypasswd -protected -new password -keystore x.jks");
1278         assertTrue(ex.indexOf("if -protected is specified, then") != -1);
1279         remove("x.jks");
1280     }
1281 
1282     void i18nPKCS11Test() throws Exception {
1283         //PKCS#11 tests
1284 
1285         //   1. sccs edit cert8.db key3.db
1286         //Runtime.getRuntime().exec("/usr/ccs/bin/sccs edit cert8.db key3.db");
1287         testOK("", p11Arg + "-storepass test12 -genkey -alias genkey -dname cn=genkey -keysize 512 -keyalg rsa");
1288         testOK("", p11Arg + "-storepass test12 -list");
1289         testOK("", p11Arg + "-storepass test12 -list -alias genkey");
1290         testOK("", p11Arg + "-storepass test12 -certreq -alias genkey -file genkey.certreq");
1291         testOK("", p11Arg + "-storepass test12 -export -alias genkey -file genkey.cert");
1292         testOK("", "-printcert -file genkey.cert");
1293         testOK("", p11Arg + "-storepass test12 -selfcert -alias genkey -dname cn=selfCert");
1294         testOK("", p11Arg + "-storepass test12 -list -alias genkey -v");
1295         assertTrue(out.indexOf("Owner: CN=selfCert") != -1);
1296         //(check that cert subject DN is [cn=selfCert])
1297         testOK("", p11Arg + "-storepass test12 -delete -alias genkey");
1298         testOK("", p11Arg + "-storepass test12 -list");
1299         assertTrue(out.indexOf("Your keystore contains 0 entries") != -1);
1300         //(check for empty database listing)
1301         //Runtime.getRuntime().exec("/usr/ccs/bin/sccs unedit cert8.db key3.db");
1302         remove("genkey.cert");
1303         remove("genkey.certreq");
1304         //  12. sccs unedit cert8.db key3.db
1305     }
1306 
1307     // tesing new option -srcProviderName
1308     void sszzTest() throws Exception {
1309         testAnyway("", NSS_P11_ARG+"-delete -alias nss -storepass test12");
1310         testAnyway("", NZZ_P11_ARG+"-delete -alias nss -storepass test12");
1311         testOK("", NSS_P11_ARG+"-genkeypair -dname CN=NSS -alias nss -storepass test12");
1312         testOK("", NSS_SRC_P11_ARG + NZZ_P11_ARG +
1313                 "-importkeystore -srcstorepass test12 -deststorepass test12");
1314         testAnyway("", NSS_P11_ARG+"-delete -alias nss -storepass test12");
1315         testAnyway("", NZZ_P11_ARG+"-delete -alias nss -storepass test12");
1316     }
1317 
1318     public static void main(String[] args) throws Exception {
1319         Locale reservedLocale = Locale.getDefault();
1320         try {
1321             // first test if HumanInputStream really acts like a human being
1322             HumanInputStream.test();
1323             KeyToolTest t = new KeyToolTest();
1324 
1325             if (System.getProperty("file") != null) {
1326                 t.sqeTest();
1327                 t.testAll();
1328                 t.i18nTest();
1329                 t.v3extTest("RSA");
1330                 t.v3extTest("DSA");
1331                 boolean testEC = true;
1332                 try {
1333                     KeyPairGenerator.getInstance("EC");
1334                 } catch (NoSuchAlgorithmException nae) {
1335                     testEC = false;
1336                 }
1337                 if (testEC) t.v3extTest("EC");
1338             }
1339 
1340             if (System.getProperty("nss") != null) {
1341                 t.srcP11Arg = NSS_SRC_P11_ARG;
1342                 t.p11Arg = NSS_P11_ARG;
1343 
1344                 t.testPKCS11();
1345 
1346                 // FAIL:
1347                 // 1. we still don't have srcprovidername yet
1348                 // 2. cannot store privatekey into NSS keystore
1349                 //    java.security.KeyStoreException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_TEMPLATE_INCOMPLETE.
1350                 //t.testPKCS11ImportKeyStore();
1351 
1352                 t.i18nPKCS11Test();
1353                 //FAIL: currently PKCS11-NSS does not support 2 NSS KeyStores to be loaded at the same time
1354                 //t.sszzTest();
1355             }
1356 
1357             if (System.getProperty("solaris") != null) {
1358                 // For Solaris Cryptography Framework
1359                 t.srcP11Arg = SUN_SRC_P11_ARG;
1360                 t.p11Arg = SUN_P11_ARG;
1361                 t.testPKCS11();
1362                 t.testPKCS11ImportKeyStore();
1363                 t.i18nPKCS11Test();
1364             }
1365 
1366             System.out.println("Test pass!!!");
1367         } finally {
1368             // restore the reserved locale
1369             Locale.setDefault(reservedLocale);
1370         }
1371     }
1372 }
1373 
1374 class TestException extends Exception {
1375     public TestException(String e) {
1376         super(e);
1377     }
1378 }
1379 
1380 /**
1381  * HumanInputStream tries to act like a human sitting in front of a computer
1382  * terminal typing on the keyboard while the keytool program is running.
1383  *
1384  * keytool has called InputStream.read() and BufferedReader.readLine() in
1385  * various places. a call to B.readLine() will try to buffer as much input as
1386  * possible. Thus, a trivial InputStream will find it impossible to feed
1387  * anything to I.read() after a B.readLine() call.
1388  *
1389  * This is why i create HumanInputStream, which will only send a single line
1390  * to B.readLine(), no more, no less, and the next I.read() can have a chance
1391  * to read the exact character right after "\n".
1392  *
1393  * I don't know why HumanInputStream works.
1394  */
1395 class HumanInputStream extends InputStream {
1396     byte[] src;
1397     int pos;
1398     int length;
1399     boolean inLine;
1400     int stopIt;
1401 
1402     public HumanInputStream(String input) {
1403         src = input.getBytes();
1404         pos = 0;
1405         length = src.length;
1406         stopIt = 0;
1407         inLine = false;
1408     }
1409 
1410     // the trick: when called through read(byte[], int, int),
1411     // return -1 twice after "\n"
1412 
1413     @Override public int read() throws IOException {
1414         int re;
1415         if(pos < length) {
1416             re = src[pos];
1417             if(inLine) {
1418                 if(stopIt > 0) {
1419                     stopIt--;
1420                     re = -1;
1421                 } else {
1422                     if(re == '\n') {
1423                         stopIt = 2;
1424                     }
1425                     pos++;
1426                 }
1427             } else {
1428                 pos++;
1429             }
1430         } else {
1431             re = -1;//throw new IOException("NO MORE TO READ");
1432         }
1433         //if (re < 32) System.err.printf("[%02d]", re);
1434         //else System.err.printf("[%c]", (char)re);
1435         return re;
1436     }
1437     @Override public int read(byte[] buffer, int offset, int len) {
1438         inLine = true;
1439         try {
1440             int re = super.read(buffer, offset, len);
1441             return re;
1442         } catch(Exception e) {
1443             throw new RuntimeException("HumanInputStream error");
1444         } finally {
1445             inLine = false;
1446         }
1447     }
1448     @Override public int available() {
1449         if(pos < length) return 1;
1450         return 0;
1451     }
1452 
1453     // test part
1454     static void assertTrue(boolean bool) {
1455         if(!bool)
1456             throw new RuntimeException();
1457     }
1458 
1459     public static void test() throws Exception {
1460 
1461         class Tester {
1462             HumanInputStream is;
1463             BufferedReader reader;
1464             Tester(String s) {
1465                 is = new HumanInputStream(s);
1466                 reader = new BufferedReader(new InputStreamReader(is));
1467             }
1468 
1469             // three kinds of test method
1470             // 1. read byte by byte from InputStream
1471             void testStreamReadOnce(int expection) throws Exception {
1472                 assertTrue(is.read() == expection);
1473             }
1474             void testStreamReadMany(String expection) throws Exception {
1475                 char[] keys = expection.toCharArray();
1476                 for(int i=0; i<keys.length; i++) {
1477                     assertTrue(is.read() == keys[i]);
1478                 }
1479             }
1480             // 2. read a line with a newly created Reader
1481             void testReaderReadline(String expection) throws Exception {
1482                 String s = new BufferedReader(new InputStreamReader(is)).readLine();
1483                 if(s == null) assertTrue(expection == null);
1484                 else assertTrue(s.equals(expection));
1485             }
1486             // 3. read a line with the old Reader
1487             void testReaderReadline2(String expection) throws Exception  {
1488                 String s = reader.readLine();
1489                 if(s == null) assertTrue(expection == null);
1490                 else assertTrue(s.equals(expection));
1491             }
1492         }
1493 
1494         Tester test;
1495 
1496         test = new Tester("111\n222\n\n444\n\n");
1497         test.testReaderReadline("111");
1498         test.testReaderReadline("222");
1499         test.testReaderReadline("");
1500         test.testReaderReadline("444");
1501         test.testReaderReadline("");
1502         test.testReaderReadline(null);
1503 
1504         test = new Tester("111\n222\n\n444\n\n");
1505         test.testReaderReadline2("111");
1506         test.testReaderReadline2("222");
1507         test.testReaderReadline2("");
1508         test.testReaderReadline2("444");
1509         test.testReaderReadline2("");
1510         test.testReaderReadline2(null);
1511 
1512         test = new Tester("111\n222\n\n444\n\n");
1513         test.testReaderReadline2("111");
1514         test.testReaderReadline("222");
1515         test.testReaderReadline2("");
1516         test.testReaderReadline2("444");
1517         test.testReaderReadline("");
1518         test.testReaderReadline2(null);
1519 
1520         test = new Tester("1\n2");
1521         test.testStreamReadMany("1\n2");
1522         test.testStreamReadOnce(-1);
1523 
1524         test = new Tester("12\n234");
1525         test.testStreamReadOnce('1');
1526         test.testReaderReadline("2");
1527         test.testStreamReadOnce('2');
1528         test.testReaderReadline2("34");
1529         test.testReaderReadline2(null);
1530 
1531         test = new Tester("changeit\n");
1532         test.testStreamReadMany("changeit\n");
1533         test.testReaderReadline(null);
1534 
1535         test = new Tester("changeit\nName\nCountry\nYes\n");
1536         test.testStreamReadMany("changeit\n");
1537         test.testReaderReadline("Name");
1538         test.testReaderReadline("Country");
1539         test.testReaderReadline("Yes");
1540         test.testReaderReadline(null);
1541 
1542         test = new Tester("Me\nHere\n");
1543         test.testReaderReadline2("Me");
1544         test.testReaderReadline2("Here");
1545     }
1546 }