blob: 7c3ca16f6f580ad7bdd845e55241888c86636da0 [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),
40 mUserId(userId), mState(STATE_UNINITIALIZED), mRetry(MAX_RETRY) {}
41
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;
72 if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
73 mRetry = MAX_RETRY;
74 }
75}
76
77void UserState::zeroizeMasterKeysInMemory() {
78 memset(mMasterKey, 0, sizeof(mMasterKey));
79 memset(mSalt, 0, sizeof(mSalt));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070080}
81
82bool UserState::deleteMasterKey() {
83 setState(STATE_UNINITIALIZED);
84 zeroizeMasterKeysInMemory();
Janis Danisevskisff3d7f42018-10-08 07:15:09 -070085 return unlink(mMasterKeyEntry.getKeyBlobPath().c_str()) == 0 || errno == ENOENT;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070086}
87
Branden Archer44d1afa2018-12-28 09:10:49 -080088ResponseCode UserState::initialize(const android::String8& pw) {
89 if (!generateMasterKey()) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010090 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070091 }
Branden Archer44d1afa2018-12-28 09:10:49 -080092 ResponseCode response = writeMasterKey(pw);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010093 if (response != ResponseCode::NO_ERROR) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070094 return response;
95 }
96 setupMasterKeys();
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010097 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070098}
99
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700100ResponseCode UserState::copyMasterKey(LockedUserState<UserState>* src) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700101 if (mState != STATE_UNINITIALIZED) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100102 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700103 }
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700104 if ((*src)->getState() != STATE_NO_ERROR) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100105 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700106 }
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700107 memcpy(mMasterKey, (*src)->mMasterKey, MASTER_KEY_SIZE_BYTES);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700108 setupMasterKeys();
109 return copyMasterKeyFile(src);
110}
111
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700112ResponseCode UserState::copyMasterKeyFile(LockedUserState<UserState>* src) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700113 /* Copy the master key file to the new user. Unfortunately we don't have the src user's
114 * password so we cannot generate a new file with a new salt.
115 */
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700116 int in = TEMP_FAILURE_RETRY(open((*src)->getMasterKeyFileName().c_str(), O_RDONLY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700117 if (in < 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100118 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700119 }
Shawn Willdene9830582017-04-18 10:47:57 -0600120 blobv3 rawBlob;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700121 size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
122 if (close(in) != 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100123 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700124 }
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700125 int out = TEMP_FAILURE_RETRY(open(mMasterKeyEntry.getKeyBlobPath().c_str(),
126 O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700127 if (out < 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100128 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700129 }
130 size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
131 if (close(out) != 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100132 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700133 }
134 if (outLength != length) {
135 ALOGW("blob not fully written %zu != %zu", outLength, length);
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700136 unlink(mMasterKeyEntry.getKeyBlobPath().c_str());
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100137 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700138 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100139 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700140}
141
Branden Archer44d1afa2018-12-28 09:10:49 -0800142ResponseCode UserState::writeMasterKey(const android::String8& pw) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700143 uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
144 generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700145 Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700146 auto lockedEntry = LockedKeyBlobEntry::get(mMasterKeyEntry);
Branden Archer44d1afa2018-12-28 09:10:49 -0800147 return lockedEntry.writeBlobs(masterKeyBlob, {}, passwordKey, STATE_NO_ERROR);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700148}
149
Branden Archer44d1afa2018-12-28 09:10:49 -0800150ResponseCode UserState::readMasterKey(const android::String8& pw) {
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700151
152 auto lockedEntry = LockedKeyBlobEntry::get(mMasterKeyEntry);
153
154 int in = TEMP_FAILURE_RETRY(open(mMasterKeyEntry.getKeyBlobPath().c_str(), O_RDONLY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700155 if (in < 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100156 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700157 }
158
159 // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
160 // to use with decryptBlob
Shawn Willdene9830582017-04-18 10:47:57 -0600161 blobv3 rawBlob;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700162 size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
163 if (close(in) != 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100164 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700165 }
166 // find salt at EOF if present, otherwise we have an old file
167 uint8_t* salt;
168 if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
169 salt = (uint8_t*)&rawBlob + length - SALT_SIZE;
170 } else {
Yi Kongd2916752018-07-26 17:44:27 -0700171 salt = nullptr;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700172 }
173 uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
174 generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700175 Blob masterKeyBlob, dummyBlob;
176 ResponseCode response;
177 std::tie(response, masterKeyBlob, dummyBlob) =
178 lockedEntry.readBlobs(passwordKey, STATE_NO_ERROR);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100179 if (response == ResponseCode::SYSTEM_ERROR) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700180 return response;
181 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100182 if (response == ResponseCode::NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700183 // If salt was missing, generate one and write a new master key file with the salt.
Yi Kongd2916752018-07-26 17:44:27 -0700184 if (salt == nullptr) {
Branden Archer44d1afa2018-12-28 09:10:49 -0800185 if (!generateSalt()) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100186 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700187 }
Branden Archer44d1afa2018-12-28 09:10:49 -0800188 response = writeMasterKey(pw);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700189 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100190 if (response == ResponseCode::NO_ERROR) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700191 memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
192 setupMasterKeys();
193 }
194 return response;
195 }
196 if (mRetry <= 0) {
197 reset();
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100198 return ResponseCode::UNINITIALIZED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700199 }
200 --mRetry;
201 switch (mRetry) {
202 case 0:
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100203 return ResponseCode::WRONG_PASSWORD_0;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700204 case 1:
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100205 return ResponseCode::WRONG_PASSWORD_1;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700206 case 2:
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100207 return ResponseCode::WRONG_PASSWORD_2;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700208 case 3:
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100209 return ResponseCode::WRONG_PASSWORD_3;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700210 default:
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100211 return ResponseCode::WRONG_PASSWORD_3;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700212 }
213}
214
215bool UserState::reset() {
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700216 DIR* dir = opendir(mMasterKeyEntry.user_dir().c_str());
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700217 if (!dir) {
218 // If the directory doesn't exist then nothing to do.
219 if (errno == ENOENT) {
220 return true;
221 }
222 ALOGW("couldn't open user directory: %s", strerror(errno));
223 return false;
224 }
225
226 struct dirent* file;
Yi Kongd2916752018-07-26 17:44:27 -0700227 while ((file = readdir(dir)) != nullptr) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700228 // skip . and ..
229 if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
230 continue;
231 }
232
233 unlinkat(dirfd(dir), file->d_name, 0);
234 }
235 closedir(dir);
236 return true;
237}
238
239void UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
240 uint8_t* salt) {
241 size_t saltSize;
Yi Kongd2916752018-07-26 17:44:27 -0700242 if (salt != nullptr) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700243 saltSize = SALT_SIZE;
244 } else {
245 // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
246 salt = (uint8_t*)"keystore";
247 // sizeof = 9, not strlen = 8
248 saltSize = sizeof("keystore");
249 }
250
Branden Archercefbcbc2018-12-28 12:24:53 -0800251 const EVP_MD* digest = EVP_sha256();
252
253 // SHA1 was used prior to increasing the key size
254 if (keySize == SHA1_DIGEST_SIZE_BYTES) {
255 digest = EVP_sha1();
256 }
257
258 PKCS5_PBKDF2_HMAC(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize, 8192,
259 digest, keySize, key);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700260}
261
Branden Archer44d1afa2018-12-28 09:10:49 -0800262bool UserState::generateSalt() {
263 return RAND_bytes(mSalt, sizeof(mSalt));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700264}
265
Branden Archer44d1afa2018-12-28 09:10:49 -0800266bool UserState::generateMasterKey() {
267 if (!RAND_bytes(mMasterKey, sizeof(mMasterKey))) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700268 return false;
269 }
Branden Archer44d1afa2018-12-28 09:10:49 -0800270 if (!generateSalt()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700271 return false;
272 }
273 return true;
274}
275
276void UserState::setupMasterKeys() {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700277 setState(STATE_NO_ERROR);
278}
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700279
280LockedUserState<UserState> UserStateDB::getUserState(uid_t userId) {
281 std::unique_lock<std::mutex> lock(locked_state_mutex_);
282 decltype(mMasterKeys.begin()) it;
283 bool inserted;
284 std::tie(it, inserted) = mMasterKeys.emplace(userId, userId);
285 if (inserted) {
286 if (!it->second.initialize()) {
287 /* There's not much we can do if initialization fails. Trying to
288 * unlock the keystore for that user will fail as well, so any
289 * subsequent request for this user will just return SYSTEM_ERROR.
290 */
291 ALOGE("User initialization failed for %u; subsequent operations will fail", userId);
292 }
293 }
294 return get(std::move(lock), &it->second);
295}
296
297LockedUserState<UserState> UserStateDB::getUserStateByUid(uid_t uid) {
298 return getUserState(get_user_id(uid));
299}
300
301LockedUserState<const UserState> UserStateDB::getUserState(uid_t userId) const {
302 std::unique_lock<std::mutex> lock(locked_state_mutex_);
303 auto it = mMasterKeys.find(userId);
304 if (it == mMasterKeys.end()) return {};
305 return get(std::move(lock), &it->second);
306}
307
308LockedUserState<const UserState> UserStateDB::getUserStateByUid(uid_t uid) const {
309 return getUserState(get_user_id(uid));
310}
311
312} // namespace keystore