Home | History | Annotate | Download | only in keystore
      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        ((NAME_MAX - 15) / 2)
     50 #define VALUE_SIZE      32768
     51 #define PASSWORD_SIZE   VALUE_SIZE
     52 
     53 struct Value {
     54     int length;
     55     uint8_t value[VALUE_SIZE];
     56 };
     57 
     58 /* Here is the encoding of keys. This is necessary in order to allow arbitrary
     59  * characters in keys. Characters in [0-~] are not encoded. Others are encoded
     60  * into two bytes. The first byte is one of [+-.] which represents the first
     61  * two bits of the character. The second byte encodes the rest of the bits into
     62  * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
     63  * that Base64 cannot be used here due to the need of prefix match on keys. */
     64 
     65 static int encode_key(char* out, uid_t uid, const Value* key) {
     66     int n = snprintf(out, NAME_MAX, "%u_", uid);
     67     out += n;
     68     const uint8_t* in = key->value;
     69     int length = key->length;
     70     for (int i = length; i > 0; --i, ++in, ++out) {
     71         if (*in >= '0' && *in <= '~') {
     72             *out = *in;
     73         } else {
     74             *out = '+' + (*in >> 6);
     75             *++out = '0' + (*in & 0x3F);
     76             ++length;
     77         }
     78     }
     79     *out = '\0';
     80     return n + length;
     81 }
     82 
     83 static int decode_key(uint8_t* out, char* in, int length) {
     84     for (int i = 0; i < length; ++i, ++in, ++out) {
     85         if (*in >= '0' && *in <= '~') {
     86             *out = *in;
     87         } else {
     88             *out = (*in - '+') << 6;
     89             *out |= (*++in - '0') & 0x3F;
     90             --length;
     91         }
     92     }
     93     *out = '\0';
     94     return length;
     95 }
     96 
     97 static size_t readFully(int fd, uint8_t* data, size_t size) {
     98     size_t remaining = size;
     99     while (remaining > 0) {
    100         ssize_t n = TEMP_FAILURE_RETRY(read(fd, data, size));
    101         if (n == -1 || n == 0) {
    102             return size-remaining;
    103         }
    104         data += n;
    105         remaining -= n;
    106     }
    107     return size;
    108 }
    109 
    110 static size_t writeFully(int fd, uint8_t* data, size_t size) {
    111     size_t remaining = size;
    112     while (remaining > 0) {
    113         ssize_t n = TEMP_FAILURE_RETRY(write(fd, data, size));
    114         if (n == -1 || n == 0) {
    115             return size-remaining;
    116         }
    117         data += n;
    118         remaining -= n;
    119     }
    120     return size;
    121 }
    122 
    123 class Entropy {
    124 public:
    125     Entropy() : mRandom(-1) {}
    126     ~Entropy() {
    127         if (mRandom != -1) {
    128             close(mRandom);
    129         }
    130     }
    131 
    132     bool open() {
    133         const char* randomDevice = "/dev/urandom";
    134         mRandom = ::open(randomDevice, O_RDONLY);
    135         if (mRandom == -1) {
    136             LOGE("open: %s: %s", randomDevice, strerror(errno));
    137             return false;
    138         }
    139         return true;
    140     }
    141 
    142     bool generate_random_data(uint8_t* data, size_t size) {
    143         return (readFully(mRandom, data, size) == size);
    144     }
    145 
    146 private:
    147     int mRandom;
    148 };
    149 
    150 /* Here is the file format. There are two parts in blob.value, the secret and
    151  * the description. The secret is stored in ciphertext, and its original size
    152  * can be found in blob.length. The description is stored after the secret in
    153  * plaintext, and its size is specified in blob.info. The total size of the two
    154  * parts must be no more than VALUE_SIZE bytes. The first three bytes of the
    155  * file are reserved for future use and are always set to zero. Fields other
    156  * than blob.info, blob.length, and blob.value are modified by encryptBlob()
    157  * and decryptBlob(). Thus they should not be accessed from outside. */
    158 
    159 struct __attribute__((packed)) blob {
    160     uint8_t reserved[3];
    161     uint8_t info;
    162     uint8_t vector[AES_BLOCK_SIZE];
    163     uint8_t encrypted[0];
    164     uint8_t digest[MD5_DIGEST_LENGTH];
    165     uint8_t digested[0];
    166     int32_t length; // in network byte order when encrypted
    167     uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
    168 };
    169 
    170 class Blob {
    171 public:
    172     Blob(uint8_t* value, int32_t valueLength, uint8_t* info, uint8_t infoLength) {
    173         mBlob.length = valueLength;
    174         memcpy(mBlob.value, value, valueLength);
    175 
    176         mBlob.info = infoLength;
    177         memcpy(mBlob.value + valueLength, info, infoLength);
    178     }
    179 
    180     Blob(blob b) {
    181         mBlob = b;
    182     }
    183 
    184     Blob() {}
    185 
    186     uint8_t* getValue() {
    187         return mBlob.value;
    188     }
    189 
    190     int32_t getLength() {
    191         return mBlob.length;
    192     }
    193 
    194     uint8_t getInfo() {
    195         return mBlob.info;
    196     }
    197 
    198     ResponseCode encryptBlob(const char* filename, AES_KEY *aes_key, Entropy* entropy) {
    199         if (!entropy->generate_random_data(mBlob.vector, AES_BLOCK_SIZE)) {
    200             return SYSTEM_ERROR;
    201         }
    202 
    203         // data includes the value and the value's length
    204         size_t dataLength = mBlob.length + sizeof(mBlob.length);
    205         // pad data to the AES_BLOCK_SIZE
    206         size_t digestedLength = ((dataLength + AES_BLOCK_SIZE - 1)
    207                                  / AES_BLOCK_SIZE * AES_BLOCK_SIZE);
    208         // encrypted data includes the digest value
    209         size_t encryptedLength = digestedLength + MD5_DIGEST_LENGTH;
    210         // move info after space for padding
    211         memmove(&mBlob.encrypted[encryptedLength], &mBlob.value[mBlob.length], mBlob.info);
    212         // zero padding area
    213         memset(mBlob.value + mBlob.length, 0, digestedLength - dataLength);
    214 
    215         mBlob.length = htonl(mBlob.length);
    216         MD5(mBlob.digested, digestedLength, mBlob.digest);
    217 
    218         uint8_t vector[AES_BLOCK_SIZE];
    219         memcpy(vector, mBlob.vector, AES_BLOCK_SIZE);
    220         AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength,
    221                         aes_key, vector, AES_ENCRYPT);
    222 
    223         memset(mBlob.reserved, 0, sizeof(mBlob.reserved));
    224         size_t headerLength = (mBlob.encrypted - (uint8_t*) &mBlob);
    225         size_t fileLength = encryptedLength + headerLength + mBlob.info;
    226 
    227         const char* tmpFileName = ".tmp";
    228         int out = open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
    229         if (out == -1) {
    230             return SYSTEM_ERROR;
    231         }
    232         size_t writtenBytes = writeFully(out, (uint8_t*) &mBlob, fileLength);
    233         if (close(out) != 0) {
    234             return SYSTEM_ERROR;
    235         }
    236         if (writtenBytes != fileLength) {
    237             unlink(tmpFileName);
    238             return SYSTEM_ERROR;
    239         }
    240         return (rename(tmpFileName, filename) == 0) ? NO_ERROR : SYSTEM_ERROR;
    241     }
    242 
    243     ResponseCode decryptBlob(const char* filename, AES_KEY *aes_key) {
    244         int in = open(filename, O_RDONLY);
    245         if (in == -1) {
    246             return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
    247         }
    248         // fileLength may be less than sizeof(mBlob) since the in
    249         // memory version has extra padding to tolerate rounding up to
    250         // the AES_BLOCK_SIZE
    251         size_t fileLength = readFully(in, (uint8_t*) &mBlob, sizeof(mBlob));
    252         if (close(in) != 0) {
    253             return SYSTEM_ERROR;
    254         }
    255         size_t headerLength = (mBlob.encrypted - (uint8_t*) &mBlob);
    256         if (fileLength < headerLength) {
    257             return VALUE_CORRUPTED;
    258         }
    259 
    260         ssize_t encryptedLength = fileLength - (headerLength + mBlob.info);
    261         if (encryptedLength < 0 || encryptedLength % AES_BLOCK_SIZE != 0) {
    262             return VALUE_CORRUPTED;
    263         }
    264         AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key,
    265                         mBlob.vector, AES_DECRYPT);
    266         size_t digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
    267         uint8_t computedDigest[MD5_DIGEST_LENGTH];
    268         MD5(mBlob.digested, digestedLength, computedDigest);
    269         if (memcmp(mBlob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
    270             return VALUE_CORRUPTED;
    271         }
    272 
    273         ssize_t maxValueLength = digestedLength - sizeof(mBlob.length);
    274         mBlob.length = ntohl(mBlob.length);
    275         if (mBlob.length < 0 || mBlob.length > maxValueLength) {
    276             return VALUE_CORRUPTED;
    277         }
    278         if (mBlob.info != 0) {
    279             // move info from after padding to after data
    280             memmove(&mBlob.value[mBlob.length], &mBlob.value[maxValueLength], mBlob.info);
    281         }
    282         return NO_ERROR;
    283     }
    284 
    285 private:
    286     struct blob mBlob;
    287 };
    288 
    289 class KeyStore {
    290 public:
    291     KeyStore(Entropy* entropy) : mEntropy(entropy), mRetry(MAX_RETRY) {
    292         if (access(MASTER_KEY_FILE, R_OK) == 0) {
    293             setState(STATE_LOCKED);
    294         } else {
    295             setState(STATE_UNINITIALIZED);
    296         }
    297     }
    298 
    299     State getState() {
    300         return mState;
    301     }
    302 
    303     int8_t getRetry() {
    304         return mRetry;
    305     }
    306 
    307     ResponseCode initialize(Value* pw) {
    308         if (!generateMasterKey()) {
    309             return SYSTEM_ERROR;
    310         }
    311         ResponseCode response = writeMasterKey(pw);
    312         if (response != NO_ERROR) {
    313             return response;
    314         }
    315         setupMasterKeys();
    316         return NO_ERROR;
    317     }
    318 
    319     ResponseCode writeMasterKey(Value* pw) {
    320         uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
    321         generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
    322         AES_KEY passwordAesKey;
    323         AES_set_encrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
    324         Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt));
    325         return masterKeyBlob.encryptBlob(MASTER_KEY_FILE, &passwordAesKey, mEntropy);
    326     }
    327 
    328     ResponseCode readMasterKey(Value* pw) {
    329         int in = open(MASTER_KEY_FILE, O_RDONLY);
    330         if (in == -1) {
    331             return SYSTEM_ERROR;
    332         }
    333 
    334         // we read the raw blob to just to get the salt to generate
    335         // the AES key, then we create the Blob to use with decryptBlob
    336         blob rawBlob;
    337         size_t length = readFully(in, (uint8_t*) &rawBlob, sizeof(rawBlob));
    338         if (close(in) != 0) {
    339             return SYSTEM_ERROR;
    340         }
    341         // find salt at EOF if present, otherwise we have an old file
    342         uint8_t* salt;
    343         if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
    344             salt = (uint8_t*) &rawBlob + length - SALT_SIZE;
    345         } else {
    346             salt = NULL;
    347         }
    348         uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
    349         generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
    350         AES_KEY passwordAesKey;
    351         AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
    352         Blob masterKeyBlob(rawBlob);
    353         ResponseCode response = masterKeyBlob.decryptBlob(MASTER_KEY_FILE, &passwordAesKey);
    354         if (response == SYSTEM_ERROR) {
    355             return SYSTEM_ERROR;
    356         }
    357         if (response == NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
    358             // if salt was missing, generate one and write a new master key file with the salt.
    359             if (salt == NULL) {
    360                 if (!generateSalt()) {
    361                     return SYSTEM_ERROR;
    362                 }
    363                 response = writeMasterKey(pw);
    364             }
    365             if (response == NO_ERROR) {
    366                 memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
    367                 setupMasterKeys();
    368             }
    369             return response;
    370         }
    371         if (mRetry <= 0) {
    372             reset();
    373             return UNINITIALIZED;
    374         }
    375         --mRetry;
    376         switch (mRetry) {
    377             case 0: return WRONG_PASSWORD_0;
    378             case 1: return WRONG_PASSWORD_1;
    379             case 2: return WRONG_PASSWORD_2;
    380             case 3: return WRONG_PASSWORD_3;
    381             default: return WRONG_PASSWORD_3;
    382         }
    383     }
    384 
    385     bool reset() {
    386         clearMasterKeys();
    387         setState(STATE_UNINITIALIZED);
    388 
    389         DIR* dir = opendir(".");
    390         struct dirent* file;
    391 
    392         if (!dir) {
    393             return false;
    394         }
    395         while ((file = readdir(dir)) != NULL) {
    396             unlink(file->d_name);
    397         }
    398         closedir(dir);
    399         return true;
    400     }
    401 
    402     bool isEmpty() {
    403         DIR* dir = opendir(".");
    404         struct dirent* file;
    405         if (!dir) {
    406             return true;
    407         }
    408         bool result = true;
    409         while ((file = readdir(dir)) != NULL) {
    410             if (isKeyFile(file->d_name)) {
    411                 result = false;
    412                 break;
    413             }
    414         }
    415         closedir(dir);
    416         return result;
    417     }
    418 
    419     void lock() {
    420         clearMasterKeys();
    421         setState(STATE_LOCKED);
    422     }
    423 
    424     ResponseCode get(const char* filename, Blob* keyBlob) {
    425         return keyBlob->decryptBlob(filename, &mMasterKeyDecryption);
    426     }
    427 
    428     ResponseCode put(const char* filename, Blob* keyBlob) {
    429         return keyBlob->encryptBlob(filename, &mMasterKeyEncryption, mEntropy);
    430     }
    431 
    432 private:
    433     static const char* MASTER_KEY_FILE;
    434     static const int MASTER_KEY_SIZE_BYTES = 16;
    435     static const int MASTER_KEY_SIZE_BITS = MASTER_KEY_SIZE_BYTES * 8;
    436 
    437     static const int MAX_RETRY = 4;
    438     static const size_t SALT_SIZE = 16;
    439 
    440     Entropy* mEntropy;
    441 
    442     State mState;
    443     int8_t mRetry;
    444 
    445     uint8_t mMasterKey[MASTER_KEY_SIZE_BYTES];
    446     uint8_t mSalt[SALT_SIZE];
    447 
    448     AES_KEY mMasterKeyEncryption;
    449     AES_KEY mMasterKeyDecryption;
    450 
    451     void setState(State state) {
    452         mState = state;
    453         if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
    454             mRetry = MAX_RETRY;
    455         }
    456     }
    457 
    458     bool generateSalt() {
    459         return mEntropy->generate_random_data(mSalt, sizeof(mSalt));
    460     }
    461 
    462     bool generateMasterKey() {
    463         if (!mEntropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
    464             return false;
    465         }
    466         if (!generateSalt()) {
    467             return false;
    468         }
    469         return true;
    470     }
    471 
    472     void setupMasterKeys() {
    473         AES_set_encrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyEncryption);
    474         AES_set_decrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyDecryption);
    475         setState(STATE_NO_ERROR);
    476     }
    477 
    478     void clearMasterKeys() {
    479         memset(mMasterKey, 0, sizeof(mMasterKey));
    480         memset(mSalt, 0, sizeof(mSalt));
    481         memset(&mMasterKeyEncryption, 0, sizeof(mMasterKeyEncryption));
    482         memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption));
    483     }
    484 
    485     static void generateKeyFromPassword(uint8_t* key, ssize_t keySize, Value* pw, uint8_t* salt) {
    486         size_t saltSize;
    487         if (salt != NULL) {
    488             saltSize = SALT_SIZE;
    489         } else {
    490             // pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
    491             salt = (uint8_t*) "keystore";
    492             // sizeof = 9, not strlen = 8
    493             saltSize = sizeof("keystore");
    494         }
    495         PKCS5_PBKDF2_HMAC_SHA1((char*) pw->value, pw->length, salt, saltSize, 8192, keySize, key);
    496     }
    497 
    498     static bool isKeyFile(const char* filename) {
    499         return ((strcmp(filename, MASTER_KEY_FILE) != 0)
    500                 && (strcmp(filename, ".") != 0)
    501                 && (strcmp(filename, "..") != 0));
    502     }
    503 };
    504 
    505 const char* KeyStore::MASTER_KEY_FILE = ".masterkey";
    506 
    507 /* Here is the protocol used in both requests and responses:
    508  *     code [length_1 message_1 ... length_n message_n] end-of-file
    509  * where code is one byte long and lengths are unsigned 16-bit integers in
    510  * network order. Thus the maximum length of a message is 65535 bytes. */
    511 
    512 static int recv_code(int sock, int8_t* code) {
    513     return recv(sock, code, 1, 0) == 1;
    514 }
    515 
    516 static int recv_message(int sock, uint8_t* message, int length) {
    517     uint8_t bytes[2];
    518     if (recv(sock, &bytes[0], 1, 0) != 1 ||
    519         recv(sock, &bytes[1], 1, 0) != 1) {
    520         return -1;
    521     } else {
    522         int offset = bytes[0] << 8 | bytes[1];
    523         if (length < offset) {
    524             return -1;
    525         }
    526         length = offset;
    527         offset = 0;
    528         while (offset < length) {
    529             int n = recv(sock, &message[offset], length - offset, 0);
    530             if (n <= 0) {
    531                 return -1;
    532             }
    533             offset += n;
    534         }
    535     }
    536     return length;
    537 }
    538 
    539 static int recv_end_of_file(int sock) {
    540     uint8_t byte;
    541     return recv(sock, &byte, 1, 0) == 0;
    542 }
    543 
    544 static void send_code(int sock, int8_t code) {
    545     send(sock, &code, 1, 0);
    546 }
    547 
    548 static void send_message(int sock, uint8_t* message, int length) {
    549     uint16_t bytes = htons(length);
    550     send(sock, &bytes, 2, 0);
    551     send(sock, message, length, 0);
    552 }
    553 
    554 /* Here are the actions. Each of them is a function without arguments. All
    555  * information is defined in global variables, which are set properly before
    556  * performing an action. The number of parameters required by each action is
    557  * fixed and defined in a table. If the return value of an action is positive,
    558  * it will be treated as a response code and transmitted to the client. Note
    559  * that the lengths of parameters are checked when they are received, so
    560  * boundary checks on parameters are omitted. */
    561 
    562 static const ResponseCode NO_ERROR_RESPONSE_CODE_SENT = (ResponseCode) 0;
    563 
    564 static ResponseCode test(KeyStore* keyStore, int sock, uid_t uid, Value*, Value*) {
    565     return (ResponseCode) keyStore->getState();
    566 }
    567 
    568 static ResponseCode get(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value*) {
    569     char filename[NAME_MAX];
    570     encode_key(filename, uid, keyName);
    571     Blob keyBlob;
    572     ResponseCode responseCode = keyStore->get(filename, &keyBlob);
    573     if (responseCode != NO_ERROR) {
    574         return responseCode;
    575     }
    576     send_code(sock, NO_ERROR);
    577     send_message(sock, keyBlob.getValue(), keyBlob.getLength());
    578     return NO_ERROR_RESPONSE_CODE_SENT;
    579 }
    580 
    581 static ResponseCode insert(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value* val) {
    582     char filename[NAME_MAX];
    583     encode_key(filename, uid, keyName);
    584     Blob keyBlob(val->value, val->length, 0, NULL);
    585     return keyStore->put(filename, &keyBlob);
    586 }
    587 
    588 static ResponseCode del(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value*) {
    589     char filename[NAME_MAX];
    590     encode_key(filename, uid, keyName);
    591     return (unlink(filename) && errno != ENOENT) ? SYSTEM_ERROR : NO_ERROR;
    592 }
    593 
    594 static ResponseCode exist(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value*) {
    595     char filename[NAME_MAX];
    596     encode_key(filename, uid, keyName);
    597     if (access(filename, R_OK) == -1) {
    598         return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND;
    599     }
    600     return NO_ERROR;
    601 }
    602 
    603 static ResponseCode saw(KeyStore* keyStore, int sock, uid_t uid, Value* keyPrefix, Value*) {
    604     DIR* dir = opendir(".");
    605     if (!dir) {
    606         return SYSTEM_ERROR;
    607     }
    608     char filename[NAME_MAX];
    609     int n = encode_key(filename, uid, keyPrefix);
    610     send_code(sock, NO_ERROR);
    611 
    612     struct dirent* file;
    613     while ((file = readdir(dir)) != NULL) {
    614         if (!strncmp(filename, file->d_name, n)) {
    615             char* p = &file->d_name[n];
    616             keyPrefix->length = decode_key(keyPrefix->value, p, strlen(p));
    617             send_message(sock, keyPrefix->value, keyPrefix->length);
    618         }
    619     }
    620     closedir(dir);
    621     return NO_ERROR_RESPONSE_CODE_SENT;
    622 }
    623 
    624 static ResponseCode reset(KeyStore* keyStore, int sock, uid_t uid, Value*, Value*) {
    625     return keyStore->reset() ? NO_ERROR : SYSTEM_ERROR;
    626 }
    627 
    628 /* Here is the history. To improve the security, the parameters to generate the
    629  * master key has been changed. To make a seamless transition, we update the
    630  * file using the same password when the user unlock it for the first time. If
    631  * any thing goes wrong during the transition, the new file will not overwrite
    632  * the old one. This avoids permanent damages of the existing data. */
    633 
    634 static ResponseCode password(KeyStore* keyStore, int sock, uid_t uid, Value* pw, Value*) {
    635     switch (keyStore->getState()) {
    636         case STATE_UNINITIALIZED: {
    637             // generate master key, encrypt with password, write to file, initialize mMasterKey*.
    638             return keyStore->initialize(pw);
    639         }
    640         case STATE_NO_ERROR: {
    641             // rewrite master key with new password.
    642             return keyStore->writeMasterKey(pw);
    643         }
    644         case STATE_LOCKED: {
    645             // read master key, decrypt with password, initialize mMasterKey*.
    646             return keyStore->readMasterKey(pw);
    647         }
    648     }
    649     return SYSTEM_ERROR;
    650 }
    651 
    652 static ResponseCode lock(KeyStore* keyStore, int sock, uid_t uid, Value*, Value*) {
    653     keyStore->lock();
    654     return NO_ERROR;
    655 }
    656 
    657 static ResponseCode unlock(KeyStore* keyStore, int sock, uid_t uid, Value* pw, Value* unused) {
    658     return password(keyStore, sock, uid, pw, unused);
    659 }
    660 
    661 static ResponseCode zero(KeyStore* keyStore, int sock, uid_t uid, Value*, Value*) {
    662     return keyStore->isEmpty() ? KEY_NOT_FOUND : NO_ERROR;
    663 }
    664 
    665 /* Here are the permissions, actions, users, and the main function. */
    666 
    667 enum perm {
    668     TEST     =    1,
    669     GET      =    2,
    670     INSERT   =    4,
    671     DELETE   =    8,
    672     EXIST    =   16,
    673     SAW      =   32,
    674     RESET    =   64,
    675     PASSWORD =  128,
    676     LOCK     =  256,
    677     UNLOCK   =  512,
    678     ZERO     = 1024,
    679 };
    680 
    681 static const int MAX_PARAM = 2;
    682 
    683 static const State STATE_ANY = (State) 0;
    684 
    685 static struct action {
    686     ResponseCode (*run)(KeyStore* keyStore, int sock, uid_t uid, Value* param1, Value* param2);
    687     int8_t code;
    688     State state;
    689     uint32_t perm;
    690     int lengths[MAX_PARAM];
    691 } actions[] = {
    692     {test,     't', STATE_ANY,      TEST,     {0, 0}},
    693     {get,      'g', STATE_NO_ERROR, GET,      {KEY_SIZE, 0}},
    694     {insert,   'i', STATE_NO_ERROR, INSERT,   {KEY_SIZE, VALUE_SIZE}},
    695     {del,      'd', STATE_ANY,      DELETE,   {KEY_SIZE, 0}},
    696     {exist,    'e', STATE_ANY,      EXIST,    {KEY_SIZE, 0}},
    697     {saw,      's', STATE_ANY,      SAW,      {KEY_SIZE, 0}},
    698     {reset,    'r', STATE_ANY,      RESET,    {0, 0}},
    699     {password, 'p', STATE_ANY,      PASSWORD, {PASSWORD_SIZE, 0}},
    700     {lock,     'l', STATE_NO_ERROR, LOCK,     {0, 0}},
    701     {unlock,   'u', STATE_LOCKED,   UNLOCK,   {PASSWORD_SIZE, 0}},
    702     {zero,     'z', STATE_ANY,      ZERO,     {0, 0}},
    703     {NULL,      0 , STATE_ANY,      0,        {0, 0}},
    704 };
    705 
    706 static struct user {
    707     uid_t uid;
    708     uid_t euid;
    709     uint32_t perms;
    710 } users[] = {
    711     {AID_SYSTEM,   ~0,         ~0},
    712     {AID_VPN,      AID_SYSTEM, GET},
    713     {AID_WIFI,     AID_SYSTEM, GET},
    714     {AID_ROOT,     AID_SYSTEM, GET},
    715     {~0,           ~0,         TEST | GET | INSERT | DELETE | EXIST | SAW},
    716 };
    717 
    718 static ResponseCode process(KeyStore* keyStore, int sock, uid_t uid, int8_t code) {
    719     struct user* user = users;
    720     struct action* action = actions;
    721     int i;
    722 
    723     while (~user->uid && user->uid != uid) {
    724         ++user;
    725     }
    726     while (action->code && action->code != code) {
    727         ++action;
    728     }
    729     if (!action->code) {
    730         return UNDEFINED_ACTION;
    731     }
    732     if (!(action->perm & user->perms)) {
    733         return PERMISSION_DENIED;
    734     }
    735     if (action->state != STATE_ANY && action->state != keyStore->getState()) {
    736         return (ResponseCode) keyStore->getState();
    737     }
    738     if (~user->euid) {
    739         uid = user->euid;
    740     }
    741     Value params[MAX_PARAM];
    742     for (i = 0; i < MAX_PARAM && action->lengths[i] != 0; ++i) {
    743         params[i].length = recv_message(sock, params[i].value, action->lengths[i]);
    744         if (params[i].length < 0) {
    745             return PROTOCOL_ERROR;
    746         }
    747     }
    748     if (!recv_end_of_file(sock)) {
    749         return PROTOCOL_ERROR;
    750     }
    751     return action->run(keyStore, sock, uid, &params[0], &params[1]);
    752 }
    753 
    754 int main(int argc, char* argv[]) {
    755     int controlSocket = android_get_control_socket("keystore");
    756     if (argc < 2) {
    757         LOGE("A directory must be specified!");
    758         return 1;
    759     }
    760     if (chdir(argv[1]) == -1) {
    761         LOGE("chdir: %s: %s", argv[1], strerror(errno));
    762         return 1;
    763     }
    764 
    765     Entropy entropy;
    766     if (!entropy.open()) {
    767         return 1;
    768     }
    769     if (listen(controlSocket, 3) == -1) {
    770         LOGE("listen: %s", strerror(errno));
    771         return 1;
    772     }
    773 
    774     signal(SIGPIPE, SIG_IGN);
    775 
    776     KeyStore keyStore(&entropy);
    777     int sock;
    778     while ((sock = accept(controlSocket, NULL, 0)) != -1) {
    779         struct timeval tv;
    780         tv.tv_sec = 3;
    781         setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    782         setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
    783 
    784         struct ucred cred;
    785         socklen_t size = sizeof(cred);
    786         int credResult = getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cred, &size);
    787         if (credResult != 0) {
    788             LOGW("getsockopt: %s", strerror(errno));
    789         } else {
    790             int8_t request;
    791             if (recv_code(sock, &request)) {
    792                 State old_state = keyStore.getState();
    793                 ResponseCode response = process(&keyStore, sock, cred.uid, request);
    794                 if (response == NO_ERROR_RESPONSE_CODE_SENT) {
    795                     response = NO_ERROR;
    796                 } else {
    797                     send_code(sock, response);
    798                 }
    799                 LOGI("uid: %d action: %c -> %d state: %d -> %d retry: %d",
    800                      cred.uid,
    801                      request, response,
    802                      old_state, keyStore.getState(),
    803                      keyStore.getRetry());
    804             }
    805         }
    806         close(sock);
    807     }
    808     LOGE("accept: %s", strerror(errno));
    809     return 1;
    810 }
    811