On Mon, Dec 05, 2016 at 11:21:04AM -0800, Eric Biggers wrote: > Add utility functions for testing filesystem-level encryption via the > common API currently supported by ext4 and f2fs, in development for > ubifs and planned for xfs. Setting and getting encryption policies will > use new commands being added to xfs_io, while adding and removing > encryption keys will use keyctl. > > Signed-off-by: Eric Biggers <ebiggers@xxxxxxxxxx> > --- > common/config | 1 + > common/encrypt | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 138 insertions(+) > create mode 100644 common/encrypt > > diff --git a/common/config b/common/config > index f0f08d2..3727ec0 100644 > --- a/common/config > +++ b/common/config > @@ -202,6 +202,7 @@ export DEBUGFS_PROG="`set_prog_path debugfs`" > export UUIDGEN_PROG="`set_prog_path uuidgen`" > export GETRICHACL_PROG="`set_prog_path getrichacl`" > export SETRICHACL_PROG="`set_prog_path setrichacl`" > +export KEYCTL_PROG="`set_prog_path keyctl`" > > # use 'udevadm settle' or 'udevsettle' to wait for lv to be settled. > # newer systems have udevadm command but older systems like RHEL5 don't. > diff --git a/common/encrypt b/common/encrypt > new file mode 100644 > index 0000000..e18068e > --- /dev/null > +++ b/common/encrypt > @@ -0,0 +1,137 @@ > +#----------------------------------------------------------------------- > +# > +# Common functions for testing filesystem-level encryption > +# > +#----------------------------------------------------------------------- > +# Copyright (c) 2016 Google, Inc. All Rights Reserved. > +# > +# Author: Eric Biggers <ebiggers@xxxxxxxxxx> > +# > +# This program is free software; you can redistribute it and/or > +# modify it under the terms of the GNU General Public License as > +# published by the Free Software Foundation. > +# > +# This program is distributed in the hope that it would be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write the Free Software Foundation, > +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > +#----------------------------------------------------------------------- > + > +_require_encryption() I think it's better to name it as _require_scratch_encryption (like _require_scratch_reflink), so that we know it takes use of SCRATCH_DEV and tests against it to check if encryption is supported. > +{ > + # The 'test_dummy_encryption' mount option interferes with trying to use > + # encryption for real, even if we are just trying to get/set policies > + # and never put any keys in the keyring. So skip the real encryption > + # tests if the 'test_dummy_encryption' mount option was specified. > + if echo "$MOUNT_OPTIONS" | grep -q "test_dummy_encryption"; then > + _notrun "Dummy encryption is on; skipping real encryption tests" > + fi There's a helper _exclude_scratch_mount_option to do this. > + > + # Make a filesystem on the scratch device with the encryption feature > + # enabled. If this fails then probably the userspace tools (e.g. > + # e2fsprogs or f2fs-tools) are too old to understand encryption. > + if ! _scratch_mkfs_encrypted &>>$seqres.full; then > + _notrun "$FSTYP userspace tools do not support encryption" > + fi > + > + # Try to mount the filesystem. If this fails then either the kernel > + # isn't aware of encryption, or the mkfs options were not compatible > + # with encryption (e.g. ext4 with block size != PAGE_SIZE). > + if ! _scratch_mount &>>$seqres.full; then > + _notrun "kernel is unaware of $FSTYP encryption feature, " \ > + "or mkfs options are not compatible with encryption" > + fi > + > + # The kernel may be aware of encryption without supporting it. For > + # example, for ext4 this is the case with kernels configured with > + # CONFIG_EXT4_FS_ENCRYPTION=n. Detect support for encryption by trying > + # to set an encryption policy. (For ext4 we could instead check for the > + # presence of /sys/fs/ext4/features/encryption, but this is broken on > + # some older kernels and is ext4-specific anyway.) > + mkdir $SCRATCH_MNT/tmpdir > + if $XFS_IO_PROG -c set_encpolicy $SCRATCH_MNT/tmpdir \ > + 2>&1 >>$seqres.full | \ > + egrep -q 'Inappropriate ioctl for device|Operation not supported' > + then > + _notrun "kernel does not support $FSTYP encryption" > + fi > + rmdir $SCRATCH_MNT/tmpdir > + _scratch_unmount > +} > + > +_scratch_mkfs_encrypted() > +{ > + _scratch_mkfs -O encrypt Do case switch based on FSTYP (like what you do in v1 patch), just don't override MKFS_OPTIONS as Dave pointed out. _scratch_mkfs_encrypted() { case $FSTYP in ext4|f2fs) _scratch_mkfs -O encrypt ;; *) _notrun "No encryption support for $FSTYP" ;; esac } > + > +# Give the invoking shell a new session keyring. This makes any keys we add to > +# the session keyring scoped to the lifetime of the test script. > +_new_session_keyring() > +{ > + $KEYCTL_PROG new_session >>$seqres.full > +} > + > +# > +# Generate a random encryption key, add it to the session keyring, and print out > +# the resulting key descriptor (example: "8bf798e1a494e1ec"). Requires the > +# keyctl program. It's assumed the caller has already set up a test-scoped > +# session keyring using _new_session_keyring. > +# > +_generate_encryption_key() > +{ > + # Generate a key descriptor (16 character hex string) > + local keydesc="" > + for ((i = 0; i < 8; i++)); do > + keydesc="${keydesc}$(printf "%02x" $(( $RANDOM % 256 )))" > + done > + > + # Generate the actual encryption key (64 bytes) > + local raw="" > + for ((i = 0; i < 64; i++)); do > + raw="${raw}\\x$(printf "%02x" $(( $RANDOM % 256 )))" > + done > + > + # > + # Add the key to the session keyring. The required structure is: > + # > + # #define FS_MAX_KEY_SIZE 64 > + # struct fscrypt_key { > + # u32 mode; > + # u8 raw[FS_MAX_KEY_SIZE]; > + # u32 size; > + # } __packed; > + # > + # The kernel ignores 'mode' but requires that 'size' be 64. > + # > + # Keys are named $FSTYP:KEYDESC where KEYDESC is the 16-character key > + # descriptor hex string. Newer kernels (ext4 4.8 and later, f2fs 4.6 > + # and later) also allow the common key prefix "fscrypt:" in addition to > + # their filesystem-specific key prefix ("ext4:", "f2fs:"). It would be > + # nice to use the common key prefix, but for now use the filesystem- > + # specific prefix to make it possible to test older kernels... > + # > + local big_endian=$(echo -ne '\x11' | od -tx2 | head -1 | \ > + cut -f2 -d' ' | cut -c1 ) > + if (( big_endian )); then > + local mode='\x00\x00\x00\x00' > + local size='\x00\x00\x00\x40' > + else > + local mode='\x00\x00\x00\x00' > + local size='\x40\x00\x00\x00' > + fi > + echo -n -e "${mode}${raw}${size}" | > + $KEYCTL_PROG padd logon $FSTYP:$keydesc @s >>$seqres.full > + echo $keydesc > +} > + > +# Unlink an encryption key from the session keyring, given its key descriptor. > +_unlink_encryption_key() > +{ > + local keydesc=$1 > + local keyid=$($KEYCTL_PROG search @s logon $FSTYP:$keydesc) > + $KEYCTL_PROG unlink $keyid >>$seqres.full > +} > -- > 2.8.0.rc3.226.g39d4020 > > -- > To unsubscribe from this list: send the line "unsubscribe fstests" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe fstests" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html