1 /* 2 * QEMU Crypto block encryption 3 * 4 * Copyright (c) 2016 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.1 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 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" 29 #ifndef _WIN32 30 #include <sys/resource.h> 31 #endif 32 33 #if (defined(_WIN32) || defined RUSAGE_THREAD) && \ 34 (defined(CONFIG_NETTLE) || defined(CONFIG_GCRYPT) || \ 35 defined(CONFIG_GNUTLS_CRYPTO)) 36 #define TEST_LUKS 37 #else 38 #undef TEST_LUKS 39 #endif 40 41 static QCryptoBlockCreateOptions qcow_create_opts = { 42 .format = Q_CRYPTO_BLOCK_FORMAT_QCOW, 43 .u.qcow = { 44 .key_secret = (char *)"sec0", 45 }, 46 }; 47 48 static QCryptoBlockOpenOptions qcow_open_opts = { 49 .format = Q_CRYPTO_BLOCK_FORMAT_QCOW, 50 .u.qcow = { 51 .key_secret = (char *)"sec0", 52 }, 53 }; 54 55 56 #ifdef TEST_LUKS 57 static QCryptoBlockOpenOptions luks_open_opts = { 58 .format = Q_CRYPTO_BLOCK_FORMAT_LUKS, 59 .u.luks = { 60 .key_secret = (char *)"sec0", 61 }, 62 }; 63 64 65 /* Creation with all default values */ 66 static QCryptoBlockCreateOptions luks_create_opts_default = { 67 .format = Q_CRYPTO_BLOCK_FORMAT_LUKS, 68 .u.luks = { 69 .key_secret = (char *)"sec0", 70 }, 71 }; 72 73 74 /* ...and with explicit values */ 75 static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_plain64 = { 76 .format = Q_CRYPTO_BLOCK_FORMAT_LUKS, 77 .u.luks = { 78 .key_secret = (char *)"sec0", 79 .has_cipher_alg = true, 80 .cipher_alg = QCRYPTO_CIPHER_ALG_AES_256, 81 .has_cipher_mode = true, 82 .cipher_mode = QCRYPTO_CIPHER_MODE_CBC, 83 .has_ivgen_alg = true, 84 .ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64, 85 }, 86 }; 87 88 89 static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_essiv = { 90 .format = Q_CRYPTO_BLOCK_FORMAT_LUKS, 91 .u.luks = { 92 .key_secret = (char *)"sec0", 93 .has_cipher_alg = true, 94 .cipher_alg = QCRYPTO_CIPHER_ALG_AES_256, 95 .has_cipher_mode = true, 96 .cipher_mode = QCRYPTO_CIPHER_MODE_CBC, 97 .has_ivgen_alg = true, 98 .ivgen_alg = QCRYPTO_IVGEN_ALG_ESSIV, 99 .has_ivgen_hash_alg = true, 100 .ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256, 101 .has_hash_alg = true, 102 .hash_alg = QCRYPTO_HASH_ALG_SHA1, 103 }, 104 }; 105 #endif /* TEST_LUKS */ 106 107 108 static struct QCryptoBlockTestData { 109 const char *path; 110 QCryptoBlockCreateOptions *create_opts; 111 QCryptoBlockOpenOptions *open_opts; 112 113 bool expect_header; 114 115 QCryptoCipherAlgorithm cipher_alg; 116 QCryptoCipherMode cipher_mode; 117 QCryptoHashAlgorithm hash_alg; 118 119 QCryptoIVGenAlgorithm ivgen_alg; 120 QCryptoHashAlgorithm ivgen_hash; 121 122 bool slow; 123 } test_data[] = { 124 { 125 .path = "/crypto/block/qcow", 126 .create_opts = &qcow_create_opts, 127 .open_opts = &qcow_open_opts, 128 129 .expect_header = false, 130 131 .cipher_alg = QCRYPTO_CIPHER_ALG_AES_128, 132 .cipher_mode = QCRYPTO_CIPHER_MODE_CBC, 133 134 .ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64, 135 }, 136 #ifdef TEST_LUKS 137 { 138 .path = "/crypto/block/luks/default", 139 .create_opts = &luks_create_opts_default, 140 .open_opts = &luks_open_opts, 141 142 .expect_header = true, 143 144 .cipher_alg = QCRYPTO_CIPHER_ALG_AES_256, 145 .cipher_mode = QCRYPTO_CIPHER_MODE_XTS, 146 .hash_alg = QCRYPTO_HASH_ALG_SHA256, 147 148 .ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64, 149 150 .slow = true, 151 }, 152 { 153 .path = "/crypto/block/luks/aes-256-cbc-plain64", 154 .create_opts = &luks_create_opts_aes256_cbc_plain64, 155 .open_opts = &luks_open_opts, 156 157 .expect_header = true, 158 159 .cipher_alg = QCRYPTO_CIPHER_ALG_AES_256, 160 .cipher_mode = QCRYPTO_CIPHER_MODE_CBC, 161 .hash_alg = QCRYPTO_HASH_ALG_SHA256, 162 163 .ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64, 164 165 .slow = true, 166 }, 167 { 168 .path = "/crypto/block/luks/aes-256-cbc-essiv", 169 .create_opts = &luks_create_opts_aes256_cbc_essiv, 170 .open_opts = &luks_open_opts, 171 172 .expect_header = true, 173 174 .cipher_alg = QCRYPTO_CIPHER_ALG_AES_256, 175 .cipher_mode = QCRYPTO_CIPHER_MODE_CBC, 176 .hash_alg = QCRYPTO_HASH_ALG_SHA1, 177 178 .ivgen_alg = QCRYPTO_IVGEN_ALG_ESSIV, 179 .ivgen_hash = QCRYPTO_HASH_ALG_SHA256, 180 181 .slow = true, 182 }, 183 #endif 184 }; 185 186 187 static int test_block_read_func(QCryptoBlock *block, 188 size_t offset, 189 uint8_t *buf, 190 size_t buflen, 191 void *opaque, 192 Error **errp) 193 { 194 Buffer *header = opaque; 195 196 g_assert_cmpint(offset + buflen, <=, header->capacity); 197 198 memcpy(buf, header->buffer + offset, buflen); 199 200 return 0; 201 } 202 203 204 static int test_block_init_func(QCryptoBlock *block, 205 size_t headerlen, 206 void *opaque, 207 Error **errp) 208 { 209 Buffer *header = opaque; 210 211 g_assert_cmpint(header->capacity, ==, 0); 212 213 buffer_reserve(header, headerlen); 214 215 return 0; 216 } 217 218 219 static int test_block_write_func(QCryptoBlock *block, 220 size_t offset, 221 const uint8_t *buf, 222 size_t buflen, 223 void *opaque, 224 Error **errp) 225 { 226 Buffer *header = opaque; 227 228 g_assert_cmpint(buflen + offset, <=, header->capacity); 229 230 memcpy(header->buffer + offset, buf, buflen); 231 header->offset = offset + buflen; 232 233 return 0; 234 } 235 236 237 static Object *test_block_secret(void) 238 { 239 return object_new_with_props( 240 TYPE_QCRYPTO_SECRET, 241 object_get_objects_root(), 242 "sec0", 243 &error_abort, 244 "data", "123456", 245 NULL); 246 } 247 248 static void test_block_assert_setup(const struct QCryptoBlockTestData *data, 249 QCryptoBlock *blk) 250 { 251 QCryptoIVGen *ivgen; 252 QCryptoCipher *cipher; 253 254 ivgen = qcrypto_block_get_ivgen(blk); 255 cipher = qcrypto_block_get_cipher(blk); 256 257 g_assert(ivgen); 258 g_assert(cipher); 259 260 g_assert_cmpint(data->cipher_alg, ==, cipher->alg); 261 g_assert_cmpint(data->cipher_mode, ==, cipher->mode); 262 g_assert_cmpint(data->hash_alg, ==, 263 qcrypto_block_get_kdf_hash(blk)); 264 265 g_assert_cmpint(data->ivgen_alg, ==, 266 qcrypto_ivgen_get_algorithm(ivgen)); 267 g_assert_cmpint(data->ivgen_hash, ==, 268 qcrypto_ivgen_get_hash(ivgen)); 269 } 270 271 272 static void test_block(gconstpointer opaque) 273 { 274 const struct QCryptoBlockTestData *data = opaque; 275 QCryptoBlock *blk; 276 Buffer header; 277 Object *sec = test_block_secret(); 278 279 memset(&header, 0, sizeof(header)); 280 buffer_init(&header, "header"); 281 282 blk = qcrypto_block_create(data->create_opts, NULL, 283 test_block_init_func, 284 test_block_write_func, 285 &header, 286 0, 287 &error_abort); 288 g_assert(blk); 289 290 if (data->expect_header) { 291 g_assert_cmpint(header.capacity, >, 0); 292 } else { 293 g_assert_cmpint(header.capacity, ==, 0); 294 } 295 296 test_block_assert_setup(data, blk); 297 298 qcrypto_block_free(blk); 299 object_unparent(sec); 300 301 /* Ensure we can't open without the secret */ 302 blk = qcrypto_block_open(data->open_opts, NULL, 303 test_block_read_func, 304 &header, 305 0, 306 1, 307 NULL); 308 g_assert(blk == NULL); 309 310 /* Ensure we can't open without the secret, unless NO_IO */ 311 blk = qcrypto_block_open(data->open_opts, NULL, 312 test_block_read_func, 313 &header, 314 QCRYPTO_BLOCK_OPEN_NO_IO, 315 1, 316 &error_abort); 317 318 g_assert(qcrypto_block_get_cipher(blk) == NULL); 319 g_assert(qcrypto_block_get_ivgen(blk) == NULL); 320 321 qcrypto_block_free(blk); 322 323 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, 328 &header, 329 0, 330 1, 331 &error_abort); 332 g_assert(blk); 333 334 test_block_assert_setup(data, blk); 335 336 qcrypto_block_free(blk); 337 338 object_unparent(sec); 339 340 buffer_free(&header); 341 } 342 343 344 #ifdef TEST_LUKS 345 typedef const char *(*LuksHeaderDoBadStuff)(QCryptoBlockLUKSHeader *hdr); 346 347 static void 348 test_luks_bad_header(gconstpointer data) 349 { 350 LuksHeaderDoBadStuff badstuff = data; 351 QCryptoBlock *blk; 352 Buffer buf; 353 Object *sec = test_block_secret(); 354 QCryptoBlockLUKSHeader hdr; 355 Error *err = NULL; 356 const char *msg; 357 358 memset(&buf, 0, sizeof(buf)); 359 buffer_init(&buf, "header"); 360 361 /* Correctly create the volume initially */ 362 blk = qcrypto_block_create(&luks_create_opts_default, NULL, 363 test_block_init_func, 364 test_block_write_func, 365 &buf, 366 0, 367 &error_abort); 368 g_assert(blk); 369 370 qcrypto_block_free(blk); 371 372 /* Mangle it in some unpleasant way */ 373 g_assert(buf.offset >= sizeof(hdr)); 374 memcpy(&hdr, buf.buffer, sizeof(hdr)); 375 qcrypto_block_luks_to_disk_endian(&hdr); 376 377 msg = badstuff(&hdr); 378 379 qcrypto_block_luks_from_disk_endian(&hdr); 380 memcpy(buf.buffer, &hdr, sizeof(hdr)); 381 382 /* Check that we fail to open it again */ 383 blk = qcrypto_block_open(&luks_open_opts, NULL, 384 test_block_read_func, 385 &buf, 386 0, 387 1, 388 &err); 389 g_assert(!blk); 390 g_assert(err); 391 392 g_assert_cmpstr(error_get_pretty(err), ==, msg); 393 error_free(err); 394 395 object_unparent(sec); 396 397 buffer_free(&buf); 398 } 399 400 static const char *luks_bad_null_term_cipher_name(QCryptoBlockLUKSHeader *hdr) 401 { 402 /* Replace NUL termination with spaces */ 403 char *offset = hdr->cipher_name + strlen(hdr->cipher_name); 404 memset(offset, ' ', sizeof(hdr->cipher_name) - (offset - hdr->cipher_name)); 405 406 return "LUKS header cipher name is not NUL terminated"; 407 } 408 409 static const char *luks_bad_null_term_cipher_mode(QCryptoBlockLUKSHeader *hdr) 410 { 411 /* Replace NUL termination with spaces */ 412 char *offset = hdr->cipher_mode + strlen(hdr->cipher_mode); 413 memset(offset, ' ', sizeof(hdr->cipher_mode) - (offset - hdr->cipher_mode)); 414 415 return "LUKS header cipher mode is not NUL terminated"; 416 } 417 418 static const char *luks_bad_null_term_hash_spec(QCryptoBlockLUKSHeader *hdr) 419 { 420 /* Replace NUL termination with spaces */ 421 char *offset = hdr->hash_spec + strlen(hdr->hash_spec); 422 memset(offset, ' ', sizeof(hdr->hash_spec) - (offset - hdr->hash_spec)); 423 424 return "LUKS header hash spec is not NUL terminated"; 425 } 426 427 static const char *luks_bad_cipher_name_empty(QCryptoBlockLUKSHeader *hdr) 428 { 429 memcpy(hdr->cipher_name, "", 1); 430 431 return "Algorithm '' with key size 32 bytes not supported"; 432 } 433 434 static const char *luks_bad_cipher_name_unknown(QCryptoBlockLUKSHeader *hdr) 435 { 436 memcpy(hdr->cipher_name, "aess", 5); 437 438 return "Algorithm 'aess' with key size 32 bytes not supported"; 439 } 440 441 static const char *luks_bad_cipher_xts_size(QCryptoBlockLUKSHeader *hdr) 442 { 443 hdr->master_key_len = 33; 444 445 return "XTS cipher key length should be a multiple of 2"; 446 } 447 448 static const char *luks_bad_cipher_cbc_size(QCryptoBlockLUKSHeader *hdr) 449 { 450 hdr->master_key_len = 33; 451 memcpy(hdr->cipher_mode, "cbc-essiv", 10); 452 453 return "Algorithm 'aes' with key size 33 bytes not supported"; 454 } 455 456 static const char *luks_bad_cipher_mode_empty(QCryptoBlockLUKSHeader *hdr) 457 { 458 memcpy(hdr->cipher_mode, "", 1); 459 460 return "Unexpected cipher mode string format ''"; 461 } 462 463 static const char *luks_bad_cipher_mode_unknown(QCryptoBlockLUKSHeader *hdr) 464 { 465 memcpy(hdr->cipher_mode, "xfs", 4); 466 467 return "Unexpected cipher mode string format 'xfs'"; 468 } 469 470 static const char *luks_bad_ivgen_separator(QCryptoBlockLUKSHeader *hdr) 471 { 472 memcpy(hdr->cipher_mode, "xts:plain64", 12); 473 474 return "Unexpected cipher mode string format 'xts:plain64'"; 475 } 476 477 static const char *luks_bad_ivgen_name_empty(QCryptoBlockLUKSHeader *hdr) 478 { 479 memcpy(hdr->cipher_mode, "xts-", 5); 480 481 return "IV generator '' not supported"; 482 } 483 484 static const char *luks_bad_ivgen_name_unknown(QCryptoBlockLUKSHeader *hdr) 485 { 486 memcpy(hdr->cipher_mode, "xts-plain65", 12); 487 488 return "IV generator 'plain65' not supported"; 489 } 490 491 static const char *luks_bad_ivgen_hash_empty(QCryptoBlockLUKSHeader *hdr) 492 { 493 memcpy(hdr->cipher_mode, "xts-plain65:", 13); 494 495 return "Hash algorithm '' not supported"; 496 } 497 498 static const char *luks_bad_ivgen_hash_unknown(QCryptoBlockLUKSHeader *hdr) 499 { 500 memcpy(hdr->cipher_mode, "xts-plain65:sha257", 19); 501 502 return "Hash algorithm 'sha257' not supported"; 503 } 504 505 static const char *luks_bad_hash_spec_empty(QCryptoBlockLUKSHeader *hdr) 506 { 507 memcpy(hdr->hash_spec, "", 1); 508 509 return "Hash algorithm '' not supported"; 510 } 511 512 static const char *luks_bad_hash_spec_unknown(QCryptoBlockLUKSHeader *hdr) 513 { 514 memcpy(hdr->hash_spec, "sha2566", 8); 515 516 return "Hash algorithm 'sha2566' not supported"; 517 } 518 519 static const char *luks_bad_stripes(QCryptoBlockLUKSHeader *hdr) 520 { 521 hdr->key_slots[0].stripes = 3999; 522 523 return "Keyslot 0 is corrupted (stripes 3999 != 4000)"; 524 } 525 526 static const char *luks_bad_key_overlap_header(QCryptoBlockLUKSHeader *hdr) 527 { 528 hdr->key_slots[0].key_offset_sector = 2; 529 530 return "Keyslot 0 is overlapping with the LUKS header"; 531 } 532 533 static const char *luks_bad_key_overlap_key(QCryptoBlockLUKSHeader *hdr) 534 { 535 hdr->key_slots[0].key_offset_sector = hdr->key_slots[1].key_offset_sector; 536 537 return "Keyslots 0 and 1 are overlapping in the header"; 538 } 539 540 static const char *luks_bad_key_overlap_payload(QCryptoBlockLUKSHeader *hdr) 541 { 542 hdr->key_slots[0].key_offset_sector = hdr->payload_offset_sector + 42; 543 544 return "Keyslot 0 is overlapping with the encrypted payload"; 545 } 546 547 static const char *luks_bad_payload_overlap_header(QCryptoBlockLUKSHeader *hdr) 548 { 549 hdr->payload_offset_sector = 2; 550 551 return "LUKS payload is overlapping with the header"; 552 } 553 554 static const char *luks_bad_key_iterations(QCryptoBlockLUKSHeader *hdr) 555 { 556 hdr->key_slots[0].iterations = 0; 557 558 return "Keyslot 0 iteration count is zero"; 559 } 560 561 static const char *luks_bad_iterations(QCryptoBlockLUKSHeader *hdr) 562 { 563 hdr->master_key_iterations = 0; 564 565 return "LUKS key iteration count is zero"; 566 } 567 #endif 568 569 int main(int argc, char **argv) 570 { 571 gsize i; 572 573 module_call_init(MODULE_INIT_QOM); 574 g_test_init(&argc, &argv, NULL); 575 576 g_assert(qcrypto_init(NULL) == 0); 577 578 for (i = 0; i < G_N_ELEMENTS(test_data); i++) { 579 if (test_data[i].open_opts->format == Q_CRYPTO_BLOCK_FORMAT_LUKS && 580 !qcrypto_hash_supports(test_data[i].hash_alg)) { 581 continue; 582 } 583 if (!test_data[i].slow || 584 g_test_slow()) { 585 g_test_add_data_func(test_data[i].path, &test_data[i], test_block); 586 } 587 } 588 589 #ifdef TEST_LUKS 590 if (g_test_slow()) { 591 g_test_add_data_func("/crypto/block/luks/bad/cipher-name-nul-term", 592 luks_bad_null_term_cipher_name, 593 test_luks_bad_header); 594 g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-nul-term", 595 luks_bad_null_term_cipher_mode, 596 test_luks_bad_header); 597 g_test_add_data_func("/crypto/block/luks/bad/hash-spec-nul-term", 598 luks_bad_null_term_hash_spec, 599 test_luks_bad_header); 600 g_test_add_data_func("/crypto/block/luks/bad/cipher-name-empty", 601 luks_bad_cipher_name_empty, 602 test_luks_bad_header); 603 g_test_add_data_func("/crypto/block/luks/bad/cipher-name-unknown", 604 luks_bad_cipher_name_unknown, 605 test_luks_bad_header); 606 g_test_add_data_func("/crypto/block/luks/bad/cipher-xts-size", 607 luks_bad_cipher_xts_size, 608 test_luks_bad_header); 609 g_test_add_data_func("/crypto/block/luks/bad/cipher-cbc-size", 610 luks_bad_cipher_cbc_size, 611 test_luks_bad_header); 612 g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-empty", 613 luks_bad_cipher_mode_empty, 614 test_luks_bad_header); 615 g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-unknown", 616 luks_bad_cipher_mode_unknown, 617 test_luks_bad_header); 618 g_test_add_data_func("/crypto/block/luks/bad/ivgen-separator", 619 luks_bad_ivgen_separator, 620 test_luks_bad_header); 621 g_test_add_data_func("/crypto/block/luks/bad/ivgen-name-empty", 622 luks_bad_ivgen_name_empty, 623 test_luks_bad_header); 624 g_test_add_data_func("/crypto/block/luks/bad/ivgen-name-unknown", 625 luks_bad_ivgen_name_unknown, 626 test_luks_bad_header); 627 g_test_add_data_func("/crypto/block/luks/bad/ivgen-hash-empty", 628 luks_bad_ivgen_hash_empty, 629 test_luks_bad_header); 630 g_test_add_data_func("/crypto/block/luks/bad/ivgen-hash-unknown", 631 luks_bad_ivgen_hash_unknown, 632 test_luks_bad_header); 633 g_test_add_data_func("/crypto/block/luks/bad/hash-spec-empty", 634 luks_bad_hash_spec_empty, 635 test_luks_bad_header); 636 g_test_add_data_func("/crypto/block/luks/bad/hash-spec-unknown", 637 luks_bad_hash_spec_unknown, 638 test_luks_bad_header); 639 g_test_add_data_func("/crypto/block/luks/bad/stripes", 640 luks_bad_stripes, 641 test_luks_bad_header); 642 g_test_add_data_func("/crypto/block/luks/bad/key-overlap-header", 643 luks_bad_key_overlap_header, 644 test_luks_bad_header); 645 g_test_add_data_func("/crypto/block/luks/bad/key-overlap-key", 646 luks_bad_key_overlap_key, 647 test_luks_bad_header); 648 g_test_add_data_func("/crypto/block/luks/bad/key-overlap-payload", 649 luks_bad_key_overlap_payload, 650 test_luks_bad_header); 651 g_test_add_data_func("/crypto/block/luks/bad/payload-overlap-header", 652 luks_bad_payload_overlap_header, 653 test_luks_bad_header); 654 g_test_add_data_func("/crypto/block/luks/bad/iterations", 655 luks_bad_iterations, 656 test_luks_bad_header); 657 g_test_add_data_func("/crypto/block/luks/bad/key-iterations", 658 luks_bad_key_iterations, 659 test_luks_bad_header); 660 } 661 #endif 662 663 return g_test_run(); 664 } 665