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 NULL); 307 g_assert(blk == NULL); 308 309 /* Ensure we can't open without the secret, unless NO_IO */ 310 blk = qcrypto_block_open(data->open_opts, NULL, 311 test_block_read_func, 312 &header, 313 QCRYPTO_BLOCK_OPEN_NO_IO, 314 &error_abort); 315 316 g_assert(qcrypto_block_get_cipher(blk) == NULL); 317 g_assert(qcrypto_block_get_ivgen(blk) == NULL); 318 319 qcrypto_block_free(blk); 320 321 322 /* Now open for real with secret */ 323 sec = test_block_secret(); 324 blk = qcrypto_block_open(data->open_opts, NULL, 325 test_block_read_func, 326 &header, 327 0, 328 &error_abort); 329 g_assert(blk); 330 331 test_block_assert_setup(data, blk); 332 333 qcrypto_block_free(blk); 334 335 object_unparent(sec); 336 337 buffer_free(&header); 338 } 339 340 341 #ifdef TEST_LUKS 342 typedef const char *(*LuksHeaderDoBadStuff)(QCryptoBlockLUKSHeader *hdr); 343 344 static void 345 test_luks_bad_header(gconstpointer data) 346 { 347 LuksHeaderDoBadStuff badstuff = data; 348 QCryptoBlock *blk; 349 Buffer buf; 350 Object *sec = test_block_secret(); 351 QCryptoBlockLUKSHeader hdr; 352 Error *err = NULL; 353 const char *msg; 354 355 memset(&buf, 0, sizeof(buf)); 356 buffer_init(&buf, "header"); 357 358 /* Correctly create the volume initially */ 359 blk = qcrypto_block_create(&luks_create_opts_default, NULL, 360 test_block_init_func, 361 test_block_write_func, 362 &buf, 363 0, 364 &error_abort); 365 g_assert(blk); 366 367 qcrypto_block_free(blk); 368 369 /* Mangle it in some unpleasant way */ 370 g_assert(buf.offset >= sizeof(hdr)); 371 memcpy(&hdr, buf.buffer, sizeof(hdr)); 372 qcrypto_block_luks_to_disk_endian(&hdr); 373 374 msg = badstuff(&hdr); 375 376 qcrypto_block_luks_from_disk_endian(&hdr); 377 memcpy(buf.buffer, &hdr, sizeof(hdr)); 378 379 /* Check that we fail to open it again */ 380 blk = qcrypto_block_open(&luks_open_opts, NULL, 381 test_block_read_func, 382 &buf, 383 0, 384 &err); 385 g_assert(!blk); 386 g_assert(err); 387 388 g_assert_cmpstr(error_get_pretty(err), ==, msg); 389 error_free(err); 390 391 object_unparent(sec); 392 393 buffer_free(&buf); 394 } 395 396 static const char *luks_bad_null_term_cipher_name(QCryptoBlockLUKSHeader *hdr) 397 { 398 /* Replace NUL termination with spaces */ 399 char *offset = hdr->cipher_name + strlen(hdr->cipher_name); 400 memset(offset, ' ', sizeof(hdr->cipher_name) - (offset - hdr->cipher_name)); 401 402 return "LUKS header cipher name is not NUL terminated"; 403 } 404 405 static const char *luks_bad_null_term_cipher_mode(QCryptoBlockLUKSHeader *hdr) 406 { 407 /* Replace NUL termination with spaces */ 408 char *offset = hdr->cipher_mode + strlen(hdr->cipher_mode); 409 memset(offset, ' ', sizeof(hdr->cipher_mode) - (offset - hdr->cipher_mode)); 410 411 return "LUKS header cipher mode is not NUL terminated"; 412 } 413 414 static const char *luks_bad_null_term_hash_spec(QCryptoBlockLUKSHeader *hdr) 415 { 416 /* Replace NUL termination with spaces */ 417 char *offset = hdr->hash_spec + strlen(hdr->hash_spec); 418 memset(offset, ' ', sizeof(hdr->hash_spec) - (offset - hdr->hash_spec)); 419 420 return "LUKS header hash spec is not NUL terminated"; 421 } 422 423 static const char *luks_bad_cipher_name_empty(QCryptoBlockLUKSHeader *hdr) 424 { 425 memcpy(hdr->cipher_name, "", 1); 426 427 return "Algorithm '' with key size 32 bytes not supported"; 428 } 429 430 static const char *luks_bad_cipher_name_unknown(QCryptoBlockLUKSHeader *hdr) 431 { 432 memcpy(hdr->cipher_name, "aess", 5); 433 434 return "Algorithm 'aess' with key size 32 bytes not supported"; 435 } 436 437 static const char *luks_bad_cipher_xts_size(QCryptoBlockLUKSHeader *hdr) 438 { 439 hdr->master_key_len = 33; 440 441 return "XTS cipher key length should be a multiple of 2"; 442 } 443 444 static const char *luks_bad_cipher_cbc_size(QCryptoBlockLUKSHeader *hdr) 445 { 446 hdr->master_key_len = 33; 447 memcpy(hdr->cipher_mode, "cbc-essiv", 10); 448 449 return "Algorithm 'aes' with key size 33 bytes not supported"; 450 } 451 452 static const char *luks_bad_cipher_mode_empty(QCryptoBlockLUKSHeader *hdr) 453 { 454 memcpy(hdr->cipher_mode, "", 1); 455 456 return "Unexpected cipher mode string format ''"; 457 } 458 459 static const char *luks_bad_cipher_mode_unknown(QCryptoBlockLUKSHeader *hdr) 460 { 461 memcpy(hdr->cipher_mode, "xfs", 4); 462 463 return "Unexpected cipher mode string format 'xfs'"; 464 } 465 466 static const char *luks_bad_ivgen_separator(QCryptoBlockLUKSHeader *hdr) 467 { 468 memcpy(hdr->cipher_mode, "xts:plain64", 12); 469 470 return "Unexpected cipher mode string format 'xts:plain64'"; 471 } 472 473 static const char *luks_bad_ivgen_name_empty(QCryptoBlockLUKSHeader *hdr) 474 { 475 memcpy(hdr->cipher_mode, "xts-", 5); 476 477 return "IV generator '' not supported"; 478 } 479 480 static const char *luks_bad_ivgen_name_unknown(QCryptoBlockLUKSHeader *hdr) 481 { 482 memcpy(hdr->cipher_mode, "xts-plain65", 12); 483 484 return "IV generator 'plain65' not supported"; 485 } 486 487 static const char *luks_bad_ivgen_hash_empty(QCryptoBlockLUKSHeader *hdr) 488 { 489 memcpy(hdr->cipher_mode, "xts-plain65:", 13); 490 491 return "Hash algorithm '' not supported"; 492 } 493 494 static const char *luks_bad_ivgen_hash_unknown(QCryptoBlockLUKSHeader *hdr) 495 { 496 memcpy(hdr->cipher_mode, "xts-plain65:sha257", 19); 497 498 return "Hash algorithm 'sha257' not supported"; 499 } 500 501 static const char *luks_bad_hash_spec_empty(QCryptoBlockLUKSHeader *hdr) 502 { 503 memcpy(hdr->hash_spec, "", 1); 504 505 return "Hash algorithm '' not supported"; 506 } 507 508 static const char *luks_bad_hash_spec_unknown(QCryptoBlockLUKSHeader *hdr) 509 { 510 memcpy(hdr->hash_spec, "sha2566", 8); 511 512 return "Hash algorithm 'sha2566' not supported"; 513 } 514 515 static const char *luks_bad_stripes(QCryptoBlockLUKSHeader *hdr) 516 { 517 hdr->key_slots[0].stripes = 3999; 518 519 return "Keyslot 0 is corrupted (stripes 3999 != 4000)"; 520 } 521 522 static const char *luks_bad_key_overlap_header(QCryptoBlockLUKSHeader *hdr) 523 { 524 hdr->key_slots[0].key_offset_sector = 2; 525 526 return "Keyslot 0 is overlapping with the LUKS header"; 527 } 528 529 static const char *luks_bad_key_overlap_key(QCryptoBlockLUKSHeader *hdr) 530 { 531 hdr->key_slots[0].key_offset_sector = hdr->key_slots[1].key_offset_sector; 532 533 return "Keyslots 0 and 1 are overlapping in the header"; 534 } 535 536 static const char *luks_bad_key_overlap_payload(QCryptoBlockLUKSHeader *hdr) 537 { 538 hdr->key_slots[0].key_offset_sector = hdr->payload_offset_sector + 42; 539 540 return "Keyslot 0 is overlapping with the encrypted payload"; 541 } 542 543 static const char *luks_bad_payload_overlap_header(QCryptoBlockLUKSHeader *hdr) 544 { 545 hdr->payload_offset_sector = 2; 546 547 return "LUKS payload is overlapping with the header"; 548 } 549 550 static const char *luks_bad_key_iterations(QCryptoBlockLUKSHeader *hdr) 551 { 552 hdr->key_slots[0].iterations = 0; 553 554 return "Keyslot 0 iteration count is zero"; 555 } 556 557 static const char *luks_bad_iterations(QCryptoBlockLUKSHeader *hdr) 558 { 559 hdr->master_key_iterations = 0; 560 561 return "LUKS key iteration count is zero"; 562 } 563 #endif 564 565 int main(int argc, char **argv) 566 { 567 gsize i; 568 569 module_call_init(MODULE_INIT_QOM); 570 g_test_init(&argc, &argv, NULL); 571 572 g_assert(qcrypto_init(NULL) == 0); 573 574 for (i = 0; i < G_N_ELEMENTS(test_data); i++) { 575 if (test_data[i].open_opts->format == Q_CRYPTO_BLOCK_FORMAT_LUKS && 576 !qcrypto_hash_supports(test_data[i].hash_alg)) { 577 continue; 578 } 579 if (!test_data[i].slow || 580 g_test_slow()) { 581 g_test_add_data_func(test_data[i].path, &test_data[i], test_block); 582 } 583 } 584 585 #ifdef TEST_LUKS 586 if (g_test_slow()) { 587 g_test_add_data_func("/crypto/block/luks/bad/cipher-name-nul-term", 588 luks_bad_null_term_cipher_name, 589 test_luks_bad_header); 590 g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-nul-term", 591 luks_bad_null_term_cipher_mode, 592 test_luks_bad_header); 593 g_test_add_data_func("/crypto/block/luks/bad/hash-spec-nul-term", 594 luks_bad_null_term_hash_spec, 595 test_luks_bad_header); 596 g_test_add_data_func("/crypto/block/luks/bad/cipher-name-empty", 597 luks_bad_cipher_name_empty, 598 test_luks_bad_header); 599 g_test_add_data_func("/crypto/block/luks/bad/cipher-name-unknown", 600 luks_bad_cipher_name_unknown, 601 test_luks_bad_header); 602 g_test_add_data_func("/crypto/block/luks/bad/cipher-xts-size", 603 luks_bad_cipher_xts_size, 604 test_luks_bad_header); 605 g_test_add_data_func("/crypto/block/luks/bad/cipher-cbc-size", 606 luks_bad_cipher_cbc_size, 607 test_luks_bad_header); 608 g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-empty", 609 luks_bad_cipher_mode_empty, 610 test_luks_bad_header); 611 g_test_add_data_func("/crypto/block/luks/bad/cipher-mode-unknown", 612 luks_bad_cipher_mode_unknown, 613 test_luks_bad_header); 614 g_test_add_data_func("/crypto/block/luks/bad/ivgen-separator", 615 luks_bad_ivgen_separator, 616 test_luks_bad_header); 617 g_test_add_data_func("/crypto/block/luks/bad/ivgen-name-empty", 618 luks_bad_ivgen_name_empty, 619 test_luks_bad_header); 620 g_test_add_data_func("/crypto/block/luks/bad/ivgen-name-unknown", 621 luks_bad_ivgen_name_unknown, 622 test_luks_bad_header); 623 g_test_add_data_func("/crypto/block/luks/bad/ivgen-hash-empty", 624 luks_bad_ivgen_hash_empty, 625 test_luks_bad_header); 626 g_test_add_data_func("/crypto/block/luks/bad/ivgen-hash-unknown", 627 luks_bad_ivgen_hash_unknown, 628 test_luks_bad_header); 629 g_test_add_data_func("/crypto/block/luks/bad/hash-spec-empty", 630 luks_bad_hash_spec_empty, 631 test_luks_bad_header); 632 g_test_add_data_func("/crypto/block/luks/bad/hash-spec-unknown", 633 luks_bad_hash_spec_unknown, 634 test_luks_bad_header); 635 g_test_add_data_func("/crypto/block/luks/bad/stripes", 636 luks_bad_stripes, 637 test_luks_bad_header); 638 g_test_add_data_func("/crypto/block/luks/bad/key-overlap-header", 639 luks_bad_key_overlap_header, 640 test_luks_bad_header); 641 g_test_add_data_func("/crypto/block/luks/bad/key-overlap-key", 642 luks_bad_key_overlap_key, 643 test_luks_bad_header); 644 g_test_add_data_func("/crypto/block/luks/bad/key-overlap-payload", 645 luks_bad_key_overlap_payload, 646 test_luks_bad_header); 647 g_test_add_data_func("/crypto/block/luks/bad/payload-overlap-header", 648 luks_bad_payload_overlap_header, 649 test_luks_bad_header); 650 g_test_add_data_func("/crypto/block/luks/bad/iterations", 651 luks_bad_iterations, 652 test_luks_bad_header); 653 g_test_add_data_func("/crypto/block/luks/bad/key-iterations", 654 luks_bad_key_iterations, 655 test_luks_bad_header); 656 } 657 #endif 658 659 return g_test_run(); 660 } 661