qemu

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

hmac-nettle.c (5671B)


      1 /*
      2  * QEMU Crypto hmac algorithms (based on nettle)
      3  *
      4  * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
      5  *
      6  * Authors:
      7  *    Longpeng(Mike) <longpeng2@huawei.com>
      8  *
      9  * This work is licensed under the terms of the GNU GPL, version 2 or
     10  * (at your option) any later version.  See the COPYING file in the
     11  * top-level directory.
     12  *
     13  */
     14 
     15 #include "qemu/osdep.h"
     16 #include "qapi/error.h"
     17 #include "crypto/hmac.h"
     18 #include "hmacpriv.h"
     19 #include <nettle/hmac.h>
     20 
     21 typedef void (*qcrypto_nettle_hmac_setkey)(void *ctx,
     22                                            size_t key_length,
     23                                            const uint8_t *key);
     24 
     25 typedef void (*qcrypto_nettle_hmac_update)(void *ctx,
     26                                            size_t length,
     27                                            const uint8_t *data);
     28 
     29 typedef void (*qcrypto_nettle_hmac_digest)(void *ctx,
     30                                            size_t length,
     31                                            uint8_t *digest);
     32 
     33 typedef struct QCryptoHmacNettle QCryptoHmacNettle;
     34 struct QCryptoHmacNettle {
     35     union qcrypto_nettle_hmac_ctx {
     36         struct hmac_md5_ctx md5_ctx;
     37         struct hmac_sha1_ctx sha1_ctx;
     38         struct hmac_sha256_ctx sha256_ctx; /* equals hmac_sha224_ctx */
     39         struct hmac_sha512_ctx sha512_ctx; /* equals hmac_sha384_ctx */
     40         struct hmac_ripemd160_ctx ripemd160_ctx;
     41     } u;
     42 };
     43 
     44 struct qcrypto_nettle_hmac_alg {
     45     qcrypto_nettle_hmac_setkey setkey;
     46     qcrypto_nettle_hmac_update update;
     47     qcrypto_nettle_hmac_digest digest;
     48     size_t len;
     49 } qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
     50     [QCRYPTO_HASH_ALG_MD5] = {
     51         .setkey = (qcrypto_nettle_hmac_setkey)hmac_md5_set_key,
     52         .update = (qcrypto_nettle_hmac_update)hmac_md5_update,
     53         .digest = (qcrypto_nettle_hmac_digest)hmac_md5_digest,
     54         .len = MD5_DIGEST_SIZE,
     55     },
     56     [QCRYPTO_HASH_ALG_SHA1] = {
     57         .setkey = (qcrypto_nettle_hmac_setkey)hmac_sha1_set_key,
     58         .update = (qcrypto_nettle_hmac_update)hmac_sha1_update,
     59         .digest = (qcrypto_nettle_hmac_digest)hmac_sha1_digest,
     60         .len = SHA1_DIGEST_SIZE,
     61     },
     62     [QCRYPTO_HASH_ALG_SHA224] = {
     63         .setkey = (qcrypto_nettle_hmac_setkey)hmac_sha224_set_key,
     64         .update = (qcrypto_nettle_hmac_update)hmac_sha224_update,
     65         .digest = (qcrypto_nettle_hmac_digest)hmac_sha224_digest,
     66         .len = SHA224_DIGEST_SIZE,
     67     },
     68     [QCRYPTO_HASH_ALG_SHA256] = {
     69         .setkey = (qcrypto_nettle_hmac_setkey)hmac_sha256_set_key,
     70         .update = (qcrypto_nettle_hmac_update)hmac_sha256_update,
     71         .digest = (qcrypto_nettle_hmac_digest)hmac_sha256_digest,
     72         .len = SHA256_DIGEST_SIZE,
     73     },
     74     [QCRYPTO_HASH_ALG_SHA384] = {
     75         .setkey = (qcrypto_nettle_hmac_setkey)hmac_sha384_set_key,
     76         .update = (qcrypto_nettle_hmac_update)hmac_sha384_update,
     77         .digest = (qcrypto_nettle_hmac_digest)hmac_sha384_digest,
     78         .len = SHA384_DIGEST_SIZE,
     79     },
     80     [QCRYPTO_HASH_ALG_SHA512] = {
     81         .setkey = (qcrypto_nettle_hmac_setkey)hmac_sha512_set_key,
     82         .update = (qcrypto_nettle_hmac_update)hmac_sha512_update,
     83         .digest = (qcrypto_nettle_hmac_digest)hmac_sha512_digest,
     84         .len = SHA512_DIGEST_SIZE,
     85     },
     86     [QCRYPTO_HASH_ALG_RIPEMD160] = {
     87         .setkey = (qcrypto_nettle_hmac_setkey)hmac_ripemd160_set_key,
     88         .update = (qcrypto_nettle_hmac_update)hmac_ripemd160_update,
     89         .digest = (qcrypto_nettle_hmac_digest)hmac_ripemd160_digest,
     90         .len = RIPEMD160_DIGEST_SIZE,
     91     },
     92 };
     93 
     94 bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
     95 {
     96     if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
     97         qcrypto_hmac_alg_map[alg].setkey != NULL) {
     98         return true;
     99     }
    100 
    101     return false;
    102 }
    103 
    104 void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
    105                            const uint8_t *key, size_t nkey,
    106                            Error **errp)
    107 {
    108     QCryptoHmacNettle *ctx;
    109 
    110     if (!qcrypto_hmac_supports(alg)) {
    111         error_setg(errp, "Unsupported hmac algorithm %s",
    112                    QCryptoHashAlgorithm_str(alg));
    113         return NULL;
    114     }
    115 
    116     ctx = g_new0(QCryptoHmacNettle, 1);
    117 
    118     qcrypto_hmac_alg_map[alg].setkey(&ctx->u, nkey, key);
    119 
    120     return ctx;
    121 }
    122 
    123 static void
    124 qcrypto_nettle_hmac_ctx_free(QCryptoHmac *hmac)
    125 {
    126     QCryptoHmacNettle *ctx;
    127 
    128     ctx = hmac->opaque;
    129     g_free(ctx);
    130 }
    131 
    132 static int
    133 qcrypto_nettle_hmac_bytesv(QCryptoHmac *hmac,
    134                            const struct iovec *iov,
    135                            size_t niov,
    136                            uint8_t **result,
    137                            size_t *resultlen,
    138                            Error **errp)
    139 {
    140     QCryptoHmacNettle *ctx;
    141     size_t i;
    142 
    143     ctx = (QCryptoHmacNettle *)hmac->opaque;
    144 
    145     for (i = 0; i < niov; ++i) {
    146         size_t len = iov[i].iov_len;
    147         uint8_t *base = iov[i].iov_base;
    148         while (len) {
    149             size_t shortlen = MIN(len, UINT_MAX);
    150             qcrypto_hmac_alg_map[hmac->alg].update(&ctx->u, len, base);
    151             len -= shortlen;
    152             base += len;
    153         }
    154     }
    155 
    156     if (*resultlen == 0) {
    157         *resultlen = qcrypto_hmac_alg_map[hmac->alg].len;
    158         *result = g_new0(uint8_t, *resultlen);
    159     } else if (*resultlen != qcrypto_hmac_alg_map[hmac->alg].len) {
    160         error_setg(errp,
    161                    "Result buffer size %zu is smaller than hash %zu",
    162                    *resultlen, qcrypto_hmac_alg_map[hmac->alg].len);
    163         return -1;
    164     }
    165 
    166     qcrypto_hmac_alg_map[hmac->alg].digest(&ctx->u, *resultlen, *result);
    167 
    168     return 0;
    169 }
    170 
    171 QCryptoHmacDriver qcrypto_hmac_lib_driver = {
    172     .hmac_bytesv = qcrypto_nettle_hmac_bytesv,
    173     .hmac_free = qcrypto_nettle_hmac_ctx_free,
    174 };