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