1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.security.tests.java.security;
19
20import java.io.IOException;
21import java.io.InputStream;
22import java.security.InvalidKeyException;
23import java.security.Key;
24import java.security.KeyStore.LoadStoreParameter;
25import java.security.KeyStore.Entry;
26import java.security.KeyStore.ProtectionParameter;
27import java.security.KeyStore;
28import java.security.KeyStoreException;
29import java.security.KeyStoreSpi;
30import java.security.NoSuchAlgorithmException;
31import java.security.NoSuchProviderException;
32import java.security.PublicKey;
33import java.security.SignatureException;
34import java.security.UnrecoverableEntryException;
35import java.security.UnrecoverableKeyException;
36import java.security.cert.Certificate;
37import java.security.cert.CertificateEncodingException;
38import java.security.cert.CertificateException;
39import java.util.Date;
40import javax.crypto.SecretKey;
41import junit.framework.TestCase;
42import org.apache.harmony.security.tests.support.MyKeyStoreSpi;
43import org.apache.harmony.security.tests.support.MyLoadStoreParams;
44
45public class KeyStoreSpiTest extends TestCase {
46
47    @SuppressWarnings("cast")
48    public void test_KeyStoreSpi() {
49
50        try {
51            MyKeyStoreSpi ksSpi = new MyKeyStoreSpi();
52            assertNotNull(ksSpi);
53            assertTrue(ksSpi instanceof KeyStoreSpi);
54        } catch (Exception ex) {
55            fail("Unexpected exception");
56        }
57    }
58
59    /*
60     * java.security.KeyStore.engineEntryInstanceOf(String, Class<?
61     * extends Entry>)
62     */
63    public void test_engineEntryInstanceOf() throws Exception {
64
65        KeyStoreSpi ksSpi = new MyKeyStoreSpi();
66
67        assertTrue(ksSpi.engineEntryInstanceOf(
68                "test_engineEntryInstanceOf_Alias1",
69                KeyStore.PrivateKeyEntry.class));
70
71        assertFalse(ksSpi.engineEntryInstanceOf(
72                "test_engineEntryInstanceOf_Alias2",
73                KeyStore.SecretKeyEntry.class));
74
75        assertFalse(ksSpi.engineEntryInstanceOf(
76                "test_engineEntryInstanceOf_Alias3",
77                KeyStore.TrustedCertificateEntry.class));
78
79        try {
80            assertFalse(ksSpi.engineEntryInstanceOf(null,
81                    KeyStore.TrustedCertificateEntry.class));
82        } catch (NullPointerException expected) {
83        }
84
85        try {
86            assertFalse(ksSpi.engineEntryInstanceOf(
87                    "test_engineEntryInstanceOf_Alias1", null));
88        } catch (NullPointerException expected) {
89        }
90
91
92    }
93
94    public void testKeyStoreSpi01() throws IOException,
95            NoSuchAlgorithmException, CertificateException,
96            UnrecoverableEntryException, KeyStoreException {
97        final boolean[] keyEntryWasSet = new boolean[1];
98        KeyStoreSpi ksSpi = new MyKeyStoreSpi() {
99            @Override public void engineSetKeyEntry(String alias, Key key, char[] password,
100                Certificate[] chain) throws KeyStoreException { keyEntryWasSet[0] = true; }
101        };
102
103        BadKeyStoreEntry badEntry = new BadKeyStoreEntry();
104        BadKeyStoreProtectionParameter badParameter = new BadKeyStoreProtectionParameter();
105
106        KeyStore.SecretKeyEntry dummyEntry = new KeyStore.SecretKeyEntry(new SecretKey() {
107            @Override public String getAlgorithm() { return null; }
108            @Override public String getFormat() { return null; }
109            @Override public byte[] getEncoded() { return null; }
110        });
111
112        try {
113            ksSpi.engineStore(null);
114        } catch (UnsupportedOperationException expected) {
115        }
116        assertNull("Not null entry", ksSpi.engineGetEntry("aaa", null));
117        assertNull("Not null entry", ksSpi.engineGetEntry(null, badParameter));
118        assertNull("Not null entry", ksSpi.engineGetEntry("aaa", badParameter));
119
120        try {
121            ksSpi.engineSetEntry("", null, null);
122            fail("KeyStoreException or NullPointerException must be thrown");
123        } catch (KeyStoreException expected) {
124        } catch (NullPointerException expected) {
125        }
126
127        try {
128            ksSpi.engineSetEntry("", new KeyStore.TrustedCertificateEntry(
129                    new MyCertificate("type", new byte[0])), null);
130            fail("KeyStoreException must be thrown");
131        } catch (KeyStoreException expected) {
132        }
133
134        try {
135            ksSpi.engineSetEntry("aaa", badEntry, null);
136            fail("KeyStoreException must be thrown");
137        } catch (KeyStoreException expected) {
138        }
139
140        ksSpi.engineSetEntry("aaa", dummyEntry, null);
141        assertTrue(keyEntryWasSet[0]);
142    }
143
144    /**
145     * Test for <code>KeyStoreSpi()</code> constructor and abstract engine
146     * methods. Assertion: creates new KeyStoreSpi object.
147     */
148    public void testKeyStoreSpi02() throws NoSuchAlgorithmException,
149            UnrecoverableKeyException, CertificateException {
150        KeyStoreSpi ksSpi = new MyKeyStoreSpi();
151        assertNull("engineGetKey(..) must return null", ksSpi.engineGetKey("",
152                new char[0]));
153        assertNull("engineGetCertificateChain(..) must return null", ksSpi
154                .engineGetCertificateChain(""));
155        assertNull("engineGetCertificate(..) must return null", ksSpi
156                .engineGetCertificate(""));
157        assertEquals("engineGetCreationDate(..) must return Date(0)", new Date(
158                0), ksSpi.engineGetCreationDate(""));
159        try {
160            ksSpi.engineSetKeyEntry("", null, new char[0], new Certificate[0]);
161            fail("KeyStoreException must be thrown from engineSetKeyEntry(..)");
162        } catch (KeyStoreException expected) {
163        }
164        try {
165            ksSpi.engineSetKeyEntry("", new byte[0], new Certificate[0]);
166            fail("KeyStoreException must be thrown from engineSetKeyEntry(..)");
167        } catch (KeyStoreException expected) {
168        }
169        try {
170            ksSpi.engineSetCertificateEntry("", null);
171            fail("KeyStoreException must be thrown "
172                    + "from engineSetCertificateEntry(..)");
173        } catch (KeyStoreException expected) {
174        }
175        try {
176            ksSpi.engineDeleteEntry("");
177            fail("KeyStoreException must be thrown from engineDeleteEntry(..)");
178        } catch (KeyStoreException expected) {
179        }
180        assertNull("engineAliases() must return null", ksSpi.engineAliases());
181        assertFalse("engineContainsAlias(..) must return false", ksSpi
182                .engineContainsAlias(""));
183        assertEquals("engineSize() must return 0", 0, ksSpi.engineSize());
184        try {
185            ksSpi.engineStore(null, null);
186            fail("IOException must be thrown");
187        } catch (IOException expected) {
188        }
189    }
190
191    /**
192     * java.security.KeyStoreSpi#engineLoad(KeyStore.LoadStoreParameter)
193     */
194    public void test_engineLoadLjava_security_KeyStore_LoadStoreParameter()
195            throws Exception {
196
197        final String msg = "error";
198
199        KeyStoreSpi ksSpi = new MyKeyStoreSpi() {
200            public void engineLoad(InputStream stream, char[] password) {
201                assertNull(stream);
202                assertNull(password);
203                throw new RuntimeException(msg);
204            }
205        };
206        try {
207            ksSpi.engineLoad(null);
208            fail("Should throw exception");
209        } catch (RuntimeException expected) {
210            assertSame(msg, expected.getMessage());
211        }
212
213        // test: protection parameter is null
214        try {
215            ksSpi.engineLoad(new MyLoadStoreParams(null));
216            fail("No expected UnsupportedOperationException");
217        } catch (UnsupportedOperationException expected) {
218        }
219
220        // test: protection parameter is not instanceof
221        // PasswordProtection or CallbackHandlerProtection
222        try {
223            ksSpi.engineLoad(new MyLoadStoreParams(new BadKeyStoreProtectionParameter()));
224            fail("No expected UnsupportedOperationException");
225        } catch (UnsupportedOperationException expected) {
226        }
227    }
228}
229
230// These are "Bad" because they are not expected inner subclasses of the KeyStore class.
231class BadKeyStoreEntry implements Entry {}
232class BadKeyStoreProtectionParameter implements ProtectionParameter {}
233
234@SuppressWarnings("unused")
235class MyCertificate extends Certificate {
236
237    // MyCertificate encoding
238    private final byte[] encoding;
239
240    public MyCertificate(String type, byte[] encoding) {
241        super(type);
242        // don't copy to allow null parameter in test
243        this.encoding = encoding;
244    }
245
246    public byte[] getEncoded() throws CertificateEncodingException {
247        // do copy to force NPE in test
248        return encoding.clone();
249    }
250
251    public void verify(PublicKey key) throws CertificateException,
252            NoSuchAlgorithmException, InvalidKeyException,
253            NoSuchProviderException, SignatureException {
254    }
255
256    public void verify(PublicKey key, String sigProvider)
257            throws CertificateException, NoSuchAlgorithmException,
258            InvalidKeyException, NoSuchProviderException, SignatureException {
259    }
260
261    public String toString() {
262        return "[My test Certificate, type: " + getType() + "]";
263    }
264
265    public PublicKey getPublicKey() {
266        return new PublicKey() {
267            public String getAlgorithm() {
268                return "DSA";
269            }
270
271            public byte[] getEncoded() {
272                return new byte[] {(byte) 1, (byte) 2, (byte) 3};
273            }
274
275            public String getFormat() {
276                return "TEST_FORMAT";
277            }
278        };
279    }
280}
281