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