KeyStore.java revision d12feb97667498378a472c5a7895a9fcd8056ec5
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 final int NO_ERROR = 1;
32    public static final int LOCKED = 2;
33    public static final int UNINITIALIZED = 3;
34    public static final int SYSTEM_ERROR = 4;
35    public static final int PROTOCOL_ERROR = 5;
36    public static final int PERMISSION_DENIED = 6;
37    public static final int KEY_NOT_FOUND = 7;
38    public static final int VALUE_CORRUPTED = 8;
39    public static final int UNDEFINED_ACTION = 9;
40    public static final 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        ArrayList<byte[]> values = execute('g', key);
60        return (values == null || values.size() == 0) ? null : values.get(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[][] saw(byte[] prefix) {
96        ArrayList<byte[]> values = execute('s', prefix);
97        return (values == null) ? null : values.toArray(new byte[values.size()][]);
98    }
99
100    public String[] saw(String prefix) {
101        byte[][] values = saw(prefix.getBytes());
102        if (values == null) {
103            return null;
104        }
105        String[] strings = new String[values.length];
106        for (int i = 0; i < values.length; ++i) {
107            strings[i] = new String(values[i]);
108        }
109        return strings;
110    }
111
112    public boolean reset() {
113        execute('r');
114        return mError == NO_ERROR;
115    }
116
117    public boolean password(byte[] oldPassword, byte[] newPassword) {
118        execute('p', oldPassword, newPassword);
119        return mError == NO_ERROR;
120    }
121
122    public boolean password(String oldPassword, String newPassword) {
123        return password(oldPassword.getBytes(), newPassword.getBytes());
124    }
125
126    public boolean password(byte[] password) {
127        return password(password, password);
128    }
129
130    public boolean password(String password) {
131        return password(password.getBytes());
132    }
133
134    public boolean lock() {
135        execute('l');
136        return mError == NO_ERROR;
137    }
138
139    public boolean unlock(byte[] password) {
140        execute('u', password);
141        return mError == NO_ERROR;
142    }
143
144    public boolean unlock(String password) {
145        return unlock(password.getBytes());
146    }
147
148    public int getLastError() {
149        return mError;
150    }
151
152    private ArrayList<byte[]> execute(int code, byte[]... parameters) {
153        mError = PROTOCOL_ERROR;
154
155        for (byte[] parameter : parameters) {
156            if (parameter == null || parameter.length > 65535) {
157                return null;
158            }
159        }
160
161        LocalSocket socket = new LocalSocket();
162        try {
163            socket.connect(sAddress);
164
165            OutputStream out = socket.getOutputStream();
166            out.write(code);
167            for (byte[] parameter : parameters) {
168                out.write(parameter.length >> 8);
169                out.write(parameter.length);
170                out.write(parameter);
171            }
172            out.flush();
173            socket.shutdownOutput();
174
175            InputStream in = socket.getInputStream();
176            if ((code = in.read()) != NO_ERROR) {
177                if (code != -1) {
178                    mError = code;
179                }
180                return null;
181            }
182
183            ArrayList<byte[]> values = new ArrayList<byte[]>();
184            while (true) {
185                int i, j;
186                if ((i = in.read()) == -1) {
187                    break;
188                }
189                if ((j = in.read()) == -1) {
190                    return null;
191                }
192                byte[] value = new byte[i << 8 | j];
193                for (i = 0; i < value.length; i += j) {
194                    if ((j = in.read(value, i, value.length - i)) == -1) {
195                        return null;
196                    }
197                }
198                values.add(value);
199            }
200            mError = NO_ERROR;
201            return values;
202        } catch (IOException e) {
203            // ignore
204        } finally {
205            try {
206                socket.close();
207            } catch (IOException e) {}
208        }
209        return null;
210    }
211}
212