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(CONFIG_UUID) && (defined(_WIN32) || defined RUSAGE_THREAD)
37 static QCryptoBlockCreateOptions qcow_create_opts
= {
38 .format
= Q_CRYPTO_BLOCK_FORMAT_QCOW
,
40 .has_key_secret
= true,
41 .key_secret
= (char *)"sec0",
45 static QCryptoBlockOpenOptions qcow_open_opts
= {
46 .format
= Q_CRYPTO_BLOCK_FORMAT_QCOW
,
48 .has_key_secret
= true,
49 .key_secret
= (char *)"sec0",
55 static QCryptoBlockOpenOptions luks_open_opts
= {
56 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
58 .has_key_secret
= true,
59 .key_secret
= (char *)"sec0",
64 /* Creation with all default values */
65 static QCryptoBlockCreateOptions luks_create_opts_default
= {
66 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
68 .has_key_secret
= true,
69 .key_secret
= (char *)"sec0",
74 /* ...and with explicit values */
75 static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_plain64
= {
76 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
78 .has_key_secret
= true,
79 .key_secret
= (char *)"sec0",
80 .has_cipher_alg
= true,
81 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
82 .has_cipher_mode
= true,
83 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
84 .has_ivgen_alg
= true,
85 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
90 static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_essiv
= {
91 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
93 .has_key_secret
= true,
94 .key_secret
= (char *)"sec0",
95 .has_cipher_alg
= true,
96 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
97 .has_cipher_mode
= true,
98 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
99 .has_ivgen_alg
= true,
100 .ivgen_alg
= QCRYPTO_IVGEN_ALG_ESSIV
,
101 .has_ivgen_hash_alg
= true,
102 .ivgen_hash_alg
= QCRYPTO_HASH_ALG_SHA256
,
103 .has_hash_alg
= true,
104 .hash_alg
= QCRYPTO_HASH_ALG_SHA1
,
107 #endif /* TEST_LUKS */
110 static struct QCryptoBlockTestData
{
112 QCryptoBlockCreateOptions
*create_opts
;
113 QCryptoBlockOpenOptions
*open_opts
;
117 QCryptoCipherAlgorithm cipher_alg
;
118 QCryptoCipherMode cipher_mode
;
119 QCryptoHashAlgorithm hash_alg
;
121 QCryptoIVGenAlgorithm ivgen_alg
;
122 QCryptoHashAlgorithm ivgen_hash
;
127 .path
= "/crypto/block/qcow",
128 .create_opts
= &qcow_create_opts
,
129 .open_opts
= &qcow_open_opts
,
131 .expect_header
= false,
133 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_128
,
134 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
136 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
140 .path
= "/crypto/block/luks/default",
141 .create_opts
= &luks_create_opts_default
,
142 .open_opts
= &luks_open_opts
,
144 .expect_header
= true,
146 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
147 .cipher_mode
= QCRYPTO_CIPHER_MODE_XTS
,
148 .hash_alg
= QCRYPTO_HASH_ALG_SHA256
,
150 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
155 .path
= "/crypto/block/luks/aes-256-cbc-plain64",
156 .create_opts
= &luks_create_opts_aes256_cbc_plain64
,
157 .open_opts
= &luks_open_opts
,
159 .expect_header
= true,
161 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
162 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
163 .hash_alg
= QCRYPTO_HASH_ALG_SHA256
,
165 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
170 .path
= "/crypto/block/luks/aes-256-cbc-essiv",
171 .create_opts
= &luks_create_opts_aes256_cbc_essiv
,
172 .open_opts
= &luks_open_opts
,
174 .expect_header
= true,
176 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
177 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
178 .hash_alg
= QCRYPTO_HASH_ALG_SHA1
,
180 .ivgen_alg
= QCRYPTO_IVGEN_ALG_ESSIV
,
181 .ivgen_hash
= QCRYPTO_HASH_ALG_SHA256
,
189 static ssize_t
test_block_read_func(QCryptoBlock
*block
,
196 Buffer
*header
= opaque
;
198 g_assert_cmpint(offset
+ buflen
, <=, header
->capacity
);
200 memcpy(buf
, header
->buffer
+ offset
, buflen
);
206 static ssize_t
test_block_init_func(QCryptoBlock
*block
,
211 Buffer
*header
= opaque
;
213 g_assert_cmpint(header
->capacity
, ==, 0);
215 buffer_reserve(header
, headerlen
);
221 static ssize_t
test_block_write_func(QCryptoBlock
*block
,
228 Buffer
*header
= opaque
;
230 g_assert_cmpint(buflen
+ offset
, <=, header
->capacity
);
232 memcpy(header
->buffer
+ offset
, buf
, buflen
);
233 header
->offset
= offset
+ buflen
;
239 static Object
*test_block_secret(void)
241 return object_new_with_props(
243 object_get_objects_root(),
250 static void test_block_assert_setup(const struct QCryptoBlockTestData
*data
,
254 QCryptoCipher
*cipher
;
256 ivgen
= qcrypto_block_get_ivgen(blk
);
257 cipher
= qcrypto_block_get_cipher(blk
);
262 g_assert_cmpint(data
->cipher_alg
, ==, cipher
->alg
);
263 g_assert_cmpint(data
->cipher_mode
, ==, cipher
->mode
);
264 g_assert_cmpint(data
->hash_alg
, ==,
265 qcrypto_block_get_kdf_hash(blk
));
267 g_assert_cmpint(data
->ivgen_alg
, ==,
268 qcrypto_ivgen_get_algorithm(ivgen
));
269 g_assert_cmpint(data
->ivgen_hash
, ==,
270 qcrypto_ivgen_get_hash(ivgen
));
274 static void test_block(gconstpointer opaque
)
276 const struct QCryptoBlockTestData
*data
= opaque
;
279 Object
*sec
= test_block_secret();
281 memset(&header
, 0, sizeof(header
));
282 buffer_init(&header
, "header");
284 blk
= qcrypto_block_create(data
->create_opts
,
285 test_block_init_func
,
286 test_block_write_func
,
291 if (data
->expect_header
) {
292 g_assert_cmpint(header
.capacity
, >, 0);
294 g_assert_cmpint(header
.capacity
, ==, 0);
297 test_block_assert_setup(data
, blk
);
299 qcrypto_block_free(blk
);
300 object_unparent(sec
);
302 /* Ensure we can't open without the secret */
303 blk
= qcrypto_block_open(data
->open_opts
,
304 test_block_read_func
,
308 g_assert(blk
== NULL
);
310 /* Ensure we can't open without the secret, unless NO_IO */
311 blk
= qcrypto_block_open(data
->open_opts
,
312 test_block_read_func
,
314 QCRYPTO_BLOCK_OPEN_NO_IO
,
317 g_assert(qcrypto_block_get_cipher(blk
) == NULL
);
318 g_assert(qcrypto_block_get_ivgen(blk
) == NULL
);
320 qcrypto_block_free(blk
);
323 /* Now open for real with secret */
324 sec
= test_block_secret();
325 blk
= qcrypto_block_open(data
->open_opts
,
326 test_block_read_func
,
332 test_block_assert_setup(data
, blk
);
334 qcrypto_block_free(blk
);
336 object_unparent(sec
);
338 buffer_free(&header
);
342 int main(int argc
, char **argv
)
346 module_call_init(MODULE_INIT_QOM
);
347 g_test_init(&argc
, &argv
, NULL
);
349 g_assert(qcrypto_init(NULL
) == 0);
351 for (i
= 0; i
< G_N_ELEMENTS(test_data
); i
++) {
352 if (test_data
[i
].open_opts
->format
== Q_CRYPTO_BLOCK_FORMAT_LUKS
&&
353 !qcrypto_hash_supports(test_data
[i
].hash_alg
)) {
356 if (!test_data
[i
].slow
||
358 g_test_add_data_func(test_data
[i
].path
, &test_data
[i
], test_block
);