/*
 * QTest TPM utilities
 *
 * Copyright (c) 2018 IBM Corporation
 * Copyright (c) 2018 Red Hat, Inc.
 *
 * Authors:
 *   Stefan Berger <stefanb@linux.vnet.ibm.com>
 *   Marc-André Lureau <marcandre.lureau@redhat.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"
#include <glib/gstdio.h>

#include "hw/acpi/tpm.h"
#include "libqtest.h"
#include "tpm-util.h"
#include "qapi/qmp/qdict.h"

void tpm_util_crb_transfer(QTestState *s,
                           const unsigned char *req, size_t req_size,
                           unsigned char *rsp, size_t rsp_size)
{
    uint64_t caddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
    uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);

    qtest_writeb(s, TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL, 1);

    qtest_memwrite(s, caddr, req, req_size);

    uint32_t sts, start = 1;
    uint64_t end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
    qtest_writel(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_START, start);
    while (true) {
        start = qtest_readl(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_START);
        if ((start & 1) == 0) {
            break;
        }
        if (g_get_monotonic_time() >= end_time) {
            break;
        }
    };
    start = qtest_readl(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_START);
    g_assert_cmpint(start & 1, ==, 0);
    sts = qtest_readl(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_STS);
    g_assert_cmpint(sts & 1, ==, 0);

    qtest_memread(s, raddr, rsp, rsp_size);
}

void tpm_util_startup(QTestState *s, tx_func *tx)
{
    unsigned char buffer[1024];
    static const unsigned char tpm_startup[] =
        "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00";
    static const unsigned char tpm_startup_resp[] =
        "\x80\x01\x00\x00\x00\x0a\x00\x00\x00\x00";

    tx(s, tpm_startup, sizeof(tpm_startup), buffer, sizeof(buffer));

    g_assert_cmpmem(buffer, sizeof(tpm_startup_resp),
                    tpm_startup_resp, sizeof(tpm_startup_resp));
}

void tpm_util_pcrextend(QTestState *s, tx_func *tx)
{
    unsigned char buffer[1024];
    static const unsigned char tpm_pcrextend[] =
        "\x80\x02\x00\x00\x00\x41\x00\x00\x01\x82\x00\x00\x00\x0a\x00\x00"
        "\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00"
        "\x0b\x74\x65\x73\x74\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        "\x00";

    static const unsigned char tpm_pcrextend_resp[] =
        "\x80\x02\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        "\x01\x00\x00";

    tx(s, tpm_pcrextend, sizeof(tpm_pcrextend), buffer, sizeof(buffer));

    g_assert_cmpmem(buffer, sizeof(tpm_pcrextend_resp),
                    tpm_pcrextend_resp, sizeof(tpm_pcrextend_resp));
}

void tpm_util_pcrread(QTestState *s, tx_func *tx,
                      const unsigned char *exp_resp, size_t exp_resp_size)
{
    unsigned char buffer[1024];
    static const unsigned char tpm_pcrread[] =
        "\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b"
        "\x03\x00\x04\x00";

    tx(s, tpm_pcrread, sizeof(tpm_pcrread), buffer, sizeof(buffer));

    /* skip pcrUpdateCounter (14th byte) in comparison */
    g_assert(exp_resp_size >= 15);
    g_assert_cmpmem(buffer, 13, exp_resp, 13);
    g_assert_cmpmem(&buffer[14], exp_resp_size - 14,
                    &exp_resp[14], exp_resp_size - 14);
}

bool tpm_util_swtpm_has_tpm2(void)
{
    bool has_tpm2 = false;
    char *out = NULL;
    static const char *argv[] = {
        "swtpm", "socket", "--help", NULL
    };

    if (!g_spawn_sync(NULL /* working_dir */,
                      (char **)argv,
                      NULL /* envp */,
                      G_SPAWN_SEARCH_PATH,
                      NULL /* child_setup */,
                      NULL /* user_data */,
                      &out,
                      NULL /* err */,
                      NULL /* exit_status */,
                      NULL)) {
        return false;
    }

    if (strstr(out, "--tpm2")) {
        has_tpm2 = true;
    }

    g_free(out);
    return has_tpm2;
}

gboolean tpm_util_swtpm_start(const char *path, GPid *pid,
                              SocketAddress **addr, GError **error)
{
    char *swtpm_argv_tpmstate = g_strdup_printf("dir=%s", path);
    char *swtpm_argv_ctrl = g_strdup_printf("type=unixio,path=%s/sock",
                                            path);
    gchar *swtpm_argv[] = {
        g_strdup("swtpm"), g_strdup("socket"),
        g_strdup("--tpmstate"), swtpm_argv_tpmstate,
        g_strdup("--ctrl"), swtpm_argv_ctrl,
        g_strdup("--tpm2"),
        NULL
    };
    gboolean succ;
    unsigned i;

    *addr = g_new0(SocketAddress, 1);
    (*addr)->type = SOCKET_ADDRESS_TYPE_UNIX;
    (*addr)->u.q_unix.path = g_build_filename(path, "sock", NULL);

    succ = g_spawn_async(NULL, swtpm_argv, NULL, G_SPAWN_SEARCH_PATH,
                         NULL, NULL, pid, error);

    for (i = 0; swtpm_argv[i]; i++) {
        g_free(swtpm_argv[i]);
    }

    return succ;
}

void tpm_util_swtpm_kill(GPid pid)
{
    int n;

    if (!pid) {
        return;
    }

    g_spawn_close_pid(pid);

    n = kill(pid, 0);
    if (n < 0) {
        return;
    }

    kill(pid, SIGKILL);
}

void tpm_util_migrate(QTestState *who, const char *uri)
{
    QDict *rsp;

    rsp = qtest_qmp(who,
                    "{ 'execute': 'migrate', 'arguments': { 'uri': %s } }",
                    uri);
    g_assert(qdict_haskey(rsp, "return"));
    qobject_unref(rsp);
}

void tpm_util_wait_for_migration_complete(QTestState *who)
{
    while (true) {
        QDict *rsp;
        QDict *rsp_return;
        bool completed;
        const char *status;

        rsp = qtest_qmp(who, "{ 'execute': 'query-migrate' }");
        g_assert(qdict_haskey(rsp, "return"));
        rsp_return = qdict_get_qdict(rsp, "return");

        g_assert(!qdict_haskey(rsp_return, "error"));
        status = qdict_get_str(rsp_return, "status");
        completed = strcmp(status, "completed") == 0;
        g_assert_cmpstr(status, !=,  "failed");
        qobject_unref(rsp);
        if (completed) {
            return;
        }
        usleep(1000);
    }
}

void tpm_util_migration_start_qemu(QTestState **src_qemu,
                                   QTestState **dst_qemu,
                                   SocketAddress *src_tpm_addr,
                                   SocketAddress *dst_tpm_addr,
                                   const char *miguri,
                                   const char *ifmodel,
                                   const char *machine_options)
{
    char *src_qemu_args, *dst_qemu_args;

    src_qemu_args = g_strdup_printf(
        "%s "
        "-chardev socket,id=chr,path=%s "
        "-tpmdev emulator,id=dev,chardev=chr "
        "-device %s,tpmdev=dev ",
        machine_options ? : "", src_tpm_addr->u.q_unix.path, ifmodel);

    *src_qemu = qtest_init(src_qemu_args);

    dst_qemu_args = g_strdup_printf(
        "%s "
        "-chardev socket,id=chr,path=%s "
        "-tpmdev emulator,id=dev,chardev=chr "
        "-device %s,tpmdev=dev "
        "-incoming %s",
        machine_options ? : "",
        dst_tpm_addr->u.q_unix.path,
        ifmodel, miguri);

    *dst_qemu = qtest_init(dst_qemu_args);

    g_free(src_qemu_args);
    g_free(dst_qemu_args);
}

/* Remove directory with remainders of swtpm */
void tpm_util_rmdir(const char *path)
{
    char *filename;
    int ret;

    filename = g_strdup_printf("%s/tpm2-00.permall", path);
    g_unlink(filename);
    g_free(filename);

    filename = g_strdup_printf("%s/.lock", path);
    g_unlink(filename);
    g_free(filename);

    ret = g_rmdir(path);
    g_assert(!ret);
}
