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