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}
72c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
73c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool UserState::deleteMasterKey() {
74c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    setState(STATE_UNINITIALIZED);
75c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    zeroizeMasterKeysInMemory();
76c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return unlink(mMasterKeyFile) == 0 || errno == ENOENT;
77c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
78c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
79c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) {
80c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!generateMasterKey(entropy)) {
81c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
82c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
83c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    ResponseCode response = writeMasterKey(pw, entropy);
84c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (response != ResponseCode::NO_ERROR) {
85c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return response;
86c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
87c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    setupMasterKeys();
88c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    return ResponseCode::NO_ERROR;
89c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
90c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
91c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode UserState::copyMasterKey(UserState* src) {
92c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (mState != STATE_UNINITIALIZED) {
93c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
94c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
95c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (src->getState() != STATE_NO_ERROR) {
96c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
97c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
98c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
99c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    setupMasterKeys();
100c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return copyMasterKeyFile(src);
101c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
102c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
103c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode UserState::copyMasterKeyFile(UserState* src) {
104c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    /* Copy the master key file to the new user.  Unfortunately we don't have the src user's
105c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden     * password so we cannot generate a new file with a new salt.
106c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden     */
107c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
108c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (in < 0) {
109c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
110c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
111e9830589dde19b080fbbfad5fdb1ae6e2955df68Shawn Willden    blobv3 rawBlob;
112c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
113c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (close(in) != 0) {
114c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
115c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
116c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    int out =
117c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
118c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (out < 0) {
119c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
120c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
121c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
122c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (close(out) != 0) {
123c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
124c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
125c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (outLength != length) {
126c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGW("blob not fully written %zu != %zu", outLength, length);
127c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        unlink(mMasterKeyFile);
128c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
129c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
130c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    return ResponseCode::NO_ERROR;
131c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
132c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
133c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) {
134c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
135c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
136c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
137e9830589dde19b080fbbfad5fdb1ae6e2955df68Shawn Willden    return masterKeyBlob.writeBlob(mMasterKeyFile, passwordKey, STATE_NO_ERROR, entropy);
138c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
139c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
140c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn WilldenResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) {
141c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
142c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (in < 0) {
143c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
144c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
145c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
146c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
147c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // to use with decryptBlob
148e9830589dde19b080fbbfad5fdb1ae6e2955df68Shawn Willden    blobv3 rawBlob;
149c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
150c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (close(in) != 0) {
151c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::SYSTEM_ERROR;
152c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
153c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    // find salt at EOF if present, otherwise we have an old file
154c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uint8_t* salt;
155c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
156c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        salt = (uint8_t*)&rawBlob + length - SALT_SIZE;
157c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    } else {
158c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        salt = NULL;
159c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
160c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
161c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
162c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    Blob masterKeyBlob(rawBlob);
163e9830589dde19b080fbbfad5fdb1ae6e2955df68Shawn Willden    ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, passwordKey, STATE_NO_ERROR);
164c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (response == ResponseCode::SYSTEM_ERROR) {
165c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return response;
166c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
167c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis    if (response == ResponseCode::NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
168c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // If salt was missing, generate one and write a new master key file with the salt.
169c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (salt == NULL) {
170c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            if (!generateSalt(entropy)) {
171c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis                return ResponseCode::SYSTEM_ERROR;
172c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            }
173c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            response = writeMasterKey(pw, entropy);
174c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
175c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        if (response == ResponseCode::NO_ERROR) {
176c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
177c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            setupMasterKeys();
178c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
179c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return response;
180c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
181c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (mRetry <= 0) {
182c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        reset();
183c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::UNINITIALIZED;
184c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
185c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    --mRetry;
186c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    switch (mRetry) {
187c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    case 0:
188c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::WRONG_PASSWORD_0;
189c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    case 1:
190c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::WRONG_PASSWORD_1;
191c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    case 2:
192c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::WRONG_PASSWORD_2;
193c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    case 3:
194c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::WRONG_PASSWORD_3;
195c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    default:
196c7a9fa29c185a8c1889486d4acf00fd59c513870Janis Danisevskis        return ResponseCode::WRONG_PASSWORD_3;
197c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
198c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
199c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
200c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool UserState::reset() {
201c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    DIR* dir = opendir(getUserDirName());
202c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!dir) {
203c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // If the directory doesn't exist then nothing to do.
204c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (errno == ENOENT) {
205c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            return true;
206c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
207c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        ALOGW("couldn't open user directory: %s", strerror(errno));
208c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return false;
209c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
210c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
211c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    struct dirent* file;
212c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    while ((file = readdir(dir)) != NULL) {
213c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // skip . and ..
214c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
215c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden            continue;
216c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        }
217c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
218c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        unlinkat(dirfd(dir), file->d_name, 0);
219c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
220c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    closedir(dir);
221c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return true;
222c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
223c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
224c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
225c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                                        uint8_t* salt) {
226c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    size_t saltSize;
227c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (salt != NULL) {
228c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        saltSize = SALT_SIZE;
229c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    } else {
230c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
231c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        salt = (uint8_t*)"keystore";
232c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        // sizeof = 9, not strlen = 8
233c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        saltSize = sizeof("keystore");
234c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
235c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
236c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize,
237c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden                           8192, keySize, key);
238c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
239c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
240c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool UserState::generateSalt(Entropy* entropy) {
241c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return entropy->generate_random_data(mSalt, sizeof(mSalt));
242c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
243c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
244c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenbool UserState::generateMasterKey(Entropy* entropy) {
245c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!entropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
246c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return false;
247c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
248c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    if (!generateSalt(entropy)) {
249c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden        return false;
250c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    }
251c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    return true;
252c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
253c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden
254c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willdenvoid UserState::setupMasterKeys() {
255c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden    setState(STATE_NO_ERROR);
256c1d1feee514e6138e1ed8ff924f5453ba8e1408aShawn Willden}
257