blob: 30dfe3c36534211388f2ccf364f9f23006d52d57 [file] [log] [blame]
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001/*
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
Branden Archercefbcbc2018-12-28 12:24:53 -080027#include <openssl/digest.h>
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070028#include <openssl/evp.h>
Branden Archer44d1afa2018-12-28 09:10:49 -080029#include <openssl/rand.h>
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070030
Logan Chiencdc813f2018-04-23 13:52:28 +080031#include <log/log.h>
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070032
33#include "blob.h"
34#include "keystore_utils.h"
35
Janis Danisevskisff3d7f42018-10-08 07:15:09 -070036namespace keystore {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010037
Janis Danisevskisff3d7f42018-10-08 07:15:09 -070038UserState::UserState(uid_t userId)
39 : mMasterKeyEntry(".masterkey", "user_" + std::to_string(userId), userId, /* masterkey */ true),
Shawn Willden688d3ab2019-10-02 11:55:27 -060040 mUserId(userId), mState(STATE_UNINITIALIZED) {}
Janis Danisevskisff3d7f42018-10-08 07:15:09 -070041
42bool UserState::operator<(const UserState& rhs) const {
43 return getUserId() < rhs.getUserId();
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070044}
45
Janis Danisevskisff3d7f42018-10-08 07:15:09 -070046bool UserState::operator<(uid_t userId) const {
47 return getUserId() < userId;
48}
49
50bool operator<(uid_t userId, const UserState& rhs) {
51 return userId < rhs.getUserId();
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070052}
53
54bool UserState::initialize() {
Janis Danisevskisff3d7f42018-10-08 07:15:09 -070055 if ((mkdir(mMasterKeyEntry.user_dir().c_str(), S_IRUSR | S_IWUSR | S_IXUSR) < 0) &&
56 (errno != EEXIST)) {
57 ALOGE("Could not create directory '%s'", mMasterKeyEntry.user_dir().c_str());
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070058 return false;
59 }
60
Janis Danisevskisff3d7f42018-10-08 07:15:09 -070061 if (mMasterKeyEntry.hasKeyBlob()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070062 setState(STATE_LOCKED);
63 } else {
64 setState(STATE_UNINITIALIZED);
65 }
66
67 return true;
68}
69
70void UserState::setState(State state) {
71 mState = state;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070072}
73
74void UserState::zeroizeMasterKeysInMemory() {
Branden Archerf5953d72019-01-10 09:08:18 -080075 memset(mMasterKey.data(), 0, mMasterKey.size());
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070076 memset(mSalt, 0, sizeof(mSalt));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070077}
78
79bool UserState::deleteMasterKey() {
80 setState(STATE_UNINITIALIZED);
81 zeroizeMasterKeysInMemory();
Janis Danisevskisff3d7f42018-10-08 07:15:09 -070082 return unlink(mMasterKeyEntry.getKeyBlobPath().c_str()) == 0 || errno == ENOENT;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070083}
84
Branden Archer44d1afa2018-12-28 09:10:49 -080085ResponseCode UserState::initialize(const android::String8& pw) {
86 if (!generateMasterKey()) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010087 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070088 }
Branden Archer44d1afa2018-12-28 09:10:49 -080089 ResponseCode response = writeMasterKey(pw);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010090 if (response != ResponseCode::NO_ERROR) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070091 return response;
92 }
93 setupMasterKeys();
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010094 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070095}
96
Janis Danisevskisff3d7f42018-10-08 07:15:09 -070097ResponseCode UserState::copyMasterKey(LockedUserState<UserState>* src) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070098 if (mState != STATE_UNINITIALIZED) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010099 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700100 }
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700101 if ((*src)->getState() != STATE_NO_ERROR) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100102 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700103 }
Branden Archerf5953d72019-01-10 09:08:18 -0800104 mMasterKey = (*src)->mMasterKey;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700105 setupMasterKeys();
106 return copyMasterKeyFile(src);
107}
108
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700109ResponseCode UserState::copyMasterKeyFile(LockedUserState<UserState>* src) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700110 /* Copy the master key file to the new user. Unfortunately we don't have the src user's
111 * password so we cannot generate a new file with a new salt.
112 */
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700113 int in = TEMP_FAILURE_RETRY(open((*src)->getMasterKeyFileName().c_str(), O_RDONLY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700114 if (in < 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100115 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700116 }
Shawn Willdene9830582017-04-18 10:47:57 -0600117 blobv3 rawBlob;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700118 size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
119 if (close(in) != 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100120 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700121 }
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700122 int out = TEMP_FAILURE_RETRY(open(mMasterKeyEntry.getKeyBlobPath().c_str(),
123 O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700124 if (out < 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100125 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700126 }
127 size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
128 if (close(out) != 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100129 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700130 }
131 if (outLength != length) {
132 ALOGW("blob not fully written %zu != %zu", outLength, length);
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700133 unlink(mMasterKeyEntry.getKeyBlobPath().c_str());
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100134 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700135 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100136 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700137}
138
Branden Archer44d1afa2018-12-28 09:10:49 -0800139ResponseCode UserState::writeMasterKey(const android::String8& pw) {
Shawn Willden17b87092019-10-01 17:43:43 -0600140 std::vector<uint8_t> passwordKey(mMasterKey.size());
Branden Archerf5953d72019-01-10 09:08:18 -0800141 generateKeyFromPassword(passwordKey, pw, mSalt);
Shawn Willden17b87092019-10-01 17:43:43 -0600142 auto blobType = TYPE_MASTER_KEY_AES256;
143 if (mMasterKey.size() == kAes128KeySizeBytes) {
144 blobType = TYPE_MASTER_KEY;
145 }
146 Blob masterKeyBlob(mMasterKey.data(), mMasterKey.size(), mSalt, sizeof(mSalt), blobType);
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700147 auto lockedEntry = LockedKeyBlobEntry::get(mMasterKeyEntry);
Branden Archer44d1afa2018-12-28 09:10:49 -0800148 return lockedEntry.writeBlobs(masterKeyBlob, {}, passwordKey, STATE_NO_ERROR);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700149}
150
Branden Archer44d1afa2018-12-28 09:10:49 -0800151ResponseCode UserState::readMasterKey(const android::String8& pw) {
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700152
153 auto lockedEntry = LockedKeyBlobEntry::get(mMasterKeyEntry);
154
155 int in = TEMP_FAILURE_RETRY(open(mMasterKeyEntry.getKeyBlobPath().c_str(), O_RDONLY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700156 if (in < 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100157 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700158 }
159
160 // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
161 // to use with decryptBlob
Shawn Willdene9830582017-04-18 10:47:57 -0600162 blobv3 rawBlob;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700163 size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
164 if (close(in) != 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100165 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700166 }
167 // find salt at EOF if present, otherwise we have an old file
168 uint8_t* salt;
169 if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
170 salt = (uint8_t*)&rawBlob + length - SALT_SIZE;
171 } else {
Yi Kongd2916752018-07-26 17:44:27 -0700172 salt = nullptr;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700173 }
Branden Archerf5953d72019-01-10 09:08:18 -0800174
Branden Archerd0315732019-01-10 14:56:05 -0800175 size_t masterKeySize = MASTER_KEY_SIZE_BYTES;
176 if (rawBlob.type == TYPE_MASTER_KEY) {
Shawn Willden17b87092019-10-01 17:43:43 -0600177 masterKeySize = kAes128KeySizeBytes;
Branden Archerd0315732019-01-10 14:56:05 -0800178 }
179
180 std::vector<uint8_t> passwordKey(masterKeySize);
Branden Archerf5953d72019-01-10 09:08:18 -0800181 generateKeyFromPassword(passwordKey, pw, salt);
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700182 Blob masterKeyBlob, dummyBlob;
183 ResponseCode response;
184 std::tie(response, masterKeyBlob, dummyBlob) =
185 lockedEntry.readBlobs(passwordKey, STATE_NO_ERROR);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100186 if (response == ResponseCode::SYSTEM_ERROR) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700187 return response;
188 }
Branden Archerd0315732019-01-10 14:56:05 -0800189
190 size_t masterKeyBlobLength = static_cast<size_t>(masterKeyBlob.getLength());
191
192 if (response == ResponseCode::NO_ERROR && masterKeyBlobLength == masterKeySize) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700193 // If salt was missing, generate one and write a new master key file with the salt.
Yi Kongd2916752018-07-26 17:44:27 -0700194 if (salt == nullptr) {
Branden Archer44d1afa2018-12-28 09:10:49 -0800195 if (!generateSalt()) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100196 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700197 }
Branden Archer44d1afa2018-12-28 09:10:49 -0800198 response = writeMasterKey(pw);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700199 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100200 if (response == ResponseCode::NO_ERROR) {
Branden Archerf5953d72019-01-10 09:08:18 -0800201 mMasterKey = std::vector<uint8_t>(masterKeyBlob.getValue(),
202 masterKeyBlob.getValue() + masterKeyBlob.getLength());
203
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700204 setupMasterKeys();
205 }
206 return response;
207 }
Shawn Willden688d3ab2019-10-02 11:55:27 -0600208
209 LOG(ERROR) << "Invalid password presented";
210 return ResponseCode::WRONG_PASSWORD_0;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700211}
212
213bool UserState::reset() {
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700214 DIR* dir = opendir(mMasterKeyEntry.user_dir().c_str());
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700215 if (!dir) {
216 // If the directory doesn't exist then nothing to do.
217 if (errno == ENOENT) {
218 return true;
219 }
220 ALOGW("couldn't open user directory: %s", strerror(errno));
221 return false;
222 }
223
224 struct dirent* file;
Yi Kongd2916752018-07-26 17:44:27 -0700225 while ((file = readdir(dir)) != nullptr) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700226 // skip . and ..
227 if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
228 continue;
229 }
230
231 unlinkat(dirfd(dir), file->d_name, 0);
232 }
233 closedir(dir);
234 return true;
235}
236
Branden Archerf5953d72019-01-10 09:08:18 -0800237void UserState::generateKeyFromPassword(std::vector<uint8_t>& key, const android::String8& pw,
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700238 uint8_t* salt) {
239 size_t saltSize;
Yi Kongd2916752018-07-26 17:44:27 -0700240 if (salt != nullptr) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700241 saltSize = SALT_SIZE;
242 } else {
243 // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
244 salt = (uint8_t*)"keystore";
245 // sizeof = 9, not strlen = 8
246 saltSize = sizeof("keystore");
247 }
248
Branden Archercefbcbc2018-12-28 12:24:53 -0800249 const EVP_MD* digest = EVP_sha256();
250
251 // SHA1 was used prior to increasing the key size
Shawn Willden17b87092019-10-01 17:43:43 -0600252 if (key.size() == kAes128KeySizeBytes) {
Branden Archercefbcbc2018-12-28 12:24:53 -0800253 digest = EVP_sha1();
254 }
255
256 PKCS5_PBKDF2_HMAC(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize, 8192,
Branden Archerf5953d72019-01-10 09:08:18 -0800257 digest, key.size(), key.data());
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700258}
259
Branden Archer44d1afa2018-12-28 09:10:49 -0800260bool UserState::generateSalt() {
261 return RAND_bytes(mSalt, sizeof(mSalt));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700262}
263
Branden Archer44d1afa2018-12-28 09:10:49 -0800264bool UserState::generateMasterKey() {
Branden Archerf5953d72019-01-10 09:08:18 -0800265 mMasterKey.resize(MASTER_KEY_SIZE_BYTES);
266 if (!RAND_bytes(mMasterKey.data(), mMasterKey.size())) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700267 return false;
268 }
Branden Archer44d1afa2018-12-28 09:10:49 -0800269 if (!generateSalt()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700270 return false;
271 }
272 return true;
273}
274
275void UserState::setupMasterKeys() {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700276 setState(STATE_NO_ERROR);
277}
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700278
279LockedUserState<UserState> UserStateDB::getUserState(uid_t userId) {
280 std::unique_lock<std::mutex> lock(locked_state_mutex_);
281 decltype(mMasterKeys.begin()) it;
282 bool inserted;
283 std::tie(it, inserted) = mMasterKeys.emplace(userId, userId);
284 if (inserted) {
285 if (!it->second.initialize()) {
286 /* There's not much we can do if initialization fails. Trying to
287 * unlock the keystore for that user will fail as well, so any
288 * subsequent request for this user will just return SYSTEM_ERROR.
289 */
290 ALOGE("User initialization failed for %u; subsequent operations will fail", userId);
291 }
292 }
293 return get(std::move(lock), &it->second);
294}
295
296LockedUserState<UserState> UserStateDB::getUserStateByUid(uid_t uid) {
297 return getUserState(get_user_id(uid));
298}
299
300LockedUserState<const UserState> UserStateDB::getUserState(uid_t userId) const {
301 std::unique_lock<std::mutex> lock(locked_state_mutex_);
302 auto it = mMasterKeys.find(userId);
303 if (it == mMasterKeys.end()) return {};
304 return get(std::move(lock), &it->second);
305}
306
307LockedUserState<const UserState> UserStateDB::getUserStateByUid(uid_t uid) const {
308 return getUserState(get_user_id(uid));
309}
310
311} // namespace keystore