/*
 * 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.
 */

#define LOG_TAG "keystore"

#include "user_state.h"

#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#include <openssl/evp.h>

#include <cutils/log.h>

#include "blob.h"
#include "keystore_utils.h"

UserState::UserState(uid_t userId) : mUserId(userId), mRetry(MAX_RETRY) {
    asprintf(&mUserDir, "user_%u", mUserId);
    asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir);
}

UserState::~UserState() {
    free(mUserDir);
    free(mMasterKeyFile);
}

bool UserState::initialize() {
    if ((mkdir(mUserDir, S_IRUSR | S_IWUSR | S_IXUSR) < 0) && (errno != EEXIST)) {
        ALOGE("Could not create directory '%s'", mUserDir);
        return false;
    }

    if (access(mMasterKeyFile, R_OK) == 0) {
        setState(STATE_LOCKED);
    } else {
        setState(STATE_UNINITIALIZED);
    }

    return true;
}

void UserState::setState(State state) {
    mState = state;
    if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
        mRetry = MAX_RETRY;
    }
}

void UserState::zeroizeMasterKeysInMemory() {
    memset(mMasterKey, 0, sizeof(mMasterKey));
    memset(mSalt, 0, sizeof(mSalt));
    memset(&mMasterKeyEncryption, 0, sizeof(mMasterKeyEncryption));
    memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption));
}

bool UserState::deleteMasterKey() {
    setState(STATE_UNINITIALIZED);
    zeroizeMasterKeysInMemory();
    return unlink(mMasterKeyFile) == 0 || errno == ENOENT;
}

ResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) {
    if (!generateMasterKey(entropy)) {
        return SYSTEM_ERROR;
    }
    ResponseCode response = writeMasterKey(pw, entropy);
    if (response != NO_ERROR) {
        return response;
    }
    setupMasterKeys();
    return ::NO_ERROR;
}

ResponseCode UserState::copyMasterKey(UserState* src) {
    if (mState != STATE_UNINITIALIZED) {
        return ::SYSTEM_ERROR;
    }
    if (src->getState() != STATE_NO_ERROR) {
        return ::SYSTEM_ERROR;
    }
    memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
    setupMasterKeys();
    return copyMasterKeyFile(src);
}

ResponseCode UserState::copyMasterKeyFile(UserState* src) {
    /* Copy the master key file to the new user.  Unfortunately we don't have the src user's
     * password so we cannot generate a new file with a new salt.
     */
    int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
    if (in < 0) {
        return ::SYSTEM_ERROR;
    }
    blob rawBlob;
    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
    if (close(in) != 0) {
        return ::SYSTEM_ERROR;
    }
    int out =
        TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
    if (out < 0) {
        return ::SYSTEM_ERROR;
    }
    size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
    if (close(out) != 0) {
        return ::SYSTEM_ERROR;
    }
    if (outLength != length) {
        ALOGW("blob not fully written %zu != %zu", outLength, length);
        unlink(mMasterKeyFile);
        return ::SYSTEM_ERROR;
    }
    return ::NO_ERROR;
}

ResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) {
    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
    AES_KEY passwordAesKey;
    AES_set_encrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
    Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
    return masterKeyBlob.writeBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR, entropy);
}

ResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) {
    int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
    if (in < 0) {
        return SYSTEM_ERROR;
    }

    // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
    // to use with decryptBlob
    blob rawBlob;
    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
    if (close(in) != 0) {
        return SYSTEM_ERROR;
    }
    // find salt at EOF if present, otherwise we have an old file
    uint8_t* salt;
    if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
        salt = (uint8_t*)&rawBlob + length - SALT_SIZE;
    } else {
        salt = NULL;
    }
    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
    AES_KEY passwordAesKey;
    AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
    Blob masterKeyBlob(rawBlob);
    ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR);
    if (response == SYSTEM_ERROR) {
        return response;
    }
    if (response == NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
        // If salt was missing, generate one and write a new master key file with the salt.
        if (salt == NULL) {
            if (!generateSalt(entropy)) {
                return SYSTEM_ERROR;
            }
            response = writeMasterKey(pw, entropy);
        }
        if (response == NO_ERROR) {
            memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
            setupMasterKeys();
        }
        return response;
    }
    if (mRetry <= 0) {
        reset();
        return UNINITIALIZED;
    }
    --mRetry;
    switch (mRetry) {
    case 0:
        return WRONG_PASSWORD_0;
    case 1:
        return WRONG_PASSWORD_1;
    case 2:
        return WRONG_PASSWORD_2;
    case 3:
        return WRONG_PASSWORD_3;
    default:
        return WRONG_PASSWORD_3;
    }
}

bool UserState::reset() {
    DIR* dir = opendir(getUserDirName());
    if (!dir) {
        // If the directory doesn't exist then nothing to do.
        if (errno == ENOENT) {
            return true;
        }
        ALOGW("couldn't open user directory: %s", strerror(errno));
        return false;
    }

    struct dirent* file;
    while ((file = readdir(dir)) != NULL) {
        // skip . and ..
        if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
            continue;
        }

        unlinkat(dirfd(dir), file->d_name, 0);
    }
    closedir(dir);
    return true;
}

void UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
                                        uint8_t* salt) {
    size_t saltSize;
    if (salt != NULL) {
        saltSize = SALT_SIZE;
    } else {
        // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
        salt = (uint8_t*)"keystore";
        // sizeof = 9, not strlen = 8
        saltSize = sizeof("keystore");
    }

    PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize,
                           8192, keySize, key);
}

bool UserState::generateSalt(Entropy* entropy) {
    return entropy->generate_random_data(mSalt, sizeof(mSalt));
}

bool UserState::generateMasterKey(Entropy* entropy) {
    if (!entropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
        return false;
    }
    if (!generateSalt(entropy)) {
        return false;
    }
    return true;
}

void UserState::setupMasterKeys() {
    AES_set_encrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyEncryption);
    AES_set_decrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyDecryption);
    setState(STATE_NO_ERROR);
}
