diff options
-rw-r--r-- | cmds/servicemanager/service_manager.c | 1 | ||||
-rw-r--r-- | core/java/android/security/IKeystoreService.java | 505 | ||||
-rw-r--r-- | keystore/java/android/security/KeyStore.java | 353 |
3 files changed, 639 insertions, 220 deletions
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c index 71e840e..c563a82 100644 --- a/cmds/servicemanager/service_manager.c +++ b/cmds/servicemanager/service_manager.c @@ -47,6 +47,7 @@ static struct { { AID_RADIO, "simphonebook" }, { AID_MEDIA, "common_time.clock" }, { AID_MEDIA, "common_time.config" }, + { AID_KEYSTORE, "android.security.keystore" }, }; void *svcmgr_handle; diff --git a/core/java/android/security/IKeystoreService.java b/core/java/android/security/IKeystoreService.java new file mode 100644 index 0000000..f8a49e6 --- /dev/null +++ b/core/java/android/security/IKeystoreService.java @@ -0,0 +1,505 @@ +/* + * Copyright (C) 2012 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.Binder; +import android.os.IBinder; +import android.os.IInterface; +import android.os.Parcel; +import android.os.RemoteException; + +/** + * This must be kept manually in sync with system/security/keystore until AIDL + * can generate both Java and C++ bindings. + * + * @hide + */ +public interface IKeystoreService extends IInterface { + public static abstract class Stub extends Binder implements IKeystoreService { + private static class Proxy implements IKeystoreService { + private final IBinder mRemote; + + Proxy(IBinder remote) { + mRemote = remote; + } + + public IBinder asBinder() { + return mRemote; + } + + public String getInterfaceDescriptor() { + return DESCRIPTOR; + } + + public int test() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_test, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public byte[] get(String name) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + byte[] _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + mRemote.transact(Stub.TRANSACTION_get, _data, _reply, 0); + _reply.readException(); + _result = _reply.createByteArray(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int insert(String name, byte[] item) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + _data.writeByteArray(item); + mRemote.transact(Stub.TRANSACTION_insert, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int del(String name) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + mRemote.transact(Stub.TRANSACTION_del, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int exist(String name) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + mRemote.transact(Stub.TRANSACTION_exist, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public String[] saw(String name) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + String[] _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + mRemote.transact(Stub.TRANSACTION_saw, _data, _reply, 0); + _reply.readException(); + int size = _reply.readInt(); + _result = new String[size]; + for (int i = 0; i < size; i++) { + _result[i] = _reply.readString(); + } + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + @Override + public int reset() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_reset, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int password(String password) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(password); + mRemote.transact(Stub.TRANSACTION_password, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int lock() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_lock, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int unlock(String password) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(password); + mRemote.transact(Stub.TRANSACTION_unlock, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + @Override + public int zero() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_zero, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int generate(String name) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + mRemote.transact(Stub.TRANSACTION_generate, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int import_key(String name, byte[] data) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + _data.writeByteArray(data); + mRemote.transact(Stub.TRANSACTION_import, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public byte[] sign(String name, byte[] data) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + byte[] _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + _data.writeByteArray(data); + mRemote.transact(Stub.TRANSACTION_sign, _data, _reply, 0); + _reply.readException(); + _result = _reply.createByteArray(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int verify(String name, byte[] data, byte[] signature) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + _data.writeByteArray(data); + _data.writeByteArray(signature); + mRemote.transact(Stub.TRANSACTION_verify, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public byte[] get_pubkey(String name) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + byte[] _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + mRemote.transact(Stub.TRANSACTION_get_pubkey, _data, _reply, 0); + _reply.readException(); + _result = _reply.createByteArray(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int del_key(String name) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + mRemote.transact(Stub.TRANSACTION_del_key, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int grant(String name, int granteeUid) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + _data.writeInt(granteeUid); + mRemote.transact(Stub.TRANSACTION_grant, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int ungrant(String name, int granteeUid) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + _data.writeInt(granteeUid); + mRemote.transact(Stub.TRANSACTION_ungrant, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + @Override + public long getmtime(String name) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + long _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(name); + mRemote.transact(Stub.TRANSACTION_getmtime, _data, _reply, 0); + _reply.readException(); + _result = _reply.readLong(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + } + + private static final String DESCRIPTOR = "android.security.keystore"; + + static final int TRANSACTION_test = IBinder.FIRST_CALL_TRANSACTION + 0; + static final int TRANSACTION_get = IBinder.FIRST_CALL_TRANSACTION + 1; + static final int TRANSACTION_insert = IBinder.FIRST_CALL_TRANSACTION + 2; + static final int TRANSACTION_del = IBinder.FIRST_CALL_TRANSACTION + 3; + static final int TRANSACTION_exist = IBinder.FIRST_CALL_TRANSACTION + 4; + static final int TRANSACTION_saw = IBinder.FIRST_CALL_TRANSACTION + 5; + static final int TRANSACTION_reset = IBinder.FIRST_CALL_TRANSACTION + 6; + static final int TRANSACTION_password = IBinder.FIRST_CALL_TRANSACTION + 7; + static final int TRANSACTION_lock = IBinder.FIRST_CALL_TRANSACTION + 8; + static final int TRANSACTION_unlock = IBinder.FIRST_CALL_TRANSACTION + 9; + static final int TRANSACTION_zero = IBinder.FIRST_CALL_TRANSACTION + 10; + static final int TRANSACTION_generate = IBinder.FIRST_CALL_TRANSACTION + 11; + static final int TRANSACTION_import = IBinder.FIRST_CALL_TRANSACTION + 12; + static final int TRANSACTION_sign = IBinder.FIRST_CALL_TRANSACTION + 13; + static final int TRANSACTION_verify = IBinder.FIRST_CALL_TRANSACTION + 14; + static final int TRANSACTION_get_pubkey = IBinder.FIRST_CALL_TRANSACTION + 15; + static final int TRANSACTION_del_key = IBinder.FIRST_CALL_TRANSACTION + 16; + static final int TRANSACTION_grant = IBinder.FIRST_CALL_TRANSACTION + 17; + static final int TRANSACTION_ungrant = IBinder.FIRST_CALL_TRANSACTION + 18; + static final int TRANSACTION_getmtime = IBinder.FIRST_CALL_TRANSACTION + 19; + + /** + * Cast an IBinder object into an IKeystoreService interface, generating + * a proxy if needed. + */ + public static IKeystoreService asInterface(IBinder obj) { + if (obj == null) { + return null; + } + IInterface iin = obj.queryLocalInterface(DESCRIPTOR); + if (iin != null && iin instanceof IKeystoreService) { + return (IKeystoreService) iin; + } + return new IKeystoreService.Stub.Proxy(obj); + } + + /** Construct the stub at attach it to the interface. */ + public Stub() { + attachInterface(this, DESCRIPTOR); + } + + public IBinder asBinder() { + return this; + } + + @Override + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) + throws RemoteException { + switch (code) { + case INTERFACE_TRANSACTION: { + reply.writeString(DESCRIPTOR); + return true; + } + case TRANSACTION_test: { + data.enforceInterface(DESCRIPTOR); + int resultCode = test(); + reply.writeNoException(); + reply.writeInt(resultCode); + return true; + } + } + return super.onTransact(code, data, reply, flags); + } + } + + public int test() throws RemoteException; + + public byte[] get(String name) throws RemoteException; + + public int insert(String name, byte[] item) throws RemoteException; + + public int del(String name) throws RemoteException; + + public int exist(String name) throws RemoteException; + + public String[] saw(String name) throws RemoteException; + + public int reset() throws RemoteException; + + public int password(String password) throws RemoteException; + + public int lock() throws RemoteException; + + public int unlock(String password) throws RemoteException; + + public int zero() throws RemoteException; + + public int generate(String name) throws RemoteException; + + public int import_key(String name, byte[] data) throws RemoteException; + + public byte[] sign(String name, byte[] data) throws RemoteException; + + public int verify(String name, byte[] data, byte[] signature) throws RemoteException; + + public byte[] get_pubkey(String name) throws RemoteException; + + public int del_key(String name) throws RemoteException; + + public int grant(String name, int granteeUid) throws RemoteException; + + public int ungrant(String name, int granteeUid) throws RemoteException; + + public long getmtime(String name) throws RemoteException; +} 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<byte[]> 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<byte[]> 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<byte[]> 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<byte[]> 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<byte[]> 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<byte[]> 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<byte[]> values = new ArrayList<byte[]>(); - 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; } } |