blob: 66edd566166a1c78cd01343c870b953c5b34bf6b [file] [log] [blame]
Jean-Baptiste Queru4d3b5c12009-07-21 11:16:54 -07001/*
2** Copyright 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
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22#include <ctype.h>
23#include <fcntl.h>
24#include <dirent.h>
25#include <errno.h>
26#include <openssl/aes.h>
27#include <openssl/evp.h>
28#include <cutils/log.h>
29
30#include "common.h"
31#include "keymgmt.h"
32
33static int retry_count = 0;
34static unsigned char iv[IV_LEN];
35static KEYSTORE_STATE state = BOOTUP;
36static AES_KEY encryptKey, decryptKey;
37
38inline void unlock_keystore(unsigned char *master_key)
39{
40 AES_set_encrypt_key(master_key, AES_KEY_LEN, &encryptKey);
41 AES_set_decrypt_key(master_key, AES_KEY_LEN, &decryptKey);
42 memset(master_key, 0, sizeof(master_key));
43 state = UNLOCKED;
44}
45
46inline void lock_keystore()
47{
48 memset(&encryptKey, 0 , sizeof(AES_KEY));
49 memset(&decryptKey, 0 , sizeof(AES_KEY));
50 state = LOCKED;
51}
52
53inline void get_encrypt_key(char *passwd, AES_KEY *key)
54{
55 unsigned char user_key[USER_KEY_LEN];
56 gen_key(passwd, user_key, USER_KEY_LEN);
57 AES_set_encrypt_key(user_key, AES_KEY_LEN, key);
58}
59
60inline void get_decrypt_key(char *passwd, AES_KEY *key)
61{
62 unsigned char user_key[USER_KEY_LEN];
63 gen_key(passwd, user_key, USER_KEY_LEN);
64 AES_set_decrypt_key(user_key, AES_KEY_LEN, key);
65}
66
67static int gen_random_blob(unsigned char *key, int size)
68{
69 int ret = 0;
70 int fd = open("/dev/urandom", O_RDONLY);
71 if (fd == -1) return -1;
72 if (read(fd, key, size) != size) ret = -1;
73 close(fd);
74 return ret;
75}
76
77static int encrypt_n_save(AES_KEY *enc_key, DATA_BLOB *blob,
78 const char *keyfile)
79{
80 int size, fd, ret = -1;
81 unsigned char enc_blob[MAX_BLOB_LEN];
82
83 char tmpfile[KEYFILE_LEN];
84 strcpy(tmpfile, keyfile);
85 strcat(tmpfile, ".tmp");
86
87 // prepare the blob
88 memcpy(blob->iv, iv, IV_LEN);
89 blob->blob_size = get_blob_size(blob);
90 memcpy(enc_blob, blob->blob, blob->blob_size);
91 AES_cbc_encrypt((unsigned char *)enc_blob, (unsigned char *)blob->blob,
92 blob->blob_size, enc_key, iv, AES_ENCRYPT);
93 // write to keyfile
94 size = data_blob_size(blob);
95 if ((fd = open(tmpfile, O_CREAT|O_RDWR)) == -1) return -1;
96 if (write(fd, blob, size) == size) ret = 0;
97 close(fd);
98 if (!ret) {
99 unlink(keyfile);
100 rename(tmpfile, keyfile);
101 chmod(keyfile, 0440);
102 }
103 return ret;
104}
105
106static int load_n_decrypt(const char *keyname, const char *keyfile,
107 AES_KEY *key, DATA_BLOB *blob)
108{
109 int fd, ret = -1;
110 if ((fd = open(keyfile, O_RDONLY)) == -1) return -1;
111 // get the encrypted blob and iv
112 if ((read(fd, blob->iv, sizeof(blob->iv)) != sizeof(blob->iv)) ||
113 (read(fd, &blob->blob_size, sizeof(uint32_t)) != sizeof(uint32_t)) ||
114 (blob->blob_size > MAX_BLOB_LEN)) {
115 goto err;
116 } else {
117 unsigned char enc_blob[MAX_BLOB_LEN];
118 if (read(fd, enc_blob, blob->blob_size) !=
119 (int) blob->blob_size) goto err;
120 // decrypt the blob
121 AES_cbc_encrypt((unsigned char *)enc_blob, (unsigned char*)blob->blob,
122 blob->blob_size, key, blob->iv, AES_DECRYPT);
123 if (strcmp(keyname, (char*)blob->keyname) == 0) ret = 0;
124 }
125err:
126 close(fd);
127 return ret;
128}
129
130static int store_master_key(char *upasswd, unsigned char *master_key)
131{
132 AES_KEY key;
133 DATA_BLOB blob;
134
135 // prepare the blob
136 strlcpy(blob.keyname, MASTER_KEY_TAG, USER_KEY_LEN);
137 blob.value_size = USER_KEY_LEN;
138 memcpy((void*)blob.value, (const void*)master_key, USER_KEY_LEN);
139
140 // generate the encryption key
141 get_encrypt_key(upasswd, &key);
142 return encrypt_n_save(&key, &blob, MASTER_KEY);
143}
144
145static int get_master_key(char *upasswd, unsigned char *master_key)
146{
147 AES_KEY key;
148 int size, ret = 0;
149 DATA_BLOB blob;
150
151 get_decrypt_key(upasswd, &key);
152 ret = load_n_decrypt(MASTER_KEY_TAG, MASTER_KEY, &key, &blob);
153 if (!ret) memcpy(master_key, blob.value, blob.value_size);
154 return ret;
155}
156
157static int create_master_key(char *upasswd)
158{
159 int ret;
160 unsigned char mpasswd[AES_KEY_LEN];
161 unsigned char master_key[USER_KEY_LEN];
162
163 gen_random_blob(mpasswd, AES_KEY_LEN);
164 gen_key((char*)mpasswd, master_key, USER_KEY_LEN);
165 if ((ret = store_master_key(upasswd, master_key)) == 0) {
166 unlock_keystore(master_key);
167 }
168 memset(master_key, 0, USER_KEY_LEN);
169 memset(mpasswd, 0, AES_KEY_LEN);
170
171 return ret;
172}
173
174static int change_passwd(char *data)
175{
176 unsigned char master_key[USER_KEY_LEN];
177 char *old_pass, *new_pass = NULL, *p, *delimiter=" ";
178 int ret, count = 0;
179 char *context = NULL;
180
181 old_pass = p = strtok_r(data, delimiter, &context);
182 while (p != NULL) {
183 count++;
184 new_pass = p;
185 p = strtok_r(NULL, delimiter, &context);
186 }
187 if (count != 2) return -1;
188 if (strlen(new_pass) < MIN_PASSWD_LENGTH) return -1;
189 if ((ret = get_master_key(old_pass, master_key)) == 0) {
190 ret = store_master_key(new_pass, master_key);
191 retry_count = 0;
192 } else {
193 ret = MAX_RETRY_COUNT - ++retry_count;
194 if (ret == 0) {
195 retry_count = 0;
196 LOGE("passwd:reach max retry count, reset the keystore now.");
197 reset_keystore();
198 return -1;
199 }
200
201 }
202 return ret;
203}
204
205int remove_key(const char *namespace, const char *keyname)
206{
207 char keyfile[KEYFILE_LEN];
208
209 if (state != UNLOCKED) return -state;
210 sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
211 return unlink(keyfile);
212}
213
214int put_key(const char *namespace, const char *keyname,
215 unsigned char *data, int size)
216{
217 DATA_BLOB blob;
218 uint32_t real_size;
219 char keyfile[KEYFILE_LEN];
220
221 if (state != UNLOCKED) {
222 LOGE("Can not store key with current state %d\n", state);
223 return -state;
224 }
225 sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
226 // flatten the args
227 strcpy(blob.keyname, keyname);
228 blob.value_size = size;
229 memcpy(blob.value, data, size);
230 return encrypt_n_save(&encryptKey, &blob, keyfile);
231}
232
233int get_key(const char *namespace, const char *keyname,
234 unsigned char *data, int *size)
235{
236 int ret;
237 DATA_BLOB blob;
238 uint32_t blob_size;
239 char keyfile[KEYFILE_LEN];
240
241 if (state != UNLOCKED) {
242 LOGE("Can not retrieve key value with current state %d\n", state);
243 return -state;
244 }
245 sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
246 ret = load_n_decrypt(keyname, keyfile, &decryptKey, &blob);
247 if (!ret) {
248 if ((blob.value_size > MAX_KEY_VALUE_LENGTH)) {
249 ret = -1;
250 } else {
251 *size = blob.value_size;
252 memcpy(data, blob.value, *size);
253 }
254 }
255 return ret;
256}
257
258int list_keys(const char *namespace, char reply[BUFFER_MAX])
259{
260 DIR *d;
261 struct dirent *de;
262
263 if (state != UNLOCKED) {
264 LOGE("Can not list key with current state %d\n", state);
265 return -1;
266 }
267
268 if (!namespace || ((d = opendir("."))) == NULL) {
269 LOGE("cannot open keystore dir or namespace is null\n");
270 return -1;
271 }
272 while ((de = readdir(d))) {
273 char *prefix, *name, *keyfile = de->d_name;
274 char *context = NULL;
275
276 if (de->d_type != DT_REG) continue;
277 if ((prefix = strtok_r(keyfile, NAME_DELIMITER, &context))
278 == NULL) continue;
279 if (strcmp(prefix, namespace)) continue;
280 if ((name = strtok_r(NULL, NAME_DELIMITER, &context)) == NULL) continue;
281 // append the key name into reply
282 if (reply[0] != 0) strlcat(reply, " ", BUFFER_MAX);
283 if (strlcat(reply, name, BUFFER_MAX) >= BUFFER_MAX) {
284 LOGE("too many files under keystore directory\n");
285 return -1;
286 }
287 }
288 closedir(d);
289 return 0;
290}
291
292int passwd(char *data)
293{
294 if (state == UNINITIALIZED) {
295 if (strchr(data, ' ')) return -1;
296 if (strlen(data) < MIN_PASSWD_LENGTH) return -1;
297 return create_master_key(data);
298 }
299 return change_passwd(data);
300}
301
302int lock()
303{
304 switch(state) {
305 case UNLOCKED:
306 lock_keystore();
307 case LOCKED:
308 return 0;
309 default:
310 return -1;
311 }
312}
313
314int unlock(char *passwd)
315{
316 unsigned char master_key[USER_KEY_LEN];
317 int ret = get_master_key(passwd, master_key);
318 if (!ret) {
319 unlock_keystore(master_key);
320 retry_count = 0;
321 } else {
322 ret = MAX_RETRY_COUNT - ++retry_count;
323 if (ret == 0) {
324 retry_count = 0;
325 LOGE("unlock:reach max retry count, reset the keystore now.");
326 reset_keystore();
327 return -1;
328 }
329 }
330 return ret;
331}
332
333KEYSTORE_STATE get_state()
334{
335 return state;
336}
337
338int reset_keystore()
339{
340 DIR *d;
341 struct dirent *de;
342
343 if ((d = opendir(".")) == NULL) {
344 LOGE("cannot open keystore dir\n");
345 return -1;
346 }
347 while ((de = readdir(d))) unlink(de->d_name);
348 closedir(d);
349 state = UNINITIALIZED;
350 LOGI("keystore is reset.");
351 return 0;
352}
353
354int init_keystore(const char *dir)
355{
356 int fd;
357
358 if (!dir) mkdir(dir, 0770);
359 if (!dir || chdir(dir)) {
360 LOGE("Can not open/create the keystore directory %s\n",
361 dir ? dir : "(null)");
362 return -1;
363 }
364 gen_random_blob(iv, IV_LEN);
365 if ((fd = open(MASTER_KEY, O_RDONLY)) == -1) {
366 state = UNINITIALIZED;
367 return 0;
368 }
369 close(fd);
370 state = LOCKED;
371 return 0;
372}