From patchwork Tue Aug 8 17:21:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sweet Tea Dorminy X-Patchwork-Id: 13346546 Received: from box.fidei.email (box.fidei.email [71.19.144.250]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E0C4F14F6D for ; Tue, 8 Aug 2023 17:31:27 +0000 (UTC) Received: from authenticated-user (box.fidei.email [71.19.144.250]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by box.fidei.email (Postfix) with ESMTPSA id 6879580348; Tue, 8 Aug 2023 13:22:09 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=dorminy.me; s=mail; t=1691515329; bh=jXkp4ZPZvCh0Pbc4dU9uaq/gyB6pGGUOl6VW41U89Is=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OZAXatfEZ/bHHP67WagSKsMa0U4wFZU3Y6hQfXQMYe9wrG+tiZKPv6ZwVAC2EUlWh uhck8x6pf+OjypBa8lu9d9cPUFAu7oEbKTlfyrl0wJ9VHHDwmVc2gNlSYrH109/BkT +lb37aJJ/30PGUrH3Av0jMsevnq25fozs1GD7a7xjjIPbpowUINjWWvOPjvAh2PYop mvKqoiaUtvP006pNiFw1ePQ1x8LBE5M1RJVUVLLKGbBHV/SbGOlvDKAEK4QjCMIhfd Zu77aoeuqirst6P+u1hQx8kWqTUH86g7YTMeXSvPUTaUidrtpu3OgFbUuTR0Fse1u4 1XyzNRuNEEtSg== From: Sweet Tea Dorminy To: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, kernel-team@meta.com, ebiggers@google.com, anand.jain@oracle.com, fdmanana@suse.com, linux-fscrypt@vger.kernel.org, fsverity@lists.linux.dev, zlang@kernel.org Cc: Sweet Tea Dorminy Subject: [RFC PATCH v3 1/9] common/encrypt: separate data and inode nonces Date: Tue, 8 Aug 2023 13:21:20 -0400 Message-ID: <6528bfda204dffd19aba07ff98f07ae6fd45792e.1691530000.git.sweettea-kernel@dorminy.me> In-Reply-To: References: Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 btrfs will have different inode and data nonces, so we need to be specific about which nonce each use needs. For now, there is no difference in the two functions. Signed-off-by: Sweet Tea Dorminy --- common/encrypt | 33 ++++++++++++++++++++++++++------- tests/f2fs/002 | 2 +- tests/generic/613 | 4 ++-- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/common/encrypt b/common/encrypt index 1a77e23b..04b6e5ac 100644 --- a/common/encrypt +++ b/common/encrypt @@ -488,7 +488,7 @@ _add_fscrypt_provisioning_key() # Retrieve the encryption nonce of the given inode as a hex string. The nonce # was randomly generated by the filesystem and isn't exposed directly to # userspace. But it can be read using the filesystem's debugging tools. -_get_encryption_nonce() +_get_encryption_file_nonce() { local device=$1 local inode=$2 @@ -532,15 +532,34 @@ _get_encryption_nonce() }' ;; *) - _fail "_get_encryption_nonce() isn't implemented on $FSTYP" + _fail "_get_encryption_file_nonce() isn't implemented on $FSTYP" ;; esac } -# Require support for _get_encryption_nonce() +# Retrieve the encryption nonce used to encrypt the data of the given inode as +# a hex string. The nonce was randomly generated by the filesystem and isn't +# exposed directly to userspace. But it can be read using the filesystem's +# debugging tools. +_get_encryption_data_nonce() +{ + local device=$1 + local inode=$2 + + case $FSTYP in + ext4|f2fs) + _get_encryption_file_nonce $device $inode + ;; + *) + _fail "_get_encryption_data_nonce() isn't implemented on $FSTYP" + ;; + esac +} + +# Require support for _get_encryption_*nonce() _require_get_encryption_nonce_support() { - echo "Checking for _get_encryption_nonce() support for $FSTYP" >> $seqres.full + echo "Checking for _get_encryption_*nonce() support for $FSTYP" >> $seqres.full case $FSTYP in ext4) _require_command "$DEBUGFS_PROG" debugfs @@ -554,7 +573,7 @@ _require_get_encryption_nonce_support() # the test fail in that case, as it was an f2fs-tools bug... ;; *) - _notrun "_get_encryption_nonce() isn't implemented on $FSTYP" + _notrun "_get_encryption_*nonce() isn't implemented on $FSTYP" ;; esac } @@ -760,7 +779,7 @@ _do_verify_ciphertext_for_encryption_policy() echo "Verifying encrypted file contents" >> $seqres.full for f in "${test_contents_files[@]}"; do read -r src inode blocklist <<< "$f" - nonce=$(_get_encryption_nonce $SCRATCH_DEV $inode) + nonce=$(_get_encryption_data_nonce $SCRATCH_DEV $inode) _dump_ciphertext_blocks $SCRATCH_DEV $blocklist > $tmp.actual_contents $crypt_contents_cmd $contents_encryption_mode $raw_key_hex \ --file-nonce=$nonce --block-size=$blocksize \ @@ -780,7 +799,7 @@ _do_verify_ciphertext_for_encryption_policy() echo "Verifying encrypted file names" >> $seqres.full for f in "${test_filenames_files[@]}"; do read -r name inode dir_inode padding <<< "$f" - nonce=$(_get_encryption_nonce $SCRATCH_DEV $dir_inode) + nonce=$(_get_encryption_file_nonce $SCRATCH_DEV $dir_inode) _get_ciphertext_filename $SCRATCH_DEV $inode $dir_inode \ > $tmp.actual_name echo -n "$name" | \ diff --git a/tests/f2fs/002 b/tests/f2fs/002 index 8235d88a..a51ddf22 100755 --- a/tests/f2fs/002 +++ b/tests/f2fs/002 @@ -129,7 +129,7 @@ blocklist=$(_get_ciphertext_block_list $file) _scratch_unmount echo -e "\n# Getting file's encryption nonce" -nonce=$(_get_encryption_nonce $SCRATCH_DEV $inode) +nonce=$(_get_encryption_data_nonce $SCRATCH_DEV $inode) echo -e "\n# Dumping the file's raw data" _dump_ciphertext_blocks $SCRATCH_DEV $blocklist > $tmp.raw diff --git a/tests/generic/613 b/tests/generic/613 index 4cf5ccc6..47c60e9c 100755 --- a/tests/generic/613 +++ b/tests/generic/613 @@ -68,10 +68,10 @@ echo -e "\n# Getting encryption nonces from inodes" echo -n > $tmp.nonces_hex echo -n > $tmp.nonces_bin for inode in "${inodes[@]}"; do - nonce=$(_get_encryption_nonce $SCRATCH_DEV $inode) + nonce=$(_get_encryption_data_nonce $SCRATCH_DEV $inode) if (( ${#nonce} != 32 )) || [ -n "$(echo "$nonce" | tr -d 0-9a-fA-F)" ] then - _fail "Expected nonce to be 16 bytes (32 hex characters), but got \"$nonce\"" + _fail "Expected nonce for inode $inode to be 16 bytes (32 hex characters), but got \"$nonce\"" fi echo $nonce >> $tmp.nonces_hex echo -ne "$(echo $nonce | sed 's/[0-9a-fA-F]\{2\}/\\x\0/g')" \ From patchwork Tue Aug 8 17:21:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sweet Tea Dorminy X-Patchwork-Id: 13346536 Received: from box.fidei.email (box.fidei.email [71.19.144.250]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E31A914F6E for ; Tue, 8 Aug 2023 17:31:27 +0000 (UTC) Received: from authenticated-user (box.fidei.email [71.19.144.250]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by box.fidei.email (Postfix) with ESMTPSA id D0F97803AF; Tue, 8 Aug 2023 13:22:10 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=dorminy.me; s=mail; t=1691515331; bh=HJHfEC2utk1cT+5gy9FZrT+lWxfLUWWvrcTsspJsx8o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IAOTX6hDO3oSDCTKQhbvj44A4DCZReh40FzcvOoLgZqLZuLyUoFfAQk+/sx++ILYF yZ46K7lXTxpC9I0p87zVtte5WQbhguhD93b+1m/ekmS2nAizJH5JxgeYKJDzUKlV/L wJATGXDG+SZC0tWdDmfw2CY+TXVk7zsbhxFn780MDea1P173atgczECY8imkeGyV5z dywPb4l6mPD1a1qN7ulAc1xqV8xmNSQekWebmmnOdEblUSmh3VdD/ZZLDOkqIiLU4N K39JaR5+e7U7+A8+FjTN1QfS3A6jfFEDCVsBxYMEisvMeKSajDtO2eEFkqJdyLdGcV JoqUJ6nIP/t4Q== From: Sweet Tea Dorminy To: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, kernel-team@meta.com, ebiggers@google.com, anand.jain@oracle.com, fdmanana@suse.com, linux-fscrypt@vger.kernel.org, fsverity@lists.linux.dev, zlang@kernel.org Cc: Sweet Tea Dorminy Subject: [RFC PATCH v3 2/9] common/encrypt: add btrfs to get_encryption_*nonce Date: Tue, 8 Aug 2023 13:21:21 -0400 Message-ID: In-Reply-To: References: Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the modes of getting the encryption nonces, either inode or extent, to the various get_encryption_nonce functions. For now, no encrypt test makes a file with more than one extent, so we can just grab the first extent's nonce for the data nonce; when we write a bigger file test, we'll need to change that. Signed-off-by: Sweet Tea Dorminy --- common/encrypt | 31 +++++++++++++++++++++++++++++++ tests/generic/613 | 4 ++++ 2 files changed, 35 insertions(+) diff --git a/common/encrypt b/common/encrypt index 04b6e5ac..fc1c8cc7 100644 --- a/common/encrypt +++ b/common/encrypt @@ -531,6 +531,17 @@ _get_encryption_file_nonce() found = 0; }' ;; + btrfs) + # Retrieve the fscrypt context for an inode as a hex string. + # btrfs prints these like: + # item 14 key ($inode FSCRYPT_CTXT_ITEM 0) itemoff 15491 itemsize 40 + # value: 02010400000000008fabf3dd745d41856e812458cd765bf0140f41d62853f4c0351837daff4dcc8f + + $BTRFS_UTIL_PROG inspect-internal dump-tree $device | \ + grep -A 1 "key ($inode FSCRYPT_CTXT_ITEM 0)" | \ + grep --only-matching 'value: [[:xdigit:]]\+' | \ + tr -d ' \n' | tail -c 32 + ;; *) _fail "_get_encryption_file_nonce() isn't implemented on $FSTYP" ;; @@ -550,6 +561,23 @@ _get_encryption_data_nonce() ext4|f2fs) _get_encryption_file_nonce $device $inode ;; + btrfs) + # Retrieve the encryption IV of the first file extent in an inode as a hex + # string. btrfs prints the file extents (for simple unshared + # inodes) like: + # item 21 key ($inode EXTENT_DATA 0) itemoff 2534 itemsize 69 + # generation 7 type 1 (regular) + # extent data disk byte 5304320 nr 1048576 + # extent data offset 0 nr 1048576 ram 1048576 + # extent compression 0 (none) + # extent encryption 161 ((1, 40: context 0201040200000000116a77667261d7422a4b1ed8c427e685edb7a0d370d0c9d40030333033333330)) + + + $BTRFS_UTIL_PROG inspect-internal dump-tree $device | \ + grep -A 5 "key ($inode EXTENT_DATA 0)" | \ + grep --only-matching 'context [[:xdigit:]]\+' | \ + tr -d ' \n' | tail -c 32 + ;; *) _fail "_get_encryption_data_nonce() isn't implemented on $FSTYP" ;; @@ -572,6 +600,9 @@ _require_get_encryption_nonce_support() # Otherwise the xattr is incorrectly parsed as v1. But just let # the test fail in that case, as it was an f2fs-tools bug... ;; + btrfs) + _require_command "$BTRFS_UTIL_PROG" btrfs + ;; *) _notrun "_get_encryption_*nonce() isn't implemented on $FSTYP" ;; diff --git a/tests/generic/613 b/tests/generic/613 index 47c60e9c..279b1bfb 100755 --- a/tests/generic/613 +++ b/tests/generic/613 @@ -69,6 +69,10 @@ echo -n > $tmp.nonces_hex echo -n > $tmp.nonces_bin for inode in "${inodes[@]}"; do nonce=$(_get_encryption_data_nonce $SCRATCH_DEV $inode) + if [ "$FSTYP" == "btrfs" ] && [ "$nonce" == "" ] + then + nonce=$(_get_encryption_file_nonce $SCRATCH_DEV $inode) + fi if (( ${#nonce} != 32 )) || [ -n "$(echo "$nonce" | tr -d 0-9a-fA-F)" ] then _fail "Expected nonce for inode $inode to be 16 bytes (32 hex characters), but got \"$nonce\"" From patchwork Tue Aug 8 17:21:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sweet Tea Dorminy X-Patchwork-Id: 13346533 Received: from box.fidei.email (box.fidei.email [71.19.144.250]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DBF351B7DB for ; Tue, 8 Aug 2023 17:31:27 +0000 (UTC) Received: from authenticated-user (box.fidei.email [71.19.144.250]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by box.fidei.email (Postfix) with ESMTPSA id 3385E809D8; Tue, 8 Aug 2023 13:22:12 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=dorminy.me; s=mail; t=1691515332; bh=YBYT5+wjFCkvsFKr1anN5MPIlgnu4aucZknFt5kUKMw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SqV+z961XpUFSRkO1ScWO5VvlCHhN3yH0Ks8QgG5pbUgaPnj5PQZRX64o1gwzport KF7GoAx9BdjtW6xrlvTSnzsJtfqenNFsLEANEP8H7lM64mjUWHCZ+3MD0+Ofg1ECHI mlM1Kb20BqVk501xAhiNPu48GBEoyD/JYlMNUhSrp6FdVfp/adgXzVJX+Pco2Y0beK KxOwMhw3dfvB06Xy2CyLX9Xd+PDuFXvq51ZuXiimVEI93KRDJ41xigKpa9KUZXoSEB 5Mc3QGfp6khVM0mAADUy5sVbs2wLooV/cuCjzvJSNf7Uogleof2KCGlX0H28hM81DQ 7h1CFpv+FDing== From: Sweet Tea Dorminy To: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, kernel-team@meta.com, ebiggers@google.com, anand.jain@oracle.com, fdmanana@suse.com, linux-fscrypt@vger.kernel.org, fsverity@lists.linux.dev, zlang@kernel.org Cc: Sweet Tea Dorminy Subject: [RFC PATCH v3 3/9] common/encrypt: add btrfs to get_ciphertext_filename Date: Tue, 8 Aug 2023 13:21:22 -0400 Message-ID: <3e0ebf7a15ff15818f3188fd757f396284ddbc3a.1691530000.git.sweettea-kernel@dorminy.me> In-Reply-To: References: Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the relevant call to get an encrypted filename from btrfs. Signed-off-by: Sweet Tea Dorminy --- common/encrypt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/common/encrypt b/common/encrypt index fc1c8cc7..2c1925da 100644 --- a/common/encrypt +++ b/common/encrypt @@ -618,6 +618,19 @@ _get_ciphertext_filename() local dir_inode=$3 case $FSTYP in + btrfs) + # Extract the filename from the inode_ref object, similar to: + # item 24 key (259 INODE_REF 257) itemoff 14826 itemsize 26 + # index 3 namelen 16 name: J\xf7\x15tD\x8eL\xae/\x98\x9f\x09\xc1\xb6\x09> + # + $BTRFS_UTIL_PROG inspect-internal dump-tree $device | \ + grep -A 1 "key ($inode INODE_REF " | tail -n 1 | \ + perl -ne ' + s/.*?name: //; + chomp; + s/\\x([[:xdigit:]]{2})/chr hex $1/eg; + print;' + ;; ext4) # Extract the filename from the debugfs output line like: # @@ -715,6 +728,9 @@ _require_get_ciphertext_filename_support() _notrun "dump.f2fs (f2fs-tools) is too old; doesn't support showing unambiguous on-disk filenames" fi ;; + btrfs) + _require_command "$BTRFS_UTIL_PROG" btrfs + ;; *) _notrun "_get_ciphertext_filename() isn't implemented on $FSTYP" ;; From patchwork Tue Aug 8 17:21:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sweet Tea Dorminy X-Patchwork-Id: 13346535 Received: from box.fidei.email (box.fidei.email [71.19.144.250]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DEEA414F6B for ; Tue, 8 Aug 2023 17:31:27 +0000 (UTC) Received: from authenticated-user (box.fidei.email [71.19.144.250]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by box.fidei.email (Postfix) with ESMTPSA id B1571809E9; Tue, 8 Aug 2023 13:22:13 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=dorminy.me; s=mail; t=1691515333; bh=726Inc6P68BCi0kM+SUSni3m2wN66ATgsTZpdV1YXhA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=w2iw0OWh+nUjaKDkhWMKMEaHCUJawApxUAUe/nrDey15oXBcy2yG3RjrFIwfIKt8F pFSpf/AT+avhEWMfnWOmaYswBMTJDEJs18SbdCMKua579tjYZf2FrFFmYYMVHkWVnk Bm1zBhLLx8XlN2lS/V76bO4jUujZTnjpbHYepR13pzH35WA2C/iY4EI0r68FJbV+I8 88/poEu/zzBw6nh7rV/UpCJslz70ATeq1Z++e3i3UUWlBZD9ykSXWoLyGoYOWAxlB9 gAfxCQHl0feLgtOS5vLV0DsvIzfjz6ICKtvVs87/Zqh04CHZ3CluUSMEKWn3hL4x9a LGzme54L6kTsQ== From: Sweet Tea Dorminy To: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, kernel-team@meta.com, ebiggers@google.com, anand.jain@oracle.com, fdmanana@suse.com, linux-fscrypt@vger.kernel.org, fsverity@lists.linux.dev, zlang@kernel.org Cc: Sweet Tea Dorminy Subject: [RFC PATCH v3 4/9] common/encrypt: enable making a encrypted btrfs filesystem Date: Tue, 8 Aug 2023 13:21:23 -0400 Message-ID: <810d879650dd3bd8da1df2e4611d55adaf670ae4.1691530000.git.sweettea-kernel@dorminy.me> In-Reply-To: References: Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Signed-off-by: Sweet Tea Dorminy --- common/encrypt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/encrypt b/common/encrypt index 2c1925da..1372af66 100644 --- a/common/encrypt +++ b/common/encrypt @@ -153,6 +153,9 @@ _scratch_mkfs_encrypted() # erase the UBI volume; reformated automatically on next mount $UBIUPDATEVOL_PROG ${SCRATCH_DEV} -t ;; + btrfs) + _scratch_mkfs + ;; ceph) _scratch_cleanup_files ;; @@ -168,6 +171,9 @@ _scratch_mkfs_sized_encrypted() ext4|f2fs) MKFS_OPTIONS="$MKFS_OPTIONS -O encrypt" _scratch_mkfs_sized $* ;; + btrfs) + _scratch_mkfs_sized $* + ;; *) _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized_encrypted" ;; From patchwork Tue Aug 8 17:21:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sweet Tea Dorminy X-Patchwork-Id: 13346521 Received: from box.fidei.email (box.fidei.email [71.19.144.250]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF28A14A8E for ; Tue, 8 Aug 2023 17:22:15 +0000 (UTC) Received: from authenticated-user (box.fidei.email [71.19.144.250]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by box.fidei.email (Postfix) with ESMTPSA id 1542F83548; Tue, 8 Aug 2023 13:22:15 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=dorminy.me; s=mail; t=1691515335; bh=k80BosUuOf3+UJm9EFkXHB69AfR7v14eADYsDzCRrm8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ehjjsu3wu1rmbMIsG8YnYBgeZrV5ixD8xbUyncG5Ux1jx2ZVVq5OpekqEcHmbqtPE RsROO5EZclETdFRvSgxUyKu9/YEM5mwY6E1pfA5yfsfr//lIKcofAI5hGn2RXOIrUE DgEGAmstfmbkgy7t2ae8akFhm+0P3yE1C/HRVvOitL3YfrAhWhzBRI7mdlcpoSJH4M MyZ/1I3AQ1TpghdvWyzIvBanGvwcbnyfJ0Ixmj5cfYJ2Dc2/C/pK4uadaOSAFSsxJB AljBYxqlJrMzoarmJM9bXIecmQ34GfJmoqqeX19XHAi7MxwSUSyP1ahqZYrsNyOwgn G71014MWyEG0w== From: Sweet Tea Dorminy To: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, kernel-team@meta.com, ebiggers@google.com, anand.jain@oracle.com, fdmanana@suse.com, linux-fscrypt@vger.kernel.org, fsverity@lists.linux.dev, zlang@kernel.org Cc: Sweet Tea Dorminy Subject: [RFC PATCH v3 5/9] generic/613: write some actual data for btrfs Date: Tue, 8 Aug 2023 13:21:24 -0400 Message-ID: <200c306794a620f1ff7db0dddf304ec5997e4456.1691530000.git.sweettea-kernel@dorminy.me> In-Reply-To: References: Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Currently, the test touches a file and assumes that that is sufficient to generate a new nonce to test for that file. However, btrfs doesn't store an encryption context for a leaf inode, and doesn't store an encryption context for data within a leaf inode until data is actually written. Thus, merely touching the file on btrfs doesn't actually generate a testable nonce. Instead, write a trivial bit of data to each file, which provokes btrfs to generate a encryption context for the data and thus a testable nonce. Signed-off-by: Sweet Tea Dorminy --- tests/generic/613 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/generic/613 b/tests/generic/613 index 279b1bfb..11f28c74 100755 --- a/tests/generic/613 +++ b/tests/generic/613 @@ -53,11 +53,11 @@ for i in {1..50}; do done for i in {1..50}; do file=$SCRATCH_MNT/v1_policy_dir_1/$i - touch $file + echo "0" > $file inodes+=("$(stat -c %i $file)") file=$SCRATCH_MNT/v2_policy_dir_1/$i - touch $file + echo "0" > $file inodes+=("$(stat -c %i $file)") done _scratch_unmount From patchwork Tue Aug 8 17:21:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sweet Tea Dorminy X-Patchwork-Id: 13346522 Received: from box.fidei.email (box.fidei.email [71.19.144.250]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4772B14A8E for ; Tue, 8 Aug 2023 17:22:17 +0000 (UTC) Received: from authenticated-user (box.fidei.email [71.19.144.250]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by box.fidei.email (Postfix) with ESMTPSA id 868BC8354E; Tue, 8 Aug 2023 13:22:16 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=dorminy.me; s=mail; t=1691515336; bh=p0lhrwRpH0M08g76wr/r8ueKNz5/IfAaaBLhtQvn+Po=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JULWczvRUBLxdZcdp04IbpPnHo4zu+K8pB7HAS8HjKcIz+L9GtjY2H43j9OFxRvvJ 5qXoYchSa9DeV/WCGLCuIRuaMctWnM5jEMYy02QXXJH5e2eeIMMSPDQuv+ZW1Lju5g fLR0xEFF5whXC27nKEpNEXV3HXty1c2Yjohm58JcP3ja/mxuJvG6vfKgKvQSnbWu9f 0KsWQKw41rPlJLOF39aH+epy1dPvnNgHNpnVWcnE2E7WsfmaNUY0QvsaeJV7DpqwLy bT8DsQq61CfR8v6Nm4qPc9oNVhHjYG6dIORsGHvziGVpb3ecgNhKa4yD62aNX5gFXv Pp4dNl8YcpX+w== From: Sweet Tea Dorminy To: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, kernel-team@meta.com, ebiggers@google.com, anand.jain@oracle.com, fdmanana@suse.com, linux-fscrypt@vger.kernel.org, fsverity@lists.linux.dev, zlang@kernel.org Cc: Sweet Tea Dorminy Subject: [RFC PATCH v3 6/9] tests: adjust generic/429 for extent encryption Date: Tue, 8 Aug 2023 13:21:25 -0400 Message-ID: <0952e60c8e73a41a0448e3ada8172744a6882550.1691530000.git.sweettea-kernel@dorminy.me> In-Reply-To: References: Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Extent encryption is different from the existing inode-based encryption insofar as it only generates encryption keys for data encryption at the moment at which the data is written. This means that when a session key is removed, even if there's an open file using it, that file immediately becomes unreadable and unwritable. This isn't an issue for non-session keys, which are soft deleted by fscrypt and stick around until there are no more open files with extent encryption using them. But for session keys, which are managed by the kernel keyring directly instead of through fscrypt, when they're removed they're removed. generic/429 uses session keys and expects to use the written data after key removal; while it's not quite what the test means for other filesystems, most of the test is still meaningful if we push the dirty data into the filesystem with a sync before dropping the key. Signed-off-by: Sweet Tea Dorminy --- tests/generic/429 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/generic/429 b/tests/generic/429 index 2cf12316..1d26deda 100755 --- a/tests/generic/429 +++ b/tests/generic/429 @@ -68,6 +68,12 @@ show_directory_with_key() show_file_contents } +# btrfs needs to have dirty data pushed into it before session keyring +# is unlinked, as it doesn't set up the data encryption key until then. +if [ "$FSTYP" = "btrfs" ]; then + sync +fi + # View the directory without the encryption key. The plaintext names shouldn't # exist, but 'cat' each to verify this, which also should create negative # dentries. The no-key names are unpredictable by design, but verify that the From patchwork Tue Aug 8 17:21:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sweet Tea Dorminy X-Patchwork-Id: 13346523 Received: from box.fidei.email (box.fidei.email [71.19.144.250]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D4F914A9C for ; Tue, 8 Aug 2023 17:22:18 +0000 (UTC) Received: from authenticated-user (box.fidei.email [71.19.144.250]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by box.fidei.email (Postfix) with ESMTPSA id 016B78354F; Tue, 8 Aug 2023 13:22:17 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=dorminy.me; s=mail; t=1691515338; bh=PYXYRGTxzf2mT8aQvtS64Oy9XHNpPxgL/l5PEONJa0A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=md0/SRAy/lGS01fQdNMFysv9kvTGeMRYsQwSM6CYwnOdzRKuA9ufS4JO57TEwaue1 Br8D5ufY6/NyCEc5TAeQ5Bbn+ck4WqL0wPD4TYGxvN3vuVBTFvlMGA5UZkUl8wiju8 C9EerO3sXwOJ8OA9dzrkw6N2SZDKh9QjDnE4UMSv3Q4sRg2Rd7EFyP6E37IUP0rDwX I+jL1HDZ78pZ6ZqYXLoPBPoE5o5ANHVNVDcGimwdsgXzj0wuKQdwfOp/brg8ywV7O2 nAXrgxuaT2tcdYrGNjsq/wFpbbUPLuGL40agGuHjmjueuvOOAV0Swp8Z+NH5vLfDYz GLG1SECtZhVdQ== From: Sweet Tea Dorminy To: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, kernel-team@meta.com, ebiggers@google.com, anand.jain@oracle.com, fdmanana@suse.com, linux-fscrypt@vger.kernel.org, fsverity@lists.linux.dev, zlang@kernel.org Cc: Sweet Tea Dorminy Subject: [RFC PATCH v3 7/9] common/verity: explicitly don't allow btrfs encryption Date: Tue, 8 Aug 2023 13:21:26 -0400 Message-ID: <27188582f31ad7e6e7027170a81fa84d77815868.1691530000.git.sweettea-kernel@dorminy.me> In-Reply-To: References: Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Currently btrfs encryption doesn't support verity, but it is planned to one day. To be explicit about the lack of support, add a custom error message to the combination. Signed-off-by: Sweet Tea Dorminy --- common/verity | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/verity b/common/verity index e0937717..5e651316 100644 --- a/common/verity +++ b/common/verity @@ -224,6 +224,10 @@ _scratch_mkfs_encrypted_verity() # features with -O. Instead -O must be supplied multiple times. _scratch_mkfs -O encrypt -O verity ;; + btrfs) + # currently verity + encryption is not supported + _notrun "btrfs doesn't currently support verity + encryption" + ;; *) _notrun "$FSTYP not supported in _scratch_mkfs_encrypted_verity" ;; From patchwork Tue Aug 8 17:21:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sweet Tea Dorminy X-Patchwork-Id: 13346524 Received: from box.fidei.email (box.fidei.email [71.19.144.250]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 266D314A9C for ; Tue, 8 Aug 2023 17:22:19 +0000 (UTC) Received: from authenticated-user (box.fidei.email [71.19.144.250]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by box.fidei.email (Postfix) with ESMTPSA id 705CC83548; Tue, 8 Aug 2023 13:22:19 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=dorminy.me; s=mail; t=1691515339; bh=3QofvkrzEbKIE7kiT4biu6yi+YODuBy1obePJtOF1UE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ox+m8WtBmbG7cZnsJbBcOj/l0/QHDpBcImOeWhZSNbacQkiGW8tQgicKq0STZoI3l qjCu16zKNyQZ5JpTTwme80vD81hqFWgaCaRD+Pa/2t5fpcEXBlSt4I9Fb62gD3EBx1 fhNyPQVEzCKIrxWzg1GI3YHyuT9AR+3aPOybW2iJhkAe8EzD/SeokMgb4ZrN6Ed/Zt hFMTo/+lVMedyMELC7KBo2AslcmI3MU8Ymj+898PEEUaAfldb5+XMJWWjADq0C9fyb DKKc4Nu4AoyUaSIlOsWsnl58SKYNVCZYpPQuvhDFGqkZ94uPoOSxuMxzPKGxAf7CN+ GnyQJrRkGY0MA== From: Sweet Tea Dorminy To: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, kernel-team@meta.com, ebiggers@google.com, anand.jain@oracle.com, fdmanana@suse.com, linux-fscrypt@vger.kernel.org, fsverity@lists.linux.dev, zlang@kernel.org Cc: Sweet Tea Dorminy Subject: [RFC PATCH v3 8/9] btrfs: add simple test of reflink of encrypted data Date: Tue, 8 Aug 2023 13:21:27 -0400 Message-ID: In-Reply-To: References: Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Make sure that we succeed at reflinking encrypted data. Test deliberately numbered with a high number so it won't conflict with tests between now and merge. --- tests/btrfs/613 | 59 +++++++++++++++++++++++++++++++++++++++++++++ tests/btrfs/613.out | 13 ++++++++++ 2 files changed, 72 insertions(+) create mode 100755 tests/btrfs/613 create mode 100644 tests/btrfs/613.out diff --git a/tests/btrfs/613 b/tests/btrfs/613 new file mode 100755 index 00000000..0288016e --- /dev/null +++ b/tests/btrfs/613 @@ -0,0 +1,59 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2023 Meta Platforms, Inc. All Rights Reserved. +# +# FS QA Test 613 +# +# Check if reflinking one encrypted file on btrfs succeeds. +# +. ./common/preamble +_begin_fstest auto encrypt + +# Import common functions. +. ./common/encrypt +. ./common/filter +. ./common/reflink + +# real QA test starts here + +# Modify as appropriate. +_supported_fs btrfs + +_require_test +_require_scratch +_require_cp_reflink +_require_scratch_encryption -v 2 +_require_command "$KEYCTL_PROG" keyctl + +_scratch_mkfs_encrypted &>> $seqres.full +_scratch_mount + +dir=$SCRATCH_MNT/dir +mkdir $dir +_set_encpolicy $dir $TEST_KEY_IDENTIFIER +_add_enckey $SCRATCH_MNT "$TEST_RAW_KEY" +echo "Creating and reflinking a file" +$XFS_IO_PROG -t -f -c "pwrite 0 33k" $dir/test > /dev/null +cp --reflink=always $dir/test $dir/test2 + +echo "Can't reflink encrypted and unencrypted" +cp --reflink=always $dir/test $SCRATCH_MNT/fail |& _filter_scratch + +echo "Diffing the file and its copy" +diff $dir/test $dir/test2 + +echo "Verifying the files are reflinked" +_verify_reflink $dir/test $dir/test2 + +echo "Diffing the files after remount" +_scratch_cycle_mount +_add_enckey $SCRATCH_MNT "$TEST_RAW_KEY" +diff $dir/test $dir/test2 + +echo "Diffing the files after key remove" +_rm_enckey $SCRATCH_MNT $TEST_KEY_IDENTIFIER +diff $dir/test $dir/test2 |& _filter_scratch + +# success, all done +status=0 +exit diff --git a/tests/btrfs/613.out b/tests/btrfs/613.out new file mode 100644 index 00000000..4895d6dd --- /dev/null +++ b/tests/btrfs/613.out @@ -0,0 +1,13 @@ +QA output created by 613 +Added encryption key with identifier 69b2f6edeee720cce0577937eb8a6751 +Creating and reflinking a file +Can't reflink encrypted and unencrypted +cp: failed to clone 'SCRATCH_MNT/fail' from 'SCRATCH_MNT/dir/test': Invalid argument +Diffing the file and its copy +Verifying the files are reflinked +Diffing the files after remount +Added encryption key with identifier 69b2f6edeee720cce0577937eb8a6751 +Diffing the files after key remove +Removed encryption key with identifier 69b2f6edeee720cce0577937eb8a6751 +diff: SCRATCH_MNT/dir/test: No such file or directory +diff: SCRATCH_MNT/dir/test2: No such file or directory From patchwork Tue Aug 8 17:21:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sweet Tea Dorminy X-Patchwork-Id: 13346525 Received: from box.fidei.email (box.fidei.email [71.19.144.250]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8FD5D14A9C for ; Tue, 8 Aug 2023 17:22:21 +0000 (UTC) Received: from authenticated-user (box.fidei.email [71.19.144.250]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by box.fidei.email (Postfix) with ESMTPSA id C779083554; Tue, 8 Aug 2023 13:22:20 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=dorminy.me; s=mail; t=1691515341; bh=2Lohhtaz6PdSPwgh5QIopdljrqSX9xnbxosrQff/heQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rVoiGK4Nu4JrF70NDmOxeGYv64z+woR8q3srCAPTZAePCITTreXoQKJk4WBRlCGBp rXFSMddQfeuDlCX0rIsU7u31pSOFNG6VpwaXF5G3TkWxLiUduNnnrZSxeWR1We+Pjw ybUlfpu5fBDPpmdTiTtaGMPE2Z+8Y5pLD0vNxJyjkUjKXptc5Q/vkdlEFAxFkwAwoI 9rTjT4JBZd/EMPq2iqt2spZnCe+4oX7FSHk36ROlE6Mk0ycpq3ZSVArrcz9Ok1ASJv 7roVQ5Q82yIi0HoGsh8L/B7y4+tpnp9b9inF0aatzvOilg/8R6tk/8Iksn6pDRrPTG 05rwyqQFkk0cA== From: Sweet Tea Dorminy To: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, kernel-team@meta.com, ebiggers@google.com, anand.jain@oracle.com, fdmanana@suse.com, linux-fscrypt@vger.kernel.org, fsverity@lists.linux.dev, zlang@kernel.org Cc: Sweet Tea Dorminy Subject: [RFC PATCH v3 9/9] btrfs: test snapshotting encrypted subvol Date: Tue, 8 Aug 2023 13:21:28 -0400 Message-ID: <400435f749f54e07a23e8e3c67bb717646747cc4.1691530000.git.sweettea-kernel@dorminy.me> In-Reply-To: References: Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Make sure that snapshots of encrypted data are readable and writeable. Test deliberately high-numbered to not conflict. Signed-off-by: Sweet Tea Dorminy --- tests/btrfs/614 | 76 ++++++++++++++++++++++++++++++ tests/btrfs/614.out | 111 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100755 tests/btrfs/614 create mode 100644 tests/btrfs/614.out diff --git a/tests/btrfs/614 b/tests/btrfs/614 new file mode 100755 index 00000000..87dd27f9 --- /dev/null +++ b/tests/btrfs/614 @@ -0,0 +1,76 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2023 Meta Platforms, Inc. All Rights Reserved. +# +# FS QA Test 614 +# +# Try taking a snapshot of an encrypted subvolume. Make sure the snapshot is +# still readable. Rewrite part of the subvol with the same data; make sure it's +# still readable. +# +. ./common/preamble +_begin_fstest auto encrypt + +# Import common functions. +. ./common/encrypt +. ./common/filter + +# real QA test starts here +_supported_fs btrfs + +_require_test +_require_scratch +_require_scratch_encryption -v 2 +_require_command "$KEYCTL_PROG" keyctl + +_scratch_mkfs_encrypted &>> $seqres.full +_scratch_mount + +udir=$SCRATCH_MNT/reference +dir=$SCRATCH_MNT/subvol +dir2=$SCRATCH_MNT/subvol2 +$BTRFS_UTIL_PROG subvolume create $dir >> $seqres.full +mkdir $udir + +_set_encpolicy $dir $TEST_KEY_IDENTIFIER +_add_enckey $SCRATCH_MNT "$TEST_RAW_KEY" + +# get files with lots of extents by using backwards writes. +for j in `seq 0 50`; do + for i in `seq 20 -1 1`; do + $XFS_IO_PROG -f -d -c "pwrite $(($i * 4096)) 4096" \ + $dir/foo-$j >> $seqres.full | _filter_xfs_io + $XFS_IO_PROG -f -d -c "pwrite $(($i * 4096)) 4096" \ + $udir/foo-$j >> $seqres.full | _filter_xfs_io + done +done + +$BTRFS_UTIL_PROG subvolume snapshot $dir $dir2 | _filter_scratch + +_scratch_remount +_add_enckey $SCRATCH_MNT "$TEST_RAW_KEY" +sleep 30 +echo "Diffing $dir and $dir2" +diff $dir $dir2 + +echo "Rewriting $dir2 partly" +# rewrite half of each file in the snapshot +for j in `seq 0 50`; do + for i in `seq 10 -1 1`; do + $XFS_IO_PROG -f -d -c "pwrite $(($i * 4096)) 4096" \ + $dir2/foo-$j >> $seqres.full | _filter_xfs_io + done +done + +echo "Diffing $dir and $dir2" +diff $dir $dir2 + +echo "Dropping key and diffing" +_rm_enckey $SCRATCH_MNT $TEST_KEY_IDENTIFIER +diff $dir $dir2 |& _filter_scratch | _filter_nokey_filenames + +$BTRFS_UTIL_PROG subvolume delete $dir > /dev/null 2>&1 + +# success, all done +status=0 +exit diff --git a/tests/btrfs/614.out b/tests/btrfs/614.out new file mode 100644 index 00000000..390807e8 --- /dev/null +++ b/tests/btrfs/614.out @@ -0,0 +1,111 @@ +QA output created by 614 +Added encryption key with identifier 69b2f6edeee720cce0577937eb8a6751 +Create a snapshot of 'SCRATCH_MNT/subvol' in 'SCRATCH_MNT/subvol2' +Added encryption key with identifier 69b2f6edeee720cce0577937eb8a6751 +Diffing /mnt/scratch/subvol and /mnt/scratch/subvol2 +Rewriting /mnt/scratch/subvol2 partly +Diffing /mnt/scratch/subvol and /mnt/scratch/subvol2 +Dropping key and diffing +Removed encryption key with identifier 69b2f6edeee720cce0577937eb8a6751 +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME +NOKEY_NAME: NOKEY_NAME/NOKEY_NAME/NOKEY_NAME: NOKEY_NAME NOKEY_NAME NOKEY_NAME NOKEY_NAME