/*
 * QEMU crypto TLS Pre-Shared Keys (PSK) support
 *
 * Copyright (c) 2018 Red Hat, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "qemu/osdep.h"
#include "crypto/tlscredspsk.h"
#include "tlscredspriv.h"
#include "qapi/error.h"
#include "qemu/module.h"
#include "qom/object_interfaces.h"
#include "trace.h"


struct QCryptoTLSCredsPSK {
    QCryptoTLSCreds parent_obj;
    char *username;
};

#ifdef CONFIG_GNUTLS

#include <gnutls/gnutls.h>

static int
lookup_key(const char *pskfile, const char *username, gnutls_datum_t *key,
           Error **errp)
{
    const size_t ulen = strlen(username);
    GError *gerr = NULL;
    char *content = NULL;
    char **lines = NULL;
    size_t clen = 0, i;
    int ret = -1;

    if (!g_file_get_contents(pskfile, &content, &clen, &gerr)) {
        error_setg(errp, "Cannot read PSK file %s: %s",
                   pskfile, gerr->message);
        g_error_free(gerr);
        return -1;
    }

    lines = g_strsplit(content, "\n", -1);
    for (i = 0; lines[i] != NULL; ++i) {
        if (strncmp(lines[i], username, ulen) == 0 && lines[i][ulen] == ':') {
            key->data = (unsigned char *) g_strdup(&lines[i][ulen + 1]);
            key->size = strlen(lines[i]) - ulen - 1;
            ret = 0;
            goto out;
        }
    }
    error_setg(errp, "Username %s not found in PSK file %s",
               username, pskfile);

 out:
    free(content);
    g_strfreev(lines);
    return ret;
}

static int
qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
                           Error **errp)
{
    g_autoptr(QCryptoTLSCredsBox) box = NULL;
    g_autofree char *pskfile = NULL;
    g_autofree char *dhparams = NULL;
    const char *username;
    int ret;
    int rv = -1;
    gnutls_datum_t key = { .data = NULL };

    trace_qcrypto_tls_creds_psk_load(creds,
            creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");

    if (!creds->parent_obj.dir) {
        error_setg(errp, "Missing 'dir' property value");
        goto cleanup;
    }

    if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
        box = qcrypto_tls_creds_box_new_server(GNUTLS_CRD_PSK);

        if (creds->username) {
            error_setg(errp, "username should not be set when endpoint=server");
            goto cleanup;
        }

        if (qcrypto_tls_creds_get_path(&creds->parent_obj,
                                       QCRYPTO_TLS_CREDS_DH_PARAMS,
                                       false, &dhparams, errp) < 0 ||
            qcrypto_tls_creds_get_path(&creds->parent_obj,
                                       QCRYPTO_TLS_CREDS_PSKFILE,
                                       true, &pskfile, errp) < 0) {
            goto cleanup;
        }

        ret = gnutls_psk_allocate_server_credentials(&box->data.pskserver);
        if (ret < 0) {
            error_setg(errp, "Cannot allocate credentials: %s",
                       gnutls_strerror(ret));
            goto cleanup;
        }

        if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
                                                 &box->dh_params,
                                                 errp) < 0) {
            goto cleanup;
        }

        ret = gnutls_psk_set_server_credentials_file(box->data.pskserver,
                                                     pskfile);
        if (ret < 0) {
            error_setg(errp, "Cannot set PSK server credentials: %s",
                       gnutls_strerror(ret));
            goto cleanup;
        }
        if (box->dh_params) {
            gnutls_psk_set_server_dh_params(box->data.pskserver,
                                            box->dh_params);
        }
    } else {
        box = qcrypto_tls_creds_box_new_client(GNUTLS_CRD_PSK);

        if (qcrypto_tls_creds_get_path(&creds->parent_obj,
                                       QCRYPTO_TLS_CREDS_PSKFILE,
                                       true, &pskfile, errp) < 0) {
            goto cleanup;
        }

        if (creds->username) {
            username = creds->username;
        } else {
            username = "qemu";
        }
        if (lookup_key(pskfile, username, &key, errp) != 0) {
            goto cleanup;
        }

        ret = gnutls_psk_allocate_client_credentials(&box->data.pskclient);
        if (ret < 0) {
            error_setg(errp, "Cannot allocate credentials: %s",
                       gnutls_strerror(ret));
            goto cleanup;
        }

        ret = gnutls_psk_set_client_credentials(box->data.pskclient,
                                                username, &key, GNUTLS_PSK_KEY_HEX);
        if (ret < 0) {
            error_setg(errp, "Cannot set PSK client credentials: %s",
                       gnutls_strerror(ret));
            goto cleanup;
        }
    }
    creds->parent_obj.box = g_steal_pointer(&box);

    rv = 0;
 cleanup:
    g_free(key.data);
    return rv;
}

#else /* ! CONFIG_GNUTLS */


static void
qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds G_GNUC_UNUSED,
                           Error **errp)
{
    error_setg(errp, "TLS credentials support requires GNUTLS");
}


#endif /* ! CONFIG_GNUTLS */


static void
qcrypto_tls_creds_psk_complete(UserCreatable *uc, Error **errp)
{
    QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(uc);

    qcrypto_tls_creds_psk_load(creds, errp);
}


static void
qcrypto_tls_creds_psk_finalize(Object *obj)
{
    QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj);

    g_free(creds->username);
}

static void
qcrypto_tls_creds_psk_prop_set_username(Object *obj,
                                        const char *value,
                                        Error **errp G_GNUC_UNUSED)
{
    QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj);

    creds->username = g_strdup(value);
}


static char *
qcrypto_tls_creds_psk_prop_get_username(Object *obj,
                                        Error **errp G_GNUC_UNUSED)
{
    QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj);

    return g_strdup(creds->username);
}

static void
qcrypto_tls_creds_psk_class_init(ObjectClass *oc, const void *data)
{
    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
    QCryptoTLSCredsClass *tcc = QCRYPTO_TLS_CREDS_CLASS(oc);

    ucc->complete = qcrypto_tls_creds_psk_complete;
    tcc->prioritySuffix = "+ECDHE-PSK:+DHE-PSK:+PSK";

    object_class_property_add_str(oc, "username",
                                  qcrypto_tls_creds_psk_prop_get_username,
                                  qcrypto_tls_creds_psk_prop_set_username);
}


static const TypeInfo qcrypto_tls_creds_psk_info = {
    .parent = TYPE_QCRYPTO_TLS_CREDS,
    .name = TYPE_QCRYPTO_TLS_CREDS_PSK,
    .instance_size = sizeof(QCryptoTLSCredsPSK),
    .instance_finalize = qcrypto_tls_creds_psk_finalize,
    .class_size = sizeof(QCryptoTLSCredsPSKClass),
    .class_init = qcrypto_tls_creds_psk_class_init,
    .interfaces = (const InterfaceInfo[]) {
        { TYPE_USER_CREATABLE },
        { }
    }
};


static void
qcrypto_tls_creds_psk_register_types(void)
{
    type_register_static(&qcrypto_tls_creds_psk_info);
}


type_init(qcrypto_tls_creds_psk_register_types);
