qemu

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

hash-nettle.c (5149B)


      1 /*
      2  * QEMU Crypto hash algorithms
      3  *
      4  * Copyright (c) 2016 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 "qapi/error.h"
     23 #include "crypto/hash.h"
     24 #include "hashpriv.h"
     25 #include <nettle/md5.h>
     26 #include <nettle/sha.h>
     27 #include <nettle/ripemd160.h>
     28 
     29 typedef void (*qcrypto_nettle_init)(void *ctx);
     30 typedef void (*qcrypto_nettle_write)(void *ctx,
     31                                      size_t len,
     32                                      const uint8_t *buf);
     33 typedef void (*qcrypto_nettle_result)(void *ctx,
     34                                       size_t len,
     35                                       uint8_t *buf);
     36 
     37 union qcrypto_hash_ctx {
     38     struct md5_ctx md5;
     39     struct sha1_ctx sha1;
     40     struct sha224_ctx sha224;
     41     struct sha256_ctx sha256;
     42     struct sha384_ctx sha384;
     43     struct sha512_ctx sha512;
     44     struct ripemd160_ctx ripemd160;
     45 };
     46 
     47 struct qcrypto_hash_alg {
     48     qcrypto_nettle_init init;
     49     qcrypto_nettle_write write;
     50     qcrypto_nettle_result result;
     51     size_t len;
     52 } qcrypto_hash_alg_map[] = {
     53     [QCRYPTO_HASH_ALG_MD5] = {
     54         .init = (qcrypto_nettle_init)md5_init,
     55         .write = (qcrypto_nettle_write)md5_update,
     56         .result = (qcrypto_nettle_result)md5_digest,
     57         .len = MD5_DIGEST_SIZE,
     58     },
     59     [QCRYPTO_HASH_ALG_SHA1] = {
     60         .init = (qcrypto_nettle_init)sha1_init,
     61         .write = (qcrypto_nettle_write)sha1_update,
     62         .result = (qcrypto_nettle_result)sha1_digest,
     63         .len = SHA1_DIGEST_SIZE,
     64     },
     65     [QCRYPTO_HASH_ALG_SHA224] = {
     66         .init = (qcrypto_nettle_init)sha224_init,
     67         .write = (qcrypto_nettle_write)sha224_update,
     68         .result = (qcrypto_nettle_result)sha224_digest,
     69         .len = SHA224_DIGEST_SIZE,
     70     },
     71     [QCRYPTO_HASH_ALG_SHA256] = {
     72         .init = (qcrypto_nettle_init)sha256_init,
     73         .write = (qcrypto_nettle_write)sha256_update,
     74         .result = (qcrypto_nettle_result)sha256_digest,
     75         .len = SHA256_DIGEST_SIZE,
     76     },
     77     [QCRYPTO_HASH_ALG_SHA384] = {
     78         .init = (qcrypto_nettle_init)sha384_init,
     79         .write = (qcrypto_nettle_write)sha384_update,
     80         .result = (qcrypto_nettle_result)sha384_digest,
     81         .len = SHA384_DIGEST_SIZE,
     82     },
     83     [QCRYPTO_HASH_ALG_SHA512] = {
     84         .init = (qcrypto_nettle_init)sha512_init,
     85         .write = (qcrypto_nettle_write)sha512_update,
     86         .result = (qcrypto_nettle_result)sha512_digest,
     87         .len = SHA512_DIGEST_SIZE,
     88     },
     89     [QCRYPTO_HASH_ALG_RIPEMD160] = {
     90         .init = (qcrypto_nettle_init)ripemd160_init,
     91         .write = (qcrypto_nettle_write)ripemd160_update,
     92         .result = (qcrypto_nettle_result)ripemd160_digest,
     93         .len = RIPEMD160_DIGEST_SIZE,
     94     },
     95 };
     96 
     97 gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
     98 {
     99     if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) &&
    100         qcrypto_hash_alg_map[alg].init != NULL) {
    101         return true;
    102     }
    103     return false;
    104 }
    105 
    106 
    107 static int
    108 qcrypto_nettle_hash_bytesv(QCryptoHashAlgorithm alg,
    109                            const struct iovec *iov,
    110                            size_t niov,
    111                            uint8_t **result,
    112                            size_t *resultlen,
    113                            Error **errp)
    114 {
    115     size_t i;
    116     union qcrypto_hash_ctx ctx;
    117 
    118     if (!qcrypto_hash_supports(alg)) {
    119         error_setg(errp,
    120                    "Unknown hash algorithm %d",
    121                    alg);
    122         return -1;
    123     }
    124 
    125     qcrypto_hash_alg_map[alg].init(&ctx);
    126 
    127     for (i = 0; i < niov; i++) {
    128         /* Some versions of nettle have functions
    129          * declared with 'int' instead of 'size_t'
    130          * so to be safe avoid writing more than
    131          * UINT_MAX bytes at a time
    132          */
    133         size_t len = iov[i].iov_len;
    134         uint8_t *base = iov[i].iov_base;
    135         while (len) {
    136             size_t shortlen = MIN(len, UINT_MAX);
    137             qcrypto_hash_alg_map[alg].write(&ctx, len, base);
    138             len -= shortlen;
    139             base += len;
    140         }
    141     }
    142 
    143     if (*resultlen == 0) {
    144         *resultlen = qcrypto_hash_alg_map[alg].len;
    145         *result = g_new0(uint8_t, *resultlen);
    146     } else if (*resultlen != qcrypto_hash_alg_map[alg].len) {
    147         error_setg(errp,
    148                    "Result buffer size %zu is smaller than hash %zu",
    149                    *resultlen, qcrypto_hash_alg_map[alg].len);
    150         return -1;
    151     }
    152 
    153     qcrypto_hash_alg_map[alg].result(&ctx, *resultlen, *result);
    154 
    155     return 0;
    156 }
    157 
    158 
    159 QCryptoHashDriver qcrypto_hash_lib_driver = {
    160     .hash_bytesv = qcrypto_nettle_hash_bytesv,
    161 };