keystore.cpp revision 5187818895c4c5f650a611c40531b1dff7764c18
1a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root/*
2a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * Copyright (C) 2009 The Android Open Source Project
3a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root *
4a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * you may not use this file except in compliance with the License.
6a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * You may obtain a copy of the License at
7a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root *
8a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root *
10a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * Unless required by applicable law or agreed to in writing, software
11a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * See the License for the specific language governing permissions and
14a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * limitations under the License.
15a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root */
16a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
17a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <stdio.h>
18a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <stdint.h>
19a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <string.h>
20a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <unistd.h>
21a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <signal.h>
22a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <errno.h>
23a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <dirent.h>
24a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <fcntl.h>
25a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <limits.h>
26a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <sys/types.h>
27a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <sys/socket.h>
28a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <sys/stat.h>
29a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <sys/time.h>
30a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <arpa/inet.h>
31a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
32a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <openssl/aes.h>
33a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <openssl/evp.h>
34a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <openssl/md5.h>
35a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
36a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#define LOG_TAG "keystore"
37a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <cutils/log.h>
38a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <cutils/sockets.h>
39a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include <private/android_filesystem_config.h>
40a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
41a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#include "keystore.h"
42a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
43a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root/* KeyStore is a secured storage for key-value pairs. In this implementation,
44a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * each file stores one key-value pair. Keys are encoded in file names, and
45a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * values are encrypted with checksums. The encryption key is protected by a
46a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * user-defined password. To keep things simple, buffers are always larger than
47a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * the maximum space we needed, so boundary checks on buffers are omitted. */
48a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
49a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#define KEY_SIZE        ((NAME_MAX - 15) / 2)
50a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#define VALUE_SIZE      32768
51a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root#define PASSWORD_SIZE   VALUE_SIZE
52a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
53a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstruct Value {
54a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int length;
55a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t value[VALUE_SIZE];
56a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root};
57a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
58a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root/* Here is the encoding of keys. This is necessary in order to allow arbitrary
59a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * characters in keys. Characters in [0-~] are not encoded. Others are encoded
60a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * into two bytes. The first byte is one of [+-.] which represents the first
61a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * two bits of the character. The second byte encodes the rest of the bits into
62a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
63a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * that Base64 cannot be used here due to the need of prefix match on keys. */
64a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
65a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic int encode_key(char* out, uid_t uid, const Value* key) {
66a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int n = snprintf(out, NAME_MAX, "%u_", uid);
67a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    out += n;
68a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    const uint8_t* in = key->value;
69a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int length = key->length;
70a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    for (int i = length; i > 0; --i, ++in, ++out) {
71a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (*in >= '0' && *in <= '~') {
72a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            *out = *in;
73a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        } else {
74a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            *out = '+' + (*in >> 6);
75a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            *++out = '0' + (*in & 0x3F);
76a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            ++length;
77a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
78a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
79a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    *out = '\0';
80a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return n + length;
81a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
82a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
835187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic int decode_key(uint8_t* out, const char* in, int length) {
84a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    for (int i = 0; i < length; ++i, ++in, ++out) {
85a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (*in >= '0' && *in <= '~') {
86a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            *out = *in;
87a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        } else {
88a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            *out = (*in - '+') << 6;
89a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            *out |= (*++in - '0') & 0x3F;
90a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            --length;
91a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
92a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
93a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    *out = '\0';
94a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return length;
95a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
96a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
97a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic size_t readFully(int fd, uint8_t* data, size_t size) {
98a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    size_t remaining = size;
99a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    while (remaining > 0) {
100a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ssize_t n = TEMP_FAILURE_RETRY(read(fd, data, size));
101a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (n == -1 || n == 0) {
102a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return size-remaining;
103a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
104a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        data += n;
105a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        remaining -= n;
106a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
107a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return size;
108a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
109a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
110a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic size_t writeFully(int fd, uint8_t* data, size_t size) {
111a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    size_t remaining = size;
112a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    while (remaining > 0) {
113a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ssize_t n = TEMP_FAILURE_RETRY(write(fd, data, size));
114a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (n == -1 || n == 0) {
115a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return size-remaining;
116a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
117a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        data += n;
118a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        remaining -= n;
119a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
120a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return size;
121a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
122a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
123a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootclass Entropy {
124a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootpublic:
125a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    Entropy() : mRandom(-1) {}
126a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    ~Entropy() {
127a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (mRandom != -1) {
128a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            close(mRandom);
129a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
130a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
131a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
132a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    bool open() {
133a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        const char* randomDevice = "/dev/urandom";
134a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        mRandom = ::open(randomDevice, O_RDONLY);
135a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (mRandom == -1) {
136a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            ALOGE("open: %s: %s", randomDevice, strerror(errno));
137a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return false;
138a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
139a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return true;
140a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
141a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
1425187818895c4c5f650a611c40531b1dff7764c18Kenny Root    bool generate_random_data(uint8_t* data, size_t size) const {
143a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return (readFully(mRandom, data, size) == size);
144a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
145a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
146a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootprivate:
147a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int mRandom;
148a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root};
149a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
150a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root/* Here is the file format. There are two parts in blob.value, the secret and
151a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * the description. The secret is stored in ciphertext, and its original size
152a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * can be found in blob.length. The description is stored after the secret in
153a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * plaintext, and its size is specified in blob.info. The total size of the two
154a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * parts must be no more than VALUE_SIZE bytes. The first three bytes of the
155a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * file are reserved for future use and are always set to zero. Fields other
156a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * than blob.info, blob.length, and blob.value are modified by encryptBlob()
157a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * and decryptBlob(). Thus they should not be accessed from outside. */
158a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
159a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstruct __attribute__((packed)) blob {
160a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t reserved[3];
161a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t info;
162a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t vector[AES_BLOCK_SIZE];
163a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t encrypted[0];
164a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t digest[MD5_DIGEST_LENGTH];
165a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t digested[0];
166a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int32_t length; // in network byte order when encrypted
167a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
168a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root};
169a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
170a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootclass Blob {
171a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootpublic:
172a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    Blob(uint8_t* value, int32_t valueLength, uint8_t* info, uint8_t infoLength) {
173a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        mBlob.length = valueLength;
174a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        memcpy(mBlob.value, value, valueLength);
175a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
176a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        mBlob.info = infoLength;
177a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        memcpy(mBlob.value + valueLength, info, infoLength);
178a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
179a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
180a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    Blob(blob b) {
181a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        mBlob = b;
182a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
183a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
184a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    Blob() {}
185a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
1865187818895c4c5f650a611c40531b1dff7764c18Kenny Root    const uint8_t* getValue() const {
187a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return mBlob.value;
188a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
189a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
1905187818895c4c5f650a611c40531b1dff7764c18Kenny Root    int32_t getLength() const {
191a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return mBlob.length;
192a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
193a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
1945187818895c4c5f650a611c40531b1dff7764c18Kenny Root    const uint8_t* getInfo() const {
1955187818895c4c5f650a611c40531b1dff7764c18Kenny Root        return mBlob.value + mBlob.length;
1965187818895c4c5f650a611c40531b1dff7764c18Kenny Root    }
1975187818895c4c5f650a611c40531b1dff7764c18Kenny Root
1985187818895c4c5f650a611c40531b1dff7764c18Kenny Root    uint8_t getInfoLength() const {
199a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return mBlob.info;
200a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
201a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
202a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    ResponseCode encryptBlob(const char* filename, AES_KEY *aes_key, Entropy* entropy) {
203a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (!entropy->generate_random_data(mBlob.vector, AES_BLOCK_SIZE)) {
204a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return SYSTEM_ERROR;
205a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
206a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
207a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // data includes the value and the value's length
208a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t dataLength = mBlob.length + sizeof(mBlob.length);
209a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // pad data to the AES_BLOCK_SIZE
210a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t digestedLength = ((dataLength + AES_BLOCK_SIZE - 1)
211a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                                 / AES_BLOCK_SIZE * AES_BLOCK_SIZE);
212a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // encrypted data includes the digest value
213a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t encryptedLength = digestedLength + MD5_DIGEST_LENGTH;
214a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // move info after space for padding
215a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        memmove(&mBlob.encrypted[encryptedLength], &mBlob.value[mBlob.length], mBlob.info);
216a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // zero padding area
217a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        memset(mBlob.value + mBlob.length, 0, digestedLength - dataLength);
218a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
219a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        mBlob.length = htonl(mBlob.length);
220a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        MD5(mBlob.digested, digestedLength, mBlob.digest);
221a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
222a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        uint8_t vector[AES_BLOCK_SIZE];
223a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        memcpy(vector, mBlob.vector, AES_BLOCK_SIZE);
224a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength,
225a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                        aes_key, vector, AES_ENCRYPT);
226a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
227a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        memset(mBlob.reserved, 0, sizeof(mBlob.reserved));
228a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t headerLength = (mBlob.encrypted - (uint8_t*) &mBlob);
229a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t fileLength = encryptedLength + headerLength + mBlob.info;
230a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
231a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        const char* tmpFileName = ".tmp";
232a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        int out = open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
233a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (out == -1) {
234a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return SYSTEM_ERROR;
235a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
236a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t writtenBytes = writeFully(out, (uint8_t*) &mBlob, fileLength);
237a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (close(out) != 0) {
238a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return SYSTEM_ERROR;
239a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
240a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (writtenBytes != fileLength) {
241a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            unlink(tmpFileName);
242a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return SYSTEM_ERROR;
243a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
244a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return (rename(tmpFileName, filename) == 0) ? NO_ERROR : SYSTEM_ERROR;
245a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
246a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
247a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    ResponseCode decryptBlob(const char* filename, AES_KEY *aes_key) {
248a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        int in = open(filename, O_RDONLY);
249a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (in == -1) {
250a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
251a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
252a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // fileLength may be less than sizeof(mBlob) since the in
253a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // memory version has extra padding to tolerate rounding up to
254a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // the AES_BLOCK_SIZE
255a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t fileLength = readFully(in, (uint8_t*) &mBlob, sizeof(mBlob));
256a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (close(in) != 0) {
257a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return SYSTEM_ERROR;
258a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
259a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t headerLength = (mBlob.encrypted - (uint8_t*) &mBlob);
260a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (fileLength < headerLength) {
261a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return VALUE_CORRUPTED;
262a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
263a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
264a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ssize_t encryptedLength = fileLength - (headerLength + mBlob.info);
265a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (encryptedLength < 0 || encryptedLength % AES_BLOCK_SIZE != 0) {
266a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return VALUE_CORRUPTED;
267a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
268a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key,
269a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                        mBlob.vector, AES_DECRYPT);
270a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
271a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        uint8_t computedDigest[MD5_DIGEST_LENGTH];
272a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        MD5(mBlob.digested, digestedLength, computedDigest);
273a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (memcmp(mBlob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
274a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return VALUE_CORRUPTED;
275a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
276a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
277a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ssize_t maxValueLength = digestedLength - sizeof(mBlob.length);
278a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        mBlob.length = ntohl(mBlob.length);
279a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (mBlob.length < 0 || mBlob.length > maxValueLength) {
280a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return VALUE_CORRUPTED;
281a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
282a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (mBlob.info != 0) {
283a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            // move info from after padding to after data
284a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            memmove(&mBlob.value[mBlob.length], &mBlob.value[maxValueLength], mBlob.info);
285a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
286a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return NO_ERROR;
287a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
288a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
289a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootprivate:
290a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    struct blob mBlob;
291a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root};
292a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
293a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootclass KeyStore {
294a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootpublic:
2955187818895c4c5f650a611c40531b1dff7764c18Kenny Root    KeyStore(Entropy* entropy)
2965187818895c4c5f650a611c40531b1dff7764c18Kenny Root        : mEntropy(entropy)
2975187818895c4c5f650a611c40531b1dff7764c18Kenny Root        , mRetry(MAX_RETRY)
2985187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {
299a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (access(MASTER_KEY_FILE, R_OK) == 0) {
300a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            setState(STATE_LOCKED);
301a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        } else {
302a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            setState(STATE_UNINITIALIZED);
303a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
304a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
305a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
3065187818895c4c5f650a611c40531b1dff7764c18Kenny Root    State getState() const {
307a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return mState;
308a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
309a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
3105187818895c4c5f650a611c40531b1dff7764c18Kenny Root    int8_t getRetry() const {
311a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return mRetry;
312a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
313a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
314a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    ResponseCode initialize(Value* pw) {
315a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (!generateMasterKey()) {
316a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return SYSTEM_ERROR;
317a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
318a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ResponseCode response = writeMasterKey(pw);
319a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (response != NO_ERROR) {
320a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return response;
321a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
322a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        setupMasterKeys();
323a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return NO_ERROR;
324a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
325a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
326a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    ResponseCode writeMasterKey(Value* pw) {
327a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
328a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
329a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        AES_KEY passwordAesKey;
330a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        AES_set_encrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
331a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt));
332a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return masterKeyBlob.encryptBlob(MASTER_KEY_FILE, &passwordAesKey, mEntropy);
333a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
334a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
335a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    ResponseCode readMasterKey(Value* pw) {
336a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        int in = open(MASTER_KEY_FILE, O_RDONLY);
337a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (in == -1) {
338a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return SYSTEM_ERROR;
339a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
340a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
341a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // we read the raw blob to just to get the salt to generate
342a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // the AES key, then we create the Blob to use with decryptBlob
343a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        blob rawBlob;
344a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t length = readFully(in, (uint8_t*) &rawBlob, sizeof(rawBlob));
345a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (close(in) != 0) {
346a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return SYSTEM_ERROR;
347a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
348a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        // find salt at EOF if present, otherwise we have an old file
349a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        uint8_t* salt;
350a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
351a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            salt = (uint8_t*) &rawBlob + length - SALT_SIZE;
352a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        } else {
353a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            salt = NULL;
354a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
355a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
356a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
357a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        AES_KEY passwordAesKey;
358a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
359a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        Blob masterKeyBlob(rawBlob);
360a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ResponseCode response = masterKeyBlob.decryptBlob(MASTER_KEY_FILE, &passwordAesKey);
361a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (response == SYSTEM_ERROR) {
362a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return SYSTEM_ERROR;
363a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
364a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (response == NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
365a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            // if salt was missing, generate one and write a new master key file with the salt.
366a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            if (salt == NULL) {
367a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                if (!generateSalt()) {
368a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                    return SYSTEM_ERROR;
369a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                }
370a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                response = writeMasterKey(pw);
371a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            }
372a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            if (response == NO_ERROR) {
373a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
374a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                setupMasterKeys();
375a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            }
376a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return response;
377a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
378a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (mRetry <= 0) {
379a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            reset();
380a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return UNINITIALIZED;
381a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
382a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        --mRetry;
383a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        switch (mRetry) {
384a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            case 0: return WRONG_PASSWORD_0;
385a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            case 1: return WRONG_PASSWORD_1;
386a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            case 2: return WRONG_PASSWORD_2;
387a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            case 3: return WRONG_PASSWORD_3;
388a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            default: return WRONG_PASSWORD_3;
389a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
390a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
391a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
392a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    bool reset() {
393a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        clearMasterKeys();
394a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        setState(STATE_UNINITIALIZED);
395a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
396a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        DIR* dir = opendir(".");
397a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        struct dirent* file;
398a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
399a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (!dir) {
400a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return false;
401a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
402a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        while ((file = readdir(dir)) != NULL) {
403a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            unlink(file->d_name);
404a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
405a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        closedir(dir);
406a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return true;
407a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
408a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
4095187818895c4c5f650a611c40531b1dff7764c18Kenny Root    bool isEmpty() const {
410a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        DIR* dir = opendir(".");
411a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        struct dirent* file;
412a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (!dir) {
413a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return true;
414a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
415a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        bool result = true;
416a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        while ((file = readdir(dir)) != NULL) {
417a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            if (isKeyFile(file->d_name)) {
418a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                result = false;
419a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                break;
420a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            }
421a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
422a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        closedir(dir);
423a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return result;
424a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
425a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
426a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    void lock() {
427a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        clearMasterKeys();
428a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        setState(STATE_LOCKED);
429a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
430a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
431a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    ResponseCode get(const char* filename, Blob* keyBlob) {
432a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return keyBlob->decryptBlob(filename, &mMasterKeyDecryption);
433a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
434a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
435a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    ResponseCode put(const char* filename, Blob* keyBlob) {
436a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return keyBlob->encryptBlob(filename, &mMasterKeyEncryption, mEntropy);
437a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
438a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
439a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootprivate:
440a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    static const char* MASTER_KEY_FILE;
441a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    static const int MASTER_KEY_SIZE_BYTES = 16;
442a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    static const int MASTER_KEY_SIZE_BITS = MASTER_KEY_SIZE_BYTES * 8;
443a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
444a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    static const int MAX_RETRY = 4;
445a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    static const size_t SALT_SIZE = 16;
446a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
447a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    Entropy* mEntropy;
448a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
449a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    State mState;
450a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int8_t mRetry;
451a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
452a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t mMasterKey[MASTER_KEY_SIZE_BYTES];
453a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t mSalt[SALT_SIZE];
454a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
455a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    AES_KEY mMasterKeyEncryption;
456a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    AES_KEY mMasterKeyDecryption;
457a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
458a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    void setState(State state) {
459a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        mState = state;
460a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
461a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            mRetry = MAX_RETRY;
462a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
463a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
464a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
465a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    bool generateSalt() {
466a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return mEntropy->generate_random_data(mSalt, sizeof(mSalt));
467a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
468a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
469a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    bool generateMasterKey() {
470a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (!mEntropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
471a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return false;
472a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
473a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (!generateSalt()) {
474a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return false;
475a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
476a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return true;
477a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
478a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
479a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    void setupMasterKeys() {
480a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        AES_set_encrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyEncryption);
481a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        AES_set_decrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyDecryption);
482a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        setState(STATE_NO_ERROR);
483a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
484a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
485a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    void clearMasterKeys() {
486a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        memset(mMasterKey, 0, sizeof(mMasterKey));
487a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        memset(mSalt, 0, sizeof(mSalt));
488a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        memset(&mMasterKeyEncryption, 0, sizeof(mMasterKeyEncryption));
489a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption));
490a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
491a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
492a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    static void generateKeyFromPassword(uint8_t* key, ssize_t keySize, Value* pw, uint8_t* salt) {
493a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        size_t saltSize;
494a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (salt != NULL) {
495a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            saltSize = SALT_SIZE;
496a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        } else {
497a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            // pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
498a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            salt = (uint8_t*) "keystore";
499a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            // sizeof = 9, not strlen = 8
500a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            saltSize = sizeof("keystore");
501a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
502a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        PKCS5_PBKDF2_HMAC_SHA1((char*) pw->value, pw->length, salt, saltSize, 8192, keySize, key);
503a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
504a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
505a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    static bool isKeyFile(const char* filename) {
506a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return ((strcmp(filename, MASTER_KEY_FILE) != 0)
507a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                && (strcmp(filename, ".") != 0)
508a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                && (strcmp(filename, "..") != 0));
509a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
510a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root};
511a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
512a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootconst char* KeyStore::MASTER_KEY_FILE = ".masterkey";
513a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
514a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root/* Here is the protocol used in both requests and responses:
515a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root *     code [length_1 message_1 ... length_n message_n] end-of-file
516a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * where code is one byte long and lengths are unsigned 16-bit integers in
517a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * network order. Thus the maximum length of a message is 65535 bytes. */
518a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
519a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic int recv_code(int sock, int8_t* code) {
520a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return recv(sock, code, 1, 0) == 1;
521a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
522a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
523a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic int recv_message(int sock, uint8_t* message, int length) {
524a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t bytes[2];
525a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (recv(sock, &bytes[0], 1, 0) != 1 ||
526a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        recv(sock, &bytes[1], 1, 0) != 1) {
527a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return -1;
528a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    } else {
529a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        int offset = bytes[0] << 8 | bytes[1];
530a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (length < offset) {
531a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return -1;
532a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
533a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        length = offset;
534a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        offset = 0;
535a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        while (offset < length) {
536a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            int n = recv(sock, &message[offset], length - offset, 0);
537a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            if (n <= 0) {
538a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                return -1;
539a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            }
540a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            offset += n;
541a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
542a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
543a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return length;
544a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
545a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
546a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic int recv_end_of_file(int sock) {
547a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint8_t byte;
548a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return recv(sock, &byte, 1, 0) == 0;
549a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
550a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
551a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic void send_code(int sock, int8_t code) {
552a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    send(sock, &code, 1, 0);
553a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
554a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
5555187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic void send_message(int sock, const uint8_t* message, int length) {
556a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint16_t bytes = htons(length);
557a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    send(sock, &bytes, 2, 0);
558a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    send(sock, message, length, 0);
559a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
560a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
561a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root/* Here are the actions. Each of them is a function without arguments. All
562a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * information is defined in global variables, which are set properly before
563a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * performing an action. The number of parameters required by each action is
564a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * fixed and defined in a table. If the return value of an action is positive,
565a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * it will be treated as a response code and transmitted to the client. Note
566a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * that the lengths of parameters are checked when they are received, so
567a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * boundary checks on parameters are omitted. */
568a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
569a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic const ResponseCode NO_ERROR_RESPONSE_CODE_SENT = (ResponseCode) 0;
570a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
5715187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode test(KeyStore* keyStore, int sock, uid_t uid, Value*, Value*, Value*) {
572a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return (ResponseCode) keyStore->getState();
573a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
574a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
5755187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode get(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value*, Value*) {
576a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    char filename[NAME_MAX];
577a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    encode_key(filename, uid, keyName);
578a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    Blob keyBlob;
579a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    ResponseCode responseCode = keyStore->get(filename, &keyBlob);
580a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (responseCode != NO_ERROR) {
581a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return responseCode;
582a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
583a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    send_code(sock, NO_ERROR);
584a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    send_message(sock, keyBlob.getValue(), keyBlob.getLength());
585a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return NO_ERROR_RESPONSE_CODE_SENT;
586a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
587a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
5885187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode insert(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value* val,
5895187818895c4c5f650a611c40531b1dff7764c18Kenny Root        Value*) {
590a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    char filename[NAME_MAX];
591a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    encode_key(filename, uid, keyName);
592a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    Blob keyBlob(val->value, val->length, NULL, 0);
593a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return keyStore->put(filename, &keyBlob);
594a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
595a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
5965187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode del(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value*, Value*) {
597a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    char filename[NAME_MAX];
598a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    encode_key(filename, uid, keyName);
599a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return (unlink(filename) && errno != ENOENT) ? SYSTEM_ERROR : NO_ERROR;
600a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
601a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
6025187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode exist(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value*, Value*) {
603a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    char filename[NAME_MAX];
604a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    encode_key(filename, uid, keyName);
605a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (access(filename, R_OK) == -1) {
606a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND;
607a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
608a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return NO_ERROR;
609a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
610a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
6115187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode saw(KeyStore* keyStore, int sock, uid_t uid, Value* keyPrefix, Value*, Value*) {
612a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    DIR* dir = opendir(".");
613a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (!dir) {
614a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return SYSTEM_ERROR;
615a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
616a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    char filename[NAME_MAX];
617a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int n = encode_key(filename, uid, keyPrefix);
618a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    send_code(sock, NO_ERROR);
619a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
620a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    struct dirent* file;
621a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    while ((file = readdir(dir)) != NULL) {
622a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (!strncmp(filename, file->d_name, n)) {
6235187818895c4c5f650a611c40531b1dff7764c18Kenny Root            const char* p = &file->d_name[n];
624a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            keyPrefix->length = decode_key(keyPrefix->value, p, strlen(p));
625a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            send_message(sock, keyPrefix->value, keyPrefix->length);
626a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
627a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
628a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    closedir(dir);
629a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return NO_ERROR_RESPONSE_CODE_SENT;
630a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
631a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
6325187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode reset(KeyStore* keyStore, int sock, uid_t uid, Value*, Value*, Value*) {
633a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return keyStore->reset() ? NO_ERROR : SYSTEM_ERROR;
634a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
635a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
636a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root/* Here is the history. To improve the security, the parameters to generate the
637a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * master key has been changed. To make a seamless transition, we update the
638a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * file using the same password when the user unlock it for the first time. If
639a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * any thing goes wrong during the transition, the new file will not overwrite
640a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root * the old one. This avoids permanent damages of the existing data. */
641a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
6425187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode password(KeyStore* keyStore, int sock, uid_t uid, Value* pw, Value*, Value*) {
643a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    switch (keyStore->getState()) {
644a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        case STATE_UNINITIALIZED: {
645a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            // generate master key, encrypt with password, write to file, initialize mMasterKey*.
646a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return keyStore->initialize(pw);
647a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
648a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        case STATE_NO_ERROR: {
649a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            // rewrite master key with new password.
650a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return keyStore->writeMasterKey(pw);
651a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
652a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        case STATE_LOCKED: {
653a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            // read master key, decrypt with password, initialize mMasterKey*.
654a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return keyStore->readMasterKey(pw);
655a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
656a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
657a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return SYSTEM_ERROR;
658a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
659a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
6605187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode lock(KeyStore* keyStore, int sock, uid_t uid, Value*, Value*, Value*) {
661a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    keyStore->lock();
662a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return NO_ERROR;
663a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
664a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
6655187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode unlock(KeyStore* keyStore, int sock, uid_t uid, Value* pw, Value* unused,
6665187818895c4c5f650a611c40531b1dff7764c18Kenny Root        Value* unused2) {
6675187818895c4c5f650a611c40531b1dff7764c18Kenny Root    return password(keyStore, sock, uid, pw, unused, unused2);
668a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
669a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
6705187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic ResponseCode zero(KeyStore* keyStore, int sock, uid_t uid, Value*, Value*, Value*) {
671a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return keyStore->isEmpty() ? KEY_NOT_FOUND : NO_ERROR;
672a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
673a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
674a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root/* Here are the permissions, actions, users, and the main function. */
675a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
676a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootenum perm {
6775187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_TEST     = 1 << TEST,
6785187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_GET      = 1 << GET,
6795187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_INSERT   = 1 << INSERT,
6805187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_DELETE   = 1 << DELETE,
6815187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_EXIST    = 1 << EXIST,
6825187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_SAW      = 1 << SAW,
6835187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_RESET    = 1 << RESET,
6845187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_PASSWORD = 1 << PASSWORD,
6855187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_LOCK     = 1 << LOCK,
6865187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_UNLOCK   = 1 << UNLOCK,
6875187818895c4c5f650a611c40531b1dff7764c18Kenny Root    P_ZERO     = 1 << ZERO,
688a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root};
689a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
6905187818895c4c5f650a611c40531b1dff7764c18Kenny Rootstatic const int MAX_PARAM = 3;
691a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
692a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic const State STATE_ANY = (State) 0;
693a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
694a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic struct action {
6955187818895c4c5f650a611c40531b1dff7764c18Kenny Root    ResponseCode (*run)(KeyStore* keyStore, int sock, uid_t uid, Value* param1, Value* param2,
6965187818895c4c5f650a611c40531b1dff7764c18Kenny Root            Value* param3);
697a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int8_t code;
698a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    State state;
699a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint32_t perm;
700a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int lengths[MAX_PARAM];
701a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root} actions[] = {
7025187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {test,       CommandCodes[TEST],       STATE_ANY,      P_TEST,     {0, 0, 0}},
7035187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {get,        CommandCodes[GET],        STATE_NO_ERROR, P_GET,      {KEY_SIZE, 0, 0}},
7045187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {insert,     CommandCodes[INSERT],     STATE_NO_ERROR, P_INSERT,   {KEY_SIZE, VALUE_SIZE, 0}},
7055187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {del,        CommandCodes[DELETE],     STATE_ANY,      P_DELETE,   {KEY_SIZE, 0, 0}},
7065187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {exist,      CommandCodes[EXIST],      STATE_ANY,      P_EXIST,    {KEY_SIZE, 0, 0}},
7075187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {saw,        CommandCodes[SAW],        STATE_ANY,      P_SAW,      {KEY_SIZE, 0, 0}},
7085187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {reset,      CommandCodes[RESET],      STATE_ANY,      P_RESET,    {0, 0, 0}},
7095187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {password,   CommandCodes[PASSWORD],   STATE_ANY,      P_PASSWORD, {PASSWORD_SIZE, 0, 0}},
7105187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {lock,       CommandCodes[LOCK],       STATE_NO_ERROR, P_LOCK,     {0, 0, 0}},
7115187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {unlock,     CommandCodes[UNLOCK],     STATE_LOCKED,   P_UNLOCK,   {PASSWORD_SIZE, 0, 0}},
7125187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {zero,       CommandCodes[ZERO],       STATE_ANY,      P_ZERO,     {0, 0, 0}},
7135187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {NULL,       0,                        STATE_ANY,      0,          {0, 0, 0}},
714a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root};
715a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
716a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic struct user {
717a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uid_t uid;
718a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uid_t euid;
719a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    uint32_t perms;
720a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root} users[] = {
721a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    {AID_SYSTEM,   ~0,         ~0},
7225187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {AID_VPN,      AID_SYSTEM, P_GET},
7235187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {AID_WIFI,     AID_SYSTEM, P_GET},
7245187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {AID_ROOT,     AID_SYSTEM, P_GET},
7255187818895c4c5f650a611c40531b1dff7764c18Kenny Root    {~0,           ~0,         P_TEST | P_GET | P_INSERT | P_DELETE | P_EXIST | P_SAW},
726a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root};
727a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
728a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootstatic ResponseCode process(KeyStore* keyStore, int sock, uid_t uid, int8_t code) {
729a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    struct user* user = users;
730a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    struct action* action = actions;
731a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int i;
732a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
733a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    while (~user->uid && user->uid != uid) {
734a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ++user;
735a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
736a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    while (action->code && action->code != code) {
737a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ++action;
738a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
739a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (!action->code) {
740a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return UNDEFINED_ACTION;
741a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
742a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (!(action->perm & user->perms)) {
743a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return PERMISSION_DENIED;
744a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
745a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (action->state != STATE_ANY && action->state != keyStore->getState()) {
746a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return (ResponseCode) keyStore->getState();
747a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
748a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (~user->euid) {
749a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        uid = user->euid;
750a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
751a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    Value params[MAX_PARAM];
752a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    for (i = 0; i < MAX_PARAM && action->lengths[i] != 0; ++i) {
753a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        params[i].length = recv_message(sock, params[i].value, action->lengths[i]);
754a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (params[i].length < 0) {
755a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            return PROTOCOL_ERROR;
756a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
757a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
758a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (!recv_end_of_file(sock)) {
759a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return PROTOCOL_ERROR;
760a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
7615187818895c4c5f650a611c40531b1dff7764c18Kenny Root    return action->run(keyStore, sock, uid, &params[0], &params[1], &params[2]);
762a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
763a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
764a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Rootint main(int argc, char* argv[]) {
765a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int controlSocket = android_get_control_socket("keystore");
766a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (argc < 2) {
767a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ALOGE("A directory must be specified!");
768a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return 1;
769a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
770a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (chdir(argv[1]) == -1) {
771a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
772a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return 1;
773a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
774a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
775a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    Entropy entropy;
776a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (!entropy.open()) {
777a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return 1;
778a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
779a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    if (listen(controlSocket, 3) == -1) {
780a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        ALOGE("listen: %s", strerror(errno));
781a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        return 1;
782a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
783a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
784a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    signal(SIGPIPE, SIG_IGN);
785a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
786a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    KeyStore keyStore(&entropy);
787a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    int sock;
788a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    while ((sock = accept(controlSocket, NULL, 0)) != -1) {
789a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        struct timeval tv;
790a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        tv.tv_sec = 3;
791a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
792a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
793a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root
794a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        struct ucred cred;
795a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        socklen_t size = sizeof(cred);
796a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        int credResult = getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cred, &size);
797a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        if (credResult != 0) {
798a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            ALOGW("getsockopt: %s", strerror(errno));
799a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        } else {
800a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            int8_t request;
801a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            if (recv_code(sock, &request)) {
802a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                State old_state = keyStore.getState();
803a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                ResponseCode response = process(&keyStore, sock, cred.uid, request);
804a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                if (response == NO_ERROR_RESPONSE_CODE_SENT) {
805a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                    response = NO_ERROR;
806a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                } else {
807a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                    send_code(sock, response);
808a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                }
809a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                ALOGI("uid: %d action: %c -> %d state: %d -> %d retry: %d",
810a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                     cred.uid,
811a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                     request, response,
812a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                     old_state, keyStore.getState(),
813a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root                     keyStore.getRetry());
814a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root            }
815a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        }
816a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root        close(sock);
817a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    }
818a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    ALOGE("accept: %s", strerror(errno));
819a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root    return 1;
820a91203b08350b2fc7efda5b1eab39e7541476b3aKenny Root}
821