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