]>
Commit | Line | Data |
---|---|---|
ed754746 DB |
1 | /* |
2 | * QEMU Crypto cipher nettle 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 | 22 | #include "crypto/xts.h" |
75c80078 | 23 | #include "cipherpriv.h" |
eaec903c | 24 | |
ed754746 DB |
25 | #include <nettle/nettle-types.h> |
26 | #include <nettle/aes.h> | |
27 | #include <nettle/des.h> | |
28 | #include <nettle/cbc.h> | |
084a85ee | 29 | #include <nettle/cast128.h> |
94318522 | 30 | #include <nettle/serpent.h> |
50f6753e | 31 | #include <nettle/twofish.h> |
3c28292f | 32 | #include <nettle/ctr.h> |
ed754746 | 33 | |
f7ac78cf DB |
34 | typedef void (*QCryptoCipherNettleFuncWrapper)(const void *ctx, |
35 | size_t length, | |
36 | uint8_t *dst, | |
37 | const uint8_t *src); | |
d3462e37 | 38 | |
f7ac78cf DB |
39 | #if CONFIG_NETTLE_VERSION_MAJOR < 3 |
40 | typedef nettle_crypt_func * QCryptoCipherNettleFuncNative; | |
d3462e37 RK |
41 | typedef void * cipher_ctx_t; |
42 | typedef unsigned cipher_length_t; | |
621e6ae6 DB |
43 | |
44 | #define cast5_set_key cast128_set_key | |
d3462e37 | 45 | #else |
f7ac78cf | 46 | typedef nettle_cipher_func * QCryptoCipherNettleFuncNative; |
d3462e37 RK |
47 | typedef const void * cipher_ctx_t; |
48 | typedef size_t cipher_length_t; | |
becaeb72 RK |
49 | #endif |
50 | ||
e3ba0b67 DB |
51 | typedef struct QCryptoNettleAES { |
52 | struct aes_ctx enc; | |
53 | struct aes_ctx dec; | |
54 | } QCryptoNettleAES; | |
55 | ||
f7ac78cf DB |
56 | static void aes_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, |
57 | uint8_t *dst, const uint8_t *src) | |
58 | { | |
59 | const QCryptoNettleAES *aesctx = ctx; | |
60 | aes_encrypt(&aesctx->enc, length, dst, src); | |
61 | } | |
62 | ||
63 | static void aes_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, | |
64 | uint8_t *dst, const uint8_t *src) | |
65 | { | |
66 | const QCryptoNettleAES *aesctx = ctx; | |
67 | aes_decrypt(&aesctx->dec, length, dst, src); | |
68 | } | |
69 | ||
70 | static void des_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, | |
71 | uint8_t *dst, const uint8_t *src) | |
72 | { | |
73 | des_encrypt(ctx, length, dst, src); | |
74 | } | |
75 | ||
76 | static void des_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, | |
77 | uint8_t *dst, const uint8_t *src) | |
78 | { | |
79 | des_decrypt(ctx, length, dst, src); | |
80 | } | |
81 | ||
ffb7bf45 LM |
82 | static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, |
83 | uint8_t *dst, const uint8_t *src) | |
84 | { | |
85 | des3_encrypt(ctx, length, dst, src); | |
86 | } | |
87 | ||
88 | static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, | |
89 | uint8_t *dst, const uint8_t *src) | |
90 | { | |
91 | des3_decrypt(ctx, length, dst, src); | |
92 | } | |
93 | ||
f7ac78cf DB |
94 | static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, |
95 | uint8_t *dst, const uint8_t *src) | |
96 | { | |
97 | cast128_encrypt(ctx, length, dst, src); | |
98 | } | |
99 | ||
100 | static void cast128_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, | |
101 | uint8_t *dst, const uint8_t *src) | |
102 | { | |
103 | cast128_decrypt(ctx, length, dst, src); | |
104 | } | |
105 | ||
106 | static void serpent_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, | |
107 | uint8_t *dst, const uint8_t *src) | |
108 | { | |
109 | serpent_encrypt(ctx, length, dst, src); | |
110 | } | |
111 | ||
112 | static void serpent_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, | |
113 | uint8_t *dst, const uint8_t *src) | |
114 | { | |
115 | serpent_decrypt(ctx, length, dst, src); | |
116 | } | |
117 | ||
118 | static void twofish_encrypt_native(cipher_ctx_t ctx, cipher_length_t length, | |
119 | uint8_t *dst, const uint8_t *src) | |
120 | { | |
121 | twofish_encrypt(ctx, length, dst, src); | |
122 | } | |
123 | ||
124 | static void twofish_decrypt_native(cipher_ctx_t ctx, cipher_length_t length, | |
125 | uint8_t *dst, const uint8_t *src) | |
126 | { | |
127 | twofish_decrypt(ctx, length, dst, src); | |
128 | } | |
129 | ||
130 | static void aes_encrypt_wrapper(const void *ctx, size_t length, | |
d3462e37 RK |
131 | uint8_t *dst, const uint8_t *src) |
132 | { | |
e3ba0b67 DB |
133 | const QCryptoNettleAES *aesctx = ctx; |
134 | aes_encrypt(&aesctx->enc, length, dst, src); | |
d3462e37 RK |
135 | } |
136 | ||
f7ac78cf | 137 | static void aes_decrypt_wrapper(const void *ctx, size_t length, |
d3462e37 RK |
138 | uint8_t *dst, const uint8_t *src) |
139 | { | |
e3ba0b67 DB |
140 | const QCryptoNettleAES *aesctx = ctx; |
141 | aes_decrypt(&aesctx->dec, length, dst, src); | |
d3462e37 RK |
142 | } |
143 | ||
f7ac78cf | 144 | static void des_encrypt_wrapper(const void *ctx, size_t length, |
d3462e37 RK |
145 | uint8_t *dst, const uint8_t *src) |
146 | { | |
147 | des_encrypt(ctx, length, dst, src); | |
148 | } | |
149 | ||
f7ac78cf | 150 | static void des_decrypt_wrapper(const void *ctx, size_t length, |
d3462e37 RK |
151 | uint8_t *dst, const uint8_t *src) |
152 | { | |
153 | des_decrypt(ctx, length, dst, src); | |
154 | } | |
155 | ||
ffb7bf45 LM |
156 | static void des3_encrypt_wrapper(const void *ctx, size_t length, |
157 | uint8_t *dst, const uint8_t *src) | |
158 | { | |
159 | des3_encrypt(ctx, length, dst, src); | |
160 | } | |
161 | ||
162 | static void des3_decrypt_wrapper(const void *ctx, size_t length, | |
163 | uint8_t *dst, const uint8_t *src) | |
164 | { | |
165 | des3_decrypt(ctx, length, dst, src); | |
166 | } | |
167 | ||
f7ac78cf | 168 | static void cast128_encrypt_wrapper(const void *ctx, size_t length, |
084a85ee DB |
169 | uint8_t *dst, const uint8_t *src) |
170 | { | |
171 | cast128_encrypt(ctx, length, dst, src); | |
172 | } | |
173 | ||
f7ac78cf | 174 | static void cast128_decrypt_wrapper(const void *ctx, size_t length, |
084a85ee DB |
175 | uint8_t *dst, const uint8_t *src) |
176 | { | |
177 | cast128_decrypt(ctx, length, dst, src); | |
178 | } | |
179 | ||
f7ac78cf | 180 | static void serpent_encrypt_wrapper(const void *ctx, size_t length, |
94318522 DB |
181 | uint8_t *dst, const uint8_t *src) |
182 | { | |
183 | serpent_encrypt(ctx, length, dst, src); | |
184 | } | |
185 | ||
f7ac78cf | 186 | static void serpent_decrypt_wrapper(const void *ctx, size_t length, |
94318522 DB |
187 | uint8_t *dst, const uint8_t *src) |
188 | { | |
189 | serpent_decrypt(ctx, length, dst, src); | |
190 | } | |
191 | ||
f7ac78cf | 192 | static void twofish_encrypt_wrapper(const void *ctx, size_t length, |
50f6753e DB |
193 | uint8_t *dst, const uint8_t *src) |
194 | { | |
195 | twofish_encrypt(ctx, length, dst, src); | |
196 | } | |
197 | ||
f7ac78cf | 198 | static void twofish_decrypt_wrapper(const void *ctx, size_t length, |
50f6753e DB |
199 | uint8_t *dst, const uint8_t *src) |
200 | { | |
201 | twofish_decrypt(ctx, length, dst, src); | |
202 | } | |
203 | ||
ed754746 DB |
204 | typedef struct QCryptoCipherNettle QCryptoCipherNettle; |
205 | struct QCryptoCipherNettle { | |
eaec903c | 206 | /* Primary cipher context for all modes */ |
e3ba0b67 | 207 | void *ctx; |
eaec903c DB |
208 | /* Second cipher context for XTS mode only */ |
209 | void *ctx_tweak; | |
210 | /* Cipher callbacks for both contexts */ | |
f7ac78cf DB |
211 | QCryptoCipherNettleFuncNative alg_encrypt_native; |
212 | QCryptoCipherNettleFuncNative alg_decrypt_native; | |
213 | QCryptoCipherNettleFuncWrapper alg_encrypt_wrapper; | |
214 | QCryptoCipherNettleFuncWrapper alg_decrypt_wrapper; | |
3c28292f | 215 | /* Initialization vector or Counter */ |
ed754746 | 216 | uint8_t *iv; |
3a661f1e | 217 | size_t blocksize; |
ed754746 DB |
218 | }; |
219 | ||
f844836d GA |
220 | bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, |
221 | QCryptoCipherMode mode) | |
ed754746 DB |
222 | { |
223 | switch (alg) { | |
224 | case QCRYPTO_CIPHER_ALG_DES_RFB: | |
ffb7bf45 | 225 | case QCRYPTO_CIPHER_ALG_3DES: |
ed754746 DB |
226 | case QCRYPTO_CIPHER_ALG_AES_128: |
227 | case QCRYPTO_CIPHER_ALG_AES_192: | |
228 | case QCRYPTO_CIPHER_ALG_AES_256: | |
084a85ee | 229 | case QCRYPTO_CIPHER_ALG_CAST5_128: |
94318522 DB |
230 | case QCRYPTO_CIPHER_ALG_SERPENT_128: |
231 | case QCRYPTO_CIPHER_ALG_SERPENT_192: | |
232 | case QCRYPTO_CIPHER_ALG_SERPENT_256: | |
50f6753e DB |
233 | case QCRYPTO_CIPHER_ALG_TWOFISH_128: |
234 | case QCRYPTO_CIPHER_ALG_TWOFISH_192: | |
235 | case QCRYPTO_CIPHER_ALG_TWOFISH_256: | |
f844836d GA |
236 | break; |
237 | default: | |
238 | return false; | |
239 | } | |
240 | ||
241 | switch (mode) { | |
242 | case QCRYPTO_CIPHER_MODE_ECB: | |
243 | case QCRYPTO_CIPHER_MODE_CBC: | |
244 | case QCRYPTO_CIPHER_MODE_XTS: | |
245 | case QCRYPTO_CIPHER_MODE_CTR: | |
ed754746 DB |
246 | return true; |
247 | default: | |
248 | return false; | |
249 | } | |
250 | } | |
251 | ||
252 | ||
75c80078 LM |
253 | static void |
254 | qcrypto_nettle_cipher_free_ctx(QCryptoCipherNettle *ctx) | |
cc5eff01 LM |
255 | { |
256 | if (!ctx) { | |
257 | return; | |
258 | } | |
259 | ||
260 | g_free(ctx->iv); | |
261 | g_free(ctx->ctx); | |
262 | g_free(ctx->ctx_tweak); | |
263 | g_free(ctx); | |
264 | } | |
265 | ||
266 | ||
eabe6c58 LM |
267 | static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, |
268 | QCryptoCipherMode mode, | |
269 | const uint8_t *key, | |
270 | size_t nkey, | |
271 | Error **errp) | |
ed754746 | 272 | { |
ed754746 DB |
273 | QCryptoCipherNettle *ctx; |
274 | uint8_t *rfbkey; | |
275 | ||
276 | switch (mode) { | |
277 | case QCRYPTO_CIPHER_MODE_ECB: | |
278 | case QCRYPTO_CIPHER_MODE_CBC: | |
eaec903c | 279 | case QCRYPTO_CIPHER_MODE_XTS: |
3c28292f | 280 | case QCRYPTO_CIPHER_MODE_CTR: |
ed754746 DB |
281 | break; |
282 | default: | |
90d6f60d | 283 | error_setg(errp, "Unsupported cipher mode %s", |
977c736f | 284 | QCryptoCipherMode_str(mode)); |
ed754746 DB |
285 | return NULL; |
286 | } | |
287 | ||
eaec903c | 288 | if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { |
ed754746 DB |
289 | return NULL; |
290 | } | |
291 | ||
ed754746 DB |
292 | ctx = g_new0(QCryptoCipherNettle, 1); |
293 | ||
294 | switch (alg) { | |
295 | case QCRYPTO_CIPHER_ALG_DES_RFB: | |
e3ba0b67 | 296 | ctx->ctx = g_new0(struct des_ctx, 1); |
ed754746 | 297 | rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey); |
e3ba0b67 | 298 | des_set_key(ctx->ctx, rfbkey); |
ed754746 DB |
299 | g_free(rfbkey); |
300 | ||
f7ac78cf DB |
301 | ctx->alg_encrypt_native = des_encrypt_native; |
302 | ctx->alg_decrypt_native = des_decrypt_native; | |
303 | ctx->alg_encrypt_wrapper = des_encrypt_wrapper; | |
304 | ctx->alg_decrypt_wrapper = des_decrypt_wrapper; | |
ed754746 | 305 | |
3a661f1e | 306 | ctx->blocksize = DES_BLOCK_SIZE; |
ed754746 DB |
307 | break; |
308 | ||
ffb7bf45 LM |
309 | case QCRYPTO_CIPHER_ALG_3DES: |
310 | ctx->ctx = g_new0(struct des3_ctx, 1); | |
311 | des3_set_key(ctx->ctx, key); | |
312 | ||
313 | ctx->alg_encrypt_native = des3_encrypt_native; | |
314 | ctx->alg_decrypt_native = des3_decrypt_native; | |
315 | ctx->alg_encrypt_wrapper = des3_encrypt_wrapper; | |
316 | ctx->alg_decrypt_wrapper = des3_decrypt_wrapper; | |
317 | ||
318 | ctx->blocksize = DES3_BLOCK_SIZE; | |
319 | break; | |
320 | ||
ed754746 DB |
321 | case QCRYPTO_CIPHER_ALG_AES_128: |
322 | case QCRYPTO_CIPHER_ALG_AES_192: | |
323 | case QCRYPTO_CIPHER_ALG_AES_256: | |
e3ba0b67 | 324 | ctx->ctx = g_new0(QCryptoNettleAES, 1); |
ed754746 | 325 | |
eaec903c DB |
326 | if (mode == QCRYPTO_CIPHER_MODE_XTS) { |
327 | ctx->ctx_tweak = g_new0(QCryptoNettleAES, 1); | |
328 | ||
329 | nkey /= 2; | |
330 | aes_set_encrypt_key(&((QCryptoNettleAES *)ctx->ctx)->enc, | |
331 | nkey, key); | |
332 | aes_set_decrypt_key(&((QCryptoNettleAES *)ctx->ctx)->dec, | |
333 | nkey, key); | |
334 | ||
335 | aes_set_encrypt_key(&((QCryptoNettleAES *)ctx->ctx_tweak)->enc, | |
336 | nkey, key + nkey); | |
337 | aes_set_decrypt_key(&((QCryptoNettleAES *)ctx->ctx_tweak)->dec, | |
338 | nkey, key + nkey); | |
339 | } else { | |
340 | aes_set_encrypt_key(&((QCryptoNettleAES *)ctx->ctx)->enc, | |
341 | nkey, key); | |
342 | aes_set_decrypt_key(&((QCryptoNettleAES *)ctx->ctx)->dec, | |
343 | nkey, key); | |
344 | } | |
ed754746 | 345 | |
f7ac78cf DB |
346 | ctx->alg_encrypt_native = aes_encrypt_native; |
347 | ctx->alg_decrypt_native = aes_decrypt_native; | |
348 | ctx->alg_encrypt_wrapper = aes_encrypt_wrapper; | |
349 | ctx->alg_decrypt_wrapper = aes_decrypt_wrapper; | |
ed754746 | 350 | |
3a661f1e | 351 | ctx->blocksize = AES_BLOCK_SIZE; |
ed754746 | 352 | break; |
084a85ee DB |
353 | |
354 | case QCRYPTO_CIPHER_ALG_CAST5_128: | |
e3ba0b67 | 355 | ctx->ctx = g_new0(struct cast128_ctx, 1); |
084a85ee | 356 | |
eaec903c DB |
357 | if (mode == QCRYPTO_CIPHER_MODE_XTS) { |
358 | ctx->ctx_tweak = g_new0(struct cast128_ctx, 1); | |
359 | ||
360 | nkey /= 2; | |
361 | cast5_set_key(ctx->ctx, nkey, key); | |
362 | cast5_set_key(ctx->ctx_tweak, nkey, key + nkey); | |
363 | } else { | |
364 | cast5_set_key(ctx->ctx, nkey, key); | |
365 | } | |
084a85ee | 366 | |
f7ac78cf DB |
367 | ctx->alg_encrypt_native = cast128_encrypt_native; |
368 | ctx->alg_decrypt_native = cast128_decrypt_native; | |
369 | ctx->alg_encrypt_wrapper = cast128_encrypt_wrapper; | |
370 | ctx->alg_decrypt_wrapper = cast128_decrypt_wrapper; | |
084a85ee DB |
371 | |
372 | ctx->blocksize = CAST128_BLOCK_SIZE; | |
373 | break; | |
94318522 DB |
374 | |
375 | case QCRYPTO_CIPHER_ALG_SERPENT_128: | |
376 | case QCRYPTO_CIPHER_ALG_SERPENT_192: | |
377 | case QCRYPTO_CIPHER_ALG_SERPENT_256: | |
e3ba0b67 | 378 | ctx->ctx = g_new0(struct serpent_ctx, 1); |
94318522 | 379 | |
eaec903c DB |
380 | if (mode == QCRYPTO_CIPHER_MODE_XTS) { |
381 | ctx->ctx_tweak = g_new0(struct serpent_ctx, 1); | |
382 | ||
383 | nkey /= 2; | |
384 | serpent_set_key(ctx->ctx, nkey, key); | |
385 | serpent_set_key(ctx->ctx_tweak, nkey, key + nkey); | |
386 | } else { | |
387 | serpent_set_key(ctx->ctx, nkey, key); | |
388 | } | |
94318522 | 389 | |
f7ac78cf DB |
390 | ctx->alg_encrypt_native = serpent_encrypt_native; |
391 | ctx->alg_decrypt_native = serpent_decrypt_native; | |
392 | ctx->alg_encrypt_wrapper = serpent_encrypt_wrapper; | |
393 | ctx->alg_decrypt_wrapper = serpent_decrypt_wrapper; | |
94318522 DB |
394 | |
395 | ctx->blocksize = SERPENT_BLOCK_SIZE; | |
396 | break; | |
397 | ||
50f6753e DB |
398 | case QCRYPTO_CIPHER_ALG_TWOFISH_128: |
399 | case QCRYPTO_CIPHER_ALG_TWOFISH_192: | |
400 | case QCRYPTO_CIPHER_ALG_TWOFISH_256: | |
e3ba0b67 | 401 | ctx->ctx = g_new0(struct twofish_ctx, 1); |
50f6753e | 402 | |
eaec903c DB |
403 | if (mode == QCRYPTO_CIPHER_MODE_XTS) { |
404 | ctx->ctx_tweak = g_new0(struct twofish_ctx, 1); | |
405 | ||
406 | nkey /= 2; | |
407 | twofish_set_key(ctx->ctx, nkey, key); | |
408 | twofish_set_key(ctx->ctx_tweak, nkey, key + nkey); | |
409 | } else { | |
410 | twofish_set_key(ctx->ctx, nkey, key); | |
411 | } | |
50f6753e | 412 | |
f7ac78cf DB |
413 | ctx->alg_encrypt_native = twofish_encrypt_native; |
414 | ctx->alg_decrypt_native = twofish_decrypt_native; | |
415 | ctx->alg_encrypt_wrapper = twofish_encrypt_wrapper; | |
416 | ctx->alg_decrypt_wrapper = twofish_decrypt_wrapper; | |
50f6753e DB |
417 | |
418 | ctx->blocksize = TWOFISH_BLOCK_SIZE; | |
419 | break; | |
420 | ||
ed754746 | 421 | default: |
90d6f60d | 422 | error_setg(errp, "Unsupported cipher algorithm %s", |
977c736f | 423 | QCryptoCipherAlgorithm_str(alg)); |
ed754746 DB |
424 | goto error; |
425 | } | |
426 | ||
a5d2f44d DB |
427 | if (mode == QCRYPTO_CIPHER_MODE_XTS && |
428 | ctx->blocksize != XTS_BLOCK_SIZE) { | |
429 | error_setg(errp, "Cipher block size %zu must equal XTS block size %d", | |
430 | ctx->blocksize, XTS_BLOCK_SIZE); | |
431 | goto error; | |
432 | } | |
433 | ||
3a661f1e | 434 | ctx->iv = g_new0(uint8_t, ctx->blocksize); |
ed754746 | 435 | |
eabe6c58 | 436 | return ctx; |
ed754746 DB |
437 | |
438 | error: | |
75c80078 | 439 | qcrypto_nettle_cipher_free_ctx(ctx); |
ed754746 DB |
440 | return NULL; |
441 | } | |
442 | ||
443 | ||
75c80078 LM |
444 | static void |
445 | qcrypto_nettle_cipher_ctx_free(QCryptoCipher *cipher) | |
ed754746 DB |
446 | { |
447 | QCryptoCipherNettle *ctx; | |
448 | ||
ed754746 | 449 | ctx = cipher->opaque; |
75c80078 | 450 | qcrypto_nettle_cipher_free_ctx(ctx); |
ed754746 DB |
451 | } |
452 | ||
453 | ||
75c80078 LM |
454 | static int |
455 | qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher, | |
456 | const void *in, | |
457 | void *out, | |
458 | size_t len, | |
459 | Error **errp) | |
ed754746 DB |
460 | { |
461 | QCryptoCipherNettle *ctx = cipher->opaque; | |
462 | ||
3a661f1e DB |
463 | if (len % ctx->blocksize) { |
464 | error_setg(errp, "Length %zu must be a multiple of block size %zu", | |
465 | len, ctx->blocksize); | |
466 | return -1; | |
467 | } | |
468 | ||
ed754746 DB |
469 | switch (cipher->mode) { |
470 | case QCRYPTO_CIPHER_MODE_ECB: | |
f7ac78cf | 471 | ctx->alg_encrypt_wrapper(ctx->ctx, len, out, in); |
ed754746 DB |
472 | break; |
473 | ||
474 | case QCRYPTO_CIPHER_MODE_CBC: | |
f7ac78cf | 475 | cbc_encrypt(ctx->ctx, ctx->alg_encrypt_native, |
3a661f1e | 476 | ctx->blocksize, ctx->iv, |
ed754746 DB |
477 | len, out, in); |
478 | break; | |
e3ba0b67 | 479 | |
eaec903c DB |
480 | case QCRYPTO_CIPHER_MODE_XTS: |
481 | xts_encrypt(ctx->ctx, ctx->ctx_tweak, | |
f7ac78cf | 482 | ctx->alg_encrypt_wrapper, ctx->alg_encrypt_wrapper, |
eaec903c DB |
483 | ctx->iv, len, out, in); |
484 | break; | |
485 | ||
3c28292f GA |
486 | case QCRYPTO_CIPHER_MODE_CTR: |
487 | ctr_crypt(ctx->ctx, ctx->alg_encrypt_native, | |
488 | ctx->blocksize, ctx->iv, | |
489 | len, out, in); | |
490 | break; | |
491 | ||
ed754746 | 492 | default: |
90d6f60d | 493 | error_setg(errp, "Unsupported cipher mode %s", |
977c736f | 494 | QCryptoCipherMode_str(cipher->mode)); |
ed754746 DB |
495 | return -1; |
496 | } | |
497 | return 0; | |
498 | } | |
499 | ||
500 | ||
75c80078 LM |
501 | static int |
502 | qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher, | |
503 | const void *in, | |
504 | void *out, | |
505 | size_t len, | |
506 | Error **errp) | |
ed754746 DB |
507 | { |
508 | QCryptoCipherNettle *ctx = cipher->opaque; | |
509 | ||
3a661f1e DB |
510 | if (len % ctx->blocksize) { |
511 | error_setg(errp, "Length %zu must be a multiple of block size %zu", | |
512 | len, ctx->blocksize); | |
513 | return -1; | |
514 | } | |
515 | ||
ed754746 DB |
516 | switch (cipher->mode) { |
517 | case QCRYPTO_CIPHER_MODE_ECB: | |
f7ac78cf | 518 | ctx->alg_decrypt_wrapper(ctx->ctx, len, out, in); |
ed754746 DB |
519 | break; |
520 | ||
521 | case QCRYPTO_CIPHER_MODE_CBC: | |
f7ac78cf | 522 | cbc_decrypt(ctx->ctx, ctx->alg_decrypt_native, |
e3ba0b67 | 523 | ctx->blocksize, ctx->iv, |
ed754746 DB |
524 | len, out, in); |
525 | break; | |
e3ba0b67 | 526 | |
eaec903c | 527 | case QCRYPTO_CIPHER_MODE_XTS: |
eaec903c | 528 | xts_decrypt(ctx->ctx, ctx->ctx_tweak, |
f7ac78cf | 529 | ctx->alg_encrypt_wrapper, ctx->alg_decrypt_wrapper, |
eaec903c DB |
530 | ctx->iv, len, out, in); |
531 | break; | |
3c28292f GA |
532 | case QCRYPTO_CIPHER_MODE_CTR: |
533 | ctr_crypt(ctx->ctx, ctx->alg_encrypt_native, | |
534 | ctx->blocksize, ctx->iv, | |
535 | len, out, in); | |
536 | break; | |
eaec903c | 537 | |
ed754746 | 538 | default: |
90d6f60d | 539 | error_setg(errp, "Unsupported cipher mode %s", |
977c736f | 540 | QCryptoCipherMode_str(cipher->mode)); |
ed754746 DB |
541 | return -1; |
542 | } | |
543 | return 0; | |
544 | } | |
545 | ||
75c80078 LM |
546 | static int |
547 | qcrypto_nettle_cipher_setiv(QCryptoCipher *cipher, | |
548 | const uint8_t *iv, size_t niv, | |
549 | Error **errp) | |
ed754746 DB |
550 | { |
551 | QCryptoCipherNettle *ctx = cipher->opaque; | |
3a661f1e | 552 | if (niv != ctx->blocksize) { |
ed754746 | 553 | error_setg(errp, "Expected IV size %zu not %zu", |
3a661f1e | 554 | ctx->blocksize, niv); |
ed754746 DB |
555 | return -1; |
556 | } | |
557 | memcpy(ctx->iv, iv, niv); | |
558 | return 0; | |
559 | } | |
eabe6c58 LM |
560 | |
561 | ||
75c80078 LM |
562 | static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { |
563 | .cipher_encrypt = qcrypto_nettle_cipher_encrypt, | |
564 | .cipher_decrypt = qcrypto_nettle_cipher_decrypt, | |
565 | .cipher_setiv = qcrypto_nettle_cipher_setiv, | |
566 | .cipher_free = qcrypto_nettle_cipher_ctx_free, | |
567 | }; |