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