/*
 * QEMU Crypto hash algorithms
 *
 * Copyright (c) 2016 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 <gcrypt.h>
#include "qapi/error.h"
#include "crypto/hash.h"
#include "hashpriv.h"


static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
    [QCRYPTO_HASH_ALG_MD5] = GCRY_MD_MD5,
    [QCRYPTO_HASH_ALG_SHA1] = GCRY_MD_SHA1,
    [QCRYPTO_HASH_ALG_SHA224] = GCRY_MD_SHA224,
    [QCRYPTO_HASH_ALG_SHA256] = GCRY_MD_SHA256,
    [QCRYPTO_HASH_ALG_SHA384] = GCRY_MD_SHA384,
    [QCRYPTO_HASH_ALG_SHA512] = GCRY_MD_SHA512,
    [QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MD_RMD160,
};

gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
{
    if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) &&
        qcrypto_hash_alg_map[alg] != GCRY_MD_NONE) {
        return true;
    }
    return false;
}


static int
qcrypto_gcrypt_hash_bytesv(QCryptoHashAlgorithm alg,
                           const struct iovec *iov,
                           size_t niov,
                           uint8_t **result,
                           size_t *resultlen,
                           Error **errp)
{
    int i, ret;
    gcry_md_hd_t md;
    unsigned char *digest;

    if (!qcrypto_hash_supports(alg)) {
        error_setg(errp,
                   "Unknown hash algorithm %d",
                   alg);
        return -1;
    }

    ret = gcry_md_open(&md, qcrypto_hash_alg_map[alg], 0);

    if (ret < 0) {
        error_setg(errp,
                   "Unable to initialize hash algorithm: %s",
                   gcry_strerror(ret));
        return -1;
    }

    for (i = 0; i < niov; i++) {
        gcry_md_write(md, iov[i].iov_base, iov[i].iov_len);
    }

    ret = gcry_md_get_algo_dlen(qcrypto_hash_alg_map[alg]);
    if (ret <= 0) {
        error_setg(errp,
                   "Unable to get hash length: %s",
                   gcry_strerror(ret));
        goto error;
    }
    if (*resultlen == 0) {
        *resultlen = ret;
        *result = g_new0(uint8_t, *resultlen);
    } else if (*resultlen != ret) {
        error_setg(errp,
                   "Result buffer size %zu is smaller than hash %d",
                   *resultlen, ret);
        goto error;
    }

    digest = gcry_md_read(md, 0);
    if (!digest) {
        error_setg(errp,
                   "No digest produced");
        goto error;
    }
    memcpy(*result, digest, *resultlen);

    gcry_md_close(md);
    return 0;

 error:
    gcry_md_close(md);
    return -1;
}


QCryptoHashDriver qcrypto_hash_lib_driver = {
    .hash_bytesv = qcrypto_gcrypt_hash_bytesv,
};
