KeyStore.java revision 44039172627d1c15737ea73836ad375559d76211
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.util.ArrayList;
26
27/**
28 * {@hide}
29 */
30public class KeyStore {
31    public static int NO_ERROR = 1;
32    public static int LOCKED = 2;
33    public static int UNINITIALIZED = 3;
34    public static int SYSTEM_ERROR = 4;
35    public static int PROTOCOL_ERROR = 5;
36    public static int PERMISSION_DENIED = 6;
37    public static int KEY_NOT_FOUND = 7;
38    public static int VALUE_CORRUPTED = 8;
39    public static int UNDEFINED_ACTION = 9;
40    public static int WRONG_PASSWORD = 10;
41
42    private static final LocalSocketAddress sAddress = new LocalSocketAddress(
43            "keystore", LocalSocketAddress.Namespace.RESERVED);
44
45    private int mError = NO_ERROR;
46
47    private KeyStore() {}
48
49    public static KeyStore getInstance() {
50        return new KeyStore();
51    }
52
53    public int test() {
54        execute('t');
55        return mError;
56    }
57
58    public byte[] get(byte[] key) {
59        byte[][] values = execute('g', key);
60        return (values == null) ? null : values[0];
61    }
62
63    public String get(String key) {
64        byte[] value = get(key.getBytes());
65        return (value == null) ? null : new String(value);
66    }
67
68    public boolean put(byte[] key, byte[] value) {
69        execute('i', key, value);
70        return mError == NO_ERROR;
71    }
72
73    public boolean put(String key, String value) {
74        return put(key.getBytes(), value.getBytes());
75    }
76
77    public boolean delete(byte[] key) {
78        execute('d', key);
79        return mError == NO_ERROR;
80    }
81
82    public boolean delete(String key) {
83        return delete(key.getBytes());
84    }
85
86    public boolean contains(byte[] key) {
87        execute('e', key);
88        return mError == NO_ERROR;
89    }
90
91    public boolean contains(String key) {
92        return contains(key.getBytes());
93    }
94
95    public byte[][] scan(byte[] prefix) {
96        return execute('s', prefix);
97    }
98
99    public String[] scan(String prefix) {
100        byte[][] values = scan(prefix.getBytes());
101        if (values == null) {
102            return null;
103        }
104        String[] strings = new String[values.length];
105        for (int i = 0; i < values.length; ++i) {
106            strings[i] = new String(values[i]);
107        }
108        return strings;
109    }
110
111    public boolean reset() {
112        execute('r');
113        return mError == NO_ERROR;
114    }
115
116    public boolean password(byte[] oldPassword, byte[] newPassword) {
117        execute('p', oldPassword, newPassword);
118        return mError == NO_ERROR;
119    }
120
121    public boolean password(String oldPassword, String newPassword) {
122        return password(oldPassword.getBytes(), newPassword.getBytes());
123    }
124
125    public boolean password(byte[] password) {
126        return password(password, password);
127    }
128
129    public boolean password(String password) {
130        return password(password.getBytes());
131    }
132
133    public boolean lock() {
134        execute('l');
135        return mError == NO_ERROR;
136    }
137
138    public boolean unlock(byte[] password) {
139        execute('u', password);
140        return mError == NO_ERROR;
141    }
142
143    public boolean unlock(String password) {
144        return unlock(password.getBytes());
145    }
146
147    public int getLastError() {
148        return mError;
149    }
150
151    private byte[][] execute(int code, byte[]... parameters) {
152        mError = PROTOCOL_ERROR;
153
154        for (byte[] parameter : parameters) {
155            if (parameter == null || parameter.length > 65535) {
156                return null;
157            }
158        }
159
160        LocalSocket socket = new LocalSocket();
161        try {
162            socket.connect(sAddress);
163
164            OutputStream out = socket.getOutputStream();
165            out.write(code);
166            for (byte[] parameter : parameters) {
167                out.write(parameter.length >> 8);
168                out.write(parameter.length);
169                out.write(parameter);
170            }
171            out.flush();
172            socket.shutdownOutput();
173
174            InputStream in = socket.getInputStream();
175            code = in.read();
176            if (code == -1) {
177                return null;
178            }
179
180            ArrayList<byte[]> results = new ArrayList<byte[]>();
181            while (true) {
182                int i, j;
183                if ((i = in.read()) == -1) {
184                    break;
185                }
186                if ((j = in.read()) == -1) {
187                    return null;
188                }
189                byte[] result = new byte[i << 8 | j];
190                for (i = 0; i < result.length; i += j) {
191                    if ((j = in.read(result, i, result.length - i)) == -1) {
192                        return null;
193                    }
194                }
195                results.add(result);
196            }
197            mError = code;
198            return results.toArray(new byte[results.size()][]);
199        } catch (IOException e) {
200            // ignore
201        } finally {
202            try {
203                socket.close();
204            } catch (IOException e) {}
205        }
206        return null;
207    }
208}
209