blob: 3848cb3b3a0902d9e6ec54da96b0205581133779 [file] [log] [blame]
Daniel P. Berrangeed754742015-07-01 18:10:34 +01001/*
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
Peter Maydell42f7a442016-01-26 18:16:55 +000021#include "qemu/osdep.h"
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +000022#include "crypto/xts.h"
Longpeng(Mike)75c80072017-07-14 14:03:58 -040023#include "cipherpriv.h"
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +000024
Daniel P. Berrangeed754742015-07-01 18:10:34 +010025#include <nettle/nettle-types.h>
26#include <nettle/aes.h>
27#include <nettle/des.h>
28#include <nettle/cbc.h>
Daniel P. Berrange084a85e2016-02-10 17:07:42 +000029#include <nettle/cast128.h>
Daniel P. Berrange94318522016-02-10 17:07:42 +000030#include <nettle/serpent.h>
Daniel P. Berrange50f67532016-02-10 17:07:42 +000031#include <nettle/twofish.h>
Gonglei3c282922016-09-26 17:23:22 +080032#include <nettle/ctr.h>
Daniel P. Berrangeed754742015-07-01 18:10:34 +010033
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +000034typedef void (*QCryptoCipherNettleFuncWrapper)(const void *ctx,
35 size_t length,
36 uint8_t *dst,
37 const uint8_t *src);
Radim Krčmářd3462e32015-07-10 19:18:01 +020038
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +000039#if CONFIG_NETTLE_VERSION_MAJOR < 3
40typedef nettle_crypt_func * QCryptoCipherNettleFuncNative;
Radim Krčmářd3462e32015-07-10 19:18:01 +020041typedef void * cipher_ctx_t;
42typedef unsigned cipher_length_t;
Daniel P. Berrange621e6ae2016-03-18 12:30:53 +000043
44#define cast5_set_key cast128_set_key
Radim Krčmářd3462e32015-07-10 19:18:01 +020045#else
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +000046typedef nettle_cipher_func * QCryptoCipherNettleFuncNative;
Radim Krčmářd3462e32015-07-10 19:18:01 +020047typedef const void * cipher_ctx_t;
48typedef size_t cipher_length_t;
Radim Krčmářbecaeb72015-07-10 19:18:00 +020049#endif
50
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +000051typedef struct QCryptoNettleAES {
52 struct aes_ctx enc;
53 struct aes_ctx dec;
54} QCryptoNettleAES;
55
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +000056static 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
63static 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
70static 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
76static 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
Longpeng(Mike)ffb7bf42016-12-08 10:33:28 +080082static 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
88static 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
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +000094static 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
100static 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
106static 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
112static 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
118static 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
124static 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
130static void aes_encrypt_wrapper(const void *ctx, size_t length,
Radim Krčmářd3462e32015-07-10 19:18:01 +0200131 uint8_t *dst, const uint8_t *src)
132{
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000133 const QCryptoNettleAES *aesctx = ctx;
134 aes_encrypt(&aesctx->enc, length, dst, src);
Radim Krčmářd3462e32015-07-10 19:18:01 +0200135}
136
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000137static void aes_decrypt_wrapper(const void *ctx, size_t length,
Radim Krčmářd3462e32015-07-10 19:18:01 +0200138 uint8_t *dst, const uint8_t *src)
139{
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000140 const QCryptoNettleAES *aesctx = ctx;
141 aes_decrypt(&aesctx->dec, length, dst, src);
Radim Krčmářd3462e32015-07-10 19:18:01 +0200142}
143
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000144static void des_encrypt_wrapper(const void *ctx, size_t length,
Radim Krčmářd3462e32015-07-10 19:18:01 +0200145 uint8_t *dst, const uint8_t *src)
146{
147 des_encrypt(ctx, length, dst, src);
148}
149
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000150static void des_decrypt_wrapper(const void *ctx, size_t length,
Radim Krčmářd3462e32015-07-10 19:18:01 +0200151 uint8_t *dst, const uint8_t *src)
152{
153 des_decrypt(ctx, length, dst, src);
154}
155
Longpeng(Mike)ffb7bf42016-12-08 10:33:28 +0800156static 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
162static 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
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000168static void cast128_encrypt_wrapper(const void *ctx, size_t length,
Daniel P. Berrange084a85e2016-02-10 17:07:42 +0000169 uint8_t *dst, const uint8_t *src)
170{
171 cast128_encrypt(ctx, length, dst, src);
172}
173
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000174static void cast128_decrypt_wrapper(const void *ctx, size_t length,
Daniel P. Berrange084a85e2016-02-10 17:07:42 +0000175 uint8_t *dst, const uint8_t *src)
176{
177 cast128_decrypt(ctx, length, dst, src);
178}
179
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000180static void serpent_encrypt_wrapper(const void *ctx, size_t length,
Daniel P. Berrange94318522016-02-10 17:07:42 +0000181 uint8_t *dst, const uint8_t *src)
182{
183 serpent_encrypt(ctx, length, dst, src);
184}
185
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000186static void serpent_decrypt_wrapper(const void *ctx, size_t length,
Daniel P. Berrange94318522016-02-10 17:07:42 +0000187 uint8_t *dst, const uint8_t *src)
188{
189 serpent_decrypt(ctx, length, dst, src);
190}
191
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000192static void twofish_encrypt_wrapper(const void *ctx, size_t length,
Daniel P. Berrange50f67532016-02-10 17:07:42 +0000193 uint8_t *dst, const uint8_t *src)
194{
195 twofish_encrypt(ctx, length, dst, src);
196}
197
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000198static void twofish_decrypt_wrapper(const void *ctx, size_t length,
Daniel P. Berrange50f67532016-02-10 17:07:42 +0000199 uint8_t *dst, const uint8_t *src)
200{
201 twofish_decrypt(ctx, length, dst, src);
202}
203
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100204typedef struct QCryptoCipherNettle QCryptoCipherNettle;
205struct QCryptoCipherNettle {
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000206 /* Primary cipher context for all modes */
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000207 void *ctx;
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000208 /* Second cipher context for XTS mode only */
209 void *ctx_tweak;
210 /* Cipher callbacks for both contexts */
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000211 QCryptoCipherNettleFuncNative alg_encrypt_native;
212 QCryptoCipherNettleFuncNative alg_decrypt_native;
213 QCryptoCipherNettleFuncWrapper alg_encrypt_wrapper;
214 QCryptoCipherNettleFuncWrapper alg_decrypt_wrapper;
Gonglei3c282922016-09-26 17:23:22 +0800215 /* Initialization vector or Counter */
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100216 uint8_t *iv;
Daniel P. Berrange3a661f12015-10-16 16:35:06 +0100217 size_t blocksize;
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100218};
219
Gongleif8448362016-09-26 17:23:21 +0800220bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
221 QCryptoCipherMode mode)
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100222{
223 switch (alg) {
224 case QCRYPTO_CIPHER_ALG_DES_RFB:
Longpeng(Mike)ffb7bf42016-12-08 10:33:28 +0800225 case QCRYPTO_CIPHER_ALG_3DES:
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100226 case QCRYPTO_CIPHER_ALG_AES_128:
227 case QCRYPTO_CIPHER_ALG_AES_192:
228 case QCRYPTO_CIPHER_ALG_AES_256:
Daniel P. Berrange084a85e2016-02-10 17:07:42 +0000229 case QCRYPTO_CIPHER_ALG_CAST5_128:
Daniel P. Berrange94318522016-02-10 17:07:42 +0000230 case QCRYPTO_CIPHER_ALG_SERPENT_128:
231 case QCRYPTO_CIPHER_ALG_SERPENT_192:
232 case QCRYPTO_CIPHER_ALG_SERPENT_256:
Daniel P. Berrange50f67532016-02-10 17:07:42 +0000233 case QCRYPTO_CIPHER_ALG_TWOFISH_128:
234 case QCRYPTO_CIPHER_ALG_TWOFISH_192:
235 case QCRYPTO_CIPHER_ALG_TWOFISH_256:
Gongleif8448362016-09-26 17:23:21 +0800236 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:
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100246 return true;
247 default:
248 return false;
249 }
250}
251
252
Longpeng(Mike)75c80072017-07-14 14:03:58 -0400253static void
254qcrypto_nettle_cipher_free_ctx(QCryptoCipherNettle *ctx)
Longpeng(Mike)cc5eff02017-07-14 14:03:54 -0400255{
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
Longpeng(Mike)eabe6c52017-07-14 14:03:56 -0400267static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
268 QCryptoCipherMode mode,
269 const uint8_t *key,
270 size_t nkey,
271 Error **errp)
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100272{
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100273 QCryptoCipherNettle *ctx;
274 uint8_t *rfbkey;
275
276 switch (mode) {
277 case QCRYPTO_CIPHER_MODE_ECB:
278 case QCRYPTO_CIPHER_MODE_CBC:
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000279 case QCRYPTO_CIPHER_MODE_XTS:
Gonglei3c282922016-09-26 17:23:22 +0800280 case QCRYPTO_CIPHER_MODE_CTR:
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100281 break;
282 default:
Daniel P. Berrange90d6f602016-09-05 18:02:05 +0100283 error_setg(errp, "Unsupported cipher mode %s",
Markus Armbruster977c7362017-08-24 10:46:08 +0200284 QCryptoCipherMode_str(mode));
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100285 return NULL;
286 }
287
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000288 if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100289 return NULL;
290 }
291
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100292 ctx = g_new0(QCryptoCipherNettle, 1);
293
294 switch (alg) {
295 case QCRYPTO_CIPHER_ALG_DES_RFB:
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000296 ctx->ctx = g_new0(struct des_ctx, 1);
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100297 rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000298 des_set_key(ctx->ctx, rfbkey);
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100299 g_free(rfbkey);
300
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000301 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;
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100305
Daniel P. Berrange3a661f12015-10-16 16:35:06 +0100306 ctx->blocksize = DES_BLOCK_SIZE;
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100307 break;
308
Longpeng(Mike)ffb7bf42016-12-08 10:33:28 +0800309 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
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100321 case QCRYPTO_CIPHER_ALG_AES_128:
322 case QCRYPTO_CIPHER_ALG_AES_192:
323 case QCRYPTO_CIPHER_ALG_AES_256:
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000324 ctx->ctx = g_new0(QCryptoNettleAES, 1);
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100325
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000326 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 }
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100345
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000346 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;
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100350
Daniel P. Berrange3a661f12015-10-16 16:35:06 +0100351 ctx->blocksize = AES_BLOCK_SIZE;
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100352 break;
Daniel P. Berrange084a85e2016-02-10 17:07:42 +0000353
354 case QCRYPTO_CIPHER_ALG_CAST5_128:
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000355 ctx->ctx = g_new0(struct cast128_ctx, 1);
Daniel P. Berrange084a85e2016-02-10 17:07:42 +0000356
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000357 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 }
Daniel P. Berrange084a85e2016-02-10 17:07:42 +0000366
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000367 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;
Daniel P. Berrange084a85e2016-02-10 17:07:42 +0000371
372 ctx->blocksize = CAST128_BLOCK_SIZE;
373 break;
Daniel P. Berrange94318522016-02-10 17:07:42 +0000374
375 case QCRYPTO_CIPHER_ALG_SERPENT_128:
376 case QCRYPTO_CIPHER_ALG_SERPENT_192:
377 case QCRYPTO_CIPHER_ALG_SERPENT_256:
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000378 ctx->ctx = g_new0(struct serpent_ctx, 1);
Daniel P. Berrange94318522016-02-10 17:07:42 +0000379
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000380 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 }
Daniel P. Berrange94318522016-02-10 17:07:42 +0000389
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000390 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;
Daniel P. Berrange94318522016-02-10 17:07:42 +0000394
395 ctx->blocksize = SERPENT_BLOCK_SIZE;
396 break;
397
Daniel P. Berrange50f67532016-02-10 17:07:42 +0000398 case QCRYPTO_CIPHER_ALG_TWOFISH_128:
399 case QCRYPTO_CIPHER_ALG_TWOFISH_192:
400 case QCRYPTO_CIPHER_ALG_TWOFISH_256:
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000401 ctx->ctx = g_new0(struct twofish_ctx, 1);
Daniel P. Berrange50f67532016-02-10 17:07:42 +0000402
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000403 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 }
Daniel P. Berrange50f67532016-02-10 17:07:42 +0000412
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000413 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;
Daniel P. Berrange50f67532016-02-10 17:07:42 +0000417
418 ctx->blocksize = TWOFISH_BLOCK_SIZE;
419 break;
420
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100421 default:
Daniel P. Berrange90d6f602016-09-05 18:02:05 +0100422 error_setg(errp, "Unsupported cipher algorithm %s",
Markus Armbruster977c7362017-08-24 10:46:08 +0200423 QCryptoCipherAlgorithm_str(alg));
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100424 goto error;
425 }
426
Daniel P. Berrangea5d2f442016-08-24 16:28:15 +0100427 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
Daniel P. Berrange3a661f12015-10-16 16:35:06 +0100434 ctx->iv = g_new0(uint8_t, ctx->blocksize);
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100435
Longpeng(Mike)eabe6c52017-07-14 14:03:56 -0400436 return ctx;
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100437
438 error:
Longpeng(Mike)75c80072017-07-14 14:03:58 -0400439 qcrypto_nettle_cipher_free_ctx(ctx);
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100440 return NULL;
441}
442
443
Longpeng(Mike)75c80072017-07-14 14:03:58 -0400444static void
445qcrypto_nettle_cipher_ctx_free(QCryptoCipher *cipher)
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100446{
447 QCryptoCipherNettle *ctx;
448
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100449 ctx = cipher->opaque;
Longpeng(Mike)75c80072017-07-14 14:03:58 -0400450 qcrypto_nettle_cipher_free_ctx(ctx);
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100451}
452
453
Longpeng(Mike)75c80072017-07-14 14:03:58 -0400454static int
455qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher,
456 const void *in,
457 void *out,
458 size_t len,
459 Error **errp)
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100460{
461 QCryptoCipherNettle *ctx = cipher->opaque;
462
Daniel P. Berrange3a661f12015-10-16 16:35:06 +0100463 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
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100469 switch (cipher->mode) {
470 case QCRYPTO_CIPHER_MODE_ECB:
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000471 ctx->alg_encrypt_wrapper(ctx->ctx, len, out, in);
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100472 break;
473
474 case QCRYPTO_CIPHER_MODE_CBC:
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000475 cbc_encrypt(ctx->ctx, ctx->alg_encrypt_native,
Daniel P. Berrange3a661f12015-10-16 16:35:06 +0100476 ctx->blocksize, ctx->iv,
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100477 len, out, in);
478 break;
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000479
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000480 case QCRYPTO_CIPHER_MODE_XTS:
481 xts_encrypt(ctx->ctx, ctx->ctx_tweak,
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000482 ctx->alg_encrypt_wrapper, ctx->alg_encrypt_wrapper,
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000483 ctx->iv, len, out, in);
484 break;
485
Gonglei3c282922016-09-26 17:23:22 +0800486 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
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100492 default:
Daniel P. Berrange90d6f602016-09-05 18:02:05 +0100493 error_setg(errp, "Unsupported cipher mode %s",
Markus Armbruster977c7362017-08-24 10:46:08 +0200494 QCryptoCipherMode_str(cipher->mode));
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100495 return -1;
496 }
497 return 0;
498}
499
500
Longpeng(Mike)75c80072017-07-14 14:03:58 -0400501static int
502qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher,
503 const void *in,
504 void *out,
505 size_t len,
506 Error **errp)
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100507{
508 QCryptoCipherNettle *ctx = cipher->opaque;
509
Daniel P. Berrange3a661f12015-10-16 16:35:06 +0100510 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
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100516 switch (cipher->mode) {
517 case QCRYPTO_CIPHER_MODE_ECB:
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000518 ctx->alg_decrypt_wrapper(ctx->ctx, len, out, in);
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100519 break;
520
521 case QCRYPTO_CIPHER_MODE_CBC:
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000522 cbc_decrypt(ctx->ctx, ctx->alg_decrypt_native,
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000523 ctx->blocksize, ctx->iv,
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100524 len, out, in);
525 break;
Daniel P. Berrangee3ba0b62016-02-11 14:05:21 +0000526
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000527 case QCRYPTO_CIPHER_MODE_XTS:
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000528 xts_decrypt(ctx->ctx, ctx->ctx_tweak,
Daniel P. Berrangef7ac78c2016-03-18 12:39:12 +0000529 ctx->alg_encrypt_wrapper, ctx->alg_decrypt_wrapper,
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000530 ctx->iv, len, out, in);
531 break;
Gonglei3c282922016-09-26 17:23:22 +0800532 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;
Daniel P. Berrangeeaec9032016-02-11 14:05:21 +0000537
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100538 default:
Daniel P. Berrange90d6f602016-09-05 18:02:05 +0100539 error_setg(errp, "Unsupported cipher mode %s",
Markus Armbruster977c7362017-08-24 10:46:08 +0200540 QCryptoCipherMode_str(cipher->mode));
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100541 return -1;
542 }
543 return 0;
544}
545
Longpeng(Mike)75c80072017-07-14 14:03:58 -0400546static int
547qcrypto_nettle_cipher_setiv(QCryptoCipher *cipher,
548 const uint8_t *iv, size_t niv,
549 Error **errp)
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100550{
551 QCryptoCipherNettle *ctx = cipher->opaque;
Daniel P. Berrange3a661f12015-10-16 16:35:06 +0100552 if (niv != ctx->blocksize) {
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100553 error_setg(errp, "Expected IV size %zu not %zu",
Daniel P. Berrange3a661f12015-10-16 16:35:06 +0100554 ctx->blocksize, niv);
Daniel P. Berrangeed754742015-07-01 18:10:34 +0100555 return -1;
556 }
557 memcpy(ctx->iv, iv, niv);
558 return 0;
559}
Longpeng(Mike)eabe6c52017-07-14 14:03:56 -0400560
561
Longpeng(Mike)75c80072017-07-14 14:03:58 -0400562static 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};