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