/*
 * Copyright (C) 2018 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.
 */

/**
 * This app tests the API in app/keymaster/secure_storage.h. To run this test,
 * include keymaster/storage_test in TRUSTY_ALL_USER_TASKS, and it will be start
 * once an RPMB proxy becomes available.
 *
 * Different application has different namespace, so this would not affect the
 * keymaster app's RPMB storage.
 */

#include <assert.h>
#include <malloc.h>
#include <stdio.h>
#ifndef __clang__
// We need to diable foritfy level for memset in gcc because we want to use
// memset unoptimized. This would falsely trigger __warn_memset_zero_len in
// /usr/include/bits/string3.h. The inline checking function is only supposed to
// work when the optimization level is at least 1. In android_keymaster_utils.h
// we would use memset unoptimized.
#pragma push_macro("__USE_FORTIFY_LEVEL")
#undef __USE_FORTIFY_LEVEL
#endif
#include <string.h>
#ifndef __clang__
#pragma pop_macro("__USE_FORTIFY_LEVEL")
#endif
#include <fstream>

#define typeof(x) __typeof__(x)
#include <trusty_unittest.h>

extern "C" {
#include <libatap/atap_util.h>
}

#include <keymaster/android_keymaster_utils.h>
#include "secure_storage_manager.h"

#define DATA_SIZE 2048
#define CHAIN_LENGTH 3

#define TLOG_TAG "km_storage_test"

using keymaster::AttestationKeySlot;
using keymaster::CertificateChain;
using keymaster::kAttestationUuidSize;
using keymaster::KeymasterKeyBlob;
using keymaster::kProductIdSize;
using keymaster::SecureStorageManager;

uint8_t* NewRandBuf(size_t size) {
    uint8_t* buf = new uint8_t[size];
    if (buf == nullptr) {
        return buf;
    }
    for (uint8_t* i = buf;
         reinterpret_cast<size_t>(i) < reinterpret_cast<size_t>(buf) + size;
         i++) {
        *i = static_cast<uint8_t>(rand() % UINT8_MAX);
    }
    return buf;
}

void TestKeyStorage(AttestationKeySlot key_slot) {
    keymaster_error_t error = KM_ERROR_OK;
    keymaster::UniquePtr<uint8_t[]> write_key;
    KeymasterKeyBlob key_blob;
    bool key_exists = false;

    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    ASSERT_NE(nullptr, ss_manager);

    write_key.reset(NewRandBuf(DATA_SIZE));
    ASSERT_NE(nullptr, write_key.get());

    error = ss_manager->WriteKeyToStorage(key_slot, write_key.get(), DATA_SIZE);
    ASSERT_EQ(KM_ERROR_OK, error);

    key_blob = ss_manager->ReadKeyFromStorage(key_slot, &error);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(DATA_SIZE, key_blob.key_material_size);
    ASSERT_NE(nullptr, write_key.get());
    ASSERT_EQ(0, memcmp(write_key.get(), key_blob.writable_data(), DATA_SIZE));

    error = ss_manager->AttestationKeyExists(key_slot, &key_exists);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(true, key_exists);

test_abort:;
}

void TestCertChainStorage(AttestationKeySlot key_slot, bool chain_exists) {
    keymaster_error_t error = KM_ERROR_OK;
    keymaster::UniquePtr<uint8_t[]> write_cert[CHAIN_LENGTH];
    unsigned int i = 0;
    uint32_t cert_chain_length;
    CertificateChain chain;

    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    ASSERT_NE(nullptr, ss_manager);

    for (i = 0; i < CHAIN_LENGTH; ++i) {
        write_cert[i].reset(NewRandBuf(DATA_SIZE));
        ASSERT_NE(nullptr, write_cert[i].get());

        error = ss_manager->WriteCertToStorage(key_slot, write_cert[i].get(),
                                               DATA_SIZE, i);
        ASSERT_EQ(KM_ERROR_OK, error);

        error = ss_manager->ReadCertChainLength(key_slot, &cert_chain_length);
        ASSERT_EQ(KM_ERROR_OK, error);
        if (chain_exists) {
            ASSERT_EQ(3, cert_chain_length);
        } else {
            ASSERT_EQ(i + 1, cert_chain_length);
        }
    }

    error = ss_manager->ReadCertChainFromStorage(key_slot, &chain);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(CHAIN_LENGTH, chain.entry_count);
    for (i = 0; i < CHAIN_LENGTH; ++i) {
        ASSERT_EQ(DATA_SIZE, chain.entries[i].data_length);
        ASSERT_EQ(0, memcmp(write_cert[i].get(), chain.entries[i].data,
                            DATA_SIZE));
    }

    error = ss_manager->DeleteCertChainFromStorage(key_slot);
    ASSERT_EQ(KM_ERROR_OK, error);
    chain.Clear();
    error = ss_manager->ReadCertChainFromStorage(key_slot, &chain);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(0, chain.entry_count);

test_abort:;
}

void TestAtapCertChainStorage(AttestationKeySlot key_slot, bool chain_exists) {
    keymaster_error_t error = KM_ERROR_OK;
    keymaster::UniquePtr<uint8_t[]> write_cert[CHAIN_LENGTH];
    keymaster::UniquePtr<uint8_t[]> write_key;
    KeymasterKeyBlob key_blob;
    bool key_exists = false;
    uint32_t cert_chain_length;
    AtapCertChain read_chain;
    AtapCertChain write_chain;
    memset(&read_chain, 0, sizeof(AtapCertChain));
    memset(&write_chain, 0, sizeof(AtapCertChain));

    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    ASSERT_NE(nullptr, ss_manager);
    write_chain.entry_count = CHAIN_LENGTH;

    for (size_t i = 0; i < CHAIN_LENGTH; ++i) {
        write_cert[i].reset(NewRandBuf(DATA_SIZE));
        ASSERT_NE(nullptr, write_cert[i].get());
        write_chain.entries[i].data_length = DATA_SIZE;
        write_chain.entries[i].data =
                reinterpret_cast<uint8_t*>(atap_malloc(DATA_SIZE));
        ASSERT_NE(nullptr, write_chain.entries[i].data);
        memcpy(write_chain.entries[i].data, write_cert[i].get(), DATA_SIZE);
    }
    write_key.reset(NewRandBuf(DATA_SIZE));
    ASSERT_NE(nullptr, write_key.get());
    error = ss_manager->WriteAtapKeyAndCertsToStorage(key_slot, write_key.get(),
                                                      DATA_SIZE, &write_chain);
    ASSERT_EQ(KM_ERROR_OK, error);

    error = ss_manager->ReadCertChainLength(key_slot, &cert_chain_length);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(3, cert_chain_length);

    memset(&read_chain, 0, sizeof(AtapCertChain));
    error = ss_manager->ReadAtapCertChainFromStorage(key_slot, &read_chain);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(CHAIN_LENGTH, read_chain.entry_count);
    for (size_t i = 0; i < CHAIN_LENGTH; ++i) {
        ASSERT_EQ(DATA_SIZE, read_chain.entries[i].data_length);
        ASSERT_EQ(0, memcmp(write_cert[i].get(), read_chain.entries[i].data,
                            DATA_SIZE));
    }
    key_blob = ss_manager->ReadKeyFromStorage(key_slot, &error);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(DATA_SIZE, key_blob.key_material_size);
    ASSERT_NE(nullptr, write_key.get());
    ASSERT_EQ(0, memcmp(write_key.get(), key_blob.writable_data(), DATA_SIZE));

    error = ss_manager->AttestationKeyExists(key_slot, &key_exists);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(true, key_exists);

test_abort:
    free_cert_chain(read_chain);
    free_cert_chain(write_chain);
}

void TestCertStorageInvalid(AttestationKeySlot key_slot) {
    keymaster_error_t error = KM_ERROR_OK;
    keymaster::UniquePtr<uint8_t[]> write_cert;
    uint32_t cert_chain_length;

    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    ASSERT_NE(nullptr, ss_manager);

    // Clear existing certificate chain
    error = ss_manager->DeleteKey(key_slot, true);
    ASSERT_EQ(KM_ERROR_OK, error);
    error = ss_manager->ReadCertChainLength(key_slot, &cert_chain_length);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(0, cert_chain_length);

    // Try to write to index (chain_length + 1)
    write_cert.reset(NewRandBuf(DATA_SIZE));
    ASSERT_NE(nullptr, write_cert.get());
    error = ss_manager->WriteCertToStorage(key_slot, write_cert.get(),
                                           DATA_SIZE, 1);
    ASSERT_EQ(KM_ERROR_INVALID_ARGUMENT, error);

    // Verify that cert chain length didn't change
    error = ss_manager->ReadCertChainLength(key_slot, &cert_chain_length);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(0, cert_chain_length);

test_abort:;
}

void DeleteAttestationData() {
    keymaster_error_t error = KM_ERROR_OK;
    uint32_t cert_chain_length;
    bool key_exists;

    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    ASSERT_NE(nullptr, ss_manager);

    error = ss_manager->DeleteAllAttestationData();
    ASSERT_EQ(KM_ERROR_OK, error);

    error = ss_manager->ReadCertChainLength(AttestationKeySlot::kRsa,
                                            &cert_chain_length);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(0, cert_chain_length);
    error = ss_manager->ReadCertChainLength(AttestationKeySlot::kEcdsa,
                                            &cert_chain_length);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(0, cert_chain_length);

    error = ss_manager->AttestationKeyExists(AttestationKeySlot::kRsa,
                                             &key_exists);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(false, key_exists);
    error = ss_manager->AttestationKeyExists(AttestationKeySlot::kEcdsa,
                                             &key_exists);
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_EQ(false, key_exists);

test_abort:;
}

void TestUuidStorage() {
    keymaster_error_t error = KM_ERROR_OK;
    keymaster::UniquePtr<uint8_t[]> write_uuid;
    keymaster::UniquePtr<uint8_t[]> read_uuid(
            new uint8_t[kAttestationUuidSize]);

    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    ASSERT_NE(nullptr, ss_manager);

    error = ss_manager->DeleteAttestationUuid();
    ASSERT_EQ(KM_ERROR_OK, error);

    write_uuid.reset(NewRandBuf(kAttestationUuidSize));
    ASSERT_NE(nullptr, write_uuid.get());

    error = ss_manager->WriteAttestationUuid((const uint8_t*)write_uuid.get());
    ASSERT_EQ(KM_ERROR_OK, error);

    error = ss_manager->ReadAttestationUuid(read_uuid.get());
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_NE(nullptr, read_uuid.get());
    ASSERT_EQ(0, memcmp(write_uuid.get(), read_uuid.get(), kProductIdSize));

    error = ss_manager->DeleteAttestationUuid();
    ASSERT_EQ(KM_ERROR_OK, error);

test_abort:;
}

void TestProductIdStorage() {
    keymaster_error_t error = KM_ERROR_OK;
    keymaster::UniquePtr<uint8_t[]> write_productid;
    keymaster::UniquePtr<uint8_t[]> read_productid(new uint8_t[kProductIdSize]);

    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    ASSERT_NE(nullptr, ss_manager);

    error = ss_manager->DeleteProductId();
    ASSERT_EQ(KM_ERROR_OK, error);

    write_productid.reset(NewRandBuf(kProductIdSize));
    ASSERT_NE(nullptr, write_productid.get());

    error = ss_manager->SetProductId((const uint8_t*)write_productid.get());
    ASSERT_EQ(KM_ERROR_OK, error);

    error = ss_manager->ReadProductId(read_productid.get());
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_NE(nullptr, read_productid.get());
    ASSERT_EQ(0, memcmp(write_productid.get(), read_productid.get(),
                        kProductIdSize));

    error = ss_manager->DeleteProductId();
    ASSERT_EQ(KM_ERROR_OK, error);

test_abort:;
}

void TestProductIdStoragePreventOverwrite() {
    keymaster_error_t error = KM_ERROR_OK;
    keymaster::UniquePtr<uint8_t[]> write_productid;
    keymaster::UniquePtr<uint8_t[]> overwrite_productid;
    keymaster::UniquePtr<uint8_t[]> read_productid(new uint8_t[kProductIdSize]);

    SecureStorageManager* ss_manager = SecureStorageManager::get_instance();
    ASSERT_NE(nullptr, ss_manager);

    error = ss_manager->DeleteProductId();
    ASSERT_EQ(KM_ERROR_OK, error);

    write_productid.reset(NewRandBuf(kProductIdSize));
    ASSERT_NE(nullptr, write_productid.get());

    error = ss_manager->SetProductId((const uint8_t*)write_productid.get());
    ASSERT_EQ(KM_ERROR_OK, error);

    overwrite_productid.reset(NewRandBuf(kProductIdSize));
    error = ss_manager->SetProductId((const uint8_t*)write_productid.get());
    ASSERT_EQ(KM_ERROR_INVALID_ARGUMENT, error);

    error = ss_manager->ReadProductId(read_productid.get());
    ASSERT_EQ(KM_ERROR_OK, error);
    ASSERT_NE(nullptr, read_productid.get());
    ASSERT_EQ(0, memcmp(write_productid.get(), read_productid.get(),
                        kProductIdSize));

    error = ss_manager->DeleteProductId();
    ASSERT_EQ(KM_ERROR_OK, error);

test_abort:;
}

#if defined(KEYMASTER_LEGACY_FORMAT)
// Test to verify backward compatibility.
void TestFormatChange() {
    keymaster_error_t error = KM_ERROR_OK;
    keymaster::UniquePtr<uint8_t[]> write_key[2];
    KeymasterKeyBlob key_blob;
    bool key_exists = false;
    AttestationKeySlot key_slots[] = {AttestationKeySlot::kRsa,
                                      AttestationKeySlot::kEcdsa};
    keymaster::UniquePtr<uint8_t[]> write_cert[2][CHAIN_LENGTH];
    CertificateChain chain;

    SecureStorageManager* ss_manager =
            SecureStorageManager::get_instance(false);
    ASSERT_NE(nullptr, ss_manager);

    // Write the key and cert in old format.
    for (size_t i = 0; i < 2; i++) {
        AttestationKeySlot key_slot = key_slots[i];
        write_key[i].reset(NewRandBuf(DATA_SIZE));
        ASSERT_NE(nullptr, write_key[i].get());
        error = ss_manager->LegacyWriteKeyToStorage(
                key_slot, write_key[i].get(), DATA_SIZE);
        ASSERT_EQ(KM_ERROR_OK, error);

        for (int index = 0; index < CHAIN_LENGTH; index++) {
            write_cert[i][index].reset(NewRandBuf(DATA_SIZE));
            ASSERT_NE(nullptr, write_cert[i][index].get());

            error = ss_manager->LegacyWriteCertToStorage(
                    key_slot, write_cert[i][index].get(), DATA_SIZE, index);
            ASSERT_EQ(KM_ERROR_OK, error);
        }
    }

    // Try to translate the format.
    ss_manager = SecureStorageManager::get_instance();
    ASSERT_NE(nullptr, ss_manager);

    // Read key and cert out using new format.
    for (size_t i = 0; i < 2; i++) {
        AttestationKeySlot key_slot = key_slots[i];
        key_blob = ss_manager->ReadKeyFromStorage(key_slot, &error);
        ASSERT_EQ(KM_ERROR_OK, error);
        ASSERT_EQ(DATA_SIZE, key_blob.key_material_size);
        ASSERT_NE(nullptr, write_key[i].get());
        ASSERT_EQ(0, memcmp(write_key[i].get(), key_blob.writable_data(),
                            DATA_SIZE));

        error = ss_manager->AttestationKeyExists(key_slot, &key_exists);
        ASSERT_EQ(KM_ERROR_OK, error);
        ASSERT_EQ(true, key_exists);
        uint32_t cert_chain_length;
        error = ss_manager->ReadCertChainLength(key_slot, &cert_chain_length);
        ASSERT_EQ(KM_ERROR_OK, error);
        ASSERT_EQ(CHAIN_LENGTH, cert_chain_length);

        chain.Clear();
        error = ss_manager->ReadCertChainFromStorage(key_slot, &chain);
        ASSERT_EQ(KM_ERROR_OK, error);
        ASSERT_EQ(CHAIN_LENGTH, chain.entry_count);

        for (int index = 0; index < CHAIN_LENGTH; index++) {
            ASSERT_EQ(DATA_SIZE, chain.entries[i].data_length);
            ASSERT_EQ(0, memcmp(write_cert[i][index].get(),
                                chain.entries[index].data, DATA_SIZE));
        }
    }

    DeleteAttestationData();
    ss_manager->DeleteProductId();
    ss_manager->DeleteAttestationUuid();

test_abort:;
}
#endif

#if defined(KEYMASTER_LEGACY_FORMAT)
TEST(KeymasterFormatChangeTest, TestFormatChange) {
    TestFormatChange();
}
#endif

typedef struct {
} KeymasterTest_t;

static void KeymasterTest_SetUp(KeymasterTest_t* state) {
    DeleteAttestationData();
}

static void KeymasterTest_TearDown(KeymasterTest_t* state) {
    DeleteAttestationData();
}

TEST_F(KeymasterTest, TestKeyStorageRsa) {
    TestKeyStorage(AttestationKeySlot::kRsa);
}

TEST_F(KeymasterTest, TestKeyStorageEcdsa) {
    TestKeyStorage(AttestationKeySlot::kEcdsa);
}

TEST_F(KeymasterTest, TestCertChainStorageRsa) {
    TestCertChainStorage(AttestationKeySlot::kRsa, false);
    TestAtapCertChainStorage(AttestationKeySlot::kRsa, false);
}

TEST_F(KeymasterTest, TestCertChainStorageEcdsa) {
    TestCertChainStorage(AttestationKeySlot::kEcdsa, false);
    TestAtapCertChainStorage(AttestationKeySlot::kEcdsa, false);
}

TEST_F(KeymasterTest, TestRewriteKey) {
    TestKeyStorage(AttestationKeySlot::kRsa);
    // Rewriting keys should work
    TestKeyStorage(AttestationKeySlot::kRsa);
}

TEST_F(KeymasterTest, TestRewriteChain) {
    TestCertChainStorage(AttestationKeySlot::kRsa, false);
    TestAtapCertChainStorage(AttestationKeySlot::kRsa, false);
    TestCertChainStorage(AttestationKeySlot::kRsa, true);
}

TEST_F(KeymasterTest, TestCertStorageInvalid) {
    TestCertStorageInvalid(AttestationKeySlot::kRsa);
}

TEST_F(KeymasterTest, TestUuidStorage) {
    TestUuidStorage();
}

TEST_F(KeymasterTest, TestProductIdStorage) {
    TestProductIdStorage();
}

#ifndef KEYMASTER_DEBUG
TEST_F(KeymasterTest, TestProductIdStoragePreventOverwrite) {
    TestProductIdStoragePreventOverwrite();
}
#endif

int main(void) {
    bool passed1 = RUN_ALL_SUITE_TESTS("KeymasterFormatChangeTest");
    bool passed2 = RUN_ALL_SUITE_TESTS("KeymasterTest");
    return (passed1 && passed2) ? 0 : 1;
}
