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.1 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 "crypto/block-luks-priv.h"
26 #include "qemu/buffer.h"
27 #include "qemu/module.h"
28 #include "crypto/secret.h"
30 #include <sys/resource.h>
33 #if (defined(_WIN32) || defined RUSAGE_THREAD) && \
34 (defined(CONFIG_NETTLE) || defined(CONFIG_GCRYPT) || \
35 defined(CONFIG_GNUTLS_CRYPTO))
41 static QCryptoBlockCreateOptions qcow_create_opts
= {
42 .format
= Q_CRYPTO_BLOCK_FORMAT_QCOW
,
44 .has_key_secret
= true,
45 .key_secret
= (char *)"sec0",
49 static QCryptoBlockOpenOptions qcow_open_opts
= {
50 .format
= Q_CRYPTO_BLOCK_FORMAT_QCOW
,
52 .has_key_secret
= true,
53 .key_secret
= (char *)"sec0",
59 static QCryptoBlockOpenOptions luks_open_opts
= {
60 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
62 .has_key_secret
= true,
63 .key_secret
= (char *)"sec0",
68 /* Creation with all default values */
69 static QCryptoBlockCreateOptions luks_create_opts_default
= {
70 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
72 .has_key_secret
= true,
73 .key_secret
= (char *)"sec0",
78 /* ...and with explicit values */
79 static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_plain64
= {
80 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
82 .has_key_secret
= true,
83 .key_secret
= (char *)"sec0",
84 .has_cipher_alg
= true,
85 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
86 .has_cipher_mode
= true,
87 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
88 .has_ivgen_alg
= true,
89 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
94 static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_essiv
= {
95 .format
= Q_CRYPTO_BLOCK_FORMAT_LUKS
,
97 .has_key_secret
= true,
98 .key_secret
= (char *)"sec0",
99 .has_cipher_alg
= true,
100 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
101 .has_cipher_mode
= true,
102 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
103 .has_ivgen_alg
= true,
104 .ivgen_alg
= QCRYPTO_IVGEN_ALG_ESSIV
,
105 .has_ivgen_hash_alg
= true,
106 .ivgen_hash_alg
= QCRYPTO_HASH_ALG_SHA256
,
107 .has_hash_alg
= true,
108 .hash_alg
= QCRYPTO_HASH_ALG_SHA1
,
111 #endif /* TEST_LUKS */
114 static struct QCryptoBlockTestData
{
116 QCryptoBlockCreateOptions
*create_opts
;
117 QCryptoBlockOpenOptions
*open_opts
;
121 QCryptoCipherAlgorithm cipher_alg
;
122 QCryptoCipherMode cipher_mode
;
123 QCryptoHashAlgorithm hash_alg
;
125 QCryptoIVGenAlgorithm ivgen_alg
;
126 QCryptoHashAlgorithm ivgen_hash
;
131 .path
= "/crypto/block/qcow",
132 .create_opts
= &qcow_create_opts
,
133 .open_opts
= &qcow_open_opts
,
135 .expect_header
= false,
137 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_128
,
138 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
140 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
144 .path
= "/crypto/block/luks/default",
145 .create_opts
= &luks_create_opts_default
,
146 .open_opts
= &luks_open_opts
,
148 .expect_header
= true,
150 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
151 .cipher_mode
= QCRYPTO_CIPHER_MODE_XTS
,
152 .hash_alg
= QCRYPTO_HASH_ALG_SHA256
,
154 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
159 .path
= "/crypto/block/luks/aes-256-cbc-plain64",
160 .create_opts
= &luks_create_opts_aes256_cbc_plain64
,
161 .open_opts
= &luks_open_opts
,
163 .expect_header
= true,
165 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
166 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
167 .hash_alg
= QCRYPTO_HASH_ALG_SHA256
,
169 .ivgen_alg
= QCRYPTO_IVGEN_ALG_PLAIN64
,
174 .path
= "/crypto/block/luks/aes-256-cbc-essiv",
175 .create_opts
= &luks_create_opts_aes256_cbc_essiv
,
176 .open_opts
= &luks_open_opts
,
178 .expect_header
= true,
180 .cipher_alg
= QCRYPTO_CIPHER_ALG_AES_256
,
181 .cipher_mode
= QCRYPTO_CIPHER_MODE_CBC
,
182 .hash_alg
= QCRYPTO_HASH_ALG_SHA1
,
184 .ivgen_alg
= QCRYPTO_IVGEN_ALG_ESSIV
,
185 .ivgen_hash
= QCRYPTO_HASH_ALG_SHA256
,
193 static int test_block_read_func(QCryptoBlock
*block
,
200 Buffer
*header
= opaque
;
202 g_assert_cmpint(offset
+ buflen
, <=, header
->capacity
);
204 memcpy(buf
, header
->buffer
+ offset
, buflen
);
210 static int test_block_init_func(QCryptoBlock
*block
,
215 Buffer
*header
= opaque
;
217 g_assert_cmpint(header
->capacity
, ==, 0);
219 buffer_reserve(header
, headerlen
);
225 static int test_block_write_func(QCryptoBlock
*block
,
232 Buffer
*header
= opaque
;
234 g_assert_cmpint(buflen
+ offset
, <=, header
->capacity
);
236 memcpy(header
->buffer
+ offset
, buf
, buflen
);
237 header
->offset
= offset
+ buflen
;
243 static Object
*test_block_secret(void)
245 return object_new_with_props(
247 object_get_objects_root(),
254 static void test_block_assert_setup(const struct QCryptoBlockTestData
*data
,
258 QCryptoCipher
*cipher
;
260 ivgen
= qcrypto_block_get_ivgen(blk
);
261 cipher
= qcrypto_block_get_cipher(blk
);
266 g_assert_cmpint(data
->cipher_alg
, ==, cipher
->alg
);
267 g_assert_cmpint(data
->cipher_mode
, ==, cipher
->mode
);
268 g_assert_cmpint(data
->hash_alg
, ==,
269 qcrypto_block_get_kdf_hash(blk
));
271 g_assert_cmpint(data
->ivgen_alg
, ==,
272 qcrypto_ivgen_get_algorithm(ivgen
));
273 g_assert_cmpint(data
->ivgen_hash
, ==,
274 qcrypto_ivgen_get_hash(ivgen
));
278 static void test_block(gconstpointer opaque
)
280 const struct QCryptoBlockTestData
*data
= opaque
;
283 Object
*sec
= test_block_secret();
285 memset(&header
, 0, sizeof(header
));
286 buffer_init(&header
, "header");
288 blk
= qcrypto_block_create(data
->create_opts
, NULL
,
289 test_block_init_func
,
290 test_block_write_func
,
295 if (data
->expect_header
) {
296 g_assert_cmpint(header
.capacity
, >, 0);
298 g_assert_cmpint(header
.capacity
, ==, 0);
301 test_block_assert_setup(data
, blk
);
303 qcrypto_block_free(blk
);
304 object_unparent(sec
);
306 /* Ensure we can't open without the secret */
307 blk
= qcrypto_block_open(data
->open_opts
, NULL
,
308 test_block_read_func
,
313 g_assert(blk
== NULL
);
315 /* Ensure we can't open without the secret, unless NO_IO */
316 blk
= qcrypto_block_open(data
->open_opts
, NULL
,
317 test_block_read_func
,
319 QCRYPTO_BLOCK_OPEN_NO_IO
,
323 g_assert(qcrypto_block_get_cipher(blk
) == NULL
);
324 g_assert(qcrypto_block_get_ivgen(blk
) == NULL
);
326 qcrypto_block_free(blk
);
329 /* Now open for real with secret */
330 sec
= test_block_secret();
331 blk
= qcrypto_block_open(data
->open_opts
, NULL
,
332 test_block_read_func
,
339 test_block_assert_setup(data
, blk
);
341 qcrypto_block_free(blk
);
343 object_unparent(sec
);
345 buffer_free(&header
);
350 typedef const char *(*LuksHeaderDoBadStuff
)(QCryptoBlockLUKSHeader
*hdr
);
353 test_luks_bad_header(gconstpointer data
)
355 LuksHeaderDoBadStuff badstuff
= data
;
358 Object
*sec
= test_block_secret();
359 QCryptoBlockLUKSHeader hdr
;
363 memset(&buf
, 0, sizeof(buf
));
364 buffer_init(&buf
, "header");
366 /* Correctly create the volume initially */
367 blk
= qcrypto_block_create(&luks_create_opts_default
, NULL
,
368 test_block_init_func
,
369 test_block_write_func
,
374 qcrypto_block_free(blk
);
376 /* Mangle it in some unpleasant way */
377 g_assert(buf
.offset
>= sizeof(hdr
));
378 memcpy(&hdr
, buf
.buffer
, sizeof(hdr
));
379 qcrypto_block_luks_to_disk_endian(&hdr
);
381 msg
= badstuff(&hdr
);
383 qcrypto_block_luks_from_disk_endian(&hdr
);
384 memcpy(buf
.buffer
, &hdr
, sizeof(hdr
));
386 /* Check that we fail to open it again */
387 blk
= qcrypto_block_open(&luks_open_opts
, NULL
,
388 test_block_read_func
,
396 g_assert_cmpstr(error_get_pretty(err
), ==, msg
);
399 object_unparent(sec
);
404 static const char *luks_bad_null_term_cipher_name(QCryptoBlockLUKSHeader
*hdr
)
406 /* Replace NUL termination with spaces */
407 char *offset
= hdr
->cipher_name
+ strlen(hdr
->cipher_name
);
408 memset(offset
, ' ', sizeof(hdr
->cipher_name
) - (offset
- hdr
->cipher_name
));
410 return "LUKS header cipher name is not NUL terminated";
413 static const char *luks_bad_null_term_cipher_mode(QCryptoBlockLUKSHeader
*hdr
)
415 /* Replace NUL termination with spaces */
416 char *offset
= hdr
->cipher_mode
+ strlen(hdr
->cipher_mode
);
417 memset(offset
, ' ', sizeof(hdr
->cipher_mode
) - (offset
- hdr
->cipher_mode
));
419 return "LUKS header cipher mode is not NUL terminated";
422 static const char *luks_bad_null_term_hash_spec(QCryptoBlockLUKSHeader
*hdr
)
424 /* Replace NUL termination with spaces */
425 char *offset
= hdr
->hash_spec
+ strlen(hdr
->hash_spec
);
426 memset(offset
, ' ', sizeof(hdr
->hash_spec
) - (offset
- hdr
->hash_spec
));
428 return "LUKS header hash spec is not NUL terminated";
431 static const char *luks_bad_cipher_name_empty(QCryptoBlockLUKSHeader
*hdr
)
433 memcpy(hdr
->cipher_name
, "", 1);
435 return "Algorithm '' with key size 32 bytes not supported";
438 static const char *luks_bad_cipher_name_unknown(QCryptoBlockLUKSHeader
*hdr
)
440 memcpy(hdr
->cipher_name
, "aess", 5);
442 return "Algorithm 'aess' with key size 32 bytes not supported";
445 static const char *luks_bad_cipher_xts_size(QCryptoBlockLUKSHeader
*hdr
)
447 hdr
->master_key_len
= 33;
449 return "XTS cipher key length should be a multiple of 2";
452 static const char *luks_bad_cipher_cbc_size(QCryptoBlockLUKSHeader
*hdr
)
454 hdr
->master_key_len
= 33;
455 memcpy(hdr
->cipher_mode
, "cbc-essiv", 10);
457 return "Algorithm 'aes' with key size 33 bytes not supported";
460 static const char *luks_bad_cipher_mode_empty(QCryptoBlockLUKSHeader
*hdr
)
462 memcpy(hdr
->cipher_mode
, "", 1);
464 return "Unexpected cipher mode string format ''";
467 static const char *luks_bad_cipher_mode_unknown(QCryptoBlockLUKSHeader
*hdr
)
469 memcpy(hdr
->cipher_mode
, "xfs", 4);
471 return "Unexpected cipher mode string format 'xfs'";
474 static const char *luks_bad_ivgen_separator(QCryptoBlockLUKSHeader
*hdr
)
476 memcpy(hdr
->cipher_mode
, "xts:plain64", 12);
478 return "Unexpected cipher mode string format 'xts:plain64'";
481 static const char *luks_bad_ivgen_name_empty(QCryptoBlockLUKSHeader
*hdr
)
483 memcpy(hdr
->cipher_mode
, "xts-", 5);
485 return "IV generator '' not supported";
488 static const char *luks_bad_ivgen_name_unknown(QCryptoBlockLUKSHeader
*hdr
)
490 memcpy(hdr
->cipher_mode
, "xts-plain65", 12);
492 return "IV generator 'plain65' not supported";
495 static const char *luks_bad_ivgen_hash_empty(QCryptoBlockLUKSHeader
*hdr
)
497 memcpy(hdr
->cipher_mode
, "xts-plain65:", 13);
499 return "Hash algorithm '' not supported";
502 static const char *luks_bad_ivgen_hash_unknown(QCryptoBlockLUKSHeader
*hdr
)
504 memcpy(hdr
->cipher_mode
, "xts-plain65:sha257", 19);
506 return "Hash algorithm 'sha257' not supported";
509 static const char *luks_bad_hash_spec_empty(QCryptoBlockLUKSHeader
*hdr
)
511 memcpy(hdr
->hash_spec
, "", 1);
513 return "Hash algorithm '' not supported";
516 static const char *luks_bad_hash_spec_unknown(QCryptoBlockLUKSHeader
*hdr
)
518 memcpy(hdr
->hash_spec
, "sha2566", 8);
520 return "Hash algorithm 'sha2566' not supported";
523 static const char *luks_bad_stripes(QCryptoBlockLUKSHeader
*hdr
)
525 hdr
->key_slots
[0].stripes
= 3999;
527 return "Keyslot 0 is corrupted (stripes 3999 != 4000)";
530 static const char *luks_bad_key_overlap_header(QCryptoBlockLUKSHeader
*hdr
)
532 hdr
->key_slots
[0].key_offset_sector
= 2;
534 return "Keyslot 0 is overlapping with the LUKS header";
537 static const char *luks_bad_key_overlap_key(QCryptoBlockLUKSHeader
*hdr
)
539 hdr
->key_slots
[0].key_offset_sector
= hdr
->key_slots
[1].key_offset_sector
;
541 return "Keyslots 0 and 1 are overlapping in the header";
544 static const char *luks_bad_key_overlap_payload(QCryptoBlockLUKSHeader
*hdr
)
546 hdr
->key_slots
[0].key_offset_sector
= hdr
->payload_offset_sector
+ 42;
548 return "Keyslot 0 is overlapping with the encrypted payload";
551 static const char *luks_bad_payload_overlap_header(QCryptoBlockLUKSHeader
*hdr
)
553 hdr
->payload_offset_sector
= 2;
555 return "LUKS payload is overlapping with the header";
558 static const char *luks_bad_key_iterations(QCryptoBlockLUKSHeader
*hdr
)
560 hdr
->key_slots
[0].iterations
= 0;
562 return "Keyslot 0 iteration count is zero";
565 static const char *luks_bad_iterations(QCryptoBlockLUKSHeader
*hdr
)
567 hdr
->master_key_iterations
= 0;
569 return "LUKS key iteration count is zero";
573 int main(int argc
, char **argv
)
577 module_call_init(MODULE_INIT_QOM
);
578 g_test_init(&argc
, &argv
, NULL
);
580 g_assert(qcrypto_init(NULL
) == 0);
582 for (i
= 0; i
< G_N_ELEMENTS(test_data
); i
++) {
583 if (test_data
[i
].open_opts
->format
== Q_CRYPTO_BLOCK_FORMAT_LUKS
&&
584 !qcrypto_hash_supports(test_data
[i
].hash_alg
)) {
587 if (!test_data
[i
].slow
||
589 g_test_add_data_func(test_data
[i
].path
, &test_data
[i
], test_block
);
595 g_test_add_data_func("/crypto/block/luks/bad/cipher-name-nul-term",
596 luks_bad_null_term_cipher_name
,
597 test_luks_bad_header
);
598 g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-nul-term",
599 luks_bad_null_term_cipher_mode
,
600 test_luks_bad_header
);
601 g_test_add_data_func("/crypto/block/luks/bad/hash-spec-nul-term",
602 luks_bad_null_term_hash_spec
,
603 test_luks_bad_header
);
604 g_test_add_data_func("/crypto/block/luks/bad/cipher-name-empty",
605 luks_bad_cipher_name_empty
,
606 test_luks_bad_header
);
607 g_test_add_data_func("/crypto/block/luks/bad/cipher-name-unknown",
608 luks_bad_cipher_name_unknown
,
609 test_luks_bad_header
);
610 g_test_add_data_func("/crypto/block/luks/bad/cipher-xts-size",
611 luks_bad_cipher_xts_size
,
612 test_luks_bad_header
);
613 g_test_add_data_func("/crypto/block/luks/bad/cipher-cbc-size",
614 luks_bad_cipher_cbc_size
,
615 test_luks_bad_header
);
616 g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-empty",
617 luks_bad_cipher_mode_empty
,
618 test_luks_bad_header
);
619 g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-unknown",
620 luks_bad_cipher_mode_unknown
,
621 test_luks_bad_header
);
622 g_test_add_data_func("/crypto/block/luks/bad/ivgen-separator",
623 luks_bad_ivgen_separator
,
624 test_luks_bad_header
);
625 g_test_add_data_func("/crypto/block/luks/bad/ivgen-name-empty",
626 luks_bad_ivgen_name_empty
,
627 test_luks_bad_header
);
628 g_test_add_data_func("/crypto/block/luks/bad/ivgen-name-unknown",
629 luks_bad_ivgen_name_unknown
,
630 test_luks_bad_header
);
631 g_test_add_data_func("/crypto/block/luks/bad/ivgen-hash-empty",
632 luks_bad_ivgen_hash_empty
,
633 test_luks_bad_header
);
634 g_test_add_data_func("/crypto/block/luks/bad/ivgen-hash-unknown",
635 luks_bad_ivgen_hash_unknown
,
636 test_luks_bad_header
);
637 g_test_add_data_func("/crypto/block/luks/bad/hash-spec-empty",
638 luks_bad_hash_spec_empty
,
639 test_luks_bad_header
);
640 g_test_add_data_func("/crypto/block/luks/bad/hash-spec-unknown",
641 luks_bad_hash_spec_unknown
,
642 test_luks_bad_header
);
643 g_test_add_data_func("/crypto/block/luks/bad/stripes",
645 test_luks_bad_header
);
646 g_test_add_data_func("/crypto/block/luks/bad/key-overlap-header",
647 luks_bad_key_overlap_header
,
648 test_luks_bad_header
);
649 g_test_add_data_func("/crypto/block/luks/bad/key-overlap-key",
650 luks_bad_key_overlap_key
,
651 test_luks_bad_header
);
652 g_test_add_data_func("/crypto/block/luks/bad/key-overlap-payload",
653 luks_bad_key_overlap_payload
,
654 test_luks_bad_header
);
655 g_test_add_data_func("/crypto/block/luks/bad/payload-overlap-header",
656 luks_bad_payload_overlap_header
,
657 test_luks_bad_header
);
658 g_test_add_data_func("/crypto/block/luks/bad/iterations",
660 test_luks_bad_header
);
661 g_test_add_data_func("/crypto/block/luks/bad/key-iterations",
662 luks_bad_key_iterations
,
663 test_luks_bad_header
);