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