qemu

Форк
0
/
hash-nettle.c 
161 строка · 5.0 Кб
1
/*
2
 * QEMU Crypto hash algorithms
3
 *
4
 * Copyright (c) 2016 Red Hat, Inc.
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 *
19
 */
20

21
#include "qemu/osdep.h"
22
#include "qapi/error.h"
23
#include "crypto/hash.h"
24
#include "hashpriv.h"
25
#include <nettle/md5.h>
26
#include <nettle/sha.h>
27
#include <nettle/ripemd160.h>
28

29
typedef void (*qcrypto_nettle_init)(void *ctx);
30
typedef void (*qcrypto_nettle_write)(void *ctx,
31
                                     size_t len,
32
                                     const uint8_t *buf);
33
typedef void (*qcrypto_nettle_result)(void *ctx,
34
                                      size_t len,
35
                                      uint8_t *buf);
36

37
union qcrypto_hash_ctx {
38
    struct md5_ctx md5;
39
    struct sha1_ctx sha1;
40
    struct sha224_ctx sha224;
41
    struct sha256_ctx sha256;
42
    struct sha384_ctx sha384;
43
    struct sha512_ctx sha512;
44
    struct ripemd160_ctx ripemd160;
45
};
46

47
struct qcrypto_hash_alg {
48
    qcrypto_nettle_init init;
49
    qcrypto_nettle_write write;
50
    qcrypto_nettle_result result;
51
    size_t len;
52
} qcrypto_hash_alg_map[] = {
53
    [QCRYPTO_HASH_ALG_MD5] = {
54
        .init = (qcrypto_nettle_init)md5_init,
55
        .write = (qcrypto_nettle_write)md5_update,
56
        .result = (qcrypto_nettle_result)md5_digest,
57
        .len = MD5_DIGEST_SIZE,
58
    },
59
    [QCRYPTO_HASH_ALG_SHA1] = {
60
        .init = (qcrypto_nettle_init)sha1_init,
61
        .write = (qcrypto_nettle_write)sha1_update,
62
        .result = (qcrypto_nettle_result)sha1_digest,
63
        .len = SHA1_DIGEST_SIZE,
64
    },
65
    [QCRYPTO_HASH_ALG_SHA224] = {
66
        .init = (qcrypto_nettle_init)sha224_init,
67
        .write = (qcrypto_nettle_write)sha224_update,
68
        .result = (qcrypto_nettle_result)sha224_digest,
69
        .len = SHA224_DIGEST_SIZE,
70
    },
71
    [QCRYPTO_HASH_ALG_SHA256] = {
72
        .init = (qcrypto_nettle_init)sha256_init,
73
        .write = (qcrypto_nettle_write)sha256_update,
74
        .result = (qcrypto_nettle_result)sha256_digest,
75
        .len = SHA256_DIGEST_SIZE,
76
    },
77
    [QCRYPTO_HASH_ALG_SHA384] = {
78
        .init = (qcrypto_nettle_init)sha384_init,
79
        .write = (qcrypto_nettle_write)sha384_update,
80
        .result = (qcrypto_nettle_result)sha384_digest,
81
        .len = SHA384_DIGEST_SIZE,
82
    },
83
    [QCRYPTO_HASH_ALG_SHA512] = {
84
        .init = (qcrypto_nettle_init)sha512_init,
85
        .write = (qcrypto_nettle_write)sha512_update,
86
        .result = (qcrypto_nettle_result)sha512_digest,
87
        .len = SHA512_DIGEST_SIZE,
88
    },
89
    [QCRYPTO_HASH_ALG_RIPEMD160] = {
90
        .init = (qcrypto_nettle_init)ripemd160_init,
91
        .write = (qcrypto_nettle_write)ripemd160_update,
92
        .result = (qcrypto_nettle_result)ripemd160_digest,
93
        .len = RIPEMD160_DIGEST_SIZE,
94
    },
95
};
96

97
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
98
{
99
    if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) &&
100
        qcrypto_hash_alg_map[alg].init != NULL) {
101
        return true;
102
    }
103
    return false;
104
}
105

106

107
static int
108
qcrypto_nettle_hash_bytesv(QCryptoHashAlgorithm alg,
109
                           const struct iovec *iov,
110
                           size_t niov,
111
                           uint8_t **result,
112
                           size_t *resultlen,
113
                           Error **errp)
114
{
115
    size_t i;
116
    union qcrypto_hash_ctx ctx;
117

118
    if (!qcrypto_hash_supports(alg)) {
119
        error_setg(errp,
120
                   "Unknown hash algorithm %d",
121
                   alg);
122
        return -1;
123
    }
124

125
    qcrypto_hash_alg_map[alg].init(&ctx);
126

127
    for (i = 0; i < niov; i++) {
128
        /* Some versions of nettle have functions
129
         * declared with 'int' instead of 'size_t'
130
         * so to be safe avoid writing more than
131
         * UINT_MAX bytes at a time
132
         */
133
        size_t len = iov[i].iov_len;
134
        uint8_t *base = iov[i].iov_base;
135
        while (len) {
136
            size_t shortlen = MIN(len, UINT_MAX);
137
            qcrypto_hash_alg_map[alg].write(&ctx, len, base);
138
            len -= shortlen;
139
            base += len;
140
        }
141
    }
142

143
    if (*resultlen == 0) {
144
        *resultlen = qcrypto_hash_alg_map[alg].len;
145
        *result = g_new0(uint8_t, *resultlen);
146
    } else if (*resultlen != qcrypto_hash_alg_map[alg].len) {
147
        error_setg(errp,
148
                   "Result buffer size %zu is smaller than hash %zu",
149
                   *resultlen, qcrypto_hash_alg_map[alg].len);
150
        return -1;
151
    }
152

153
    qcrypto_hash_alg_map[alg].result(&ctx, *resultlen, *result);
154

155
    return 0;
156
}
157

158

159
QCryptoHashDriver qcrypto_hash_lib_driver = {
160
    .hash_bytesv = qcrypto_nettle_hash_bytesv,
161
};
162

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

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

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

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