qemu

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

hmac-glib.c (3046B)


      1 /*
      2  * QEMU Crypto hmac algorithms (based on glib)
      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 
     20 static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
     21     [QCRYPTO_HASH_ALG_MD5] = G_CHECKSUM_MD5,
     22     [QCRYPTO_HASH_ALG_SHA1] = G_CHECKSUM_SHA1,
     23     [QCRYPTO_HASH_ALG_SHA256] = G_CHECKSUM_SHA256,
     24     [QCRYPTO_HASH_ALG_SHA512] = G_CHECKSUM_SHA512,
     25     [QCRYPTO_HASH_ALG_SHA224] = -1,
     26     [QCRYPTO_HASH_ALG_SHA384] = -1,
     27     [QCRYPTO_HASH_ALG_RIPEMD160] = -1,
     28 };
     29 
     30 typedef struct QCryptoHmacGlib QCryptoHmacGlib;
     31 struct QCryptoHmacGlib {
     32     GHmac *ghmac;
     33 };
     34 
     35 bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
     36 {
     37     if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
     38         qcrypto_hmac_alg_map[alg] != -1) {
     39         return true;
     40     }
     41 
     42     return false;
     43 }
     44 
     45 void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
     46                            const uint8_t *key, size_t nkey,
     47                            Error **errp)
     48 {
     49     QCryptoHmacGlib *ctx;
     50 
     51     if (!qcrypto_hmac_supports(alg)) {
     52         error_setg(errp, "Unsupported hmac algorithm %s",
     53                    QCryptoHashAlgorithm_str(alg));
     54         return NULL;
     55     }
     56 
     57     ctx = g_new0(QCryptoHmacGlib, 1);
     58 
     59     ctx->ghmac = g_hmac_new(qcrypto_hmac_alg_map[alg],
     60                             (const uint8_t *)key, nkey);
     61     if (!ctx->ghmac) {
     62         error_setg(errp, "Cannot initialize hmac and set key");
     63         goto error;
     64     }
     65 
     66     return ctx;
     67 
     68 error:
     69     g_free(ctx);
     70     return NULL;
     71 }
     72 
     73 static void
     74 qcrypto_glib_hmac_ctx_free(QCryptoHmac *hmac)
     75 {
     76     QCryptoHmacGlib *ctx;
     77 
     78     ctx = hmac->opaque;
     79     g_hmac_unref(ctx->ghmac);
     80 
     81     g_free(ctx);
     82 }
     83 
     84 static int
     85 qcrypto_glib_hmac_bytesv(QCryptoHmac *hmac,
     86                          const struct iovec *iov,
     87                          size_t niov,
     88                          uint8_t **result,
     89                          size_t *resultlen,
     90                          Error **errp)
     91 {
     92     QCryptoHmacGlib *ctx;
     93     int i, ret;
     94 
     95     ctx = hmac->opaque;
     96 
     97     for (i = 0; i < niov; i++) {
     98         g_hmac_update(ctx->ghmac, iov[i].iov_base, iov[i].iov_len);
     99     }
    100 
    101     ret = g_checksum_type_get_length(qcrypto_hmac_alg_map[hmac->alg]);
    102     if (ret < 0) {
    103         error_setg(errp, "Unable to get hmac length");
    104         return -1;
    105     }
    106 
    107     if (*resultlen == 0) {
    108         *resultlen = ret;
    109         *result = g_new0(uint8_t, *resultlen);
    110     } else if (*resultlen != ret) {
    111         error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
    112                    *resultlen, ret);
    113         return -1;
    114     }
    115 
    116     g_hmac_get_digest(ctx->ghmac, *result, resultlen);
    117 
    118     return 0;
    119 }
    120 
    121 QCryptoHmacDriver qcrypto_hmac_lib_driver = {
    122     .hmac_bytesv = qcrypto_glib_hmac_bytesv,
    123     .hmac_free = qcrypto_glib_hmac_ctx_free,
    124 };