• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/digest.h>
28 #include <openssl/evp.h>
29 #include <openssl/rand.h>
30 
31 #include <log/log.h>
32 
33 #include "blob.h"
34 #include "keystore_utils.h"
35 
36 namespace keystore {
37 
UserState(uid_t userId)38 UserState::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 
operator <(const UserState & rhs) const42 bool UserState::operator<(const UserState& rhs) const {
43     return getUserId() < rhs.getUserId();
44 }
45 
operator <(uid_t userId) const46 bool UserState::operator<(uid_t userId) const {
47     return getUserId() < userId;
48 }
49 
operator <(uid_t userId,const UserState & rhs)50 bool operator<(uid_t userId, const UserState& rhs) {
51     return userId < rhs.getUserId();
52 }
53 
initialize()54 bool UserState::initialize() {
55     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());
58         return false;
59     }
60 
61     if (mMasterKeyEntry.hasKeyBlob()) {
62         setState(STATE_LOCKED);
63     } else {
64         setState(STATE_UNINITIALIZED);
65     }
66 
67     return true;
68 }
69 
setState(State state)70 void UserState::setState(State state) {
71     mState = state;
72     if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
73         mRetry = MAX_RETRY;
74     }
75 }
76 
zeroizeMasterKeysInMemory()77 void UserState::zeroizeMasterKeysInMemory() {
78     memset(mMasterKey.data(), 0, mMasterKey.size());
79     memset(mSalt, 0, sizeof(mSalt));
80 }
81 
deleteMasterKey()82 bool UserState::deleteMasterKey() {
83     setState(STATE_UNINITIALIZED);
84     zeroizeMasterKeysInMemory();
85     return unlink(mMasterKeyEntry.getKeyBlobPath().c_str()) == 0 || errno == ENOENT;
86 }
87 
initialize(const android::String8 & pw)88 ResponseCode UserState::initialize(const android::String8& pw) {
89     if (!generateMasterKey()) {
90         return ResponseCode::SYSTEM_ERROR;
91     }
92     ResponseCode response = writeMasterKey(pw);
93     if (response != ResponseCode::NO_ERROR) {
94         return response;
95     }
96     setupMasterKeys();
97     return ResponseCode::NO_ERROR;
98 }
99 
copyMasterKey(LockedUserState<UserState> * src)100 ResponseCode UserState::copyMasterKey(LockedUserState<UserState>* src) {
101     if (mState != STATE_UNINITIALIZED) {
102         return ResponseCode::SYSTEM_ERROR;
103     }
104     if ((*src)->getState() != STATE_NO_ERROR) {
105         return ResponseCode::SYSTEM_ERROR;
106     }
107     mMasterKey = (*src)->mMasterKey;
108     setupMasterKeys();
109     return copyMasterKeyFile(src);
110 }
111 
copyMasterKeyFile(LockedUserState<UserState> * src)112 ResponseCode UserState::copyMasterKeyFile(LockedUserState<UserState>* src) {
113     /* 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      */
116     int in = TEMP_FAILURE_RETRY(open((*src)->getMasterKeyFileName().c_str(), O_RDONLY));
117     if (in < 0) {
118         return ResponseCode::SYSTEM_ERROR;
119     }
120     blobv3 rawBlob;
121     size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
122     if (close(in) != 0) {
123         return ResponseCode::SYSTEM_ERROR;
124     }
125     int out = TEMP_FAILURE_RETRY(open(mMasterKeyEntry.getKeyBlobPath().c_str(),
126                                       O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
127     if (out < 0) {
128         return ResponseCode::SYSTEM_ERROR;
129     }
130     size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
131     if (close(out) != 0) {
132         return ResponseCode::SYSTEM_ERROR;
133     }
134     if (outLength != length) {
135         ALOGW("blob not fully written %zu != %zu", outLength, length);
136         unlink(mMasterKeyEntry.getKeyBlobPath().c_str());
137         return ResponseCode::SYSTEM_ERROR;
138     }
139     return ResponseCode::NO_ERROR;
140 }
141 
writeMasterKey(const android::String8 & pw)142 ResponseCode UserState::writeMasterKey(const android::String8& pw) {
143     std::vector<uint8_t> passwordKey(MASTER_KEY_SIZE_BYTES);
144     generateKeyFromPassword(passwordKey, pw, mSalt);
145     Blob masterKeyBlob(mMasterKey.data(), mMasterKey.size(), mSalt, sizeof(mSalt),
146                        TYPE_MASTER_KEY_AES256);
147     auto lockedEntry = LockedKeyBlobEntry::get(mMasterKeyEntry);
148     return lockedEntry.writeBlobs(masterKeyBlob, {}, passwordKey, STATE_NO_ERROR);
149 }
150 
readMasterKey(const android::String8 & pw)151 ResponseCode UserState::readMasterKey(const android::String8& pw) {
152 
153     auto lockedEntry = LockedKeyBlobEntry::get(mMasterKeyEntry);
154 
155     int in = TEMP_FAILURE_RETRY(open(mMasterKeyEntry.getKeyBlobPath().c_str(), O_RDONLY));
156     if (in < 0) {
157         return ResponseCode::SYSTEM_ERROR;
158     }
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
162     blobv3 rawBlob;
163     size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
164     if (close(in) != 0) {
165         return ResponseCode::SYSTEM_ERROR;
166     }
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 {
172         salt = nullptr;
173     }
174 
175     size_t masterKeySize = MASTER_KEY_SIZE_BYTES;
176     if (rawBlob.type == TYPE_MASTER_KEY) {
177         masterKeySize = SHA1_DIGEST_SIZE_BYTES;
178     }
179 
180     std::vector<uint8_t> passwordKey(masterKeySize);
181     generateKeyFromPassword(passwordKey, pw, salt);
182     Blob masterKeyBlob, dummyBlob;
183     ResponseCode response;
184     std::tie(response, masterKeyBlob, dummyBlob) =
185         lockedEntry.readBlobs(passwordKey, STATE_NO_ERROR);
186     if (response == ResponseCode::SYSTEM_ERROR) {
187         return response;
188     }
189 
190     size_t masterKeyBlobLength = static_cast<size_t>(masterKeyBlob.getLength());
191 
192     if (response == ResponseCode::NO_ERROR && masterKeyBlobLength == masterKeySize) {
193         // If salt was missing, generate one and write a new master key file with the salt.
194         if (salt == nullptr) {
195             if (!generateSalt()) {
196                 return ResponseCode::SYSTEM_ERROR;
197             }
198             response = writeMasterKey(pw);
199         }
200         if (response == ResponseCode::NO_ERROR) {
201             mMasterKey = std::vector<uint8_t>(masterKeyBlob.getValue(),
202                                               masterKeyBlob.getValue() + masterKeyBlob.getLength());
203 
204             setupMasterKeys();
205         }
206         return response;
207     }
208     if (mRetry <= 0) {
209         reset();
210         return ResponseCode::UNINITIALIZED;
211     }
212     --mRetry;
213     switch (mRetry) {
214     case 0:
215         return ResponseCode::WRONG_PASSWORD_0;
216     case 1:
217         return ResponseCode::WRONG_PASSWORD_1;
218     case 2:
219         return ResponseCode::WRONG_PASSWORD_2;
220     case 3:
221         return ResponseCode::WRONG_PASSWORD_3;
222     default:
223         return ResponseCode::WRONG_PASSWORD_3;
224     }
225 }
226 
reset()227 bool UserState::reset() {
228     DIR* dir = opendir(mMasterKeyEntry.user_dir().c_str());
229     if (!dir) {
230         // If the directory doesn't exist then nothing to do.
231         if (errno == ENOENT) {
232             return true;
233         }
234         ALOGW("couldn't open user directory: %s", strerror(errno));
235         return false;
236     }
237 
238     struct dirent* file;
239     while ((file = readdir(dir)) != nullptr) {
240         // skip . and ..
241         if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
242             continue;
243         }
244 
245         unlinkat(dirfd(dir), file->d_name, 0);
246     }
247     closedir(dir);
248     return true;
249 }
250 
generateKeyFromPassword(std::vector<uint8_t> & key,const android::String8 & pw,uint8_t * salt)251 void UserState::generateKeyFromPassword(std::vector<uint8_t>& key, const android::String8& pw,
252                                         uint8_t* salt) {
253     size_t saltSize;
254     if (salt != nullptr) {
255         saltSize = SALT_SIZE;
256     } else {
257         // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
258         salt = (uint8_t*)"keystore";
259         // sizeof = 9, not strlen = 8
260         saltSize = sizeof("keystore");
261     }
262 
263     const EVP_MD* digest = EVP_sha256();
264 
265     // SHA1 was used prior to increasing the key size
266     if (key.size() == SHA1_DIGEST_SIZE_BYTES) {
267         digest = EVP_sha1();
268     }
269 
270     PKCS5_PBKDF2_HMAC(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize, 8192,
271                       digest, key.size(), key.data());
272 }
273 
generateSalt()274 bool UserState::generateSalt() {
275     return RAND_bytes(mSalt, sizeof(mSalt));
276 }
277 
generateMasterKey()278 bool UserState::generateMasterKey() {
279     mMasterKey.resize(MASTER_KEY_SIZE_BYTES);
280     if (!RAND_bytes(mMasterKey.data(), mMasterKey.size())) {
281         return false;
282     }
283     if (!generateSalt()) {
284         return false;
285     }
286     return true;
287 }
288 
setupMasterKeys()289 void UserState::setupMasterKeys() {
290     setState(STATE_NO_ERROR);
291 }
292 
getUserState(uid_t userId)293 LockedUserState<UserState> UserStateDB::getUserState(uid_t userId) {
294     std::unique_lock<std::mutex> lock(locked_state_mutex_);
295     decltype(mMasterKeys.begin()) it;
296     bool inserted;
297     std::tie(it, inserted) = mMasterKeys.emplace(userId, userId);
298     if (inserted) {
299         if (!it->second.initialize()) {
300             /* There's not much we can do if initialization fails. Trying to
301              * unlock the keystore for that user will fail as well, so any
302              * subsequent request for this user will just return SYSTEM_ERROR.
303              */
304             ALOGE("User initialization failed for %u; subsequent operations will fail", userId);
305         }
306     }
307     return get(std::move(lock), &it->second);
308 }
309 
getUserStateByUid(uid_t uid)310 LockedUserState<UserState> UserStateDB::getUserStateByUid(uid_t uid) {
311     return getUserState(get_user_id(uid));
312 }
313 
getUserState(uid_t userId) const314 LockedUserState<const UserState> UserStateDB::getUserState(uid_t userId) const {
315     std::unique_lock<std::mutex> lock(locked_state_mutex_);
316     auto it = mMasterKeys.find(userId);
317     if (it == mMasterKeys.end()) return {};
318     return get(std::move(lock), &it->second);
319 }
320 
getUserStateByUid(uid_t uid) const321 LockedUserState<const UserState> UserStateDB::getUserStateByUid(uid_t uid) const {
322     return getUserState(get_user_id(uid));
323 }
324 
325 }  // namespace keystore
326