diff options
author | Oscar Montemayor <oam@google.com> | 2010-01-06 11:35:59 -0800 |
---|---|---|
committer | Oscar Montemayor <oam@google.com> | 2010-01-06 16:23:57 -0800 |
commit | 8da98e30d8b2ae6e203f769dab0d6ec34cab3011 (patch) | |
tree | 16dcc138f20b9880b4eff88eb4f47743c29b683f /keystore | |
parent | 5e3f6caeb08c54fb79f427a528e084711652bbdb (diff) | |
download | frameworks_base-8da98e30d8b2ae6e203f769dab0d6ec34cab3011.zip frameworks_base-8da98e30d8b2ae6e203f769dab0d6ec34cab3011.tar.gz frameworks_base-8da98e30d8b2ae6e203f769dab0d6ec34cab3011.tar.bz2 |
Apps on SD card project.
A simple keystore to store system-only key material, by leveraging file system access permissions.
Diffstat (limited to 'keystore')
3 files changed, 188 insertions, 0 deletions
diff --git a/keystore/java/android/security/SystemKeyStore.java b/keystore/java/android/security/SystemKeyStore.java new file mode 100644 index 0000000..452125a --- /dev/null +++ b/keystore/java/android/security/SystemKeyStore.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +import android.os.Environment; +import android.os.Process; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +/** + *@hide + */ +public class SystemKeyStore { + + private static final String SYSTEM_KEYSTORE_DIRECTORY = "misc/systemkeys"; + private static SystemKeyStore mInstance = new SystemKeyStore(); + + private SystemKeyStore() { } + + public static SystemKeyStore getInstance() { + return mInstance; + } + + public byte[] generateNewKey(int numBits, String algName, String keyName) + throws NoSuchAlgorithmException { + + // Check if key with similar name exists. If so, return null. + File keyFile = getKeyFile(keyName); + if (keyFile.exists()) { + throw new IllegalArgumentException(); + } + + KeyGenerator skg = KeyGenerator.getInstance(algName); + SecureRandom srng = SecureRandom.getInstance("SHA1PRNG"); + skg.init(numBits, srng); + + SecretKey sk = skg.generateKey(); + byte[] retKey = sk.getEncoded(); + + try { + // Store the key + if (!keyFile.createNewFile()) { + throw new IllegalArgumentException(); + } + + FileOutputStream fos = new FileOutputStream(keyFile); + fos.write(retKey); + fos.flush(); + fos.close(); + } catch (IOException ioe) { + return null; + } + return retKey; + } + + private File getKeyFile(String keyName) { + File sysKeystoreDir = new File(Environment.getDataDirectory(), + SYSTEM_KEYSTORE_DIRECTORY); + File keyFile = new File(sysKeystoreDir, keyName); + return keyFile; + } + + public byte[] retrieveKey(String keyName) { + + File keyFile = getKeyFile(keyName); + if (!keyFile.exists()) { + return null; + } + + try { + FileInputStream fis = new FileInputStream(keyFile); + int keyLen = fis.available(); + byte[] retKey = new byte[keyLen]; + fis.read(retKey); + fis.close(); + return retKey; + } catch (IOException ioe) { } + throw new IllegalArgumentException(); + } + + public void deleteKey(String keyName) { + + // Get the file first. + File keyFile = getKeyFile(keyName); + if (!keyFile.exists()) { + throw new IllegalArgumentException(); + } + + keyFile.delete(); + } +} diff --git a/keystore/tests/src/android/security/KeyStoreTestRunner.java b/keystore/tests/src/android/security/KeyStoreTestRunner.java index c85922d..c56eeb9 100644 --- a/keystore/tests/src/android/security/KeyStoreTestRunner.java +++ b/keystore/tests/src/android/security/KeyStoreTestRunner.java @@ -37,6 +37,7 @@ public class KeyStoreTestRunner extends InstrumentationTestRunner { public TestSuite getAllTests() { TestSuite suite = new InstrumentationTestSuite(this); suite.addTestSuite(android.security.tests.KeyStoreTest.class); + suite.addTestSuite(android.security.tests.SystemKeyStoreTest.class); return suite; } diff --git a/keystore/tests/src/android/security/SystemKeyStoreTest.java b/keystore/tests/src/android/security/SystemKeyStoreTest.java new file mode 100644 index 0000000..a85f889 --- /dev/null +++ b/keystore/tests/src/android/security/SystemKeyStoreTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.tests; + +import android.app.Activity; +import android.security.SystemKeyStore; +import android.test.ActivityUnitTestCase; +import android.test.suitebuilder.annotation.MediumTest; + +/** + * Junit / Instrumentation test case for KeyStore class + * + * Running the test suite: + * + * adb shell am instrument -w android.security.tests/.KeyStoreTestRunner + */ +@MediumTest +public class SystemKeyStoreTest extends ActivityUnitTestCase<Activity> { + + private static final String keyName = "TestKey"; + private SystemKeyStore mSysKeyStore = null; + + public SystemKeyStoreTest() { + super(Activity.class); + } + + @Override + protected void setUp() throws Exception { + mSysKeyStore = SystemKeyStore.getInstance(); + try { + mSysKeyStore.deleteKey(keyName); + } catch (Exception e) { } + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + try { + mSysKeyStore.deleteKey(keyName); + } catch (Exception e) { } + super.tearDown(); + } + + public void testBasicAccess() throws Exception { + try { + byte[] newKey = mSysKeyStore.generateNewKey(128, "AES", keyName); + assertNotNull(newKey); + byte[] recKey = mSysKeyStore.retrieveKey(keyName); + assertEquals(newKey.length, recKey.length); + for (int i = 0; i < newKey.length; i++) { + assertEquals(newKey[i], recKey[i]); + } + mSysKeyStore.deleteKey(keyName); + byte[] nullKey = mSysKeyStore.retrieveKey(keyName); + assertNull(nullKey); + } catch (Exception e) { + fail(); + } + } +} |