2 * QEMU Crypto block encryption
4 * Copyright (c) 2016 Red Hat, Inc.
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.
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.
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/>.
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "crypto/init.h"
24 #include "crypto/block.h"
25 #include "qemu/buffer.h"
26 #include "crypto/secret.h"
28 #include <sys/resource.h>
31 #if (defined(_WIN32) || defined RUSAGE_THREAD) && \
32 (defined(CONFIG_NETTLE) || defined(CONFIG_GCRYPT))
38 static QCryptoBlockCreateOptions qcow_create_opts
= {
39 .format
= Q_CRYPTO_BLOCK_FORMAT_QCOW
,
41 .has_key_secret
= true,
42 .key_secret
= (char *)"sec0",
46 static QCryptoBlockOpenOptions qcow_open_opts
= {
47 .format
= Q_CRYPTO_BLOCK_FORMAT_QCOW
,
49 .has_key_secret
= true,
50 .key_secret
= (char *)"sec0",
56 static QCryptoBlockOpenOptions luks_open_opts
= {
57 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
59 .has_key_secret
= true,
60 .key_secret
= (char *)"sec0",
65 /* Creation with all default values */
66 static QCryptoBlockCreateOptions luks_create_opts_default
= {
67 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
69 .has_key_secret
= true,
70 .key_secret
= (char *)"sec0",
75 /* ...and with explicit values */
76 static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_plain64
= {
77 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
79 .has_key_secret
= true,
80 .key_secret
= (char *)"sec0",
81 .has_cipher_alg
= true,
82 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
83 .has_cipher_mode
= true,
84 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
85 .has_ivgen_alg
= true,
86 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
91 static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_essiv
= {
92 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
94 .has_key_secret
= true,
95 .key_secret
= (char *)"sec0",
96 .has_cipher_alg
= true,
97 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
98 .has_cipher_mode
= true,
99 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
100 .has_ivgen_alg
= true,
101 .ivgen_alg
= QCRYPTO_IVGEN_ALG_ESSIV
,
102 .has_ivgen_hash_alg
= true,
103 .ivgen_hash_alg
= QCRYPTO_HASH_ALG_SHA256
,
104 .has_hash_alg
= true,
105 .hash_alg
= QCRYPTO_HASH_ALG_SHA1
,
108 #endif /* TEST_LUKS */
111 static struct QCryptoBlockTestData
{
113 QCryptoBlockCreateOptions
*create_opts
;
114 QCryptoBlockOpenOptions
*open_opts
;
118 QCryptoCipherAlgorithm cipher_alg
;
119 QCryptoCipherMode cipher_mode
;
120 QCryptoHashAlgorithm hash_alg
;
122 QCryptoIVGenAlgorithm ivgen_alg
;
123 QCryptoHashAlgorithm ivgen_hash
;
128 .path
= "/crypto/block/qcow",
129 .create_opts
= &qcow_create_opts
,
130 .open_opts
= &qcow_open_opts
,
132 .expect_header
= false,
134 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_128
,
135 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
137 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
141 .path
= "/crypto/block/luks/default",
142 .create_opts
= &luks_create_opts_default
,
143 .open_opts
= &luks_open_opts
,
145 .expect_header
= true,
147 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
148 .cipher_mode
= QCRYPTO_CIPHER_MODE_XTS
,
149 .hash_alg
= QCRYPTO_HASH_ALG_SHA256
,
151 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
156 .path
= "/crypto/block/luks/aes-256-cbc-plain64",
157 .create_opts
= &luks_create_opts_aes256_cbc_plain64
,
158 .open_opts
= &luks_open_opts
,
160 .expect_header
= true,
162 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
163 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
164 .hash_alg
= QCRYPTO_HASH_ALG_SHA256
,
166 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
171 .path
= "/crypto/block/luks/aes-256-cbc-essiv",
172 .create_opts
= &luks_create_opts_aes256_cbc_essiv
,
173 .open_opts
= &luks_open_opts
,
175 .expect_header
= true,
177 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
178 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
179 .hash_alg
= QCRYPTO_HASH_ALG_SHA1
,
181 .ivgen_alg
= QCRYPTO_IVGEN_ALG_ESSIV
,
182 .ivgen_hash
= QCRYPTO_HASH_ALG_SHA256
,
190 static ssize_t
test_block_read_func(QCryptoBlock
*block
,
197 Buffer
*header
= opaque
;
199 g_assert_cmpint(offset
+ buflen
, <=, header
->capacity
);
201 memcpy(buf
, header
->buffer
+ offset
, buflen
);
207 static ssize_t
test_block_init_func(QCryptoBlock
*block
,
212 Buffer
*header
= opaque
;
214 g_assert_cmpint(header
->capacity
, ==, 0);
216 buffer_reserve(header
, headerlen
);
222 static ssize_t
test_block_write_func(QCryptoBlock
*block
,
229 Buffer
*header
= opaque
;
231 g_assert_cmpint(buflen
+ offset
, <=, header
->capacity
);
233 memcpy(header
->buffer
+ offset
, buf
, buflen
);
234 header
->offset
= offset
+ buflen
;
240 static Object
*test_block_secret(void)
242 return object_new_with_props(
244 object_get_objects_root(),
251 static void test_block_assert_setup(const struct QCryptoBlockTestData
*data
,
255 QCryptoCipher
*cipher
;
257 ivgen
= qcrypto_block_get_ivgen(blk
);
258 cipher
= qcrypto_block_get_cipher(blk
);
263 g_assert_cmpint(data
->cipher_alg
, ==, cipher
->alg
);
264 g_assert_cmpint(data
->cipher_mode
, ==, cipher
->mode
);
265 g_assert_cmpint(data
->hash_alg
, ==,
266 qcrypto_block_get_kdf_hash(blk
));
268 g_assert_cmpint(data
->ivgen_alg
, ==,
269 qcrypto_ivgen_get_algorithm(ivgen
));
270 g_assert_cmpint(data
->ivgen_hash
, ==,
271 qcrypto_ivgen_get_hash(ivgen
));
275 static void test_block(gconstpointer opaque
)
277 const struct QCryptoBlockTestData
*data
= opaque
;
280 Object
*sec
= test_block_secret();
282 memset(&header
, 0, sizeof(header
));
283 buffer_init(&header
, "header");
285 blk
= qcrypto_block_create(data
->create_opts
, NULL
,
286 test_block_init_func
,
287 test_block_write_func
,
292 if (data
->expect_header
) {
293 g_assert_cmpint(header
.capacity
, >, 0);
295 g_assert_cmpint(header
.capacity
, ==, 0);
298 test_block_assert_setup(data
, blk
);
300 qcrypto_block_free(blk
);
301 object_unparent(sec
);
303 /* Ensure we can't open without the secret */
304 blk
= qcrypto_block_open(data
->open_opts
, NULL
,
305 test_block_read_func
,
309 g_assert(blk
== NULL
);
311 /* Ensure we can't open without the secret, unless NO_IO */
312 blk
= qcrypto_block_open(data
->open_opts
, NULL
,
313 test_block_read_func
,
315 QCRYPTO_BLOCK_OPEN_NO_IO
,
318 g_assert(qcrypto_block_get_cipher(blk
) == NULL
);
319 g_assert(qcrypto_block_get_ivgen(blk
) == NULL
);
321 qcrypto_block_free(blk
);
324 /* Now open for real with secret */
325 sec
= test_block_secret();
326 blk
= qcrypto_block_open(data
->open_opts
, NULL
,
327 test_block_read_func
,
333 test_block_assert_setup(data
, blk
);
335 qcrypto_block_free(blk
);
337 object_unparent(sec
);
339 buffer_free(&header
);
343 int main(int argc
, char **argv
)
347 module_call_init(MODULE_INIT_QOM
);
348 g_test_init(&argc
, &argv
, NULL
);
350 g_assert(qcrypto_init(NULL
) == 0);
352 for (i
= 0; i
< G_N_ELEMENTS(test_data
); i
++) {
353 if (test_data
[i
].open_opts
->format
== Q_CRYPTO_BLOCK_FORMAT_LUKS
&&
354 !qcrypto_hash_supports(test_data
[i
].hash_alg
)) {
357 if (!test_data
[i
].slow
||
359 g_test_add_data_func(test_data
[i
].path
, &test_data
[i
], test_block
);