1c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden/*
2c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * Copyright (C) 2016 The Android Open Source Project
3c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden *
4c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * Licensed under the Apache License, Version 2.0 (the "License");
5c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * you may not use this file except in compliance with the License.
6c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * You may obtain a copy of the License at
7c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden *
8c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden *      http://www.apache.org/licenses/LICENSE-2.0
9c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden *
10c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * Unless required by applicable law or agreed to in writing, software
11c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * distributed under the License is distributed on an "AS IS" BASIS,
12c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * See the License for the specific language governing permissions and
14c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden * limitations under the License.
15c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden */
16c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
17c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#define LOG_TAG "keystore"
18c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
19c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include "user_state.h"
20c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
21c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include <dirent.h>
22c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include <fcntl.h>
23c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include <stdio.h>
24c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include <stdlib.h>
25c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include <sys/stat.h>
26c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
27c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include <openssl/evp.h>
28c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
29c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include <cutils/log.h>
30c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
31c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include "blob.h"
32c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden#include "keystore_utils.h"
33c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
34c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis
35c7a9fa29c185a8c1889486d4acf00fd59c513870Janis DanisevskisUserState::UserState(uid_t userId) :
36c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        mUserId(userId), mState(STATE_UNINITIALIZED), mRetry(MAX_RETRY) {
37c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    asprintf(&mUserDir, "user_%u", mUserId);
38c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir);
39c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
40c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
41c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenUserState::~UserState() {
42c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    free(mUserDir);
43c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    free(mMasterKeyFile);
44c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
45c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
46c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool UserState::initialize() {
47c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if ((mkdir(mUserDir, S_IRUSR | S_IWUSR | S_IXUSR) < 0) && (errno != EEXIST)) {
48c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGE("Could not create directory '%s'", mUserDir);
49c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return false;
50c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
51c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
52c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (access(mMasterKeyFile, R_OK) == 0) {
53c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        setState(STATE_LOCKED);
54c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    } else {
55c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        setState(STATE_UNINITIALIZED);
56c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
57c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
58c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return true;
59c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
60c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
61c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid UserState::setState(State state) {
62c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    mState = state;
63c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
64c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        mRetry = MAX_RETRY;
65c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
66c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
67c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
68c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid UserState::zeroizeMasterKeysInMemory() {
69c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    memset(mMasterKey, 0, sizeof(mMasterKey));
70c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    memset(mSalt, 0, sizeof(mSalt));
71c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    memset(&mMasterKeyEncryption, 0, sizeof(mMasterKeyEncryption));
72c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption));
73c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
74c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
75c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool UserState::deleteMasterKey() {
76c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    setState(STATE_UNINITIALIZED);
77c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    zeroizeMasterKeysInMemory();
78c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return unlink(mMasterKeyFile) == 0 || errno == ENOENT;
79c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
80c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
81c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) {
82c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!generateMasterKey(entropy)) {
83c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
84c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
85c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    ResponseCode response = writeMasterKey(pw, entropy);
86c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (response != ResponseCode::NO_ERROR) {
87c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return response;
88c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
89c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    setupMasterKeys();
90c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    return ResponseCode::NO_ERROR;
91c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
92c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
93c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode UserState::copyMasterKey(UserState* src) {
94c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (mState != STATE_UNINITIALIZED) {
95c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
96c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
97c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (src->getState() != STATE_NO_ERROR) {
98c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
99c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
100c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
101c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    setupMasterKeys();
102c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return copyMasterKeyFile(src);
103c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
104c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
105c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode UserState::copyMasterKeyFile(UserState* src) {
106c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    /* Copy the master key file to the new user.  Unfortunately we don't have the src user's
107c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden     * password so we cannot generate a new file with a new salt.
108c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden     */
109c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
110c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (in < 0) {
111c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
112c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
113c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    blob rawBlob;
114c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
115c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (close(in) != 0) {
116c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
117c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
118c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    int out =
119c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
120c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (out < 0) {
121c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
122c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
123c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
124c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (close(out) != 0) {
125c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
126c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
127c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (outLength != length) {
128c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGW("blob not fully written %zu != %zu", outLength, length);
129c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        unlink(mMasterKeyFile);
130c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
131c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
132c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    return ResponseCode::NO_ERROR;
133c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
134c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
135c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) {
136c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
137c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
138c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    AES_KEY passwordAesKey;
139c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    AES_set_encrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
140c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
141c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return masterKeyBlob.writeBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR, entropy);
142c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
143c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
144c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) {
145c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
146c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (in < 0) {
147c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
148c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
149c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
150c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
151c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // to use with decryptBlob
152c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    blob rawBlob;
153c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
154c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (close(in) != 0) {
155c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
156c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
157c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // find salt at EOF if present, otherwise we have an old file
158c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uint8_t* salt;
159c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
160c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        salt = (uint8_t*)&rawBlob + length - SALT_SIZE;
161c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    } else {
162c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        salt = NULL;
163c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
164c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
165c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
166c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    AES_KEY passwordAesKey;
167c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
168c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    Blob masterKeyBlob(rawBlob);
169c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR);
170c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (response == ResponseCode::SYSTEM_ERROR) {
171c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return response;
172c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
173c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (response == ResponseCode::NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
174c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // If salt was missing, generate one and write a new master key file with the salt.
175c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (salt == NULL) {
176c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            if (!generateSalt(entropy)) {
177c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis                return ResponseCode::SYSTEM_ERROR;
178c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            }
179c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            response = writeMasterKey(pw, entropy);
180c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
181c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        if (response == ResponseCode::NO_ERROR) {
182c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
183c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            setupMasterKeys();
184c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
185c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return response;
186c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
187c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (mRetry <= 0) {
188c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        reset();
189c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::UNINITIALIZED;
190c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
191c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    --mRetry;
192c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    switch (mRetry) {
193c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    case 0:
194c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::WRONG_PASSWORD_0;
195c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    case 1:
196c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::WRONG_PASSWORD_1;
197c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    case 2:
198c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::WRONG_PASSWORD_2;
199c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    case 3:
200c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::WRONG_PASSWORD_3;
201c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    default:
202c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::WRONG_PASSWORD_3;
203c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
204c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
205c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
206c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool UserState::reset() {
207c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    DIR* dir = opendir(getUserDirName());
208c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!dir) {
209c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // If the directory doesn't exist then nothing to do.
210c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (errno == ENOENT) {
211c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            return true;
212c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
213c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGW("couldn't open user directory: %s", strerror(errno));
214c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return false;
215c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
216c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
217c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    struct dirent* file;
218c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    while ((file = readdir(dir)) != NULL) {
219c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // skip . and ..
220c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
221c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            continue;
222c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
223c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
224c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        unlinkat(dirfd(dir), file->d_name, 0);
225c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
226c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    closedir(dir);
227c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return true;
228c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
229c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
230c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
231c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                                        uint8_t* salt) {
232c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t saltSize;
233c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (salt != NULL) {
234c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        saltSize = SALT_SIZE;
235c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    } else {
236c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
237c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        salt = (uint8_t*)"keystore";
238c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // sizeof = 9, not strlen = 8
239c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        saltSize = sizeof("keystore");
240c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
241c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
242c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize,
243c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                           8192, keySize, key);
244c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
245c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
246c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool UserState::generateSalt(Entropy* entropy) {
247c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return entropy->generate_random_data(mSalt, sizeof(mSalt));
248c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
249c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
250c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool UserState::generateMasterKey(Entropy* entropy) {
251c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!entropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
252c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return false;
253c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
254c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!generateSalt(entropy)) {
255c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return false;
256c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
257c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return true;
258c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
259c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
260c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid UserState::setupMasterKeys() {
261c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    AES_set_encrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyEncryption);
262c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    AES_set_decrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyDecryption);
263c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    setState(STATE_NO_ERROR);
264c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
265