]> git.proxmox.com Git - mirror_qemu.git/blame - crypto/cipher-gcrypt.c.inc
crypto: make loaded property read-only
[mirror_qemu.git] / crypto / cipher-gcrypt.c.inc
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
21#include <gcrypt.h>
22
f844836d
GA
23bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
24 QCryptoCipherMode mode)
62893b67
DB
25{
26 switch (alg) {
83bee4b5 27 case QCRYPTO_CIPHER_ALG_DES:
ffb7bf45 28 case QCRYPTO_CIPHER_ALG_3DES:
62893b67
DB
29 case QCRYPTO_CIPHER_ALG_AES_128:
30 case QCRYPTO_CIPHER_ALG_AES_192:
31 case QCRYPTO_CIPHER_ALG_AES_256:
084a85ee 32 case QCRYPTO_CIPHER_ALG_CAST5_128:
94318522
DB
33 case QCRYPTO_CIPHER_ALG_SERPENT_128:
34 case QCRYPTO_CIPHER_ALG_SERPENT_192:
35 case QCRYPTO_CIPHER_ALG_SERPENT_256:
50f6753e
DB
36 case QCRYPTO_CIPHER_ALG_TWOFISH_128:
37 case QCRYPTO_CIPHER_ALG_TWOFISH_256:
f844836d
GA
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:
62893b67
DB
48 return true;
49 default:
50 return false;
51 }
52}
53
1b010d93 54typedef struct QCryptoCipherGcrypt {
3eedf5cc 55 QCryptoCipher base;
3a661f1e
DB
56 gcry_cipher_hd_t handle;
57 size_t blocksize;
1b010d93
RH
58} QCryptoCipherGcrypt;
59
62893b67 60
1b010d93 61static void qcrypto_gcrypt_ctx_free(QCryptoCipher *cipher)
cc5eff01 62{
1b010d93 63 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
cc5eff01
LM
64
65 gcry_cipher_close(ctx->handle);
1b010d93
RH
66 g_free(ctx);
67}
68
69static 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
91static 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
113static 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
136static 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
159static 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
166static 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
3eedf5cc
RH
173static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
174 QCryptoCipherMode mode,
175 const uint8_t *key,
176 size_t nkey,
177 Error **errp)
62893b67 178{
3a661f1e 179 QCryptoCipherGcrypt *ctx;
1b010d93 180 const QCryptoCipherDriver *drv;
62893b67
DB
181 gcry_error_t err;
182 int gcryalg, gcrymode;
183
eaec903c 184 if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
62893b67
DB
185 return NULL;
186 }
187
188 switch (alg) {
83bee4b5 189 case QCRYPTO_CIPHER_ALG_DES:
62893b67
DB
190 gcryalg = GCRY_CIPHER_DES;
191 break;
ffb7bf45
LM
192 case QCRYPTO_CIPHER_ALG_3DES:
193 gcryalg = GCRY_CIPHER_3DES;
194 break;
62893b67
DB
195 case QCRYPTO_CIPHER_ALG_AES_128:
196 gcryalg = GCRY_CIPHER_AES128;
197 break;
62893b67
DB
198 case QCRYPTO_CIPHER_ALG_AES_192:
199 gcryalg = GCRY_CIPHER_AES192;
200 break;
62893b67
DB
201 case QCRYPTO_CIPHER_ALG_AES_256:
202 gcryalg = GCRY_CIPHER_AES256;
203 break;
084a85ee
DB
204 case QCRYPTO_CIPHER_ALG_CAST5_128:
205 gcryalg = GCRY_CIPHER_CAST5;
206 break;
94318522
DB
207 case QCRYPTO_CIPHER_ALG_SERPENT_128:
208 gcryalg = GCRY_CIPHER_SERPENT128;
209 break;
94318522
DB
210 case QCRYPTO_CIPHER_ALG_SERPENT_192:
211 gcryalg = GCRY_CIPHER_SERPENT192;
212 break;
94318522
DB
213 case QCRYPTO_CIPHER_ALG_SERPENT_256:
214 gcryalg = GCRY_CIPHER_SERPENT256;
215 break;
50f6753e
DB
216 case QCRYPTO_CIPHER_ALG_TWOFISH_128:
217 gcryalg = GCRY_CIPHER_TWOFISH128;
218 break;
50f6753e
DB
219 case QCRYPTO_CIPHER_ALG_TWOFISH_256:
220 gcryalg = GCRY_CIPHER_TWOFISH;
221 break;
62893b67 222 default:
90d6f60d 223 error_setg(errp, "Unsupported cipher algorithm %s",
977c736f 224 QCryptoCipherAlgorithm_str(alg));
62893b67
DB
225 return NULL;
226 }
227
1b010d93
RH
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:
1b010d93 234 gcrymode = GCRY_CIPHER_MODE_XTS;
1b010d93
RH
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
3a661f1e 249 ctx = g_new0(QCryptoCipherGcrypt, 1);
1b010d93 250 ctx->base.driver = drv;
3a661f1e
DB
251
252 err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
62893b67
DB
253 if (err != 0) {
254 error_setg(errp, "Cannot initialize cipher: %s",
255 gcry_strerror(err));
256 goto error;
257 }
1b010d93
RH
258 ctx->blocksize = gcry_cipher_get_algo_blklen(gcryalg);
259
83bee4b5 260 err = gcry_cipher_setkey(ctx->handle, key, nkey);
1b010d93
RH
261 if (err != 0) {
262 error_setg(errp, "Cannot set key: %s", gcry_strerror(err));
263 goto error;
62893b67
DB
264 }
265
3eedf5cc 266 return &ctx->base;
62893b67
DB
267
268 error:
1b010d93
RH
269 gcry_cipher_close(ctx->handle);
270 g_free(ctx);
271 return NULL;
62893b67 272}