]> git.proxmox.com Git - mirror_qemu.git/blob - crypto/cipher-gcrypt.c.inc
qemu-docs: Update options for graphical frontends
[mirror_qemu.git] / crypto / cipher-gcrypt.c.inc
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 bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
24 QCryptoCipherMode mode)
25 {
26 switch (alg) {
27 case QCRYPTO_CIPHER_ALG_DES:
28 case QCRYPTO_CIPHER_ALG_3DES:
29 case QCRYPTO_CIPHER_ALG_AES_128:
30 case QCRYPTO_CIPHER_ALG_AES_192:
31 case QCRYPTO_CIPHER_ALG_AES_256:
32 case QCRYPTO_CIPHER_ALG_CAST5_128:
33 case QCRYPTO_CIPHER_ALG_SERPENT_128:
34 case QCRYPTO_CIPHER_ALG_SERPENT_192:
35 case QCRYPTO_CIPHER_ALG_SERPENT_256:
36 case QCRYPTO_CIPHER_ALG_TWOFISH_128:
37 case QCRYPTO_CIPHER_ALG_TWOFISH_256:
38 break;
39 default:
40 return false;
41 }
42
43 switch (mode) {
44 case QCRYPTO_CIPHER_MODE_ECB:
45 case QCRYPTO_CIPHER_MODE_CBC:
46 case QCRYPTO_CIPHER_MODE_XTS:
47 case QCRYPTO_CIPHER_MODE_CTR:
48 return true;
49 default:
50 return false;
51 }
52 }
53
54 typedef struct QCryptoCipherGcrypt {
55 QCryptoCipher base;
56 gcry_cipher_hd_t handle;
57 size_t blocksize;
58 } QCryptoCipherGcrypt;
59
60
61 static void qcrypto_gcrypt_ctx_free(QCryptoCipher *cipher)
62 {
63 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
64
65 gcry_cipher_close(ctx->handle);
66 g_free(ctx);
67 }
68
69 static int qcrypto_gcrypt_encrypt(QCryptoCipher *cipher, const void *in,
70 void *out, size_t len, Error **errp)
71 {
72 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
73 gcry_error_t err;
74
75 if (len & (ctx->blocksize - 1)) {
76 error_setg(errp, "Length %zu must be a multiple of block size %zu",
77 len, ctx->blocksize);
78 return -1;
79 }
80
81 err = gcry_cipher_encrypt(ctx->handle, out, len, in, len);
82 if (err != 0) {
83 error_setg(errp, "Cannot encrypt data: %s", gcry_strerror(err));
84 return -1;
85 }
86
87 return 0;
88 }
89
90
91 static int qcrypto_gcrypt_decrypt(QCryptoCipher *cipher, const void *in,
92 void *out, size_t len, Error **errp)
93 {
94 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
95 gcry_error_t err;
96
97 if (len & (ctx->blocksize - 1)) {
98 error_setg(errp, "Length %zu must be a multiple of block size %zu",
99 len, ctx->blocksize);
100 return -1;
101 }
102
103 err = gcry_cipher_decrypt(ctx->handle, out, len, in, len);
104 if (err != 0) {
105 error_setg(errp, "Cannot decrypt data: %s",
106 gcry_strerror(err));
107 return -1;
108 }
109
110 return 0;
111 }
112
113 static int qcrypto_gcrypt_setiv(QCryptoCipher *cipher,
114 const uint8_t *iv, size_t niv,
115 Error **errp)
116 {
117 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
118 gcry_error_t err;
119
120 if (niv != ctx->blocksize) {
121 error_setg(errp, "Expected IV size %zu not %zu",
122 ctx->blocksize, niv);
123 return -1;
124 }
125
126 gcry_cipher_reset(ctx->handle);
127 err = gcry_cipher_setiv(ctx->handle, iv, niv);
128 if (err != 0) {
129 error_setg(errp, "Cannot set IV: %s", gcry_strerror(err));
130 return -1;
131 }
132
133 return 0;
134 }
135
136 static int qcrypto_gcrypt_ctr_setiv(QCryptoCipher *cipher,
137 const uint8_t *iv, size_t niv,
138 Error **errp)
139 {
140 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
141 gcry_error_t err;
142
143 if (niv != ctx->blocksize) {
144 error_setg(errp, "Expected IV size %zu not %zu",
145 ctx->blocksize, niv);
146 return -1;
147 }
148
149 err = gcry_cipher_setctr(ctx->handle, iv, niv);
150 if (err != 0) {
151 error_setg(errp, "Cannot set Counter: %s", gcry_strerror(err));
152 return -1;
153 }
154
155 return 0;
156 }
157
158
159 static const struct QCryptoCipherDriver qcrypto_gcrypt_driver = {
160 .cipher_encrypt = qcrypto_gcrypt_encrypt,
161 .cipher_decrypt = qcrypto_gcrypt_decrypt,
162 .cipher_setiv = qcrypto_gcrypt_setiv,
163 .cipher_free = qcrypto_gcrypt_ctx_free,
164 };
165
166 static const struct QCryptoCipherDriver qcrypto_gcrypt_ctr_driver = {
167 .cipher_encrypt = qcrypto_gcrypt_encrypt,
168 .cipher_decrypt = qcrypto_gcrypt_decrypt,
169 .cipher_setiv = qcrypto_gcrypt_ctr_setiv,
170 .cipher_free = qcrypto_gcrypt_ctx_free,
171 };
172
173 static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
174 QCryptoCipherMode mode,
175 const uint8_t *key,
176 size_t nkey,
177 Error **errp)
178 {
179 QCryptoCipherGcrypt *ctx;
180 const QCryptoCipherDriver *drv;
181 gcry_error_t err;
182 int gcryalg, gcrymode;
183
184 if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
185 return NULL;
186 }
187
188 switch (alg) {
189 case QCRYPTO_CIPHER_ALG_DES:
190 gcryalg = GCRY_CIPHER_DES;
191 break;
192 case QCRYPTO_CIPHER_ALG_3DES:
193 gcryalg = GCRY_CIPHER_3DES;
194 break;
195 case QCRYPTO_CIPHER_ALG_AES_128:
196 gcryalg = GCRY_CIPHER_AES128;
197 break;
198 case QCRYPTO_CIPHER_ALG_AES_192:
199 gcryalg = GCRY_CIPHER_AES192;
200 break;
201 case QCRYPTO_CIPHER_ALG_AES_256:
202 gcryalg = GCRY_CIPHER_AES256;
203 break;
204 case QCRYPTO_CIPHER_ALG_CAST5_128:
205 gcryalg = GCRY_CIPHER_CAST5;
206 break;
207 case QCRYPTO_CIPHER_ALG_SERPENT_128:
208 gcryalg = GCRY_CIPHER_SERPENT128;
209 break;
210 case QCRYPTO_CIPHER_ALG_SERPENT_192:
211 gcryalg = GCRY_CIPHER_SERPENT192;
212 break;
213 case QCRYPTO_CIPHER_ALG_SERPENT_256:
214 gcryalg = GCRY_CIPHER_SERPENT256;
215 break;
216 case QCRYPTO_CIPHER_ALG_TWOFISH_128:
217 gcryalg = GCRY_CIPHER_TWOFISH128;
218 break;
219 case QCRYPTO_CIPHER_ALG_TWOFISH_256:
220 gcryalg = GCRY_CIPHER_TWOFISH;
221 break;
222 default:
223 error_setg(errp, "Unsupported cipher algorithm %s",
224 QCryptoCipherAlgorithm_str(alg));
225 return NULL;
226 }
227
228 drv = &qcrypto_gcrypt_driver;
229 switch (mode) {
230 case QCRYPTO_CIPHER_MODE_ECB:
231 gcrymode = GCRY_CIPHER_MODE_ECB;
232 break;
233 case QCRYPTO_CIPHER_MODE_XTS:
234 gcrymode = GCRY_CIPHER_MODE_XTS;
235 break;
236 case QCRYPTO_CIPHER_MODE_CBC:
237 gcrymode = GCRY_CIPHER_MODE_CBC;
238 break;
239 case QCRYPTO_CIPHER_MODE_CTR:
240 drv = &qcrypto_gcrypt_ctr_driver;
241 gcrymode = GCRY_CIPHER_MODE_CTR;
242 break;
243 default:
244 error_setg(errp, "Unsupported cipher mode %s",
245 QCryptoCipherMode_str(mode));
246 return NULL;
247 }
248
249 ctx = g_new0(QCryptoCipherGcrypt, 1);
250 ctx->base.driver = drv;
251
252 err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
253 if (err != 0) {
254 error_setg(errp, "Cannot initialize cipher: %s",
255 gcry_strerror(err));
256 goto error;
257 }
258 ctx->blocksize = gcry_cipher_get_algo_blklen(gcryalg);
259
260 err = gcry_cipher_setkey(ctx->handle, key, nkey);
261 if (err != 0) {
262 error_setg(errp, "Cannot set key: %s", gcry_strerror(err));
263 goto error;
264 }
265
266 return &ctx->base;
267
268 error:
269 gcry_cipher_close(ctx->handle);
270 g_free(ctx);
271 return NULL;
272 }