]> Git Repo - qemu.git/blame - crypto/cipher-gcrypt.c
crypto: fix building complaint
[qemu.git] / crypto / cipher-gcrypt.c
CommitLineData
62893b67
DB
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 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
42f7a448 21#include "qemu/osdep.h"
eaec903c
DB
22#include "crypto/xts.h"
23
62893b67
DB
24#include <gcrypt.h>
25
26
27bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg)
28{
29 switch (alg) {
30 case QCRYPTO_CIPHER_ALG_DES_RFB:
31 case QCRYPTO_CIPHER_ALG_AES_128:
32 case QCRYPTO_CIPHER_ALG_AES_192:
33 case QCRYPTO_CIPHER_ALG_AES_256:
084a85ee 34 case QCRYPTO_CIPHER_ALG_CAST5_128:
94318522
DB
35 case QCRYPTO_CIPHER_ALG_SERPENT_128:
36 case QCRYPTO_CIPHER_ALG_SERPENT_192:
37 case QCRYPTO_CIPHER_ALG_SERPENT_256:
50f6753e
DB
38 case QCRYPTO_CIPHER_ALG_TWOFISH_128:
39 case QCRYPTO_CIPHER_ALG_TWOFISH_256:
62893b67
DB
40 return true;
41 default:
42 return false;
43 }
44}
45
3a661f1e
DB
46typedef struct QCryptoCipherGcrypt QCryptoCipherGcrypt;
47struct QCryptoCipherGcrypt {
48 gcry_cipher_hd_t handle;
eaec903c 49 gcry_cipher_hd_t tweakhandle;
3a661f1e 50 size_t blocksize;
eaec903c 51 uint8_t *iv;
3a661f1e 52};
62893b67
DB
53
54QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
55 QCryptoCipherMode mode,
56 const uint8_t *key, size_t nkey,
57 Error **errp)
58{
59 QCryptoCipher *cipher;
3a661f1e 60 QCryptoCipherGcrypt *ctx;
62893b67
DB
61 gcry_error_t err;
62 int gcryalg, gcrymode;
63
64 switch (mode) {
65 case QCRYPTO_CIPHER_MODE_ECB:
eaec903c 66 case QCRYPTO_CIPHER_MODE_XTS:
62893b67
DB
67 gcrymode = GCRY_CIPHER_MODE_ECB;
68 break;
69 case QCRYPTO_CIPHER_MODE_CBC:
70 gcrymode = GCRY_CIPHER_MODE_CBC;
71 break;
72 default:
73 error_setg(errp, "Unsupported cipher mode %d", mode);
74 return NULL;
75 }
76
eaec903c 77 if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
62893b67
DB
78 return NULL;
79 }
80
81 switch (alg) {
82 case QCRYPTO_CIPHER_ALG_DES_RFB:
83 gcryalg = GCRY_CIPHER_DES;
84 break;
85
86 case QCRYPTO_CIPHER_ALG_AES_128:
87 gcryalg = GCRY_CIPHER_AES128;
88 break;
89
90 case QCRYPTO_CIPHER_ALG_AES_192:
91 gcryalg = GCRY_CIPHER_AES192;
92 break;
93
94 case QCRYPTO_CIPHER_ALG_AES_256:
95 gcryalg = GCRY_CIPHER_AES256;
96 break;
97
084a85ee
DB
98 case QCRYPTO_CIPHER_ALG_CAST5_128:
99 gcryalg = GCRY_CIPHER_CAST5;
100 break;
101
94318522
DB
102 case QCRYPTO_CIPHER_ALG_SERPENT_128:
103 gcryalg = GCRY_CIPHER_SERPENT128;
104 break;
105
106 case QCRYPTO_CIPHER_ALG_SERPENT_192:
107 gcryalg = GCRY_CIPHER_SERPENT192;
108 break;
109
110 case QCRYPTO_CIPHER_ALG_SERPENT_256:
111 gcryalg = GCRY_CIPHER_SERPENT256;
112 break;
113
50f6753e
DB
114 case QCRYPTO_CIPHER_ALG_TWOFISH_128:
115 gcryalg = GCRY_CIPHER_TWOFISH128;
116 break;
117
118 case QCRYPTO_CIPHER_ALG_TWOFISH_256:
119 gcryalg = GCRY_CIPHER_TWOFISH;
120 break;
121
62893b67
DB
122 default:
123 error_setg(errp, "Unsupported cipher algorithm %d", alg);
124 return NULL;
125 }
126
127 cipher = g_new0(QCryptoCipher, 1);
128 cipher->alg = alg;
129 cipher->mode = mode;
130
3a661f1e
DB
131 ctx = g_new0(QCryptoCipherGcrypt, 1);
132
133 err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
62893b67
DB
134 if (err != 0) {
135 error_setg(errp, "Cannot initialize cipher: %s",
136 gcry_strerror(err));
137 goto error;
138 }
eaec903c
DB
139 if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
140 err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0);
141 if (err != 0) {
142 error_setg(errp, "Cannot initialize cipher: %s",
143 gcry_strerror(err));
144 goto error;
145 }
146 }
62893b67
DB
147
148 if (cipher->alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
149 /* We're using standard DES cipher from gcrypt, so we need
150 * to munge the key so that the results are the same as the
151 * bizarre RFB variant of DES :-)
152 */
153 uint8_t *rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
3a661f1e 154 err = gcry_cipher_setkey(ctx->handle, rfbkey, nkey);
62893b67 155 g_free(rfbkey);
3a661f1e 156 ctx->blocksize = 8;
62893b67 157 } else {
eaec903c
DB
158 if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
159 nkey /= 2;
160 err = gcry_cipher_setkey(ctx->handle, key, nkey);
161 if (err != 0) {
162 error_setg(errp, "Cannot set key: %s",
163 gcry_strerror(err));
164 goto error;
165 }
166 err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey);
167 } else {
168 err = gcry_cipher_setkey(ctx->handle, key, nkey);
169 }
170 if (err != 0) {
171 error_setg(errp, "Cannot set key: %s",
172 gcry_strerror(err));
173 goto error;
174 }
084a85ee
DB
175 switch (cipher->alg) {
176 case QCRYPTO_CIPHER_ALG_AES_128:
177 case QCRYPTO_CIPHER_ALG_AES_192:
178 case QCRYPTO_CIPHER_ALG_AES_256:
94318522
DB
179 case QCRYPTO_CIPHER_ALG_SERPENT_128:
180 case QCRYPTO_CIPHER_ALG_SERPENT_192:
181 case QCRYPTO_CIPHER_ALG_SERPENT_256:
50f6753e
DB
182 case QCRYPTO_CIPHER_ALG_TWOFISH_128:
183 case QCRYPTO_CIPHER_ALG_TWOFISH_256:
084a85ee
DB
184 ctx->blocksize = 16;
185 break;
186 case QCRYPTO_CIPHER_ALG_CAST5_128:
187 ctx->blocksize = 8;
188 break;
189 default:
190 g_assert_not_reached();
191 }
62893b67 192 }
eaec903c
DB
193
194 if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
a5d2f44d
DB
195 if (ctx->blocksize != XTS_BLOCK_SIZE) {
196 error_setg(errp,
197 "Cipher block size %zu must equal XTS block size %d",
198 ctx->blocksize, XTS_BLOCK_SIZE);
199 goto error;
200 }
eaec903c 201 ctx->iv = g_new0(uint8_t, ctx->blocksize);
62893b67
DB
202 }
203
3a661f1e 204 cipher->opaque = ctx;
62893b67
DB
205 return cipher;
206
207 error:
3a661f1e 208 gcry_cipher_close(ctx->handle);
eaec903c
DB
209 if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
210 gcry_cipher_close(ctx->tweakhandle);
211 }
3a661f1e 212 g_free(ctx);
62893b67
DB
213 g_free(cipher);
214 return NULL;
215}
216
217
218void qcrypto_cipher_free(QCryptoCipher *cipher)
219{
3a661f1e 220 QCryptoCipherGcrypt *ctx;
62893b67
DB
221 if (!cipher) {
222 return;
223 }
3a661f1e
DB
224 ctx = cipher->opaque;
225 gcry_cipher_close(ctx->handle);
eaec903c
DB
226 if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
227 gcry_cipher_close(ctx->tweakhandle);
228 }
229 g_free(ctx->iv);
3a661f1e 230 g_free(ctx);
62893b67
DB
231 g_free(cipher);
232}
233
234
eaec903c
DB
235static void qcrypto_gcrypt_xts_encrypt(const void *ctx,
236 size_t length,
237 uint8_t *dst,
238 const uint8_t *src)
239{
240 gcry_error_t err;
241 err = gcry_cipher_encrypt((gcry_cipher_hd_t)ctx, dst, length, src, length);
242 g_assert(err == 0);
243}
244
245static void qcrypto_gcrypt_xts_decrypt(const void *ctx,
246 size_t length,
247 uint8_t *dst,
248 const uint8_t *src)
249{
250 gcry_error_t err;
251 err = gcry_cipher_decrypt((gcry_cipher_hd_t)ctx, dst, length, src, length);
252 g_assert(err == 0);
253}
254
62893b67
DB
255int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
256 const void *in,
257 void *out,
258 size_t len,
259 Error **errp)
260{
3a661f1e 261 QCryptoCipherGcrypt *ctx = cipher->opaque;
62893b67
DB
262 gcry_error_t err;
263
3a661f1e
DB
264 if (len % ctx->blocksize) {
265 error_setg(errp, "Length %zu must be a multiple of block size %zu",
266 len, ctx->blocksize);
267 return -1;
268 }
269
eaec903c
DB
270 if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
271 xts_encrypt(ctx->handle, ctx->tweakhandle,
272 qcrypto_gcrypt_xts_encrypt,
273 qcrypto_gcrypt_xts_decrypt,
274 ctx->iv, len, out, in);
275 } else {
276 err = gcry_cipher_encrypt(ctx->handle,
277 out, len,
278 in, len);
279 if (err != 0) {
280 error_setg(errp, "Cannot encrypt data: %s",
281 gcry_strerror(err));
282 return -1;
283 }
62893b67
DB
284 }
285
286 return 0;
287}
288
289
290int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
291 const void *in,
292 void *out,
293 size_t len,
294 Error **errp)
295{
3a661f1e 296 QCryptoCipherGcrypt *ctx = cipher->opaque;
62893b67
DB
297 gcry_error_t err;
298
3a661f1e
DB
299 if (len % ctx->blocksize) {
300 error_setg(errp, "Length %zu must be a multiple of block size %zu",
301 len, ctx->blocksize);
302 return -1;
303 }
304
eaec903c
DB
305 if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
306 xts_decrypt(ctx->handle, ctx->tweakhandle,
307 qcrypto_gcrypt_xts_encrypt,
308 qcrypto_gcrypt_xts_decrypt,
309 ctx->iv, len, out, in);
310 } else {
311 err = gcry_cipher_decrypt(ctx->handle,
312 out, len,
313 in, len);
314 if (err != 0) {
315 error_setg(errp, "Cannot decrypt data: %s",
316 gcry_strerror(err));
317 return -1;
318 }
62893b67
DB
319 }
320
321 return 0;
322}
323
324int qcrypto_cipher_setiv(QCryptoCipher *cipher,
325 const uint8_t *iv, size_t niv,
326 Error **errp)
327{
3a661f1e 328 QCryptoCipherGcrypt *ctx = cipher->opaque;
62893b67
DB
329 gcry_error_t err;
330
3a661f1e
DB
331 if (niv != ctx->blocksize) {
332 error_setg(errp, "Expected IV size %zu not %zu",
333 ctx->blocksize, niv);
334 return -1;
335 }
336
eaec903c
DB
337 if (ctx->iv) {
338 memcpy(ctx->iv, iv, niv);
339 } else {
340 gcry_cipher_reset(ctx->handle);
341 err = gcry_cipher_setiv(ctx->handle, iv, niv);
342 if (err != 0) {
343 error_setg(errp, "Cannot set IV: %s",
62893b67 344 gcry_strerror(err));
eaec903c
DB
345 return -1;
346 }
62893b67
DB
347 }
348
349 return 0;
350}
This page took 0.135834 seconds and 4 git commands to generate.