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