KeyStore.java revision 46703b099516c383a6882815bcf9cd4df0ec538d
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.security; 18 19import android.net.LocalSocketAddress; 20import android.net.LocalSocket; 21 22import java.io.InputStream; 23import java.io.IOException; 24import java.io.OutputStream; 25import java.io.UnsupportedEncodingException; 26import java.nio.charset.Charsets; 27import java.util.ArrayList; 28 29/** 30 * @hide This should not be made public in its present form because it 31 * assumes that private and secret key bytes are available and would 32 * preclude the use of hardware crypto. 33 */ 34public class KeyStore { 35 public static final int NO_ERROR = 1; 36 public static final int LOCKED = 2; 37 public static final int UNINITIALIZED = 3; 38 public static final int SYSTEM_ERROR = 4; 39 public static final int PROTOCOL_ERROR = 5; 40 public static final int PERMISSION_DENIED = 6; 41 public static final int KEY_NOT_FOUND = 7; 42 public static final int VALUE_CORRUPTED = 8; 43 public static final int UNDEFINED_ACTION = 9; 44 public static final int WRONG_PASSWORD = 10; 45 46 private static final LocalSocketAddress sAddress = new LocalSocketAddress( 47 "keystore", LocalSocketAddress.Namespace.RESERVED); 48 49 private int mError = NO_ERROR; 50 51 private KeyStore() {} 52 53 public static KeyStore getInstance() { 54 return new KeyStore(); 55 } 56 57 public int test() { 58 execute('t'); 59 return mError; 60 } 61 62 public byte[] get(byte[] key) { 63 ArrayList<byte[]> values = execute('g', key); 64 return (values == null || values.isEmpty()) ? null : values.get(0); 65 } 66 67 public String get(String key) { 68 byte[] value = get(getBytes(key)); 69 return (value == null) ? null : toString(value); 70 } 71 72 public boolean put(byte[] key, byte[] value) { 73 execute('i', key, value); 74 return mError == NO_ERROR; 75 } 76 77 public boolean put(String key, String value) { 78 return put(getBytes(key), getBytes(value)); 79 } 80 81 public boolean delete(byte[] key) { 82 execute('d', key); 83 return mError == NO_ERROR; 84 } 85 86 public boolean delete(String key) { 87 return delete(getBytes(key)); 88 } 89 90 public boolean contains(byte[] key) { 91 execute('e', key); 92 return mError == NO_ERROR; 93 } 94 95 public boolean contains(String key) { 96 return contains(getBytes(key)); 97 } 98 99 public byte[][] saw(byte[] prefix) { 100 ArrayList<byte[]> values = execute('s', prefix); 101 return (values == null) ? null : values.toArray(new byte[values.size()][]); 102 } 103 104 public String[] saw(String prefix) { 105 byte[][] values = saw(getBytes(prefix)); 106 if (values == null) { 107 return null; 108 } 109 String[] strings = new String[values.length]; 110 for (int i = 0; i < values.length; ++i) { 111 strings[i] = toString(values[i]); 112 } 113 return strings; 114 } 115 116 public boolean reset() { 117 execute('r'); 118 return mError == NO_ERROR; 119 } 120 121 public boolean password(byte[] oldPassword, byte[] newPassword) { 122 execute('p', oldPassword, newPassword); 123 return mError == NO_ERROR; 124 } 125 126 public boolean password(String oldPassword, String newPassword) { 127 return password(getBytes(oldPassword), getBytes(newPassword)); 128 } 129 130 public boolean password(byte[] password) { 131 return password(password, password); 132 } 133 134 public boolean password(String password) { 135 return password(getBytes(password)); 136 } 137 138 public boolean lock() { 139 execute('l'); 140 return mError == NO_ERROR; 141 } 142 143 public boolean unlock(byte[] password) { 144 execute('u', password); 145 return mError == NO_ERROR; 146 } 147 148 public boolean unlock(String password) { 149 return unlock(getBytes(password)); 150 } 151 152 public int getLastError() { 153 return mError; 154 } 155 156 private ArrayList<byte[]> execute(int code, byte[]... parameters) { 157 mError = PROTOCOL_ERROR; 158 159 for (byte[] parameter : parameters) { 160 if (parameter == null || parameter.length > 65535) { 161 return null; 162 } 163 } 164 165 LocalSocket socket = new LocalSocket(); 166 try { 167 socket.connect(sAddress); 168 169 OutputStream out = socket.getOutputStream(); 170 out.write(code); 171 for (byte[] parameter : parameters) { 172 out.write(parameter.length >> 8); 173 out.write(parameter.length); 174 out.write(parameter); 175 } 176 out.flush(); 177 socket.shutdownOutput(); 178 179 InputStream in = socket.getInputStream(); 180 if ((code = in.read()) != NO_ERROR) { 181 if (code != -1) { 182 mError = code; 183 } 184 return null; 185 } 186 187 ArrayList<byte[]> values = new ArrayList<byte[]>(); 188 while (true) { 189 int i, j; 190 if ((i = in.read()) == -1) { 191 break; 192 } 193 if ((j = in.read()) == -1) { 194 return null; 195 } 196 byte[] value = new byte[i << 8 | j]; 197 for (i = 0; i < value.length; i += j) { 198 if ((j = in.read(value, i, value.length - i)) == -1) { 199 return null; 200 } 201 } 202 values.add(value); 203 } 204 mError = NO_ERROR; 205 return values; 206 } catch (IOException e) { 207 // ignore 208 } finally { 209 try { 210 socket.close(); 211 } catch (IOException e) {} 212 } 213 return null; 214 } 215 216 private static byte[] getBytes(String string) { 217 return string.getBytes(Charsets.UTF_8); 218 } 219 220 private static String toString(byte[] bytes) { 221 return new String(bytes, Charsets.UTF_8); 222 } 223} 224