qemu

Форк
0
/
hmac-gnutls.c 
139 строк · 3.5 Кб
1
/*
2
 * QEMU Crypto hmac algorithms
3
 *
4
 * Copyright (c) 2021 Red Hat, Inc.
5
 *
6
 * Derived from hmac-gcrypt.c:
7
 *
8
 *   Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
9
 *
10
 * This work is licensed under the terms of the GNU GPL, version 2 or
11
 * (at your option) any later version.  See the COPYING file in the
12
 * top-level directory.
13
 *
14
 */
15

16
#include "qemu/osdep.h"
17
#include <gnutls/crypto.h>
18

19
#include "qapi/error.h"
20
#include "crypto/hmac.h"
21
#include "hmacpriv.h"
22

23
static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
24
    [QCRYPTO_HASH_ALG_MD5] = GNUTLS_MAC_MD5,
25
    [QCRYPTO_HASH_ALG_SHA1] = GNUTLS_MAC_SHA1,
26
    [QCRYPTO_HASH_ALG_SHA224] = GNUTLS_MAC_SHA224,
27
    [QCRYPTO_HASH_ALG_SHA256] = GNUTLS_MAC_SHA256,
28
    [QCRYPTO_HASH_ALG_SHA384] = GNUTLS_MAC_SHA384,
29
    [QCRYPTO_HASH_ALG_SHA512] = GNUTLS_MAC_SHA512,
30
    [QCRYPTO_HASH_ALG_RIPEMD160] = GNUTLS_MAC_RMD160,
31
};
32

33
typedef struct QCryptoHmacGnutls QCryptoHmacGnutls;
34
struct QCryptoHmacGnutls {
35
    gnutls_hmac_hd_t handle;
36
};
37

38
bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
39
{
40
    size_t i;
41
    const gnutls_digest_algorithm_t *algs;
42
    if (alg >= G_N_ELEMENTS(qcrypto_hmac_alg_map) ||
43
        qcrypto_hmac_alg_map[alg] == GNUTLS_DIG_UNKNOWN) {
44
        return false;
45
    }
46
    algs = gnutls_digest_list();
47
    for (i = 0; algs[i] != GNUTLS_DIG_UNKNOWN; i++) {
48
        if (algs[i] == qcrypto_hmac_alg_map[alg]) {
49
            return true;
50
        }
51
    }
52
    return false;
53
}
54

55
void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
56
                           const uint8_t *key, size_t nkey,
57
                           Error **errp)
58
{
59
    QCryptoHmacGnutls *ctx;
60
    int err;
61

62
    if (!qcrypto_hmac_supports(alg)) {
63
        error_setg(errp, "Unsupported hmac algorithm %s",
64
                   QCryptoHashAlgorithm_str(alg));
65
        return NULL;
66
    }
67

68
    ctx = g_new0(QCryptoHmacGnutls, 1);
69

70
    err = gnutls_hmac_init(&ctx->handle,
71
                           qcrypto_hmac_alg_map[alg],
72
                           (const void *)key, nkey);
73
    if (err != 0) {
74
        error_setg(errp, "Cannot initialize hmac: %s",
75
                   gnutls_strerror(err));
76
        goto error;
77
    }
78

79
    return ctx;
80

81
error:
82
    g_free(ctx);
83
    return NULL;
84
}
85

86
static void
87
qcrypto_gnutls_hmac_ctx_free(QCryptoHmac *hmac)
88
{
89
    QCryptoHmacGnutls *ctx;
90

91
    ctx = hmac->opaque;
92
    gnutls_hmac_deinit(ctx->handle, NULL);
93

94
    g_free(ctx);
95
}
96

97
static int
98
qcrypto_gnutls_hmac_bytesv(QCryptoHmac *hmac,
99
                           const struct iovec *iov,
100
                           size_t niov,
101
                           uint8_t **result,
102
                           size_t *resultlen,
103
                           Error **errp)
104
{
105
    QCryptoHmacGnutls *ctx;
106
    uint32_t ret;
107
    int i;
108

109
    ctx = hmac->opaque;
110

111
    for (i = 0; i < niov; i++) {
112
        gnutls_hmac(ctx->handle, iov[i].iov_base, iov[i].iov_len);
113
    }
114

115
    ret = gnutls_hmac_get_len(qcrypto_hmac_alg_map[hmac->alg]);
116
    if (ret <= 0) {
117
        error_setg(errp, "Unable to get hmac length: %s",
118
                   gnutls_strerror(ret));
119
        return -1;
120
    }
121

122
    if (*resultlen == 0) {
123
        *resultlen = ret;
124
        *result = g_new0(uint8_t, *resultlen);
125
    } else if (*resultlen != ret) {
126
        error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
127
                   *resultlen, ret);
128
        return -1;
129
    }
130

131
    gnutls_hmac_output(ctx->handle, *result);
132

133
    return 0;
134
}
135

136
QCryptoHmacDriver qcrypto_hmac_lib_driver = {
137
    .hmac_bytesv = qcrypto_gnutls_hmac_bytesv,
138
    .hmac_free = qcrypto_gnutls_hmac_ctx_free,
139
};
140

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.