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, ¶ms[0], ¶ms[1], ¶ms[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