Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8da98e30 authored by Oscar Montemayor's avatar Oscar Montemayor
Browse files

Apps on SD card project.

A simple keystore to store system-only key material, by leveraging file system access permissions.
parent 5e3f6cae
Loading
Loading
Loading
Loading
+113 −0
Original line number Diff line number Diff line
/*
 * 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();
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -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;
    }

+74 −0
Original line number Diff line number Diff line
/*
 * 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();
        }
    }
}