144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh/*
244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * Copyright (C) 2009 The Android Open Source Project
344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh *
444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License");
544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * you may not use this file except in compliance with the License.
644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * You may obtain a copy of the License at
744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh *
844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh *      http://www.apache.org/licenses/LICENSE-2.0
944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh *
1044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software
1144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS,
1244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * See the License for the specific language governing permissions and
1444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * limitations under the License.
1544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh */
1644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1744039172627d1c15737ea73836ad375559d76211Chia-chi Yehpackage android.security;
1844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1944039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport android.net.LocalSocketAddress;
2044039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport android.net.LocalSocket;
2144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
2244039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport java.io.InputStream;
2344039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport java.io.IOException;
2444039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport java.io.OutputStream;
255b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstromimport java.io.UTFDataFormatException;
2646703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstromimport java.nio.charset.Charsets;
275b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstromimport java.nio.charset.ModifiedUtf8;
2844039172627d1c15737ea73836ad375559d76211Chia-chi Yehimport java.util.ArrayList;
2944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
3044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh/**
3146703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom * @hide This should not be made public in its present form because it
3246703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom * assumes that private and secret key bytes are available and would
3346703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom * preclude the use of hardware crypto.
3444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh */
3544039172627d1c15737ea73836ad375559d76211Chia-chi Yehpublic class KeyStore {
365cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom
375cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    // ResponseCodes
387e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int NO_ERROR = 1;
397e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int LOCKED = 2;
407e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int UNINITIALIZED = 3;
417e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int SYSTEM_ERROR = 4;
427e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int PROTOCOL_ERROR = 5;
437e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int PERMISSION_DENIED = 6;
447e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int KEY_NOT_FOUND = 7;
457e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int VALUE_CORRUPTED = 8;
467e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int UNDEFINED_ACTION = 9;
477e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int WRONG_PASSWORD = 10;
485cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom
495cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    // States
505cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
5144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
5244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    private static final LocalSocketAddress sAddress = new LocalSocketAddress(
5344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            "keystore", LocalSocketAddress.Namespace.RESERVED);
5444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
5544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    private int mError = NO_ERROR;
5644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
5744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    private KeyStore() {}
5844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
5944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public static KeyStore getInstance() {
6044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return new KeyStore();
6144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
6244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
635cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    public State state() {
6444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        execute('t');
655cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom        switch (mError) {
665cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            case NO_ERROR: return State.UNLOCKED;
675cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            case LOCKED: return State.LOCKED;
685cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            case UNINITIALIZED: return State.UNINITIALIZED;
695cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            default: throw new AssertionError(mError);
705cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom        }
7144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
7244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
735cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    private byte[] get(byte[] key) {
74d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh        ArrayList<byte[]> values = execute('g', key);
7534c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich        return (values == null || values.isEmpty()) ? null : values.get(0);
7644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
7744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
785cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    public byte[] get(String key) {
795b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return get(getKeyBytes(key));
8044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
8144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
825cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    private boolean put(byte[] key, byte[] value) {
8344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        execute('i', key, value);
8444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return mError == NO_ERROR;
8544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
8644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
875cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    public boolean put(String key, byte[] value) {
885b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return put(getKeyBytes(key), value);
8944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
9044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
915cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    private boolean delete(byte[] key) {
9244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        execute('d', key);
9344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return mError == NO_ERROR;
9444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
9544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
9644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public boolean delete(String key) {
975b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return delete(getKeyBytes(key));
9844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
9944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1005cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    private boolean contains(byte[] key) {
10144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        execute('e', key);
10244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return mError == NO_ERROR;
10344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
10444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
10544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public boolean contains(String key) {
1065b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return contains(getKeyBytes(key));
10744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
10844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
109613fcc850686dfe71cec9809c3694be9cf02cdc7Chia-chi Yeh    public byte[][] saw(byte[] prefix) {
110d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh        ArrayList<byte[]> values = execute('s', prefix);
111d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh        return (values == null) ? null : values.toArray(new byte[values.size()][]);
11244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
11344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
114613fcc850686dfe71cec9809c3694be9cf02cdc7Chia-chi Yeh    public String[] saw(String prefix) {
1155b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        byte[][] values = saw(getKeyBytes(prefix));
11644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        if (values == null) {
11744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            return null;
11844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        }
11944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        String[] strings = new String[values.length];
12044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        for (int i = 0; i < values.length; ++i) {
1215b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom            strings[i] = toKeyString(values[i]);
12244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        }
12344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return strings;
12444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
12544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
12644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public boolean reset() {
12744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        execute('r');
12844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return mError == NO_ERROR;
12944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
13044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1315cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    private boolean password(byte[] password) {
1325cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom        execute('p', password);
13344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return mError == NO_ERROR;
13444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
13544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
13644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public boolean password(String password) {
1375b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return password(getPasswordBytes(password));
13844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
13944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
14044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public boolean lock() {
14144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        execute('l');
14244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return mError == NO_ERROR;
14344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
14444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1455cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    private boolean unlock(byte[] password) {
14644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        execute('u', password);
14744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return mError == NO_ERROR;
14844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
14944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
15044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public boolean unlock(String password) {
1515b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return unlock(getPasswordBytes(password));
15244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
15344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1545cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    public boolean isEmpty() {
1555cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom        execute('z');
1565cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom        return mError == KEY_NOT_FOUND;
1575cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    }
1585cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom
1595423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    private boolean generate(byte[] key) {
1605423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        execute('a', key);
1615423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        return mError == NO_ERROR;
1625423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
1635423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
1645423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean generate(String key) {
1655b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return generate(getKeyBytes(key));
1665423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
1675423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
1685423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    private boolean importKey(byte[] keyName, byte[] key) {
1695423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        execute('m', keyName, key);
1705423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        return mError == NO_ERROR;
1715423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
1725423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
1735423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean importKey(String keyName, byte[] key) {
1745b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return importKey(getKeyBytes(keyName), key);
1755423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
1765423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
1775423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    private byte[] getPubkey(byte[] key) {
1785423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        ArrayList<byte[]> values = execute('b', key);
1795423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        return (values == null || values.isEmpty()) ? null : values.get(0);
1805423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
1815423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
1825423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public byte[] getPubkey(String key) {
1835b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return getPubkey(getKeyBytes(key));
1845423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
1855423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
1865423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    private boolean delKey(byte[] key) {
1875423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        execute('k', key);
1885423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        return mError == NO_ERROR;
1895423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
1905423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
1915423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean delKey(String key) {
1925b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return delKey(getKeyBytes(key));
1935423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
1945423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
1955423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    private byte[] sign(byte[] keyName, byte[] data) {
1965423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        final ArrayList<byte[]> values = execute('n', keyName, data);
1975423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        return (values == null || values.isEmpty()) ? null : values.get(0);
1985423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
1995423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
2005423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public byte[] sign(String key, byte[] data) {
2015b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return sign(getKeyBytes(key), data);
2025423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
2035423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
2045423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    private boolean verify(byte[] keyName, byte[] data, byte[] signature) {
2055423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        execute('v', keyName, data, signature);
2065423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        return mError == NO_ERROR;
2075423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
2085423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
2095423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean verify(String key, byte[] data, byte[] signature) {
2105b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return verify(getKeyBytes(key), data, signature);
2115423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
2125423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
2135423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    private boolean grant(byte[] key, byte[] uid) {
2145423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        execute('x', key, uid);
2155423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        return mError == NO_ERROR;
2165423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
2175423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
2185423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean grant(String key, int uid) {
2195b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom         return grant(getKeyBytes(key), getUidBytes(uid));
2205423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
2215423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
2225423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    private boolean ungrant(byte[] key, byte[] uid) {
2235423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        execute('y', key, uid);
2245423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        return mError == NO_ERROR;
2255423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
2265423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
2275423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean ungrant(String key, int uid) {
2285b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return ungrant(getKeyBytes(key), getUidBytes(uid));
2295423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
2305423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
23144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public int getLastError() {
23244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return mError;
23344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
23444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
235d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh    private ArrayList<byte[]> execute(int code, byte[]... parameters) {
23644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        mError = PROTOCOL_ERROR;
23744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
23844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        for (byte[] parameter : parameters) {
23944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            if (parameter == null || parameter.length > 65535) {
24044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                return null;
24144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            }
24244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        }
24344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
24444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        LocalSocket socket = new LocalSocket();
24544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        try {
24644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            socket.connect(sAddress);
24744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
24844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            OutputStream out = socket.getOutputStream();
24944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            out.write(code);
25044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            for (byte[] parameter : parameters) {
25144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                out.write(parameter.length >> 8);
25244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                out.write(parameter.length);
25344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                out.write(parameter);
25444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            }
25544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            out.flush();
25644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            socket.shutdownOutput();
25744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
25844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            InputStream in = socket.getInputStream();
259f1ece5d0c16fa3e79390e41ad9bec020c77d7720Chia-chi Yeh            if ((code = in.read()) != NO_ERROR) {
260f1ece5d0c16fa3e79390e41ad9bec020c77d7720Chia-chi Yeh                if (code != -1) {
261f1ece5d0c16fa3e79390e41ad9bec020c77d7720Chia-chi Yeh                    mError = code;
262f1ece5d0c16fa3e79390e41ad9bec020c77d7720Chia-chi Yeh                }
26344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                return null;
26444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            }
26544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
266d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh            ArrayList<byte[]> values = new ArrayList<byte[]>();
26744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            while (true) {
26844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                int i, j;
26944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                if ((i = in.read()) == -1) {
27044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                    break;
27144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                }
27244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                if ((j = in.read()) == -1) {
27344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                    return null;
27444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                }
275d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh                byte[] value = new byte[i << 8 | j];
276d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh                for (i = 0; i < value.length; i += j) {
277d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh                    if ((j = in.read(value, i, value.length - i)) == -1) {
27844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                        return null;
27944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                    }
28044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                }
281d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh                values.add(value);
28244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            }
283f1ece5d0c16fa3e79390e41ad9bec020c77d7720Chia-chi Yeh            mError = NO_ERROR;
284d12feb97667498378a472c5a7895a9fcd8056ec5Chia-chi Yeh            return values;
28544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        } catch (IOException e) {
28644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            // ignore
28744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        } finally {
28844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            try {
28944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh                socket.close();
29044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            } catch (IOException e) {}
29144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        }
29244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        return null;
29344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
29434c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich
2955b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom    /**
2965b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom     * ModifiedUtf8 is used for key encoding to match the
2975b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom     * implementation of NativeCrypto.ENGINE_load_private_key.
2985b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom     */
2995b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom    private static byte[] getKeyBytes(String string) {
3005b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        try {
3015b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom            int utfCount = (int) ModifiedUtf8.countBytes(string, false);
3025b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom            byte[] result = new byte[utfCount];
3035b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom            ModifiedUtf8.encode(result, 0, string);
3045b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom            return result;
3055b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        } catch (UTFDataFormatException e) {
3065b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom            throw new RuntimeException(e);
3075b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        }
3085b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom    }
3095b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom
3105b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom    private static String toKeyString(byte[] bytes) {
3115b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        try {
3125b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom            return ModifiedUtf8.decode(bytes, new char[bytes.length], 0, bytes.length);
3135b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        } catch (UTFDataFormatException e) {
3145b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom            throw new RuntimeException(e);
3155b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        }
3165b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom    }
3175b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom
3185b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom    private static byte[] getPasswordBytes(String password) {
3195b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return password.getBytes(Charsets.UTF_8);
32034c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich    }
32134c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich
3225b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom    private static byte[] getUidBytes(int uid) {
3235b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        return Integer.toString(uid).getBytes(Charsets.UTF_8);
32434c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich    }
32544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh}
326