|  | /* | 
|  | * Copyright (C) 2016 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #ifndef KEYSTORE_USER_STATE_H_ | 
|  | #define KEYSTORE_USER_STATE_H_ | 
|  |  | 
|  | #include <sys/types.h> | 
|  |  | 
|  | #include <openssl/aes.h> | 
|  |  | 
|  | #include <utils/String8.h> | 
|  |  | 
|  | #include <keystore/keystore.h> | 
|  |  | 
|  | #include "blob.h" | 
|  | #include "keystore_utils.h" | 
|  |  | 
|  | #include <android-base/logging.h> | 
|  | #include <condition_variable> | 
|  | #include <keystore/keystore_concurrency.h> | 
|  | #include <mutex> | 
|  | #include <set> | 
|  | #include <vector> | 
|  |  | 
|  | namespace keystore { | 
|  |  | 
|  | class UserState; | 
|  |  | 
|  | template <typename UserState> using LockedUserState = ProxyLock<UnlockProxyLockHelper<UserState>>; | 
|  |  | 
|  | class UserState { | 
|  | public: | 
|  | explicit UserState(uid_t userId); | 
|  |  | 
|  | bool initialize(); | 
|  |  | 
|  | uid_t getUserId() const { return mUserId; } | 
|  | const std::string& getUserDirName() const { return mMasterKeyEntry.user_dir(); } | 
|  |  | 
|  | std::string getMasterKeyFileName() const { return mMasterKeyEntry.getKeyBlobPath(); } | 
|  |  | 
|  | void setState(State state); | 
|  | State getState() const { return mState; } | 
|  |  | 
|  | void zeroizeMasterKeysInMemory(); | 
|  | bool deleteMasterKey(); | 
|  |  | 
|  | ResponseCode initialize(const android::String8& pw); | 
|  |  | 
|  | ResponseCode copyMasterKey(LockedUserState<UserState>* src); | 
|  | ResponseCode copyMasterKeyFile(LockedUserState<UserState>* src); | 
|  | ResponseCode writeMasterKey(const android::String8& pw); | 
|  | ResponseCode readMasterKey(const android::String8& pw); | 
|  |  | 
|  | const std::vector<uint8_t>& getEncryptionKey() const { return mMasterKey; } | 
|  |  | 
|  | bool reset(); | 
|  |  | 
|  | bool operator<(const UserState& rhs) const; | 
|  | bool operator<(uid_t userId) const; | 
|  |  | 
|  | private: | 
|  | static constexpr int SHA1_DIGEST_SIZE_BYTES = 16; | 
|  | static constexpr int SHA256_DIGEST_SIZE_BYTES = 32; | 
|  |  | 
|  | static constexpr int MASTER_KEY_SIZE_BYTES = kAes256KeySizeBytes; | 
|  | static constexpr int MASTER_KEY_SIZE_BITS = MASTER_KEY_SIZE_BYTES * 8; | 
|  |  | 
|  | static constexpr size_t SALT_SIZE = 16; | 
|  |  | 
|  | void generateKeyFromPassword(std::vector<uint8_t>& key, const android::String8& pw, | 
|  | uint8_t* salt); | 
|  | bool generateSalt(); | 
|  | bool generateMasterKey(); | 
|  | void setupMasterKeys(); | 
|  |  | 
|  | KeyBlobEntry mMasterKeyEntry; | 
|  |  | 
|  | uid_t mUserId; | 
|  | State mState; | 
|  |  | 
|  | std::vector<uint8_t> mMasterKey; | 
|  | uint8_t mSalt[SALT_SIZE]; | 
|  | }; | 
|  |  | 
|  | bool operator<(uid_t userId, const UserState& rhs); | 
|  |  | 
|  | class UserStateDB { | 
|  | public: | 
|  | LockedUserState<UserState> getUserState(uid_t userId); | 
|  | LockedUserState<UserState> getUserStateByUid(uid_t uid); | 
|  | LockedUserState<const UserState> getUserState(uid_t userId) const; | 
|  | LockedUserState<const UserState> getUserStateByUid(uid_t uid) const; | 
|  |  | 
|  | private: | 
|  | mutable std::set<const UserState*> locked_state_; | 
|  | mutable std::mutex locked_state_mutex_; | 
|  | mutable std::condition_variable locked_state_mutex_cond_var_; | 
|  |  | 
|  | template <typename UserState> | 
|  | LockedUserState<UserState> get(std::unique_lock<std::mutex> lock, UserState* entry) const { | 
|  | locked_state_mutex_cond_var_.wait( | 
|  | lock, [&] { return locked_state_.find(entry) == locked_state_.end(); }); | 
|  | locked_state_.insert(entry); | 
|  | return {entry, [&](UserState* entry) { | 
|  | std::unique_lock<std::mutex> lock(locked_state_mutex_); | 
|  | locked_state_.erase(entry); | 
|  | lock.unlock(); | 
|  | locked_state_mutex_cond_var_.notify_all(); | 
|  | }}; | 
|  | } | 
|  |  | 
|  | std::map<uid_t, UserState> mMasterKeys; | 
|  | }; | 
|  |  | 
|  | }  //  namespace keystore | 
|  |  | 
|  | #endif  // KEYSTORE_USER_STATE_H_ |