~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to crypto/hmac-gcrypt.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

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