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 17#include <stdio.h> 18#include <stdint.h> 19#include <string.h> 20#include <unistd.h> 21#include <signal.h> 22#include <errno.h> 23#include <dirent.h> 24#include <fcntl.h> 25#include <limits.h> 26#include <sys/types.h> 27#include <sys/socket.h> 28#include <sys/stat.h> 29#include <sys/time.h> 30#include <arpa/inet.h> 31 32#include <openssl/aes.h> 33#include <openssl/evp.h> 34#include <openssl/md5.h> 35 36#define LOG_TAG "keystore" 37#include <cutils/log.h> 38#include <cutils/sockets.h> 39#include <private/android_filesystem_config.h> 40 41#include "keystore.h" 42 43/* KeyStore is a secured storage for key-value pairs. In this implementation, 44 * each file stores one key-value pair. Keys are encoded in file names, and 45 * values are encrypted with checksums. The encryption key is protected by a 46 * user-defined password. To keep things simple, buffers are always larger than 47 * the maximum space we needed, so boundary checks on buffers are omitted. */ 48 49#define KEY_SIZE 120 50#define VALUE_SIZE 32768 51#define PASSWORD_SIZE VALUE_SIZE 52 53/* Here is the encoding of keys. This is necessary in order to allow arbitrary 54 * characters in keys. Characters in [0-~] are not encoded. Others are encoded 55 * into two bytes. The first byte is one of [+-.] which represents the first 56 * two bits of the character. The second byte encodes the rest of the bits into 57 * [0-o]. Therefore in the worst case the length of a key gets doubled. Note 58 * that Base64 cannot be used here due to the need of prefix match on keys. */ 59 60static int encode_key(char *out, uint8_t *in, int length) 61{ 62 int i; 63 for (i = length; i > 0; --i, ++in, ++out) { 64 if (*in >= '0' && *in <= '~') { 65 *out = *in; 66 } else { 67 *out = '+' + (*in >> 6); 68 *++out = '0' + (*in & 0x3F); 69 ++length; 70 } 71 } 72 *out = 0; 73 return length; 74} 75 76static int decode_key(uint8_t *out, char *in, int length) 77{ 78 int i; 79 for (i = 0; i < length; ++i, ++in, ++out) { 80 if (*in >= '0' && *in <= '~') { 81 *out = *in; 82 } else { 83 *out = (*in - '+') << 6; 84 *out |= (*++in - '0') & 0x3F; 85 --length; 86 } 87 } 88 *out = 0; 89 return length; 90} 91 92/* Here is the protocol used in both requests and responses: 93 * code [length_1 message_1 ... length_n message_n] end-of-file 94 * where code is one byte long and lengths are unsigned 16-bit integers in 95 * network order. Thus the maximum length of a message is 65535 bytes. */ 96 97static int the_socket = -1; 98 99static int recv_code(int8_t *code) 100{ 101 return recv(the_socket, code, 1, 0) == 1; 102} 103 104static int recv_message(uint8_t *message, int length) 105{ 106 uint8_t bytes[2]; 107 if (recv(the_socket, &bytes[0], 1, 0) != 1 || 108 recv(the_socket, &bytes[1], 1, 0) != 1) { 109 return -1; 110 } else { 111 int offset = bytes[0] << 8 | bytes[1]; 112 if (length < offset) { 113 return -1; 114 } 115 length = offset; 116 offset = 0; 117 while (offset < length) { 118 int n = recv(the_socket, &message[offset], length - offset, 0); 119 if (n <= 0) { 120 return -1; 121 } 122 offset += n; 123 } 124 } 125 return length; 126} 127 128static int recv_end_of_file() 129{ 130 uint8_t byte; 131 return recv(the_socket, &byte, 1, 0) == 0; 132} 133 134static void send_code(int8_t code) 135{ 136 send(the_socket, &code, 1, 0); 137} 138 139static void send_message(uint8_t *message, int length) 140{ 141 uint16_t bytes = htons(length); 142 send(the_socket, &bytes, 2, 0); 143 send(the_socket, message, length, 0); 144} 145 146/* Here is the file format. Values are encrypted by AES CBC, and MD5 is used to 147 * compute their checksums. To make the files portable, the length is stored in 148 * network order. Note that the first four bytes are reserved for future use and 149 * are always set to zero in this implementation. */ 150 151static int the_entropy = -1; 152 153static struct __attribute__((packed)) { 154 uint32_t reserved; 155 uint8_t vector[AES_BLOCK_SIZE]; 156 uint8_t encrypted[0]; 157 uint8_t digest[MD5_DIGEST_LENGTH]; 158 uint8_t digested[0]; 159 int32_t length; 160 uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE]; 161} blob; 162 163static int8_t encrypt_blob(char *name, AES_KEY *aes_key) 164{ 165 uint8_t vector[AES_BLOCK_SIZE]; 166 int length = blob.length; 167 int fd; 168 169 if (read(the_entropy, vector, AES_BLOCK_SIZE) != AES_BLOCK_SIZE) { 170 return SYSTEM_ERROR; 171 } 172 173 length += blob.value - blob.digested; 174 blob.length = htonl(blob.length); 175 MD5(blob.digested, length, blob.digest); 176 177 length += blob.digested - blob.encrypted; 178 length = (length + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE; 179 memcpy(vector, blob.vector, AES_BLOCK_SIZE); 180 AES_cbc_encrypt(blob.encrypted, blob.encrypted, length, aes_key, vector, 181 AES_ENCRYPT); 182 183 blob.reserved = 0; 184 length += blob.encrypted - (uint8_t *)&blob; 185 186 fd = open(".tmp", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR); 187 if (fd == -1 || write(fd, &blob, length) != length) { 188 return SYSTEM_ERROR; 189 } 190 close(fd); 191 return rename(".tmp", name) ? SYSTEM_ERROR : NO_ERROR; 192} 193 194static int8_t decrypt_blob(char *name, AES_KEY *aes_key) 195{ 196 int fd = open(name, O_RDONLY); 197 int length; 198 199 if (fd == -1) { 200 return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR; 201 } 202 length = read(fd, &blob, sizeof(blob)); 203 close(fd); 204 205 length -= blob.encrypted - (uint8_t *)&blob; 206 if (length < blob.value - blob.encrypted || length % AES_BLOCK_SIZE != 0) { 207 return VALUE_CORRUPTED; 208 } 209 210 AES_cbc_encrypt(blob.encrypted, blob.encrypted, length, aes_key, 211 blob.vector, AES_DECRYPT); 212 length -= blob.digested - blob.encrypted; 213 if (!memcmp(blob.digest, MD5(blob.digested, length, NULL), 214 MD5_DIGEST_LENGTH)) { 215 return VALUE_CORRUPTED; 216 } 217 218 length -= blob.value - blob.digested; 219 blob.length = ntohl(blob.length); 220 return (length < blob.length) ? VALUE_CORRUPTED : NO_ERROR; 221} 222 223/* Here are the actions. Each of them is a function without arguments. All 224 * information is defined in global variables, which are set properly before 225 * performing an action. The number of parameters required by each action is 226 * fixed and defined in a table. If the return value of an action is positive, 227 * it will be treated as a response code and transmitted to the client. Note 228 * that the lengths of parameters are checked when they are received, so 229 * boundary checks on parameters are omitted. */ 230 231#define MAX_PARAM 2 232#define MAX_RETRY 4 233 234static uid_t uid = -1; 235static int8_t state = UNINITIALIZED; 236static int8_t retry = MAX_RETRY; 237 238static struct { 239 int length; 240 uint8_t value[VALUE_SIZE]; 241} params[MAX_PARAM]; 242 243static AES_KEY encryption_key; 244static AES_KEY decryption_key; 245 246static int8_t test() 247{ 248 return state; 249} 250 251static int8_t get() 252{ 253 char name[NAME_MAX]; 254 int n = sprintf(name, "%u_", uid); 255 encode_key(&name[n], params[0].value, params[0].length); 256 n = decrypt_blob(name, &decryption_key); 257 if (n != NO_ERROR) { 258 return n; 259 } 260 send_code(NO_ERROR); 261 send_message(blob.value, blob.length); 262 return -NO_ERROR; 263} 264 265static int8_t insert() 266{ 267 char name[NAME_MAX]; 268 int n = sprintf(name, "%u_", uid); 269 encode_key(&name[n], params[0].value, params[0].length); 270 blob.length = params[1].length; 271 memcpy(blob.value, params[1].value, params[1].length); 272 return encrypt_blob(name, &encryption_key); 273} 274 275static int8_t delete() 276{ 277 char name[NAME_MAX]; 278 int n = sprintf(name, "%u_", uid); 279 encode_key(&name[n], params[0].value, params[0].length); 280 return (unlink(name) && errno != ENOENT) ? SYSTEM_ERROR : NO_ERROR; 281} 282 283static int8_t exist() 284{ 285 char name[NAME_MAX]; 286 int n = sprintf(name, "%u_", uid); 287 encode_key(&name[n], params[0].value, params[0].length); 288 if (access(name, R_OK) == -1) { 289 return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND; 290 } 291 return NO_ERROR; 292} 293 294static int8_t saw() 295{ 296 DIR *dir = opendir("."); 297 struct dirent *file; 298 char name[NAME_MAX]; 299 int n; 300 301 if (!dir) { 302 return SYSTEM_ERROR; 303 } 304 n = sprintf(name, "%u_", uid); 305 n += encode_key(&name[n], params[0].value, params[0].length); 306 send_code(NO_ERROR); 307 while ((file = readdir(dir)) != NULL) { 308 if (!strncmp(name, file->d_name, n)) { 309 char *p = &file->d_name[n]; 310 params[0].length = decode_key(params[0].value, p, strlen(p)); 311 send_message(params[0].value, params[0].length); 312 } 313 } 314 closedir(dir); 315 return -NO_ERROR; 316} 317 318static int8_t reset() 319{ 320 DIR *dir = opendir("."); 321 struct dirent *file; 322 323 memset(&encryption_key, 0, sizeof(encryption_key)); 324 memset(&decryption_key, 0, sizeof(decryption_key)); 325 state = UNINITIALIZED; 326 retry = MAX_RETRY; 327 328 if (!dir) { 329 return SYSTEM_ERROR; 330 } 331 while ((file = readdir(dir)) != NULL) { 332 unlink(file->d_name); 333 } 334 closedir(dir); 335 return NO_ERROR; 336} 337 338#define MASTER_KEY_FILE ".masterkey" 339#define MASTER_KEY_SIZE 16 340 341static void generate_key(uint8_t *key, uint8_t *password, int length) 342{ 343 PKCS5_PBKDF2_HMAC_SHA1((char *)password, length, (uint8_t *)"keystore", 344 sizeof("keystore"), 1024, MASTER_KEY_SIZE, key); 345} 346 347static int8_t password() 348{ 349 uint8_t key[MASTER_KEY_SIZE]; 350 AES_KEY aes_key; 351 int n; 352 353 if (state == UNINITIALIZED) { 354 blob.length = MASTER_KEY_SIZE; 355 if (read(the_entropy, blob.value, MASTER_KEY_SIZE) != MASTER_KEY_SIZE) { 356 return SYSTEM_ERROR; 357 } 358 } else { 359 generate_key(key, params[0].value, params[0].length); 360 AES_set_decrypt_key(key, MASTER_KEY_SIZE * 8, &aes_key); 361 n = decrypt_blob(MASTER_KEY_FILE, &aes_key); 362 if (n == SYSTEM_ERROR) { 363 return SYSTEM_ERROR; 364 } 365 if (n != NO_ERROR || blob.length != MASTER_KEY_SIZE) { 366 if (retry <= 0) { 367 reset(); 368 return UNINITIALIZED; 369 } 370 return WRONG_PASSWORD + --retry; 371 } 372 } 373 374 if (params[1].length == -1) { 375 memcpy(key, blob.value, MASTER_KEY_SIZE); 376 } else { 377 generate_key(key, params[1].value, params[1].length); 378 AES_set_encrypt_key(key, MASTER_KEY_SIZE * 8, &aes_key); 379 memcpy(key, blob.value, MASTER_KEY_SIZE); 380 n = encrypt_blob(MASTER_KEY_FILE, &aes_key); 381 } 382 383 if (n == NO_ERROR) { 384 AES_set_encrypt_key(key, MASTER_KEY_SIZE * 8, &encryption_key); 385 AES_set_decrypt_key(key, MASTER_KEY_SIZE * 8, &decryption_key); 386 state = NO_ERROR; 387 retry = MAX_RETRY; 388 } 389 return n; 390} 391 392static int8_t lock() 393{ 394 memset(&encryption_key, 0, sizeof(encryption_key)); 395 memset(&decryption_key, 0, sizeof(decryption_key)); 396 state = LOCKED; 397 return NO_ERROR; 398} 399 400static int8_t unlock() 401{ 402 params[1].length = -1; 403 return password(); 404} 405 406/* Here are the permissions, actions, users, and the main function. */ 407 408enum perm { 409 TEST = 1, 410 GET = 2, 411 INSERT = 4, 412 DELETE = 8, 413 EXIST = 16, 414 SAW = 32, 415 RESET = 64, 416 PASSWORD = 128, 417 LOCK = 256, 418 UNLOCK = 512, 419}; 420 421static struct action { 422 int8_t (*run)(); 423 int8_t code; 424 int8_t state; 425 uint32_t perm; 426 int lengths[MAX_PARAM]; 427} actions[] = { 428 {test, 't', 0, TEST, {0}}, 429 {get, 'g', NO_ERROR, GET, {KEY_SIZE}}, 430 {insert, 'i', NO_ERROR, INSERT, {KEY_SIZE, VALUE_SIZE}}, 431 {delete, 'd', 0, DELETE, {KEY_SIZE}}, 432 {exist, 'e', 0, EXIST, {KEY_SIZE}}, 433 {saw, 's', 0, SAW, {KEY_SIZE}}, 434 {reset, 'r', 0, RESET, {0}}, 435 {password, 'p', 0, PASSWORD, {PASSWORD_SIZE, PASSWORD_SIZE}}, 436 {lock, 'l', NO_ERROR, LOCK, {0}}, 437 {unlock, 'u', LOCKED, UNLOCK, {PASSWORD_SIZE}}, 438 {NULL, 0 , 0, 0, {0}}, 439}; 440 441static struct user { 442 uid_t uid; 443 uid_t euid; 444 uint32_t perms; 445} users[] = { 446 {AID_SYSTEM, 0, ~GET}, 447 {AID_VPN, AID_SYSTEM, GET}, 448 {AID_WIFI, AID_SYSTEM, GET}, 449 {0, 0, TEST | GET | INSERT | DELETE | EXIST | SAW}, 450}; 451 452static int8_t process(int8_t code) { 453 struct user *user = users; 454 struct action *action = actions; 455 int i; 456 457 while (user->uid && user->uid != uid) { 458 ++user; 459 } 460 while (action->code && action->code != code) { 461 ++action; 462 } 463 if (!action->code) { 464 return UNDEFINED_ACTION; 465 } 466 if (!(action->perm & user->perms)) { 467 return PERMISSION_DENIED; 468 } 469 if (action->state && action->state != state) { 470 return state; 471 } 472 if (user->euid) { 473 uid = user->euid; 474 } 475 for (i = 0; i < MAX_PARAM && action->lengths[i]; ++i) { 476 params[i].length = recv_message(params[i].value, action->lengths[i]); 477 if (params[i].length == -1) { 478 return PROTOCOL_ERROR; 479 } 480 } 481 if (!recv_end_of_file()) { 482 return PROTOCOL_ERROR; 483 } 484 return action->run(); 485} 486 487#define RANDOM_DEVICE "/dev/urandom" 488 489int main(int argc, char **argv) 490{ 491 int control_socket = android_get_control_socket("keystore"); 492 if (argc < 2) { 493 LOGE("A directory must be specified!"); 494 return 1; 495 } 496 if (chdir(argv[1]) == -1) { 497 LOGE("chdir: %s: %s", argv[1], strerror(errno)); 498 return 1; 499 } 500 if ((the_entropy = open(RANDOM_DEVICE, O_RDONLY)) == -1) { 501 LOGE("open: %s: %s", RANDOM_DEVICE, strerror(errno)); 502 return 1; 503 } 504 if (listen(control_socket, 3) == -1) { 505 LOGE("listen: %s", strerror(errno)); 506 return 1; 507 } 508 509 signal(SIGPIPE, SIG_IGN); 510 if (access(MASTER_KEY_FILE, R_OK) == 0) { 511 state = LOCKED; 512 } 513 514 while ((the_socket = accept(control_socket, NULL, 0)) != -1) { 515 struct timeval tv = {.tv_sec = 3}; 516 struct ucred cred; 517 socklen_t size = sizeof(cred); 518 int8_t request; 519 520 setsockopt(the_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); 521 setsockopt(the_socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); 522 523 if (getsockopt(the_socket, SOL_SOCKET, SO_PEERCRED, &cred, &size)) { 524 LOGW("getsockopt: %s", strerror(errno)); 525 } else if (recv_code(&request)) { 526 int8_t old_state = state; 527 int8_t response; 528 uid = cred.uid; 529 530 if ((response = process(request)) > 0) { 531 send_code(response); 532 response = -response; 533 } 534 535 LOGI("uid: %d action: %c -> %d state: %d -> %d retry: %d", 536 cred.uid, request, -response, old_state, state, retry); 537 } 538 close(the_socket); 539 } 540 LOGE("accept: %s", strerror(errno)); 541 return 1; 542} 543