summaryrefslogtreecommitdiff
path: root/keystore/user_state.h
blob: 75d99d91d57dbd4f3331aa99b92068cd691b706b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * 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_