1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "keystore" 18 19 #include "user_state.h" 20 21 #include <dirent.h> 22 #include <fcntl.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <sys/stat.h> 26 27 #include <openssl/evp.h> 28 29 #include <cutils/log.h> 30 31 #include "blob.h" 32 #include "keystore_utils.h" 33 34 UserState::UserState(uid_t userId) : mUserId(userId), mRetry(MAX_RETRY) { 35 asprintf(&mUserDir, "user_%u", mUserId); 36 asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir); 37 } 38 39 UserState::~UserState() { 40 free(mUserDir); 41 free(mMasterKeyFile); 42 } 43 44 bool UserState::initialize() { 45 if ((mkdir(mUserDir, S_IRUSR | S_IWUSR | S_IXUSR) < 0) && (errno != EEXIST)) { 46 ALOGE("Could not create directory '%s'", mUserDir); 47 return false; 48 } 49 50 if (access(mMasterKeyFile, R_OK) == 0) { 51 setState(STATE_LOCKED); 52 } else { 53 setState(STATE_UNINITIALIZED); 54 } 55 56 return true; 57 } 58 59 void UserState::setState(State state) { 60 mState = state; 61 if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) { 62 mRetry = MAX_RETRY; 63 } 64 } 65 66 void UserState::zeroizeMasterKeysInMemory() { 67 memset(mMasterKey, 0, sizeof(mMasterKey)); 68 memset(mSalt, 0, sizeof(mSalt)); 69 memset(&mMasterKeyEncryption, 0, sizeof(mMasterKeyEncryption)); 70 memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption)); 71 } 72 73 bool UserState::deleteMasterKey() { 74 setState(STATE_UNINITIALIZED); 75 zeroizeMasterKeysInMemory(); 76 return unlink(mMasterKeyFile) == 0 || errno == ENOENT; 77 } 78 79 ResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) { 80 if (!generateMasterKey(entropy)) { 81 return SYSTEM_ERROR; 82 } 83 ResponseCode response = writeMasterKey(pw, entropy); 84 if (response != NO_ERROR) { 85 return response; 86 } 87 setupMasterKeys(); 88 return ::NO_ERROR; 89 } 90 91 ResponseCode UserState::copyMasterKey(UserState* src) { 92 if (mState != STATE_UNINITIALIZED) { 93 return ::SYSTEM_ERROR; 94 } 95 if (src->getState() != STATE_NO_ERROR) { 96 return ::SYSTEM_ERROR; 97 } 98 memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES); 99 setupMasterKeys(); 100 return copyMasterKeyFile(src); 101 } 102 103 ResponseCode UserState::copyMasterKeyFile(UserState* src) { 104 /* Copy the master key file to the new user. Unfortunately we don't have the src user's 105 * password so we cannot generate a new file with a new salt. 106 */ 107 int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY)); 108 if (in < 0) { 109 return ::SYSTEM_ERROR; 110 } 111 blob rawBlob; 112 size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob)); 113 if (close(in) != 0) { 114 return ::SYSTEM_ERROR; 115 } 116 int out = 117 TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)); 118 if (out < 0) { 119 return ::SYSTEM_ERROR; 120 } 121 size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length); 122 if (close(out) != 0) { 123 return ::SYSTEM_ERROR; 124 } 125 if (outLength != length) { 126 ALOGW("blob not fully written %zu != %zu", outLength, length); 127 unlink(mMasterKeyFile); 128 return ::SYSTEM_ERROR; 129 } 130 return ::NO_ERROR; 131 } 132 133 ResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) { 134 uint8_t passwordKey[MASTER_KEY_SIZE_BYTES]; 135 generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt); 136 AES_KEY passwordAesKey; 137 AES_set_encrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey); 138 Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY); 139 return masterKeyBlob.writeBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR, entropy); 140 } 141 142 ResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) { 143 int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY)); 144 if (in < 0) { 145 return SYSTEM_ERROR; 146 } 147 148 // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob 149 // to use with decryptBlob 150 blob rawBlob; 151 size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob)); 152 if (close(in) != 0) { 153 return SYSTEM_ERROR; 154 } 155 // find salt at EOF if present, otherwise we have an old file 156 uint8_t* salt; 157 if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) { 158 salt = (uint8_t*)&rawBlob + length - SALT_SIZE; 159 } else { 160 salt = NULL; 161 } 162 uint8_t passwordKey[MASTER_KEY_SIZE_BYTES]; 163 generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt); 164 AES_KEY passwordAesKey; 165 AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey); 166 Blob masterKeyBlob(rawBlob); 167 ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR); 168 if (response == SYSTEM_ERROR) { 169 return response; 170 } 171 if (response == NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) { 172 // If salt was missing, generate one and write a new master key file with the salt. 173 if (salt == NULL) { 174 if (!generateSalt(entropy)) { 175 return SYSTEM_ERROR; 176 } 177 response = writeMasterKey(pw, entropy); 178 } 179 if (response == NO_ERROR) { 180 memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES); 181 setupMasterKeys(); 182 } 183 return response; 184 } 185 if (mRetry <= 0) { 186 reset(); 187 return UNINITIALIZED; 188 } 189 --mRetry; 190 switch (mRetry) { 191 case 0: 192 return WRONG_PASSWORD_0; 193 case 1: 194 return WRONG_PASSWORD_1; 195 case 2: 196 return WRONG_PASSWORD_2; 197 case 3: 198 return WRONG_PASSWORD_3; 199 default: 200 return WRONG_PASSWORD_3; 201 } 202 } 203 204 bool UserState::reset() { 205 DIR* dir = opendir(getUserDirName()); 206 if (!dir) { 207 // If the directory doesn't exist then nothing to do. 208 if (errno == ENOENT) { 209 return true; 210 } 211 ALOGW("couldn't open user directory: %s", strerror(errno)); 212 return false; 213 } 214 215 struct dirent* file; 216 while ((file = readdir(dir)) != NULL) { 217 // skip . and .. 218 if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) { 219 continue; 220 } 221 222 unlinkat(dirfd(dir), file->d_name, 0); 223 } 224 closedir(dir); 225 return true; 226 } 227 228 void UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw, 229 uint8_t* salt) { 230 size_t saltSize; 231 if (salt != NULL) { 232 saltSize = SALT_SIZE; 233 } else { 234 // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found 235 salt = (uint8_t*)"keystore"; 236 // sizeof = 9, not strlen = 8 237 saltSize = sizeof("keystore"); 238 } 239 240 PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize, 241 8192, keySize, key); 242 } 243 244 bool UserState::generateSalt(Entropy* entropy) { 245 return entropy->generate_random_data(mSalt, sizeof(mSalt)); 246 } 247 248 bool UserState::generateMasterKey(Entropy* entropy) { 249 if (!entropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) { 250 return false; 251 } 252 if (!generateSalt(entropy)) { 253 return false; 254 } 255 return true; 256 } 257 258 void UserState::setupMasterKeys() { 259 AES_set_encrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyEncryption); 260 AES_set_decrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyDecryption); 261 setState(STATE_NO_ERROR); 262 } 263