| /* | 
 |  * 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_ |