• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 
17 package android.security;
18 
19 import android.app.Activity;
20 import android.security.KeyStore;
21 import android.test.ActivityUnitTestCase;
22 import android.test.AssertionFailedError;
23 import android.test.suitebuilder.annotation.MediumTest;
24 import java.nio.charset.Charsets;
25 import java.util.Arrays;
26 import java.util.Date;
27 import java.util.HashSet;
28 
29 /**
30  * Junit / Instrumentation test case for KeyStore class
31  *
32  * Running the test suite:
33  *
34  *  runtest keystore-unit
35  *
36  * Or this individual test case:
37  *
38  *  runtest --path frameworks/base/keystore/tests/src/android/security/KeyStoreTest.java
39  */
40 @MediumTest
41 public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
42     private static final String TEST_PASSWD = "12345678";
43     private static final String TEST_PASSWD2 = "87654321";
44     private static final String TEST_KEYNAME = "test-key";
45     private static final String TEST_KEYNAME1 = "test-key.1";
46     private static final String TEST_KEYNAME2 = "test-key\02";
47     private static final byte[] TEST_KEYVALUE = "test value".getBytes(Charsets.UTF_8);
48 
49     // "Hello, World" in Chinese
50     private static final String TEST_I18N_KEY = "\u4F60\u597D, \u4E16\u754C";
51     private static final byte[] TEST_I18N_VALUE = TEST_I18N_KEY.getBytes(Charsets.UTF_8);
52 
53     // Test vector data for signatures
54     private static final byte[] TEST_DATA =  new byte[256];
55     static {
56         for (int i = 0; i < TEST_DATA.length; i++) {
57             TEST_DATA[i] = (byte) i;
58         }
59     }
60 
61     private KeyStore mKeyStore = null;
62 
KeyStoreTest()63     public KeyStoreTest() {
64         super(Activity.class);
65     }
66 
67     private static final byte[] PRIVKEY_BYTES = hexToBytes(
68             "308204BE020100300D06092A864886F70D0101010500048204A8308204A4020100028201" +
69             "0100E0473E8AB8F2284FEB9E742FF9748FA118ED98633C92F52AEB7A2EBE0D3BE60329BE" +
70             "766AD10EB6A515D0D2CFD9BEA7930F0C306537899F7958CD3E85B01F8818524D312584A9" +
71             "4B251E3625B54141EDBFEE198808E1BB97FC7CB49B9EAAAF68E9C98D7D0EDC53BBC0FA00" +
72             "34356D6305FBBCC3C7001405386ABBC873CB0F3EF7425F3D33DF7B315AE036D2A0B66AFD" +
73             "47503B169BF36E3B5162515B715FDA83DEAF2C58AEB9ABFB3097C3CC9DD9DBE5EF296C17" +
74             "6139028E8A671E63056D45F40188D2C4133490845DE52C2534E9C6B2478C07BDAE928823" +
75             "B62D066C7770F9F63F3DBA247F530844747BE7AAA85D853B8BD244ACEC3DE3C89AB46453" +
76             "AB4D24C3AC6902030100010282010037784776A5F17698F5AC960DFB83A1B67564E648BD" +
77             "0597CF8AB8087186F2669C27A9ECBDD480F0197A80D07309E6C6A96F925331E57F8B4AC6" +
78             "F4D45EDA45A23269C09FC428C07A4E6EDF738A15DEC97FABD2F2BB47A14F20EA72FCFE4C" +
79             "36E01ADA77BD137CD8D4DA10BB162E94A4662971F175F985FA188F056CB97EE2816F43AB" +
80             "9D3747612486CDA8C16196C30818A995EC85D38467791267B3BF21F273710A6925862576" +
81             "841C5B6712C12D4BD20A2F3299ADB7C135DA5E9515ABDA76E7CAF2A3BE80551D073B78BF" +
82             "1162C48AD2B7F4743A0238EE4D252F7D5E7E6533CCAE64CCB39360075A2FD1E034EC3AE5" +
83             "CE9C408CCBF0E25E4114021687B3DD4754AE8102818100F541884BC3737B2922D4119EF4" +
84             "5E2DEE2CD4CBB75F45505A157AA5009F99C73A2DF0724AC46024306332EA898177634546" +
85             "5DC6DF1E0A6F140AFF3B7396E6A8994AC5DAA96873472FE37749D14EB3E075E629DBEB35" +
86             "83338A6F3649D0A2654A7A42FD9AB6BFA4AC4D481D390BB229B064BDC311CC1BE1B63189" +
87             "DA7C40CDECF2B102818100EA1A742DDB881CEDB7288C87E38D868DD7A409D15A43F445D5" +
88             "377A0B5731DDBFCA2DAF28A8E13CD5C0AFCEC3347D74A39E235A3CD9633F274DE2B94F92" +
89             "DF43833911D9E9F1CF58F27DE2E08FF45964C720D3EC2139DC7CAFC912953CDECB2F355A" +
90             "2E2C35A50FAD754CB3B23166424BA3B6E3112A2B898C38C5C15EDB238693390281805182" +
91             "8F1EC6FD996029901BAF1D7E337BA5F0AF27E984EAD895ACE62BD7DF4EE45A224089F2CC" +
92             "151AF3CD173FCE0474BCB04F386A2CDCC0E0036BA2419F54579262D47100BE931984A3EF" +
93             "A05BECF141574DC079B3A95C4A83E6C43F3214D6DF32D512DE198085E531E616B83FD7DD" +
94             "9D1F4E2607C3333D07C55D107D1D3893587102818100DB4FB50F50DE8EDB53FF34C80931" +
95             "88A0512867DA2CCA04897759E587C244010DAF8664D59E8083D16C164789301F67A9F078" +
96             "060D834A2ADBD367575B68A8A842C2B02A89B3F31FCCEC8A22FE395795C5C6C7422B4E5D" +
97             "74A1E9A8F30E7759B9FC2D639C1F15673E84E93A5EF1506F4315383C38D45CBD1B14048F" +
98             "4721DC82326102818100D8114593AF415FB612DBF1923710D54D07486205A76A3B431949" +
99             "68C0DFF1F11EF0F61A4A337D5FD3741BBC9640E447B8B6B6C47C3AC1204357D3B0C55BA9" +
100             "286BDA73F629296F5FA9146D8976357D3C751E75148696A40B74685C82CE30902D639D72" +
101             "4FF24D5E2E9407EE34EDED2E3B4DF65AA9BCFEB6DF28D07BA6903F165768");
102 
103 
hexToBytes(String s)104     private static byte[] hexToBytes(String s) {
105         int len = s.length();
106         byte[] data = new byte[len / 2];
107         for (int i = 0; i < len; i += 2) {
108             data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(
109                     s.charAt(i + 1), 16));
110         }
111         return data;
112     }
113 
114     @Override
setUp()115     protected void setUp() throws Exception {
116         mKeyStore = KeyStore.getInstance();
117         if (mKeyStore.state() != KeyStore.State.UNINITIALIZED) {
118             mKeyStore.reset();
119         }
120         assertEquals("KeyStore should be in an uninitialized state",
121                 KeyStore.State.UNINITIALIZED, mKeyStore.state());
122         super.setUp();
123     }
124 
125     @Override
tearDown()126     protected void tearDown() throws Exception {
127         mKeyStore.reset();
128         super.tearDown();
129     }
130 
teststate()131     public void teststate() throws Exception {
132         assertEquals(KeyStore.State.UNINITIALIZED, mKeyStore.state());
133     }
134 
testPassword()135     public void testPassword() throws Exception {
136         assertTrue(mKeyStore.password(TEST_PASSWD));
137         assertEquals(KeyStore.State.UNLOCKED, mKeyStore.state());
138     }
139 
testGet()140     public void testGet() throws Exception {
141         assertNull(mKeyStore.get(TEST_KEYNAME));
142         mKeyStore.password(TEST_PASSWD);
143         assertNull(mKeyStore.get(TEST_KEYNAME));
144         assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
145         assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
146     }
147 
testPut()148     public void testPut() throws Exception {
149         assertNull(mKeyStore.get(TEST_KEYNAME));
150         assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
151         assertFalse(mKeyStore.contains(TEST_KEYNAME));
152         mKeyStore.password(TEST_PASSWD);
153         assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
154         assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
155     }
156 
testI18n()157     public void testI18n() throws Exception {
158         assertFalse(mKeyStore.put(TEST_I18N_KEY, TEST_I18N_VALUE));
159         assertFalse(mKeyStore.contains(TEST_I18N_KEY));
160         mKeyStore.password(TEST_I18N_KEY);
161         assertTrue(mKeyStore.put(TEST_I18N_KEY, TEST_I18N_VALUE));
162         assertTrue(mKeyStore.contains(TEST_I18N_KEY));
163     }
164 
testDelete()165     public void testDelete() throws Exception {
166         assertFalse(mKeyStore.delete(TEST_KEYNAME));
167         mKeyStore.password(TEST_PASSWD);
168         assertFalse(mKeyStore.delete(TEST_KEYNAME));
169 
170         mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE);
171         assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
172         assertTrue(mKeyStore.delete(TEST_KEYNAME));
173         assertNull(mKeyStore.get(TEST_KEYNAME));
174     }
175 
testContains()176     public void testContains() throws Exception {
177         assertFalse(mKeyStore.contains(TEST_KEYNAME));
178 
179         mKeyStore.password(TEST_PASSWD);
180         assertFalse(mKeyStore.contains(TEST_KEYNAME));
181 
182         mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE);
183         assertTrue(mKeyStore.contains(TEST_KEYNAME));
184     }
185 
testSaw()186     public void testSaw() throws Exception {
187         String[] emptyResult = mKeyStore.saw(TEST_KEYNAME);
188         assertNotNull(emptyResult);
189         assertEquals(0, emptyResult.length);
190 
191         mKeyStore.password(TEST_PASSWD);
192         mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE);
193         mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE);
194 
195         String[] results = mKeyStore.saw(TEST_KEYNAME);
196         assertEquals(new HashSet(Arrays.asList(TEST_KEYNAME1.substring(TEST_KEYNAME.length()),
197                                                TEST_KEYNAME2.substring(TEST_KEYNAME.length()))),
198                      new HashSet(Arrays.asList(results)));
199     }
200 
testLock()201     public void testLock() throws Exception {
202         assertFalse(mKeyStore.lock());
203 
204         mKeyStore.password(TEST_PASSWD);
205         assertEquals(KeyStore.State.UNLOCKED, mKeyStore.state());
206 
207         assertTrue(mKeyStore.lock());
208         assertEquals(KeyStore.State.LOCKED, mKeyStore.state());
209     }
210 
testUnlock()211     public void testUnlock() throws Exception {
212         mKeyStore.password(TEST_PASSWD);
213         assertEquals(KeyStore.State.UNLOCKED, mKeyStore.state());
214         mKeyStore.lock();
215 
216         assertFalse(mKeyStore.unlock(TEST_PASSWD2));
217         assertTrue(mKeyStore.unlock(TEST_PASSWD));
218     }
219 
testIsEmpty()220     public void testIsEmpty() throws Exception {
221         assertTrue(mKeyStore.isEmpty());
222         mKeyStore.password(TEST_PASSWD);
223         assertTrue(mKeyStore.isEmpty());
224         mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE);
225         assertFalse(mKeyStore.isEmpty());
226         mKeyStore.reset();
227         assertTrue(mKeyStore.isEmpty());
228     }
229 
testGenerate_NotInitialized_Fail()230     public void testGenerate_NotInitialized_Fail() throws Exception {
231         assertFalse("Should fail when keystore is not initialized",
232                 mKeyStore.generate(TEST_KEYNAME));
233     }
234 
testGenerate_Locked_Fail()235     public void testGenerate_Locked_Fail() throws Exception {
236         mKeyStore.password(TEST_PASSWD);
237         mKeyStore.lock();
238         assertFalse("Should fail when keystore is locked", mKeyStore.generate(TEST_KEYNAME));
239     }
240 
testGenerate_Success()241     public void testGenerate_Success() throws Exception {
242         mKeyStore.password(TEST_PASSWD);
243 
244         assertTrue("Should be able to generate key when unlocked",
245                 mKeyStore.generate(TEST_KEYNAME));
246     }
247 
testImport_Success()248     public void testImport_Success() throws Exception {
249         mKeyStore.password(TEST_PASSWD);
250 
251         assertTrue("Should be able to import key when unlocked",
252                 mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
253     }
254 
testImport_Failure_BadEncoding()255     public void testImport_Failure_BadEncoding() throws Exception {
256         mKeyStore.password(TEST_PASSWD);
257 
258         assertFalse("Invalid DER-encoded key should not be imported",
259                 mKeyStore.importKey(TEST_KEYNAME, TEST_DATA));
260     }
261 
testSign_Success()262     public void testSign_Success() throws Exception {
263         mKeyStore.password(TEST_PASSWD);
264 
265         assertTrue(mKeyStore.generate(TEST_KEYNAME));
266         final byte[] signature = mKeyStore.sign(TEST_KEYNAME, TEST_DATA);
267 
268         assertNotNull("Signature should not be null", signature);
269     }
270 
testVerify_Success()271     public void testVerify_Success() throws Exception {
272         mKeyStore.password(TEST_PASSWD);
273 
274         assertTrue(mKeyStore.generate(TEST_KEYNAME));
275         final byte[] signature = mKeyStore.sign(TEST_KEYNAME, TEST_DATA);
276 
277         assertNotNull("Signature should not be null", signature);
278 
279         assertTrue("Signature should verify with same data",
280                 mKeyStore.verify(TEST_KEYNAME, TEST_DATA, signature));
281     }
282 
testSign_NotInitialized_Failure()283     public void testSign_NotInitialized_Failure() throws Exception {
284         assertNull("Should not be able to sign without first initializing the keystore",
285                 mKeyStore.sign(TEST_KEYNAME, TEST_DATA));
286     }
287 
testSign_NotGenerated_Failure()288     public void testSign_NotGenerated_Failure() throws Exception {
289         mKeyStore.password(TEST_PASSWD);
290 
291         assertNull("Should not be able to sign without first generating keys",
292                 mKeyStore.sign(TEST_KEYNAME, TEST_DATA));
293     }
294 
testGrant_Generated_Success()295     public void testGrant_Generated_Success() throws Exception {
296         assertTrue("Password should work for keystore",
297                 mKeyStore.password(TEST_PASSWD));
298 
299         assertTrue("Should be able to generate key for testcase",
300                 mKeyStore.generate(TEST_KEYNAME));
301 
302         assertTrue("Should be able to grant key to other user",
303                 mKeyStore.grant(TEST_KEYNAME, 0));
304     }
305 
testGrant_Imported_Success()306     public void testGrant_Imported_Success() throws Exception {
307         assertTrue("Password should work for keystore", mKeyStore.password(TEST_PASSWD));
308 
309         assertTrue("Should be able to import key for testcase",
310                 mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
311 
312         assertTrue("Should be able to grant key to other user", mKeyStore.grant(TEST_KEYNAME, 0));
313     }
314 
testGrant_NoKey_Failure()315     public void testGrant_NoKey_Failure() throws Exception {
316         assertTrue("Should be able to unlock keystore for test",
317                 mKeyStore.password(TEST_PASSWD));
318 
319         assertFalse("Should not be able to grant without first initializing the keystore",
320                 mKeyStore.grant(TEST_KEYNAME, 0));
321     }
322 
testGrant_NotInitialized_Failure()323     public void testGrant_NotInitialized_Failure() throws Exception {
324         assertFalse("Should not be able to grant without first initializing the keystore",
325                 mKeyStore.grant(TEST_KEYNAME, 0));
326     }
327 
testUngrant_Generated_Success()328     public void testUngrant_Generated_Success() throws Exception {
329         assertTrue("Password should work for keystore",
330                 mKeyStore.password(TEST_PASSWD));
331 
332         assertTrue("Should be able to generate key for testcase",
333                 mKeyStore.generate(TEST_KEYNAME));
334 
335         assertTrue("Should be able to grant key to other user",
336                 mKeyStore.grant(TEST_KEYNAME, 0));
337 
338         assertTrue("Should be able to ungrant key to other user",
339                 mKeyStore.ungrant(TEST_KEYNAME, 0));
340     }
341 
testUngrant_Imported_Success()342     public void testUngrant_Imported_Success() throws Exception {
343         assertTrue("Password should work for keystore",
344                 mKeyStore.password(TEST_PASSWD));
345 
346         assertTrue("Should be able to import key for testcase",
347                 mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
348 
349         assertTrue("Should be able to grant key to other user",
350                 mKeyStore.grant(TEST_KEYNAME, 0));
351 
352         assertTrue("Should be able to ungrant key to other user",
353                 mKeyStore.ungrant(TEST_KEYNAME, 0));
354     }
355 
testUngrant_NotInitialized_Failure()356     public void testUngrant_NotInitialized_Failure() throws Exception {
357         assertFalse("Should fail to ungrant key when keystore not initialized",
358                 mKeyStore.ungrant(TEST_KEYNAME, 0));
359     }
360 
testUngrant_NoGrant_Failure()361     public void testUngrant_NoGrant_Failure() throws Exception {
362         assertTrue("Password should work for keystore",
363                 mKeyStore.password(TEST_PASSWD));
364 
365         assertTrue("Should be able to generate key for testcase",
366                 mKeyStore.generate(TEST_KEYNAME));
367 
368         assertFalse("Should not be able to revoke not existent grant",
369                 mKeyStore.ungrant(TEST_KEYNAME, 0));
370     }
371 
testUngrant_DoubleUngrant_Failure()372     public void testUngrant_DoubleUngrant_Failure() throws Exception {
373         assertTrue("Password should work for keystore",
374                 mKeyStore.password(TEST_PASSWD));
375 
376         assertTrue("Should be able to generate key for testcase",
377                 mKeyStore.generate(TEST_KEYNAME));
378 
379         assertTrue("Should be able to grant key to other user",
380                 mKeyStore.grant(TEST_KEYNAME, 0));
381 
382         assertTrue("Should be able to ungrant key to other user",
383                 mKeyStore.ungrant(TEST_KEYNAME, 0));
384 
385         assertFalse("Should fail to ungrant key to other user second time",
386                 mKeyStore.ungrant(TEST_KEYNAME, 0));
387     }
388 
testUngrant_DoubleGrantUngrant_Failure()389     public void testUngrant_DoubleGrantUngrant_Failure() throws Exception {
390         assertTrue("Password should work for keystore",
391                 mKeyStore.password(TEST_PASSWD));
392 
393         assertTrue("Should be able to generate key for testcase",
394                 mKeyStore.generate(TEST_KEYNAME));
395 
396         assertTrue("Should be able to grant key to other user",
397                 mKeyStore.grant(TEST_KEYNAME, 0));
398 
399         assertTrue("Should be able to grant key to other user a second time",
400                 mKeyStore.grant(TEST_KEYNAME, 0));
401 
402         assertTrue("Should be able to ungrant key to other user",
403                 mKeyStore.ungrant(TEST_KEYNAME, 0));
404 
405         assertFalse("Should fail to ungrant key to other user second time",
406                 mKeyStore.ungrant(TEST_KEYNAME, 0));
407     }
408 
409     /**
410      * The amount of time to allow before and after expected time for variance
411      * in timing tests.
412      */
413     private static final long SLOP_TIME_MILLIS = 15000L;
414 
testGetmtime_Success()415     public void testGetmtime_Success() throws Exception {
416         assertTrue("Password should work for keystore",
417                 mKeyStore.password(TEST_PASSWD));
418 
419         assertTrue("Should be able to import key when unlocked",
420                 mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
421 
422         long now = System.currentTimeMillis();
423         long actual = mKeyStore.getmtime(TEST_KEYNAME);
424 
425         long expectedAfter = now - SLOP_TIME_MILLIS;
426         long expectedBefore = now + SLOP_TIME_MILLIS;
427 
428         assertLessThan("Time should be close to current time", expectedBefore, actual);
429         assertGreaterThan("Time should be close to current time", expectedAfter, actual);
430     }
431 
assertLessThan(String explanation, long expectedBefore, long actual)432     private static void assertLessThan(String explanation, long expectedBefore, long actual) {
433         if (actual >= expectedBefore) {
434             throw new AssertionFailedError(explanation + ": actual=" + actual
435                     + ", expected before: " + expectedBefore);
436         }
437     }
438 
assertGreaterThan(String explanation, long expectedAfter, long actual)439     private static void assertGreaterThan(String explanation, long expectedAfter, long actual) {
440         if (actual <= expectedAfter) {
441             throw new AssertionFailedError(explanation + ": actual=" + actual
442                     + ", expected after: " + expectedAfter);
443         }
444     }
445 
testGetmtime_NonExist_Failure()446     public void testGetmtime_NonExist_Failure() throws Exception {
447         assertTrue("Password should work for keystore",
448                 mKeyStore.password(TEST_PASSWD));
449 
450         assertTrue("Should be able to import key when unlocked",
451                 mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
452 
453         assertEquals("-1 should be returned for non-existent key",
454                 -1L, mKeyStore.getmtime(TEST_KEYNAME2));
455     }
456 }
457