master
inc 390 lines 11.5 KB
Raw
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(QCryptoCipherAlgo alg)
24 {
25 switch (alg) {
26 case QCRYPTO_CIPHER_ALGO_DES:
27 return GCRY_CIPHER_DES;
28 case QCRYPTO_CIPHER_ALGO_3DES:
29 return GCRY_CIPHER_3DES;
30 case QCRYPTO_CIPHER_ALGO_AES_128:
31 return GCRY_CIPHER_AES128;
32 case QCRYPTO_CIPHER_ALGO_AES_192:
33 return GCRY_CIPHER_AES192;
34 case QCRYPTO_CIPHER_ALGO_AES_256:
35 return GCRY_CIPHER_AES256;
36 case QCRYPTO_CIPHER_ALGO_CAST5_128:
37 return GCRY_CIPHER_CAST5;
38 case QCRYPTO_CIPHER_ALGO_SERPENT_128:
39 return GCRY_CIPHER_SERPENT128;
40 case QCRYPTO_CIPHER_ALGO_SERPENT_192:
41 return GCRY_CIPHER_SERPENT192;
42 case QCRYPTO_CIPHER_ALGO_SERPENT_256:
43 return GCRY_CIPHER_SERPENT256;
44 case QCRYPTO_CIPHER_ALGO_TWOFISH_128:
45 return GCRY_CIPHER_TWOFISH128;
46 case QCRYPTO_CIPHER_ALGO_TWOFISH_256:
47 return GCRY_CIPHER_TWOFISH;
48 #ifdef CONFIG_CRYPTO_SM4
49 case QCRYPTO_CIPHER_ALGO_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 case QCRYPTO_CIPHER_MODE_GCM:
69 return GCRY_CIPHER_MODE_GCM;
70 default:
71 return GCRY_CIPHER_MODE_NONE;
72 }
73 }
74
75 bool qcrypto_cipher_supports(QCryptoCipherAlgo alg,
76 QCryptoCipherMode mode)
77 {
78 switch (alg) {
79 case QCRYPTO_CIPHER_ALGO_DES:
80 case QCRYPTO_CIPHER_ALGO_3DES:
81 case QCRYPTO_CIPHER_ALGO_AES_128:
82 case QCRYPTO_CIPHER_ALGO_AES_192:
83 case QCRYPTO_CIPHER_ALGO_AES_256:
84 case QCRYPTO_CIPHER_ALGO_CAST5_128:
85 case QCRYPTO_CIPHER_ALGO_SERPENT_128:
86 case QCRYPTO_CIPHER_ALGO_SERPENT_192:
87 case QCRYPTO_CIPHER_ALGO_SERPENT_256:
88 case QCRYPTO_CIPHER_ALGO_TWOFISH_128:
89 case QCRYPTO_CIPHER_ALGO_TWOFISH_256:
90 #ifdef CONFIG_CRYPTO_SM4
91 case QCRYPTO_CIPHER_ALGO_SM4:
92 #endif
93 break;
94 default:
95 return false;
96 }
97
98 if (gcry_cipher_algo_info(qcrypto_cipher_alg_to_gcry_alg(alg),
99 GCRYCTL_TEST_ALGO, NULL, NULL) != 0) {
100 return false;
101 }
102
103 switch (mode) {
104 case QCRYPTO_CIPHER_MODE_ECB:
105 case QCRYPTO_CIPHER_MODE_CBC:
106 case QCRYPTO_CIPHER_MODE_XTS:
107 case QCRYPTO_CIPHER_MODE_CTR:
108 return true;
109 case QCRYPTO_CIPHER_MODE_GCM:
110 /* GCM requires a 128-bit block cipher. */
111 return gcry_cipher_get_algo_blklen(
112 qcrypto_cipher_alg_to_gcry_alg(alg)) == 16;
113 default:
114 return false;
115 }
116 }
117
118 typedef struct QCryptoCipherGcrypt {
119 QCryptoCipher base;
120 gcry_cipher_hd_t handle;
121 size_t blocksize;
122 } QCryptoCipherGcrypt;
123
124
125 static void qcrypto_gcrypt_ctx_free(QCryptoCipher *cipher)
126 {
127 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
128
129 gcry_cipher_close(ctx->handle);
130 g_free(ctx);
131 }
132
133 static int qcrypto_gcrypt_encrypt(QCryptoCipher *cipher, const void *in,
134 void *out, size_t len, Error **errp)
135 {
136 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
137 gcry_error_t err;
138
139 if (len & (ctx->blocksize - 1)) {
140 error_setg(errp, "Length %zu must be a multiple of block size %zu",
141 len, ctx->blocksize);
142 return -1;
143 }
144
145 err = gcry_cipher_encrypt(ctx->handle, out, len, in, len);
146 if (err != 0) {
147 error_setg(errp, "Cannot encrypt data: %s", gcry_strerror(err));
148 return -1;
149 }
150
151 return 0;
152 }
153
154
155 static int qcrypto_gcrypt_decrypt(QCryptoCipher *cipher, const void *in,
156 void *out, size_t len, Error **errp)
157 {
158 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
159 gcry_error_t err;
160
161 if (len & (ctx->blocksize - 1)) {
162 error_setg(errp, "Length %zu must be a multiple of block size %zu",
163 len, ctx->blocksize);
164 return -1;
165 }
166
167 err = gcry_cipher_decrypt(ctx->handle, out, len, in, len);
168 if (err != 0) {
169 error_setg(errp, "Cannot decrypt data: %s",
170 gcry_strerror(err));
171 return -1;
172 }
173
174 return 0;
175 }
176
177 static int qcrypto_gcrypt_setiv(QCryptoCipher *cipher,
178 const uint8_t *iv, size_t niv,
179 Error **errp)
180 {
181 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
182 gcry_error_t err;
183
184 if (niv != ctx->blocksize) {
185 error_setg(errp, "Expected IV size %zu not %zu",
186 ctx->blocksize, niv);
187 return -1;
188 }
189
190 gcry_cipher_reset(ctx->handle);
191 err = gcry_cipher_setiv(ctx->handle, iv, niv);
192 if (err != 0) {
193 error_setg(errp, "Cannot set IV: %s", gcry_strerror(err));
194 return -1;
195 }
196
197 return 0;
198 }
199
200 static int qcrypto_gcrypt_ctr_setiv(QCryptoCipher *cipher,
201 const uint8_t *iv, size_t niv,
202 Error **errp)
203 {
204 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
205 gcry_error_t err;
206
207 if (niv != ctx->blocksize) {
208 error_setg(errp, "Expected IV size %zu not %zu",
209 ctx->blocksize, niv);
210 return -1;
211 }
212
213 err = gcry_cipher_setctr(ctx->handle, iv, niv);
214 if (err != 0) {
215 error_setg(errp, "Cannot set Counter: %s", gcry_strerror(err));
216 return -1;
217 }
218
219 return 0;
220 }
221
222
223 static const struct QCryptoCipherDriver qcrypto_gcrypt_driver = {
224 .cipher_encrypt = qcrypto_gcrypt_encrypt,
225 .cipher_decrypt = qcrypto_gcrypt_decrypt,
226 .cipher_setiv = qcrypto_gcrypt_setiv,
227 .cipher_free = qcrypto_gcrypt_ctx_free,
228 };
229
230 static const struct QCryptoCipherDriver qcrypto_gcrypt_ctr_driver = {
231 .cipher_encrypt = qcrypto_gcrypt_encrypt,
232 .cipher_decrypt = qcrypto_gcrypt_decrypt,
233 .cipher_setiv = qcrypto_gcrypt_ctr_setiv,
234 .cipher_free = qcrypto_gcrypt_ctx_free,
235 };
236
237 /*
238 * GCM is an AEAD stream mode: the IV/nonce need not match the block size,
239 * the message length need not be a multiple of the block size, associated
240 * data is fed with gcry_cipher_authenticate() and the authentication tag is
241 * read back with gcry_cipher_gettag().
242 */
243 static int qcrypto_gcrypt_gcm_setiv(QCryptoCipher *cipher,
244 const uint8_t *iv, size_t niv,
245 Error **errp)
246 {
247 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
248 gcry_error_t err;
249
250 gcry_cipher_reset(ctx->handle);
251 err = gcry_cipher_setiv(ctx->handle, iv, niv);
252 if (err != 0) {
253 error_setg(errp, "Cannot set IV: %s", gcry_strerror(err));
254 return -1;
255 }
256
257 return 0;
258 }
259
260 static int qcrypto_gcrypt_gcm_setaad(QCryptoCipher *cipher,
261 const uint8_t *aad, size_t len,
262 Error **errp)
263 {
264 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
265 gcry_error_t err;
266
267 err = gcry_cipher_authenticate(ctx->handle, aad, len);
268 if (err != 0) {
269 error_setg(errp, "Cannot set AAD: %s", gcry_strerror(err));
270 return -1;
271 }
272
273 return 0;
274 }
275
276 static int qcrypto_gcrypt_gcm_encrypt(QCryptoCipher *cipher, const void *in,
277 void *out, size_t len, Error **errp)
278 {
279 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
280 gcry_error_t err;
281
282 err = gcry_cipher_encrypt(ctx->handle, out, len, in, len);
283 if (err != 0) {
284 error_setg(errp, "Cannot encrypt data: %s", gcry_strerror(err));
285 return -1;
286 }
287
288 return 0;
289 }
290
291 static int qcrypto_gcrypt_gcm_decrypt(QCryptoCipher *cipher, const void *in,
292 void *out, size_t len, Error **errp)
293 {
294 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
295 gcry_error_t err;
296
297 err = gcry_cipher_decrypt(ctx->handle, out, len, in, len);
298 if (err != 0) {
299 error_setg(errp, "Cannot decrypt data: %s", gcry_strerror(err));
300 return -1;
301 }
302
303 return 0;
304 }
305
306 static int qcrypto_gcrypt_gcm_gettag(QCryptoCipher *cipher,
307 uint8_t *tag, size_t len, Error **errp)
308 {
309 QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
310 gcry_error_t err;
311
312 err = gcry_cipher_gettag(ctx->handle, tag, len);
313 if (err != 0) {
314 error_setg(errp, "Cannot get tag: %s", gcry_strerror(err));
315 return -1;
316 }
317
318 return 0;
319 }
320
321 static const struct QCryptoCipherDriver qcrypto_gcrypt_gcm_driver = {
322 .cipher_encrypt = qcrypto_gcrypt_gcm_encrypt,
323 .cipher_decrypt = qcrypto_gcrypt_gcm_decrypt,
324 .cipher_setiv = qcrypto_gcrypt_gcm_setiv,
325 .cipher_setaad = qcrypto_gcrypt_gcm_setaad,
326 .cipher_gettag = qcrypto_gcrypt_gcm_gettag,
327 .cipher_free = qcrypto_gcrypt_ctx_free,
328 };
329
330 static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgo alg,
331 QCryptoCipherMode mode,
332 const uint8_t *key,
333 size_t nkey,
334 Error **errp)
335 {
336 QCryptoCipherGcrypt *ctx;
337 const QCryptoCipherDriver *drv;
338 gcry_error_t err;
339 int gcryalg, gcrymode;
340
341 if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
342 return NULL;
343 }
344
345 gcryalg = qcrypto_cipher_alg_to_gcry_alg(alg);
346 if (gcryalg == GCRY_CIPHER_NONE) {
347 error_setg(errp, "Unsupported cipher algorithm %s",
348 QCryptoCipherAlgo_str(alg));
349 return NULL;
350 }
351
352 gcrymode = qcrypto_cipher_mode_to_gcry_mode(mode);
353 if (gcrymode == GCRY_CIPHER_MODE_NONE) {
354 error_setg(errp, "Unsupported cipher mode %s",
355 QCryptoCipherMode_str(mode));
356 return NULL;
357 }
358
359 if (mode == QCRYPTO_CIPHER_MODE_CTR) {
360 drv = &qcrypto_gcrypt_ctr_driver;
361 } else if (mode == QCRYPTO_CIPHER_MODE_GCM) {
362 drv = &qcrypto_gcrypt_gcm_driver;
363 } else {
364 drv = &qcrypto_gcrypt_driver;
365 }
366
367 ctx = g_new0(QCryptoCipherGcrypt, 1);
368 ctx->base.driver = drv;
369
370 err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
371 if (err != 0) {
372 error_setg(errp, "Cannot initialize cipher: %s",
373 gcry_strerror(err));
374 goto error;
375 }
376 ctx->blocksize = gcry_cipher_get_algo_blklen(gcryalg);
377
378 err = gcry_cipher_setkey(ctx->handle, key, nkey);
379 if (err != 0) {
380 error_setg(errp, "Cannot set key: %s", gcry_strerror(err));
381 goto error;
382 }
383
384 return &ctx->base;
385
386 error:
387 gcry_cipher_close(ctx->handle);
388 g_free(ctx);
389 return NULL;
390 }