qemu/crypto/hash.c
<<
>>
Prefs
   1/*
   2 * QEMU Crypto hash algorithms
   3 *
   4 * Copyright (c) 2015 Red Hat, Inc.
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 *
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "qapi/error.h"
  23#include "crypto/hash.h"
  24#include "hashpriv.h"
  25
  26static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
  27    [QCRYPTO_HASH_ALG_MD5] = 16,
  28    [QCRYPTO_HASH_ALG_SHA1] = 20,
  29    [QCRYPTO_HASH_ALG_SHA224] = 28,
  30    [QCRYPTO_HASH_ALG_SHA256] = 32,
  31    [QCRYPTO_HASH_ALG_SHA384] = 48,
  32    [QCRYPTO_HASH_ALG_SHA512] = 64,
  33    [QCRYPTO_HASH_ALG_RIPEMD160] = 20,
  34};
  35
  36size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
  37{
  38    assert(alg < G_N_ELEMENTS(qcrypto_hash_alg_size));
  39    return qcrypto_hash_alg_size[alg];
  40}
  41
  42int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
  43                        const struct iovec *iov,
  44                        size_t niov,
  45                        uint8_t **result,
  46                        size_t *resultlen,
  47                        Error **errp)
  48{
  49#ifdef CONFIG_AF_ALG
  50    int ret;
  51    /*
  52     * TODO:
  53     * Maybe we should treat some afalg errors as fatal
  54     */
  55    ret = qcrypto_hash_afalg_driver.hash_bytesv(alg, iov, niov,
  56                                                result, resultlen,
  57                                                NULL);
  58    if (ret == 0) {
  59        return ret;
  60    }
  61#endif
  62
  63    return qcrypto_hash_lib_driver.hash_bytesv(alg, iov, niov,
  64                                               result, resultlen,
  65                                               errp);
  66}
  67
  68
  69int qcrypto_hash_bytes(QCryptoHashAlgorithm alg,
  70                       const char *buf,
  71                       size_t len,
  72                       uint8_t **result,
  73                       size_t *resultlen,
  74                       Error **errp)
  75{
  76    struct iovec iov = { .iov_base = (char *)buf,
  77                         .iov_len = len };
  78    return qcrypto_hash_bytesv(alg, &iov, 1, result, resultlen, errp);
  79}
  80
  81static const char hex[] = "0123456789abcdef";
  82
  83int qcrypto_hash_digestv(QCryptoHashAlgorithm alg,
  84                         const struct iovec *iov,
  85                         size_t niov,
  86                         char **digest,
  87                         Error **errp)
  88{
  89    uint8_t *result = NULL;
  90    size_t resultlen = 0;
  91    size_t i;
  92
  93    if (qcrypto_hash_bytesv(alg, iov, niov, &result, &resultlen, errp) < 0) {
  94        return -1;
  95    }
  96
  97    *digest = g_new0(char, (resultlen * 2) + 1);
  98    for (i = 0 ; i < resultlen ; i++) {
  99        (*digest)[(i * 2)] = hex[(result[i] >> 4) & 0xf];
 100        (*digest)[(i * 2) + 1] = hex[result[i] & 0xf];
 101    }
 102    (*digest)[resultlen * 2] = '\0';
 103    g_free(result);
 104    return 0;
 105}
 106
 107int qcrypto_hash_digest(QCryptoHashAlgorithm alg,
 108                        const char *buf,
 109                        size_t len,
 110                        char **digest,
 111                        Error **errp)
 112{
 113    struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
 114
 115    return qcrypto_hash_digestv(alg, &iov, 1, digest, errp);
 116}
 117
 118int qcrypto_hash_base64v(QCryptoHashAlgorithm alg,
 119                         const struct iovec *iov,
 120                         size_t niov,
 121                         char **base64,
 122                         Error **errp)
 123{
 124    uint8_t *result = NULL;
 125    size_t resultlen = 0;
 126
 127    if (qcrypto_hash_bytesv(alg, iov, niov, &result, &resultlen, errp) < 0) {
 128        return -1;
 129    }
 130
 131    *base64 = g_base64_encode(result, resultlen);
 132    g_free(result);
 133    return 0;
 134}
 135
 136int qcrypto_hash_base64(QCryptoHashAlgorithm alg,
 137                        const char *buf,
 138                        size_t len,
 139                        char **base64,
 140                        Error **errp)
 141{
 142    struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
 143
 144    return qcrypto_hash_base64v(alg, &iov, 1, base64, errp);
 145}
 146