/* * 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; } int8_t getRetry() const { return mRetry; } 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 const int SHA1_DIGEST_SIZE_BYTES = 16; static const int SHA256_DIGEST_SIZE_BYTES = 32; static const int MASTER_KEY_SIZE_BYTES = SHA256_DIGEST_SIZE_BYTES; static const int MASTER_KEY_SIZE_BITS = MASTER_KEY_SIZE_BYTES * 8; static const int MAX_RETRY = 4; static const 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; int8_t mRetry; 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_