qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

hash-gnutls.c (3084B)


      1 /*
      2  * QEMU Crypto hash algorithms
      3  *
      4  * Copyright (c) 2021 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 <gnutls/crypto.h>
     23 #include "qapi/error.h"
     24 #include "crypto/hash.h"
     25 #include "hashpriv.h"
     26 
     27 
     28 static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
     29     [QCRYPTO_HASH_ALG_MD5] = GNUTLS_DIG_MD5,
     30     [QCRYPTO_HASH_ALG_SHA1] = GNUTLS_DIG_SHA1,
     31     [QCRYPTO_HASH_ALG_SHA224] = GNUTLS_DIG_SHA224,
     32     [QCRYPTO_HASH_ALG_SHA256] = GNUTLS_DIG_SHA256,
     33     [QCRYPTO_HASH_ALG_SHA384] = GNUTLS_DIG_SHA384,
     34     [QCRYPTO_HASH_ALG_SHA512] = GNUTLS_DIG_SHA512,
     35     [QCRYPTO_HASH_ALG_RIPEMD160] = GNUTLS_DIG_RMD160,
     36 };
     37 
     38 gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
     39 {
     40     size_t i;
     41     const gnutls_digest_algorithm_t *algs;
     42     if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_map) ||
     43         qcrypto_hash_alg_map[alg] == GNUTLS_DIG_UNKNOWN) {
     44         return false;
     45     }
     46     algs = gnutls_digest_list();
     47     for (i = 0; algs[i] != GNUTLS_DIG_UNKNOWN; i++) {
     48         if (algs[i] == qcrypto_hash_alg_map[alg]) {
     49             return true;
     50         }
     51     }
     52     return false;
     53 }
     54 
     55 
     56 static int
     57 qcrypto_gnutls_hash_bytesv(QCryptoHashAlgorithm alg,
     58                            const struct iovec *iov,
     59                            size_t niov,
     60                            uint8_t **result,
     61                            size_t *resultlen,
     62                            Error **errp)
     63 {
     64     int i, ret;
     65     gnutls_hash_hd_t hash;
     66 
     67     if (!qcrypto_hash_supports(alg)) {
     68         error_setg(errp,
     69                    "Unknown hash algorithm %d",
     70                    alg);
     71         return -1;
     72     }
     73 
     74     ret = gnutls_hash_get_len(qcrypto_hash_alg_map[alg]);
     75     if (*resultlen == 0) {
     76         *resultlen = ret;
     77         *result = g_new0(uint8_t, *resultlen);
     78     } else if (*resultlen != ret) {
     79         error_setg(errp,
     80                    "Result buffer size %zu is smaller than hash %d",
     81                    *resultlen, ret);
     82         return -1;
     83     }
     84 
     85     ret = gnutls_hash_init(&hash, qcrypto_hash_alg_map[alg]);
     86     if (ret < 0) {
     87         error_setg(errp,
     88                    "Unable to initialize hash algorithm: %s",
     89                    gnutls_strerror(ret));
     90         return -1;
     91     }
     92 
     93     for (i = 0; i < niov; i++) {
     94         gnutls_hash(hash, iov[i].iov_base, iov[i].iov_len);
     95     }
     96 
     97     gnutls_hash_deinit(hash, *result);
     98     return 0;
     99 }
    100 
    101 
    102 QCryptoHashDriver qcrypto_hash_lib_driver = {
    103     .hash_bytesv = qcrypto_gnutls_hash_bytesv,
    104 };