/*
 * Copyright (C) 2015 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 <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>

#include <cutils/log.h>

#include "blob.h"
#include "entropy.h"

#include "keystore_utils.h"

Blob::Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
           BlobType type) {
    memset(&mBlob, 0, sizeof(mBlob));
    if (valueLength > VALUE_SIZE) {
        valueLength = VALUE_SIZE;
        ALOGW("Provided blob length too large");
    }
    if (infoLength + valueLength > VALUE_SIZE) {
        infoLength = VALUE_SIZE - valueLength;
        ALOGW("Provided info length too large");
    }
    mBlob.length = valueLength;
    memcpy(mBlob.value, value, valueLength);

    mBlob.info = infoLength;
    memcpy(mBlob.value + valueLength, info, infoLength);

    mBlob.version = CURRENT_BLOB_VERSION;
    mBlob.type = uint8_t(type);

    if (type == TYPE_MASTER_KEY) {
        mBlob.flags = KEYSTORE_FLAG_ENCRYPTED;
    } else {
        mBlob.flags = KEYSTORE_FLAG_NONE;
    }
}

Blob::Blob(blob b) {
    mBlob = b;
}

Blob::Blob() {
    memset(&mBlob, 0, sizeof(mBlob));
}

bool Blob::isEncrypted() const {
    if (mBlob.version < 2) {
        return true;
    }

    return mBlob.flags & KEYSTORE_FLAG_ENCRYPTED;
}

void Blob::setEncrypted(bool encrypted) {
    if (encrypted) {
        mBlob.flags |= KEYSTORE_FLAG_ENCRYPTED;
    } else {
        mBlob.flags &= ~KEYSTORE_FLAG_ENCRYPTED;
    }
}

void Blob::setFallback(bool fallback) {
    if (fallback) {
        mBlob.flags |= KEYSTORE_FLAG_FALLBACK;
    } else {
        mBlob.flags &= ~KEYSTORE_FLAG_FALLBACK;
    }
}

ResponseCode Blob::writeBlob(const char* filename, AES_KEY* aes_key, State state,
                             Entropy* entropy) {
    ALOGV("writing blob %s", filename);
    if (isEncrypted()) {
        if (state != STATE_NO_ERROR) {
            ALOGD("couldn't insert encrypted blob while not unlocked");
            return ResponseCode::LOCKED;
        }

        if (!entropy->generate_random_data(mBlob.vector, AES_BLOCK_SIZE)) {
            ALOGW("Could not read random data for: %s", filename);
            return ResponseCode::SYSTEM_ERROR;
        }
    }

    // data includes the value and the value's length
    size_t dataLength = mBlob.length + sizeof(mBlob.length);
    // pad data to the AES_BLOCK_SIZE
    size_t digestedLength = ((dataLength + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE);
    // encrypted data includes the digest value
    size_t encryptedLength = digestedLength + MD5_DIGEST_LENGTH;
    // move info after space for padding
    memmove(&mBlob.encrypted[encryptedLength], &mBlob.value[mBlob.length], mBlob.info);
    // zero padding area
    memset(mBlob.value + mBlob.length, 0, digestedLength - dataLength);

    mBlob.length = htonl(mBlob.length);

    if (isEncrypted()) {
        MD5(mBlob.digested, digestedLength, mBlob.digest);

        uint8_t vector[AES_BLOCK_SIZE];
        memcpy(vector, mBlob.vector, AES_BLOCK_SIZE);
        AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key, vector,
                        AES_ENCRYPT);
    }

    size_t headerLength = (mBlob.encrypted - (uint8_t*)&mBlob);
    size_t fileLength = encryptedLength + headerLength + mBlob.info;

    const char* tmpFileName = ".tmp";
    int out =
        TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
    if (out < 0) {
        ALOGW("could not open file: %s: %s", tmpFileName, strerror(errno));
        return ResponseCode::SYSTEM_ERROR;
    }
    size_t writtenBytes = writeFully(out, (uint8_t*)&mBlob, fileLength);
    if (close(out) != 0) {
        return ResponseCode::SYSTEM_ERROR;
    }
    if (writtenBytes != fileLength) {
        ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
        unlink(tmpFileName);
        return ResponseCode::SYSTEM_ERROR;
    }
    if (rename(tmpFileName, filename) == -1) {
        ALOGW("could not rename blob to %s: %s", filename, strerror(errno));
        return ResponseCode::SYSTEM_ERROR;
    }
    return ResponseCode::NO_ERROR;
}

ResponseCode Blob::readBlob(const char* filename, AES_KEY* aes_key, State state) {
    ALOGV("reading blob %s", filename);
    int in = TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
    if (in < 0) {
        return (errno == ENOENT) ? ResponseCode::KEY_NOT_FOUND : ResponseCode::SYSTEM_ERROR;
    }
    // fileLength may be less than sizeof(mBlob) since the in
    // memory version has extra padding to tolerate rounding up to
    // the AES_BLOCK_SIZE
    size_t fileLength = readFully(in, (uint8_t*)&mBlob, sizeof(mBlob));
    if (close(in) != 0) {
        return ResponseCode::SYSTEM_ERROR;
    }

    if (fileLength == 0) {
        return ResponseCode::VALUE_CORRUPTED;
    }

    if (isEncrypted() && (state != STATE_NO_ERROR)) {
        return ResponseCode::LOCKED;
    }

    size_t headerLength = (mBlob.encrypted - (uint8_t*)&mBlob);
    if (fileLength < headerLength) {
        return ResponseCode::VALUE_CORRUPTED;
    }

    ssize_t encryptedLength = fileLength - (headerLength + mBlob.info);
    if (encryptedLength < 0) {
        return ResponseCode::VALUE_CORRUPTED;
    }

    ssize_t digestedLength;
    if (isEncrypted()) {
        if (encryptedLength % AES_BLOCK_SIZE != 0) {
            return ResponseCode::VALUE_CORRUPTED;
        }

        AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key, mBlob.vector,
                        AES_DECRYPT);
        digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
        uint8_t computedDigest[MD5_DIGEST_LENGTH];
        MD5(mBlob.digested, digestedLength, computedDigest);
        if (memcmp(mBlob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
            return ResponseCode::VALUE_CORRUPTED;
        }
    } else {
        digestedLength = encryptedLength;
    }

    ssize_t maxValueLength = digestedLength - sizeof(mBlob.length);
    mBlob.length = ntohl(mBlob.length);
    if (mBlob.length < 0 || mBlob.length > maxValueLength) {
        return ResponseCode::VALUE_CORRUPTED;
    }
    if (mBlob.info != 0) {
        // move info from after padding to after data
        memmove(&mBlob.value[mBlob.length], &mBlob.value[maxValueLength], mBlob.info);
    }
    return ResponseCode::NO_ERROR;
}
