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 */
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      */
remove(String filename)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      */
test(String input, String cmd)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 
test(InputStream in, String cmd)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      */
testOK(String input, String cmd)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      */
testFail(String input, String cmd)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      */
testOK(InputStream is, String cmd)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      */
testFail(InputStream is, String cmd)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      */
testAnyway(String input, String cmd)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      */
afterFail(String input, String cmd, String should)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 
assertTrue(boolean bool, String msg)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 
assertTrue(boolean bool)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      */
loadStore(String file, String pass, String type)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      */
testAll()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 
testPKCS11()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 
testPKCS11ImportKeyStore()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     //
sqeTest()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
sqeImportTest()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
sqeKeyclonetest()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
sqeKeypasswdTest()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
sqeListTest()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
sqeSelfCertTest()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
sqeStorepassTest()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 
sqeGenkeyTest()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 
sqeExportTest()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 
sqeDeleteTest()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 
sqeCsrTest()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 
sqePrintcertTest()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
checkPem(String file)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 
v3extTest(String keyAlg)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 
i18nTest()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 
i18nPKCS11Test()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
sszzTest()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 
main(String[] args)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 {
TestException(String e)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 
HumanInputStream(String input)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 
read()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     }
read(byte[] buffer, int offset, int len)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     }
available()1449     @Override public int available() {
1450         if(pos < length) return 1;
1451         return 0;
1452     }
1453 
1454     // test part
assertTrue(boolean bool)1455     static void assertTrue(boolean bool) {
1456         if(!bool)
1457             throw new RuntimeException();
1458     }
1459 
test()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 }
1548