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.1 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 "crypto/hash.h"
  23#include "hashpriv.h"
  24
  25static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
  26    [QCRYPTO_HASH_ALG_MD5] = 16,
  27    [QCRYPTO_HASH_ALG_SHA1] = 20,
  28    [QCRYPTO_HASH_ALG_SHA224] = 28,
  29    [QCRYPTO_HASH_ALG_SHA256] = 32,
  30    [QCRYPTO_HASH_ALG_SHA384] = 48,
  31    [QCRYPTO_HASH_ALG_SHA512] = 64,
  32    [QCRYPTO_HASH_ALG_RIPEMD160] = 20,
  33};
  34
  35size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
  36{
  37    assert(alg < G_N_ELEMENTS(qcrypto_hash_alg_size));
  38    return qcrypto_hash_alg_size[alg];
  39}
  40
  41int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
  42                        const struct iovec *iov,
  43                        size_t niov,
  44                        uint8_t **result,
  45                        size_t *resultlen,
  46                        Error **errp)
  47{
  48#ifdef CONFIG_AF_ALG
  49    int ret;
  50    /*
  51     * TODO:
  52     * Maybe we should treat some afalg errors as fatal
  53     */
  54    ret = qcrypto_hash_afalg_driver.hash_bytesv(alg, iov, niov,
  55                                                result, resultlen,
  56                                                NULL);
  57    if (ret == 0) {
  58        return ret;
  59    }
  60#endif
  61
  62    return qcrypto_hash_lib_driver.hash_bytesv(alg, iov, niov,
  63                                               result, resultlen,
  64                                               errp);
  65}
  66
  67
  68int qcrypto_hash_bytes(QCryptoHashAlgorithm alg,
  69                       const char *buf,
  70                       size_t len,
  71                       uint8_t **result,
  72                       size_t *resultlen,
  73                       Error **errp)
  74{
  75    struct iovec iov = { .iov_base = (char *)buf,
  76                         .iov_len = len };
  77    return qcrypto_hash_bytesv(alg, &iov, 1, result, resultlen, errp);
  78}
  79
  80static const char hex[] = "0123456789abcdef";
  81
  82int qcrypto_hash_digestv(QCryptoHashAlgorithm alg,
  83                         const struct iovec *iov,
  84                         size_t niov,
  85                         char **digest,
  86                         Error **errp)
  87{
  88    uint8_t *result = NULL;
  89    size_t resultlen = 0;
  90    size_t i;
  91
  92    if (qcrypto_hash_bytesv(alg, iov, niov, &result, &resultlen, errp) < 0) {
  93        return -1;
  94    }
  95
  96    *digest = g_new0(char, (resultlen * 2) + 1);
  97    for (i = 0 ; i < resultlen ; i++) {
  98        (*digest)[(i * 2)] = hex[(result[i] >> 4) & 0xf];
  99        (*digest)[(i * 2) + 1] = hex[result[i] & 0xf];
 100    }
 101    (*digest)[resultlen * 2] = '\0';
 102    g_free(result);
 103    return 0;
 104}
 105
 106int qcrypto_hash_digest(QCryptoHashAlgorithm alg,
 107                        const char *buf,
 108                        size_t len,
 109                        char **digest,
 110                        Error **errp)
 111{
 112    struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
 113
 114    return qcrypto_hash_digestv(alg, &iov, 1, digest, errp);
 115}
 116
 117int qcrypto_hash_base64v(QCryptoHashAlgorithm alg,
 118                         const struct iovec *iov,
 119                         size_t niov,
 120                         char **base64,
 121                         Error **errp)
 122{
 123    uint8_t *result = NULL;
 124    size_t resultlen = 0;
 125
 126    if (qcrypto_hash_bytesv(alg, iov, niov, &result, &resultlen, errp) < 0) {
 127        return -1;
 128    }
 129
 130    *base64 = g_base64_encode(result, resultlen);
 131    g_free(result);
 132    return 0;
 133}
 134
 135int qcrypto_hash_base64(QCryptoHashAlgorithm alg,
 136                        const char *buf,
 137                        size_t len,
 138                        char **base64,
 139                        Error **errp)
 140{
 141    struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
 142
 143    return qcrypto_hash_base64v(alg, &iov, 1, base64, errp);
 144}
 145