cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

hmac-gcrypt.c (3883B)


      1/*
      2 * QEMU Crypto hmac algorithms (based on libgcrypt)
      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 <gcrypt.h>
     20
     21static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
     22    [QCRYPTO_HASH_ALG_MD5] = GCRY_MAC_HMAC_MD5,
     23    [QCRYPTO_HASH_ALG_SHA1] = GCRY_MAC_HMAC_SHA1,
     24    [QCRYPTO_HASH_ALG_SHA224] = GCRY_MAC_HMAC_SHA224,
     25    [QCRYPTO_HASH_ALG_SHA256] = GCRY_MAC_HMAC_SHA256,
     26    [QCRYPTO_HASH_ALG_SHA384] = GCRY_MAC_HMAC_SHA384,
     27    [QCRYPTO_HASH_ALG_SHA512] = GCRY_MAC_HMAC_SHA512,
     28    [QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MAC_HMAC_RMD160,
     29};
     30
     31typedef struct QCryptoHmacGcrypt QCryptoHmacGcrypt;
     32struct QCryptoHmacGcrypt {
     33    gcry_mac_hd_t handle;
     34};
     35
     36bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
     37{
     38    if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
     39        qcrypto_hmac_alg_map[alg] != GCRY_MAC_NONE) {
     40        return true;
     41    }
     42
     43    return false;
     44}
     45
     46void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
     47                           const uint8_t *key, size_t nkey,
     48                           Error **errp)
     49{
     50    QCryptoHmacGcrypt *ctx;
     51    gcry_error_t err;
     52
     53    if (!qcrypto_hmac_supports(alg)) {
     54        error_setg(errp, "Unsupported hmac algorithm %s",
     55                   QCryptoHashAlgorithm_str(alg));
     56        return NULL;
     57    }
     58
     59    ctx = g_new0(QCryptoHmacGcrypt, 1);
     60
     61    err = gcry_mac_open(&ctx->handle, qcrypto_hmac_alg_map[alg],
     62                        GCRY_MAC_FLAG_SECURE, NULL);
     63    if (err != 0) {
     64        error_setg(errp, "Cannot initialize hmac: %s",
     65                   gcry_strerror(err));
     66        goto error;
     67    }
     68
     69    err = gcry_mac_setkey(ctx->handle, (const void *)key, nkey);
     70    if (err != 0) {
     71        error_setg(errp, "Cannot set key: %s",
     72                   gcry_strerror(err));
     73        gcry_mac_close(ctx->handle);
     74        goto error;
     75    }
     76
     77    return ctx;
     78
     79error:
     80    g_free(ctx);
     81    return NULL;
     82}
     83
     84static void
     85qcrypto_gcrypt_hmac_ctx_free(QCryptoHmac *hmac)
     86{
     87    QCryptoHmacGcrypt *ctx;
     88
     89    ctx = hmac->opaque;
     90    gcry_mac_close(ctx->handle);
     91
     92    g_free(ctx);
     93}
     94
     95static int
     96qcrypto_gcrypt_hmac_bytesv(QCryptoHmac *hmac,
     97                           const struct iovec *iov,
     98                           size_t niov,
     99                           uint8_t **result,
    100                           size_t *resultlen,
    101                           Error **errp)
    102{
    103    QCryptoHmacGcrypt *ctx;
    104    gcry_error_t err;
    105    uint32_t ret;
    106    int i;
    107
    108    ctx = hmac->opaque;
    109
    110    for (i = 0; i < niov; i++) {
    111        gcry_mac_write(ctx->handle, iov[i].iov_base, iov[i].iov_len);
    112    }
    113
    114    ret = gcry_mac_get_algo_maclen(qcrypto_hmac_alg_map[hmac->alg]);
    115    if (ret <= 0) {
    116        error_setg(errp, "Unable to get hmac length: %s",
    117                   gcry_strerror(ret));
    118        return -1;
    119    }
    120
    121    if (*resultlen == 0) {
    122        *resultlen = ret;
    123        *result = g_new0(uint8_t, *resultlen);
    124    } else if (*resultlen != ret) {
    125        error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
    126                   *resultlen, ret);
    127        return -1;
    128    }
    129
    130    err = gcry_mac_read(ctx->handle, *result, resultlen);
    131    if (err != 0) {
    132        error_setg(errp, "Cannot get result: %s",
    133                   gcry_strerror(err));
    134        return -1;
    135    }
    136
    137    err = gcry_mac_reset(ctx->handle);
    138    if (err != 0) {
    139        error_setg(errp, "Cannot reset hmac context: %s",
    140                   gcry_strerror(err));
    141        return -1;
    142    }
    143
    144    return 0;
    145}
    146
    147QCryptoHmacDriver qcrypto_hmac_lib_driver = {
    148    .hmac_bytesv = qcrypto_gcrypt_hmac_bytesv,
    149    .hmac_free = qcrypto_gcrypt_hmac_ctx_free,
    150};