Home | History | Annotate | Download | only in security
      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 
     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 
    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
    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
    126     protected void tearDown() throws Exception {
    127         mKeyStore.reset();
    128         super.tearDown();
    129     }
    130 
    131     public void teststate() throws Exception {
    132         assertEquals(KeyStore.State.UNINITIALIZED, mKeyStore.state());
    133     }
    134 
    135     public void testPassword() throws Exception {
    136         assertTrue(mKeyStore.password(TEST_PASSWD));
    137         assertEquals(KeyStore.State.UNLOCKED, mKeyStore.state());
    138     }
    139 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    230     public void testGenerate_NotInitialized_Fail() throws Exception {
    231         assertFalse("Should fail when keystore is not initialized",
    232                 mKeyStore.generate(TEST_KEYNAME));
    233     }
    234 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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