diff --git a/lib/luks1/keymanage.c b/lib/luks1/keymanage.c index 4a936a59..224b10ff 100644 --- a/lib/luks1/keymanage.c +++ b/lib/luks1/keymanage.c @@ -154,6 +154,7 @@ int LUKS_hdr_backup( { struct device *device = crypt_metadata_device(ctx); int r = 0, devfd = -1; + ssize_t hdr_size; ssize_t buffer_size; char *buffer = NULL; @@ -161,15 +162,19 @@ int LUKS_hdr_backup( if (r) return r; - buffer_size = LUKS_device_sectors(hdr->keyBytes) << SECTOR_SHIFT; + hdr_size = LUKS_device_sectors(hdr->keyBytes) << SECTOR_SHIFT; + buffer_size = size_round_up(hdr_size, crypt_getpagesize()); + buffer = crypt_safe_alloc(buffer_size); - if (!buffer || buffer_size < LUKS_ALIGN_KEYSLOTS) { + if (!buffer || hdr_size < LUKS_ALIGN_KEYSLOTS || hdr_size > buffer_size) { r = -ENOMEM; goto out; } log_dbg("Storing backup of header (%u bytes) and keyslot area (%u bytes).", - sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS); + sizeof(*hdr), hdr_size - LUKS_ALIGN_KEYSLOTS); + + log_dbg("Output backup file size: %u bytes.", buffer_size); devfd = device_open(device, O_RDONLY); if(devfd == -1) { @@ -178,7 +183,7 @@ int LUKS_hdr_backup( goto out; } - if (read_blockwise(devfd, device_block_size(device), buffer, buffer_size) < buffer_size) { + if (read_blockwise(devfd, device_block_size(device), buffer, hdr_size) < hdr_size) { r = -EIO; goto out; } diff --git a/tests/api-test.c b/tests/api-test.c index 0a567836..08dd2538 100644 --- a/tests/api-test.c +++ b/tests/api-test.c @@ -1,7 +1,7 @@ /* * cryptsetup library API check functions * - * Copyright (C) 2009-2012 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2013 Red Hat, Inc. All rights reserved. * Copyright (C) 2009-2013, Milan Broz * * This program is free software; you can redistribute it and/or @@ -94,6 +94,7 @@ static int global_lines = 0; static char *DEVICE_1 = NULL; static char *DEVICE_2 = NULL; +static char *DEVICE_3 = NULL; static char *THE_LOOP_DEV = NULL; static char *tmp_file_1 = NULL; @@ -374,6 +375,9 @@ static void _cleanup(void) if (crypt_loop_device(DEVICE_2)) crypt_loop_detach(DEVICE_2); + if (crypt_loop_device(DEVICE_3)) + crypt_loop_detach(DEVICE_3); + _system("rm -f " IMAGE_EMPTY, 0); _system("rm -f " IMAGE1, 0); @@ -394,6 +398,7 @@ static void _cleanup(void) free(THE_LOOP_DEV); free(DEVICE_1); free(DEVICE_2); + free(DEVICE_3); } static int _setup(void) @@ -458,6 +463,12 @@ static int _setup(void) fd = crypt_loop_attach(DEVICE_2, IMAGE_EMPTY, 0, 0, &ro); close(fd); } + if (!DEVICE_3) + DEVICE_3 = crypt_loop_get_device(); + if (!DEVICE_3) { + printf("Cannot find free loop device.\n"); + return 1; + } /* Keymaterial offset is less than 8 sectors */ _system(" [ ! -e " EVL_HEADER_1 " ] && bzip2 -dk " EVL_HEADER_1 ".bz2", 1); /* keymaterial offset aims into payload area */ @@ -1428,6 +1439,7 @@ static void LuksHeaderBackup(void) .data_alignment = 2048, }; char key[128]; + int fd, ro = O_RDONLY; const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; size_t key_size = strlen(mk_hex) / 2; @@ -1435,6 +1447,8 @@ static void LuksHeaderBackup(void) const char *cipher_mode = "cbc-essiv:sha256"; uint64_t r_payload_offset; + const char *passphrase = PASSPHRASE; + crypt_decode_key(key, mk_hex, key_size); OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset)); @@ -1444,6 +1458,8 @@ static void LuksHeaderBackup(void) OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), 7); + EQ_(crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, passphrase, strlen(passphrase)), 0); OK_(crypt_header_backup(cd, CRYPT_LUKS1, BACKUP_FILE)); OK_(crypt_deactivate(cd, CDEVICE_1)); crypt_free(cd); @@ -1457,6 +1473,43 @@ static void LuksHeaderBackup(void) OK_(crypt_deactivate(cd, CDEVICE_1)); crypt_free(cd); + // exercise luksOpen using backup header in file + OK_(crypt_init(&cd, BACKUP_FILE)); + OK_(crypt_load(cd, CRYPT_LUKS1, NULL)); + OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK)); + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + OK_(crypt_init(&cd, BACKUP_FILE)); + OK_(crypt_load(cd, CRYPT_LUKS1, NULL)); + OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK)); + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase), 0), 7); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + // exercise luksOpen using backup header on block device + fd = crypt_loop_attach(DEVICE_3, BACKUP_FILE, 0, 0, &ro); + close(fd); + OK_(fd < 0); + OK_(crypt_init(&cd, DEVICE_3)); + OK_(crypt_load(cd, CRYPT_LUKS1, NULL)); + OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK)); + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + OK_(crypt_init(&cd, DEVICE_3)); + OK_(crypt_load(cd, CRYPT_LUKS1, NULL)); + OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK)); + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase), 0), 7); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + _cleanup_dmdevices(); }