Preview copy operation of encrypted file systems (#774818)

Implement composing of the copy paste operation for encrypted file
systems.

Copying a closed LUKS partition would duplicate the LUKS header
containing the UUID, passphrase and master encryption key.  From a
security point of view having additional copies of encrypted data with
the same master key is an extra risk, but it all depends on what is
going to happen with that copy.  The Cryptsetup FAQ [1] talks about how
to make a backup at the file system level and block level, preferring
file system level with separate encryption if needed.  It strongly
recommends separate encryption if the copy is removable or going
off-site [2].  Also in the case of cloning the data, cloning the LUKS
container is strongly discouraged [3].

Therefore copying of encrypted file systems will be implemented by
copying the file system inside an open LUKS encryption mapping and not
by copying a closed LUKS partition.

Also, while creating new LUKS encryption is not yet supported, copying
an encrypted file system into a new partition will not be permitted as
that will always decrypt the data.  An encrypted file system will be
allowed to be copied into an existing plain partition, decrypting the
data, or into an existing open encrypted partition, keeping it
encrypted.  Pasting over the top of a closed encrypted partition will
remove the LUKS encryption.  (This is planned to be removed when
creating and removing LUKS encryption is implemented as part of full
LUKS read-write support).

Remember that when pasting into an existing partition the file system
must fit within the available space and that encryption has overhead
from the LUKS header.  Therefore copying from a plain partition into a
partition of the same size with open an encryption mapping will not fit
for space reasons.

[1] The Cryptsetup FAQ, Backup and data Recovery section
https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions

[2] 6.7 Does a backup compromise security?
"If you do network-backup or tape-backup, I strongly recommend to go the
filesystem backup path with independent encryption, as you typically
cannot reliably delete data in these scenarios, especially in a cloud
setting."

[3] 6.15 Can I clone a LUKS container?
"You can, but it breaks security, because the cloned container has the
same header and hence the same master key.  You cannot change the master
key on a LUKS container, even if you change the passphrase(s), the
master key stays the same. That means whoever has access to one of the
clones can decrypt them all, completely bypassing the passphrases.

The right way to do this is to first luksFormat the target container,
then to clone the contents of the source container, with both containers
mapped, i.e. decrypted.  You can clone the decrypted contents of a LUKS
container in binary mode, although you may run into secondary issues
with GUIDs in filesystems, partition tables, RAID-components and the
like. These are just the normal problems binary cloning causes.

Note that if you need to ship (e.g.) cloned LUKS containers with a
default passphrase, that is fine as long as each container was
individually created (and hence has its own master key). In this case,
changing the default passphrase will make it secure again."

Bug 774818 - Implement LUKS read-write actions NOT requiring a
             passphrase
This commit is contained in:
Mike Fleetwood 2016-11-02 22:05:30 +00:00 committed by Curtis Gedak
parent 35d57011e9
commit 4c70ec3aee
1 changed files with 76 additions and 33 deletions

View File

@ -1155,13 +1155,21 @@ void Win_GParted::set_valid_operations()
allow_new( true );
// Find out if there is a partition to be copied and if it fits inside this unallocated space
if ( copied_partition != NULL && ! devices[current_device].readonly )
// FIXME:
// Temporarily disable copying of encrypted content into new partitions
// which can't yet be encrypted, until full LUKS read-write support is
// implemented.
if ( copied_partition != NULL &&
! devices[current_device].readonly &&
copied_partition->filesystem != FS_LUKS )
{
const Partition & copied_filesystem_ptn = copied_partition->get_filesystem_partition();
Byte_Value required_size ;
if ( copied_partition->filesystem == FS_XFS )
required_size = copied_partition->estimated_min_size() * copied_partition->sector_size;
if ( copied_filesystem_ptn.filesystem == FS_XFS )
required_size = copied_filesystem_ptn.estimated_min_size() *
copied_filesystem_ptn.sector_size;
else
required_size = copied_partition->get_byte_length();
required_size = copied_filesystem_ptn.get_byte_length();
//Determine if space is needed for the Master Boot Record or
// the Extended Boot Record. Generally an an additional track or MEBIBYTE
@ -1235,7 +1243,7 @@ void Win_GParted::set_valid_operations()
allow_resize( true ) ;
//only allow copying of real partitions
if ( selected_partition_ptr->status == STAT_REAL && fs.copy )
if ( selected_partition_ptr->status == STAT_REAL && fs_cap.copy )
allow_copy( true ) ;
//only allow labelling of real partitions that support labelling
@ -1270,10 +1278,11 @@ void Win_GParted::set_valid_operations()
}
// See if there is a partition to be copied and it fits inside this selected partition
if ( copied_partition != NULL &&
copied_partition->get_byte_length() <= selected_partition_ptr->get_byte_length() &&
selected_partition_ptr->status == STAT_REAL &&
*copied_partition != *selected_partition_ptr )
if ( copied_partition != NULL &&
( copied_partition->get_filesystem_partition().get_byte_length() <=
selected_filesystem.get_byte_length() ) &&
selected_partition_ptr->status == STAT_REAL &&
*copied_partition != *selected_partition_ptr )
allow_paste( true );
//see if we can somehow check/repair this file system....
@ -1844,18 +1853,20 @@ void Win_GParted::activate_paste()
return ;
}
const Partition & copied_filesystem_ptn = copied_partition->get_filesystem_partition();
if ( selected_partition_ptr->type == TYPE_UNALLOCATED )
{
if ( ! max_amount_prim_reached() )
{
// We don't want the messages, mount points or name of the source
// partition for the new partition being created.
Partition * part_temp = copied_partition->clone();
Partition * part_temp = copied_filesystem_ptn.clone();
part_temp->clear_messages();
part_temp->clear_mountpoints();
part_temp->name.clear();
Dialog_Partition_Copy dialog( gparted_core.get_fs( copied_partition->filesystem ),
Dialog_Partition_Copy dialog( gparted_core.get_fs( copied_filesystem_ptn.filesystem ),
*selected_partition_ptr,
*part_temp );
delete part_temp;
@ -1886,41 +1897,73 @@ void Win_GParted::activate_paste()
}
else
{
const Partition & selected_filesystem_ptn = selected_partition_ptr->get_filesystem_partition();
bool shown_dialog = false ;
// VGNAME from mount mount
if ( selected_partition_ptr->filesystem == FS_LVM2_PV &&
! selected_partition_ptr->get_mountpoint().empty() )
if ( selected_filesystem_ptn.filesystem == FS_LVM2_PV &&
! selected_filesystem_ptn.get_mountpoint().empty() )
{
if ( ! remove_non_empty_lvm2_pv_dialog( OPERATION_COPY ) )
return ;
shown_dialog = true ;
}
Partition * partition_new = selected_partition_ptr->clone();
partition_new->alignment = ALIGN_STRICT;
partition_new->filesystem = copied_partition->filesystem;
partition_new->set_filesystem_label( copied_partition->get_filesystem_label() );
partition_new->uuid = copied_partition->uuid;
Sector new_size = partition_new->get_sector_length();
if ( copied_partition->get_sector_length() == new_size )
Partition * partition_new;
if ( selected_partition_ptr->filesystem == FS_LUKS && ! selected_partition_ptr->busy )
{
// Pasting into same size existing partition, therefore only block
// copy operation will be performed maintaining the file system
// size.
partition_new->set_sector_usage(
copied_partition->sectors_used + copied_partition->sectors_unused,
copied_partition->sectors_unused );
// Pasting into a closed LUKS encrypted partition will overwrite
// the encryption replacing it with a non-encrypted file system.
// Start with a plain Partition object instead of cloning the
// existing PartitionLUKS object containing a Partition object.
// FIXME:
// Expect to remove this case when creating and removing LUKS
// encryption is added as a separate action when full LUKS
// read-write support is implemented.
// WARNING:
// Deliberate object slicing of *selected_partition_ptr from
// PartitionLUKS to Partition.
partition_new = new Partition( *selected_partition_ptr );
}
else
{
// Pasting into larger existing partition, therefore block copy
// followed by file system grow operations (if supported) will be
// performed making the file system fill the partition.
partition_new->set_sector_usage(
new_size,
new_size - copied_partition->sectors_used );
// Pasting over a file system, either a plain file system or one
// within an open LUKS encryption mapping. Start with a clone of
// the existing Partition object whether it be a plain Partition
// object or a PartitionLUKS object containing a Partition object.
partition_new = selected_partition_ptr->clone();
}
partition_new->alignment = ALIGN_STRICT;
{
// Sub-block so that filesystem_ptn_new reference goes out of
// scope before partition_new pointer is deallocated.
Partition & filesystem_ptn_new = partition_new->get_filesystem_partition();
filesystem_ptn_new.filesystem = copied_filesystem_ptn.filesystem;
filesystem_ptn_new.set_filesystem_label( copied_filesystem_ptn.get_filesystem_label() );
filesystem_ptn_new.uuid = copied_filesystem_ptn.uuid;
Sector new_size = filesystem_ptn_new.get_sector_length();
if ( copied_filesystem_ptn.get_sector_length() == new_size )
{
// Pasting into same size existing partition, therefore
// only block copy operation will be performed maintaining
// the file system size.
filesystem_ptn_new.set_sector_usage(
copied_filesystem_ptn.sectors_used + copied_filesystem_ptn.sectors_unused,
copied_filesystem_ptn.sectors_unused );
}
else
{
// Pasting into larger existing partition, therefore block
// copy followed by file system grow operations (if
// supported) will be performed making the file system
// fill the partition.
filesystem_ptn_new.set_sector_usage(
new_size,
new_size - copied_filesystem_ptn.sectors_used );
}
filesystem_ptn_new.clear_messages();
}
partition_new->clear_messages();
Operation * operation = new OperationCopy( devices[current_device],
*selected_partition_ptr,