blob: 7183688bd356c98f12b54c98e9bc43b76341f673 [file] [log] [blame]
Chia-chi Yeh44039172009-09-21 11:53:59 +08001/*
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;
Nick Kralevich34c47c82010-03-09 13:28:14 -080025import java.io.UnsupportedEncodingException;
Brian Carlstrom46703b02011-04-06 15:41:29 -070026import java.nio.charset.Charsets;
Chia-chi Yeh44039172009-09-21 11:53:59 +080027import java.util.ArrayList;
28
29/**
Brian Carlstrom46703b02011-04-06 15:41:29 -070030 * @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.
Chia-chi Yeh44039172009-09-21 11:53:59 +080033 */
34public class KeyStore {
Chia-chi Yehd12feb92010-02-06 10:43:22 +080035 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;
Chia-chi Yeh44039172009-09-21 11:53:59 +080045
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) {
Chia-chi Yehd12feb92010-02-06 10:43:22 +080063 ArrayList<byte[]> values = execute('g', key);
Nick Kralevich34c47c82010-03-09 13:28:14 -080064 return (values == null || values.isEmpty()) ? null : values.get(0);
Chia-chi Yeh44039172009-09-21 11:53:59 +080065 }
66
67 public String get(String key) {
Nick Kralevich34c47c82010-03-09 13:28:14 -080068 byte[] value = get(getBytes(key));
69 return (value == null) ? null : toString(value);
Chia-chi Yeh44039172009-09-21 11:53:59 +080070 }
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) {
Nick Kralevich34c47c82010-03-09 13:28:14 -080078 return put(getBytes(key), getBytes(value));
Chia-chi Yeh44039172009-09-21 11:53:59 +080079 }
80
81 public boolean delete(byte[] key) {
82 execute('d', key);
83 return mError == NO_ERROR;
84 }
85
86 public boolean delete(String key) {
Nick Kralevich34c47c82010-03-09 13:28:14 -080087 return delete(getBytes(key));
Chia-chi Yeh44039172009-09-21 11:53:59 +080088 }
89
90 public boolean contains(byte[] key) {
91 execute('e', key);
92 return mError == NO_ERROR;
93 }
94
95 public boolean contains(String key) {
Nick Kralevich34c47c82010-03-09 13:28:14 -080096 return contains(getBytes(key));
Chia-chi Yeh44039172009-09-21 11:53:59 +080097 }
98
Chia-chi Yeh613fcc82009-09-22 03:04:46 +080099 public byte[][] saw(byte[] prefix) {
Chia-chi Yehd12feb92010-02-06 10:43:22 +0800100 ArrayList<byte[]> values = execute('s', prefix);
101 return (values == null) ? null : values.toArray(new byte[values.size()][]);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800102 }
103
Chia-chi Yeh613fcc82009-09-22 03:04:46 +0800104 public String[] saw(String prefix) {
Nick Kralevich34c47c82010-03-09 13:28:14 -0800105 byte[][] values = saw(getBytes(prefix));
Chia-chi Yeh44039172009-09-21 11:53:59 +0800106 if (values == null) {
107 return null;
108 }
109 String[] strings = new String[values.length];
110 for (int i = 0; i < values.length; ++i) {
Nick Kralevich34c47c82010-03-09 13:28:14 -0800111 strings[i] = toString(values[i]);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800112 }
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) {
Nick Kralevich34c47c82010-03-09 13:28:14 -0800127 return password(getBytes(oldPassword), getBytes(newPassword));
Chia-chi Yeh44039172009-09-21 11:53:59 +0800128 }
129
130 public boolean password(byte[] password) {
131 return password(password, password);
132 }
133
134 public boolean password(String password) {
Nick Kralevich34c47c82010-03-09 13:28:14 -0800135 return password(getBytes(password));
Chia-chi Yeh44039172009-09-21 11:53:59 +0800136 }
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) {
Nick Kralevich34c47c82010-03-09 13:28:14 -0800149 return unlock(getBytes(password));
Chia-chi Yeh44039172009-09-21 11:53:59 +0800150 }
151
152 public int getLastError() {
153 return mError;
154 }
155
Chia-chi Yehd12feb92010-02-06 10:43:22 +0800156 private ArrayList<byte[]> execute(int code, byte[]... parameters) {
Chia-chi Yeh44039172009-09-21 11:53:59 +0800157 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();
Chia-chi Yehf1ece5d2009-09-24 13:29:58 +0800180 if ((code = in.read()) != NO_ERROR) {
181 if (code != -1) {
182 mError = code;
183 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800184 return null;
185 }
186
Chia-chi Yehd12feb92010-02-06 10:43:22 +0800187 ArrayList<byte[]> values = new ArrayList<byte[]>();
Chia-chi Yeh44039172009-09-21 11:53:59 +0800188 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 }
Chia-chi Yehd12feb92010-02-06 10:43:22 +0800196 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) {
Chia-chi Yeh44039172009-09-21 11:53:59 +0800199 return null;
200 }
201 }
Chia-chi Yehd12feb92010-02-06 10:43:22 +0800202 values.add(value);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800203 }
Chia-chi Yehf1ece5d2009-09-24 13:29:58 +0800204 mError = NO_ERROR;
Chia-chi Yehd12feb92010-02-06 10:43:22 +0800205 return values;
Chia-chi Yeh44039172009-09-21 11:53:59 +0800206 } catch (IOException e) {
207 // ignore
208 } finally {
209 try {
210 socket.close();
211 } catch (IOException e) {}
212 }
213 return null;
214 }
Nick Kralevich34c47c82010-03-09 13:28:14 -0800215
216 private static byte[] getBytes(String string) {
Brian Carlstrom46703b02011-04-06 15:41:29 -0700217 return string.getBytes(Charsets.UTF_8);
Nick Kralevich34c47c82010-03-09 13:28:14 -0800218 }
219
220 private static String toString(byte[] bytes) {
Brian Carlstrom46703b02011-04-06 15:41:29 -0700221 return new String(bytes, Charsets.UTF_8);
Nick Kralevich34c47c82010-03-09 13:28:14 -0800222 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800223}