From 6b77645aa9ac51ce33ea67adba226aaf1a6e8846 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Fri, 2 Nov 2012 15:40:32 -0700 Subject: Switch keystore to binder Change-Id: I9fa1fc05068bee1eed3f618fb32f70cf3d4c05d4 --- keystore/java/android/security/KeyStore.java | 353 ++++++++++----------------- 1 file changed, 133 insertions(+), 220 deletions(-) (limited to 'keystore/java') diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 4637991..44be804 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -16,17 +16,9 @@ package android.security; -import android.net.LocalSocketAddress; -import android.net.LocalSocket; - -import java.io.InputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UTFDataFormatException; -import java.nio.charset.Charsets; -import java.nio.charset.ModifiedUtf8; -import java.util.ArrayList; -import java.util.Date; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; /** * @hide This should not be made public in its present form because it @@ -34,6 +26,7 @@ import java.util.Date; * preclude the use of hardware crypto. */ public class KeyStore { + private static final String TAG = "KeyStore"; // ResponseCodes public static final int NO_ERROR = 1; @@ -50,20 +43,30 @@ public class KeyStore { // States public enum State { UNLOCKED, LOCKED, UNINITIALIZED }; - private static final LocalSocketAddress sAddress = new LocalSocketAddress( - "keystore", LocalSocketAddress.Namespace.RESERVED); - private int mError = NO_ERROR; - private KeyStore() {} + private final IKeystoreService mBinder; + + private KeyStore(IKeystoreService binder) { + mBinder = binder; + } public static KeyStore getInstance() { - return new KeyStore(); + IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager + .getService("android.security.keystore")); + return new KeyStore(keystore); } public State state() { - execute('t'); - switch (mError) { + final int ret; + try { + ret = mBinder.test(); + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + throw new AssertionError(e); + } + + switch (ret) { case NO_ERROR: return State.UNLOCKED; case LOCKED: return State.LOCKED; case UNINITIALIZED: return State.UNINITIALIZED; @@ -71,171 +74,167 @@ public class KeyStore { } } - private byte[] get(byte[] key) { - ArrayList values = execute('g', key); - return (values == null || values.isEmpty()) ? null : values.get(0); - } - public byte[] get(String key) { - return get(getKeyBytes(key)); - } - - private boolean put(byte[] key, byte[] value) { - execute('i', key, value); - return mError == NO_ERROR; + try { + return mBinder.get(key); + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return null; + } } public boolean put(String key, byte[] value) { - return put(getKeyBytes(key), value); - } - - private boolean delete(byte[] key) { - execute('d', key); - return mError == NO_ERROR; + try { + return mBinder.insert(key, value) == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public boolean delete(String key) { - return delete(getKeyBytes(key)); - } - - private boolean contains(byte[] key) { - execute('e', key); - return mError == NO_ERROR; + try { + return mBinder.del(key) == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public boolean contains(String key) { - return contains(getKeyBytes(key)); - } - - public byte[][] saw(byte[] prefix) { - ArrayList values = execute('s', prefix); - return (values == null) ? null : values.toArray(new byte[values.size()][]); + try { + return mBinder.exist(key) == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public String[] saw(String prefix) { - byte[][] values = saw(getKeyBytes(prefix)); - if (values == null) { + try { + return mBinder.saw(prefix); + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); return null; } - String[] strings = new String[values.length]; - for (int i = 0; i < values.length; ++i) { - strings[i] = toKeyString(values[i]); - } - return strings; } public boolean reset() { - execute('r'); - return mError == NO_ERROR; - } - - private boolean password(byte[] password) { - execute('p', password); - return mError == NO_ERROR; + try { + return mBinder.reset() == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public boolean password(String password) { - return password(getPasswordBytes(password)); + try { + return mBinder.password(password) == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public boolean lock() { - execute('l'); - return mError == NO_ERROR; - } - - private boolean unlock(byte[] password) { - execute('u', password); - return mError == NO_ERROR; + try { + return mBinder.lock() == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public boolean unlock(String password) { - return unlock(getPasswordBytes(password)); + try { + mError = mBinder.unlock(password); + return mError == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public boolean isEmpty() { - execute('z'); - return mError == KEY_NOT_FOUND; - } - - private boolean generate(byte[] key) { - execute('a', key); - return mError == NO_ERROR; + try { + return mBinder.zero() == KEY_NOT_FOUND; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public boolean generate(String key) { - return generate(getKeyBytes(key)); - } - - private boolean importKey(byte[] keyName, byte[] key) { - execute('m', keyName, key); - return mError == NO_ERROR; + try { + return mBinder.generate(key) == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public boolean importKey(String keyName, byte[] key) { - return importKey(getKeyBytes(keyName), key); - } - - private byte[] getPubkey(byte[] key) { - ArrayList values = execute('b', key); - return (values == null || values.isEmpty()) ? null : values.get(0); + try { + return mBinder.import_key(keyName, key) == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public byte[] getPubkey(String key) { - return getPubkey(getKeyBytes(key)); - } - - private boolean delKey(byte[] key) { - execute('k', key); - return mError == NO_ERROR; + try { + return mBinder.get_pubkey(key); + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return null; + } } public boolean delKey(String key) { - return delKey(getKeyBytes(key)); - } - - private byte[] sign(byte[] keyName, byte[] data) { - final ArrayList values = execute('n', keyName, data); - return (values == null || values.isEmpty()) ? null : values.get(0); + try { + return mBinder.del_key(key) == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public byte[] sign(String key, byte[] data) { - return sign(getKeyBytes(key), data); - } - - private boolean verify(byte[] keyName, byte[] data, byte[] signature) { - execute('v', keyName, data, signature); - return mError == NO_ERROR; + try { + return mBinder.sign(key, data); + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return null; + } } public boolean verify(String key, byte[] data, byte[] signature) { - return verify(getKeyBytes(key), data, signature); - } - - private boolean grant(byte[] key, byte[] uid) { - execute('x', key, uid); - return mError == NO_ERROR; + try { + return mBinder.verify(key, data, signature) == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public boolean grant(String key, int uid) { - return grant(getKeyBytes(key), getUidBytes(uid)); - } - - private boolean ungrant(byte[] key, byte[] uid) { - execute('y', key, uid); - return mError == NO_ERROR; + try { + return mBinder.grant(key, uid) == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } } public boolean ungrant(String key, int uid) { - return ungrant(getKeyBytes(key), getUidBytes(uid)); - } - - private long getmtime(byte[] key) { - final ArrayList values = execute('c', key); - if (values == null || values.isEmpty()) { - return -1L; + try { + return mBinder.ungrant(key, uid) == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; } - - return Long.parseLong(new String(values.get(0))) * 1000L; } /** @@ -243,101 +242,15 @@ public class KeyStore { * epoch. Will return -1L if the key could not be found or other error. */ public long getmtime(String key) { - return getmtime(getKeyBytes(key)); - } - - public int getLastError() { - return mError; - } - - private ArrayList execute(int code, byte[]... parameters) { - mError = PROTOCOL_ERROR; - - for (byte[] parameter : parameters) { - if (parameter == null || parameter.length > 65535) { - return null; - } - } - - LocalSocket socket = new LocalSocket(); - try { - socket.connect(sAddress); - - OutputStream out = socket.getOutputStream(); - out.write(code); - for (byte[] parameter : parameters) { - out.write(parameter.length >> 8); - out.write(parameter.length); - out.write(parameter); - } - out.flush(); - socket.shutdownOutput(); - - InputStream in = socket.getInputStream(); - if ((code = in.read()) != NO_ERROR) { - if (code != -1) { - mError = code; - } - return null; - } - - ArrayList values = new ArrayList(); - while (true) { - int i, j; - if ((i = in.read()) == -1) { - break; - } - if ((j = in.read()) == -1) { - return null; - } - byte[] value = new byte[i << 8 | j]; - for (i = 0; i < value.length; i += j) { - if ((j = in.read(value, i, value.length - i)) == -1) { - return null; - } - } - values.add(value); - } - mError = NO_ERROR; - return values; - } catch (IOException e) { - // ignore - } finally { - try { - socket.close(); - } catch (IOException e) {} - } - return null; - } - - /** - * ModifiedUtf8 is used for key encoding to match the - * implementation of NativeCrypto.ENGINE_load_private_key. - */ - private static byte[] getKeyBytes(String string) { try { - int utfCount = (int) ModifiedUtf8.countBytes(string, false); - byte[] result = new byte[utfCount]; - ModifiedUtf8.encode(result, 0, string); - return result; - } catch (UTFDataFormatException e) { - throw new RuntimeException(e); - } - } - - private static String toKeyString(byte[] bytes) { - try { - return ModifiedUtf8.decode(bytes, new char[bytes.length], 0, bytes.length); - } catch (UTFDataFormatException e) { - throw new RuntimeException(e); + return mBinder.getmtime(key); + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return -1L; } } - private static byte[] getPasswordBytes(String password) { - return password.getBytes(Charsets.UTF_8); - } - - private static byte[] getUidBytes(int uid) { - return Integer.toString(uid).getBytes(Charsets.UTF_8); + public int getLastError() { + return mError; } } -- cgit v1.1