1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.apache.harmony.security.tests.java.security;
18
19import junit.framework.TestCase;
20
21import org.apache.harmony.security.tests.support.KeyStoreTestSupport;
22import org.apache.harmony.security.tests.support.tmpCallbackHandler;
23
24import java.io.File;
25import java.io.FileOutputStream;
26import java.io.IOException;
27import java.security.KeyStore;
28import java.security.KeyStoreException;
29import java.security.NoSuchAlgorithmException;
30import java.security.Provider;
31import java.security.Security;
32import java.security.cert.CertificateException;
33import java.util.Enumeration;
34
35public class KeyStoreBuilderTest extends TestCase {
36
37    protected void setUp() throws Exception {
38        super.setUp();
39    }
40
41    protected void tearDown() throws Exception {
42        super.tearDown();
43    }
44
45    private static char[] pass = { 's', 't', 'o', 'r', 'e', 'p', 'w', 'd' };
46
47    private KeyStore.PasswordProtection protPass = new KeyStore.PasswordProtection(
48            pass);
49
50    private tmpCallbackHandler tmpCall = new tmpCallbackHandler();
51
52    private KeyStore.CallbackHandlerProtection callbackHand = new KeyStore.CallbackHandlerProtection(
53            tmpCall);
54
55    private MyProtectionParameter myProtParam = new MyProtectionParameter(
56            new byte[5]);
57
58    public static String[] validValues = KeyStoreTestSupport.validValues;
59
60    private static String defaultType = KeyStoreTestSupport.defaultType;
61
62
63    private static Provider defaultProvider = null;
64
65    static {
66        defaultProvider = Security.getProviders(
67                "KeyStore." + KeyStore.getDefaultType())[0];
68    }
69
70    /*
71     * test for constructor KeyStoreBuilder
72     */
73    public void testConstructor() {
74        KeyStoreBuilder ksb;
75        try {
76            ksb = new KeyStoreBuilder();
77            assertNotNull(ksb);
78
79            ksb.getKeyStore();
80            ksb.getProtectionParameter("test");
81        } catch (Exception e) {
82            fail("Unexpected exception " + e.getMessage());
83        }
84    }
85
86    /*
87     * test for method newInstance(KeyStore, KeyStore.ProtectionParameter)
88     */
89    public void testNewInstanceKeyStoreProtectionParameter()
90            throws KeyStoreException, NoSuchAlgorithmException, IOException,
91            CertificateException {
92        // exceptions verification
93
94        try {
95            KeyStore.Builder.newInstance(null, null);
96            fail("NullPointerException must be thrown");
97        } catch (NullPointerException e) {
98            // expected
99        }
100
101        try {
102            KeyStore.Builder.newInstance(null, protPass);
103            fail("NullPointerException must be thrown");
104        } catch (NullPointerException e) {
105            // expected
106        }
107
108        KeyStore.Builder ksB;
109
110        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
111        try {
112            KeyStore.Builder.newInstance(ks, null);
113            fail("NullPointerException must be thrown when ProtectionParameter is null");
114        } catch (NullPointerException e) {
115            // expected
116        }
117
118        KeyStore.PasswordProtection protPass1 = new KeyStore.PasswordProtection(
119                pass);
120        KeyStore.ProtectionParameter[] pp = { protPass, protPass1,
121                callbackHand, myProtParam };
122       for (int i = 0; i < pp.length; i++) {
123            ks = KeyStore.getInstance(KeyStore.getDefaultType());
124            try {
125                KeyStore.Builder.newInstance(ks, pp[i]);
126                fail("IllegalArgumentException must be thrown because KeyStore was not initialized");
127            } catch (IllegalArgumentException e) {
128                // expected
129            }
130
131            ks.load(null, pass);
132            ksB = KeyStore.Builder.newInstance(ks, pp[i]);
133
134            assertEquals("Incorrect KeyStore", ksB.getKeyStore().size(), 0);
135
136            ksB = KeyStore.Builder.newInstance(ks, pp[i]);
137
138            // verification getKeyStore() and getProtectionParameter(String
139            // alias)
140            assertEquals("Incorrect KeyStore", ks, ksB.getKeyStore());
141
142            try {
143                ksB.getProtectionParameter(null);
144                fail("NullPointerException must be thrown");
145            } catch (NullPointerException e) {
146            }
147            try {
148                assertEquals(ksB.getProtectionParameter("aaa"), pp[i]);
149            } catch (KeyStoreException e) {
150                fail("Unexpected: " + e.toString() + " was thrown");
151            }
152
153            try {
154                assertEquals(ksB.getProtectionParameter("Bad alias"), pp[i]);
155            } catch (KeyStoreException e) {
156                // KeyStoreException might be thrown because there is no entry
157                // with such alias
158            }
159
160            try {
161                assertEquals(ksB.getProtectionParameter(""), pp[i]);
162            } catch (KeyStoreException e) {
163                // KeyStoreException might be thrown because there is no entry
164                // with such alias
165            }
166
167            KeyStore.ProtectionParameter pPar = ksB
168                    .getProtectionParameter("aaa");
169
170            switch (i) {
171            case 0:
172                assertTrue(pPar instanceof KeyStore.PasswordProtection);
173                break;
174            case 1:
175                assertTrue(pPar instanceof KeyStore.PasswordProtection);
176                break;
177            case 2:
178                assertTrue(pPar instanceof KeyStore.CallbackHandlerProtection);
179                break;
180            case 3:
181                assertTrue(pPar instanceof MyProtectionParameter);
182                break;
183            default:
184                fail("Incorrect protection parameter");
185            }
186            assertEquals(pPar, pp[i]);
187        }
188    }
189
190    /*
191     * Test for methods: <code>newInstance(String type, Provider provider, File
192     * file, ProtectionParameter protectionParameter)</code> <code>getKeyStore()</code>
193     * <code>getProtectionParameter(String alias)</code> Assertions: throws
194     * NullPointerException if type, file or protectionParameter is null; throws
195     * IllegalArgumentException if file does not exist or is not file; throws
196     * IllegalArgumentException if ProtectionParameter is not PasswordProtection
197     * or CallbackHandlerProtection; returns new object
198     *
199     * getKeyStore() returns specified keystore; getProtectionParameter(String
200     * alias) throws NullPointerException when alias is null; throws
201     * KeyStoreException when alias is not available; returns
202     * ProtectionParameter which is used in newInstance(...)
203     *
204     */
205    public void testNewInstanceStringProviderFileProtectionParameter()
206            throws Exception {
207
208        File fl = File.createTempFile("KSBuilder_ImplTest", "keystore");
209        fl.deleteOnExit();
210        KeyStore.Builder ksB;
211        KeyStore.Builder ksB1;
212        KeyStore ks = null;
213        KeyStore ks1 = null;
214
215        MyProtectionParameter myPP = new MyProtectionParameter(new byte[5]);
216        // check exceptions
217        try {
218
219            KeyStore.Builder.newInstance(null, defaultProvider, fl, protPass);
220            fail("NullPointerException must be thrown when type is null");
221        } catch (NullPointerException e) {
222        }
223        try {
224            KeyStore.Builder.newInstance(KeyStore.getDefaultType(), defaultProvider, null,
225                    protPass);
226            fail("NullPointerException must be thrown when file is null");
227        } catch (NullPointerException e) {
228        }
229        try {
230            KeyStore.Builder
231                    .newInstance(KeyStore.getDefaultType(), defaultProvider, fl, null);
232            fail("NullPointerException must be thrown when ProtectionParameter is null");
233        } catch (NullPointerException e) {
234        }
235        try {
236            KeyStore.Builder
237                    .newInstance(KeyStore.getDefaultType(), defaultProvider, fl, myPP);
238            fail("IllegalArgumentException must be thrown when ProtectionParameter is not correct");
239        } catch (IllegalArgumentException e) {
240        }
241        try {
242            KeyStore.Builder.newInstance(KeyStore.getDefaultType(), defaultProvider,
243                    new File(fl.getAbsolutePath().concat("should_absent")),
244                    protPass);
245            fail("IllegalArgumentException must be thrown when file does not exist");
246        } catch (IllegalArgumentException e) {
247        }
248        try {
249            // 'file' param points to directory
250            KeyStore.Builder.newInstance(KeyStore.getDefaultType(), defaultProvider, fl
251                    .getParentFile(), protPass);
252            fail("IllegalArgumentException must be thrown when file does not exist");
253        } catch (IllegalArgumentException e) {
254        }
255        ksB = KeyStore.Builder.newInstance(KeyStore.getDefaultType(), defaultProvider, fl,
256                protPass);
257        try {
258            ksB.getKeyStore();
259            fail("KeyStoreException must be throw because file is empty");
260        } catch (KeyStoreException e) {
261        }
262
263        fl = createKS();
264
265        // Exception Tests with custom ProtectionParameter
266        try {
267            KeyStore.Builder.newInstance(KeyStore.getDefaultType(),
268                    null, fl, myPP);
269            fail("IllegalArgumentException must be "
270                    + "thrown for incorrect ProtectionParameter");
271        } catch (IllegalArgumentException e) {
272        }
273        try {
274            KeyStore.Builder.newInstance(KeyStore.getDefaultType(),
275                    defaultProvider, fl, myPP);
276            fail("IllegalArgumentException must be "
277                    + "thrown for incorrect ProtectionParameter");
278        } catch (IllegalArgumentException e) {
279        }
280
281        // Tests with PasswordProtection
282        ksB = KeyStore.Builder.newInstance(KeyStore.getDefaultType(),
283                null, fl, protPass);
284        ksB1 = KeyStore.Builder.newInstance(KeyStore.getDefaultType(),
285                defaultProvider, fl, protPass);
286        try {
287            ks = ksB.getKeyStore();
288        } catch (KeyStoreException e) {
289            fail("Unexpected KeyException was thrown");
290        }
291        try {
292            ks1 = ksB1.getKeyStore();
293        } catch (KeyStoreException e) {
294            fail("Unexpected KeyException was thrown: " + e.getMessage());
295        }
296        assertEquals("Incorrect KeyStore size", ks.size(), ks1.size());
297        ;
298
299        for (Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements(); ) {
300            String aName = aliases.nextElement();
301            try {
302                assertEquals("Incorrect ProtectionParameter", ksB
303                        .getProtectionParameter(aName), protPass);
304            } catch (Exception e) {
305                fail("Unexpected: " + e.toString()
306                        + " was thrown for alias: " + aName);
307            }
308        }
309
310        ksB.getKeyStore();
311
312        try {
313            assertEquals(ksB.getProtectionParameter("Bad alias"), protPass);
314        } catch (KeyStoreException e) {
315            // KeyStoreException might be thrown because there is no entry
316            // with such alias
317        }
318
319
320        for (Enumeration<String> aliases = ks1.aliases(); aliases.hasMoreElements(); ) {
321            String aName = aliases.nextElement();
322            assertEquals("Incorrect ProtectionParameter", ksB1
323                    .getProtectionParameter(aName), protPass);
324        }
325
326        try {
327            assertEquals(ksB1.getProtectionParameter("Bad alias"), protPass);
328        } catch (KeyStoreException e) {
329            // KeyStoreException might be thrown because there is no entry
330            // with such alias
331        }
332
333
334        // Tests with CallbackHandlerProtection
335        ksB = KeyStore.Builder.newInstance(KeyStore.getDefaultType(),
336                null, fl, callbackHand);
337        ksB1 = KeyStore.Builder.newInstance(KeyStore.getDefaultType(),
338                defaultProvider, fl, callbackHand);
339        try {
340            ks = ksB.getKeyStore();
341            fail("KeyStoreException must be thrown for incorrect "
342                    + "ProtectionParameter");
343        } catch (KeyStoreException e) {
344        }
345        try {
346            ks1 = ksB1.getKeyStore();
347            fail("KeyStoreException must be thrown for incorrect "
348                    + "ProtectionParameter");
349        } catch (KeyStoreException e) {
350        }
351        assertEquals("Incorrect KeyStore size", ks.size(), ks1.size());
352
353        for (Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements();) {
354            String aName = aliases.nextElement();
355            try {
356                assertEquals("Incorrect ProtectionParameter", ksB
357                        .getProtectionParameter(aName), callbackHand);
358            } catch (Exception e) {
359                fail("Unexpected: " + e.toString()
360                        + " was thrown for alias: " + aName);
361            }
362        }
363
364        for (Enumeration<String> iter = ks1.aliases(); iter.hasMoreElements();) {
365            String aName = iter.nextElement();
366            assertEquals("Incorrect ProtectionParameter", ksB1
367                    .getProtectionParameter(aName), callbackHand);
368        }
369    }
370
371    /*
372     * Test for method: <code>newInstance(String type, Provider provider,
373     * ProtectionParameter protectionParameter)</code> <code>getKeyStore()</code>
374     * <code>getProtectionParameter(String alias)</code> Assertions: throws
375     * NullPointerException if type, or protectionParameter is null; returns new
376     * object
377     *
378     * getKeyStore() returns empty keystore getProtectionParameter(String alias)
379     * throws NullPointerException when alias is null; throws KeyStoreException
380     * when alias is not available
381     *
382     */
383    public void testNewInstanceStringProviderProtectionParameter()
384            throws KeyStoreException {
385
386        try {
387            KeyStore.Builder.newInstance(null, defaultProvider, protPass);
388            fail("NullPointerException must be thrown when type is null");
389        } catch (NullPointerException e) {
390        }
391        try {
392            KeyStore.Builder.newInstance(defaultType, defaultProvider, null);
393            fail("NullPointerException must be thrown when ProtectionParameter is null");
394        } catch (NullPointerException e) {
395        }
396        MyProtectionParameter myPP = new MyProtectionParameter(new byte[5]);
397        KeyStore.ProtectionParameter[] pp = { protPass, myPP, callbackHand };
398        KeyStore.Builder ksB, ksB1;
399        KeyStore ks = null;
400        for (int i = 0; i < pp.length; i++) {
401            ksB = KeyStore.Builder.newInstance(defaultType, defaultProvider,
402                    pp[i]);
403            ksB1 = KeyStore.Builder.newInstance(defaultType, null, pp[i]);
404            switch (i) {
405            case 0:
406                try {
407                    ks = ksB.getKeyStore();
408                    assertNotNull("KeyStore is null", ks);
409                    try {
410                        assertEquals(ksB.getProtectionParameter("Bad alias"),
411                                pp[i]);
412                    } catch (KeyStoreException e) {
413                        // KeyStoreException might be thrown because there is no
414                        // entry with such alias
415                    }
416
417                    ks = ksB1.getKeyStore();
418                    assertNotNull("KeyStore is null", ks);
419
420                    try {
421                        assertEquals(ksB1.getProtectionParameter("Bad alias"),
422                                pp[i]);
423                    } catch (KeyStoreException e) {
424                        // KeyStoreException might be thrown because there is no
425                        // entry with such alias
426                    }
427                } catch (KeyStoreException e) {
428                    try {
429                        ks = ksB.getKeyStore();
430                    } catch (KeyStoreException e1) {
431                        assertEquals("Incorrect exception", e.getMessage(), e1
432                                .getMessage());
433                    }
434                }
435                break;
436            case 1:
437            case 2:
438                Exception ex1 = null;
439                Exception ex2 = null;
440                try {
441                    ks = ksB.getKeyStore();
442                } catch (KeyStoreException e) {
443                    ex1 = e;
444                }
445                try {
446                    ks = ksB.getKeyStore();
447                } catch (KeyStoreException e) {
448                    ex2 = e;
449                }
450                assertEquals("Incorrect exception", ex1.getMessage(), ex2
451                        .getMessage());
452
453                try {
454                    ksB.getProtectionParameter("aaa");
455                    fail("IllegalStateException must be thrown because getKeyStore() was not invoked");
456                } catch (IllegalStateException e) {
457                }
458
459                try {
460                    ks = ksB1.getKeyStore();
461                } catch (KeyStoreException e) {
462                    ex1 = e;
463                }
464                try {
465                    ks = ksB1.getKeyStore();
466                } catch (KeyStoreException e) {
467                    ex2 = e;
468                }
469                assertEquals("Incorrect exception", ex1.getMessage(), ex2
470                        .getMessage());
471
472                try {
473                    ksB1.getProtectionParameter("aaa");
474                    fail("IllegalStateException must be thrown because getKeyStore() was not invoked");
475                } catch (IllegalStateException e) {
476                }
477                break;
478
479            }
480        }
481    }
482
483    /**
484     * Additional class for creating KeyStoreBuilder
485     */
486    class MyProtectionParameter implements KeyStore.ProtectionParameter {
487        public MyProtectionParameter(byte[] param) {
488            if (param == null) {
489                throw new NullPointerException("param is null");
490            }
491        }
492    }
493
494//     Creates empty KeyStore and loads it to file
495    private File createKS() throws Exception {
496        FileOutputStream fos = null;
497        File ff = File.createTempFile("KSBuilder_ImplTest", "keystore");
498        ff.deleteOnExit();
499        try {
500
501            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
502            fos = new FileOutputStream(ff);
503            ks.load(null, null);
504            ks.store(fos, pass);
505        } finally {
506            if (fos != null) {
507                try {
508                    fos.close();
509                } catch (IOException e) {
510                }
511            }
512        }
513        return ff;
514    }
515
516    class KeyStoreBuilder extends KeyStore.Builder {
517        public KeyStoreBuilder() {
518            super();
519        }
520
521        public KeyStore getKeyStore() {
522            return null;
523        }
524
525        public KeyStore.ProtectionParameter getProtectionParameter(String alias) {
526            return null;
527        }
528    }
529}
530