xref: /openbmc/qemu/crypto/hmac-glib.c (revision e11680524afc6fb5b38e2a9e2e55c3c313ab8f97)
112a4f216SLongpeng(Mike) /*
212a4f216SLongpeng(Mike)  * QEMU Crypto hmac algorithms (based on glib)
312a4f216SLongpeng(Mike)  *
412a4f216SLongpeng(Mike)  * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
512a4f216SLongpeng(Mike)  *
612a4f216SLongpeng(Mike)  * Authors:
712a4f216SLongpeng(Mike)  *    Longpeng(Mike) <longpeng2@huawei.com>
812a4f216SLongpeng(Mike)  *
912a4f216SLongpeng(Mike)  * This work is licensed under the terms of the GNU GPL, version 2 or
1012a4f216SLongpeng(Mike)  * (at your option) any later version.  See the COPYING file in the
1112a4f216SLongpeng(Mike)  * top-level directory.
1212a4f216SLongpeng(Mike)  *
1312a4f216SLongpeng(Mike)  */
1412a4f216SLongpeng(Mike) 
1512a4f216SLongpeng(Mike) #include "qemu/osdep.h"
1612a4f216SLongpeng(Mike) #include "qapi/error.h"
1712a4f216SLongpeng(Mike) #include "crypto/hmac.h"
1812a4f216SLongpeng(Mike) 
19*e1168052SLongpeng(Mike) /* Support for HMAC Algos has been added in GLib 2.30 */
20*e1168052SLongpeng(Mike) #if GLIB_CHECK_VERSION(2, 30, 0)
21*e1168052SLongpeng(Mike) 
22*e1168052SLongpeng(Mike) static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
23*e1168052SLongpeng(Mike)     [QCRYPTO_HASH_ALG_MD5] = G_CHECKSUM_MD5,
24*e1168052SLongpeng(Mike)     [QCRYPTO_HASH_ALG_SHA1] = G_CHECKSUM_SHA1,
25*e1168052SLongpeng(Mike)     [QCRYPTO_HASH_ALG_SHA256] = G_CHECKSUM_SHA256,
26*e1168052SLongpeng(Mike) /* Support for HMAC SHA-512 in GLib 2.42 */
27*e1168052SLongpeng(Mike) #if GLIB_CHECK_VERSION(2, 42, 0)
28*e1168052SLongpeng(Mike)     [QCRYPTO_HASH_ALG_SHA512] = G_CHECKSUM_SHA512,
29*e1168052SLongpeng(Mike) #else
30*e1168052SLongpeng(Mike)     [QCRYPTO_HASH_ALG_SHA512] = -1,
31*e1168052SLongpeng(Mike) #endif
32*e1168052SLongpeng(Mike)     [QCRYPTO_HASH_ALG_SHA224] = -1,
33*e1168052SLongpeng(Mike)     [QCRYPTO_HASH_ALG_SHA384] = -1,
34*e1168052SLongpeng(Mike)     [QCRYPTO_HASH_ALG_RIPEMD160] = -1,
35*e1168052SLongpeng(Mike) };
36*e1168052SLongpeng(Mike) 
37*e1168052SLongpeng(Mike) typedef struct QCryptoHmacGlib QCryptoHmacGlib;
38*e1168052SLongpeng(Mike) struct QCryptoHmacGlib {
39*e1168052SLongpeng(Mike)     GHmac *ghmac;
40*e1168052SLongpeng(Mike) };
41*e1168052SLongpeng(Mike) 
42*e1168052SLongpeng(Mike) bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
43*e1168052SLongpeng(Mike) {
44*e1168052SLongpeng(Mike)     if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
45*e1168052SLongpeng(Mike)         qcrypto_hmac_alg_map[alg] != -1) {
46*e1168052SLongpeng(Mike)         return true;
47*e1168052SLongpeng(Mike)     }
48*e1168052SLongpeng(Mike) 
49*e1168052SLongpeng(Mike)     return false;
50*e1168052SLongpeng(Mike) }
51*e1168052SLongpeng(Mike) 
52*e1168052SLongpeng(Mike) QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
53*e1168052SLongpeng(Mike)                               const uint8_t *key, size_t nkey,
54*e1168052SLongpeng(Mike)                               Error **errp)
55*e1168052SLongpeng(Mike) {
56*e1168052SLongpeng(Mike)     QCryptoHmac *hmac;
57*e1168052SLongpeng(Mike)     QCryptoHmacGlib *ctx;
58*e1168052SLongpeng(Mike) 
59*e1168052SLongpeng(Mike)     if (!qcrypto_hmac_supports(alg)) {
60*e1168052SLongpeng(Mike)         error_setg(errp, "Unsupported hmac algorithm %s",
61*e1168052SLongpeng(Mike)                    QCryptoHashAlgorithm_lookup[alg]);
62*e1168052SLongpeng(Mike)         return NULL;
63*e1168052SLongpeng(Mike)     }
64*e1168052SLongpeng(Mike) 
65*e1168052SLongpeng(Mike)     hmac = g_new0(QCryptoHmac, 1);
66*e1168052SLongpeng(Mike)     hmac->alg = alg;
67*e1168052SLongpeng(Mike) 
68*e1168052SLongpeng(Mike)     ctx = g_new0(QCryptoHmacGlib, 1);
69*e1168052SLongpeng(Mike) 
70*e1168052SLongpeng(Mike)     ctx->ghmac = g_hmac_new(qcrypto_hmac_alg_map[alg],
71*e1168052SLongpeng(Mike)                             (const uint8_t *)key, nkey);
72*e1168052SLongpeng(Mike)     if (!ctx->ghmac) {
73*e1168052SLongpeng(Mike)         error_setg(errp, "Cannot initialize hmac and set key");
74*e1168052SLongpeng(Mike)         goto error;
75*e1168052SLongpeng(Mike)     }
76*e1168052SLongpeng(Mike) 
77*e1168052SLongpeng(Mike)     hmac->opaque = ctx;
78*e1168052SLongpeng(Mike)     return hmac;
79*e1168052SLongpeng(Mike) 
80*e1168052SLongpeng(Mike) error:
81*e1168052SLongpeng(Mike)     g_free(ctx);
82*e1168052SLongpeng(Mike)     g_free(hmac);
83*e1168052SLongpeng(Mike)     return NULL;
84*e1168052SLongpeng(Mike) }
85*e1168052SLongpeng(Mike) 
86*e1168052SLongpeng(Mike) void qcrypto_hmac_free(QCryptoHmac *hmac)
87*e1168052SLongpeng(Mike) {
88*e1168052SLongpeng(Mike)     QCryptoHmacGlib *ctx;
89*e1168052SLongpeng(Mike) 
90*e1168052SLongpeng(Mike)     if (!hmac) {
91*e1168052SLongpeng(Mike)         return;
92*e1168052SLongpeng(Mike)     }
93*e1168052SLongpeng(Mike) 
94*e1168052SLongpeng(Mike)     ctx = hmac->opaque;
95*e1168052SLongpeng(Mike)     g_hmac_unref(ctx->ghmac);
96*e1168052SLongpeng(Mike) 
97*e1168052SLongpeng(Mike)     g_free(ctx);
98*e1168052SLongpeng(Mike)     g_free(hmac);
99*e1168052SLongpeng(Mike) }
100*e1168052SLongpeng(Mike) 
101*e1168052SLongpeng(Mike) int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
102*e1168052SLongpeng(Mike)                         const struct iovec *iov,
103*e1168052SLongpeng(Mike)                         size_t niov,
104*e1168052SLongpeng(Mike)                         uint8_t **result,
105*e1168052SLongpeng(Mike)                         size_t *resultlen,
106*e1168052SLongpeng(Mike)                         Error **errp)
107*e1168052SLongpeng(Mike) {
108*e1168052SLongpeng(Mike)     QCryptoHmacGlib *ctx;
109*e1168052SLongpeng(Mike)     int i, ret;
110*e1168052SLongpeng(Mike) 
111*e1168052SLongpeng(Mike)     ctx = hmac->opaque;
112*e1168052SLongpeng(Mike) 
113*e1168052SLongpeng(Mike)     for (i = 0; i < niov; i++) {
114*e1168052SLongpeng(Mike)         g_hmac_update(ctx->ghmac, iov[i].iov_base, iov[i].iov_len);
115*e1168052SLongpeng(Mike)     }
116*e1168052SLongpeng(Mike) 
117*e1168052SLongpeng(Mike)     ret = g_checksum_type_get_length(qcrypto_hmac_alg_map[hmac->alg]);
118*e1168052SLongpeng(Mike)     if (ret < 0) {
119*e1168052SLongpeng(Mike)         error_setg(errp, "Unable to get hmac length");
120*e1168052SLongpeng(Mike)         return -1;
121*e1168052SLongpeng(Mike)     }
122*e1168052SLongpeng(Mike) 
123*e1168052SLongpeng(Mike)     if (*resultlen == 0) {
124*e1168052SLongpeng(Mike)         *resultlen = ret;
125*e1168052SLongpeng(Mike)         *result = g_new0(uint8_t, *resultlen);
126*e1168052SLongpeng(Mike)     } else if (*resultlen != ret) {
127*e1168052SLongpeng(Mike)         error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
128*e1168052SLongpeng(Mike)                    *resultlen, ret);
129*e1168052SLongpeng(Mike)         return -1;
130*e1168052SLongpeng(Mike)     }
131*e1168052SLongpeng(Mike) 
132*e1168052SLongpeng(Mike)     g_hmac_get_digest(ctx->ghmac, *result, resultlen);
133*e1168052SLongpeng(Mike) 
134*e1168052SLongpeng(Mike)     return 0;
135*e1168052SLongpeng(Mike) }
136*e1168052SLongpeng(Mike) 
137*e1168052SLongpeng(Mike) #else
138*e1168052SLongpeng(Mike) 
13912a4f216SLongpeng(Mike) bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
14012a4f216SLongpeng(Mike) {
14112a4f216SLongpeng(Mike)     return false;
14212a4f216SLongpeng(Mike) }
14312a4f216SLongpeng(Mike) 
14412a4f216SLongpeng(Mike) QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
14512a4f216SLongpeng(Mike)                               const uint8_t *key, size_t nkey,
14612a4f216SLongpeng(Mike)                               Error **errp)
14712a4f216SLongpeng(Mike) {
14812a4f216SLongpeng(Mike)     return NULL;
14912a4f216SLongpeng(Mike) }
15012a4f216SLongpeng(Mike) 
15112a4f216SLongpeng(Mike) void qcrypto_hmac_free(QCryptoHmac *hmac)
15212a4f216SLongpeng(Mike) {
15312a4f216SLongpeng(Mike)     return;
15412a4f216SLongpeng(Mike) }
15512a4f216SLongpeng(Mike) 
15612a4f216SLongpeng(Mike) int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
15712a4f216SLongpeng(Mike)                         const struct iovec *iov,
15812a4f216SLongpeng(Mike)                         size_t niov,
15912a4f216SLongpeng(Mike)                         uint8_t **result,
16012a4f216SLongpeng(Mike)                         size_t *resultlen,
16112a4f216SLongpeng(Mike)                         Error **errp)
16212a4f216SLongpeng(Mike) {
16312a4f216SLongpeng(Mike)     return -1;
16412a4f216SLongpeng(Mike) }
165*e1168052SLongpeng(Mike) 
166*e1168052SLongpeng(Mike) #endif
167