From patchwork Wed Dec 21 21:21:57 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 9483787 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A7156601D2 for ; Wed, 21 Dec 2016 21:24:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 98179284C8 for ; Wed, 21 Dec 2016 21:24:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8CC9D284DA; Wed, 21 Dec 2016 21:24:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EC973284D2 for ; Wed, 21 Dec 2016 21:24:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758115AbcLUVYg (ORCPT ); Wed, 21 Dec 2016 16:24:36 -0500 Received: from mail-pg0-f66.google.com ([74.125.83.66]:34562 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758119AbcLUVYg (ORCPT ); Wed, 21 Dec 2016 16:24:36 -0500 Received: by mail-pg0-f66.google.com with SMTP id b1so17563492pgc.1 for ; Wed, 21 Dec 2016 13:24:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=JeDBMvtvEOOjkKyNBzvYMdd3vH8Kh7vxOf7UX77sxM4=; b=QUPXiQdAQGsZQ+r/wUMFmD19QrMnmBxayO4hTjOhIEfC5id5G4+OlgRt2lTifmjf8C 79uH1z7+Lb0qkaBCagJE1FTqhtRt9hwJqm64VHgXFlpCzGpv5zrDLBeP7fluerEx7r+E U4gszt9jUPt3SsDM/0y3oRXv+dt/Jhst4YOi8zQGtBN+b6akaR9bW4iDxmKMGpv66fUn Iz8Xg6swkMon6O41Vhfgty/VhBpJ3zLOZQ+EbsNN8lEzezESlt59/UodYk791OJxYyrr 8/a2ZhSi72u2rMnV+wH/HyhA/1MkcTZl1VcUZANWBnhmTxBA1VJVo9BUrt7GJ7xb6wlN Bz7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=JeDBMvtvEOOjkKyNBzvYMdd3vH8Kh7vxOf7UX77sxM4=; b=C9if46386lP69F5JH3/oPzk+af0NAt8ihYyAl7x06HSQJmXEXJ+b6BseUuuvclzgk1 gX/Zs2QvxNEJTbwvdWqCe7hBup/Ylpra7LEoePDatgXshteGQUu3+IOcJQq1XvYwosBU Z2wDsnAgxv6X5Lp5sFCzeqbdDtEQUnEC2HPI0XNGKkUf2WfflBl4iwfEtFMwQqTWoyRn z6TZvjQS4iZHBRelL9skf3HB3BXmEDyHseUF8pmFBTJVbJuyLUJqmUeUSIcFObOIflCp xuwt7T6555Y1l3cM+ndKUWUZgISYEg3g/G6ql0aTqpHl7r9Hf0msUnkaw/r7G1/S4lYx u7aQ== X-Gm-Message-State: AIkVDXKqPKOChQv3470230BwXPksKBOny8TL0yUT+GXFOSBaAmz4HJdVYiSNQt8YAHoMGw== X-Received: by 10.99.115.5 with SMTP id o5mr10967772pgc.165.1482355475120; Wed, 21 Dec 2016 13:24:35 -0800 (PST) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.119.30.131]) by smtp.gmail.com with ESMTPSA id 13sm49035453pfz.30.2016.12.21.13.24.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 21 Dec 2016 13:24:34 -0800 (PST) From: Eric Biggers To: fstests@vger.kernel.org Cc: Theodore Ts'o , Jaegeuk Kim , Richard Weinberger , David Gstir , Michael Halcrow , Eric Sandeen , Eric Biggers Subject: [PATCH v5 1/6] generic: add utilities for testing filesystem encryption Date: Wed, 21 Dec 2016 13:21:57 -0800 Message-Id: <1482355322-74978-2-git-send-email-ebiggers3@gmail.com> X-Mailer: git-send-email 2.8.0.rc3.226.g39d4020 In-Reply-To: <1482355322-74978-1-git-send-email-ebiggers3@gmail.com> References: <1482355322-74978-1-git-send-email-ebiggers3@gmail.com> Sender: fstests-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: fstests@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Eric Biggers 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 --- common/config | 1 + common/encrypt | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 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..f09104d --- /dev/null +++ b/common/encrypt @@ -0,0 +1,146 @@ +#----------------------------------------------------------------------- +# +# Common functions for testing filesystem-level encryption +# +#----------------------------------------------------------------------- +# Copyright (c) 2016 Google, Inc. All Rights Reserved. +# +# Author: Eric Biggers +# +# 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_scratch_encryption() +{ + _require_scratch + + _require_xfs_io_command "set_encpolicy" + + # 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. + _exclude_scratch_mount_option "test_dummy_encryption" + + # 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() +{ + 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 +}