qemu

Форк
0
/
cipher-gcrypt.c.inc 
289 строк · 8.3 Кб
1
/*
2
 * QEMU Crypto cipher libgcrypt algorithms
3
 *
4
 * Copyright (c) 2015 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 <gcrypt.h>
22

23
static int qcrypto_cipher_alg_to_gcry_alg(QCryptoCipherAlgorithm alg)
24
{
25
    switch (alg) {
26
    case QCRYPTO_CIPHER_ALG_DES:
27
        return GCRY_CIPHER_DES;
28
    case QCRYPTO_CIPHER_ALG_3DES:
29
        return GCRY_CIPHER_3DES;
30
    case QCRYPTO_CIPHER_ALG_AES_128:
31
        return GCRY_CIPHER_AES128;
32
    case QCRYPTO_CIPHER_ALG_AES_192:
33
        return GCRY_CIPHER_AES192;
34
    case QCRYPTO_CIPHER_ALG_AES_256:
35
        return GCRY_CIPHER_AES256;
36
    case QCRYPTO_CIPHER_ALG_CAST5_128:
37
        return GCRY_CIPHER_CAST5;
38
    case QCRYPTO_CIPHER_ALG_SERPENT_128:
39
        return GCRY_CIPHER_SERPENT128;
40
    case QCRYPTO_CIPHER_ALG_SERPENT_192:
41
        return GCRY_CIPHER_SERPENT192;
42
    case QCRYPTO_CIPHER_ALG_SERPENT_256:
43
        return GCRY_CIPHER_SERPENT256;
44
    case QCRYPTO_CIPHER_ALG_TWOFISH_128:
45
        return GCRY_CIPHER_TWOFISH128;
46
    case QCRYPTO_CIPHER_ALG_TWOFISH_256:
47
        return GCRY_CIPHER_TWOFISH;
48
#ifdef CONFIG_CRYPTO_SM4
49
    case QCRYPTO_CIPHER_ALG_SM4:
50
        return GCRY_CIPHER_SM4;
51
#endif
52
    default:
53
        return GCRY_CIPHER_NONE;
54
    }
55
}
56

57
static int qcrypto_cipher_mode_to_gcry_mode(QCryptoCipherMode mode)
58
{
59
    switch (mode) {
60
    case QCRYPTO_CIPHER_MODE_ECB:
61
        return GCRY_CIPHER_MODE_ECB;
62
    case QCRYPTO_CIPHER_MODE_XTS:
63
        return GCRY_CIPHER_MODE_XTS;
64
    case QCRYPTO_CIPHER_MODE_CBC:
65
        return GCRY_CIPHER_MODE_CBC;
66
    case QCRYPTO_CIPHER_MODE_CTR:
67
        return GCRY_CIPHER_MODE_CTR;
68
    default:
69
        return GCRY_CIPHER_MODE_NONE;
70
    }
71
}
72

73
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
74
                             QCryptoCipherMode mode)
75
{
76
    switch (alg) {
77
    case QCRYPTO_CIPHER_ALG_DES:
78
    case QCRYPTO_CIPHER_ALG_3DES:
79
    case QCRYPTO_CIPHER_ALG_AES_128:
80
    case QCRYPTO_CIPHER_ALG_AES_192:
81
    case QCRYPTO_CIPHER_ALG_AES_256:
82
    case QCRYPTO_CIPHER_ALG_CAST5_128:
83
    case QCRYPTO_CIPHER_ALG_SERPENT_128:
84
    case QCRYPTO_CIPHER_ALG_SERPENT_192:
85
    case QCRYPTO_CIPHER_ALG_SERPENT_256:
86
    case QCRYPTO_CIPHER_ALG_TWOFISH_128:
87
    case QCRYPTO_CIPHER_ALG_TWOFISH_256:
88
#ifdef CONFIG_CRYPTO_SM4
89
    case QCRYPTO_CIPHER_ALG_SM4:
90
#endif
91
        break;
92
    default:
93
        return false;
94
    }
95

96
    if (gcry_cipher_algo_info(qcrypto_cipher_alg_to_gcry_alg(alg),
97
                              GCRYCTL_TEST_ALGO, NULL, NULL) != 0) {
98
        return false;
99
    }
100

101
    switch (mode) {
102
    case QCRYPTO_CIPHER_MODE_ECB:
103
    case QCRYPTO_CIPHER_MODE_CBC:
104
    case QCRYPTO_CIPHER_MODE_XTS:
105
    case QCRYPTO_CIPHER_MODE_CTR:
106
        return true;
107
    default:
108
        return false;
109
    }
110
}
111

112
typedef struct QCryptoCipherGcrypt {
113
    QCryptoCipher base;
114
    gcry_cipher_hd_t handle;
115
    size_t blocksize;
116
} QCryptoCipherGcrypt;
117

118

119
static void qcrypto_gcrypt_ctx_free(QCryptoCipher *cipher)
120
{
121
    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
122

123
    gcry_cipher_close(ctx->handle);
124
    g_free(ctx);
125
}
126

127
static int qcrypto_gcrypt_encrypt(QCryptoCipher *cipher, const void *in,
128
                                  void *out, size_t len, Error **errp)
129
{
130
    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
131
    gcry_error_t err;
132

133
    if (len & (ctx->blocksize - 1)) {
134
        error_setg(errp, "Length %zu must be a multiple of block size %zu",
135
                   len, ctx->blocksize);
136
        return -1;
137
    }
138

139
    err = gcry_cipher_encrypt(ctx->handle, out, len, in, len);
140
    if (err != 0) {
141
        error_setg(errp, "Cannot encrypt data: %s", gcry_strerror(err));
142
        return -1;
143
    }
144

145
    return 0;
146
}
147

148

149
static int qcrypto_gcrypt_decrypt(QCryptoCipher *cipher, const void *in,
150
                                  void *out, size_t len, Error **errp)
151
{
152
    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
153
    gcry_error_t err;
154

155
    if (len & (ctx->blocksize - 1)) {
156
        error_setg(errp, "Length %zu must be a multiple of block size %zu",
157
                   len, ctx->blocksize);
158
        return -1;
159
    }
160

161
    err = gcry_cipher_decrypt(ctx->handle, out, len, in, len);
162
    if (err != 0) {
163
        error_setg(errp, "Cannot decrypt data: %s",
164
                   gcry_strerror(err));
165
        return -1;
166
    }
167

168
    return 0;
169
}
170

171
static int qcrypto_gcrypt_setiv(QCryptoCipher *cipher,
172
                                const uint8_t *iv, size_t niv,
173
                                Error **errp)
174
{
175
    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
176
    gcry_error_t err;
177

178
    if (niv != ctx->blocksize) {
179
        error_setg(errp, "Expected IV size %zu not %zu",
180
                   ctx->blocksize, niv);
181
        return -1;
182
    }
183

184
    gcry_cipher_reset(ctx->handle);
185
    err = gcry_cipher_setiv(ctx->handle, iv, niv);
186
    if (err != 0) {
187
        error_setg(errp, "Cannot set IV: %s", gcry_strerror(err));
188
        return -1;
189
    }
190

191
    return 0;
192
}
193

194
static int qcrypto_gcrypt_ctr_setiv(QCryptoCipher *cipher,
195
                                    const uint8_t *iv, size_t niv,
196
                                    Error **errp)
197
{
198
    QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
199
    gcry_error_t err;
200

201
    if (niv != ctx->blocksize) {
202
        error_setg(errp, "Expected IV size %zu not %zu",
203
                   ctx->blocksize, niv);
204
        return -1;
205
    }
206

207
    err = gcry_cipher_setctr(ctx->handle, iv, niv);
208
    if (err != 0) {
209
        error_setg(errp, "Cannot set Counter: %s", gcry_strerror(err));
210
        return -1;
211
    }
212

213
    return 0;
214
}
215

216

217
static const struct QCryptoCipherDriver qcrypto_gcrypt_driver = {
218
    .cipher_encrypt = qcrypto_gcrypt_encrypt,
219
    .cipher_decrypt = qcrypto_gcrypt_decrypt,
220
    .cipher_setiv = qcrypto_gcrypt_setiv,
221
    .cipher_free = qcrypto_gcrypt_ctx_free,
222
};
223

224
static const struct QCryptoCipherDriver qcrypto_gcrypt_ctr_driver = {
225
    .cipher_encrypt = qcrypto_gcrypt_encrypt,
226
    .cipher_decrypt = qcrypto_gcrypt_decrypt,
227
    .cipher_setiv = qcrypto_gcrypt_ctr_setiv,
228
    .cipher_free = qcrypto_gcrypt_ctx_free,
229
};
230

231
static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
232
                                             QCryptoCipherMode mode,
233
                                             const uint8_t *key,
234
                                             size_t nkey,
235
                                             Error **errp)
236
{
237
    QCryptoCipherGcrypt *ctx;
238
    const QCryptoCipherDriver *drv;
239
    gcry_error_t err;
240
    int gcryalg, gcrymode;
241

242
    if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
243
        return NULL;
244
    }
245

246
    gcryalg = qcrypto_cipher_alg_to_gcry_alg(alg);
247
    if (gcryalg == GCRY_CIPHER_NONE) {
248
        error_setg(errp, "Unsupported cipher algorithm %s",
249
                   QCryptoCipherAlgorithm_str(alg));
250
        return NULL;
251
    }
252

253
    gcrymode = qcrypto_cipher_mode_to_gcry_mode(mode);
254
    if (gcrymode == GCRY_CIPHER_MODE_NONE) {
255
        error_setg(errp, "Unsupported cipher mode %s",
256
                   QCryptoCipherMode_str(mode));
257
        return NULL;
258
    }
259

260
    if (mode == QCRYPTO_CIPHER_MODE_CTR) {
261
        drv = &qcrypto_gcrypt_ctr_driver;
262
    } else {
263
        drv = &qcrypto_gcrypt_driver;
264
    }
265

266
    ctx = g_new0(QCryptoCipherGcrypt, 1);
267
    ctx->base.driver = drv;
268

269
    err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
270
    if (err != 0) {
271
        error_setg(errp, "Cannot initialize cipher: %s",
272
                   gcry_strerror(err));
273
        goto error;
274
    }
275
    ctx->blocksize = gcry_cipher_get_algo_blklen(gcryalg);
276

277
    err = gcry_cipher_setkey(ctx->handle, key, nkey);
278
    if (err != 0) {
279
        error_setg(errp, "Cannot set key: %s", gcry_strerror(err));
280
        goto error;
281
    }
282

283
    return &ctx->base;
284

285
 error:
286
    gcry_cipher_close(ctx->handle);
287
    g_free(ctx);
288
    return NULL;
289
}
290

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

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

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

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