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-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
     21typedef void (*qcrypto_nettle_hmac_setkey)(void *ctx,
     22                                           size_t key_length,
     23                                           const uint8_t *key);
     24
     25typedef void (*qcrypto_nettle_hmac_update)(void *ctx,
     26                                           size_t length,
     27                                           const uint8_t *data);
     28
     29typedef void (*qcrypto_nettle_hmac_digest)(void *ctx,
     30                                           size_t length,
     31                                           uint8_t *digest);
     32
     33typedef struct QCryptoHmacNettle QCryptoHmacNettle;
     34struct 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
     44struct 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
     94bool 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
    104void *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
    123static void
    124qcrypto_nettle_hmac_ctx_free(QCryptoHmac *hmac)
    125{
    126    QCryptoHmacNettle *ctx;
    127
    128    ctx = hmac->opaque;
    129    g_free(ctx);
    130}
    131
    132static int
    133qcrypto_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
    171QCryptoHmacDriver qcrypto_hmac_lib_driver = {
    172    .hmac_bytesv = qcrypto_nettle_hmac_bytesv,
    173    .hmac_free = qcrypto_nettle_hmac_ctx_free,
    174};