From patchwork Mon Oct 23 21:40:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829654 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="JbL7E3Bu"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="glzQYSNs"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVHk37gCz9sPt for ; Tue, 24 Oct 2017 08:42:42 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=1tKLtPGlbLKk3VULsIzy/vWULmfdWIj/vNkrOrHFMkk=; b=JbL7E3Bunvygp0bLYN4KJQo2GB wlI+1kz1h8JI/Ag9o/nV3iR7N6P6aSjPS2XaGhnPM8o/l037VkUKBoyWdHNrhZ3k1zwyuAiyZ+Hc3 hBAdhTkpvDHIg5BCcquyLSevC8uNiQlOo5Dz3TRb8FxOshHfV+WCnuiWDpYSwL6jnXJ7SwqLwBuOp +NqQQVsROhI+3X6e7S7StyTp4VpzFRT83PY79OksjhOFOOooU7RQCfUzKZD8bCr5R1hqJ5Itv9BaU hdw3tcqkEJhaohW14q76IaJugBHfe2Woc3X/D37wZzLG3hukbq1rI2Dwcy6AW3b0voF+NlJPlZLlX /NkiCSMA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUV-0004kK-Tf; Mon, 23 Oct 2017 21:42:36 +0000 Received: from mail-io0-x242.google.com ([2607:f8b0:4001:c06::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUR-0004fL-Pn for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:34 +0000 Received: by mail-io0-x242.google.com with SMTP id n137so21760645iod.6 for ; Mon, 23 Oct 2017 14:42:11 -0700 (PDT) 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=RWzr6AEc1Y+08Sc6Z5TXghPCExRxgnlcGUvUgvGnKio=; b=glzQYSNsSBDLDE/nk4frqeg3HNva3bS7lXX45otUIZry+TOorx2ur4YhytLLdHBboa nJYL8OmAh+KT1AQsBTAT0fm8lCRzjhZF2x9JMNSiF0L8qXHirwRaFbyqAfX6NfP0ojSr i3Iv6kdyHr3Mefd8shSvkh/OQUdlZeXsGUElN5vr6CgmMk3vgpTsZs4djk1VxxORTn/j h/Hs07C+BkkGu3SuSJlcBJyb6ltNjLSveyGHUHiRBkvJ8jtiI1LFPvcrpOzspGUW9AIU Sa/fy7U9zAzOYj+MazmfPukQbaclsIAGVWqvEa8B4+6CJzUjrhVvvk3vzDl9TQtrnbCd 4E+w== 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=RWzr6AEc1Y+08Sc6Z5TXghPCExRxgnlcGUvUgvGnKio=; b=riMXmV0th/GRFLlE5znbHFySk/3TDcckzpzIcdzxmcsjVmQdSPszu4i3vttmsw/+z6 K3rhgme++jVe+0OF1WwNTSt6/3g5bbS9Xyv9FUx+fpCJ3H9FIDlnqOPZMjNVWIhrbpv7 9LU/3J8g8ajIFYtA0PKlSnCsQJWnMcAlmeb8tqDjVtxbq3KeeS2kPHL+6bls3DyL8UzJ CS6u6d9KaLFso51P3hCRq8wtXbc6mmu4vPBMZrWFonhWDpFvIvIPfqGTOhfsoUbfZuPe 7wffUSpb4MCbyLqzKEokDidND23PIYa+FaMQAxg8J6J6zjrrGTu32ZVRfiuOeshsONpN ZhWA== X-Gm-Message-State: AMCzsaWCKdSHTWXabEQfa6d4suwAsn07OofNatFXrEDIBuT0tsNYt1At nLceQkRSM+g8XiGKHgOisXk= X-Google-Smtp-Source: ABhQp+SkwdGNYgYLIZc75kQ10EaSGMzOQA0keAn+yXuFTLWSYti8dpoKFAj2BVpivHhmCf6mtFoV5w== X-Received: by 10.107.29.73 with SMTP id d70mr18396373iod.201.1508794930798; Mon, 23 Oct 2017 14:42:10 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:10 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 01/25] fs, fscrypt: move uapi definitions to new header Date: Mon, 23 Oct 2017 14:40:34 -0700 Message-Id: <20171023214058.128121-2-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144231_941930_3779E807 X-CRM114-Status: GOOD ( 16.59 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers There are going to be more filesystem encryption definitions added, and we don't want to use a disproportionate amount of space in for filesystem encryption stuff. So move the fscrypt definitions to a new header . For compatibility with existing userspace programs which may be including , still includes the new header. (It's debatable whether we really need this, though; the filesystem encryption API is new enough that most if not all programs that are using it have to declare it themselves anyway.) Signed-off-by: Eric Biggers Reviewed-by: Michael Halcrow --- include/linux/fscrypt.h | 2 +- include/uapi/linux/fs.h | 50 +++-------------------------------------- include/uapi/linux/fscrypt.h | 53 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 48 deletions(-) create mode 100644 include/uapi/linux/fscrypt.h diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 53437bfdfcbc..f7aa7d62e235 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #define FS_CRYPTO_BLOCK_SIZE 16 diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 56235dddea7d..6ecd3ee9960c 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -12,6 +12,9 @@ #include #include #include +#ifndef __KERNEL__ +#include +#endif /* * It's silly to have NR_OPEN bigger than NR_FILE, but you can change @@ -253,53 +256,6 @@ struct fsxattr { #define FS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) #define FS_IOC_FSSETXATTR _IOW ('X', 32, struct fsxattr) -/* - * File system encryption support - */ -/* Policy provided via an ioctl on the topmost directory */ -#define FS_KEY_DESCRIPTOR_SIZE 8 - -#define FS_POLICY_FLAGS_PAD_4 0x00 -#define FS_POLICY_FLAGS_PAD_8 0x01 -#define FS_POLICY_FLAGS_PAD_16 0x02 -#define FS_POLICY_FLAGS_PAD_32 0x03 -#define FS_POLICY_FLAGS_PAD_MASK 0x03 -#define FS_POLICY_FLAGS_VALID 0x03 - -/* Encryption algorithms */ -#define FS_ENCRYPTION_MODE_INVALID 0 -#define FS_ENCRYPTION_MODE_AES_256_XTS 1 -#define FS_ENCRYPTION_MODE_AES_256_GCM 2 -#define FS_ENCRYPTION_MODE_AES_256_CBC 3 -#define FS_ENCRYPTION_MODE_AES_256_CTS 4 -#define FS_ENCRYPTION_MODE_AES_128_CBC 5 -#define FS_ENCRYPTION_MODE_AES_128_CTS 6 - -struct fscrypt_policy { - __u8 version; - __u8 contents_encryption_mode; - __u8 filenames_encryption_mode; - __u8 flags; - __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; -}; - -#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) -#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) -#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) - -/* Parameters for passing an encryption key into the kernel keyring */ -#define FS_KEY_DESC_PREFIX "fscrypt:" -#define FS_KEY_DESC_PREFIX_SIZE 8 - -/* Structure that userspace passes to the kernel keyring */ -#define FS_MAX_KEY_SIZE 64 - -struct fscrypt_key { - __u32 mode; - __u8 raw[FS_MAX_KEY_SIZE]; - __u32 size; -}; - /* * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS) * diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h new file mode 100644 index 000000000000..c09209fc42ea --- /dev/null +++ b/include/uapi/linux/fscrypt.h @@ -0,0 +1,53 @@ +#ifndef _UAPI_LINUX_FSCRYPT_H +#define _UAPI_LINUX_FSCRYPT_H + +#include + +/* + * File system encryption support + */ +/* Policy provided via an ioctl on the topmost directory */ +#define FS_KEY_DESCRIPTOR_SIZE 8 + +#define FS_POLICY_FLAGS_PAD_4 0x00 +#define FS_POLICY_FLAGS_PAD_8 0x01 +#define FS_POLICY_FLAGS_PAD_16 0x02 +#define FS_POLICY_FLAGS_PAD_32 0x03 +#define FS_POLICY_FLAGS_PAD_MASK 0x03 +#define FS_POLICY_FLAGS_VALID 0x03 + +/* Encryption algorithms */ +#define FS_ENCRYPTION_MODE_INVALID 0 +#define FS_ENCRYPTION_MODE_AES_256_XTS 1 +#define FS_ENCRYPTION_MODE_AES_256_GCM 2 +#define FS_ENCRYPTION_MODE_AES_256_CBC 3 +#define FS_ENCRYPTION_MODE_AES_256_CTS 4 +#define FS_ENCRYPTION_MODE_AES_128_CBC 5 +#define FS_ENCRYPTION_MODE_AES_128_CTS 6 + +struct fscrypt_policy { + __u8 version; + __u8 contents_encryption_mode; + __u8 filenames_encryption_mode; + __u8 flags; + __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; +}; + +#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) +#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) +#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) + +/* Parameters for passing an encryption key into the kernel keyring */ +#define FS_KEY_DESC_PREFIX "fscrypt:" +#define FS_KEY_DESC_PREFIX_SIZE 8 + +/* Structure that userspace passes to the kernel keyring */ +#define FS_MAX_KEY_SIZE 64 + +struct fscrypt_key { + __u32 mode; + __u8 raw[FS_MAX_KEY_SIZE]; + __u32 size; +}; + +#endif /* _UAPI_LINUX_FSCRYPT_H */ From patchwork Mon Oct 23 21:40:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829675 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="XuMw/oP9"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="uSklb3u6"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVKS56Zhz9sPr for ; Tue, 24 Oct 2017 08:44:12 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=LrG4mP9BCa29gtJVwpKj9PN4d1aWKPf/BFwdA+wjM9Q=; b=XuMw/oP9BK79FcFcCtUb+Wmtvt 4FA4D+tOjPU5SkgFPzLtEQ2cB4uoeKzzWk1893HiAUno/tO6M/fLZ92L56uG8ljsE2T5pl7zlZOwF O2axQgMYmtO44okyQPgJAySPhgv0biJwuUX38LLRtsTPlqz39e5+5J+N6gKfGCyoRX6Fhc6Wu+XrE Sj9lrnr/UcLUpvnoYxZAUjquFpdo+555dDcMBlU41buDvbPkMH1BnLc1YniDKJ0uPfBcqsAoO5U4g Ppckb3QZf0bNr71Aftl+ZaMjSJJcgNCrm+j0SNNMEmYHAVBDT82RfCBrXUjUWVnEQ4cJ5BkWWXKeo D/5GqsrQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kVx-00061q-M3; Mon, 23 Oct 2017 21:44:05 +0000 Received: from mail-io0-x243.google.com ([2607:f8b0:4001:c06::243]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUT-0004fN-0j for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:37 +0000 Received: by mail-io0-x243.google.com with SMTP id 97so21700437iok.7 for ; Mon, 23 Oct 2017 14:42:12 -0700 (PDT) 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=loucawc3/CQiBAXgvcIlW3xlYUgnNzHJZkRDJfZAax8=; b=uSklb3u6CI9TowIdZ0ktsKRv2Ji1MJRLDr8NRI7tkfUdod2njNIp1VJL2eYfLg12e6 4KLFOvwa1cqg9xdkS3AT97rz7GK+zE1/Vq1Yz+oI5YEpYY6fLt9x74qdVj2dGs7/19qj nKwIg9fiZ6aI8BIbZPanzxfAPu+e/UTEXJDk8LcIcV0/pUni4LKr831blr9dI1omhZUc Eg34g9QwYhhHnha/HW3Qm4g+7wxkhXn4H6cIRMSeAJEvfwNgxIhqDtyq+D6jdMhDMB9Y TWyjH19huL1bn4B9g35WEECuqiIXICNTvzctwtYXh1DaC+eCPnahZQNE14FJsvs9udf8 WHwg== 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=loucawc3/CQiBAXgvcIlW3xlYUgnNzHJZkRDJfZAax8=; b=sNzHxpECuv9bMNwgxdxDfvA8FsX0uCvuxEHDdDR4Ig27q9iSiB/hkvJRRQjrN+0m5l HFHyoRzuytWMZditlMfA16H1CyRZeGn1v8KIDuufi2ZWWu2tdx9B4VecXH9+MLktNEQl RVPrpV9miCaPL/2vmbg0U1Lj195zSq7n8VrrKXNnv3kauimsDX5Q5IcbvBKgBEB+DlB7 8jsW7WYhLKMNVwmznNv7BreVoOfC0xRW8WgPGmtPgpJV8cowzYJG+Yk1g9ssaZzundp0 vfinpNqUr/wngnhPu1oScPKkpNPlB8Iks1G5fQbnh4m0b4j3wRPIlhyQ0c29tYr4kci/ EkEQ== X-Gm-Message-State: AMCzsaWlPGSEz7wl5TOitlFfrDGE9+mliqZa5KvKl4P4znDxdNOo/zNY yzKl8WoraJKi3ZZuX5kpKg0= X-Google-Smtp-Source: ABhQp+Re5rCHRPrbMbuzWjIj9cd68i0Hd2eWi0ZCQU+UqIW/7fIk/AOCECgu3focwICn0tcDvySzEQ== X-Received: by 10.107.162.67 with SMTP id l64mr19223690ioe.278.1508794932077; Mon, 23 Oct 2017 14:42:12 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:11 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 02/25] fscrypt: use FSCRYPT_ prefix for uapi constants Date: Mon, 23 Oct 2017 14:40:35 -0700 Message-Id: <20171023214058.128121-3-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144233_222893_E45827ED X-CRM114-Status: GOOD ( 15.66 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:243 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Prefix all filesystem encryption UAPI constants except the ioctl numbers with "FSCRYPT_" rather than with "FS_". This namespaces the constants more appropriately and makes it clear that they are related specifically to the filesystem encryption feature, and to the 'fscrypt_*' structures. With some of the old names like "FS_POLICY_FLAGS_VALID", it was not immediately clear that the constant had anything to do with encryption. This is also useful because we'll be adding more encryption-related constants, e.g. for the policy version, and we'd otherwise have to choose whether to use unclear names like FS_POLICY_VERSION_* or inconsistent names like FS_ENCRYPTION_POLICY_VERSION_*. For source compatibility with older userspace programs, keep the old names defined as aliases to the new ones. (It's debatable whether we really need this, though; the filesystem encryption API is new enough that most if not all programs that are using it have to declare it themselves anyway.) Signed-off-by: Eric Biggers Reviewed-by: Michael Halcrow --- Documentation/filesystems/fscrypt.rst | 14 ++++----- include/uapi/linux/fscrypt.h | 59 ++++++++++++++++++++++++----------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst index 776ddc655f79..f12956f3f1f8 100644 --- a/Documentation/filesystems/fscrypt.rst +++ b/Documentation/filesystems/fscrypt.rst @@ -251,14 +251,14 @@ empty directory or verifies that a directory or regular file already has the specified encryption policy. It takes in a pointer to a :c:type:`struct fscrypt_policy`, defined as follows:: - #define FS_KEY_DESCRIPTOR_SIZE 8 + #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 struct fscrypt_policy { __u8 version; __u8 contents_encryption_mode; __u8 filenames_encryption_mode; __u8 flags; - __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; + __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; This structure must be initialized as follows: @@ -274,7 +274,7 @@ This structure must be initialized as follows: - ``flags`` must be set to a value from ```` which identifies the amount of NUL-padding to use when encrypting - filenames. If unsure, use FS_POLICY_FLAGS_PAD_32 (0x3). + filenames. If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32 (0x3). - ``master_key_descriptor`` specifies how to find the master key in the keyring; see `Adding keys`_. It is up to userspace to choose a @@ -374,11 +374,11 @@ followed by the 16-character lower case hex representation of the ``master_key_descriptor`` that was set in the encryption policy. The key payload must conform to the following structure:: - #define FS_MAX_KEY_SIZE 64 + #define FSCRYPT_MAX_KEY_SIZE 64 struct fscrypt_key { u32 mode; - u8 raw[FS_MAX_KEY_SIZE]; + u8 raw[FSCRYPT_MAX_KEY_SIZE]; u32 size; }; @@ -533,7 +533,7 @@ much confusion if an encryption policy were to be added to or removed from anything other than an empty directory.) The struct is defined as follows:: - #define FS_KEY_DESCRIPTOR_SIZE 8 + #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 #define FS_KEY_DERIVATION_NONCE_SIZE 16 struct fscrypt_context { @@ -541,7 +541,7 @@ as follows:: u8 contents_encryption_mode; u8 filenames_encryption_mode; u8 flags; - u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; + u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; }; diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index c09209fc42ea..26c381a40279 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -7,30 +7,31 @@ * File system encryption support */ /* Policy provided via an ioctl on the topmost directory */ -#define FS_KEY_DESCRIPTOR_SIZE 8 +#define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 -#define FS_POLICY_FLAGS_PAD_4 0x00 -#define FS_POLICY_FLAGS_PAD_8 0x01 -#define FS_POLICY_FLAGS_PAD_16 0x02 -#define FS_POLICY_FLAGS_PAD_32 0x03 -#define FS_POLICY_FLAGS_PAD_MASK 0x03 -#define FS_POLICY_FLAGS_VALID 0x03 +/* Encryption policy flags */ +#define FSCRYPT_POLICY_FLAGS_PAD_4 0x00 +#define FSCRYPT_POLICY_FLAGS_PAD_8 0x01 +#define FSCRYPT_POLICY_FLAGS_PAD_16 0x02 +#define FSCRYPT_POLICY_FLAGS_PAD_32 0x03 +#define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03 +#define FSCRYPT_POLICY_FLAGS_VALID 0x03 /* Encryption algorithms */ -#define FS_ENCRYPTION_MODE_INVALID 0 -#define FS_ENCRYPTION_MODE_AES_256_XTS 1 -#define FS_ENCRYPTION_MODE_AES_256_GCM 2 -#define FS_ENCRYPTION_MODE_AES_256_CBC 3 -#define FS_ENCRYPTION_MODE_AES_256_CTS 4 -#define FS_ENCRYPTION_MODE_AES_128_CBC 5 -#define FS_ENCRYPTION_MODE_AES_128_CTS 6 +#define FSCRYPT_MODE_INVALID 0 +#define FSCRYPT_MODE_AES_256_XTS 1 +#define FSCRYPT_MODE_AES_256_GCM 2 +#define FSCRYPT_MODE_AES_256_CBC 3 +#define FSCRYPT_MODE_AES_256_CTS 4 +#define FSCRYPT_MODE_AES_128_CBC 5 +#define FSCRYPT_MODE_AES_128_CTS 6 struct fscrypt_policy { __u8 version; __u8 contents_encryption_mode; __u8 filenames_encryption_mode; __u8 flags; - __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; + __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; #define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) @@ -38,16 +39,36 @@ struct fscrypt_policy { #define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) /* Parameters for passing an encryption key into the kernel keyring */ -#define FS_KEY_DESC_PREFIX "fscrypt:" -#define FS_KEY_DESC_PREFIX_SIZE 8 +#define FSCRYPT_KEY_DESC_PREFIX "fscrypt:" +#define FSCRYPT_KEY_DESC_PREFIX_SIZE 8 /* Structure that userspace passes to the kernel keyring */ -#define FS_MAX_KEY_SIZE 64 +#define FSCRYPT_MAX_KEY_SIZE 64 struct fscrypt_key { __u32 mode; - __u8 raw[FS_MAX_KEY_SIZE]; + __u8 raw[FSCRYPT_MAX_KEY_SIZE]; __u32 size; }; +/**********************************************************************/ + +/* old names; don't add anything new here! */ +#define FS_POLICY_FLAGS_PAD_4 FSCRYPT_POLICY_FLAGS_PAD_4 +#define FS_POLICY_FLAGS_PAD_8 FSCRYPT_POLICY_FLAGS_PAD_8 +#define FS_POLICY_FLAGS_PAD_16 FSCRYPT_POLICY_FLAGS_PAD_16 +#define FS_POLICY_FLAGS_PAD_32 FSCRYPT_POLICY_FLAGS_PAD_32 +#define FS_POLICY_FLAGS_PAD_MASK FSCRYPT_POLICY_FLAGS_PAD_MASK +#define FS_POLICY_FLAGS_VALID FSCRYPT_POLICY_FLAGS_VALID +#define FS_KEY_DESCRIPTOR_SIZE FSCRYPT_KEY_DESCRIPTOR_SIZE +#define FS_ENCRYPTION_MODE_INVALID FSCRYPT_MODE_INVALID +#define FS_ENCRYPTION_MODE_AES_256_XTS FSCRYPT_MODE_AES_256_XTS +#define FS_ENCRYPTION_MODE_AES_256_GCM FSCRYPT_MODE_AES_256_GCM +#define FS_ENCRYPTION_MODE_AES_256_CBC FSCRYPT_MODE_AES_256_CBC +#define FS_ENCRYPTION_MODE_AES_256_CTS FSCRYPT_MODE_AES_256_CTS +#define FS_ENCRYPTION_MODE_AES_128_CBC FSCRYPT_MODE_AES_128_CBC +#define FS_ENCRYPTION_MODE_AES_128_CTS FSCRYPT_MODE_AES_128_CTS +#define FS_KEY_DESC_PREFIX FSCRYPT_KEY_DESC_PREFIX +#define FS_KEY_DESC_PREFIX_SIZE FSCRYPT_KEY_DESC_PREFIX_SIZE +#define FS_MAX_KEY_SIZE FSCRYPT_MAX_KEY_SIZE #endif /* _UAPI_LINUX_FSCRYPT_H */ From patchwork Mon Oct 23 21:40:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829659 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="dCTkNSZ+"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Z5VF66EQ"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVJ72X9wz9sPm for ; Tue, 24 Oct 2017 08:43:03 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=HKSAPddeOgwvbgc5w0GIGjLTetXOghzA6BB3COikISM=; b=dCTkNSZ+mCKCr6IzLyoNjUtv3A SuP71GuO5jR/XK6/CXvsDJzL4NHCgU9Vzr6mNzWDYR2u3HLoJjIKP/awh52ifnIWUxiUIwyEEISwu QzOd0Lhb/CfVj5k3X2Mxr8FOminwRkPA9tG6KkgTSOoF2uaoQ6x5AaiDeriw/HJCYlxqeakYziXOy F0bRqIuuLHM4Ugtw2j6hreVVCQABIp0lTQN2H1sl+DBKnMfU+ndqacWKEmm8UvHKTeTQn30o0vQVS g1i8SmaOR2dcY4/aUfQGi+qR4QqaUaR3Wr7mkkWyEUPk17SMD4gqSuBA/zAypU2teFgYHB9AR84SC n18nJHzQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUn-0004z0-KZ; Mon, 23 Oct 2017 21:42:53 +0000 Received: from mail-io0-x242.google.com ([2607:f8b0:4001:c06::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUR-0004fT-Pr for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:34 +0000 Received: by mail-io0-x242.google.com with SMTP id b186so21739313iof.8 for ; Mon, 23 Oct 2017 14:42:14 -0700 (PDT) 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=UIdBN3CE/fFP8k/jp0riCfEZRfy+HENluYQKnQvJikI=; b=Z5VF66EQ/+TpkjBkAq5HetJTRMqMGRoZsthoenKnv8SUDbRGGI7rAhNCFrI64Bc4CP v1Lbi5iB8dJf3zQmKZhw1JeECFHHam4wpGrEyNvwmbcIdBhPHyFjltgysjt1Dukq9fq1 ApJuQbUCjPagh6Pt8QWDeVvnSlGYhIBhPEcYv29MGfExH47JNXYHSrgcXiiiwDX79Odq jKcu2wyX3LHJPPPY8o4ikxVhd+Z5WJUi03BzkEnPWXC3CXI+J/4IzWIgtoIV2MoDpumj onV2NMdfbG46nlOukMXh11m1G25bZUre6HdH6Fwm9quLwar/Fx9pWoyWaSLA89sIENw3 wPpw== 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=UIdBN3CE/fFP8k/jp0riCfEZRfy+HENluYQKnQvJikI=; b=iLwVhNhcwCOluCgXPN9f9hZOBy61N0Y3vI6wZVPPZOJTNYx+h2E9nJusL7ifE19Ez9 x4jwG5PmlXzp3IMkoH/2dBUvHf3yJhyzaWXOe8/H8eMQiRdR8Er8kQR4Q5CtZIx7UHhA Ev4GfjbhzWFk8aH5bPkrKRaAzhyxYoidbkF1oROcqyKmcyMTyh1fjZaQl6aij1ygj+wn r5hhEdnjCL7ov/JfwhLcmNHG7i4f7FSsHzxPTzooum+QupJq3MGFPyKxeICf8VCgLgIT XRr4dUTohMCU90vBLY92RaZkzkef1a3nH0t4zu2yLZkWC/rSA7PZ+qVN9Eo0yaar2eqi 6cuw== X-Gm-Message-State: AMCzsaXn2kdPulgazf9mLVehlJYxWYDHBI4DqUDkoejOfrbOU+N+C7Jk kzZCOg2zD4a4B8cRsw6CCsI= X-Google-Smtp-Source: ABhQp+R+vPFVohyTk2JIx62it0Kze3jLIFez+/V6aCSrPFu5m+AyM/ocFEP3VoRupHy9ehkxXhVFWQ== X-Received: by 10.107.163.15 with SMTP id m15mr18626997ioe.61.1508794933476; Mon, 23 Oct 2017 14:42:13 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:12 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 03/25] fscrypt: use FSCRYPT_* definitions, not FS_* Date: Mon, 23 Oct 2017 14:40:36 -0700 Message-Id: <20171023214058.128121-4-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144231_970355_89741916 X-CRM114-Status: GOOD ( 17.00 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Update the filesystem encryption kernel code to use the new names for the UAPI constants rather than the old names. Signed-off-by: Eric Biggers Reviewed-by: Michael Halcrow --- fs/crypto/fname.c | 4 ++-- fs/crypto/fscrypt_private.h | 4 ++-- fs/crypto/keyinfo.c | 36 +++++++++++++++++------------------- fs/crypto/policy.c | 14 +++++++------- include/linux/fscrypt.h | 8 ++++---- 5 files changed, 32 insertions(+), 34 deletions(-) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 2878289b3ed2..c91bcef65b9f 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -46,7 +46,7 @@ static int fname_encrypt(struct inode *inode, int res = 0; char iv[FS_CRYPTO_BLOCK_SIZE]; struct scatterlist sg; - int padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK); + int padding = 4 << (ci->ci_flags & FSCRYPT_POLICY_FLAGS_PAD_MASK); unsigned int lim; unsigned int cryptlen; @@ -217,7 +217,7 @@ u32 fscrypt_fname_encrypted_size(const struct inode *inode, u32 ilen) struct fscrypt_info *ci = inode->i_crypt_info; if (ci) - padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK); + padding = 4 << (ci->ci_flags & FSCRYPT_POLICY_FLAGS_PAD_MASK); ilen = max(ilen, (u32)FS_CRYPTO_BLOCK_SIZE); return round_up(ilen, padding); } diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index a180981ee6d7..5cb80a2d39ea 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -43,7 +43,7 @@ struct fscrypt_context { u8 contents_encryption_mode; u8 filenames_encryption_mode; u8 flags; - u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE]; + u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; } __packed; @@ -59,7 +59,7 @@ struct fscrypt_info { u8 ci_flags; struct crypto_skcipher *ci_ctfm; struct crypto_cipher *ci_essiv_tfm; - u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; + u8 ci_master_key[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; typedef enum { diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 7aed93bcfb82..ac41f646e7b7 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -38,7 +38,7 @@ static void derive_crypt_complete(struct crypto_async_request *req, int rc) */ static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE], const struct fscrypt_key *source_key, - u8 derived_raw_key[FS_MAX_KEY_SIZE]) + u8 derived_raw_key[FSCRYPT_MAX_KEY_SIZE]) { int res = 0; struct skcipher_request *req = NULL; @@ -91,7 +91,7 @@ static int validate_user_key(struct fscrypt_info *crypt_info, int res; description = kasprintf(GFP_NOFS, "%s%*phN", prefix, - FS_KEY_DESCRIPTOR_SIZE, + FSCRYPT_KEY_DESCRIPTOR_SIZE, ctx->master_key_descriptor); if (!description) return -ENOMEM; @@ -121,7 +121,8 @@ static int validate_user_key(struct fscrypt_info *crypt_info, master_key = (struct fscrypt_key *)ukp->data; BUILD_BUG_ON(FS_AES_128_ECB_KEY_SIZE != FS_KEY_DERIVATION_NONCE_SIZE); - if (master_key->size < min_keysize || master_key->size > FS_MAX_KEY_SIZE + if (master_key->size < min_keysize || + master_key->size > FSCRYPT_MAX_KEY_SIZE || master_key->size % AES_BLOCK_SIZE != 0) { printk_once(KERN_WARNING "%s: key size incorrect: %d\n", @@ -140,14 +141,10 @@ static const struct { const char *cipher_str; int keysize; } available_modes[] = { - [FS_ENCRYPTION_MODE_AES_256_XTS] = { "xts(aes)", - FS_AES_256_XTS_KEY_SIZE }, - [FS_ENCRYPTION_MODE_AES_256_CTS] = { "cts(cbc(aes))", - FS_AES_256_CTS_KEY_SIZE }, - [FS_ENCRYPTION_MODE_AES_128_CBC] = { "cbc(aes)", - FS_AES_128_CBC_KEY_SIZE }, - [FS_ENCRYPTION_MODE_AES_128_CTS] = { "cts(cbc(aes))", - FS_AES_128_CTS_KEY_SIZE }, + [FSCRYPT_MODE_AES_256_XTS] = { "xts(aes)", FS_AES_256_XTS_KEY_SIZE }, + [FSCRYPT_MODE_AES_256_CTS] = { "cts(cbc(aes))", FS_AES_256_CTS_KEY_SIZE }, + [FSCRYPT_MODE_AES_128_CBC] = { "cbc(aes)", FS_AES_128_CBC_KEY_SIZE }, + [FSCRYPT_MODE_AES_128_CTS] = { "cts(cbc(aes))", FS_AES_128_CTS_KEY_SIZE }, }; static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode, @@ -278,9 +275,10 @@ int fscrypt_get_encryption_info(struct inode *inode) /* Fake up a context for an unencrypted directory */ memset(&ctx, 0, sizeof(ctx)); ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; - ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS; - ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS; - memset(ctx.master_key_descriptor, 0x42, FS_KEY_DESCRIPTOR_SIZE); + ctx.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; + ctx.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; + memset(ctx.master_key_descriptor, 0x42, + FSCRYPT_KEY_DESCRIPTOR_SIZE); } else if (res != sizeof(ctx)) { return -EINVAL; } @@ -288,7 +286,7 @@ int fscrypt_get_encryption_info(struct inode *inode) if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) return -EINVAL; - if (ctx.flags & ~FS_POLICY_FLAGS_VALID) + if (ctx.flags & ~FSCRYPT_POLICY_FLAGS_VALID) return -EINVAL; crypt_info = kmem_cache_alloc(fscrypt_info_cachep, GFP_NOFS); @@ -312,12 +310,12 @@ int fscrypt_get_encryption_info(struct inode *inode) * crypto API as part of key derivation. */ res = -ENOMEM; - raw_key = kmalloc(FS_MAX_KEY_SIZE, GFP_NOFS); + raw_key = kmalloc(FSCRYPT_MAX_KEY_SIZE, GFP_NOFS); if (!raw_key) goto out; - res = validate_user_key(crypt_info, &ctx, raw_key, FS_KEY_DESC_PREFIX, - keysize); + res = validate_user_key(crypt_info, &ctx, raw_key, + FSCRYPT_KEY_DESC_PREFIX, keysize); if (res && inode->i_sb->s_cop->key_prefix) { int res2 = validate_user_key(crypt_info, &ctx, raw_key, inode->i_sb->s_cop->key_prefix, @@ -349,7 +347,7 @@ int fscrypt_get_encryption_info(struct inode *inode) goto out; if (S_ISREG(inode->i_mode) && - crypt_info->ci_data_mode == FS_ENCRYPTION_MODE_AES_128_CBC) { + crypt_info->ci_data_mode == FSCRYPT_MODE_AES_128_CBC) { res = init_essiv_generator(crypt_info, raw_key, keysize); if (res) { pr_debug("%s: error %d (inode %lu) allocating essiv tfm\n", diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 6a63b8a0d46c..19332a6fd52d 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -21,7 +21,7 @@ static bool is_encryption_context_consistent_with_policy( const struct fscrypt_policy *policy) { return memcmp(ctx->master_key_descriptor, policy->master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE) == 0 && + FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && (ctx->flags == policy->flags) && (ctx->contents_encryption_mode == policy->contents_encryption_mode) && @@ -36,13 +36,13 @@ static int create_encryption_context_from_policy(struct inode *inode, ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; memcpy(ctx.master_key_descriptor, policy->master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE); + FSCRYPT_KEY_DESCRIPTOR_SIZE); if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, policy->filenames_encryption_mode)) return -EINVAL; - if (policy->flags & ~FS_POLICY_FLAGS_VALID) + if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) return -EINVAL; ctx.contents_encryption_mode = policy->contents_encryption_mode; @@ -125,7 +125,7 @@ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) policy.filenames_encryption_mode = ctx.filenames_encryption_mode; policy.flags = ctx.flags; memcpy(policy.master_key_descriptor, ctx.master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE); + FSCRYPT_KEY_DESCRIPTOR_SIZE); if (copy_to_user(arg, &policy, sizeof(policy))) return -EFAULT; @@ -199,7 +199,7 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) if (parent_ci && child_ci) { return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key, - FS_KEY_DESCRIPTOR_SIZE) == 0 && + FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && (parent_ci->ci_data_mode == child_ci->ci_data_mode) && (parent_ci->ci_filename_mode == child_ci->ci_filename_mode) && @@ -216,7 +216,7 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) return memcmp(parent_ctx.master_key_descriptor, child_ctx.master_key_descriptor, - FS_KEY_DESCRIPTOR_SIZE) == 0 && + FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && (parent_ctx.contents_encryption_mode == child_ctx.contents_encryption_mode) && (parent_ctx.filenames_encryption_mode == @@ -254,7 +254,7 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child, ctx.filenames_encryption_mode = ci->ci_filename_mode; ctx.flags = ci->ci_flags; memcpy(ctx.master_key_descriptor, ci->ci_master_key, - FS_KEY_DESCRIPTOR_SIZE); + FSCRYPT_KEY_DESCRIPTOR_SIZE); get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE); res = parent->i_sb->s_cop->set_context(child, &ctx, diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index f7aa7d62e235..671ce57e4673 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -99,12 +99,12 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode) static inline bool fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode) { - if (contents_mode == FS_ENCRYPTION_MODE_AES_128_CBC && - filenames_mode == FS_ENCRYPTION_MODE_AES_128_CTS) + if (contents_mode == FSCRYPT_MODE_AES_128_CBC && + filenames_mode == FSCRYPT_MODE_AES_128_CTS) return true; - if (contents_mode == FS_ENCRYPTION_MODE_AES_256_XTS && - filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) + if (contents_mode == FSCRYPT_MODE_AES_256_XTS && + filenames_mode == FSCRYPT_MODE_AES_256_CTS) return true; return false; From patchwork Mon Oct 23 21:40:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829679 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="bbA8heWd"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="cbujn3QE"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVKr6Ysnz9sRg for ; Tue, 24 Oct 2017 08:44:32 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=Vk7KEz4bDN+hJlOggpmp0j8Nl8/R34vWvshFXT66nc4=; b=bbA8heWdwv7dnR7YySITJ44x1B iqxwgUU4+CVLQr7aeyMWNZ99gP+/gJx0YJzaf0pbYjYWSAEHIoquEAKOcXIQOYa91u1LmJwUHtFDy /8gD2mbysTpc9KkGR6osYlxLW2U4H2Cw18TruMHs0dcIvYRR8weHVnQEgTN6eEp91UKjIFtKCzl9H g9F51HJnUsq0lZBWH4pg4upB0ZkDMdgGxK8vsG2cPf5Rx/m89jB7pAeDrCkW337HuQK1efLhJpXCD Fl+7XcWQhenj7Xe6onxsW01A5NNZ1l/G6vqiBdpuVoqeqmxvxKG9Yhi67LjcxWdCU3FBTWvhK7Dkm In+cwmnQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kWF-0006GL-7i; Mon, 23 Oct 2017 21:44:23 +0000 Received: from mail-io0-x244.google.com ([2607:f8b0:4001:c06::244]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUS-0004fd-OH for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:37 +0000 Received: by mail-io0-x244.google.com with SMTP id 97so21700544iok.7 for ; Mon, 23 Oct 2017 14:42:15 -0700 (PDT) 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=hUAs1fwaOUa8W4Qac1pvK3n8sY4bEQX/091zabAwlIc=; b=cbujn3QE4gDLX7eiJTuGmAWtzSIo5Jhw8IzirsPNOqgHJoYrJ7m83lZZh/Fd3VgM/p jbf5vDt2g32lc58j+jMlhZltcABxp36d22z7A1Q0/a04wcpxzDiGrcKGv31tktFxDHLU gCLtYMWfwTqngHFe58O/cMAIUtJpJ8/Xh015kFMxm/lWWATVCeBqCwxNN4nqIm7aku6C r9IMCaJKJlrdxC08NTvsFFM7p7wOU6VPwhRQ9fDTFFfO/aihv8Nm5VrU05vH8HLcfmD6 HPOvf9j4+9CryHIAiNPZ0SjdiO4m+VESnamTXA/iS/1ZdL3633DOj3yfgaE6havskCdT EN/A== 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=hUAs1fwaOUa8W4Qac1pvK3n8sY4bEQX/091zabAwlIc=; b=aowhJ7PMQu6AmLkaxQBd3m+SN/1DEUaz0gtFF9KXK/vhtK/U3uQ1+pnWo/nE2NhOjV KkSJiQLyGxjtpEa/R1/0EZGWooGg9D+b71CqJTCRv+JqqyEII6d/+ovH3SpEpA076fyO Vy3ImubOaBO4Y331zvtcS9+LRVSaHp6g1nRhGBJu0H75L0qonaPInWdtteQzuh5YxQu8 w3s8r0m68Y8ylcwyXZotK/evSRZWNJT6mHeXRZI/p9lwtk5AUcgqfxvJGoNRFcXyLFh+ +NVqxeVnpeFF3PfM6dqbD6fWsTJcA91Fg6aRvmNKlRS88PmhZPP1MiGQpT0xEsA/kSqD 1Acw== X-Gm-Message-State: AMCzsaVAvCsj6XJaszj4yUemdgFB0AqJo5P7Q1P7NRK8+a71KbigdiGw 6a4CJ4oV5XnwUVFUXgsLa5c= X-Google-Smtp-Source: ABhQp+RkcT5Kk9lxFMUwEcEzYlMdg/ZwfbMj3T7qPAwz64C2N51kjhABrraM0Rxg7rKWAqcU3KY3YA== X-Received: by 10.107.35.15 with SMTP id j15mr1940112ioj.241.1508794934755; Mon, 23 Oct 2017 14:42:14 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:14 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 04/25] fscrypt: refactor finding and deriving key Date: Mon, 23 Oct 2017 14:40:37 -0700 Message-Id: <20171023214058.128121-5-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144232_991373_D92E8577 X-CRM114-Status: GOOD ( 23.69 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers In preparation for introducing a new way to find the master keys and derive the per-file keys, clean up the current method. This includes: - Introduce a helper function find_and_derive_key() so that we don't have to add more code directly to fscrypt_get_encryption_info(). - Don't pass the 'struct fscrypt_key' directly into derive_key_aes(). This is in preparation for the case where we find the master key in a filesystem-level keyring, where (for good reasons) the key payload will *not* be formatted as the UAPI 'struct fscrypt_key'. - Separate finding the key from key derivation. In particular, it *only* makes sense to fall back to the alternate key description prefix if searching for the "fscrypt:" prefix returns -ENOKEY. It doesn't make sense to do so when derive_key_aes() fails, for example. - Improve the error messages for when the fscrypt_key is invalid. - Rename 'raw_key' to 'derived_key' for clarity. Signed-off-by: Eric Biggers Reviewed-by: Michael Halcrow --- fs/crypto/keyinfo.c | 205 ++++++++++++++++++++++++++++------------------------ 1 file changed, 109 insertions(+), 96 deletions(-) diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index ac41f646e7b7..d3a97c2cd4dd 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -28,113 +28,138 @@ static void derive_crypt_complete(struct crypto_async_request *req, int rc) complete(&ecr->completion); } -/** - * derive_key_aes() - Derive a key using AES-128-ECB - * @deriving_key: Encryption key used for derivation. - * @source_key: Source key to which to apply derivation. - * @derived_raw_key: Derived raw key. +/* + * Key derivation function. This generates the derived key by encrypting the + * master key with AES-128-ECB using the nonce as the AES key. * - * Return: Zero on success; non-zero otherwise. + * The master key must be at least as long as the derived key. If the master + * key is longer, then only the first 'derived_keysize' bytes are used. */ -static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE], - const struct fscrypt_key *source_key, - u8 derived_raw_key[FSCRYPT_MAX_KEY_SIZE]) +static int derive_key_aes(const u8 *master_key, + const struct fscrypt_context *ctx, + u8 *derived_key, unsigned int derived_keysize) { - int res = 0; + int err; struct skcipher_request *req = NULL; DECLARE_FS_COMPLETION_RESULT(ecr); struct scatterlist src_sg, dst_sg; - struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0); + struct crypto_skcipher *tfm; + + tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); - if (IS_ERR(tfm)) { - res = PTR_ERR(tfm); - tfm = NULL; - goto out; - } crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY); req = skcipher_request_alloc(tfm, GFP_NOFS); if (!req) { - res = -ENOMEM; + err = -ENOMEM; goto out; } skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, derive_crypt_complete, &ecr); - res = crypto_skcipher_setkey(tfm, deriving_key, - FS_AES_128_ECB_KEY_SIZE); - if (res < 0) + + BUILD_BUG_ON(sizeof(ctx->nonce) != FS_AES_128_ECB_KEY_SIZE); + err = crypto_skcipher_setkey(tfm, ctx->nonce, sizeof(ctx->nonce)); + if (err) goto out; - sg_init_one(&src_sg, source_key->raw, source_key->size); - sg_init_one(&dst_sg, derived_raw_key, source_key->size); - skcipher_request_set_crypt(req, &src_sg, &dst_sg, source_key->size, + sg_init_one(&src_sg, master_key, derived_keysize); + sg_init_one(&dst_sg, derived_key, derived_keysize); + skcipher_request_set_crypt(req, &src_sg, &dst_sg, derived_keysize, NULL); - res = crypto_skcipher_encrypt(req); - if (res == -EINPROGRESS || res == -EBUSY) { + err = crypto_skcipher_encrypt(req); + if (err == -EINPROGRESS || err == -EBUSY) { wait_for_completion(&ecr.completion); - res = ecr.res; + err = ecr.res; } out: skcipher_request_free(req); crypto_free_skcipher(tfm); - return res; + return err; } -static int validate_user_key(struct fscrypt_info *crypt_info, - struct fscrypt_context *ctx, u8 *raw_key, - const char *prefix, int min_keysize) +/* + * Search the current task's subscribed keyrings for a "logon" key with + * description prefix:descriptor, and if found acquire a read lock on it and + * return a pointer to its validated payload in *payload_ret. + */ +static struct key * +find_and_lock_process_key(const char *prefix, + const u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE], + unsigned int min_keysize, + const struct fscrypt_key **payload_ret) { char *description; - struct key *keyring_key; - struct fscrypt_key *master_key; + struct key *key; const struct user_key_payload *ukp; - int res; + const struct fscrypt_key *payload; description = kasprintf(GFP_NOFS, "%s%*phN", prefix, - FSCRYPT_KEY_DESCRIPTOR_SIZE, - ctx->master_key_descriptor); + FSCRYPT_KEY_DESCRIPTOR_SIZE, descriptor); if (!description) - return -ENOMEM; + return ERR_PTR(-ENOMEM); - keyring_key = request_key(&key_type_logon, description, NULL); + key = request_key(&key_type_logon, description, NULL); kfree(description); - if (IS_ERR(keyring_key)) - return PTR_ERR(keyring_key); - down_read(&keyring_key->sem); - - if (keyring_key->type != &key_type_logon) { - printk_once(KERN_WARNING - "%s: key type must be logon\n", __func__); - res = -ENOKEY; - goto out; - } - ukp = user_key_payload_locked(keyring_key); - if (!ukp) { - /* key was revoked before we acquired its semaphore */ - res = -EKEYREVOKED; - goto out; + if (IS_ERR(key)) + return key; + + down_read(&key->sem); + ukp = user_key_payload_locked(key); + + if (!ukp) /* was the key revoked before we acquired its semaphore? */ + goto invalid; + + payload = (const struct fscrypt_key *)ukp->data; + + if (ukp->datalen != sizeof(struct fscrypt_key) || + payload->size < 1 || payload->size > FSCRYPT_MAX_KEY_SIZE) { + pr_warn_ratelimited("fscrypt: key with description '%s' has invalid payload\n", + key->description); + goto invalid; } - if (ukp->datalen != sizeof(struct fscrypt_key)) { - res = -EINVAL; - goto out; + + if (payload->size < min_keysize) { + pr_warn_ratelimited("fscrypt: key with description '%s' is too short " + "(got %u bytes, need %u+ bytes)\n", + key->description, + payload->size, min_keysize); + goto invalid; } - master_key = (struct fscrypt_key *)ukp->data; - BUILD_BUG_ON(FS_AES_128_ECB_KEY_SIZE != FS_KEY_DERIVATION_NONCE_SIZE); - - if (master_key->size < min_keysize || - master_key->size > FSCRYPT_MAX_KEY_SIZE - || master_key->size % AES_BLOCK_SIZE != 0) { - printk_once(KERN_WARNING - "%s: key size incorrect: %d\n", - __func__, master_key->size); - res = -ENOKEY; - goto out; + + *payload_ret = payload; + return key; + +invalid: + up_read(&key->sem); + key_put(key); + return ERR_PTR(-ENOKEY); +} + +/* Find the master key, then derive the inode's actual encryption key */ +static int find_and_derive_key(const struct inode *inode, + const struct fscrypt_context *ctx, + u8 *derived_key, unsigned int derived_keysize) +{ + struct key *key; + const struct fscrypt_key *payload; + int err; + + key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX, + ctx->master_key_descriptor, + derived_keysize, &payload); + if (key == ERR_PTR(-ENOKEY) && inode->i_sb->s_cop->key_prefix) { + key = find_and_lock_process_key(inode->i_sb->s_cop->key_prefix, + ctx->master_key_descriptor, + derived_keysize, &payload); } - res = derive_key_aes(ctx->nonce, master_key, raw_key); -out: - up_read(&keyring_key->sem); - key_put(keyring_key); - return res; + if (IS_ERR(key)) + return PTR_ERR(key); + err = derive_key_aes(payload->raw, ctx, derived_key, derived_keysize); + up_read(&key->sem); + key_put(key); + return err; } static const struct { @@ -256,8 +281,8 @@ int fscrypt_get_encryption_info(struct inode *inode) struct fscrypt_context ctx; struct crypto_skcipher *ctfm; const char *cipher_str; - int keysize; - u8 *raw_key = NULL; + unsigned int derived_keysize; + u8 *derived_key = NULL; int res; if (inode->i_crypt_info) @@ -301,7 +326,8 @@ int fscrypt_get_encryption_info(struct inode *inode) memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, sizeof(crypt_info->ci_master_key)); - res = determine_cipher_type(crypt_info, inode, &cipher_str, &keysize); + res = determine_cipher_type(crypt_info, inode, + &cipher_str, &derived_keysize); if (res) goto out; @@ -310,24 +336,14 @@ int fscrypt_get_encryption_info(struct inode *inode) * crypto API as part of key derivation. */ res = -ENOMEM; - raw_key = kmalloc(FSCRYPT_MAX_KEY_SIZE, GFP_NOFS); - if (!raw_key) + derived_key = kmalloc(FS_MAX_KEY_SIZE, GFP_NOFS); + if (!derived_key) goto out; - res = validate_user_key(crypt_info, &ctx, raw_key, - FSCRYPT_KEY_DESC_PREFIX, keysize); - if (res && inode->i_sb->s_cop->key_prefix) { - int res2 = validate_user_key(crypt_info, &ctx, raw_key, - inode->i_sb->s_cop->key_prefix, - keysize); - if (res2) { - if (res2 == -ENOKEY) - res = -ENOKEY; - goto out; - } - } else if (res) { + res = find_and_derive_key(inode, &ctx, derived_key, derived_keysize); + if (res) goto out; - } + ctfm = crypto_alloc_skcipher(cipher_str, 0, 0); if (!ctfm || IS_ERR(ctfm)) { res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; @@ -338,17 +354,14 @@ int fscrypt_get_encryption_info(struct inode *inode) crypt_info->ci_ctfm = ctfm; crypto_skcipher_clear_flags(ctfm, ~0); crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY); - /* - * if the provided key is longer than keysize, we use the first - * keysize bytes of the derived key only - */ - res = crypto_skcipher_setkey(ctfm, raw_key, keysize); + res = crypto_skcipher_setkey(ctfm, derived_key, derived_keysize); if (res) goto out; if (S_ISREG(inode->i_mode) && crypt_info->ci_data_mode == FSCRYPT_MODE_AES_128_CBC) { - res = init_essiv_generator(crypt_info, raw_key, keysize); + res = init_essiv_generator(crypt_info, derived_key, + derived_keysize); if (res) { pr_debug("%s: error %d (inode %lu) allocating essiv tfm\n", __func__, res, inode->i_ino); @@ -361,7 +374,7 @@ int fscrypt_get_encryption_info(struct inode *inode) if (res == -ENOKEY) res = 0; put_crypt_info(crypt_info); - kzfree(raw_key); + kzfree(derived_key); return res; } EXPORT_SYMBOL(fscrypt_get_encryption_info); From patchwork Mon Oct 23 21:40:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829664 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="dLODOQQR"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="cImZbeoA"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVJb3Wjcz9sPt for ; Tue, 24 Oct 2017 08:43:27 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=sEU2EOV7lsJyFgYX5MPZbiVxpEY+mgC05xGG/hhELTI=; b=dLODOQQRBCfC+l5E9/BFF5UcQi CHUQgp90GqewQjVsYAFy00HDUG1lECfClaWRxzaC2MfOF0WT0KRndP1lMpnCcZk63sQj4Bi2kqlPw wHEs0fXo8f5C+S/xM9kq1/E+2qFBbgeK/iiQSUFMMdnUsLUyw4btagqs487/XFqU0LVnMAUiltf3u 0Inj+hIDSIUO1A0qUew6TtjWb81yqlTncKyUTb8a9mIEh4GfbVA1XCo7EFEnJaRyPkS31Hej3kZlY s4rnB50O/5vDlKItMu3FcfEKgkapdLKJnmGgtxPUymLz7K9wXz720hlbofEtq4S4H4WCoYSiy4kAC URBe6Cpg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kVH-0005Py-C2; Mon, 23 Oct 2017 21:43:23 +0000 Received: from mail-io0-x244.google.com ([2607:f8b0:4001:c06::244]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUS-0004fz-OO for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:36 +0000 Received: by mail-io0-x244.google.com with SMTP id n137so21760814iod.6 for ; Mon, 23 Oct 2017 14:42:16 -0700 (PDT) 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=ZXxOc7bqPylR64/IGbno9751CRE5IjhvJXc3eyHiJr4=; b=cImZbeoAXAqKDPzwkRlrnhnpZeSCmY7sRHXfilOoPudPirEzMXQF5wM/z48MAloIbz uR/a7KLJNq10czGWuwmHEorwezS62vcqSwUowyqZBXg7/lFllzsS1xYSGMIFmVvs8awn cSpIOmiteL9Uf6FSL24ip2hIZQwcAHpuzZdBkO+p5davhu9Wu108A7YvJK5tAlX8QqgC vcLqDRODWqGSHUNKx3BzYS7ozFIt1QzmauLQA8ksuvstnxOYRAdNbGFfWs6itKQTbZOc z1FeuA42qmvx0YYKmcDep77HfuikYi2M/8UGbDgya2FZX6Jgoqn+SZKU0LAMteiWqAK6 3vtA== 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=ZXxOc7bqPylR64/IGbno9751CRE5IjhvJXc3eyHiJr4=; b=HcdN+VtsvREOnszkrRVY1IdJJn295Bn3N9L3sD7LRMjiz/ozoRXDPv9O8PzrHQqF3n 9r1qOZVhc8R+0w0LaZGOyexjU55UI/gchtagY4Ob3AUILUjIWYhgCSPyqliGc1dOCsgB kUbk1zHciR0plWnIhIeDM8kywGAU/e1KxIvoupqTFhJxBbLeZssVAwL4/5AJNr3iIlxw jsErL233bPlO67wzNAalxvuFqtlbszIJPutOfCMGrsnBJ0pnf5LU28JxI1mUax9ExWW6 V19CdXK0yIu+xVt1HpgrYV3K+9NgKqlQZ6ZnViMg5C57jTepbv8TZTaFRXq6f6J6WkAm NXqQ== X-Gm-Message-State: AMCzsaVkbbuuYnHuYOBKMwMyoQ8lpD8cWcjEPHRmT5Qm8EOq3jDN3jiR XjBKTfRUVfDVRZ/KDiCXxUg= X-Google-Smtp-Source: ABhQp+TwQzJyNtN5jhj0ZqvqV/Vw+qAuFsdMtc+iLIIC/LN26T6ql8elWydDLgrxUzs95v9InBGKag== X-Received: by 10.107.137.23 with SMTP id l23mr18083039iod.138.1508794936035; Mon, 23 Oct 2017 14:42:16 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:15 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 05/25] fs: add ->s_master_keys to struct super_block Date: Mon, 23 Oct 2017 14:40:38 -0700 Message-Id: <20171023214058.128121-6-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144232_965285_02E1E5C9 X-CRM114-Status: GOOD ( 15.88 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Add an ->s_master_keys keyring to 'struct super_block' for holding encryption keys which have been added to the filesystem. This keyring will be populated using a new fscrypt ioctl. This is needed for several reasons, including: - To solve the visibility problems of having filesystem encryption keys stored in process-subscribed keyrings, while the VFS state of the filesystem is actually global. - To implement a proper API for removing keys, which among other things will require maintaining the list of inodes that are using each master key so that we can evict the inodes when the key is removed. - To allow caching a crypto transform for each master key so that we don't have to repeatedly allocate one over and over. See later patches for full details, including why it wouldn't be enough to add the concept of a "global keyring" to the keyrings API instead. ->s_master_keys will only be allocated when someone tries to add a key for the first time. Otherwise it will stay NULL. Note that this could go in the filesystem-specific superblocks instead. However, we already have three filesystems using fs/crypto/, so it's useful to have it in the VFS. Signed-off-by: Eric Biggers Reviewed-by: Michael Halcrow --- fs/super.c | 3 +++ include/linux/fs.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/fs/super.c b/fs/super.c index 166c4ee0d0ed..161a9d05aa9f 100644 --- a/fs/super.c +++ b/fs/super.c @@ -168,6 +168,9 @@ static void destroy_super(struct super_block *s) WARN_ON(!list_empty(&s->s_mounts)); put_user_ns(s->s_user_ns); kfree(s->s_subtype); +#if IS_ENABLED(CONFIG_FS_ENCRYPTION) + key_put(s->s_master_keys); +#endif call_rcu(&s->rcu, destroy_super_rcu); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 3efd5ded21c9..8cfb0877d32c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1440,6 +1440,10 @@ struct super_block { spinlock_t s_inode_wblist_lock; struct list_head s_inodes_wb; /* writeback inodes */ + +#if IS_ENABLED(CONFIG_FS_ENCRYPTION) + struct key *s_master_keys; /* master crypto keys in use */ +#endif } __randomize_layout; /* Helper functions so that in most cases filesystems will From patchwork Mon Oct 23 21:40:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829683 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="uDmP/9fB"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="kovZ8+Cs"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVMk4kBBz9sPr for ; Tue, 24 Oct 2017 08:46:10 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=3QwHYOhPWhfNsOmtl5Gx+4O2r+1TwYxC+YXVrR99jtU=; b=uDmP/9fBU6i0sKDfqw20GYW7Se uNQlzHqqS55Y7W4qvtOjIC+BmxFERf2O1d9hT2IwXS4HkWOEaMVjKKaDzxdFwP4rqJHc0vpJuQylw +Aj2SKbqn63cmdh1zZusVy+6oyW/FRkU3NNlTdx9u+r3DIb+Kve2Paq6hj3TAe/8cMwwqzuupP4qb RD0jSW+w8BtWc56EF0ZDJLRE65fvIC26L2p9yD2jrkjTjBDVFJe5k30aXQ51dpQxTtIxcQd4uYOqc Mu95IM7CzE5mSvYC3JBy6Lquh5oryqXOFHAqViTwpnA4rW6sh3AtwqvQaMqTrazxuoubySwIxRxfj wJYogzuA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kXu-0000KK-KC; Mon, 23 Oct 2017 21:46:06 +0000 Received: from mail-io0-x243.google.com ([2607:f8b0:4001:c06::243]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUX-0004g2-Nu for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:55 +0000 Received: by mail-io0-x243.google.com with SMTP id b186so21739463iof.8 for ; Mon, 23 Oct 2017 14:42:18 -0700 (PDT) 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=TdGJTgVUCqRKWTGQ9RKIi92RQ/5OTQV3UxQAmtlkWQs=; b=kovZ8+CsHG81pmh8o8BWUeOKDjFKwPFsDuIAp70wZYq0CIEDEY5XODiVue2/8pQY2R F1YkWSRw5Au55qMtCUeFqlfQj3zL703JRFeNHbDDvBtEU19dJQ7ZwOMaulitvNgLcYdE m225cu4l+Srs/m8JwFx5p/aIHpld6vktLqTtByMyIhyNPg/pqASLSiLsOM9yNCjbJ8/B UQengZl2vgBVw5vl9l9X52DYrnXvuG3JQyyfSy81hqbFHPmI/uk6sZEQRVdR7jUOGelG 5PnS+IusnPkywB5ynIoJX+7aRN61yVlsK38ak55KQCzwDy7+s9vE4sTSv97I+M9XPEdc srsg== 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=TdGJTgVUCqRKWTGQ9RKIi92RQ/5OTQV3UxQAmtlkWQs=; b=Yi6JKgjKYbQ2h5upu/nRiMHtT8W6uxCbmgIramL4gJwLI62lDjMyn4ApuAozfwFn7K CjXCARLXfCrh4yvnP9xPWOBaWibdCAED/dhMTKpeZxh58u0JHnVgDwrJB134YVZ3j+0+ jh8JpJxLI1VCTSV+8tgiKpvOzQEk1InPyifa1w/ikZUlkyDfzeEq4Vx8NtIJw7+UOoD0 mDfgiEjmI03vFlmtjzGN8uIwExf3FP6sCPa0QC5w/jflo3vHRKpXpYS6rOkPovXIUETw x83K7iIHmU+eJfGnHoG8bwiNaRj/2tWnChAg7jeM2TLV6jvHlscSa1+QEUZE0skQy39R N3lA== X-Gm-Message-State: AMCzsaXPR9O1ZWpo/B10ZVSMZZLd6Y5zYyiIHulp8ovV7RL83yrBPFef 4HQAP81JGqVLFOG5wnVIywroa9OJ X-Google-Smtp-Source: ABhQp+SFbpeo1mlWFnDzN3faHBF5sgmn0s5XRk8DziN1cQGh7LAK1ReG+F05b5V5YsRCwn56hJWpig== X-Received: by 10.107.10.82 with SMTP id u79mr19423371ioi.252.1508794937485; Mon, 23 Oct 2017 14:42:17 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:16 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 06/25] fscrypt: add FS_IOC_ADD_ENCRYPTION_KEY ioctl Date: Mon, 23 Oct 2017 14:40:39 -0700 Message-Id: <20171023214058.128121-7-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144238_340080_F657F3D7 X-CRM114-Status: GOOD ( 34.85 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:243 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Add a new filesystem encryption ioctl, FS_IOC_ADD_ENCRYPTION_KEY. This ioctl adds a master encryption key to the filesystem encryption keyring ->s_master_keys. When a process tries to access an encrypted file that has not yet been "unlocked" (set up with an ->i_crypt_info containing a crypto transform keyed by the file's derived key), fscrypt_get_encryption_info() will search for the master key in ->s_master_keys before falling back to the process-subscribed keyrings. For now this ioctl is root-only, which is necessary in part because the keys are identified by master_key_descriptor, which is not cryptographically tied to the actual key payload. However, a later patch will introduce a new encryption policy version where the key is identified by a cryptographic hash. This will, in combination with other protections, make it possible for non-root users to use this ioctl in some situations. Why we need this ~~~~~~~~~~~~~~~~ The main problem is that the "locked/unlocked" (ciphertext/plaintext) status of encrypted files is global, but currently the master keys are not. We only look for master keys in the process-subscribed keyrings; that is, the current thread keyring, process keyring, and session keyring, where the session keyring usually contains the user keyring. This means we have to put the master keys in the keyrings for individual users or for individual sessions. This causes much confusion as soon as a process with a different UID, such as a 'sudo' command, tries to access encrypted files. In such a situation, whether each individual inode appears "locked" or "unlocked" will depend on whether it was previously accessed and happens to still be in the inode cache, which is more or less nondeterministic. It may seem that we should indeed provide each process its own "view" of the filesystem depending on whether it "has the key" or not. However that would be extremely difficult to do without a separate mount, due to the way the VFS caches work. Furthermore, it is actually missing the point of encryption because it would *not* be encryption that would provide the different "views", but rather kernel *code*. Thus, it would simply be an access control mechanism largely redundant with the many existing access control mechanisms such as UNIX file permissions and LSMs. The reality is that the confidentially of encrypted files *after the kernel already has the encryption key in memory* is only protected by the correctness of the kernel, not by the mathematical properties of encryption. And at the end of the day, almost all users of filesystem encryption we are aware of do really need the global view, because they need encrypted files to be accessible to processes running under different UIDs. This can be as simple as needing to be able to run 'sudo', or it can be something more complex like Android's key management system where applications running under different UIDs as well as system processes need access to the same encrypted files. As a result, some very ugly hacks have been added to try to emulate globally visible keys. The Android and Chromium OS key management systems simply create a "session" keyring in PID 1 and put all the keys in it, which abuses the "session" keyring to have nothing to do with a "session", but rather be a global keyring. This is fragile, as it means that the "session" keyring must never be changed. There have also been bugs involving processes that were forked before the "session" keyring was created, causing them to miss out on the keys. Meanwhile, filesystem encryption tools written for general-purpose Linux distributions have no such ability to abuse the "session" keyring. They instead must implement "interesting" workarounds such as linking all the user keyrings into root's user keyring, as is done by the fscrypt userspace tool (see the design document at https://goo.gl/55cCrI). This raises security concerns, to say the least. By having an API to add a key to the *filesystem* we'll be able to eliminate all the above hacks and better express the intended semantics: the "locked/unlocked" status of an encrypted directory is global. And orthogonally to encryption, existing mechanisms such as file permissions and LSMs can and should continue to be used for the purpose of *access control*. Why use a custom key type ~~~~~~~~~~~~~~~~~~~~~~~~~ The keys the new ioctl adds to ->s_master_keys are still "keys" in the sense of the keyrings service, but they have a custom key type rather than the "logon" key type we currently require when userspace provides a key via a process-subscribed keyring. Judging just from this patch alone, the "logon" key type would be sufficient. However, later patches will be solving problems such as the nonstandard KDF and the lack of a key removal API. The solutions for these problems will require tracking information on a per-master-key basis. Therefore, we'll need a custom structure associated with each master key anyway. A custom key type lets us do that easily. Why not use add_key() ~~~~~~~~~~~~~~~~~~~~~ Instead of adding a new ioctl() to add a key, we could have userspace use the add_key() system call. In combination with an ioctl which retrieves the key ID of ->s_master_keys, add_key() could be used to add a key to ->s_master_keys. Alternatively, we could add the concept of a "global keyring" or "namespace keyring" to the keyrings service, where that keyring would be searched in addition to the process-subscribed keyrings. Then, add_key() could add a key to that. This actually makes sense given only the present patch. However, unfortunately it falls apart once we consider the follow-on changes. First, we also need to add the ability to remove an encryption key, and it will need to have more specialized semantics than keyctl_unlink() or keyctl_revoke() can provide. For example, we must not only wipe the master key *secret* from memory, but we must also try to evict all the inodes which had been "unlocked" using the key. And it's possible that even though the master key secret was wiped, some inodes could not be evicted, since they may be busy. In that case, we still want to wipe the master key *secret* so that no more encrypted files can be "unlocked". But we also want to allow userspace to retry the request later, so that evicting the remaining inodes can be re-attempted. Alternatively, we want the same list of inodes to be picked up again if the secret happens to be added again. Trying to shoehorn these specific semantics into the keyrings API would be very difficult. Later we also want to open up the add/remove key operations to non-root users by taking advantage of a new encryption policy version which includes a cryptographic hash of the master key. This is needed because otherwise we wouldn't be able to fully replace the process-subscribed keyrings and avoid all its problems mentioned earlier. But to actually make non-root use secure, we'll need to do some extra accounting where we keep track of all users who have added a given key, then only really remove a key after all users have removed it. Non-root users also cannot simply be given write permission to a global keyring. So again, it seems that trying to shoehorn the needed semantics into the keyrings API would just create problems. Nevertheless, we do still use the keyrings service internally so that we reuse some code and get some "free" functionality such as having the keys show up in /proc/keys for debugging purposes. Signed-off-by: Eric Biggers Reviewed-by: Michael Halcrow --- fs/crypto/crypto.c | 12 +- fs/crypto/fscrypt_private.h | 3 + fs/crypto/keyinfo.c | 351 +++++++++++++++++++++++++++++++++++++++- include/linux/fscrypt_notsupp.h | 5 + include/linux/fscrypt_supp.h | 1 + include/uapi/linux/fscrypt.h | 41 +++-- 6 files changed, 397 insertions(+), 16 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 608f6bbe0f31..489c504ac20d 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -449,6 +450,8 @@ int fscrypt_initialize(unsigned int cop_flags) */ static int __init fscrypt_init(void) { + int err = -ENOMEM; + fscrypt_read_workqueue = alloc_workqueue("fscrypt_read_queue", WQ_HIGHPRI, 0); if (!fscrypt_read_workqueue) @@ -462,14 +465,20 @@ static int __init fscrypt_init(void) if (!fscrypt_info_cachep) goto fail_free_ctx; + err = register_key_type(&key_type_fscrypt_mk); + if (err) + goto fail_free_info; + return 0; +fail_free_info: + kmem_cache_destroy(fscrypt_info_cachep); fail_free_ctx: kmem_cache_destroy(fscrypt_ctx_cachep); fail_free_queue: destroy_workqueue(fscrypt_read_workqueue); fail: - return -ENOMEM; + return err; } module_init(fscrypt_init) @@ -484,6 +493,7 @@ static void __exit fscrypt_exit(void) destroy_workqueue(fscrypt_read_workqueue); kmem_cache_destroy(fscrypt_ctx_cachep); kmem_cache_destroy(fscrypt_info_cachep); + unregister_key_type(&key_type_fscrypt_mk); fscrypt_essiv_cleanup(); } diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 5cb80a2d39ea..b2fad12eeedb 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -27,6 +27,8 @@ #define FS_KEY_DERIVATION_NONCE_SIZE 16 +#define FSCRYPT_MIN_KEY_SIZE 16 + /** * Encryption context for inode * @@ -93,6 +95,7 @@ extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags); /* keyinfo.c */ +extern struct key_type key_type_fscrypt_mk; extern void __exit fscrypt_essiv_cleanup(void); #endif /* _FSCRYPT_PRIVATE_H */ diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index d3a97c2cd4dd..3f1cb8bbc1e5 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -9,14 +9,307 @@ */ #include -#include +#include #include +#include +#include #include #include #include "fscrypt_private.h" static struct crypto_shash *essiv_hash_tfm; +/* + * fscrypt_master_key_secret - secret key material of an in-use master key + */ +struct fscrypt_master_key_secret { + + /* Size of the raw key in bytes */ + u32 size; + + /* The raw key */ + u8 raw[FSCRYPT_MAX_KEY_SIZE]; +}; + +/* + * fscrypt_master_key - an in-use master key + * + * This represents a master encryption key which has been added to the + * filesystem and can be used to "unlock" the encrypted files which were + * encrypted with it. + */ +struct fscrypt_master_key { + + /* The secret key material */ + struct fscrypt_master_key_secret mk_secret; + + /* Arbitrary key descriptor which was assigned by userspace */ + struct fscrypt_key_specifier mk_spec; +}; + +static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec) +{ + switch (spec->type) { + case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: + return FSCRYPT_KEY_DESCRIPTOR_SIZE; + } + return 0; +} + +static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec) +{ + if (spec->reserved) + return false; + return master_key_spec_len(spec) != 0; +} + +static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret) +{ + memzero_explicit(secret, sizeof(*secret)); +} + +static void move_master_key_secret(struct fscrypt_master_key_secret *dst, + struct fscrypt_master_key_secret *src) +{ + memcpy(dst, src, sizeof(*dst)); + memzero_explicit(src, sizeof(*src)); +} + +static void free_master_key(struct fscrypt_master_key *mk) +{ + wipe_master_key_secret(&mk->mk_secret); + kzfree(mk); +} + +static int fscrypt_key_instantiate(struct key *key, + struct key_preparsed_payload *prep) +{ + key->payload.data[0] = (struct fscrypt_master_key *)prep->data; + return 0; +} + +static void fscrypt_key_destroy(struct key *key) +{ + free_master_key(key->payload.data[0]); +} + +static void fscrypt_key_describe(const struct key *key, struct seq_file *m) +{ + seq_puts(m, key->description); +} + +/* + * Type of key in ->s_master_keys. Each key of this type represents a master + * key which has been added to the filesystem. Its payload is a + * 'struct fscrypt_master_key'. + */ +struct key_type key_type_fscrypt_mk = { + .name = "._fscrypt", + .instantiate = fscrypt_key_instantiate, + .destroy = fscrypt_key_destroy, + .describe = fscrypt_key_describe, +}; + +/* + * Search ->s_master_keys. Note that we mark the keyring reference as + * "possessed" so that we can use the KEY_POS_SEARCH permission. + */ +static struct key *search_fscrypt_keyring(struct key *keyring, + struct key_type *type, + const char *description) +{ + key_ref_t keyref; + + keyref = keyring_search(make_key_ref(keyring, 1), type, description); + if (IS_ERR(keyref)) { + if (PTR_ERR(keyref) == -EAGAIN) + keyref = ERR_PTR(-ENOKEY); + return ERR_CAST(keyref); + } + return key_ref_to_ptr(keyref); +} + +#define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE \ + (sizeof("fscrypt-") - 1 + sizeof(((struct super_block *)0)->s_id) + 1) + +#define FSCRYPT_MK_DESCRIPTION_SIZE (2 * FSCRYPT_KEY_DESCRIPTOR_SIZE + 1) + +static void format_fs_keyring_description( + char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE], + const struct super_block *sb) +{ + sprintf(description, "fscrypt-%s", sb->s_id); +} + +static void format_mk_description( + char description[FSCRYPT_MK_DESCRIPTION_SIZE], + const struct fscrypt_key_specifier *mk_spec) +{ + sprintf(description, "%*phN", + master_key_spec_len(mk_spec), mk_spec->max_specifier); +} + +/* + * Find the specified master key in ->s_master_keys. + * Returns ERR_PTR(-ENOKEY) if not found. + */ +static struct key *find_master_key(struct super_block *sb, + const struct fscrypt_key_specifier *mk_spec) +{ + struct key *keyring; + char description[FSCRYPT_MK_DESCRIPTION_SIZE]; + + /* pairs with smp_store_release() in add_to_filesystem_keyring() */ + keyring = smp_load_acquire(&sb->s_master_keys); + if (keyring == NULL) + return ERR_PTR(-ENOKEY); + + format_mk_description(description, mk_spec); + return search_fscrypt_keyring(keyring, &key_type_fscrypt_mk, + description); +} + +static struct key * +allocate_master_key(struct fscrypt_master_key_secret *secret, + const struct fscrypt_key_specifier *mk_spec) +{ + struct fscrypt_master_key *mk; + struct key *key; + char description[FSCRYPT_MK_DESCRIPTION_SIZE]; + int err; + + mk = kzalloc(sizeof(*mk), GFP_NOFS); + if (!mk) + return ERR_PTR(-ENOMEM); + + mk->mk_spec = *mk_spec; + + move_master_key_secret(&mk->mk_secret, secret); + + format_mk_description(description, mk_spec); + key = key_alloc(&key_type_fscrypt_mk, description, + GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), + KEY_POS_SEARCH | KEY_USR_SEARCH | + KEY_USR_READ | KEY_USR_VIEW, 0, NULL); + if (IS_ERR(key)) + goto out_free_mk; + + err = key_instantiate_and_link(key, mk, sizeof(*mk), NULL, NULL); + if (err) { + key_put(key); + key = ERR_PTR(err); + goto out_free_mk; + } + return key; + +out_free_mk: + free_master_key(mk); + return key; +} + +/* + * Add the given key to ->s_master_keys, creating ->s_master_keys if it doesn't + * already exist. Synchronized by fscrypt_add_key_mutex. + */ +static int add_to_filesystem_keyring(struct super_block *sb, struct key *key) +{ + struct key *keyring = sb->s_master_keys; + + if (keyring == NULL) { + char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE]; + + format_fs_keyring_description(description, sb); + keyring = keyring_alloc(description, GLOBAL_ROOT_UID, + GLOBAL_ROOT_GID, current_cred(), + KEY_POS_SEARCH | KEY_USR_SEARCH | + KEY_USR_READ | KEY_USR_VIEW, + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); + if (IS_ERR(keyring)) + return PTR_ERR(keyring); + + /* Pairs with smp_load_acquire() in find_master_key() */ + smp_store_release(&sb->s_master_keys, keyring); + } + + return key_link(keyring, key); +} + +static int add_master_key(struct super_block *sb, + struct fscrypt_master_key_secret *secret, + const struct fscrypt_key_specifier *mk_spec) +{ + struct key *key; + int err; + static DEFINE_MUTEX(fscrypt_add_key_mutex); + + mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */ + key = find_master_key(sb, mk_spec); + if (IS_ERR(key)) { + if (key != ERR_PTR(-ENOKEY)) { + err = PTR_ERR(key); + goto out_unlock; + } + /* Didn't find the key in ->s_master_keys; add it. */ + + key = allocate_master_key(secret, mk_spec); + if (IS_ERR(key)) { + err = PTR_ERR(key); + goto out_unlock; + } + err = add_to_filesystem_keyring(sb, key); + if (err) + goto out_put_key; + } + err = 0; +out_put_key: + key_put(key); +out_unlock: + mutex_unlock(&fscrypt_add_key_mutex); + return err; +} + +/* + * Add a master encryption key to the filesystem, causing all files which were + * encrypted with it to appear "unlocked" (decrypted) when accessed. + */ +int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) +{ + struct super_block *sb = file_inode(filp)->i_sb; + struct fscrypt_add_key_args __user *uarg = _uarg; + struct fscrypt_add_key_args arg; + struct fscrypt_master_key_secret secret; + int err; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE || + arg.raw_size > FSCRYPT_MAX_KEY_SIZE) + return -EINVAL; + + if (arg.reserved1 || + memchr_inv(arg.reserved2, 0, sizeof(arg.reserved2))) + return -EINVAL; + + if (!valid_key_spec(&arg.key_spec)) + return -EINVAL; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + memset(&secret, 0, sizeof(secret)); + secret.size = arg.raw_size; + err = -EFAULT; + if (copy_from_user(secret.raw, uarg->raw, secret.size)) + goto out_wipe_secret; + + err = add_master_key(sb, &secret, &arg.key_spec); +out_wipe_secret: + wipe_master_key_secret(&secret); + return err; +} +EXPORT_SYMBOL_GPL(fscrypt_ioctl_add_key); + static void derive_crypt_complete(struct crypto_async_request *req, int rc) { struct fscrypt_completion_result *ecr = req->data; @@ -137,10 +430,10 @@ find_and_lock_process_key(const char *prefix, return ERR_PTR(-ENOKEY); } -/* Find the master key, then derive the inode's actual encryption key */ -static int find_and_derive_key(const struct inode *inode, - const struct fscrypt_context *ctx, - u8 *derived_key, unsigned int derived_keysize) +static int find_and_derive_key_legacy(const struct inode *inode, + const struct fscrypt_context *ctx, + u8 *derived_key, + unsigned int derived_keysize) { struct key *key; const struct fscrypt_key *payload; @@ -162,6 +455,54 @@ static int find_and_derive_key(const struct inode *inode, return err; } +/* Find the master key, then derive the inode's actual encryption key */ +static int find_and_derive_key(const struct inode *inode, + const struct fscrypt_context *ctx, + u8 *derived_key, unsigned int derived_keysize) +{ + struct key *key; + struct fscrypt_master_key *mk; + struct fscrypt_key_specifier mk_spec; + int err; + + mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; + memcpy(mk_spec.descriptor, ctx->master_key_descriptor, + FSCRYPT_KEY_DESCRIPTOR_SIZE); + + key = find_master_key(inode->i_sb, &mk_spec); + if (IS_ERR(key)) { + if (key != ERR_PTR(-ENOKEY)) + return PTR_ERR(key); + /* + * As a legacy fallback, we search the current task's subscribed + * keyrings in addition to ->s_master_keys. + */ + return find_and_derive_key_legacy(inode, ctx, derived_key, + derived_keysize); + } + mk = key->payload.data[0]; + + /* + * Require that the master key be at least as long as the derived key. + * Otherwise, the derived key cannot possibly contain as much entropy as + * that required by the encryption mode it will be used for. + */ + if (mk->mk_secret.size < derived_keysize) { + pr_warn_ratelimited("fscrypt: key with description '%s' is too short " + "(got %u bytes, need %u+ bytes)\n", + key->description, + mk->mk_secret.size, derived_keysize); + err = -ENOKEY; + goto out_put_key; + } + + err = derive_key_aes(mk->mk_secret.raw, ctx, + derived_key, derived_keysize); +out_put_key: + key_put(key); + return err; +} + static const struct { const char *cipher_str; int keysize; diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index c4c6bf2c390e..7ca8a44fc984 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -84,6 +84,11 @@ static inline int fscrypt_inherit_context(struct inode *parent, } /* keyinfo.c */ +static inline int fscrypt_ioctl_add_key(struct file *filp, void __user *arg) +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_get_encryption_info(struct inode *inode) { return -EOPNOTSUPP; diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index 2db5e9706f60..313943214d57 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -42,6 +42,7 @@ extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); /* keyinfo.c */ +extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg); extern int fscrypt_get_encryption_info(struct inode *); extern void fscrypt_put_encryption_info(struct inode *, struct fscrypt_info *); diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 26c381a40279..aebe5d84d091 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -34,22 +34,43 @@ struct fscrypt_policy { __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; -#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy) -#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16]) -#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy) - -/* Parameters for passing an encryption key into the kernel keyring */ +/* + * Process-subscribed "logon" key description prefix and payload format. + * Deprecated; prefer FS_IOC_ADD_ENCRYPTION_KEY instead. + */ #define FSCRYPT_KEY_DESC_PREFIX "fscrypt:" -#define FSCRYPT_KEY_DESC_PREFIX_SIZE 8 - -/* Structure that userspace passes to the kernel keyring */ -#define FSCRYPT_MAX_KEY_SIZE 64 - +#define FSCRYPT_KEY_DESC_PREFIX_SIZE 8 +#define FSCRYPT_MAX_KEY_SIZE 64 struct fscrypt_key { __u32 mode; __u8 raw[FSCRYPT_MAX_KEY_SIZE]; __u32 size; }; + +struct fscrypt_key_specifier { + __u32 type; +#define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR 1 + __u32 reserved; + union { + __u8 max_specifier[32]; + __u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + }; +}; + +/* Struct passed to FS_IOC_ADD_ENCRYPTION_KEY */ +struct fscrypt_add_key_args { + __u32 raw_size; + __u32 reserved1; + __u64 reserved2[2]; + struct fscrypt_key_specifier key_spec; + __u8 raw[]; +}; + +#define FS_IOC_SET_ENCRYPTION_POLICY _IOR( 'f', 19, struct fscrypt_policy) +#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW( 'f', 20, __u8[16]) +#define FS_IOC_GET_ENCRYPTION_POLICY _IOW( 'f', 21, struct fscrypt_policy) +#define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 22, struct fscrypt_add_key_args) + /**********************************************************************/ /* old names; don't add anything new here! */ From patchwork Mon Oct 23 21:40:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829680 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="PEMBU7me"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="pf4Lf4vx"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVL94qSFz9sPr for ; Tue, 24 Oct 2017 08:44:49 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=Uqy66I0rz2/WEKS1pgadNA5oaAL//3ElKMVqYtFULpY=; b=PEMBU7me3eytgiZtukwdu7LiDT mGTLHAMMuzTG2Nmes9saQTSjjRAt5bI6FBMQtDI+4ZhM64LYKKlimbjiYFXZjDCwhnU39wosqa0XR oRQUpnFYOyMKsAxMCOTZ7lo4dtd7ea/xB3ziu/V3p+ALZZebPeJcuQoXF8wHYMEWv/Z7iWs0a6LHu ZJiBeUF1PPJz16aRoWFBapG+dkYd7FBYPqCyCHVI/jTodncu4RWc9eGukc5m85PRp43/baimv3SPQ s1nrI8yuKn14G5pkhP4cUOQlgSMqNT3ygEFMd7uOGeZjZjH0SJW1GVljExX0OwwJJnaD9cZkK3GzF MiGu9uig==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kWY-0006Vh-NJ; Mon, 23 Oct 2017 21:44:42 +0000 Received: from mail-io0-x242.google.com ([2607:f8b0:4001:c06::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUW-0004gB-GX for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:38 +0000 Received: by mail-io0-x242.google.com with SMTP id p186so21680928ioe.12 for ; Mon, 23 Oct 2017 14:42:19 -0700 (PDT) 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=/i3mqgW8YjPejX5sRMdtUKZ5bdvjOqMKhpBbmcCFtsA=; b=pf4Lf4vxCMPSkzQdepfakYfLfqtb5OEmzeI/9osFT+YqtBhj8birEHfVCSfLQCvoWt tUA8gn8lU3bBt096uSaBuGMuJpDup/RFZsx74g+c+0Y/L/aCd2CsFLY+4XFAV8RUC1P9 dxX65J7cO9VBg7dlkdUd6SsIBo1krt1IRQXM1Zz0n4TDkuSxE6uxUwb0dOcj5HrXRkzX llxi1F66r49bF081Kw8+OJK4ri22ZVboTJeXkqbiNX5r/qAnhxRmamVYgF3Ooj8k1BTb sKyh9Nm9c9RVeT2yufgmun6KHb4+OId4xFWF8hfB8+Nf0ll05DeKO00gzNdaPimPhzve ePDw== 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=/i3mqgW8YjPejX5sRMdtUKZ5bdvjOqMKhpBbmcCFtsA=; b=P7X2swXCHZEdLaSErg3c34l9W0zTfLT30h8A3Y6OTc4c3o9RqZLIiyNzwgpehCDKix xaIf8CdmB53WEKqFTCj3+ObaQaEgumH2mUGcxuvLO/unXfMN3XbSVo9EjmNJZDvoDS+9 caT7XkrflAU6/xRb0LNNts1netNWpZI6ZpDc0eHvoYrE5cdbURYOJY1GHF8fQy5L/OzP PN0ZPp2vhn5O/UavNst9FbbEOxX4xJueE7SFM6QEnI2uYDyXbfPrLO9Ri+KDqTHUBCJy ZaxuDlM+QsI2nqRhpBjfUgmNUyFgOTLW3T/021yBAauu6JFMs/XUpKpiqkBAQcnsV/SU xJsA== X-Gm-Message-State: AMCzsaXH4sAcy1D3SKwLjTZ64ybF9CiPAnN6vtA1m7kZOVz50fWpcPJn tgfWLRSncsZhyrOnz0FOpHk= X-Google-Smtp-Source: ABhQp+Qfuw9qHCHWk4gvlHTKuusnzfmAaDBxjbAAU+w4cSF7Nd4Z3rDDOLovjN76TP4IDsu5gsZd/w== X-Received: by 10.107.138.222 with SMTP id c91mr10432868ioj.246.1508794938985; Mon, 23 Oct 2017 14:42:18 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:18 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 07/25] fs/inode.c: export inode_lru_list_del() Date: Mon, 23 Oct 2017 14:40:40 -0700 Message-Id: <20171023214058.128121-8-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144236_764467_465A11B3 X-CRM114-Status: UNSURE ( 9.65 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers When a filesystem encryption key is removed, we need all files which had been "unlocked" (had ->i_crypt_info set up) with it to appear "locked" again. This is most easily done by evicting the inodes. This can currently be done using 'echo 2 > /proc/sys/vm/drop_caches'; however, that is overkill and not usable by non-root users. In preparation for allowing fs/crypto/ to evict just the needed inodes, export inode_lru_list_del() to modules. Signed-off-by: Eric Biggers Reviewed-by: Michael Halcrow --- fs/inode.c | 5 ++--- include/linux/fs.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index d1e35b53bb23..30ce98956801 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -420,13 +420,12 @@ void inode_add_lru(struct inode *inode) inode_lru_list_add(inode); } - -static void inode_lru_list_del(struct inode *inode) +void inode_lru_list_del(struct inode *inode) { - if (list_lru_del(&inode->i_sb->s_inode_lru, &inode->i_lru)) this_cpu_dec(nr_unused); } +EXPORT_SYMBOL_GPL(inode_lru_list_del); /** * inode_sb_list_add - add inode to the superblock list of inodes diff --git a/include/linux/fs.h b/include/linux/fs.h index 8cfb0877d32c..2833ace2f01d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2879,6 +2879,7 @@ static inline void lockdep_annotate_inode_mutex_key(struct inode *inode) { }; extern void unlock_new_inode(struct inode *); extern unsigned int get_next_ino(void); extern void evict_inodes(struct super_block *sb); +extern void inode_lru_list_del(struct inode *inode); extern void __iget(struct inode * inode); extern void iget_failed(struct inode *); From patchwork Mon Oct 23 21:40:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829681 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="TYfXT6WJ"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="uInkygRH"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVLZ42CQz9sPr for ; Tue, 24 Oct 2017 08:45:10 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=ucQeVyNiuuRvK9dWJrhoyX6mp0xyJ8xlJS2Gx8nw2mA=; b=TYfXT6WJ3HMd7pIaemZz+2ZNsT UhhE2oF3DziBusYRqiFN+UBZPmqz8LYluqWWYzEbUiaoAIa3rBV7AJdQU40+w8R0UIN5wDXyjN3P7 iccw/S+USDAxArWVrP1LJv03UOKCLt7XIDpbOu1a9veZKxcGqcQ8EFCi0wHXOpPyojP+xVMpZunN2 ZkQKbBQrnHpnaBBo/w6Do7qgTJJ0Zb6nl/O+l1DUNhJv5gVFmxzcULS6ljd71FY65Sw4H2QVCEpd7 D57CN15F2HHirQ/hYXdmV6Itjqu5zz24ctvz2h0Epc8HYYMZIOnRfuVGl53zo4dsskOxVuwKEGa3V 1Lo/+IJQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kWq-0006js-8W; Mon, 23 Oct 2017 21:45:00 +0000 Received: from mail-it0-x242.google.com ([2607:f8b0:4001:c0b::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUb-0004gH-9N for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:48 +0000 Received: by mail-it0-x242.google.com with SMTP id k70so6822012itk.0 for ; Mon, 23 Oct 2017 14:42:20 -0700 (PDT) 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=wiAoc0JHIPz4HAo1BFCpnFyXTNkBIyNbTooXOraiqBE=; b=uInkygRHFd34bCPKGXqHDVXFaWKgpkAJENWTj8+6DxI/CVmkZ2vUM9R9cxo8lz97t7 2YMFfSN+elcoCimm90w4Lxlon1wjrCRLfYcYZpZLzaNcJgxaIR+iUUVAjN32o81OtQaV Z/zCIs5dwVcl973xb8pbystw/6rm74XgEmLnk24EfGRgYJwAcud6sqTI/7/DjrROCyCA k1OYThU0y5hyJkQlelNsg6fBGw/qNIuHEIuuLIB94gDtDvW2ZVs2sp+TdqEQqqIKMWOS DhZMyFr1ni05VcDwKjPGEPD0kQd11FAkoxuiMtyMl6nmA4ztcNb9q+XPIjhcvyTtvPxm R+fA== 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=wiAoc0JHIPz4HAo1BFCpnFyXTNkBIyNbTooXOraiqBE=; b=esZxIuqaQDSatFofAoU4clUB85yHy8ZpVeq4fiuLo4jvmjQC9fZrZ9KSQQwWJ+XfQz DdcQ9H8BXGiewTs+UvLQ85Q3zbIVitUeMO8I51FQUOV1za/olf8GTjS5k6oMABnQs7jL WZL4+mdtBcQ+fyd3Tk6zuJ5ghM8xYFJLMCcfBpBYhl87iYk0Pwxwuw4fg3t/0NkIBxwG w7LPXWsUUKw2bzAPhZdpDTjbxS+5hTHVXDey7p//bSWjcC5EzrLh7JMaUDPPvZfbCwj8 5FS1Zlh3ToIZqD9N9cqW3JEL0Kzhr+K3bPMKvNpdd2kO4399SuRIJN6lOAAqBFYVJJuF Hb+w== X-Gm-Message-State: AMCzsaWYHrCCWzHXGt4nmygXu2ltQrzyOFgv9Jg2T4d7lbc7tOsrZd1k nc4uLsKk75PdS0lJp4C8UGY= X-Google-Smtp-Source: ABhQp+QklVKqmOxvS5EPAR1bGWPJimKjCOvUruutksE3uobbNpP7koBEHKEQEWTx+iR3pEu0xgHf+A== X-Received: by 10.36.77.131 with SMTP id l125mr10541183itb.7.1508794940291; Mon, 23 Oct 2017 14:42:20 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:19 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 08/25] fs/inode.c: rename and export dispose_list() Date: Mon, 23 Oct 2017 14:40:41 -0700 Message-Id: <20171023214058.128121-9-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144242_071188_6D0209A7 X-CRM114-Status: GOOD ( 13.60 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c0b:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers When a filesystem encryption key is removed, we need all files which had been "unlocked" (had ->i_crypt_info set up) with it to appear "locked" again. This is most easily done by evicting the inodes. This can currently be done using 'echo 2 > /proc/sys/vm/drop_caches'; however, that is overkill and not usable by non-root users. In preparation for allowing fs/crypto/ to evict just the needed inodes, export dispose_list() to modules. For clarity also rename it to evict_inode_list(). Signed-off-by: Eric Biggers --- fs/inode.c | 19 ++++++++++--------- include/linux/fs.h | 1 + 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 30ce98956801..fe47930835c0 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -570,13 +570,13 @@ static void evict(struct inode *inode) } /* - * dispose_list - dispose of the contents of a local list - * @head: the head of the list to free + * evict_inode_list - evict each inode in a local list of inodes + * @head: the head of the list * - * Dispose-list gets a local list with local inodes in it, so it doesn't + * This gets a local list with local inodes in it, so it doesn't * need to worry about list corruption and SMP locks. */ -static void dispose_list(struct list_head *head) +void evict_inode_list(struct list_head *head) { while (!list_empty(head)) { struct inode *inode; @@ -588,6 +588,7 @@ static void dispose_list(struct list_head *head) cond_resched(); } } +EXPORT_SYMBOL_GPL(evict_inode_list); /** * evict_inodes - evict all evictable inodes for a superblock @@ -628,13 +629,13 @@ void evict_inodes(struct super_block *sb) if (need_resched()) { spin_unlock(&sb->s_inode_list_lock); cond_resched(); - dispose_list(&dispose); + evict_inode_list(&dispose); goto again; } } spin_unlock(&sb->s_inode_list_lock); - dispose_list(&dispose); + evict_inode_list(&dispose); } EXPORT_SYMBOL_GPL(evict_inodes); @@ -679,7 +680,7 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty) } spin_unlock(&sb->s_inode_list_lock); - dispose_list(&dispose); + evict_inode_list(&dispose); return busy; } @@ -763,7 +764,7 @@ static enum lru_status inode_lru_isolate(struct list_head *item, * Walk the superblock inode LRU for freeable inodes and attempt to free them. * This is called from the superblock shrinker function with a number of inodes * to trim from the LRU. Inodes to be freed are moved to a temporary list and - * then are freed outside inode_lock by dispose_list(). + * then are freed outside inode_lock by evict_inode_list(). */ long prune_icache_sb(struct super_block *sb, struct shrink_control *sc) { @@ -772,7 +773,7 @@ long prune_icache_sb(struct super_block *sb, struct shrink_control *sc) freed = list_lru_shrink_walk(&sb->s_inode_lru, sc, inode_lru_isolate, &freeable); - dispose_list(&freeable); + evict_inode_list(&freeable); return freed; } diff --git a/include/linux/fs.h b/include/linux/fs.h index 2833ace2f01d..e0a8dae5f9dc 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2880,6 +2880,7 @@ extern void unlock_new_inode(struct inode *); extern unsigned int get_next_ino(void); extern void evict_inodes(struct super_block *sb); extern void inode_lru_list_del(struct inode *inode); +extern void evict_inode_list(struct list_head *head); extern void __iget(struct inode * inode); extern void iget_failed(struct inode *); From patchwork Mon Oct 23 21:40:42 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829684 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="AaxyX0/e"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="rZT3CF0V"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVNN03bPz9sPr for ; Tue, 24 Oct 2017 08:46:44 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=FmJTN0pBoXU8u+t7dMU89k2MWfjfXC4PVC48BPKapTs=; b=AaxyX0/eFKd+ObBVsq5NdXGtKw yHUXIKu+lNQ5UHlbzWXaaCM9nfoLd9iEuWJnNnksJM/U7OvcGA2CyrXx4OwTUPxma2Fm+83YjGkqQ hbDWM2igLZR+dS2ih438voFJLTQG0UXUNAkD92Ct5JxH2l+LY4qwGRAxAEmKU2MBeV/gWnSEUz4JD /57yFBTJjEh6ZVNT/R1AxkxiFBjbq+cwpYOvh7Ms2UKUAmTNfQbIY5uTNjFtvtPCTicpPhTJoemKW ttEc6/oSMR9Y7iiyt1JpUmcREXMe3BMGLoXBJ+7Oma9q6o0LOEJfRBt9+4A5TO9vv7VLWQyugHL2y dmE0PLbQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kYD-0000ap-L6; Mon, 23 Oct 2017 21:46:25 +0000 Received: from mail-it0-x232.google.com ([2607:f8b0:4001:c0b::232]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUc-0004gK-GC for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:56 +0000 Received: by mail-it0-x232.google.com with SMTP id c3so7671471itc.3 for ; Mon, 23 Oct 2017 14:42:22 -0700 (PDT) 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=MwU8NLXH/25/d6bIsCheKX9gJkr397GYZ6MiKkLdbzw=; b=rZT3CF0VFfVKR0XZA5ggZMYq2xtwDj92msG2b5uHreLbWb6eLQOp4ubM4OBMtDyiGP UxX80cJWNu9l08zAvlQoOOGe42eTrDYaueZ1BLMFerF2L1T8Hn3itdW3kV+tgAF/J1Iy bCpd41E0HhVzKbOankK42Np3dgy5aH6HjjdqZFi+MQEAvTMjeORcuE9nLKmwHDP3Satm zAJ/WrYkaQ0e6k2Z7+DtFez3LtG8q7Yd8i/kpsnlPg02S1MewJQTg5HrB7XWdHAUd2Pp HKHqAEBpLOs2vCW8d3dOVTbONvmKDKYWkroY5i2viH2rdhDYzFJz6lv7iDqzyYeTb1yA Epsw== 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=MwU8NLXH/25/d6bIsCheKX9gJkr397GYZ6MiKkLdbzw=; b=I4gUrFvVIhehOF5L34NM/L+UWkZMpHHkm+HkM1QvXtyygc2Swt7IxisHe5AncAMxFc AxvW+s4RFzKlfgG/W9tgpx+D7sfhV8bmkj9FlrMlicp+hNZlREB1jHJh85j6Je16TbEY MnZfprD3pQiUmuJHFCJbOYaaVGFbQjlJGNP0MB6xZ1XwzGc0u8ELvQJHY/N6Me5lI3vN Rd3S0WJjZCxy6LMqvodgehoLjLmWK2DusPveUgIr60SH90FheHJFN4TgiAnYgZJwBe4n 5wu8movXBneLx4bU2X7uBieQ0mJjPx7a8qV4Au2iZCBEZ6zOVnhFU++u2Y7+prPne2Jw dCUw== X-Gm-Message-State: AMCzsaUe1yQyNzaHxd3uCEKNXlFtw0XwkCgbkrglmiAF+i0fS0UUo7wV olUVKtEuJz84N3eAiA1him0= X-Google-Smtp-Source: ABhQp+RJH5bdwhb+eDMUqLDVaXUw+70J7zLZGdOQU2/7Fgf/3gFqtLdScknrr1jnLT4jh9laeuBtew== X-Received: by 10.36.244.69 with SMTP id u5mr11939455iti.67.1508794941530; Mon, 23 Oct 2017 14:42:21 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:21 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 09/25] fs/dcache.c: add shrink_dcache_inode() Date: Mon, 23 Oct 2017 14:40:42 -0700 Message-Id: <20171023214058.128121-10-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144243_146963_E2813A88 X-CRM114-Status: GOOD ( 11.95 ) X-Spam-Score: -2.5 (--) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-2.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [2607:f8b0:4001:c0b:0:0:0:232 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers When a filesystem encryption key is removed, we need all files which had been "unlocked" (had ->i_crypt_info set up) with it to appear "locked" again. This is most easily done by evicting the inodes. This can currently be done using 'echo 2 > /proc/sys/vm/drop_caches'; however, that is overkill and not usable by non-root users. To evict just the needed inodes we also need the ability to evict those inodes' dentries, since an inode is pinned by its dentries. Therefore, add a function shrink_dcache_inode() which iterates through an inode's dentries and evicts any unused ones as well as any unused descendants (since there may be negative dentries pinning the inode's dentries). Signed-off-by: Eric Biggers --- fs/dcache.c | 33 +++++++++++++++++++++++++++++++++ include/linux/dcache.h | 1 + 2 files changed, 34 insertions(+) diff --git a/fs/dcache.c b/fs/dcache.c index f90141387f01..455540e889f8 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1456,6 +1456,39 @@ void shrink_dcache_parent(struct dentry *parent) } EXPORT_SYMBOL(shrink_dcache_parent); +/** + * shrink_dcache_inode - prune dcache for inode + * @inode: inode to prune + * + * Evict all unused aliases of the specified inode from the dcache. This is + * intended to be used when trying to evict a specific inode, since inodes are + * pinned by their dentries. We also have to descend to ->d_subdirs for each + * alias, since aliases may be pinned by negative child dentries. + */ +void shrink_dcache_inode(struct inode *inode) +{ + for (;;) { + struct select_data data; + struct dentry *dentry; + + INIT_LIST_HEAD(&data.dispose); + data.start = NULL; + data.found = 0; + + spin_lock(&inode->i_lock); + hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) + d_walk(dentry, &data, select_collect, NULL); + spin_unlock(&inode->i_lock); + + if (!data.found) + break; + + shrink_dentry_list(&data.dispose); + cond_resched(); + } +} +EXPORT_SYMBOL(shrink_dcache_inode); + static enum d_walk_ret umount_check(void *_data, struct dentry *dentry) { /* it has busy descendents; complain about those instead */ diff --git a/include/linux/dcache.h b/include/linux/dcache.h index ed1a7cf6923a..fb08199d67d5 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -245,6 +245,7 @@ extern struct dentry * d_obtain_alias(struct inode *); extern struct dentry * d_obtain_root(struct inode *); extern void shrink_dcache_sb(struct super_block *); extern void shrink_dcache_parent(struct dentry *); +extern void shrink_dcache_inode(struct inode *); extern void shrink_dcache_for_umount(struct super_block *); extern void d_invalidate(struct dentry *); From patchwork Mon Oct 23 21:40:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829690 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="DB7pvKHv"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="PuXDLx90"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVQW0Gmyz9sPr for ; Tue, 24 Oct 2017 08:48:34 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=ngruLBFoamPJUwC3pQW9lW8HhsONzmLl2MoSWYSgP/c=; b=DB7pvKHvph78c24CJpwGLeDzAG LKyp1FM53mDW1khD0q3j929kp7lv12RW4Vdh28Bim3U3doiEggYGx/AxVBdYU6+RbBHQfV5mMkfsx nTv/41dmwMS7o5nWPvOfqvR6DJaXDAFUww1UF9GJBn2X5MMmxzlBKpzvE+Yjas0PKxAJXF5M6Uj4C NVJaU6T842tVANjQaTGHjlww7J6KLHLzcBtbQIAUCCf0hTT/C9NsLM9XH1nD7OFDTspdQUXuQYp9K Wx6ihSKa+XpIA2MQXzDfqFotJb5PnbvMS7H477bz2+BtmBh+F5kKUi0lCZSgiYA8qgxgQEjoLGpwz cYHqx+mg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kaC-0002Wp-5h; Mon, 23 Oct 2017 21:48:28 +0000 Received: from mail-it0-x244.google.com ([2607:f8b0:4001:c0b::244]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUe-0004gR-7D for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:14 +0000 Received: by mail-it0-x244.google.com with SMTP id r127so7684632itb.5 for ; Mon, 23 Oct 2017 14:42:23 -0700 (PDT) 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=rVh1lG19FDPK0jBQFfvJ5uWV+auXzHbLRl7foWj3oRQ=; b=PuXDLx90jyyEm8vgBfx/yXIYxfkq4BwIDBgv6jbvtLG9VRU2C3lktgWqZa5IreR3bY ath7kTN0+JNokzqUU091ExTD0+3/vguAEJep73yboB8idwoFporwgcCH19GgmGPAoQFg 9Df7N1TOXzquzBgzc/LmkV3jWjNMjkpIzTvASAwBw3om6XGHFQY6AZ8NiAMtNNQgKbO5 beQQ3lP78B/fTnJ9THNs90RjuTg3J2bqeQeWgm7+7U7gLfw1vP2a6bpkYBoAXG+ZV8ZH Ij3hnSTBCZ4U8FWiiEv2L7lbIeX9YR7p/Voav0e8xBtiRcYfPMiU4GY6hzEzEto3YqFj 9Jzw== 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=rVh1lG19FDPK0jBQFfvJ5uWV+auXzHbLRl7foWj3oRQ=; b=A8JNWNH4Y8+LAVBvBWst13xya5OnlIowklzDzIQMCukDRx6NJijxpB/c9ULx+5/+ib wKltrcqo1aL4m449Sof1GenfqGdaRHJs9YuWwcTfC79pRyrNZDbm5+eDQargivhYv30m 3JNjcYwLtmm1nZnyMhdl1hDDJtaTgd09hSEnah3qpoxpOZ1wf58+BYOLQEGi+kGC+exN 2u2G3WR7ub7JViaF//myH36F+Rg6csditVj296ER85u4bd53UddwDEgsQSYa3N4Ww4gT DH80Yeox//ilX5DNtheUkk2kAix7Q4diEhL2EHe89jgjnxtNfWpS+pshs6E/1G67934u +xyA== X-Gm-Message-State: AMCzsaUjZPDbv2S5ONb1YD63lg4wEWbihvHNCO4JB2Snr1pwj6cLTSDY kPfj7GdeMglDg8ihzIQ+6v4= X-Google-Smtp-Source: ABhQp+T82uRWMcwicRLxG2Bd6yZ6qjtW2RoZIKbe9en3lFk4fhWAB+ePqoPWvgstuBrY0tNu1QhITw== X-Received: by 10.36.238.73 with SMTP id b70mr9937458iti.127.1508794942923; Mon, 23 Oct 2017 14:42:22 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:22 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 10/25] fscrypt: add FS_IOC_REMOVE_ENCRYPTION_KEY ioctl Date: Mon, 23 Oct 2017 14:40:43 -0700 Message-Id: <20171023214058.128121-11-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144245_031609_2DA9E606 X-CRM114-Status: GOOD ( 34.07 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c0b:0:0:0:244 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Problem ~~~~~~~ Many filesystem encryption users want the ability to remove encryption keys, causing the corresponding encrypted directories to appear "locked" (presented in ciphertext form) again. Moreover, users want removing an encryption key to *really* remove it, in the sense that the removed keys cannot be recovered even if kernel memory is compromised, e.g. by the exploit of a kernel security vulnerability or by a physical attack. This is desirable after a user logs out of the system, for example. In many cases users even already assume this to be the case and are surprised to hear when it's not. It is *not* sufficient to simply unlink the master key from the keyring (or to revoke or invalidate it), since files are encrypted with per-file keys instead of with the master keys directly. Therefore, to really remove a key we must also remove the per-file keys, e.g. by evicting the corresponding inodes from the inode cache. This also would have the benefit of making encrypted files appear "locked" again. Currently the workaround is to run: sync echo 2 > /proc/sys/vm/drop_caches This is a very bad solution because it evicts all not-in-use inodes in the system rather than just the inodes associated with the key being removed. Moreover, it requires root privileges, so non-root users cannot lock their encrypted directories. Finally, the drop_caches sysctl was originally meant for debugging purposes only. Nevertheless, the largest users of filesystem encryption (Android and Chromium OS) actually want this capability badly enough that they are actually using the drop_caches workaround. Similarly, the drop_caches workaround is also used in the PAM module provided by the fscrypt userspace tool (https://github.com/google/fscrypt). Needless to say, this is causing significant performance problems due to inodes for unencrypted system files being evicted. So a real solution is needed. Solution ~~~~~~~~ To properly solve this problem, we need an API which removes and wipes the given master key, *and* removes and and wipes the corresponding per-file keys. This requires tracking which inodes have been "unlocked" using each master key. Originally that was not possible because the kernel didn't actually have a centralized notion of what a master key even was. But now that we have the filesystem-level keyring ->s_master_keys it is finally possible. Add this API as a new ioctl, FS_IOC_REMOVE_ENCRYPTION_KEY. It is the counterpart of FS_IOC_ADD_ENCRYPTION_KEY. FS_IOC_REMOVE_ENCRYPTION_KEY first wipes the master key's secret from memory. Then, it syncs the filesystem and tries to evict the list of inodes that had been "unlocked" with the key. Evicting the inodes has several effects, including: - The actual keys used to encrypt the data (in ->i_crypt_info->ci_ctfm) are wiped from memory. Thus, they can no longer be recovered, even if kernel memory is later compromised. - The encrypted files and directories once again appear "locked", i.e. in ciphertext or in "encrypted" form. This is highly desirable from a user interface perspective. It can also be desirable from a security perspective (although sometimes for the wrong reasons!). - The pagecache pages are freed, which allows the plaintext file contents to be overwritten in memory later as the system continues running. Currently we do not actually wipe the pages on free, nor does the kernel more generally wipe memory on free either. Thus, for now we tolerate that an attacker who later gains access to kernel memory may be able to see portions of file contents and file names in plaintext in unallocated memory. Security-conscious users who do not mind a performance hit may ameliorate this by enabling page poisoning. Of course, some inodes may still be in use when a master key is removed, and we cannot simply revoke random file descriptors, mmap's, etc. The approach we take is to skip in-use inodes, and notify userspace by returning -EBUSY if any inodes could not be evicted. Still, even in this case the master key secret is removed, so no more files can be unlocked with it. Moreover, most of the inodes should still be evicted as well. Userspace can then retry the ioctl later to evict the remaining inodes. Alternatively, if userspace adds the key again, then the refreshed secret will be associated with the existing list of inodes so that they are correctly tracked for future key removals. For now, FS_IOC_REMOVE_ENCRYPTION_KEY has to be restricted to privileged users only, just like FS_IOC_ADD_ENCRYPTION_KEY. This is sufficient for use cases where all encryption keys are managed by a privileged process, e.g. as is the case on Android and Chromium OS. But in the more general case, non-root users need to be able to both unlock *and* lock their own encrypted directories. As it turns out, we will indeed be able to support this through these ioctls, but non-root use will need to be tied to the use of a new encryption policy version which identifies the master key using a cryptographic hash. (See later patches.) Signed-off-by: Eric Biggers --- fs/crypto/fscrypt_private.h | 18 ++- fs/crypto/keyinfo.c | 347 ++++++++++++++++++++++++++++++++++++++-- fs/crypto/policy.c | 5 +- include/linux/fscrypt_notsupp.h | 6 + include/linux/fscrypt_supp.h | 1 + include/uapi/linux/fscrypt.h | 7 + 6 files changed, 367 insertions(+), 17 deletions(-) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index b2fad12eeedb..2fdc4e5c0771 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -61,7 +61,23 @@ struct fscrypt_info { u8 ci_flags; struct crypto_skcipher *ci_ctfm; struct crypto_cipher *ci_essiv_tfm; - u8 ci_master_key[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + u8 ci_master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + + /* + * The master key with which this inode was unlocked (decrypted). This + * will be NULL if the master key was found in a process-subscribed + * keyring rather than in the filesystem-level keyring. + */ + struct key *ci_master_key; + + /* Link in list of inodes that were unlocked with the master key */ + struct list_head ci_master_key_link; + + /* + * Back-pointer to the inode, needed during key removal. Only set when + * ->ci_master_key is set. + */ + struct inode *ci_inode; }; typedef enum { diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 3f1cb8bbc1e5..dc2697cf9114 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -40,11 +40,35 @@ struct fscrypt_master_key_secret { */ struct fscrypt_master_key { - /* The secret key material */ + /* + * The secret key material. After FS_IOC_REMOVE_ENCRYPTION_KEY is + * executed, this is wiped and no new inodes can be unlocked with this + * key; however, there may still be inodes in ->mk_decrypted_inodes + * which could not be evicted. As long as some inodes still remain, + * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or + * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again. + * + * Locking: protected by key->sem. + */ struct fscrypt_master_key_secret mk_secret; /* Arbitrary key descriptor which was assigned by userspace */ struct fscrypt_key_specifier mk_spec; + + /* + * Length of ->mk_decrypted_inodes, plus one if mk_secret is present. + * Once this goes to 0, the master key is removed from ->s_master_keys. + * This struct will continue to live as long as the 'struct key' whose + * payload it is, but we won't let this reference count rise again. + */ + refcount_t mk_refcount; + + /* + * List of inodes that were unlocked using this key. This allows the + * inodes to be evicted efficiently if the key is removed. + */ + struct list_head mk_decrypted_inodes; + spinlock_t mk_decrypted_inodes_lock; }; static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec) @@ -63,6 +87,12 @@ static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec) return master_key_spec_len(spec) != 0; } +static bool +is_master_key_secret_present(const struct fscrypt_master_key_secret *secret) +{ + return secret->size != 0; +} + static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret) { memzero_explicit(secret, sizeof(*secret)); @@ -96,6 +126,13 @@ static void fscrypt_key_destroy(struct key *key) static void fscrypt_key_describe(const struct key *key, struct seq_file *m) { seq_puts(m, key->description); + + if (key_is_positive(key)) { + struct fscrypt_master_key *mk = key->payload.data[0]; + + if (!is_master_key_secret_present(&mk->mk_secret)) + seq_puts(m, ": secret removed"); + } } /* @@ -122,7 +159,8 @@ static struct key *search_fscrypt_keyring(struct key *keyring, keyref = keyring_search(make_key_ref(keyring, 1), type, description); if (IS_ERR(keyref)) { - if (PTR_ERR(keyref) == -EAGAIN) + if (PTR_ERR(keyref) == -EAGAIN || + PTR_ERR(keyref) == -EKEYREVOKED) keyref = ERR_PTR(-ENOKEY); return ERR_CAST(keyref); } @@ -186,6 +224,10 @@ allocate_master_key(struct fscrypt_master_key_secret *secret, move_master_key_secret(&mk->mk_secret, secret); + refcount_set(&mk->mk_refcount, 1); /* secret is present */ + INIT_LIST_HEAD(&mk->mk_decrypted_inodes); + spin_lock_init(&mk->mk_decrypted_inodes_lock); + format_mk_description(description, mk_spec); key = key_alloc(&key_type_fscrypt_mk, description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), @@ -243,6 +285,7 @@ static int add_master_key(struct super_block *sb, static DEFINE_MUTEX(fscrypt_add_key_mutex); mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */ +retry: key = find_master_key(sb, mk_spec); if (IS_ERR(key)) { if (key != ERR_PTR(-ENOKEY)) { @@ -259,6 +302,33 @@ static int add_master_key(struct super_block *sb, err = add_to_filesystem_keyring(sb, key); if (err) goto out_put_key; + } else { + struct fscrypt_master_key *mk = key->payload.data[0]; + bool rekey; + + /* Found the key in ->s_master_keys */ + + down_write(&key->sem); + + /* + * Take a reference if we'll be re-adding ->mk_secret. If we + * couldn't take a reference, then the key is being removed from + * ->s_master_keys and can no longer be used. So invalidate the + * key (someone else is doing that too, but they might be + * slower) and retry searching ->s_master_keys. + */ + rekey = !is_master_key_secret_present(&mk->mk_secret); + if (rekey && !refcount_inc_not_zero(&mk->mk_refcount)) { + up_write(&key->sem); + key_invalidate(key); + key_put(key); + goto retry; + } + + /* Re-add the secret key material if needed */ + if (rekey) + move_master_key_secret(&mk->mk_secret, secret); + up_write(&key->sem); } err = 0; out_put_key: @@ -270,7 +340,8 @@ static int add_master_key(struct super_block *sb, /* * Add a master encryption key to the filesystem, causing all files which were - * encrypted with it to appear "unlocked" (decrypted) when accessed. + * encrypted with it to appear "unlocked" (decrypted) when accessed. The key + * can be removed later by FS_IOC_REMOVE_ENCRYPTION_KEY. */ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) { @@ -310,6 +381,191 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) } EXPORT_SYMBOL_GPL(fscrypt_ioctl_add_key); +static void evict_dentries_for_decrypted_inodes(struct fscrypt_master_key *mk) +{ + struct fscrypt_info *ci; + struct inode *inode; + struct inode *toput_inode = NULL; + + spin_lock(&mk->mk_decrypted_inodes_lock); + + list_for_each_entry(ci, &mk->mk_decrypted_inodes, ci_master_key_link) { + inode = ci->ci_inode; + spin_lock(&inode->i_lock); + if (inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW)) { + spin_unlock(&inode->i_lock); + continue; + } + __iget(inode); + spin_unlock(&inode->i_lock); + spin_unlock(&mk->mk_decrypted_inodes_lock); + + shrink_dcache_inode(inode); + iput(toput_inode); + toput_inode = inode; + + spin_lock(&mk->mk_decrypted_inodes_lock); + } + + spin_unlock(&mk->mk_decrypted_inodes_lock); + iput(toput_inode); +} + +static int evict_decrypted_inodes(struct fscrypt_master_key *mk) +{ + struct fscrypt_info *ci; + struct inode *inode; + LIST_HEAD(dispose); + unsigned long num_busy = 0; + unsigned long busy_ino; + + spin_lock(&mk->mk_decrypted_inodes_lock); + + list_for_each_entry(ci, &mk->mk_decrypted_inodes, ci_master_key_link) { + inode = ci->ci_inode; + spin_lock(&inode->i_lock); + + if (inode->i_state & (I_FREEING | I_WILL_FREE)) + goto next; + + if (atomic_read(&inode->i_count) || + (inode->i_state & ~I_REFERENCED)) { + num_busy++; + busy_ino = inode->i_ino; + goto next; + } + + inode->i_state |= I_FREEING; + inode_lru_list_del(inode); + list_add(&inode->i_lru, &dispose); +next: + spin_unlock(&inode->i_lock); + } + + spin_unlock(&mk->mk_decrypted_inodes_lock); + + evict_inode_list(&dispose); + + if (unlikely(num_busy)) { + pr_warn_ratelimited("fscrypt: %lu inodes still busy after removing key with description %*phN (%sino: %lu)\n", + num_busy, master_key_spec_len(&mk->mk_spec), + mk->mk_spec.max_specifier, + (num_busy > 1 ? "example " : ""), busy_ino); + return -EBUSY; + } + + return 0; +} + +static int try_to_lock_encrypted_files(struct super_block *sb, + struct fscrypt_master_key *mk) +{ + int err1; + int err2; + + /* + * An inode can't be evicted while it still has dirty pages, or while + * the inode itself is still dirty. Thus, we first have to clean all + * the inodes in ->mk_decrypted_inodes. + * + * Just do it the easy way: call sync_filesystem(). It's overkill, but + * it works, and it's more important to minimize the amount of caches we + * drop than the amount of data we sync. Also, unprivileged users can + * already call sync_filesystem() via sys_syncfs() or sys_sync(). + */ + down_read(&sb->s_umount); + err1 = sync_filesystem(sb); + up_read(&sb->s_umount); + + /* + * Inodes are pinned by their dentries, so we have to evict the dentries + * first. We could potentially just call shrink_dcache_sb() here, but + * that would be overkill, and an unprivileged user shouldn't be able to + * evict all dentries for the entire filesystem. Instead, go through + * the inodes' alias lists and try to evict each dentry. + */ + evict_dentries_for_decrypted_inodes(mk); + + /* + * Finally, iterate through ->mk_decrypted_inodes and evict as many + * inodes as we can. Similarly, we could potentially just call + * invalidate_inodes() here, but that would be overkill, and an + * unprivileged user shouldn't be able to evict all inodes for the + * entire filesystem. + * + * Note that ideally, we wouldn't really evict the inodes, but rather + * just free their ->i_crypt_info and pagecache. But eviction is *much* + * easier to correctly implement without causing use-after-free bugs. + */ + err2 = evict_decrypted_inodes(mk); + + return err1 ?: err2; +} + +/* + * Try to remove an fscrypt master encryption key. + * + * First we wipe the actual master key secret from memory, so that no more + * inodes can be unlocked with it. Then, we try to evict all cached inodes that + * had been unlocked using the key. Since this can fail for in-use inodes, this + * is expected to be used in cooperation with userspace ensuring that none of + * the files are still open. + * + * If, nevertheless, some inodes could not be evicted, we return -EBUSY + * (although we still evicted as many inodes as possible) and keep the 'struct + * key' and the 'struct fscrypt_master_key' around to keep track of the list of + * remaining inodes. Userspace can then retry the ioctl later to retry evicting + * the remaining inodes, or alternatively can add the secret key again. + * + * Note that even though we wipe the encryption *keys* from memory, decrypted + * data can likely still be found in memory, e.g. in pagecache pages that have + * been freed. Wiping such data is currently out of scope, short of users who + * may choose to enable page and slab poisoning systemwide. + */ +int fscrypt_ioctl_remove_key(struct file *filp, const void __user *uarg) +{ + struct super_block *sb = file_inode(filp)->i_sb; + struct fscrypt_remove_key_args arg; + struct key *key; + struct fscrypt_master_key *mk; + int err; + bool dead; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + if (memchr_inv(arg.reserved, 0, sizeof(arg.reserved))) + return -EINVAL; + + if (!valid_key_spec(&arg.key_spec)) + return -EINVAL; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + key = find_master_key(sb, &arg.key_spec); + if (IS_ERR(key)) + return PTR_ERR(key); + mk = key->payload.data[0]; + + down_write(&key->sem); + dead = false; + if (is_master_key_secret_present(&mk->mk_secret)) { + wipe_master_key_secret(&mk->mk_secret); + dead = refcount_dec_and_test(&mk->mk_refcount); + } + up_write(&key->sem); + if (dead) { + key_invalidate(key); + err = 0; + } else { + err = try_to_lock_encrypted_files(sb, mk); + } + key_put(key); + return err; +} +EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key); + static void derive_crypt_complete(struct crypto_async_request *req, int rc) { struct fscrypt_completion_result *ecr = req->data; @@ -455,10 +711,20 @@ static int find_and_derive_key_legacy(const struct inode *inode, return err; } -/* Find the master key, then derive the inode's actual encryption key */ +/* + * Find the master key, then derive the inode's actual encryption key. + * + * If the master key is found in the filesystem-level keyring, then the + * corresponding 'struct key' is returned read-locked in *master_key_ret. This + * is needed because we need to hold the semaphore until we link the new + * fscrypt_info into ->mk_decrypted_inodes, but in the case where multiple tasks + * are racing to set up an inode's ->i_crypt_info, only the winner should link + * its fscrypt_info into ->mk_decrypted_inodes. + */ static int find_and_derive_key(const struct inode *inode, const struct fscrypt_context *ctx, - u8 *derived_key, unsigned int derived_keysize) + u8 *derived_key, unsigned int derived_keysize, + struct key **master_key_ret) { struct key *key; struct fscrypt_master_key *mk; @@ -481,6 +747,13 @@ static int find_and_derive_key(const struct inode *inode, derived_keysize); } mk = key->payload.data[0]; + down_read(&key->sem); + + /* Has the secret been removed using FS_IOC_REMOVE_ENCRYPTION_KEY? */ + if (!is_master_key_secret_present(&mk->mk_secret)) { + err = -ENOKEY; + goto out_release_key; + } /* * Require that the master key be at least as long as the derived key. @@ -493,12 +766,19 @@ static int find_and_derive_key(const struct inode *inode, key->description, mk->mk_secret.size, derived_keysize); err = -ENOKEY; - goto out_put_key; + goto out_release_key; } err = derive_key_aes(mk->mk_secret.raw, ctx, derived_key, derived_keysize); -out_put_key: + if (err) + goto out_release_key; + + *master_key_ret = key; + return 0; + +out_release_key: + up_read(&key->sem); key_put(key); return err; } @@ -542,11 +822,32 @@ static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode, static void put_crypt_info(struct fscrypt_info *ci) { + struct key *key; + if (!ci) return; crypto_free_skcipher(ci->ci_ctfm); crypto_free_cipher(ci->ci_essiv_tfm); + key = ci->ci_master_key; + if (key) { + struct fscrypt_master_key *mk = key->payload.data[0]; + + /* + * Remove this inode from the list of inodes that were unlocked + * with the master key. + * + * In addition, if we're removing the last inode from a key that + * already had its secret removed, invalidate the key so that it + * gets removed from ->s_master_keys. + */ + spin_lock(&mk->mk_decrypted_inodes_lock); + list_del(&ci->ci_master_key_link); + spin_unlock(&mk->mk_decrypted_inodes_lock); + if (refcount_dec_and_test(&mk->mk_refcount)) + key_invalidate(key); + key_put(key); + } kmem_cache_free(fscrypt_info_cachep, ci); } @@ -624,6 +925,7 @@ int fscrypt_get_encryption_info(struct inode *inode) const char *cipher_str; unsigned int derived_keysize; u8 *derived_key = NULL; + struct key *master_key = NULL; int res; if (inode->i_crypt_info) @@ -655,17 +957,15 @@ int fscrypt_get_encryption_info(struct inode *inode) if (ctx.flags & ~FSCRYPT_POLICY_FLAGS_VALID) return -EINVAL; - crypt_info = kmem_cache_alloc(fscrypt_info_cachep, GFP_NOFS); + crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_NOFS); if (!crypt_info) return -ENOMEM; crypt_info->ci_flags = ctx.flags; crypt_info->ci_data_mode = ctx.contents_encryption_mode; crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; - crypt_info->ci_ctfm = NULL; - crypt_info->ci_essiv_tfm = NULL; - memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, - sizeof(crypt_info->ci_master_key)); + memcpy(crypt_info->ci_master_key_descriptor, ctx.master_key_descriptor, + FSCRYPT_KEY_DESCRIPTOR_SIZE); res = determine_cipher_type(crypt_info, inode, &cipher_str, &derived_keysize); @@ -681,7 +981,8 @@ int fscrypt_get_encryption_info(struct inode *inode) if (!derived_key) goto out; - res = find_and_derive_key(inode, &ctx, derived_key, derived_keysize); + res = find_and_derive_key(inode, &ctx, derived_key, derived_keysize, + &master_key); if (res) goto out; @@ -709,9 +1010,27 @@ int fscrypt_get_encryption_info(struct inode *inode) goto out; } } - if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL) + + if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL) { + if (master_key) { + struct fscrypt_master_key *mk = + master_key->payload.data[0]; + + crypt_info->ci_inode = inode; + refcount_inc(&mk->mk_refcount); + crypt_info->ci_master_key = key_get(master_key); + spin_lock(&mk->mk_decrypted_inodes_lock); + list_add(&crypt_info->ci_master_key_link, + &mk->mk_decrypted_inodes); + spin_unlock(&mk->mk_decrypted_inodes_lock); + } crypt_info = NULL; + } out: + if (master_key) { + up_read(&master_key->sem); + key_put(master_key); + } if (res == -ENOKEY) res = 0; put_crypt_info(crypt_info); diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 19332a6fd52d..a856c8941be6 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -198,7 +198,8 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) child_ci = child->i_crypt_info; if (parent_ci && child_ci) { - return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key, + return memcmp(parent_ci->ci_master_key_descriptor, + child_ci->ci_master_key_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && (parent_ci->ci_data_mode == child_ci->ci_data_mode) && (parent_ci->ci_filename_mode == @@ -253,7 +254,7 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child, ctx.contents_encryption_mode = ci->ci_data_mode; ctx.filenames_encryption_mode = ci->ci_filename_mode; ctx.flags = ci->ci_flags; - memcpy(ctx.master_key_descriptor, ci->ci_master_key, + memcpy(ctx.master_key_descriptor, ci->ci_master_key_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE); get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE); diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index 7ca8a44fc984..92616bfdc294 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -89,6 +89,12 @@ static inline int fscrypt_ioctl_add_key(struct file *filp, void __user *arg) return -EOPNOTSUPP; } +static inline int fscrypt_ioctl_remove_key(struct file *filp, + const void __user *arg) +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_get_encryption_info(struct inode *inode) { return -EOPNOTSUPP; diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index 313943214d57..620ca4f1bafe 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -43,6 +43,7 @@ extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); /* keyinfo.c */ extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg); +extern int fscrypt_ioctl_remove_key(struct file *filp, const void __user *arg); extern int fscrypt_get_encryption_info(struct inode *); extern void fscrypt_put_encryption_info(struct inode *, struct fscrypt_info *); diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index aebe5d84d091..5d02f138668c 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -66,10 +66,17 @@ struct fscrypt_add_key_args { __u8 raw[]; }; +/* Struct passed to FS_IOC_REMOVE_ENCRYPTION_KEY */ +struct fscrypt_remove_key_args { + __u64 reserved[3]; + struct fscrypt_key_specifier key_spec; +}; + #define FS_IOC_SET_ENCRYPTION_POLICY _IOR( 'f', 19, struct fscrypt_policy) #define FS_IOC_GET_ENCRYPTION_PWSALT _IOW( 'f', 20, __u8[16]) #define FS_IOC_GET_ENCRYPTION_POLICY _IOW( 'f', 21, struct fscrypt_policy) #define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 22, struct fscrypt_add_key_args) +#define FS_IOC_REMOVE_ENCRYPTION_KEY _IOR( 'f', 23, struct fscrypt_remove_key_args) /**********************************************************************/ From patchwork Mon Oct 23 21:40:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829685 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="acvi6Ywh"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="pLvt1dOG"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVNQ1mTDz9sPr for ; Tue, 24 Oct 2017 08:46:46 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=Mp1sWuea+HurDQraOj0gbgSqhjCtJvp11KK4d2hljy0=; b=acvi6YwhykV/o7i7x8edlQtogP GUDmf6CPbC/PXNjBBWGZ8UjOucIXNGgm7me1dWUOy3gSctX3NMKY1J6+blk6iJ28yyPmmMFXVBEwn Ty54lxCO0HFkPmBleifwvmsDCWVB8ioqs8oRkPJmUqDga92W35vL/I9XCcPlZ4YQDQm7TiAP7zapg HetZnDpMQ40Uht4MUrv4yb+64nXlW1mDFFlPqh4cWFlb3c9QAQR4IFSlkXM6LmGxf1JxI5TaEojW3 O/wbfDvr2ob5r8m20GkPK3IYFIIrruGPDHhLEQ/VSG3UhV3bDflb7z9a0Wf67d/0Bbwf5cSkUCi9x /8lra0DQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kYV-0000rV-76; Mon, 23 Oct 2017 21:46:43 +0000 Received: from mail-it0-x242.google.com ([2607:f8b0:4001:c0b::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUb-0004gT-9O for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:58 +0000 Received: by mail-it0-x242.google.com with SMTP id n195so6818236itg.1 for ; Mon, 23 Oct 2017 14:42:24 -0700 (PDT) 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=4fk93GRnVqCBDf1H2gOV6iWZyAWe9dS54rgSGmwqAXM=; b=pLvt1dOGDpggKyTDMdVd70KKoDZFtldFssI//VPvuHYNWj3HVjWH3Loqvvgqo2E2dL kH/jlYD58xtuzhB0ACU2q4SDXPjP5tRKNCoENhWSaqH2ZTtdarHl7MHSTWn0IXmtZHFi Tn+/dilPkhNL8e7A+A6+DTBMYr4HRNu/rHqXvqDk2dajZiQEE5p0H9gsWtOpnJ1MTrBh cY9vPkT8Gjkcanuxeuq50w1Km8eF7Ymho9DMFh9EYq2Nhz/GSonCUFIxnyLcsCAph7+f eTsqXgBr4B9z3XN9TnPaZYYoHNA1GjcnVNDpab2qse1TBS1e/ZNmMfIvR8i/6HgYmRHL 8P7g== 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=4fk93GRnVqCBDf1H2gOV6iWZyAWe9dS54rgSGmwqAXM=; b=tPKT8TQoCDQfNju6NRCKbQt7CrO+b6WvjI4nqrMmBYi3p7togkVKZDCyJMk7wdA8Vw YoobBI/87sPvwa8aIxU8Zao47smNOGs3umeUa+e8o1z8pbb8SmJufoijaBtHZ2zIX6vQ qSG8hL2hMnu+H/r+rIDeuUbXsLYhBN/w8YgQ7o5SNW1QBdDD5aZOKaJz+mkC2S6efCpF kRh38xUpKpf1YyarARUbPxEdEXXdvLkt6y9O8RQyGo38Y40s3J0Bz18VOfjjA59bgouW cFpME7RpCSYUDqg+nG6Vmilvz/ANEaSJ/i9Zcuz0lmxLRG0xSt0nHSCYwuOipY3u7+Lg JjNw== X-Gm-Message-State: AMCzsaX12Y0Ak80ogs97uNJ8mnh9lOSd3Oz2JBlGYkQIzLGAErqd+5v+ K6V5YZuqywQUNJL+/6pjBGQ= X-Google-Smtp-Source: ABhQp+TNQdKeR5heSfEVv/atoiJJ15KMNOPZCI1va3YqPUNGI4lnWa2LHZPjRMIsgM2PpxZrLm6kbw== X-Received: by 10.36.54.210 with SMTP id l201mr11073461itl.0.1508794944157; Mon, 23 Oct 2017 14:42:24 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:23 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 11/25] fscrypt: add FS_IOC_GET_ENCRYPTION_KEY_STATUS ioctl Date: Mon, 23 Oct 2017 14:40:44 -0700 Message-Id: <20171023214058.128121-12-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144242_352003_B91BC0D9 X-CRM114-Status: GOOD ( 20.84 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c0b:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Add a new ioctl, FS_IOC_GET_ENCRYPTION_KEY_STATUS. Given a key specified by 'struct fscrypt_key_specifier' (the same way a key is specified for the ioctls which add and remove keys), it returns status information in a 'struct fscrypt_get_key_status_args'. The main motivation for this is that applications need to be able to check whether an encrypted directory is "unlocked" or not, so that they can add the key if it is not, and avoid adding the key (which may involve prompting the user for a passphrase) if it already is. It's possible to use some workarounds such as checking whether opening a regular file fails with ENOKEY, or checking whether the filenames "look like gibberish" or not. However, no workaround is usable in all cases. It's also not a simple matter of locked/unlocked anymore because we also have a partially locked state, where FS_IOC_REMOVE_ENCRYPTION_KEY has removed the secret but some encrypted files are still in use. This difference can be important for applications. Moreover, after later patches some applications will also need a way to determine whether a key was added by the current user vs. by some other user. Ideally we'd have been able to use keyctl_search() to check whether a key is present or not, rather than introducing a new ioctl. However, even if the keyrings permission system was fixed to allow granting read-only access to a keyring (currently the "Search" permission allows keyctl_invalidate()), it still wouldn't work out because the fscrypt master keys can be in states other than just present/absent, as described above. Moreover, we'd still have to at least add an ioctl which retrieves the ID of ->s_master_keys. /proc/keys cannot really be the API either, since reading /proc/keys involves iterating through all keys on the system and is primarily meant as a debugging interface. We also don't necessarily want to grant everyone VIEW access to all the fscrypt keys as that would imply everyone being able to list them as well. Therefore, a new ioctl to get an fscrypt key's status seems like the best solution. It is also consistent with the ioctls to add and remove keys. Signed-off-by: Eric Biggers --- fs/crypto/keyinfo.c | 64 +++++++++++++++++++++++++++++++++++++++++ include/linux/fscrypt_notsupp.h | 6 ++++ include/linux/fscrypt_supp.h | 1 + include/uapi/linux/fscrypt.h | 17 +++++++++++ 4 files changed, 88 insertions(+) diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index dc2697cf9114..4052030a4c96 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -566,6 +566,70 @@ int fscrypt_ioctl_remove_key(struct file *filp, const void __user *uarg) } EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key); +/* + * Retrieve the status of an fscrypt master encryption key. + * + * We set ->status to indicate whether the key is absent, present, or + * incompletely removed. "Incompletely removed" means that the master key + * secret has been removed, but some files which had been unlocked with it are + * still in use. This field allows applications to easily determine the state + * of an encrypted directory without using a hack such as trying to open a + * regular file in it (which can confuse the "incompletely removed" state with + * absent or present). + * + * Note: this ioctl only works with keys added to the filesystem-level keyring. + * It does *not* work with keys added via the old mechanism which involved + * process-subscribed keyrings. + */ +int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) +{ + struct super_block *sb = file_inode(filp)->i_sb; + struct fscrypt_get_key_status_args arg; + struct key *key; + struct fscrypt_master_key *mk; + int err; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; + + if (memchr_inv(arg.reserved1, 0, sizeof(arg.reserved1))) + return -EINVAL; + + if (!valid_key_spec(&arg.key_spec)) + return -EINVAL; + + arg.reserved2 = 0; + memset(arg.reserved3, 0, sizeof(arg.reserved3)); + + key = find_master_key(sb, &arg.key_spec); + if (IS_ERR(key)) { + if (key != ERR_PTR(-ENOKEY)) + return PTR_ERR(key); + arg.status = FSCRYPT_KEY_STATUS_ABSENT; + err = 0; + goto out; + } + mk = key->payload.data[0]; + down_read(&key->sem); + + if (!is_master_key_secret_present(&mk->mk_secret)) { + arg.status = FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED; + err = 0; + goto out_release_key; + } + + arg.status = FSCRYPT_KEY_STATUS_PRESENT; + err = 0; +out_release_key: + up_read(&key->sem); + key_put(key); +out: + if (!err && copy_to_user(uarg, &arg, sizeof(arg))) + err = -EFAULT; + return err; +} +EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_key_status); + static void derive_crypt_complete(struct crypto_async_request *req, int rc) { struct fscrypt_completion_result *ecr = req->data; diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index 92616bfdc294..bd60f951b06a 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -95,6 +95,12 @@ static inline int fscrypt_ioctl_remove_key(struct file *filp, return -EOPNOTSUPP; } +static inline int fscrypt_ioctl_get_key_status(struct file *filp, + void __user *arg) +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_get_encryption_info(struct inode *inode) { return -EOPNOTSUPP; diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index 620ca4f1bafe..ace278056dbe 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -44,6 +44,7 @@ extern int fscrypt_inherit_context(struct inode *, struct inode *, /* keyinfo.c */ extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg); extern int fscrypt_ioctl_remove_key(struct file *filp, const void __user *arg); +extern int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg); extern int fscrypt_get_encryption_info(struct inode *); extern void fscrypt_put_encryption_info(struct inode *, struct fscrypt_info *); diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 5d02f138668c..9da153df238a 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -72,11 +72,28 @@ struct fscrypt_remove_key_args { struct fscrypt_key_specifier key_spec; }; +/* Struct passed to FS_IOC_GET_ENCRYPTION_KEY_STATUS */ +struct fscrypt_get_key_status_args { + /* input */ + __u64 reserved1[3]; + struct fscrypt_key_specifier key_spec; + + /* output */ + __u32 status; +#define FSCRYPT_KEY_STATUS_ABSENT 1 +#define FSCRYPT_KEY_STATUS_PRESENT 2 +#define FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED 3 + __u32 reserved2; + + __u64 reserved3[7]; +}; + #define FS_IOC_SET_ENCRYPTION_POLICY _IOR( 'f', 19, struct fscrypt_policy) #define FS_IOC_GET_ENCRYPTION_PWSALT _IOW( 'f', 20, __u8[16]) #define FS_IOC_GET_ENCRYPTION_POLICY _IOW( 'f', 21, struct fscrypt_policy) #define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 22, struct fscrypt_add_key_args) #define FS_IOC_REMOVE_ENCRYPTION_KEY _IOR( 'f', 23, struct fscrypt_remove_key_args) +#define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f',24, struct fscrypt_get_key_status_args) /**********************************************************************/ From patchwork Mon Oct 23 21:40:45 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829698 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="W9OjOAn6"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="MczdoO+H"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVf72JSsz9s0Z for ; Tue, 24 Oct 2017 08:58:39 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=ZmTHYAu3NtIL2ZOgJ/lgA8m5P/m9tOASDrqhHULqM8E=; b=W9OjOAn66ezgACUU9flNS4ULQr GVGwMAEZPtmqUwDcSpYssm4uHDuuK6avPSMNEex7YcKE+Vd2+9NV+PRs+BQ/NvVwSf6DryPnfPvPE XkFJDOgZsb4G0ifUchxBKccLWHz8mMoSuoQkEn9Utt9TlPXByNYb/6KetMIiJNUKzh4mEqP5bDadQ +GqWl8E67Eay92X8AemC0cqTkeK2CL/689uxABt/091V6fsksdYaDQ5bZYQQIsho7rRDMvjhWb6MP hE1d9DQWcl0CTg0SwtypfMJg01dlLch6jgH5fWt8BjidvWlHI7P8h2bznTRHpGN4ZtnxMlBFxW9W5 pphIwS7w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kjx-0006qn-47; Mon, 23 Oct 2017 21:58:33 +0000 Received: from mail-it0-x242.google.com ([2607:f8b0:4001:c0b::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUb-0004gW-9Q for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:49 +0000 Received: by mail-it0-x242.google.com with SMTP id o135so7706444itb.0 for ; Mon, 23 Oct 2017 14:42:25 -0700 (PDT) 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=R6C2AaIneOIoXK0xAiQxuXlGvMlgmSYIIzFiV5vgznY=; b=MczdoO+HetE3uCJyjN+DCLsHsvFeX1TzOL3WXkBil7ZkL1m43GHCycyWaUomKXl91t PQ8akUqFyGA7RPRzJd/3+dWC6y8CVNi8qj9UuxNCveB4sN3mxgkKVyHkReUSeAa06+Il w1e0Rkax/1jQxpBHSUYrVgoRuCoowqRk8u7gxDok7+GMwe9YL/sK6dQgY0QI3hy7IqTj OjCLSj3lxblvqbeWasnV4i6Ifh0yKU5/Dk4QRz+qv/N+BzaSTTT5Z3VXwtR4h6+7dsSI TGZTkR0dQ1Z/Dgci9OMZh4cwLhvEiybaYzT3q9fNLuz+s5zK4blALf+9WqJ1sAfgHRny Kk3g== 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=R6C2AaIneOIoXK0xAiQxuXlGvMlgmSYIIzFiV5vgznY=; b=ETXIIL9MlTbuP173hWqfggupGxbIZPdvoOmyJkiQObs84vsZm9BO3GOQOhrx2mXco1 HrKyZlvFvxSxTmL84iDGNs/uo9op6r3a/ISrE23OjNrsmi6lK50xHAamhgHek6kAppcS bd2eKkPEoEhqA51Z5hgnZNxoM1QH4BoLIDCgFXwimUlMULwlwo4FkiSWThDIhJ1IyHYQ aPBDwGVGz9N+CL5sKpr0V+vOC5zJ8KHkCAwfAMtpfYFXSgwbywottDXbPldC9iuuMD0U eescCWFXs8oOGlAuA6M43Wsnq6SBhpvpqk5p4gU5AWnq5clhzVOfLWq4uldrXydPp6fw 7obg== X-Gm-Message-State: AMCzsaVjLxHTWPzpBElsipM+nER06HFM6w91G6H6bii2xxmoG4wkEEzO Ueznu4QS557qt8ASG3YXbIY= X-Google-Smtp-Source: ABhQp+RSUFcy9d6MFUB0UUAg7tIAbr8MIaz9+cjaBCaDvK3Y2v0xXa6vpnRnD/F4RDZ6BQ7bNUNEGQ== X-Received: by 10.36.233.196 with SMTP id f187mr10615019ith.14.1508794945434; Mon, 23 Oct 2017 14:42:25 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:25 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 12/25] ext4 crypto: wire up new ioctls for managing encryption keys Date: Mon, 23 Oct 2017 14:40:45 -0700 Message-Id: <20171023214058.128121-13-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144242_296758_2E977022 X-CRM114-Status: UNSURE ( 7.83 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c0b:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Signed-off-by: Eric Biggers --- fs/ext4/ioctl.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index afb66d4ab5cf..b8a6765a556f 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -978,6 +978,21 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case EXT4_IOC_GET_ENCRYPTION_POLICY: return fscrypt_ioctl_get_policy(filp, (void __user *)arg); + case FS_IOC_ADD_ENCRYPTION_KEY: + if (!ext4_has_feature_encrypt(sb)) + return -EOPNOTSUPP; + return fscrypt_ioctl_add_key(filp, (void __user *)arg); + + case FS_IOC_REMOVE_ENCRYPTION_KEY: + if (!ext4_has_feature_encrypt(sb)) + return -EOPNOTSUPP; + return fscrypt_ioctl_remove_key(filp, (const void __user *)arg); + + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: + if (!ext4_has_feature_encrypt(sb)) + return -EOPNOTSUPP; + return fscrypt_ioctl_get_key_status(filp, (void __user *)arg); + case EXT4_IOC_FSGETXATTR: { struct fsxattr fa; @@ -1102,6 +1117,9 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case EXT4_IOC_SET_ENCRYPTION_POLICY: case EXT4_IOC_GET_ENCRYPTION_PWSALT: case EXT4_IOC_GET_ENCRYPTION_POLICY: + case FS_IOC_ADD_ENCRYPTION_KEY: + case FS_IOC_REMOVE_ENCRYPTION_KEY: + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: case EXT4_IOC_SHUTDOWN: case FS_IOC_GETFSMAP: break; From patchwork Mon Oct 23 21:40:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829682 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="pJNGZCq8"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="gWqezrSC"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVMT3sGTz9sPt for ; Tue, 24 Oct 2017 08:45:57 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=PUV1aHLXX1ZtcSYcFjdl1DeRnPF0+SHgfvDirWgYudQ=; b=pJNGZCq8meEE1UXalR1pJZXh9e WaQJyiG9fZI0GkqpI8vPmimFb0Wj7myZ6ROSbKvUw0d/gXBnA+gLEoDoKcDf/GbEwmF/OQlkPRDa9 MbMySJ1/0huD8iHaQirm5tiisnErxefgoQ/U3OQKuw9aaRfktrquo+RJh1/rnSLE141MeqIfJtKls Ot9/8JO1zEW6Ugsi160TltDtonukYqgc7G8UnBwHj1bh2bz+TCSRaSGTboAIYGXu5gTHKwqYNLi8y izFlNvBrZTSvacdxU1Oh6ipUYiA9gDRZwRXk4tELZ7eMN7uef/CiK2z1erfD56+dhf7cW7YeJkvEC 4oJeFLDw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kXc-0008WL-Gt; Mon, 23 Oct 2017 21:45:48 +0000 Received: from mail-io0-x242.google.com ([2607:f8b0:4001:c06::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUg-0004ge-Gt for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:55 +0000 Received: by mail-io0-x242.google.com with SMTP id p186so21681217ioe.12 for ; Mon, 23 Oct 2017 14:42:27 -0700 (PDT) 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=jAhGMqQsViLdQ28Cp4m3d4i0dN1WL0MwsTETCvPIBwA=; b=gWqezrSCxDld13xUz5iB2icbznkayxMKXBPaNFNGz3aZAln6Dj6L0WVWesoVJ5gcJ+ ky4ctyzenvlSCM7k0TiyNbdmI++d+l3BPnCcNVtZunlu4UdVbuEuHPOXIHG+FaQzxYx7 MN2qFHwj+uoi2MGDSmqponQpWJs42LVb/DnwT4y/BN1vmY2hUr/XK7JdavfsO/srs4s0 NhHaPMlH7ovEJibVnM3MA2P+ARiLakODremgrjk5vxj7j11IgaSDOE5OB5Q4lD4oLNLe Q6aCjfVyD3uLtfpMxEAK/lcT1W3vZkRVdqPAHBLrovGRNAWV/Q4IBf+sPwLa0T7KoWJW jvuA== 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=jAhGMqQsViLdQ28Cp4m3d4i0dN1WL0MwsTETCvPIBwA=; b=ffYtGsZE6Amh70LujFHzR56gsEOiVL+O74cqlWAK/V2YSoE+Hqg4RI+0sdoJtlvLRG YsGZOTr4PPhqkFWuwIGnzpCwGe0cI9v7shJxSPz35eqPkn79T7QGwH5wlo5L/4uWtzA9 bdpPAL5+u9E+TOS6r+MGvkuAa2DibmQlbwRGCEZRs21Gl6SvKT1LRWob+gcwTjnqH/oG qqk33GpaXRPzujoLYQ/rAaVcBoh9NlbyyA+bSJmMOUbKJbGy3gvf4kB+5qKh3jfttk/N b4UoZT3LzCOP2mQJLrAmJ4mlSbTCEFjlxWFHoAh8Wgr4hNJE6uONmYrB0DzHYmdmvFqB gf3Q== X-Gm-Message-State: AMCzsaX/Qm2+Rsaf41kJBJA8yg2CjE++WEwvXzg+zeersweRH4e5ilno hglYS/mjOCyIBjnJmD9VkfI= X-Google-Smtp-Source: ABhQp+TC6a5lFG+uMjQBPXOwSNra3BElECyumBqazBHOEhaudVt6HRr/Jo5GenPtAyKladPibxwy3A== X-Received: by 10.107.186.87 with SMTP id k84mr19309249iof.121.1508794946719; Mon, 23 Oct 2017 14:42:26 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:26 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 13/25] f2fs crypto: wire up new ioctls for managing encryption keys Date: Mon, 23 Oct 2017 14:40:46 -0700 Message-Id: <20171023214058.128121-14-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144247_108970_676FCACC X-CRM114-Status: UNSURE ( 7.54 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Signed-off-by: Eric Biggers --- fs/f2fs/file.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 517e112c8a9a..0296a9594fe7 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2651,6 +2651,12 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return f2fs_ioc_get_encryption_policy(filp, arg); case F2FS_IOC_GET_ENCRYPTION_PWSALT: return f2fs_ioc_get_encryption_pwsalt(filp, arg); + case FS_IOC_ADD_ENCRYPTION_KEY: + return fscrypt_ioctl_add_key(filp, (void __user *)arg); + case FS_IOC_REMOVE_ENCRYPTION_KEY: + return fscrypt_ioctl_remove_key(filp, (const void __user *)arg); + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: + return fscrypt_ioctl_get_key_status(filp, (void __user *)arg); case F2FS_IOC_GARBAGE_COLLECT: return f2fs_ioc_gc(filp, arg); case F2FS_IOC_GARBAGE_COLLECT_RANGE: @@ -2731,6 +2737,9 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC_SET_ENCRYPTION_POLICY: case F2FS_IOC_GET_ENCRYPTION_PWSALT: case F2FS_IOC_GET_ENCRYPTION_POLICY: + case FS_IOC_ADD_ENCRYPTION_KEY: + case FS_IOC_REMOVE_ENCRYPTION_KEY: + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: case F2FS_IOC_GARBAGE_COLLECT: case F2FS_IOC_GARBAGE_COLLECT_RANGE: case F2FS_IOC_WRITE_CHECKPOINT: From patchwork Mon Oct 23 21:40:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829686 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="gmuaEK/F"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="VGPzTcZo"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVNm657Nz9sPr for ; Tue, 24 Oct 2017 08:47:04 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=SCMfLLKj8CuDz8ZxhpJoP4opxRSTaU26l/RkoTtptmg=; b=gmuaEK/F6Sfu/VHVq4XYWunasA NGiMs7AvQz9KY4DAsZPyq6xEGNPU0aCJYVquaUfC5TblqDG5SmtYFN/yUtMIvx0AGRIIFj203wRMc l4RZMr1wdKZ/q3LxhwdVq+WclHRqcjJdih72Dizxw7pqH7e6lw/mwTGYEfp3GHlNkscQohiS7MDy/ ybw9nwhrDVE8X6AgUGWroYpdncXWsTgcJH1SGs66dZSp+CQDOXuSXGIEgUkbbAOovlcKiDLrXU93j +JyyGs0Fn5unmGIIkYYKEb99EMZ9Ug46hVGii3bNcej4qwo4MiRYYk7ByOfSjVvXfjnw5EyDQC0X/ OrirfI4Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kYm-00018o-Uh; Mon, 23 Oct 2017 21:47:00 +0000 Received: from mail-io0-x244.google.com ([2607:f8b0:4001:c06::244]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUh-0004gy-QB for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:02 +0000 Received: by mail-io0-x244.google.com with SMTP id p186so21681265ioe.12 for ; Mon, 23 Oct 2017 14:42:28 -0700 (PDT) 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=QUfHkpecBlLdLVUNqn67/PgAG+kEvbbZIrssE94eL6s=; b=VGPzTcZoDtmaIFyxFbGwrU4iDmMt8zk9KIp/BkYfI2I1WlPPXuortAGSY7LHBncdDv MXUnYnZNttnx3vDNNeO4GadXZrCPnlic/+t3FticaJ6bZHnjYAADoRVGExyhNzsaDc89 iIMxM9jb7zBgdVo4jK/F/lo5N1ds1J9tey1QC+s64HkjFmdCjC1EH2fTZISR01ssHaiT WgzkEKoEj1LSFHbepybfb3EEqD5MaNr0pG/PWtziFox1mqqwo8Kw2RG/zOuv2rdmto8u 5qCi4lXRJWLWrOZOryurd/zFg2EBZwY0tSqsGSSJSggpUH3KvIdElAww8+GnSWD+W/D2 JBlQ== 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=QUfHkpecBlLdLVUNqn67/PgAG+kEvbbZIrssE94eL6s=; b=gwZUQVN9YunKm39kG9cg46hcHdFvSaAbIdltzzAj1pXo0yroS0QSxiD5Tbf6vWjD/h Sf9/asyMp0FRb/HA8ZyDz5diJFkOqOjzBkzr4rOj8Nzw+aRnl8O22GWC4PMnM9R+SSUS H3Z8MaPEcuk2u9RFptp80xVzwcgpV67s4zTVg06q1mPK4VJXqnWfmAgdLvHsvcSO9WJf Tnj++nCpPmbI5FW8Yh8gp9Uii/b+nGI31sUxJXZ5o/g4yFA3jPS6kuF7Qpsko8in4cYo 6Fwvg2XIEn4JNqimYNj63jKbuSFWkGFid37aVqTua8z16FeVw0oAQPpQAWCDip8A4wBc geUw== X-Gm-Message-State: AMCzsaWJ+grM7ZhJkqP0vkyJCQY2SAZhi6uzhzSITw2JFryWgw7+JUET cBco44QxjJ3NT9IDaZWcTgY= X-Google-Smtp-Source: ABhQp+TPuEafxtwHdHrn3WFN7nQ7gLOS4bDqSLYIa6OozxpNhD68RV709wXkOz9M6Nd1cbtE9tr8jQ== X-Received: by 10.107.192.71 with SMTP id q68mr6542203iof.81.1508794947960; Mon, 23 Oct 2017 14:42:27 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:27 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 14/25] ubifs crypto: wire up new ioctls for managing encryption keys Date: Mon, 23 Oct 2017 14:40:47 -0700 Message-Id: <20171023214058.128121-15-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144248_256223_BDB78C1E X-CRM114-Status: UNSURE ( 8.12 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Signed-off-by: Eric Biggers --- fs/ubifs/ioctl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index 0164bcc827f8..09ede2d1898f 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c @@ -205,6 +205,15 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #endif } + case FS_IOC_ADD_ENCRYPTION_KEY: + return fscrypt_ioctl_add_key(file, (void __user *)arg); + + case FS_IOC_REMOVE_ENCRYPTION_KEY: + return fscrypt_ioctl_remove_key(file, (const void __user *)arg); + + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: + return fscrypt_ioctl_get_key_status(file, (void __user *)arg); + default: return -ENOTTY; } @@ -222,6 +231,9 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; case FS_IOC_SET_ENCRYPTION_POLICY: case FS_IOC_GET_ENCRYPTION_POLICY: + case FS_IOC_ADD_ENCRYPTION_KEY: + case FS_IOC_REMOVE_ENCRYPTION_KEY: + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: break; default: return -ENOIOCTLCMD; From patchwork Mon Oct 23 21:40:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829687 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="KA3I8Y6P"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="arrW1K/l"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVP73qMzz9sPr for ; Tue, 24 Oct 2017 08:47:23 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=hFYJMcVjtfiVjGUemaz4G1O6puu2zUhiYaSf0+dhB7g=; b=KA3I8Y6P90EMInweUrTL4ZYcXu AEy6WoRLueZMQtEZ7PWFLsqClfh6tybd7lNwANaB4sIK8dN2r3uVRCIUzZw99FfmfzGiFp2MC9jHU 6xF3CCxHw5tMPnpKHPY2ND2SkzvOBO57z5mveq0lJVVdW9SstuQTFUuzmZCrZX38uh64GEdTDQYay VolRB5VXf+V03FNI1YqelqSpUccrJSnm2OS9FnhcUH/5fz9sIY+vfcpazE+WqHnpagW6m/eiIkVmU ok/oMAs7fD7YVPhEu/oOICL9yYLwOb8qmLmglcGS11DHoYBVNcXmBi1KN76DbqUWjbv/PFAvGXCxr zdSQW/1A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kZ5-0001Qo-Fl; Mon, 23 Oct 2017 21:47:19 +0000 Received: from mail-io0-x242.google.com ([2607:f8b0:4001:c06::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUg-0004h8-HV for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:04 +0000 Received: by mail-io0-x242.google.com with SMTP id 97so21701090iok.7 for ; Mon, 23 Oct 2017 14:42:29 -0700 (PDT) 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=OMXcS9y24ubcseOc+pBdDRqhoky0kt8ih38nCA8A/Gs=; b=arrW1K/ldyXztDfm70pKJJSgrCA71CdpqQaaWlmoCHb5qCqNmKGz/YYmoa/YWuP8qh laxUBenf2OnBG0+pOVVzGSP+Mr8QMu/OARUO10Jp+dZJLDIfJgop63Adbud7Es5tPg1s y87hPn35jsQG7wA4paKhqIPiVHOB7txpYZMlRHKmbsW9E2WAvmlq/wpvI3UdUVaJuqBe 0w8WGCH2Qc+QDyzRX8f6plS/vMC3C2dCsbL7VdB5RRR8srN+kPQnArZrEfgoMCKqfvsv 2sEqRqk3EJBfkqfI4Xj0loNbmoZ4xMowiX8Q3YXMaSyZ5etkxeoFD4B5xKpgZGGcwxX4 /7gg== 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=OMXcS9y24ubcseOc+pBdDRqhoky0kt8ih38nCA8A/Gs=; b=WphOaFm1wFQmnRo4upLict/hcwmbj/86mHwRp/SMW9NboMpj/y3b1bVJGGReeY0+Oc rNS//+8F65jQK+cBxhS0Opqj84w4ZzkSTxdWaXN6lGlI2YLVug8YKlGJsosFSIBZKHDx ebbaZVrXtI4jBMg3oMfJqLlZEbTGoRYHX0yCZeau+rGEuBFZO4owPqreml5f2/uAcv3C JuaYjWu+ITUmj+AIOp1HU9qATBhYV+Pw6GFG/KbSX0xf/XsXv1h4uNX8zNKEbEvdnd3C FmqGyoemYLBUnI+3xGQyjFz/uv9KuutyTbL6KfrRKRssAHzWAD/qqCbI9FnsIRYwWkw8 ZAWA== X-Gm-Message-State: AMCzsaUIHb2X4eR0fiF/N65d7PBZyGahSLeoQD8t8O9bC9IPyW7OOOgt ByBZys7xY3FcuNVqovMqoIg= X-Google-Smtp-Source: ABhQp+R/Ok11T+Ua/PLXztktVTW9ixZgtGZE67fAfGplStsc7eZQXQ2dBQck6whUs7AvUc6IamYpNQ== X-Received: by 10.107.169.34 with SMTP id s34mr10247939ioe.103.1508794949256; Mon, 23 Oct 2017 14:42:29 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:28 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 15/25] fscrypt: add UAPI definitions to get/set v2 encryption policies Date: Mon, 23 Oct 2017 14:40:48 -0700 Message-Id: <20171023214058.128121-16-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144247_221701_1AD6469F X-CRM114-Status: GOOD ( 16.24 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Currently, fscrypt policies and xattrs identify the master key by master_key_descriptor, which is an arbitrary 8-byte value used to form the description of the keyring key. However, there is no verification that the key descriptor in any way corresponds with the key payload. Since ->i_crypt_info by necessity gets set up on a "first come, first serve" basis, this flaw allows a process with only read-only access to an encrypted file or directory to provide the wrong key, causing the file contents or directory listing to be corrupted. This is a bug with security implications which must be fixed. To fix this bug without simply locking down adding keys to root, we must replace master_key_descriptor with a cryptographic hash of the key. We name the replacement master_key_identifier and make it 16 bytes long, which should provide enough collision resistance, and more importantly preimage resistance, without bloating the size of the encryption xattr too much. This will be both an on-disk format and API change, since we'll need to define new versions of both the fscrypt_context and fscrypt_policy. This patch begins this process by defining the UAPI changes to manage v2 policies. (Note: we jump to version 2 even though the previous policy version number was 0 because the fscrypt_context was actually already using version 1, not version 0. It would be really confusing to have them always be 1 off from each other.) The existing FS_IOC_SET_ENCRYPTION_POLICY will be used to set a v2 policy, as the kernel will be able to examine the 'version' field. However, a new ioctl FS_IOC_GET_ENCRYPTION_POLICY_EX is needed to get a v2 policy, since the returned struct needs to be larger. This ioctl includes a size field as input, so that it can be used for both v1 and v2 policies as well as any new policy versions that may get added in the future. Signed-off-by: Eric Biggers --- include/uapi/linux/fscrypt.h | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 9da153df238a..065060b20a34 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -7,7 +7,6 @@ * File system encryption support */ /* Policy provided via an ioctl on the topmost directory */ -#define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 /* Encryption policy flags */ #define FSCRYPT_POLICY_FLAGS_PAD_4 0x00 @@ -26,13 +25,22 @@ #define FSCRYPT_MODE_AES_128_CBC 5 #define FSCRYPT_MODE_AES_128_CTS 6 -struct fscrypt_policy { +/* + * Legacy policy version; no key verification (potentially insecure). + * For new encrypted directories, use fscrypt_policy_v2 instead. + * + * Careful: the .version field for this is actually 0, not 1. + */ +#define FSCRYPT_POLICY_VERSION_LEGACY 0 +#define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 +struct fscrypt_policy_v1 { __u8 version; __u8 contents_encryption_mode; __u8 filenames_encryption_mode; __u8 flags; __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; +#define fscrypt_policy fscrypt_policy_v1 /* * Process-subscribed "logon" key description prefix and payload format. @@ -47,6 +55,30 @@ struct fscrypt_key { __u32 size; }; +/* + * New policy version with HKDF and key verification (recommended). + */ +#define FSCRYPT_POLICY_VERSION_2 2 +#define FSCRYPT_KEY_IDENTIFIER_SIZE 16 +struct fscrypt_policy_v2 { + __u8 version; + __u8 contents_encryption_mode; + __u8 filenames_encryption_mode; + __u8 flags; + __u8 reserved[4]; + __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; +}; + +/* Struct passed to FS_IOC_GET_ENCRYPTION_POLICY_EX */ +struct fscrypt_get_policy_ex_args { + __u64 size; /* input/output */ + union { + __u8 version; + struct fscrypt_policy_v1 v1; + struct fscrypt_policy_v2 v2; + } policy; /* output */ +}; + struct fscrypt_key_specifier { __u32 type; #define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR 1 @@ -91,6 +123,7 @@ struct fscrypt_get_key_status_args { #define FS_IOC_SET_ENCRYPTION_POLICY _IOR( 'f', 19, struct fscrypt_policy) #define FS_IOC_GET_ENCRYPTION_PWSALT _IOW( 'f', 20, __u8[16]) #define FS_IOC_GET_ENCRYPTION_POLICY _IOW( 'f', 21, struct fscrypt_policy) +#define FS_IOC_GET_ENCRYPTION_POLICY_EX _IOWR('f', 21, __u8[9]) /* size + version */ #define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 22, struct fscrypt_add_key_args) #define FS_IOC_REMOVE_ENCRYPTION_KEY _IOR( 'f', 23, struct fscrypt_remove_key_args) #define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f',24, struct fscrypt_get_key_status_args) From patchwork Mon Oct 23 21:40:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829691 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="CxcqTXKJ"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="XxlgIprW"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVQx1wGmz9sPr for ; Tue, 24 Oct 2017 08:48:57 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=ZRdwARU2LkUsUIMzEsAxGzP3PekyvUgoEaxtQCc3qdQ=; b=CxcqTXKJ4ZExuiEAADJYEO8jn0 0bpSvHN/wixPhWi68W/Zr/kFXsicnyzSq1wC5NgF6YDtSZer5nTzktkcst9hrDjT5P9hLEKeMswgd oeDy8KSYgGQv3mTTtGK2MGG96RJ0ENF8Aio/jcmSx1q3BiIei1/XLh6qs0wENU3ni+2OunbzmfKb4 MqZhDRkZx9hxMVTTLLKnGM7sTP9vxSPmkakUjHpzOcdlj83x1V+B1w94dg9m1KQWYlZ0f/INSKriz Dt5RLu8Ki2bdb2YAJ1xqVRWae7x/TiQq8rVrhrbfzaMgYz0xY3FngzNov3EN5oHt6FU6tGEs5Jj0D PrlwYZ+Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kaU-0002mm-4L; Mon, 23 Oct 2017 21:48:46 +0000 Received: from mail-io0-f196.google.com ([209.85.223.196]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUm-0004hR-5Q for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:18 +0000 Received: by mail-io0-f196.google.com with SMTP id 189so21720124iow.10 for ; Mon, 23 Oct 2017 14:42:31 -0700 (PDT) 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=7PAFel6xMMTAASphSbnZbb/0C93sFMs1mLjjC+b6+Kk=; b=XxlgIprW1p8wqJ7EnJvrIbzQAMlxtZIhq0W2sEA9aFpusCdFFBodwh76BRuehiE05S IMP3+nmdcsdyVt+d8K5K+G+kSbZI+xN7hOHJUC5hlbDLveB4nMUERIDn0uzokmPcUFwL aqe4f0miXgtVG54owVALV8Ej57qjMdFSiD70hfDcvR45Gbloh69GISSOtlOAK5h4A/l0 h8QiMsnj6QBWNjynNAcpA9BEor1Di5hPgbn673KeG9JnaCRZAlc+8JH5obQXwvfGt3mS FJFBKxSBw4VnTqNWeFoPmh5flgFpwnOHAMH+onITwqBoTgFOZ/2/arDa2nKu28qhkU/g Vl/w== 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=7PAFel6xMMTAASphSbnZbb/0C93sFMs1mLjjC+b6+Kk=; b=phoDmNjM/1R7VZtnVJierS2UspA1FHG6MU2F/mReYU8Y1kWsOH4rwF0h/wJ2rYv4KH wXZDMtQo+OPA/3AWbbjmwGBpOWx1ZU5DAj4ayEucBaIIBu1nXQSDPmijo+51ES6XDw9u N9YnDNfBxi0tasMvI1dVtVYc5NTZwkADHb9JzGAett01yZC0KJraRIG9kYx/qnONFYkG 6v8EAFh+PlJJSdn+eKvU57pl3/bSIOh29ZIdhW/pC+DdPYu4IdrmWaAyMRkuXOE+L8p4 SBdAfmhLbsZOMzMD3t6bx/uLVRj6XDiUWxOW+5HWq6VTplQQhR9+fZjnYf7xsfZulIFo HySQ== X-Gm-Message-State: AMCzsaVg7R6RBgBG6kJIhVU3oU6SxTsophQDbt2+RWjXKsxVLtZ1od8M XBDRNSbok850UbsYJiETdIuEHHPx X-Google-Smtp-Source: ABhQp+TGJOqheSJHlCLfFqwXk0Fgb7N42Pp5FFoKpjhXWIx34Sz2TefB3kOC6wC3V3YzPXf8c0u58A== X-Received: by 10.107.31.143 with SMTP id f137mr10182620iof.86.1508794950809; Mon, 23 Oct 2017 14:42:30 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:30 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 16/25] fscrypt: implement basic handling of v2 encryption policies Date: Mon, 23 Oct 2017 14:40:49 -0700 Message-Id: <20171023214058.128121-17-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144252_974219_B06AEE4F X-CRM114-Status: GOOD ( 24.95 ) X-Spam-Score: -4.0 (----) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-4.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [209.85.223.196 listed in list.dnswl.org] 0.5 RCVD_IN_SORBS_SPAM RBL: SORBS: sender is a spam source [209.85.223.196 listed in dnsbl.sorbs.net] -2.8 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.223.196 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Update the fscrypt internals to handle v2 encryption policies. This includes supporting getting and setting them, translating them to/from the on-disk fscrypt_context. It also includes storing either a v1 or v2 policy struct in the fscrypt_info for use by fscrypt_inherit_context() and fscrypt_has_permitted_context(). (Previously we were storing the individual fields, but it is a bit easier to store a policy struct.) An fscrypt_policy_v1 (previously 'fscrypt_policy') maps to/from an fscrypt_context_v1 (previously 'fscrypt_context'), while an fscrypt_policy_v2 maps to/from an fscrypt_context_v2. Key management for v2 policies will be implemented by later patches. For now, attempting to set up an inode's key just fails with EOPNOTSUPP. Signed-off-by: Eric Biggers --- fs/crypto/fname.c | 4 +- fs/crypto/fscrypt_private.h | 172 ++++++++++++++++--- fs/crypto/keyinfo.c | 70 ++++---- fs/crypto/policy.c | 368 ++++++++++++++++++++++++++++------------ include/linux/fscrypt.h | 2 +- include/linux/fscrypt_notsupp.h | 6 + include/linux/fscrypt_supp.h | 1 + 7 files changed, 452 insertions(+), 171 deletions(-) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index c91bcef65b9f..78dc0e3f6328 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -46,7 +46,7 @@ static int fname_encrypt(struct inode *inode, int res = 0; char iv[FS_CRYPTO_BLOCK_SIZE]; struct scatterlist sg; - int padding = 4 << (ci->ci_flags & FSCRYPT_POLICY_FLAGS_PAD_MASK); + int padding = fscrypt_policy_fname_padding(&ci->ci_policy); unsigned int lim; unsigned int cryptlen; @@ -217,7 +217,7 @@ u32 fscrypt_fname_encrypted_size(const struct inode *inode, u32 ilen) struct fscrypt_info *ci = inode->i_crypt_info; if (ci) - padding = 4 << (ci->ci_flags & FSCRYPT_POLICY_FLAGS_PAD_MASK); + padding = fscrypt_policy_fname_padding(&ci->ci_policy); ilen = max(ilen, (u32)FS_CRYPTO_BLOCK_SIZE); return round_up(ilen, padding); } diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 2fdc4e5c0771..dec85c4b14a8 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -29,39 +29,159 @@ #define FSCRYPT_MIN_KEY_SIZE 16 -/** - * Encryption context for inode - * - * Protector format: - * 1 byte: Protector format (1 = this version) - * 1 byte: File contents encryption mode - * 1 byte: File names encryption mode - * 1 byte: Flags - * 8 bytes: Master Key descriptor - * 16 bytes: Encryption Key derivation nonce - */ -struct fscrypt_context { - u8 format; +struct fscrypt_context_v1 { + + u8 version; /* FSCRYPT_CONTEXT_V1 */ + + /* Same meaning as in v2 context --- see below */ u8 contents_encryption_mode; u8 filenames_encryption_mode; u8 flags; + + /* + * Descriptor for this file's master key in a process-subscribed keyring + * --- typically a session keyring, or a user keyring linked into a + * session or user session keyring. This is an arbitrary value, chosen + * by userspace when it set the encryption policy. It is *not* + * necessarily tied to the actual key payload. + */ u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + + /* + * A unique value used in combination with the master key to derive the + * file's actual encryption key + */ u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; -} __packed; +}; + +struct fscrypt_context_v2 { + + u8 version; /* FSCRYPT_CONTEXT_V2 */ + + /* Encryption mode for the contents of regular files */ + u8 contents_encryption_mode; -#define FS_ENCRYPTION_CONTEXT_FORMAT_V1 1 + /* Encryption mode for filenames in directories and symlink targets */ + u8 filenames_encryption_mode; + + /* Options that affect how encryption is done (e.g. padding amount) */ + u8 flags; + + /* Reserved, must be 0 */ + u8 reserved[4]; + + /* + * A cryptographic hash of the master key with which this file is + * encrypted + */ + u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; + + /* + * A unique value used in combination with the master key to derive the + * file's actual encryption key + */ + u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; +}; + +/** + * fscrypt_context - the encryption context for an inode + * + * Filesystems usually store this in an extended attribute. It identifies the + * encryption algorithm and key with which the file is encrypted. + * + * Since this is stored on-disk, be careful not to reorder fields or add any + * implicit padding bytes! + */ +union fscrypt_context { + struct fscrypt_context_v1 v1; + struct fscrypt_context_v2 v2; +}; + +#define FSCRYPT_CONTEXT_V1 1 +#define FSCRYPT_CONTEXT_V2 2 + +static inline int fscrypt_context_size(const union fscrypt_context *ctx) +{ + switch (ctx->v1.version) { + case FSCRYPT_CONTEXT_V1: + return sizeof(ctx->v1); + case FSCRYPT_CONTEXT_V2: + return sizeof(ctx->v2); + } + return 0; +} + +static inline bool +fscrypt_valid_context_format(const union fscrypt_context *ctx, int size) +{ + return size >= 1 && size == fscrypt_context_size(ctx); +} + +#undef fscrypt_policy +union fscrypt_policy { + struct fscrypt_policy_v1 v1; + struct fscrypt_policy_v2 v2; +}; + +static inline int fscrypt_policy_size(const union fscrypt_policy *policy) +{ + switch (policy->v1.version) { + case FSCRYPT_POLICY_VERSION_LEGACY: + return sizeof(policy->v1); + case FSCRYPT_POLICY_VERSION_2: + return sizeof(policy->v2); + } + return 0; +} + +static inline u8 +fscrypt_policy_contents_mode(const union fscrypt_policy *policy) +{ + switch (policy->v1.version) { + case FSCRYPT_POLICY_VERSION_LEGACY: + return policy->v1.contents_encryption_mode; + case FSCRYPT_POLICY_VERSION_2: + return policy->v2.contents_encryption_mode; + } + BUG(); +} + +static inline u8 +fscrypt_policy_fnames_mode(const union fscrypt_policy *policy) +{ + switch (policy->v1.version) { + case FSCRYPT_POLICY_VERSION_LEGACY: + return policy->v1.filenames_encryption_mode; + case FSCRYPT_POLICY_VERSION_2: + return policy->v2.filenames_encryption_mode; + } + BUG(); +} + +static inline int +fscrypt_policy_fname_padding(const union fscrypt_policy *policy) +{ + switch (policy->v1.version) { + case FSCRYPT_POLICY_VERSION_LEGACY: + return 4 << (policy->v1.flags & FSCRYPT_POLICY_FLAGS_PAD_MASK); + case FSCRYPT_POLICY_VERSION_2: + return 4 << (policy->v2.flags & FSCRYPT_POLICY_FLAGS_PAD_MASK); + } + BUG(); +} /* - * A pointer to this structure is stored in the file system's in-core - * representation of an inode. + * fscrypt_info - the "encryption key" for an inode + * + * When an encrypted file's key is made available, an instance of this struct is + * allocated and stored in ->i_crypt_info. Once created, it remains until the + * inode is evicted. */ struct fscrypt_info { - u8 ci_data_mode; - u8 ci_filename_mode; - u8 ci_flags; + + /* The actual crypto transforms needed for encryption and decryption */ struct crypto_skcipher *ci_ctfm; struct crypto_cipher *ci_essiv_tfm; - u8 ci_master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; /* * The master key with which this inode was unlocked (decrypted). This @@ -78,6 +198,9 @@ struct fscrypt_info { * ->ci_master_key is set. */ struct inode *ci_inode; + + /* The encryption policy used by this file */ + union fscrypt_policy ci_policy; }; typedef enum { @@ -114,4 +237,11 @@ extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, extern struct key_type key_type_fscrypt_mk; extern void __exit fscrypt_essiv_cleanup(void); +/* policy.c */ +extern bool fscrypt_policies_equal(const union fscrypt_policy *policy1, + const union fscrypt_policy *policy2); +extern bool fscrypt_supported_policy(const union fscrypt_policy *policy_u); +extern void fscrypt_context_to_policy(const union fscrypt_context *ctx_u, + union fscrypt_policy *policy_u); + #endif /* _FSCRYPT_PRIVATE_H */ diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 4052030a4c96..937a678ebba1 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -649,7 +649,7 @@ static void derive_crypt_complete(struct crypto_async_request *req, int rc) * key is longer, then only the first 'derived_keysize' bytes are used. */ static int derive_key_aes(const u8 *master_key, - const struct fscrypt_context *ctx, + const struct fscrypt_context_v1 *ctx, u8 *derived_key, unsigned int derived_keysize) { int err; @@ -751,7 +751,7 @@ find_and_lock_process_key(const char *prefix, } static int find_and_derive_key_legacy(const struct inode *inode, - const struct fscrypt_context *ctx, + const struct fscrypt_context_v1 *ctx, u8 *derived_key, unsigned int derived_keysize) { @@ -786,7 +786,7 @@ static int find_and_derive_key_legacy(const struct inode *inode, * its fscrypt_info into ->mk_decrypted_inodes. */ static int find_and_derive_key(const struct inode *inode, - const struct fscrypt_context *ctx, + const union fscrypt_context *ctx, u8 *derived_key, unsigned int derived_keysize, struct key **master_key_ret) { @@ -795,9 +795,15 @@ static int find_and_derive_key(const struct inode *inode, struct fscrypt_key_specifier mk_spec; int err; - mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; - memcpy(mk_spec.descriptor, ctx->master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); + switch (ctx->v1.version) { + case FSCRYPT_CONTEXT_V1: + mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; + memcpy(mk_spec.descriptor, ctx->v1.master_key_descriptor, + FSCRYPT_KEY_DESCRIPTOR_SIZE); + break; + default: + return -EOPNOTSUPP; + } key = find_master_key(inode->i_sb, &mk_spec); if (IS_ERR(key)) { @@ -807,7 +813,7 @@ static int find_and_derive_key(const struct inode *inode, * As a legacy fallback, we search the current task's subscribed * keyrings in addition to ->s_master_keys. */ - return find_and_derive_key_legacy(inode, ctx, derived_key, + return find_and_derive_key_legacy(inode, &ctx->v1, derived_key, derived_keysize); } mk = key->payload.data[0]; @@ -833,7 +839,7 @@ static int find_and_derive_key(const struct inode *inode, goto out_release_key; } - err = derive_key_aes(mk->mk_secret.raw, ctx, + err = derive_key_aes(mk->mk_secret.raw, &ctx->v1, derived_key, derived_keysize); if (err) goto out_release_key; @@ -862,17 +868,10 @@ static int determine_cipher_type(struct fscrypt_info *ci, struct inode *inode, { u32 mode; - if (!fscrypt_valid_enc_modes(ci->ci_data_mode, ci->ci_filename_mode)) { - pr_warn_ratelimited("fscrypt: inode %lu uses unsupported encryption modes (contents mode %d, filenames mode %d)\n", - inode->i_ino, - ci->ci_data_mode, ci->ci_filename_mode); - return -EINVAL; - } - if (S_ISREG(inode->i_mode)) { - mode = ci->ci_data_mode; + mode = fscrypt_policy_contents_mode(&ci->ci_policy); } else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { - mode = ci->ci_filename_mode; + mode = fscrypt_policy_fnames_mode(&ci->ci_policy); } else { WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n", inode->i_ino, (inode->i_mode & S_IFMT)); @@ -984,7 +983,7 @@ void __exit fscrypt_essiv_cleanup(void) int fscrypt_get_encryption_info(struct inode *inode) { struct fscrypt_info *crypt_info; - struct fscrypt_context ctx; + union fscrypt_context ctx; struct crypto_skcipher *ctfm; const char *cipher_str; unsigned int derived_keysize; @@ -1006,33 +1005,31 @@ int fscrypt_get_encryption_info(struct inode *inode) return res; /* Fake up a context for an unencrypted directory */ memset(&ctx, 0, sizeof(ctx)); - ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; - ctx.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; - ctx.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; - memset(ctx.master_key_descriptor, 0x42, + ctx.v1.version = FSCRYPT_CONTEXT_V1; + ctx.v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; + ctx.v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; + memset(ctx.v1.master_key_descriptor, 0x42, FSCRYPT_KEY_DESCRIPTOR_SIZE); - } else if (res != sizeof(ctx)) { - return -EINVAL; + res = sizeof(ctx.v1); } - if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) - return -EINVAL; - - if (ctx.flags & ~FSCRYPT_POLICY_FLAGS_VALID) + if (!fscrypt_valid_context_format(&ctx, res)) return -EINVAL; crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_NOFS); if (!crypt_info) return -ENOMEM; - crypt_info->ci_flags = ctx.flags; - crypt_info->ci_data_mode = ctx.contents_encryption_mode; - crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; - memcpy(crypt_info->ci_master_key_descriptor, ctx.master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); + fscrypt_context_to_policy(&ctx, &crypt_info->ci_policy); + if (!fscrypt_supported_policy(&crypt_info->ci_policy)) { + res = -EINVAL; + pr_warn_ratelimited("fscrypt: inode %lu uses unsupported encryption policy\n", + inode->i_ino); + goto out; + } - res = determine_cipher_type(crypt_info, inode, - &cipher_str, &derived_keysize); + res = determine_cipher_type(crypt_info, inode, &cipher_str, + &derived_keysize); if (res) goto out; @@ -1065,7 +1062,8 @@ int fscrypt_get_encryption_info(struct inode *inode) goto out; if (S_ISREG(inode->i_mode) && - crypt_info->ci_data_mode == FSCRYPT_MODE_AES_128_CBC) { + (fscrypt_policy_contents_mode(&crypt_info->ci_policy) == + FSCRYPT_MODE_AES_128_CBC)) { res = init_essiv_generator(crypt_info, derived_key, derived_keysize); if (res) { diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index a856c8941be6..27a391038f73 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -6,6 +6,7 @@ * * Written by Michael Halcrow, 2015. * Modified by Jaegeuk Kim, 2015. + * Modified by Eric Biggers, 2017 for v2 policy support. */ #include @@ -13,84 +14,227 @@ #include #include "fscrypt_private.h" -/* - * check whether an encryption policy is consistent with an encryption context - */ -static bool is_encryption_context_consistent_with_policy( - const struct fscrypt_context *ctx, - const struct fscrypt_policy *policy) +bool fscrypt_policies_equal(const union fscrypt_policy *policy1, + const union fscrypt_policy *policy2) +{ + if (policy1->v1.version != policy2->v1.version) + return false; + + return !memcmp(policy1, policy2, fscrypt_policy_size(policy1)); +} + +bool fscrypt_supported_policy(const union fscrypt_policy *policy_u) +{ + switch (policy_u->v1.version) { + case FSCRYPT_POLICY_VERSION_LEGACY: { + const struct fscrypt_policy_v1 *policy = &policy_u->v1; + + if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, + policy->filenames_encryption_mode)) + return false; + + if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) + return false; + + return true; + } + case FSCRYPT_POLICY_VERSION_2: { + const struct fscrypt_policy_v2 *policy = &policy_u->v2; + + if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, + policy->filenames_encryption_mode)) + return false; + + if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) + return false; + + if (memchr_inv(policy->reserved, 0, sizeof(policy->reserved))) + return false; + + return true; + } + } + return false; +} + +static void fscrypt_policy_to_context(const union fscrypt_policy *policy_u, + union fscrypt_context *ctx_u) { - return memcmp(ctx->master_key_descriptor, policy->master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && - (ctx->flags == policy->flags) && - (ctx->contents_encryption_mode == - policy->contents_encryption_mode) && - (ctx->filenames_encryption_mode == - policy->filenames_encryption_mode); + memset(ctx_u, 0, sizeof(*ctx_u)); + + switch (policy_u->v1.version) { + case FSCRYPT_POLICY_VERSION_LEGACY: { + const struct fscrypt_policy_v1 *policy = &policy_u->v1; + struct fscrypt_context_v1 *ctx = &ctx_u->v1; + + ctx->version = FSCRYPT_CONTEXT_V1; + ctx->contents_encryption_mode = + policy->contents_encryption_mode; + ctx->filenames_encryption_mode = + policy->filenames_encryption_mode; + ctx->flags = policy->flags; + memcpy(ctx->master_key_descriptor, + policy->master_key_descriptor, + sizeof(ctx->master_key_descriptor)); + get_random_bytes(ctx->nonce, sizeof(ctx->nonce)); + break; + } + case FSCRYPT_POLICY_VERSION_2: { + const struct fscrypt_policy_v2 *policy = &policy_u->v2; + struct fscrypt_context_v2 *ctx = &ctx_u->v2; + + ctx->version = FSCRYPT_CONTEXT_V2; + ctx->contents_encryption_mode = + policy->contents_encryption_mode; + ctx->filenames_encryption_mode = + policy->filenames_encryption_mode; + ctx->flags = policy->flags; + memcpy(ctx->reserved, policy->reserved, sizeof(ctx->reserved)); + memcpy(ctx->master_key_identifier, + policy->master_key_identifier, + sizeof(ctx->master_key_identifier)); + get_random_bytes(ctx->nonce, sizeof(ctx->nonce)); + break; + } + default: + BUG(); + } } -static int create_encryption_context_from_policy(struct inode *inode, - const struct fscrypt_policy *policy) +void fscrypt_context_to_policy(const union fscrypt_context *ctx_u, + union fscrypt_policy *policy_u) { - struct fscrypt_context ctx; + memset(policy_u, 0, sizeof(*policy_u)); + + switch (ctx_u->v1.version) { + case FSCRYPT_CONTEXT_V1: { + const struct fscrypt_context_v1 *ctx = &ctx_u->v1; + struct fscrypt_policy_v1 *policy = &policy_u->v1; + + policy->version = FSCRYPT_POLICY_VERSION_LEGACY; + policy->contents_encryption_mode = + ctx->contents_encryption_mode; + policy->filenames_encryption_mode = + ctx->filenames_encryption_mode; + policy->flags = ctx->flags; + memcpy(policy->master_key_descriptor, + ctx->master_key_descriptor, + sizeof(policy->master_key_descriptor)); + return; + } + case FSCRYPT_CONTEXT_V2: { + const struct fscrypt_context_v2 *ctx = &ctx_u->v2; + struct fscrypt_policy_v2 *policy = &policy_u->v2; + + policy->version = FSCRYPT_POLICY_VERSION_2; + policy->contents_encryption_mode = + ctx->contents_encryption_mode; + policy->filenames_encryption_mode = + ctx->filenames_encryption_mode; + policy->flags = ctx->flags; + memcpy(policy->reserved, ctx->reserved, + sizeof(policy->reserved)); + memcpy(policy->master_key_identifier, + ctx->master_key_identifier, + sizeof(policy->master_key_identifier)); + return; + } + default: + BUG(); + } +} - ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; - memcpy(ctx.master_key_descriptor, policy->master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); +static int fscrypt_get_policy(struct inode *inode, union fscrypt_policy *policy) +{ + union fscrypt_context ctx; + int ret; + + if (inode->i_crypt_info) { + *policy = inode->i_crypt_info->ci_policy; + return 0; + } + + if (!IS_ENCRYPTED(inode)) + return -ENODATA; - if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, - policy->filenames_encryption_mode)) + ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); + if (ret < 0) + return (ret == -ERANGE) ? -EINVAL : ret; + if (!fscrypt_valid_context_format(&ctx, ret)) return -EINVAL; + fscrypt_context_to_policy(&ctx, policy); + return 0; +} + +static int set_encryption_policy(struct inode *inode, + const union fscrypt_policy *policy) +{ + union fscrypt_context ctx; - if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) + if (!fscrypt_supported_policy(policy)) return -EINVAL; - ctx.contents_encryption_mode = policy->contents_encryption_mode; - ctx.filenames_encryption_mode = policy->filenames_encryption_mode; - ctx.flags = policy->flags; - BUILD_BUG_ON(sizeof(ctx.nonce) != FS_KEY_DERIVATION_NONCE_SIZE); - get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); + fscrypt_policy_to_context(policy, &ctx); + + if (policy->v1.version == FSCRYPT_POLICY_VERSION_LEGACY) { + /* + * The original encryption policy version provided no way of + * verifying that the correct master key was supplied, which was + * insecure in scenarios where multiple users have access to the + * same encrypted files (even just read-only access). The new + * encryption policy version fixes this and also implies use of + * an improved key derivation function and allows non-root users + * to securely remove keys. So as long as compatibility with + * old kernels isn't required, it is recommended to use the new + * policy version for all new encrypted directories. + */ + pr_warn_once("%s (pid %d) is setting less secure v1 encryption policy; recommend upgrading to v2.\n", + current->comm, current->pid); + } - return inode->i_sb->s_cop->set_context(inode, &ctx, sizeof(ctx), NULL); + return inode->i_sb->s_cop->set_context(inode, &ctx, + fscrypt_context_size(&ctx), + NULL); } int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) { - struct fscrypt_policy policy; + union fscrypt_policy policy; + union fscrypt_policy existing_policy; struct inode *inode = file_inode(filp); + int size; int ret; - struct fscrypt_context ctx; - if (copy_from_user(&policy, arg, sizeof(policy))) + if (copy_from_user(&policy, arg, sizeof(u8))) + return -EFAULT; + + size = fscrypt_policy_size(&policy); + if (size == 0) + return -EINVAL; + + if (copy_from_user((u8 *)&policy + 1, arg + 1, size - 1)) return -EFAULT; if (!inode_owner_or_capable(inode)) return -EACCES; - if (policy.version != 0) - return -EINVAL; - ret = mnt_want_write_file(filp); if (ret) return ret; inode_lock(inode); - ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); + ret = fscrypt_get_policy(inode, &existing_policy); if (ret == -ENODATA) { if (!S_ISDIR(inode->i_mode)) ret = -ENOTDIR; else if (!inode->i_sb->s_cop->empty_dir(inode)) ret = -ENOTEMPTY; else - ret = create_encryption_context_from_policy(inode, - &policy); - } else if (ret == sizeof(ctx) && - is_encryption_context_consistent_with_policy(&ctx, - &policy)) { - /* The file already uses the same encryption policy. */ - ret = 0; - } else if (ret >= 0 || ret == -ERANGE) { + ret = set_encryption_policy(inode, &policy); + } else if (ret == -EINVAL || + (ret == 0 && !fscrypt_policies_equal(&policy, + &existing_policy))) { /* The file already uses a different encryption policy. */ ret = -EEXIST; } @@ -102,36 +246,61 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) } EXPORT_SYMBOL(fscrypt_ioctl_set_policy); +/* Original ioctl version; can only get the original policy version */ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) { - struct inode *inode = file_inode(filp); - struct fscrypt_context ctx; - struct fscrypt_policy policy; - int res; + union fscrypt_policy policy; + int err; - if (!IS_ENCRYPTED(inode)) - return -ENODATA; + err = fscrypt_get_policy(file_inode(filp), &policy); + if (err) + return err; - res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); - if (res < 0 && res != -ERANGE) - return res; - if (res != sizeof(ctx)) + if (policy.v1.version != FSCRYPT_POLICY_VERSION_LEGACY) return -EINVAL; - if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) + + if (copy_to_user(arg, &policy, sizeof(policy.v1))) + return -EFAULT; + return 0; +} +EXPORT_SYMBOL(fscrypt_ioctl_get_policy); + +/* Extended ioctl version; can get policies of any version */ +int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *_arg) +{ + struct fscrypt_get_policy_ex_args __user *arg = _arg; + __u64 size; + __u64 actual_size; + size_t policy_size; + union fscrypt_policy policy; + int err; + + if (get_user(size, &arg->size)) + return -EFAULT; + + if (size <= offsetof(struct fscrypt_get_policy_ex_args, policy) || + size >= 65536) return -EINVAL; - policy.version = 0; - policy.contents_encryption_mode = ctx.contents_encryption_mode; - policy.filenames_encryption_mode = ctx.filenames_encryption_mode; - policy.flags = ctx.flags; - memcpy(policy.master_key_descriptor, ctx.master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); + err = fscrypt_get_policy(file_inode(filp), &policy); + if (err) + return err; + + policy_size = fscrypt_policy_size(&policy); + actual_size = offsetof(struct fscrypt_get_policy_ex_args, policy) + + policy_size; - if (copy_to_user(arg, &policy, sizeof(policy))) + if (size < actual_size) + return -EOVERFLOW; + + if (put_user(actual_size, &arg->size)) + return -EFAULT; + + if (copy_to_user(&arg->policy, &policy, policy_size)) return -EFAULT; return 0; } -EXPORT_SYMBOL(fscrypt_ioctl_get_policy); +EXPORT_SYMBOL(fscrypt_ioctl_get_policy_ex); /** * fscrypt_has_permitted_context() - is a file's encryption policy permitted @@ -155,10 +324,8 @@ EXPORT_SYMBOL(fscrypt_ioctl_get_policy); */ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) { - const struct fscrypt_operations *cops = parent->i_sb->s_cop; - const struct fscrypt_info *parent_ci, *child_ci; - struct fscrypt_context parent_ctx, child_ctx; - int res; + union fscrypt_policy parent_policy, child_policy; + int err; /* No restrictions on file types which are never encrypted */ if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) && @@ -188,41 +355,22 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) * In any case, if an unexpected error occurs, fall back to "forbidden". */ - res = fscrypt_get_encryption_info(parent); - if (res) + err = fscrypt_get_encryption_info(parent); + if (err) return 0; - res = fscrypt_get_encryption_info(child); - if (res) + err = fscrypt_get_encryption_info(child); + if (err) return 0; - parent_ci = parent->i_crypt_info; - child_ci = child->i_crypt_info; - - if (parent_ci && child_ci) { - return memcmp(parent_ci->ci_master_key_descriptor, - child_ci->ci_master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && - (parent_ci->ci_data_mode == child_ci->ci_data_mode) && - (parent_ci->ci_filename_mode == - child_ci->ci_filename_mode) && - (parent_ci->ci_flags == child_ci->ci_flags); - } - res = cops->get_context(parent, &parent_ctx, sizeof(parent_ctx)); - if (res != sizeof(parent_ctx)) + err = fscrypt_get_policy(parent, &parent_policy); + if (err) return 0; - res = cops->get_context(child, &child_ctx, sizeof(child_ctx)); - if (res != sizeof(child_ctx)) + err = fscrypt_get_policy(child, &child_policy); + if (err) return 0; - return memcmp(parent_ctx.master_key_descriptor, - child_ctx.master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && - (parent_ctx.contents_encryption_mode == - child_ctx.contents_encryption_mode) && - (parent_ctx.filenames_encryption_mode == - child_ctx.filenames_encryption_mode) && - (parent_ctx.flags == child_ctx.flags); + return fscrypt_policies_equal(&parent_policy, &child_policy); } EXPORT_SYMBOL(fscrypt_has_permitted_context); @@ -238,30 +386,28 @@ EXPORT_SYMBOL(fscrypt_has_permitted_context); int fscrypt_inherit_context(struct inode *parent, struct inode *child, void *fs_data, bool preload) { - struct fscrypt_context ctx; - struct fscrypt_info *ci; - int res; + int err; + const struct fscrypt_info *ci; + union fscrypt_context ctx; - res = fscrypt_get_encryption_info(parent); - if (res < 0) - return res; + err = fscrypt_get_encryption_info(parent); + if (err) + return err; ci = parent->i_crypt_info; if (ci == NULL) return -ENOKEY; - ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; - ctx.contents_encryption_mode = ci->ci_data_mode; - ctx.filenames_encryption_mode = ci->ci_filename_mode; - ctx.flags = ci->ci_flags; - memcpy(ctx.master_key_descriptor, ci->ci_master_key_descriptor, - FSCRYPT_KEY_DESCRIPTOR_SIZE); - get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); BUILD_BUG_ON(sizeof(ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE); - res = parent->i_sb->s_cop->set_context(child, &ctx, - sizeof(ctx), fs_data); - if (res) - return res; + + fscrypt_policy_to_context(&ci->ci_policy, &ctx); + + err = parent->i_sb->s_cop->set_context(child, &ctx, + fscrypt_context_size(&ctx), + fs_data); + if (err) + return err; + return preload ? fscrypt_get_encryption_info(child): 0; } EXPORT_SYMBOL(fscrypt_inherit_context); diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 671ce57e4673..aa8c6e8bfed8 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -86,7 +86,7 @@ struct fscrypt_operations { }; /* Maximum value for the third parameter of fscrypt_operations.set_context(). */ -#define FSCRYPT_SET_CONTEXT_MAX_SIZE 28 +#define FSCRYPT_SET_CONTEXT_MAX_SIZE 40 static inline bool fscrypt_dummy_context_enabled(struct inode *inode) { diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index bd60f951b06a..41bd5b70e343 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -70,6 +70,12 @@ static inline int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) return -EOPNOTSUPP; } +static inline int fscrypt_ioctl_get_policy_ex(struct file *filp, + void __user *arg) +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) { diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index ace278056dbe..a11b0b2d14b0 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -38,6 +38,7 @@ static inline void fscrypt_set_encrypted_dentry(struct dentry *dentry) /* policy.c */ extern int fscrypt_ioctl_set_policy(struct file *, const void __user *); extern int fscrypt_ioctl_get_policy(struct file *, void __user *); +extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *); extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); From patchwork Mon Oct 23 21:40:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829703 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="PilpDfh+"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="m85Acexi"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="JSDM4oG+"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVjg5GPfz9sPt for ; Tue, 24 Oct 2017 09:01:43 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=bJM0t0zD5PPf/c+0sYtLFOwDoHlEvMyvFto9r+WPeXY=; b=PilpDfh+8GhcX0QJ3kjgJGToHb gJ8iTBX9dvoOlA/2Dw9Xnf7g/3Y7omQ4/ToZh5EdaLWKodQ5OxEoizohOoYaOYpY6CYAZp9dNgEY6 zfP6Gkkaq/pDNdaOnp0WxDDBkdTCGngtrWZVPOpYiwUylFmecAhZ5Qpr/ofsgWOKvfo3E0w0fVLOi pT0eoDe7aNw/e8k+GgR3CpuFnyu7fUCPE02vjpmRKJbGnFZo8TH/EoqYPWTFpB6DD8/PuEpspALiU pmH8MRdsx05p2O2+DT8PMrZazvI1N5GnpSfoXj3dROv4pqxf7lk8+3qEtmu9cEAVVK7eRGjYp9K4j m2AG7dzg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kmr-0002OY-6f; Mon, 23 Oct 2017 22:01:33 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kmE-0007eL-78 for linux-mtd@bombadil.infradead.org; Mon, 23 Oct 2017 22:00:54 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=M0HtKc8LygBEs38XxTPU0A68Tkp5KwzV3MolA/ydToc=; b=m85AcexiCYbprk/N4BqHjrvs1 +ZIYTltZMRot7l24BdYuL240gA29JsKnmK3WidN/TSkEGX+/Dnhoh3SnsjiyPmK/Iei5rmeW8KMlJ 5U4XDpg4OlDdUDFTRcCZ7RxcmYnemxflfY7zz/lOECkMtONsoMVu3R9kw2qRde4mn8GIgaoThucCG +XKMFjXxiyBDuFeTfHdSBd8xXsb5wjclqK+A5M8i/3x8slFzV7n4CkH2+jJrVnvz5LMKuTPlawvEP zJpmAmZrLu3imrGtJRbH1kK9TShL845NqL6Xoq/AmJiYlen2vXoxsqaQFyPSyETNgLimt8gIo7Nvo H9xaCsp9A==; Received: from mail-io0-x244.google.com ([2607:f8b0:4001:c06::244]) by casper.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUo-00076Y-I8 for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:57 +0000 Received: by mail-io0-x244.google.com with SMTP id 134so21710462ioo.0 for ; Mon, 23 Oct 2017 14:42:33 -0700 (PDT) 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=M0HtKc8LygBEs38XxTPU0A68Tkp5KwzV3MolA/ydToc=; b=JSDM4oG+KMKrf4TmBa2GsGG3mxO97HfIXQ3mu0fJhuZ49/sd0twzvapIbyqpp0Xc/S E04ymH31jz8KHWsdatL++Zae2ajckexkTlJHNXZM5Cmqomgm2l5xkbqqAzyT9cPlGRXM Llbl4E8yT82ka0JD93ZKsfXXszLN5YHrzGiO0Jddjfym6rHeZGauoL/sT/j2AdTqVMqx ap7jBnGzt3n07hGD8oATQT3cF3Nuqd9szutf4Q3Xro+0u9Lj1MlqcBezHT1LR6jKh2xa 2PLGPTkJa744ldZSC+XDA80TcS6ORywNxe9plAcXI/JapyTBa2B2/D39QK2ph+6jltVg /MbQ== 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=M0HtKc8LygBEs38XxTPU0A68Tkp5KwzV3MolA/ydToc=; b=b+1jmToGkpe9h4cZyqH6y/R7jxPIzDaXI+mRTHJKqWAkaZktt2ZxkbMmnQjG0tyZNk CsietplRtH/vExzn0AlM076z102dVyDz7qvhYV7/T2Jdf65vveWfPsa9G/OW9xp8k71F xEf3huKvwonV4Ey/PDL6DihZznTMAiinnP0DYs/mMpW8DYWIz32l/G1zZtdeDCkTsmty xCsgnM2ce7kBQ87RHmlqmH7ZY1sex/GFBpkC/tjcDfHa6oZLupoT7R8XX7P8jNVLhbtb +CjfyZV9e2GBh2VbVpiyuLS+WPfoPZj35dBfoh6NF1OUEawCO5PyOG/emj1ZXnoYxIb2 CWQw== X-Gm-Message-State: AMCzsaVn/+wbYg130wYJ4CjjnOIx3XjoEQSZLptN5Pj3zcDFsV1zq8LW fg1aw2hYy/XBEcycfwrm5k3KotQC X-Google-Smtp-Source: ABhQp+T24jP6+ziED4xAPsPOQg/UCR1/Fn4arpEW41rz5dfWqUGeHyRIu4UO1LVYGcvli+UNRBQVCw== X-Received: by 10.107.3.193 with SMTP id e62mr19552820ioi.88.1508794952318; Mon, 23 Oct 2017 14:42:32 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:31 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 17/25] fscrypt: add an HKDF-SHA512 implementation Date: Mon, 23 Oct 2017 14:40:50 -0700 Message-Id: <20171023214058.128121-18-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_224254_826913_456963A2 X-CRM114-Status: GOOD ( 41.46 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on casper.infradead.org summary: Content analysis details: (-1.8 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:244 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers For v2 encryption policies, we need to hash the master key to compute a master_key_identifier. Naively, we could just use a truncated SHA-512 or another common cryptographic hash function. However, that would cause the same key material to be used in two different ways: both as input to the hash function, and as input to the AES-ECB-based KDF when deriving the per-inode encryption keys. There *probably* isn't any practical attack on that, but still it would be better "crypto hygiene" to use the key material for one purpose only, e.g. just for a KDF. It also happens that the AES-based KDF is on our list of things to fix. While it does generate unique derived keys with sufficient entropy, it is nonstandard and has some problems that don't exist in standard KDFs such as HKDF. For example, the AES-based KDF is reversible: given a derived key and nonce, an attacker can easily compute the master key. This was maybe okay for the original threat model of ext4 encryption where the master key and derived keys were considered equally hard to compromise. But now we would like to be more robust against threats such as a derived key being compromised through a timing attack, or a derived key for an in-use file being compromised after the master key has already been wiped from memory via FS_IOC_REMOVE_ENCRYPTION_KEY. HKDF also has other advantages over the AES-ECB-based KDF such as evenly distributing the entropy from the input key material and being more extensible to deriving other key material that may be needed. Since we're introducing a new encryption policy version that already includes an on-disk format change, and we also now have a good place to cache an HMAC transform for each master key (struct fscrypt_master_key) so that HKDF can be implemented efficiently, we finally have a chance to switch to HKDF to derive the per-file keys. In addition, we'll use HKDF to derive the master_key_identifier, avoiding the need for a separate cryptographic hash primitive. This is secure because the output from HKDF is cryptographically isolated, i.e. sending some output in the clear doesn't reveal any other output, in a computational sense. (This is assuming that application-specific info strings aren't repeated between different uses of HKDF, but we'll use context bytes to ensure that.) Thus, this patch adds an implementation of HKDF to keyinfo.c, using an HMAC transform allocated from the crypto API. Later patches will make use of it. Note that using HKDF-SHA512 as the key derivation function will introduce a dependency on the security and implementation of SHA-512, whereas before we were using only AES for both key derivation and encryption. However, by using HMAC rather than the hash function directly, HKDF is designed to remain secure even if various classes of attacks, e.g. collision attacks, are found against the underlying unkeyed hash function. Even HMAC-MD5 is still considered secure in practice, despite MD5 itself having been heavily compromised. And meanwhile, the AES-based KDF used the public nonce as the cipher *key*, which is an unusual case which probably hasn't undergone much cryptanalysis. HKDF-SHA512 seems like a safer bet. We *could* actually avoid introducing a hash primitive by instantiating HKDF-Expand with CMAC-AES256 as the pseudorandom function rather than HMAC-SHA512. That would work; however, the HKDF specification doesn't explicitly allow a non-HMAC pseudorandom function, so it would be less standard. It would also require skipping HKDF-Extract and making the API accept only 32-byte master keys, since otherwise HKDF-Extract using CMAC-AES would produce a pseudorandom key only 16 bytes long which would only be enough for AES-128, not AES-256. References: - RFC 5869. "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)". https://tools.ietf.org/html/rfc5869 - Krawczyk (2010). "Cryptographic Extraction and Key Derivation: The HKDF Scheme". https://eprint.iacr.org/2010/264.pdf Signed-off-by: Eric Biggers --- fs/crypto/Kconfig | 2 + fs/crypto/keyinfo.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 181 insertions(+), 1 deletion(-) diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index 02b7d91c9231..bbd4e38b293c 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig @@ -8,6 +8,8 @@ config FS_ENCRYPTION select CRYPTO_CTS select CRYPTO_CTR select CRYPTO_SHA256 + select CRYPTO_SHA512 + select CRYPTO_HMAC select KEYS help Enable encryption of files and directories. This diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 937a678ebba1..e9de625ddfe4 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -6,6 +6,11 @@ * This contains encryption key functions. * * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015. + * + * HKDF support and key add/remove API added by Eric Biggers, 2017. + * + * The implementation and usage of HKDF should conform to RFC-5869 ("HMAC-based + * Extract-and-Expand Key Derivation Function"). */ #include @@ -14,10 +19,181 @@ #include #include #include +#include #include #include "fscrypt_private.h" -static struct crypto_shash *essiv_hash_tfm; +/* + * Any unkeyed cryptographic hash algorithm can be used with HKDF, but we use + * SHA-512 because it is reasonably secure and efficient; and since it produces + * a 64-byte digest, deriving an AES-256-XTS key preserves all 64 bytes of + * entropy from the master key and requires only one iteration of HKDF-Expand. + */ +#define HKDF_HMAC_ALG "hmac(sha512)" +#define HKDF_HASHLEN SHA512_DIGEST_SIZE + +/* + * HKDF consists of two steps: + * + * 1. HKDF-Extract: extract a fixed-length pseudorandom key from the + * input keying material and optional salt. + * 2. HKDF-Expand: expand the pseudorandom key into output keying material of + * any length, parameterized by an application-specific info string. + * + * HKDF-Extract can be skipped if the input is already a good pseudorandom key + * that is at least as long as the hash. While the fscrypt master keys should + * already be good pseudorandom keys, when using encryption algorithms that use + * short keys (e.g. AES-128-CBC) we'd like to permit the master key to be + * shorter than HKDF_HASHLEN bytes. Thus, we still must do HKDF-Extract. + * + * Ideally, HKDF-Extract would be passed a random salt for each distinct input + * key. Details about the advantages of a random salt can be found in the HKDF + * paper (Krawczyk, 2010; "Cryptographic Extraction and Key Derivation: The HKDF + * Scheme"). However, we do not have the ability to store a salt on a + * per-master-key basis. Thus, we have to use a fixed salt. This is sufficient + * as long as the master keys are already pseudorandom and are long enough to + * make dictionary attacks infeasible. This should be the case if userspace + * used a cryptographically secure random number generator, e.g. /dev/urandom, + * to generate the master keys and it was initialized with sufficient entropy. + * + * For the fixed salt we use "fscrypt_hkdf_salt" rather than default of all 0's + * defined by RFC-5869. This is only to be slightly more robust against + * userspace (unwisely) reusing the master keys for different purposes. + * Logically, it's more likely that the keys would be passed to unsalted + * HKDF-SHA512 than specifically to "fscrypt_hkdf_salt"-salted HKDF-SHA512. + * Of course, a random salt would be better for this purpose. + */ + +#define HKDF_SALT "fscrypt_hkdf_salt" +#define HKDF_SALT_LEN (sizeof(HKDF_SALT) - 1) + +/* + * HKDF-Extract (RFC-5869 section 2.2). This extracts a pseudorandom key 'prk' + * from the input key material 'ikm' and a salt. See explanation above for why + * we use a fixed salt. + */ +static int hkdf_extract(struct crypto_shash *hmac_tfm, + const u8 *ikm, unsigned int ikmlen, + u8 prk[HKDF_HASHLEN]) +{ + SHASH_DESC_ON_STACK(desc, hmac_tfm); + int err; + + desc->tfm = hmac_tfm; + desc->flags = 0; + + err = crypto_shash_setkey(hmac_tfm, HKDF_SALT, HKDF_SALT_LEN); + if (err) + goto out; + + err = crypto_shash_digest(desc, ikm, ikmlen, prk); +out: + shash_desc_zero(desc); + return err; +} + +/* + * HKDF-Expand (RFC-5869 section 2.3). This expands the pseudorandom key, which + * has already been keyed into 'hmac_tfm', into 'okmlen' bytes of output keying + * material, parameterized by the application-specific information string of + * 'info' prefixed with the 'context' byte. ('context' isn't part of the HKDF + * specification; it's just a prefix we add to our application-specific info + * strings to guarantee that we don't accidentally repeat an info string when + * using HKDF for different purposes.) + */ +static int hkdf_expand(struct crypto_shash *hmac_tfm, u8 context, + const u8 *info, unsigned int infolen, + u8 *okm, unsigned int okmlen) +{ + SHASH_DESC_ON_STACK(desc, hmac_tfm); + int err; + const u8 *prev = NULL; + unsigned int i; + u8 counter = 1; + u8 tmp[HKDF_HASHLEN]; + + desc->tfm = hmac_tfm; + desc->flags = 0; + + if (unlikely(okmlen > 255 * HKDF_HASHLEN)) + return -EINVAL; + + for (i = 0; i < okmlen; i += HKDF_HASHLEN) { + + err = crypto_shash_init(desc); + if (err) + goto out; + + if (prev) { + err = crypto_shash_update(desc, prev, HKDF_HASHLEN); + if (err) + goto out; + } + + err = crypto_shash_update(desc, &context, 1); + if (err) + goto out; + + err = crypto_shash_update(desc, info, infolen); + if (err) + goto out; + + if (okmlen - i < HKDF_HASHLEN) { + err = crypto_shash_finup(desc, &counter, 1, tmp); + if (err) + goto out; + memcpy(&okm[i], tmp, okmlen - i); + memzero_explicit(tmp, sizeof(tmp)); + } else { + err = crypto_shash_finup(desc, &counter, 1, &okm[i]); + if (err) + goto out; + } + counter++; + prev = &okm[i]; + } + err = 0; +out: + shash_desc_zero(desc); + return err; +} + +/* + * Precompute HKDF-Extract using the master key as the input key material, then + * return an HMAC transform that is keyed using the resulting pseudorandom key. + * This can be used to derive further key material using HKDF-Expand. + */ +static struct crypto_shash *allocate_hmac_tfm(const u8 *master_key, u32 size) +{ + struct crypto_shash *hmac_tfm; + u8 prk[HKDF_HASHLEN]; + int err; + + hmac_tfm = crypto_alloc_shash(HKDF_HMAC_ALG, 0, 0); + if (IS_ERR(hmac_tfm)) { + pr_warn("fscrypt: error allocating " HKDF_HMAC_ALG ": %ld\n", + PTR_ERR(hmac_tfm)); + goto out; + } + + BUG_ON(crypto_shash_digestsize(hmac_tfm) != sizeof(prk)); + + err = hkdf_extract(hmac_tfm, master_key, size, prk); + if (err) + goto fail; + + err = crypto_shash_setkey(hmac_tfm, prk, sizeof(prk)); + if (err) + goto fail; +out: + memzero_explicit(prk, sizeof(prk)); + return hmac_tfm; + +fail: + crypto_free_shash(hmac_tfm); + hmac_tfm = ERR_PTR(err); + goto out; +} /* * fscrypt_master_key_secret - secret key material of an in-use master key @@ -914,6 +1090,8 @@ static void put_crypt_info(struct fscrypt_info *ci) kmem_cache_free(fscrypt_info_cachep, ci); } +static struct crypto_shash *essiv_hash_tfm; + static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) { struct crypto_shash *tfm = READ_ONCE(essiv_hash_tfm); From patchwork Mon Oct 23 21:40:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829704 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="WuBV7eER"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="i5E69jwc"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="GpF44tTH"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVjy6ngcz9sPt for ; Tue, 24 Oct 2017 09:01:58 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=sjkTsRN7vkj+KYOtGL2USk9pgIAwBkeMONrMi60QRKg=; b=WuBV7eER9NVzy7Zfyj0hE1kGKG eZb4rztR0E/TWZtIYg0mv/mweE7kVagNI4aTSWZgCfdx+qdWls32GKsR7y2MuGJ+qtjPutLOtoGZe IjdfZyd+edISGYd93FQVmtouR4yfJ7o/D5H9MTvqSB5zs7TztTqvFHc0GtWupriJP7cFlwuYeJdRq iu1PGXrhHBExl05NceTUKcYIBE2aemCMMd/QvzeV/9QRkROFy0vMS931stqMf0U31fHN4cPhxS80g pB1yubh0N4hkxdl3Os10DEIIzd2sMobV2chAqBQfNNKSx8lQZIOJI6RxCw+m4K0UotfZAOczf2Xyn 0Ee24cOQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6knC-0002lA-KR; Mon, 23 Oct 2017 22:01:54 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kmE-0000Pi-Am for linux-mtd@bombadil.infradead.org; Mon, 23 Oct 2017 22:00:54 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=/NNjL42227y+17N3q+8JQJQx/GzyIdYSd/kkDs6iCQs=; b=i5E69jwcCFVAG0gu2Uj3IAWQU qLA+gzq1Z+92cgY0yXXCTEQ32fRwp/JP1vqMewW8WALmDTVWxc5mCUCN/++4o0FX3e9CHQVP2zjBT 6HqHTwSHxwBPIc0R+1TnYpr1PV1WPNpJdvXCjWFCyzr6W+mnJ69msF2tQP16dTtnoau8eLeqCJYuw +NoLpvwSMTYsFdVrY18rYkrtzqHdXw3oCr67N6hkYoNzumMEU2G8ojQxHp2VaD4yXhgAl3JBhNRGn Pxk7EN3Qxbuw6VFmrdEqlSIZoFpM9t0FleZVbtp+V0tiQ3pbGvqwx2oRGC2vcHbFqGHT19xv0iNY2 Tfsx5RpNA==; Received: from mail-io0-x242.google.com ([2607:f8b0:4001:c06::242]) by casper.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUp-00076a-7H for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:42:56 +0000 Received: by mail-io0-x242.google.com with SMTP id 97so21701267iok.7 for ; Mon, 23 Oct 2017 14:42:35 -0700 (PDT) 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=/NNjL42227y+17N3q+8JQJQx/GzyIdYSd/kkDs6iCQs=; b=GpF44tTHxdqPPFgMsO1/N/6A0Wx5/j5UD7xqdhn4ZUXV0h89Re7LAZBUlAykdJnQPu dzmRoA7lg77j4TZnUkdteJL52pOy5sbsPMig+H6xLWQNe1tDy1QqBz/PyWRTtMVQvBRz QVS28dNnifcLXJCmq5unqDB7aERIAeXu/J5ifm0K4mCZxpdRycN8Ca52o2Utj+5CEbs3 ZG8zg/FqEHiN7sqrsamcU56sIJodqjZrMEwYC1WtBSFfIQ96SBSx8UF17TCaU5qsW/ux KOOoyl2kDDJ6b41IoW9as1BMJCe1C1a6lGoszy7UtRGPqwYHB9hiJNRSoOEHVHY6zXyK 3vQg== 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=/NNjL42227y+17N3q+8JQJQx/GzyIdYSd/kkDs6iCQs=; b=XEGWqMrUHckxP/ftmL8t+ClqLPTJhX+RnFuPzTz4MPkZTRFQOfGTJG5XHTCC1UqZGm tk1iBA11QlvWDWenBS8y1b1d9fiaksIlvTwOKA1W2qM95BbqStfxsmvRtiQI9aaW9/N8 6ghkVkW23Q9AKT/Ap25gNaEHDLqpulbay++l8Jms/YaeowOFuZiDTe4hYBdQTmnmfv1X j0K/yxGAr8kLbnxkdsU7h1ie29ZccGg+CDfUQbyCeE7VMSAztl3YgyHVb5lpvplQds+n 2b/xru0g9TUTs1eQeYiA8lKvguGS/0IETkgLBREusfjpBH3iQsJSZLzC6gk9W2QfFmYj HqcA== X-Gm-Message-State: AMCzsaVgk5eCHox5mQcmitc1xYm/By1b55VOivh+YF19Ne2Z1mXgCVmI wjOWHXqu7mkly2HLpZWyVd4= X-Google-Smtp-Source: ABhQp+QO1HWbcnv37YJYKloe6q+/CzEmiUuOwCFgWmigS7UXdf47wc089dYilSAnkyQHjKUyZOAjLQ== X-Received: by 10.107.163.15 with SMTP id m15mr18627859ioe.61.1508794953630; Mon, 23 Oct 2017 14:42:33 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:33 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 18/25] fscrypt: allow adding and removing keys for v2 encryption policies Date: Mon, 23 Oct 2017 14:40:51 -0700 Message-Id: <20171023214058.128121-19-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_224255_375973_90BD6697 X-CRM114-Status: GOOD ( 29.21 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on casper.infradead.org summary: Content analysis details: (-1.8 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Extend the FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY ioctls to support adding and removing keys for use by v2 encryption policies. Keys for v2 encryption policies are identified by a 16-byte "identifier", which is a cryptographic hash of the key, instead of by an 8-byte "descriptor". For FS_IOC_ADD_ENCRYPTION_KEY, the kernel calculates the key identifier and copies it to userspace. Userspace is not allowed to choose the key identifier, since the kernel would have to recalculate it anyway to verify that it is correct. For FS_IOC_REMOVE_ENCRYPTION_KEY, userspace provides the key identifier rather than the key descriptor to identify the key to be removed. For both ioctls, a type field indicates whether the old or new way of specifying keys is being used. A common structure is used, 'struct fscrypt_key_specifier', and it has some extra space just in case we have to introduce a new way to identify keys in the future. Note that keys for v1 and v2 encryption policies are both stored in ->s_master_keys, but their descriptions will be of different lengths. Therefore, they cannot be mixed up when we search for a key. For now the ioctls still always require capable(CAP_SYS_ADMIN). We'll be able to relax that soon, but only for v2 policies. Signed-off-by: Eric Biggers --- fs/crypto/keyinfo.c | 75 ++++++++++++++++++++++++++++++++++++++++---- include/uapi/linux/fscrypt.h | 2 ++ 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index e9de625ddfe4..c9e7b2b262d2 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -32,6 +32,19 @@ #define HKDF_HMAC_ALG "hmac(sha512)" #define HKDF_HASHLEN SHA512_DIGEST_SIZE +/* + * The list of contexts in which we use HKDF to derive additional keys from a + * master key. The values in this list are used as the first byte of the + * application-specific info string to guarantee that info strings are never + * repeated between contexts. + * + * Keys derived with different info strings are cryptographically isolated from + * each other --- knowledge of one derived key doesn't reveal any others. + * (This property is particularly important for the derived key used as the + * "key identifier", as that is stored in the clear.) + */ +#define HKDF_CONTEXT_KEY_IDENTIFIER 1 + /* * HKDF consists of two steps: * @@ -228,7 +241,12 @@ struct fscrypt_master_key { */ struct fscrypt_master_key_secret mk_secret; - /* Arbitrary key descriptor which was assigned by userspace */ + /* + * For v1 policy keys: an arbitrary key descriptor which was assigned by + * userspace (->descriptor). + * + * For v2 policy keys: a cryptographic hash of this key (->identifier). + */ struct fscrypt_key_specifier mk_spec; /* @@ -252,6 +270,8 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec) switch (spec->type) { case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: return FSCRYPT_KEY_DESCRIPTOR_SIZE; + case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER: + return FSCRYPT_KEY_IDENTIFIER_SIZE; } return 0; } @@ -346,7 +366,7 @@ static struct key *search_fscrypt_keyring(struct key *keyring, #define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE \ (sizeof("fscrypt-") - 1 + sizeof(((struct super_block *)0)->s_id) + 1) -#define FSCRYPT_MK_DESCRIPTION_SIZE (2 * FSCRYPT_KEY_DESCRIPTOR_SIZE + 1) +#define FSCRYPT_MK_DESCRIPTION_SIZE (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1) static void format_fs_keyring_description( char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE], @@ -550,6 +570,39 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) if (copy_from_user(secret.raw, uarg->raw, secret.size)) goto out_wipe_secret; + if (arg.key_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) { + struct crypto_shash *hmac_tfm; + + hmac_tfm = allocate_hmac_tfm(secret.raw, secret.size); + if (IS_ERR(hmac_tfm)) { + err = PTR_ERR(hmac_tfm); + goto out_wipe_secret; + } + + /* + * Hash the master key to get the key identifier, then return it + * to userspace. Specifically, we derive the key identifier + * from the master key with HKDF-SHA512, using a unique + * application-specific info string. This is preferable to a + * simple truncated SHA512 because it means we only ever use the + * master key for a single cryptographic primitive (HKDF-SHA512) + * rather than two (HKDF-SHA512 and SHA512). It *maybe* would + * be okay, but cryptographically it would be bad practice. + */ + err = hkdf_expand(hmac_tfm, HKDF_CONTEXT_KEY_IDENTIFIER, + NULL, 0, arg.key_spec.identifier, + FSCRYPT_KEY_IDENTIFIER_SIZE); + crypto_free_shash(hmac_tfm); + if (err) + goto out_wipe_secret; + + err = -EFAULT; + if (copy_to_user(uarg->key_spec.identifier, + arg.key_spec.identifier, + FSCRYPT_KEY_IDENTIFIER_SIZE)) + goto out_wipe_secret; + } + err = add_master_key(sb, &secret, &arg.key_spec); out_wipe_secret: wipe_master_key_secret(&secret); @@ -872,6 +925,10 @@ static int derive_key_aes(const u8 *master_key, * Search the current task's subscribed keyrings for a "logon" key with * description prefix:descriptor, and if found acquire a read lock on it and * return a pointer to its validated payload in *payload_ret. + * + * This is only used for v1 encryption policies, where keys are identified by + * master_key_descriptor. With newer policy versions, only the filesystem-level + * keyring (->s_master_keys) is supported. */ static struct key * find_and_lock_process_key(const char *prefix, @@ -977,17 +1034,23 @@ static int find_and_derive_key(const struct inode *inode, memcpy(mk_spec.descriptor, ctx->v1.master_key_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE); break; + case FSCRYPT_CONTEXT_V2: + mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER; + memcpy(mk_spec.identifier, ctx->v2.master_key_identifier, + FSCRYPT_KEY_IDENTIFIER_SIZE); + break; default: - return -EOPNOTSUPP; + return -EOPNOTSUPP; /* should have been checked earlier too */ } key = find_master_key(inode->i_sb, &mk_spec); if (IS_ERR(key)) { - if (key != ERR_PTR(-ENOKEY)) + if (key != ERR_PTR(-ENOKEY) || + ctx->v1.version != FSCRYPT_CONTEXT_V1) return PTR_ERR(key); /* - * As a legacy fallback, we search the current task's subscribed - * keyrings in addition to ->s_master_keys. + * As a legacy fallback for v1 policies, we search the current + * task's subscribed keyrings in addition to ->s_master_keys. */ return find_and_derive_key_legacy(inode, &ctx->v1, derived_key, derived_keysize); diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 065060b20a34..1918bdc0c6d7 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -82,10 +82,12 @@ struct fscrypt_get_policy_ex_args { struct fscrypt_key_specifier { __u32 type; #define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR 1 +#define FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER 2 __u32 reserved; union { __u8 max_specifier[32]; __u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + __u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; }; }; From patchwork Mon Oct 23 21:40:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829688 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Q83p/wn3"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="IDXC3K9+"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVPZ546sz9sPr for ; Tue, 24 Oct 2017 08:47:46 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=PvESF+OWJtsYbjGdH1GMvQnwwQOfJd/B+Qy9Qpy30BI=; b=Q83p/wn3YqZyM8uku3Otqlt1WX LjcnkKKINkLkzOciv0Ip241zmeitQ/i2Vl28OLInJdgzx/1Pu7mDKifpiN+WQz+nIdnzi9/HqMOKE ilorLj56hPCNMGRYqqrxhOjtoU26NdS38DMF6sF0hQDmEo8jiwpYDOR/apaoGRqPSh/ifIQXxUbjo Gs/4Q6lI6a4iD5oeEvyD/Cln/+sq50LlybNijsPHnRNyPF3fss4K+soisZhRCvRHdPlSnrjKF7pni z6buXemRWhTSUkEW82PaOLf71phungfAvpGNT/PTziLSkymH719blfgzctmO8KMLBaXfQR6WrvPI7 Yxq1gGOQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kZN-0001h1-16; Mon, 23 Oct 2017 21:47:37 +0000 Received: from mail-io0-x242.google.com ([2607:f8b0:4001:c06::242]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUl-0004kH-GO for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:08 +0000 Received: by mail-io0-x242.google.com with SMTP id e89so21712717ioi.11 for ; Mon, 23 Oct 2017 14:42:35 -0700 (PDT) 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=AdQYfKtecEkjrPqGJc7GmeYZ5R0tQ7+mjuXrtXhv3cE=; b=IDXC3K9+77tXXXofmuOcNbeAwtevVmewKwsRAiB89YsrMQnckXwAgh8h6yX0XHIjXv DvXdjAawMLKqBrBkyFJLTRWNO+DSung/lZx10XSgGWgiuEQq+Cmi04GeEjFUfoWJRP/a XahJ70l0iL8b1NCt4UoS/Wpvk8fiNEnk/ILec0PVv/2Sc1Q1zU0PWkyDNOpMb+FTQkCY xKfOjHS9sh03tX7bSelLE3s8MDQ1SCpUHVaUmCfWTWgVCg/OdkVLTI28up7+kWzI47ER NHcW7W+KfwtZ5BOvt6Owzf4JcSjn7vLM/wUvWm9NBdTlNNSRKoCbtv1isg647gsJBNt0 xaww== 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=AdQYfKtecEkjrPqGJc7GmeYZ5R0tQ7+mjuXrtXhv3cE=; b=Bx7xkm5w7YXkE9iXFypa3juTer+gU+B52NyaBfVdCSlhocKJZ4ezj2EX0NGbu+vemg IyqS9D1LIhsGC2dXKQZ0bIvm+ljG5GjddCRjLCPTJel7vdLLOQ7Uipus6NsCHZ4HxQqA sZFlF+srwG7WQBFreUpFArXm7bSCNEMZma60h2R93ogBM10hvVPEfzodR4Iz9p+2/PKR Mimyx51MubVV37yWlvM3ZzOs1vaJPL5N+8gFJavXeiMD5l9Aqqmel5RIZenG107+0JNE 0erubIB55ymZ008+SW+3Z4FPbz3S9/kZ19UsfMVI/L+7NjIw2lyKzTLoCuRaJ/COEcfZ 3mzQ== X-Gm-Message-State: AMCzsaX/4snOCvjmfcYjPqC5vLj7ovOqDzn9dHNTpcUlZ1GSNGNukOkU w+0vAT1/+suqAWA8FtcC+Hg= X-Google-Smtp-Source: ABhQp+TU54ewO3yKgl+t8uOEZ1bu2tAkcffEx2YRVffG1fWbzAl6jMAK2WFm/2JU3XlxAENl61l4tA== X-Received: by 10.107.132.167 with SMTP id o39mr19830735ioi.243.1508794954930; Mon, 23 Oct 2017 14:42:34 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:34 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 19/25] fscrypt: use HKDF-SHA512 to derive the per-file keys for v2 policies Date: Mon, 23 Oct 2017 14:40:52 -0700 Message-Id: <20171023214058.128121-20-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144252_237302_3A9A03B5 X-CRM114-Status: GOOD ( 25.59 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers The AES-ECB-based method we're using to derive the per-inode encryption keys is nonstandard and has a number of problems, such as being trivially reversible. Fix these problems for v2 encryption policies by deriving the keys using HKDF-SHA512 instead. The inode's nonce prefixed with a context byte is used as the application-specific info string. Supposedly, one of the reasons that HKDF wasn't used originally was because of performance concerns. However, we actually can derive on the order of 1 million keys per second, so it's likely not a bottleneck in practice. Moreover, although HKDF-SHA512 can require a bit more actual crypto work per key derivation than the old KDF, the real world performance is actually just as good or even better than the old KDF. This is because the old KDF has to allocate and key a new "ecb(aes)" transform for every key derivation (since it's keyed with the nonce rather than the master key), whereas with HKDF we simply use a cached, pre-keyed "hmac(sha512)" transform. And the old KDF often spends more time allocating its crypto transform than doing actual crypto work. Another benefit to switching to HKDF is that we no longer need to hold the raw master key in memory, but rather only an HMAC transform keyed by a pseudorandom key extracted from the master key. Of course, for the software HMAC implementation there is no security benefit, since compromising the state of the HMAC transform is equivalent to compromising the raw master key. However, there could be a security benefit if used with an HMAC implementation that holds the secret in crypto accelerator hardware rather than in main memory. Signed-off-by: Eric Biggers --- fs/crypto/fscrypt_private.h | 4 ++-- fs/crypto/keyinfo.c | 58 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index dec85c4b14a8..6d420c9a85bd 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -49,7 +49,7 @@ struct fscrypt_context_v1 { /* * A unique value used in combination with the master key to derive the - * file's actual encryption key + * file's actual encryption key, using the AES-ECB-based KDF. */ u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; }; @@ -78,7 +78,7 @@ struct fscrypt_context_v2 { /* * A unique value used in combination with the master key to derive the - * file's actual encryption key + * file's actual encryption key, using HKDF-SHA512. */ u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; }; diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index c9e7b2b262d2..ec181c4eca56 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -44,6 +44,7 @@ * "key identifier", as that is stored in the clear.) */ #define HKDF_CONTEXT_KEY_IDENTIFIER 1 +#define HKDF_CONTEXT_PER_FILE_KEY 2 /* * HKDF consists of two steps: @@ -213,10 +214,18 @@ static struct crypto_shash *allocate_hmac_tfm(const u8 *master_key, u32 size) */ struct fscrypt_master_key_secret { - /* Size of the raw key in bytes */ + /* + * For v2 policy keys: an HMAC transform keyed by the pseudorandom key + * generated by computing HKDF-Extract with the raw master key as the + * input key material. This is used to efficiently derive the per-inode + * encryption keys using HKDF-Expand later. + */ + struct crypto_shash *hmac_tfm; + + /* Size of the raw key in bytes. Set even if ->raw isn't set. */ u32 size; - /* The raw key */ + /* For v1 policy keys: the raw key. */ u8 raw[FSCRYPT_MAX_KEY_SIZE]; }; @@ -291,6 +300,7 @@ is_master_key_secret_present(const struct fscrypt_master_key_secret *secret) static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret) { + crypto_free_shash(secret->hmac_tfm); memzero_explicit(secret, sizeof(*secret)); } @@ -571,14 +581,17 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) goto out_wipe_secret; if (arg.key_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) { - struct crypto_shash *hmac_tfm; - hmac_tfm = allocate_hmac_tfm(secret.raw, secret.size); - if (IS_ERR(hmac_tfm)) { - err = PTR_ERR(hmac_tfm); + secret.hmac_tfm = allocate_hmac_tfm(secret.raw, secret.size); + if (IS_ERR(secret.hmac_tfm)) { + err = PTR_ERR(secret.hmac_tfm); + secret.hmac_tfm = NULL; goto out_wipe_secret; } + /* The raw key is no longer needed */ + memzero_explicit(secret.raw, sizeof(secret.raw)); + /* * Hash the master key to get the key identifier, then return it * to userspace. Specifically, we derive the key identifier @@ -589,10 +602,9 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) * rather than two (HKDF-SHA512 and SHA512). It *maybe* would * be okay, but cryptographically it would be bad practice. */ - err = hkdf_expand(hmac_tfm, HKDF_CONTEXT_KEY_IDENTIFIER, + err = hkdf_expand(secret.hmac_tfm, HKDF_CONTEXT_KEY_IDENTIFIER, NULL, 0, arg.key_spec.identifier, FSCRYPT_KEY_IDENTIFIER_SIZE); - crypto_free_shash(hmac_tfm); if (err) goto out_wipe_secret; @@ -871,8 +883,13 @@ static void derive_crypt_complete(struct crypto_async_request *req, int rc) } /* - * Key derivation function. This generates the derived key by encrypting the - * master key with AES-128-ECB using the nonce as the AES key. + * Legacy key derivation function. This generates the derived key by encrypting + * the master key with AES-128-ECB using the nonce as the AES key. This + * provides a unique derived key with sufficient entropy for each inode. + * However, it's nonstandard, non-extensible, doesn't evenly distribute the + * entropy from the master key, and is trivially reversible: an attacker who + * compromises a derived key can "decrypt" it to get back to the master key, + * then derive any other key. For all new code, use HKDF instead. * * The master key must be at least as long as the derived key. If the master * key is longer, then only the first 'derived_keysize' bytes are used. @@ -1078,8 +1095,21 @@ static int find_and_derive_key(const struct inode *inode, goto out_release_key; } - err = derive_key_aes(mk->mk_secret.raw, &ctx->v1, - derived_key, derived_keysize); + /* + * Derive the inode's encryption key, given the master key and the nonce + * from the inode's fscrypt_context. v1 policies used an AES-ECB-based + * KDF (Key Derivation Function). Newer policies use HKDF-SHA512, which + * fixes a number of problems with the AES-ECB-based KDF. + */ + if (ctx->v1.version == FSCRYPT_CONTEXT_V1) { + err = derive_key_aes(mk->mk_secret.raw, &ctx->v1, + derived_key, derived_keysize); + } else { + err = hkdf_expand(mk->mk_secret.hmac_tfm, + HKDF_CONTEXT_PER_FILE_KEY, + ctx->v2.nonce, sizeof(ctx->v2.nonce), + derived_key, derived_keysize); + } if (err) goto out_release_key; @@ -1275,8 +1305,8 @@ int fscrypt_get_encryption_info(struct inode *inode) goto out; /* - * This cannot be a stack buffer because it is passed to the scatterlist - * crypto API as part of key derivation. + * This cannot be a stack buffer because it may be passed to the + * scatterlist crypto API during key derivation. */ res = -ENOMEM; derived_key = kmalloc(FS_MAX_KEY_SIZE, GFP_NOFS); From patchwork Mon Oct 23 21:40:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829692 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Sc8/sKSy"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="IukNUpLi"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVRC2CXbz9sPr for ; Tue, 24 Oct 2017 08:49:11 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=6mpFpe+UPpL62PQyKOZa1IWsf96i0ezcP3LUzb2Piqo=; b=Sc8/sKSyY7DGfHr1fcXPJIds/a 626NJVn28j0O6bawXzR6VaS2/rgUDdfrDtP07bRixjfhFUjfRFw2vrYLUAIb0QVr07SjC2r7V4DR4 eJpWjGT2CKcSt3pZoEuiVH22X1qZFHXi2zHJVB2C1+F3ctRruJR8HaWtOuTwgnuHBaC87wpHjxeSK IfSWivNexnUuFQeOa/YDQXPCFsrvCvJ+Uir+HnWqA2Wlt7BlNkC/hpYteT2+6or08hdvKNMHRl6EE 2SzIwVsm2IMynq96tHhr0oXDcPfrbA871pqwyhx1NvxQ/H9fzWTRquJn1ebitiAyqvFfar0dp0JJO rS28yL2g==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kal-00031M-CX; Mon, 23 Oct 2017 21:49:03 +0000 Received: from mail-io0-x243.google.com ([2607:f8b0:4001:c06::243]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUm-0004ks-NW for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:20 +0000 Received: by mail-io0-x243.google.com with SMTP id b186so21740123iof.8 for ; Mon, 23 Oct 2017 14:42:37 -0700 (PDT) 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=UqwBPntNJGFGHEFPhT53FrUJ2990XYmdEL0ehuffT9Q=; b=IukNUpLiORswWOOlNVsNHalZYjulIr1cEtDZHqweAqMsvKVh70F4DX0eGvrnlcOM8N ZCCdPtmn827kOGSi2TZpK2hxx7jEZbrKVJZVZoJeLH9zFHi3Nx2BdyCIcUrRoQ/CSgCS 5lxhKbJj5pl7dtci0zZ9dPmvK4sEENm1Ri5YruZ+bqn5lHDu2ITge4nIsiaI0+knBB9D BbryWBODS4CA7NnxZQg9l+CpL19V6Z0GXgug+awapQfsOnzh6YpCpYbqXJ+TGLpSKaE4 F9nM16R7QoB2kK0+8n9TEisLSxDq3Gdmb8V8wya9Jvu/aZntgEivyYXHhaAj6rLqdxOg LYSQ== 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=UqwBPntNJGFGHEFPhT53FrUJ2990XYmdEL0ehuffT9Q=; b=Z+fjd+00SpOnY+DR7A2WROBWJhl3Sj4Cxpwo8zZMghF6okkVyZqpreI3oGwF5EgVTA AfziZpnEfPf6eP73Lh4ogh53qOvbmOdC9Esd124rSMgP8rfduoaUTtlia9DxMgKH+EY9 k9u3OAWQNAqKuC3SiwPbAtvETGRdM0W1EVtAmj4XHEuEhsBU41T1/dE4FKhoRAFljNIK v4MfrDPrcrvMOXp1Cwc44YZyXmKdC1+OfQiNkiKw38ZW9doVQG8RiP04WtZpriNVBYGg HDKM/HJ16TfHyhwgprDnGKo725rbcuglltYwQw2maeLQ73xDxCTp3thoJCFLylk8yrd5 lTKw== X-Gm-Message-State: AMCzsaW//mUxejTsdtivUUNovbcyxxDZtwghloNqj4Bo7mFRmGmBlz2w TH/qhft4sh4sYKcqQQeTt/g= X-Google-Smtp-Source: ABhQp+QyB7tPiBxn4LPdKlp3Q3yiZjqScE13KNDymmZrNUEb0UbB9nAoWKAtYLG3S7Qc6HZc6CNTBQ== X-Received: by 10.107.147.135 with SMTP id v129mr17984940iod.289.1508794956272; Mon, 23 Oct 2017 14:42:36 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:35 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 20/25] fscrypt: allow unprivileged users to add/remove keys for v2 policies Date: Mon, 23 Oct 2017 14:40:53 -0700 Message-Id: <20171023214058.128121-21-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144253_415465_4BF1648F X-CRM114-Status: GOOD ( 25.54 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:243 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Having the FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY ioctls be root-only is sufficient for some users of filesystem encryption, e.g. Android and Chromium OS where all the encryption keys are managed by a privileged process. However, it is not sufficient for general use where non-root users are setting up encrypted directories. If these ioctls were root-only, such users would have to continue to use process-subscribed keyrings and would continue to run into all the problems noted earlier, including visibility problems when processes running under different UIDs need to be able to access the files, and the inability to remove the key, "locking" the directory. Fortunately, we can indeed make the ioctls unprivileged, but only for v2 encryption policies and only after a few additional changes which this patch implements. First, to allow any user to add a key with filesystem-level visibility, the keys must be identified using a cryptographic hash so that users cannot add the wrong key for other users' files. We use the key_identifier for this, which is why v2 encryption policies are a requirement. Second, we charge each key a user adds to their quota for the keyrings service. Thus, a user can't cause a denial of service by adding a very large number of keys. Third, we have to be careful about when a key is allowed to be removed, given that multiple users may add the same key (although that should *not* normally be the case; it's astronomically unlikely for keys to collide by chance, so it should only happen as a result of explicit sharing or compromise). One might consider only allowing the first user who added a key to remove it, or allowing any user who knows a key to remove it. But neither of those are good enough because we don't want a user on the system who knows another user's key to be able to cause a denial of service where the former user removes the latter user's key at an inopportune time. After all, it *should* be the case that if you have an encrypted directory and you give everyone in the world the key, including malicious users on the same system, it should still be no less secure than *not* using encryption. The solution is to keep track of which users have added a key and only really remove the key once all users have removed it. However, it is tolerated that a user will be unable to remove a key, i.e. unable to "lock" their encrypted files, if another user has added the same key. But in a sense, this is actually a good thing because it will avoid providing a false notion of security where a key appears to have been "removed" when actually it's still in memory, available to any attacker who compromises the operating system kernel. Signed-off-by: Eric Biggers --- fs/crypto/crypto.c | 7 + fs/crypto/fscrypt_private.h | 1 + fs/crypto/keyinfo.c | 341 ++++++++++++++++++++++++++++++++++++++++--- include/uapi/linux/fscrypt.h | 11 +- 4 files changed, 338 insertions(+), 22 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 489c504ac20d..e57a13889689 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -469,8 +469,14 @@ static int __init fscrypt_init(void) if (err) goto fail_free_info; + err = register_key_type(&key_type_fscrypt_mk_user); + if (err) + goto fail_unregister_fscrypt_mk_type; + return 0; +fail_unregister_fscrypt_mk_type: + unregister_key_type(&key_type_fscrypt_mk); fail_free_info: kmem_cache_destroy(fscrypt_info_cachep); fail_free_ctx: @@ -494,6 +500,7 @@ static void __exit fscrypt_exit(void) kmem_cache_destroy(fscrypt_ctx_cachep); kmem_cache_destroy(fscrypt_info_cachep); unregister_key_type(&key_type_fscrypt_mk); + unregister_key_type(&key_type_fscrypt_mk_user); fscrypt_essiv_cleanup(); } diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 6d420c9a85bd..d0a63086fa95 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -235,6 +235,7 @@ extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, /* keyinfo.c */ extern struct key_type key_type_fscrypt_mk; +extern struct key_type key_type_fscrypt_mk_user; extern void __exit fscrypt_essiv_cleanup(void); /* policy.c */ diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index ec181c4eca56..1fe44983239a 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -246,9 +246,16 @@ struct fscrypt_master_key { * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again. * - * Locking: protected by key->sem. + * Locking: protected by key->sem (outer) and mk_secret_sem (inner). + * The reason for two locks is that key->sem also protects modifying + * mk_users, which ranks it above the semaphore for the keyring key + * type, which is in turn above page faults (via keyring_read). But + * sometimes filesystems call fscrypt_get_encryption_info() from within + * a transaction, which ranks it below page faults. So we need a + * separate lock which protects *just* mk_secret, not also mk_users. */ struct fscrypt_master_key_secret mk_secret; + struct rw_semaphore mk_secret_sem; /* * For v1 policy keys: an arbitrary key descriptor which was assigned by @@ -258,6 +265,19 @@ struct fscrypt_master_key { */ struct fscrypt_key_specifier mk_spec; + /* + * Keyring which contains a key of type 'key_type_fscrypt_mk_user' for + * each user who has added this key. Normally there would be just one + * user who adds a particular key, but it's possible that multiple users + * would add the same key, and we don't want to allow one user to remove + * it before the others want it removed too. + * + * This is NULL for v1 policy keys. + * + * Locking: protected by key->sem. + */ + struct key *mk_users; + /* * Length of ->mk_decrypted_inodes, plus one if mk_secret is present. * Once this goes to 0, the master key is removed from ->s_master_keys. @@ -314,6 +334,7 @@ static void move_master_key_secret(struct fscrypt_master_key_secret *dst, static void free_master_key(struct fscrypt_master_key *mk) { wipe_master_key_secret(&mk->mk_secret); + key_put(mk->mk_users); kzfree(mk); } @@ -353,9 +374,42 @@ struct key_type key_type_fscrypt_mk = { .describe = fscrypt_key_describe, }; +static int fscrypt_mk_user_key_instantiate(struct key *key, + struct key_preparsed_payload *prep) +{ + /* + * We just charge FSCRYPT_MAX_KEY_SIZE bytes to the user's key quota for + * each key, regardless of the exact key size. The amount of memory + * actually used is greater than the size of the raw key anyway. + */ + return key_payload_reserve(key, FSCRYPT_MAX_KEY_SIZE); +} + +static void fscrypt_mk_user_key_describe(const struct key *key, + struct seq_file *m) +{ + seq_puts(m, key->description); +} + +/* + * Type of key in ->mk_users. Each key of this type represents a particular + * user who has added a particular master key. + * + * Note that the name of this key type really should be something like + * ".fscrypt-user" instead of simply ".fscrypt". But the shorter name is chosen + * mainly for simplicity of presentation in /proc/keys when read by a non-root + * user. And it is expected to be rare that a key is actually added by multiple + * users, since users should keep their encryption keys confidential. + */ +struct key_type key_type_fscrypt_mk_user = { + .name = ".fscrypt", + .instantiate = fscrypt_mk_user_key_instantiate, + .describe = fscrypt_mk_user_key_describe, +}; + /* - * Search ->s_master_keys. Note that we mark the keyring reference as - * "possessed" so that we can use the KEY_POS_SEARCH permission. + * Search either ->s_master_keys or ->mk_users. Note that we mark the keyring + * reference as "possessed" so that we can use the KEY_POS_SEARCH permission. */ static struct key *search_fscrypt_keyring(struct key *keyring, struct key_type *type, @@ -378,6 +432,13 @@ static struct key *search_fscrypt_keyring(struct key *keyring, #define FSCRYPT_MK_DESCRIPTION_SIZE (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1) +#define FSCRYPT_MK_USERS_DESCRIPTION_SIZE \ + (sizeof("fscrypt-") - 1 + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \ + sizeof("-users") - 1 + 1) + +#define FSCRYPT_MK_USER_DESCRIPTION_SIZE \ + (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + sizeof(".uid.") - 1 + 10 + 1) + static void format_fs_keyring_description( char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE], const struct super_block *sb) @@ -393,6 +454,23 @@ static void format_mk_description( master_key_spec_len(mk_spec), mk_spec->max_specifier); } +static void format_mk_users_keyring_description( + char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE], + const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]) +{ + sprintf(description, "fscrypt-%*phN-users", + FSCRYPT_KEY_IDENTIFIER_SIZE, mk_identifier); +} + +static void format_mk_user_description( + char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE], + const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]) +{ + + sprintf(description, "%*phN.uid.%u", FSCRYPT_KEY_IDENTIFIER_SIZE, + mk_identifier, __kuid_val(current_fsuid())); +} + /* * Find the specified master key in ->s_master_keys. * Returns ERR_PTR(-ENOKEY) if not found. @@ -413,6 +491,80 @@ static struct key *find_master_key(struct super_block *sb, description); } +/* + * Find the current user's key in the master key's ->mk_users. + * Returns ERR_PTR(-ENOKEY) if not found. + */ +static struct key *find_master_key_user(struct fscrypt_master_key *mk) +{ + char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE]; + + format_mk_user_description(description, mk->mk_spec.identifier); + return search_fscrypt_keyring(mk->mk_users, &key_type_fscrypt_mk_user, + description); +} + +static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk) +{ + char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE]; + struct key *mk_users; + + format_mk_users_keyring_description(description, + mk->mk_spec.identifier); + + mk_users = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, + current_cred(), KEY_POS_SEARCH | + KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW, + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); + if (IS_ERR(mk_users)) + return PTR_ERR(mk_users); + + mk->mk_users = mk_users; + return 0; +} + +/* + * Give the current user a key in ->mk_users. This charges the user's quota and + * marks the master key as added by the current user, so that it cannot be + * removed by another user with the key. + */ +static int add_master_key_user(struct fscrypt_master_key *mk) +{ + char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE]; + struct key *mk_user; + int err; + + format_mk_user_description(description, mk->mk_spec.identifier); + mk_user = key_alloc(&key_type_fscrypt_mk_user, description, + current_fsuid(), current_gid(), current_cred(), + KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL); + if (IS_ERR(mk_user)) + return PTR_ERR(mk_user); + + err = key_instantiate_and_link(mk_user, NULL, 0, mk->mk_users, NULL); + key_put(mk_user); + return err; +} + +/* + * Remove the current user's key from ->mk_users, if present. + */ +static int remove_master_key_user(struct fscrypt_master_key *mk) +{ + struct key *mk_user; + int err; + + mk_user = find_master_key_user(mk); + if (IS_ERR(mk_user)) { + if (mk_user != ERR_PTR(-ENOKEY)) + return PTR_ERR(mk_user); + return 0; + } + err = key_unlink(mk->mk_users, mk_user); + key_put(mk_user); + return err; +} + static struct key * allocate_master_key(struct fscrypt_master_key_secret *secret, const struct fscrypt_key_specifier *mk_spec) @@ -429,16 +581,36 @@ allocate_master_key(struct fscrypt_master_key_secret *secret, mk->mk_spec = *mk_spec; move_master_key_secret(&mk->mk_secret, secret); + init_rwsem(&mk->mk_secret_sem); refcount_set(&mk->mk_refcount, 1); /* secret is present */ INIT_LIST_HEAD(&mk->mk_decrypted_inodes); spin_lock_init(&mk->mk_decrypted_inodes_lock); + if (mk_spec->type != FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR) { + err = allocate_master_key_users_keyring(mk); + if (err) { + key = ERR_PTR(err); + goto out_free_mk; + } + + err = add_master_key_user(mk); + if (err) { + key = ERR_PTR(err); + goto out_free_mk; + } + } + + /* + * Note that we don't charge this key to anyone's quota since it's owned + * by root, and the keys in ->mk_users are charged instead. + */ format_mk_description(description, mk_spec); key = key_alloc(&key_type_fscrypt_mk, description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), KEY_POS_SEARCH | KEY_USR_SEARCH | - KEY_USR_READ | KEY_USR_VIEW, 0, NULL); + KEY_USR_READ | KEY_USR_VIEW, + KEY_ALLOC_NOT_IN_QUOTA, NULL); if (IS_ERR(key)) goto out_free_mk; @@ -510,12 +682,31 @@ static int add_master_key(struct super_block *sb, goto out_put_key; } else { struct fscrypt_master_key *mk = key->payload.data[0]; + struct key *mk_user; bool rekey; /* Found the key in ->s_master_keys */ down_write(&key->sem); + /* + * If the current user is already in ->mk_users, then there's + * nothing to do. + */ + if (mk->mk_users) { + mk_user = find_master_key_user(mk); + if (mk_user != ERR_PTR(-ENOKEY)) { + up_write(&key->sem); + if (IS_ERR(mk_user)) { + err = PTR_ERR(mk_user); + } else { + key_put(mk_user); + err = 0; + } + goto out_put_key; + } + } + /* * Take a reference if we'll be re-adding ->mk_secret. If we * couldn't take a reference, then the key is being removed from @@ -531,9 +722,24 @@ static int add_master_key(struct super_block *sb, goto retry; } + /* Add the current user to ->mk_users */ + if (mk->mk_users) { + err = add_master_key_user(mk); + if (err) { + up_write(&key->sem); + if (rekey && + refcount_dec_and_test(&mk->mk_refcount)) + key_invalidate(key); + goto out_put_key; + } + } + /* Re-add the secret key material if needed */ - if (rekey) + if (rekey) { + down_write(&mk->mk_secret_sem); move_master_key_secret(&mk->mk_secret, secret); + up_write(&mk->mk_secret_sem); + } up_write(&key->sem); } err = 0; @@ -548,6 +754,23 @@ static int add_master_key(struct super_block *sb, * Add a master encryption key to the filesystem, causing all files which were * encrypted with it to appear "unlocked" (decrypted) when accessed. The key * can be removed later by FS_IOC_REMOVE_ENCRYPTION_KEY. + * + * When adding a key for use by v1 encryption policies, this ioctl is + * privileged, and userspace must provide the 'key_descriptor'. + * + * When adding a key for use by v2+ encryption policies, this ioctl is + * unprivileged. This is needed, in general, to allow non-root users to use + * encryption without encountering the visibility problems of process-subscribed + * keyrings and the inability to properly remove keys. This works by having + * each key identified by its cryptographically secure hash --- the + * 'key_identifier'. The cryptographic hash ensures that a malicious user + * cannot add the wrong key for a given identifier. Furthermore, each added key + * is charged to the appropriate user's quota for the keyrings service, which + * prevents a malicious user from adding too many keys. Finally, we forbid a + * user from removing a key while other users have added it too, which prevents + * a user who knows another user's key from causing a denial-of-service by + * removing it at an inopportune time. (We tolerate that a user who knows a key + * can prevent other users from removing it.) */ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) { @@ -571,9 +794,6 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) if (!valid_key_spec(&arg.key_spec)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - memset(&secret, 0, sizeof(secret)); secret.size = arg.raw_size; err = -EFAULT; @@ -613,6 +833,15 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) arg.key_spec.identifier, FSCRYPT_KEY_IDENTIFIER_SIZE)) goto out_wipe_secret; + } else { + /* + * Only root can add keys that are identified by an arbitrary + * descriptor rather than by a cryptographic hash --- since + * otherwise a malicious user could add the wrong key. + */ + err = -EACCES; + if (!capable(CAP_SYS_ADMIN)) + goto out_wipe_secret; } err = add_master_key(sb, &secret, &arg.key_spec); @@ -744,7 +973,9 @@ static int try_to_lock_encrypted_files(struct super_block *sb, } /* - * Try to remove an fscrypt master encryption key. + * Try to remove an fscrypt master encryption key. If other users have also + * added the key, we'll remove the current user's usage of the key, then return + * -EUSERS. Otherwise we'll continue on and try to actually remove the key. * * First we wipe the actual master key secret from memory, so that no more * inodes can be unlocked with it. Then, we try to evict all cached inodes that @@ -775,13 +1006,33 @@ int fscrypt_ioctl_remove_key(struct file *filp, const void __user *uarg) if (copy_from_user(&arg, uarg, sizeof(arg))) return -EFAULT; - if (memchr_inv(arg.reserved, 0, sizeof(arg.reserved))) + if (arg.flags & ~FSCRYPT_REMOVE_KEY_FLAG_ALL_USERS) + return -EINVAL; + + if (arg.reserved1) + return -EINVAL; + + if (memchr_inv(arg.reserved2, 0, sizeof(arg.reserved2))) return -EINVAL; if (!valid_key_spec(&arg.key_spec)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) + /* + * Only root can request that the key be removed no matter how many + * user(s) have added it. + */ + if ((arg.flags & FSCRYPT_REMOVE_KEY_FLAG_ALL_USERS) && + !capable(CAP_SYS_ADMIN)) + return -EACCES; + + /* + * Only root can remove keys that are identified by an arbitrary + * descriptor rather than by a cryptographic hash --- since only root + * can add such keys. + */ + if (arg.key_spec.type != FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER && + !capable(CAP_SYS_ADMIN)) return -EACCES; key = find_master_key(sb, &arg.key_spec); @@ -790,10 +1041,34 @@ int fscrypt_ioctl_remove_key(struct file *filp, const void __user *uarg) mk = key->payload.data[0]; down_write(&key->sem); + + if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) { + if (arg.flags & FSCRYPT_REMOVE_KEY_FLAG_ALL_USERS) + err = keyring_clear(mk->mk_users); + else + err = remove_master_key_user(mk); + if (err) { + up_write(&key->sem); + goto out_put_key; + } + if (mk->mk_users->keys.nr_leaves_on_tree != 0) { + /* + * Other users have still added the key too. We removed + * the current user's usage of the key if there was one, + * but we still can't remove the key itself. + */ + err = -EUSERS; + up_write(&key->sem); + goto out_put_key; + } + } + dead = false; if (is_master_key_secret_present(&mk->mk_secret)) { + down_write(&mk->mk_secret_sem); wipe_master_key_secret(&mk->mk_secret); dead = refcount_dec_and_test(&mk->mk_refcount); + up_write(&mk->mk_secret_sem); } up_write(&key->sem); if (dead) { @@ -802,6 +1077,7 @@ int fscrypt_ioctl_remove_key(struct file *filp, const void __user *uarg) } else { err = try_to_lock_encrypted_files(sb, mk); } +out_put_key: key_put(key); return err; } @@ -818,6 +1094,15 @@ EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key); * regular file in it (which can confuse the "incompletely removed" state with * absent or present). * + * In addition, for v2 policy keys we allow applications to determine, via + * ->status_flags and ->user_count, whether the key has been added by the + * current user, by other users, or by both. Most applications should not need + * this, since ordinarily only one user should know a given key. However, if a + * secret key is shared by multiple users, applications may wish to add an + * already-present key to prevent other users from removing it. This ioctl can + * be used to check whether that really is the case before the work is done to + * add the key --- which might e.g. require prompting the user for a passphrase. + * * Note: this ioctl only works with keys added to the filesystem-level keyring. * It does *not* work with keys added via the old mechanism which involved * process-subscribed keyrings. @@ -839,6 +1124,8 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) if (!valid_key_spec(&arg.key_spec)) return -EINVAL; + arg.status_flags = 0; + arg.user_count = 0; arg.reserved2 = 0; memset(arg.reserved3, 0, sizeof(arg.reserved3)); @@ -860,6 +1147,19 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) } arg.status = FSCRYPT_KEY_STATUS_PRESENT; + if (mk->mk_users) { + struct key *mk_user; + + arg.user_count = mk->mk_users->keys.nr_leaves_on_tree; + mk_user = find_master_key_user(mk); + if (!IS_ERR(mk_user)) { + arg.status_flags |= FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF; + key_put(mk_user); + } else if (mk_user != ERR_PTR(-ENOKEY)) { + err = PTR_ERR(mk_user); + goto out_release_key; + } + } err = 0; out_release_key: up_read(&key->sem); @@ -1029,11 +1329,12 @@ static int find_and_derive_key_legacy(const struct inode *inode, * Find the master key, then derive the inode's actual encryption key. * * If the master key is found in the filesystem-level keyring, then the - * corresponding 'struct key' is returned read-locked in *master_key_ret. This - * is needed because we need to hold the semaphore until we link the new - * fscrypt_info into ->mk_decrypted_inodes, but in the case where multiple tasks - * are racing to set up an inode's ->i_crypt_info, only the winner should link - * its fscrypt_info into ->mk_decrypted_inodes. + * corresponding 'struct key' is returned in *master_key_ret with + * ->mk_secret_sem read-locked. This is needed because we need to hold + * ->mk_secret_sem until we link the new fscrypt_info into + * ->mk_decrypted_inodes, but in the case where multiple tasks are racing to set + * up an inode's ->i_crypt_info, only the winner should link its fscrypt_info + * into ->mk_decrypted_inodes. */ static int find_and_derive_key(const struct inode *inode, const union fscrypt_context *ctx, @@ -1073,7 +1374,7 @@ static int find_and_derive_key(const struct inode *inode, derived_keysize); } mk = key->payload.data[0]; - down_read(&key->sem); + down_read(&mk->mk_secret_sem); /* Has the secret been removed using FS_IOC_REMOVE_ENCRYPTION_KEY? */ if (!is_master_key_secret_present(&mk->mk_secret)) { @@ -1117,7 +1418,7 @@ static int find_and_derive_key(const struct inode *inode, return 0; out_release_key: - up_read(&key->sem); + up_read(&mk->mk_secret_sem); key_put(key); return err; } @@ -1361,7 +1662,9 @@ int fscrypt_get_encryption_info(struct inode *inode) } out: if (master_key) { - up_read(&master_key->sem); + struct fscrypt_master_key *mk = master_key->payload.data[0]; + + up_read(&mk->mk_secret_sem); key_put(master_key); } if (res == -ENOKEY) diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 1918bdc0c6d7..901e87d8fb74 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -102,7 +102,10 @@ struct fscrypt_add_key_args { /* Struct passed to FS_IOC_REMOVE_ENCRYPTION_KEY */ struct fscrypt_remove_key_args { - __u64 reserved[3]; + __u32 flags; +#define FSCRYPT_REMOVE_KEY_FLAG_ALL_USERS 0x00000001 + __u32 reserved1; + __u64 reserved2[2]; struct fscrypt_key_specifier key_spec; }; @@ -117,9 +120,11 @@ struct fscrypt_get_key_status_args { #define FSCRYPT_KEY_STATUS_ABSENT 1 #define FSCRYPT_KEY_STATUS_PRESENT 2 #define FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED 3 + __u32 status_flags; +#define FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF 0x00000001 + __u32 user_count; __u32 reserved2; - - __u64 reserved3[7]; + __u64 reserved3[6]; }; #define FS_IOC_SET_ENCRYPTION_POLICY _IOR( 'f', 19, struct fscrypt_policy) From patchwork Mon Oct 23 21:40:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829689 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="BI7kk1hL"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="mOtC1K5u"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVQD0TNGz9sPr for ; Tue, 24 Oct 2017 08:48:20 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=zTxryStZyQaGOKNprXdhQJY4gSzsTx7/tOxsagFQVyk=; b=BI7kk1hLkM77BXX3M/P7Zm7iKT jmK9Rf0FznNKErA7KluqTPRZcey4j586P7+KvCjzT/j4vT0P24Q0Mk+T7kcObCCRQs8HAh9Cy6oX1 cwyjtVX4WhcNU/fIabLpFzOqcawJQ787nIyOiIvUhqtrTxwRrwypruLsvxUgD4c3Ukg3qcKxz5G2k BqaGqzCb7UofVHijMYfKmjKOE7iMiQrFAwM0ISeL1m/jxl9rWar7eqoeiifa0i/zUhB1TipVY63zz tpIMgwPYeBypWupVctErK2vPgcb4Qf0nVntPgkUyAggFpSqM+4JSoED0M1AGESF3vFmAreYmN7a33 4XaUWiUw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kZv-0002Eu-Cz; Mon, 23 Oct 2017 21:48:11 +0000 Received: from mail-io0-x244.google.com ([2607:f8b0:4001:c06::244]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUr-0004lT-Oa for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:13 +0000 Received: by mail-io0-x244.google.com with SMTP id 134so21710681ioo.0 for ; Mon, 23 Oct 2017 14:42:38 -0700 (PDT) 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=6bj+3PpKOEqnjjCfFytXcJdfqep6Tsq3tGn/CH2pnfU=; b=mOtC1K5uD1IQOUkDxmkg8LOeQg964c87AtZbg/MnR72YOTSWhPNgiIvWAoP3E5A3gy Xj7xm0j9Isa07F6HzOZyvz5v3fWGtqI1FBF+O/TLub2msFrJno9ZwtLb3KKmnycQl3gV eYcQEPqY2MXArBUjPt5WdiM89gCVnD/zqdx4ru8hotZqPhr3NOVBEFOLpDRTr7ELotIn alOkLbiBr96OnqNlsVXE4CMQm85lEFKz8HCPi6UsJzej6n5uxNGQSQq343Bs1VZqVXw9 b5nOiyyXdsTMkF4r2YqUC2P4RdDZBrg2A2ZPq11/P9L3b8wUfy9/jaF0rIWyFxF6Cvf2 qz4g== 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=6bj+3PpKOEqnjjCfFytXcJdfqep6Tsq3tGn/CH2pnfU=; b=plldar5XPeov/p7Q/Wu98mrCTm/7mp6Xqape2OVyOcXN4B6oxVJ8nWelm3YvUNhYx3 2wD6rHMaWRacmnqVCyGdnHaiYVGEa6PwwxqHIflwK+KzEe/zBR3sU2GbXhoHGyuxheQf Vqr6j5Fvqv+7ePZRKLtC+BhYAmnqTnwgo2+y6aA8TfKg6Eup8UCS5lpzf5hveXxQikSa fnAcWfTyXeoUKr/OG9jfDRH6g/F/gd6J+ta/ex9oCOW7WryshT1U65KpZxyV7DN8z2Tt qo7MXyxbMEO42dhn6xXhB0+A0cByyaRFAFblta40kprTtHNzduS7iNO35ucQ/Dgm0j/k a1TA== X-Gm-Message-State: AMCzsaU+CntvDuCql9CJGztZZhKyxBS6kaIVkEmE957W+oMZxBFgJw1z dYxcHvUA6lRlP3i2X9VkS9E= X-Google-Smtp-Source: ABhQp+RH1Lyy/9yjcppo1NO0unSUK8en9i9rBXkfes1gjNC2HRCS9wOoUhBH+z8Uj6NbiIiqVyf2dw== X-Received: by 10.107.10.82 with SMTP id u79mr19424303ioi.252.1508794957596; Mon, 23 Oct 2017 14:42:37 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.36 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:37 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 21/25] fscrypt: require that key be added when setting a v2 encryption policy Date: Mon, 23 Oct 2017 14:40:54 -0700 Message-Id: <20171023214058.128121-22-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144258_665438_EC5D1172 X-CRM114-Status: GOOD ( 16.23 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers By looking up the master keys in a filesystem-level keyring rather than in the calling processes' key hierarchy, it becomes possible for a user to set an encryption policy which refers to some key they don't actually know, then encrypt their files using that key. Cryptographically this shouldn't actually be a major problem; for one, every file will still be encrypted with a unique derived key, rather than with the master key directly. But to be on the safe side, enforce that a v2 encryption policy can only be set if the user has previously added the key, or has capable(CAP_FOWNER). We tolerate that this problem will continue to exist for v1 encryption policies, however; there is no way around that. Signed-off-by: Eric Biggers --- fs/crypto/fscrypt_private.h | 2 ++ fs/crypto/keyinfo.c | 42 ++++++++++++++++++++++++++++++++++++++++++ fs/crypto/policy.c | 6 ++++++ 3 files changed, 50 insertions(+) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index d0a63086fa95..7a0d5b6c2504 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -234,6 +234,8 @@ extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags); /* keyinfo.c */ +extern int fscrypt_verify_key_added(struct super_block *sb, + const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]); extern struct key_type key_type_fscrypt_mk; extern struct key_type key_type_fscrypt_mk_user; extern void __exit fscrypt_essiv_cleanup(void); diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 1fe44983239a..fd59f37dad10 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -851,6 +851,48 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) } EXPORT_SYMBOL_GPL(fscrypt_ioctl_add_key); +/* + * Verify that the current user has added a master key that has the given + * identifier (returns -ENOKEY if not). This is needed to prevent a user from + * encrypting their files using some other user's key which they don't actually + * know. Cryptographically speaking, it's debatable how much of a problem this + * actually would be, but it's best to just forbid it. + * + * The system administrator (CAP_FOWNER) can override this, which should be + * enough for any use cases where encryption policies are being set using keys + * that were chosen ahead of time but aren't available at the moment. + */ +int fscrypt_verify_key_added(struct super_block *sb, + const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]) +{ + struct fscrypt_key_specifier mk_spec; + struct key *key, *mk_user; + struct fscrypt_master_key *mk; + int err; + + mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER; + memcpy(mk_spec.identifier, identifier, FSCRYPT_KEY_IDENTIFIER_SIZE); + + key = find_master_key(sb, &mk_spec); + if (IS_ERR(key)) { + err = PTR_ERR(key); + goto out; + } + mk = key->payload.data[0]; + mk_user = find_master_key_user(mk); + if (IS_ERR(mk_user)) { + err = PTR_ERR(mk_user); + } else { + key_put(mk_user); + err = 0; + } + key_put(key); +out: + if (err == -ENOKEY && capable(CAP_FOWNER)) + err = 0; + return err; +} + static void evict_dentries_for_decrypted_inodes(struct fscrypt_master_key *mk) { struct fscrypt_info *ci; diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 27a391038f73..cfb404def9ed 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -170,6 +170,7 @@ static int set_encryption_policy(struct inode *inode, const union fscrypt_policy *policy) { union fscrypt_context ctx; + int err; if (!fscrypt_supported_policy(policy)) return -EINVAL; @@ -190,6 +191,11 @@ static int set_encryption_policy(struct inode *inode, */ pr_warn_once("%s (pid %d) is setting less secure v1 encryption policy; recommend upgrading to v2.\n", current->comm, current->pid); + } else { + err = fscrypt_verify_key_added(inode->i_sb, + policy->v2.master_key_identifier); + if (err) + return err; } return inode->i_sb->s_cop->set_context(inode, &ctx, From patchwork Mon Oct 23 21:40:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829697 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="E7rgLkh8"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ghlbmXXM"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVf33phxz9s0Z for ; Tue, 24 Oct 2017 08:58:34 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=N9gb03L7xCf/nc3t2SfvpUcCnIwjSZad6cYiURLME/Q=; b=E7rgLkh8q6iVFwBnEtRqC2RUFt qmf9gs/eXimhFNGWfVoYGsRCuqFv7n2RYB9TBZkVtnY3KLZb0GI7hwlqXq5QZtlvvYVq0TT5d4bE1 jtmT76YWKhuHXsQiqpy2VvcgJeIt6SPwB/d7SIcpS/WqijvCXXR7uQjw623ADO6EtriJLIaIVVK9z 03UkNtrlSA4uIFR+1ZQhom0HJwmCVJeNjCjwHDh7YJa9lp7r6ax6MIhgmV4ZXm8QbVmTP80/jIGu5 1/SvsuhbIe72+Ifcnx5g5Gg6Io22tjF5uLZfJdWe5bNWtuDjrkGASJjJroQ7o/Tkc4rL90u1KcAcn V79swf1w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kjx-0006qy-9e; Mon, 23 Oct 2017 21:58:33 +0000 Received: from mail-io0-x243.google.com ([2607:f8b0:4001:c06::243]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUr-0004mh-Nq for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:10 +0000 Received: by mail-io0-x243.google.com with SMTP id p186so21681688ioe.12 for ; Mon, 23 Oct 2017 14:42:39 -0700 (PDT) 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=3Yfs/8DKKdrc1dp/8fpKhalhfGjGCXihEUBk0IQ0evE=; b=ghlbmXXMFNKK2OeKK/bzMJgUsAkaXoq1wMkMXlFJDOvvYcMtA2Vb7XGDnfPo8OsjxJ 0iv8jAxJWQsll3arUb6se1Po7pv0yYI0TX9gCzaaKq2ClK5ymFvgfRY/GW6kcqb3g/Y/ xCJ30UgQYZDBYy0NNmbkMKjPm5zmdRIe6vVMPhXq57S5TgePt/6iF5djb2cT69Dtg9xy kfAFaBEV0OaaWvfOQNU6mQWHfCzsV4nX5jJm+obShqv+UEYlLr1uqmk6ZRf6ezqX9h/F U90783EdWzMmp6RB2nKLT0rBYTuDmocSXNGzvaBzLpbgsoQzjkSxTlwOtRRfkP/iL3jZ e1BA== 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=3Yfs/8DKKdrc1dp/8fpKhalhfGjGCXihEUBk0IQ0evE=; b=GRcgxnu4yY4jx+6ykz9+jF8ajd9NLdDEJyCdRktjZ1iZPc//cwZvt2oHZwAZeiOB1c zDWbjaMIAt15pM5QkZ/bejQOSm/dw4KjvNc9R7HNhzoboRCWztXJyzy5bwfMAd+qE+sg NgnN1R8X42XyfyHSk/1MBzQH3XSR1YzZj5pZRyZJoi/DzmFaeoS26oivBIL41yPtIRNQ HBtNh7rh8CBx0X8kR1+OhJfilZtpH1U78eG6N8PEHF0zTGtCPUfeS7ZYMlkoE3xKHLoH 37O3ub7JqO+oDzMe6hsCRwGHgYM1CM0FDbk/j47nf90ABeHupJw9QjsWfEgHE945VsgY GrVw== X-Gm-Message-State: AMCzsaX+H75M2YfjK65EhoilsYkn5zKopPlyQhMRehmxSKa61qxRb9yt Q/P22JB72K28HlGgReac32A= X-Google-Smtp-Source: ABhQp+Sf8Lydz7qTkbbn0sYc4Q4QmZ0Ai9NicxevcMM9xRJS+CAKJNchh+zsl7lFdBmQ8TOK7Cfedg== X-Received: by 10.107.37.143 with SMTP id l137mr18420094iol.104.1508794958837; Mon, 23 Oct 2017 14:42:38 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:38 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 22/25] ext4 crypto: wire up FS_IOC_GET_ENCRYPTION_POLICY_EX Date: Mon, 23 Oct 2017 14:40:55 -0700 Message-Id: <20171023214058.128121-23-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_144258_359046_DFFBBE57 X-CRM114-Status: UNSURE ( 8.95 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:243 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers FS_IOC_GET_ENCRYPTION_POLICY_EX allows filesystem encryption users to retrieve the encryption policy for files and directories that use a v2 encryption policy. Unlike the original FS_IOC_GET_ENCRYPTION_POLICY, FS_IOC_GET_ENCRYPTION_POLICY_EX is also extensible to new versions of the policy struct that may be added in the future. Signed-off-by: Eric Biggers --- fs/ext4/ioctl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index b8a6765a556f..954042f311dc 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -978,6 +978,9 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case EXT4_IOC_GET_ENCRYPTION_POLICY: return fscrypt_ioctl_get_policy(filp, (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_POLICY_EX: + return fscrypt_ioctl_get_policy_ex(filp, (void __user *)arg); + case FS_IOC_ADD_ENCRYPTION_KEY: if (!ext4_has_feature_encrypt(sb)) return -EOPNOTSUPP; @@ -1117,6 +1120,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case EXT4_IOC_SET_ENCRYPTION_POLICY: case EXT4_IOC_GET_ENCRYPTION_PWSALT: case EXT4_IOC_GET_ENCRYPTION_POLICY: + case FS_IOC_GET_ENCRYPTION_POLICY_EX: case FS_IOC_ADD_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_GET_ENCRYPTION_KEY_STATUS: From patchwork Mon Oct 23 21:40:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829702 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="a7Et9EBC"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="B6PW5JZt"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="upHOoXMz"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVjG4mshz9sPt for ; Tue, 24 Oct 2017 09:01:22 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=TGC3Fjfi45/5nMfzfyAcQ8RMgQnjjkZWyTWyc6UUY1s=; b=a7Et9EBCFoWoJ7Xkt3ywXY39xT EayuMtwDhJDgG+fACU5EkXBlpAE2qp67YkKPvWW5AgyOVIeQY8X6FBTewkgfk9UH7Bc4SHfSjYRiL wsZNIsgpvsWJm4asnJgvglydpkzorLKouskoWykgET3Q1ND5q8+UapEkET+pD1aXjmut3R/fVb7dP gC37Z9LLv8H6eALJTj9O0JRoNvBSBq9jc4OUhZDXNeS1YzhWgr4ZtelCV56syZJbab58zu/9Ivs2u Hn8ZOu0T/7FK67pRKm6CIwkUgkIK3DsFNAr3JBVHNOGEGhagtUWY3/buAo8mLg1zcmjuIikGfoXHe whtNVclg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kmY-00023t-73; Mon, 23 Oct 2017 22:01:14 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kmB-0000Bl-Vj for linux-mtd@bombadil.infradead.org; Mon, 23 Oct 2017 22:00:52 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=q4ysmxM1Tc8eT1daOT1MgVemWjX6+/LfBa3mlqqW5UI=; b=B6PW5JZtcZinuBhRat5J5t2ov yYaZRDLt+vR1q3XTsOMfjDplGQ/Wpie00Z47AP6huvY13hZiIG3VfBR8rRbH72HoJHZ7DQ6ffOnu4 sW+aDHIypgXDw/e0GMdIxYCDPjFJN47+g0U5Exh5+6WXXszwSMCId2wziv6iAIoM074r6rCSPD6ep qGQ1E8eVavGBCZ1lIOM5LS7yfgfMlP+aYgtTBy4J7SugZdufN2J807nOK6glSOdYzDkJd/eW7+XFc vAAkZQRRgF7HmSKyAgkN9o1Uas8etvVieWypsCBu4ZpwrEqhcg8qJhBZHXaDzgtsz2Vc+CAbbCk+n LrGnOk0Gw==; Received: from mail-io0-x242.google.com ([2607:f8b0:4001:c06::242]) by casper.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUu-00076w-5I for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:01 +0000 Received: by mail-io0-x242.google.com with SMTP id e89so21712887ioi.11 for ; Mon, 23 Oct 2017 14:42:41 -0700 (PDT) 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=q4ysmxM1Tc8eT1daOT1MgVemWjX6+/LfBa3mlqqW5UI=; b=upHOoXMzBopebaQdaFztRT7emgSQ3m9N/DGoH0rDp15I/217Vjv8l2lc2bIo0r5xM1 F917nKkqT4WktmiC64Z2T/gZC0CTA57BbNFAfrrmcSwFp1RfL01faY+vW7sfLDQrVsIr JVQjLKsCsPDFq9+DpN/9C4xW+6yery4+pW1vg5XxjaN5wYlEAwX3ARiAa42ypVMHFxGC X9SshHuMYLxFWa8eJx0uNfDUwXQoxJ/sRW/REbZFr94jKqTkIAavukU6QjcCEuoY8IaU MSTH5ey8FB+aWXDf/qcuUwGHt3Xw44ZP5vS4ZQjTpAKm71F4NO31XrnDi58Ja9Re9jtX 0uPQ== 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=q4ysmxM1Tc8eT1daOT1MgVemWjX6+/LfBa3mlqqW5UI=; b=SkQmupCsx4X2G2OXPH/TRZOIdxyd1XGF1jp+4dtWsvURb8/AlLxQ3Om79z3TWxJDnj 6OC9N3ho4qsPev0P/XT+jmsc0+jMjjGeHpRowfIoSivXWVbhZdZpMmQE0Te27cUKJKVc NfLr3LkOJKs6Lv2s8oEXZJcRBCZRZ5FRMZtQJr16jEol4PRKMng8viyywU1b35exDEEJ VtTLdA1yPoqtdoPOycl1x4ONOjWqLhg3/68w2xmFbkXCWyYNtybMflHh5P4FvzA+HUvq x64f+MnH8K2u9Fa5im+4Eo8JPAW1tUqAPldpt/QutuVRZRIzGupeplJlyHagDYPWzGOm V8kQ== X-Gm-Message-State: AMCzsaVmFxXp59zcpXT0Y4IMl2FDL8lSFJbwXEKBpXn2+sioQ9ODP0Bx vma4bwR0S7hwhOscPsZF40bG+4vu X-Google-Smtp-Source: ABhQp+RuKIGNC4ir0VKFmsI9dyfMpyICcYq5Bu/hz1SRAzQQT2INFz4DqV4Iy9bJ/aCZbZa7+iJAnQ== X-Received: by 10.107.186.87 with SMTP id k84mr19309825iof.121.1508794960096; Mon, 23 Oct 2017 14:42:40 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:39 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 23/25] f2fs crypto: wire up FS_IOC_GET_ENCRYPTION_POLICY_EX Date: Mon, 23 Oct 2017 14:40:56 -0700 Message-Id: <20171023214058.128121-24-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_224300_313348_A85EB1FE X-CRM114-Status: GOOD ( 12.10 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on casper.infradead.org summary: Content analysis details: (-1.8 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:242 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers FS_IOC_GET_ENCRYPTION_POLICY_EX allows filesystem encryption users to retrieve the encryption policy for files and directories that use a v2 encryption policy. Unlike the original FS_IOC_GET_ENCRYPTION_POLICY, FS_IOC_GET_ENCRYPTION_POLICY_EX is also extensible to new versions of the policy struct that may be added in the future. Signed-off-by: Eric Biggers --- fs/f2fs/file.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 0296a9594fe7..68b6ba732f25 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1887,11 +1887,6 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg) return fscrypt_ioctl_set_policy(filp, (const void __user *)arg); } -static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg) -{ - return fscrypt_ioctl_get_policy(filp, (void __user *)arg); -} - static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -2647,10 +2642,12 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return f2fs_ioc_fitrim(filp, arg); case F2FS_IOC_SET_ENCRYPTION_POLICY: return f2fs_ioc_set_encryption_policy(filp, arg); - case F2FS_IOC_GET_ENCRYPTION_POLICY: - return f2fs_ioc_get_encryption_policy(filp, arg); case F2FS_IOC_GET_ENCRYPTION_PWSALT: return f2fs_ioc_get_encryption_pwsalt(filp, arg); + case F2FS_IOC_GET_ENCRYPTION_POLICY: + return fscrypt_ioctl_get_policy(filp, (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_POLICY_EX: + return fscrypt_ioctl_get_policy_ex(filp, (void __user *)arg); case FS_IOC_ADD_ENCRYPTION_KEY: return fscrypt_ioctl_add_key(filp, (void __user *)arg); case FS_IOC_REMOVE_ENCRYPTION_KEY: @@ -2737,6 +2734,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC_SET_ENCRYPTION_POLICY: case F2FS_IOC_GET_ENCRYPTION_PWSALT: case F2FS_IOC_GET_ENCRYPTION_POLICY: + case FS_IOC_GET_ENCRYPTION_POLICY_EX: case FS_IOC_ADD_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_GET_ENCRYPTION_KEY_STATUS: From patchwork Mon Oct 23 21:40:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829729 X-Patchwork-Delegate: richard@nod.at Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="iC30hJKe"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="xRgyTAm5"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="lufl455k"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLWn13Kscz9sP1 for ; Tue, 24 Oct 2017 09:49:41 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=e3bqBYpewOor5DgNKdVf9NuezaNGjXNRtLHp4LndBVw=; b=iC30hJKelI67eeoYyN27+4GHqD q6MMa7CKjoXXnNH6Rvas2V0Z+/xV/GURKtdsSDv4hiah0cYoNXFMuG/G9Tfakhrk0c/q0M2aEmuE4 d4D0lkUIQOX+gWmN4J2tYl/6xftvUBN94t6qW7k21vtyPEBWQfa4BGP8YE4xzzX47hWcKSCdh1HlI B4WkjryHLRT6X8nTx34R9fCr06C+MskS13CrlB+SGxl38ULYtuEsX3pVvSj5kSBifUk4KcEPXGnLA Og+WFFrr0myomCa9wNlGR5FFcxbTIK/pXqAtgCk/x/1kvVM8mZj4vM/1ydRGNGsU5SWbuwTIhQlVn WsjShh6Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6lX1-0004vn-7j; Mon, 23 Oct 2017 22:49:15 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6lWy-0004up-VZ for linux-mtd@bombadil.infradead.org; Mon, 23 Oct 2017 22:49:13 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=JTvI73Oj3Dl4mvmZRRODzNdflOYA5Ch8R//atESWGDc=; b=xRgyTAm53zLYgxwYN8MSIh7WJ VEcb4ZlHunGDC7o2ks16fPLvBqPPmSz7X1p4SDIgxd3+KjpO7l1shpbqDwC2cK5qyAo/JymYFsjvb kfEEaokoGONm8Jarjg/Ypir3D7P/Dspm404oByNdcE33OFDcpt82dQGzBjNLbsWAYNT72YD8VZEcg CKVhtQE3MX+0sNEl4rVJLuZjGNljTYQca51vDSdsp4dYjgSfYd+b/2E1fsp870+rbS3j/eJ0KzTEs s1DeB+UV0cZo+CyHn/iFuNOFdmaaHBov1rd8Vzzj3UNyJg/1c/baOZLcTbXT854OmRPhwWfISXKJM hH4au/zzw==; Received: from mail-io0-x241.google.com ([2607:f8b0:4001:c06::241]) by merlin.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUz-0004Wx-SA for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:06 +0000 Received: by mail-io0-x241.google.com with SMTP id m81so21686657ioi.13 for ; Mon, 23 Oct 2017 14:42:43 -0700 (PDT) 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=JTvI73Oj3Dl4mvmZRRODzNdflOYA5Ch8R//atESWGDc=; b=lufl455kDTyzCtOLPyb4YHNopkfC/myBB5XPQwvenbfCRaK162lbyebysjlLAzfq0v wnrWP8FFOzt+t9dpjRVLqqtn9W1zCZY44cDZwkvNmh5R8mHXmPIyf9u8W6v9p1V0hmwQ eKyDE+ioUzeOEeHBengCVzvsNYsSScTfPcQvxM1lTNQCpgpDqcRjoUsHwV4Nb0GC4G/Q gVD890OziSY+W96hPwM6FxucoDf6aJUa1eoMmiQI+ZXsYsqXvRD4tGW8WjZIo6n2ZxTM cGy+qAjA7RNl44U0di4Z3yRtyfWvO1jkWfrd0wac5mcetmJcYaDOymW0v+CobyQGqMK3 q2fA== 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=JTvI73Oj3Dl4mvmZRRODzNdflOYA5Ch8R//atESWGDc=; b=ErEf3H/6EUMFT/P9SyBEIgS01qPc0bjbUNdh9i5dGpYtROrFdHPBQNvJk6/qUCD5Tv HzOF8soqJizf9mNnjozkJaPjg9bdHIdDM1o4FcFL4n31C5BJeYUbD+qpjCmO5t2tP4ug wz2AD4nNkQKe67Fi7agUZraxJYN4KF6AS9j5cN7kLB0oOA+XABfDyqz2wHZ3mZME+a+b 5r5c5u99LfYiCO/W8R6Ij8SRiwaUGlmUgQLxQSYLy3ln9GNpM9QxxctgNMEwxS5TDv44 XA8pUDdH4ND1Lix1ViRFWlLyPPA/nH+onjZUO3lw5cdAdO7Hit2ZlKxoPktw4yI7Knuj k27w== X-Gm-Message-State: AMCzsaWJkZKTnc2ECIvgx5a09C8iynvPpl16oHyj7ItO6DivavQOCDNH c1n/3Q+yA/359A+pl6NLdi2lKdUr X-Google-Smtp-Source: ABhQp+ScReiKSbXswNsep7vpcXMH2OsyA/pz5ActX2y6vakq4hkK11jTeQTIlDjGsbMneLjoLf4tRA== X-Received: by 10.107.146.134 with SMTP id u128mr18327542iod.209.1508794961361; Mon, 23 Oct 2017 14:42:41 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:40 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 24/25] ubifs crypto: wire up FS_IOC_GET_ENCRYPTION_POLICY_EX Date: Mon, 23 Oct 2017 14:40:57 -0700 Message-Id: <20171023214058.128121-25-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-Spam-Note: CRM114 invocation failed X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on merlin.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:241 listed in] [list.dnswl.org] 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers FS_IOC_GET_ENCRYPTION_POLICY_EX allows filesystem encryption users to retrieve the encryption policy for files and directories that use a v2 encryption policy. Unlike the original FS_IOC_GET_ENCRYPTION_POLICY, FS_IOC_GET_ENCRYPTION_POLICY_EX is also extensible to new versions of the policy struct that may be added in the future. Signed-off-by: Eric Biggers --- fs/ubifs/ioctl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index 09ede2d1898f..2064c01ac864 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c @@ -197,13 +197,12 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EOPNOTSUPP; #endif } - case FS_IOC_GET_ENCRYPTION_POLICY: { -#ifdef CONFIG_UBIFS_FS_ENCRYPTION + + case FS_IOC_GET_ENCRYPTION_POLICY: return fscrypt_ioctl_get_policy(file, (void __user *)arg); -#else - return -EOPNOTSUPP; -#endif - } + + case FS_IOC_GET_ENCRYPTION_POLICY_EX: + return fscrypt_ioctl_get_policy_ex(file, (void __user *)arg); case FS_IOC_ADD_ENCRYPTION_KEY: return fscrypt_ioctl_add_key(file, (void __user *)arg); @@ -231,6 +230,7 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; case FS_IOC_SET_ENCRYPTION_POLICY: case FS_IOC_GET_ENCRYPTION_POLICY: + case FS_IOC_GET_ENCRYPTION_POLICY_EX: case FS_IOC_ADD_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_GET_ENCRYPTION_KEY_STATUS: From patchwork Mon Oct 23 21:40:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 829701 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="fe/2ivKi"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="H41m1eEd"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hwUlc1Ba"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yLVhn55kHz9sPt for ; Tue, 24 Oct 2017 09:00:57 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=gQ1mIj6Kw9bVGXNlM1c6JcM0gqIGIHp3Rm8DywdSoy8=; b=fe/2ivKilpmVHQViU9Ex8i49Az unDlUI3PIHmZHnxlbyfrKmZ2SqllukVlXos6AAaCS5bfiQiLDeSLaN22QPsoVk7hc+AuvzdOfkGQL oWVMphkhxvvJomp6U0SenzKDHtbhsLDGrMhi9hGvAx3eOj9TVzZu45C8S9iuCf10dwI/pK1epTakt 1kqXYE+BzFi8jLPWfmrFOdoWq1FvJk4TfkqtYAB8NDFNDO5ZKU4HCgS+O7wURBhQxgv6LXGa3+IN+ CO+7GErRRNaKtHKVcqvkqQxykybegPdDp3iq/Nx5GdWUyZxY24/6ByEL9xy3aGOAYqs01xFPirTN4 sH1VoFUQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e6kmD-0001Yx-Bd; Mon, 23 Oct 2017 22:00:53 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kmA-0000Pi-HO for linux-mtd@bombadil.infradead.org; Mon, 23 Oct 2017 22:00:50 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=W5YAIXr5iorMF90RSHZ03a665IYaPJu1c2ghmt3hDBM=; b=H41m1eEdS3jl34mQvHOKm+5qv 8z5smEM2i1tULhEooGpJ7Xsi03y8rvcSBMi/+UYNvwu/TK3lViX0ZjNQ5Un1ojKEUfiDOkRQT1lgy y2hyYGIMIT3Qv6dMnDgl2fS76Qpxn/k2NYzYxIxZ9n6ZSpgfuH7XNA4RCkGxeSSV4jzsOc6rGMOWB VoF4FLaADK/W7uyZ+FPCRR08oTxnBDdAp9pkwVLrPnMjNT09g9JKY25gEGEoGNWFc+XTHW9ujgjL/ OCcl7cWZfQsBXhi9gpQXbb2vKWc4blkHXT9Ev5cz/VpvbYO3JO0rnMSLxqXxQF56h1jIth94vLGhr O4mswCMCw==; Received: from mail-io0-x241.google.com ([2607:f8b0:4001:c06::241]) by casper.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e6kUz-00077D-5m for linux-mtd@lists.infradead.org; Mon, 23 Oct 2017 21:43:08 +0000 Received: by mail-io0-x241.google.com with SMTP id n137so21761815iod.6 for ; Mon, 23 Oct 2017 14:42:45 -0700 (PDT) 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=W5YAIXr5iorMF90RSHZ03a665IYaPJu1c2ghmt3hDBM=; b=hwUlc1Ban8ukcpJES9TdmRodj2ZXWM4vhdbbCLVIX61zCL/L7zzT5DA3AD+C4j1RFX tN8UfWfnYeEXyEcgzaO5POeHX89TDTLectUUuRuNWyMEilUEosP3OUcPZWUeiccSJRrr dm+xWFpsUzkQX4HVZIYmXjy9ejHDhTaMZxt5Nbq0DciWTtrVQzUnJ2CLkkPUyJDwvLhD 1FB6xH8NVJFSB3R599+BcNHIbbrkxQ8j941+LT6R7cLbluqZnRxC0kUXXMKdGqwRS/k/ n6Cv9ZZe8Ovt9IAhkhsVnQ43gBHPjTZF+1uVCIIvXguIYdpiQBy4to1QBJm+v5gruFR+ 509w== 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=W5YAIXr5iorMF90RSHZ03a665IYaPJu1c2ghmt3hDBM=; b=XscAeNlF3AyEp056jzfg4k2C8xx6IyVnrC6a0plpOXRIBz2Rzc/xJcTjdjJi0MZFO/ q/T5Lo+5L63gi0+2HCYEl/bHf3nz4XMo9ijSSvby1tIe46Wk2dbAr5+jKJTYxlpTmYmU YSTcnlNa4BeEp3BQM9kS8O6ijFlV0yjouYHcAlhoR77Aqo5OoBBBYBegs3tJEFNsrfqR o5qFdZQr/DRTf/D9tlJYmHQ1KUYk8cjMtewQQOo64xy8j7t8wjSUxID/dDOVTEHDQXWs 7z/EQfjJfvHTEzZDhflnrcuI02QlcMbKpkLWBmlOldakpafHE5jethXV9ReQ0EpdSvxi dPFw== X-Gm-Message-State: AMCzsaWi/JGcK/SjktXSnRMW9ifXmb6KsACMXVDC8byXLER+psWvEaDx NwnBwwHS3msBSKruzvddBW4= X-Google-Smtp-Source: ABhQp+SbRWGjRLrDRH+e2Dtw91aiuz2YnYahLxaMLCaD+ge9ZjC/A4+Q1RR3tIRS8rFXf5okVtGatA== X-Received: by 10.107.8.100 with SMTP id 97mr18830179ioi.83.1508794962915; Mon, 23 Oct 2017 14:42:42 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.175.88]) by smtp.gmail.com with ESMTPSA id i63sm3558482ioi.68.2017.10.23.14.42.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 23 Oct 2017 14:42:42 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [RFC PATCH 25/25] fscrypt: document the new ioctls and policy version Date: Mon, 23 Oct 2017 14:40:58 -0700 Message-Id: <20171023214058.128121-26-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0.rc0.271.g36b669edcc-goog In-Reply-To: <20171023214058.128121-1-ebiggers3@gmail.com> References: <20171023214058.128121-1-ebiggers3@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171023_224305_571431_92937137 X-CRM114-Status: GOOD ( 41.00 ) X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on casper.infradead.org summary: Content analysis details: (-1.8 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4001:c06:0:0:0:241 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryo Hashimoto , Gwendal Grignou , "Theodore Y . Ts'o" , Eric Biggers , linux-api@vger.kernel.org, Nick Desaulniers , linux-f2fs-devel@lists.sourceforge.net, keyrings@vger.kernel.org, linux-mtd@lists.infradead.org, Michael Halcrow , Sarthak Kukreti , linux-fsdevel@vger.kernel.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Update the fscrypt documentation file to catch up to all the latest changes, including the new ioctls to manage master encryption keys in the filesystem-level keyring, the support for v2 encryption policies, and the new key derivation function. Signed-off-by: Eric Biggers --- Documentation/filesystems/fscrypt.rst | 565 ++++++++++++++++++++++++++++------ 1 file changed, 472 insertions(+), 93 deletions(-) diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst index f12956f3f1f8..f2d0ff2269f3 100644 --- a/Documentation/filesystems/fscrypt.rst +++ b/Documentation/filesystems/fscrypt.rst @@ -72,6 +72,9 @@ Online attacks fscrypt (and storage encryption in general) can only provide limited protection, if any at all, against online attacks. In detail: +Side-channel attacks +~~~~~~~~~~~~~~~~~~~~ + fscrypt is only resistant to side-channel attacks, such as timing or electromagnetic attacks, to the extent that the underlying Linux Cryptographic API algorithms are. If a vulnerable algorithm is used, @@ -80,29 +83,86 @@ attacker to mount a side channel attack against the online system. Side channel attacks may also be mounted against applications consuming decrypted data. -After an encryption key has been provided, fscrypt is not designed to -hide the plaintext file contents or filenames from other users on the -same system, regardless of the visibility of the keyring key. -Instead, existing access control mechanisms such as file mode bits, -POSIX ACLs, LSMs, or mount namespaces should be used for this purpose. -Also note that as long as the encryption keys are *anywhere* in -memory, an online attacker can necessarily compromise them by mounting -a physical attack or by exploiting any kernel security vulnerability -which provides an arbitrary memory read primitive. - -While it is ostensibly possible to "evict" keys from the system, -recently accessed encrypted files will remain accessible at least -until the filesystem is unmounted or the VFS caches are dropped, e.g. -using ``echo 2 > /proc/sys/vm/drop_caches``. Even after that, if the -RAM is compromised before being powered off, it will likely still be -possible to recover portions of the plaintext file contents, if not -some of the encryption keys as well. (Since Linux v4.12, all -in-kernel keys related to fscrypt are sanitized before being freed. -However, userspace would need to do its part as well.) - -Currently, fscrypt does not prevent a user from maliciously providing -an incorrect key for another user's existing encrypted files. A -protection against this is planned. +Unauthorized file access +~~~~~~~~~~~~~~~~~~~~~~~~ + +After an encryption key has been added, fscrypt does not hide the +plaintext file contents or filenames from other users on the same +system. Instead, existing access control mechanisms such as file mode +bits, POSIX ACLs, LSMs, or namespaces should be used for this purpose. + +(For the reasoning behind this, understand that while the key is +added, the confidentiality of the data, from the perspective of the +system itself, is *not* protected by the mathematical properties of +encryption but rather only by the correctness of the kernel. +Therefore, any encryption-specific access control checks would merely +be enforced by kernel *code* and therefore would be largely redundant +with the wide variety of access control mechanisms already available.) + +Kernel compromise +~~~~~~~~~~~~~~~~~ + +An attacker who compromises the system enough to read from arbitrary +memory, e.g. by mounting a physical attack or by exploiting a kernel +security vulnerability, can compromise all encryption keys that are +currently in use. + +However, fscrypt does allow an encryption key to be removed from the +kernel, which may protect it from later compromise. + +In more detail, the FS_IOC_REMOVE_ENCRYPTION_KEY ioctl will wipe a +master encryption key from kernel memory. Moreover, it will try to +evict all cached inodes which had been "unlocked" using the key, +thereby wiping their derived encryption keys and making them once +again appear "locked", i.e. in ciphertext or encrypted form. + +However, FS_IOC_REMOVE_ENCRYPTION_KEY has some limitations: + +- Derived keys for in-use files will *not* be removed or wiped. + Therefore, for maximum effect, userspace should close the relevant + encrypted files and directories before removing a master key, as + well as kill any processes whose working directory is in an affected + encrypted directory. + +- The kernel cannot magically wipe copies of the master key(s) that + userspace might have as well. Therefore, userspace must wipe all + copies of the master key(s) it makes as well. Naturally, the same + also applies to all higher levels in the key hierarchy, e.g. to all + key(s) that are used to wrap or derive the fscrypt master keys. + Userspace should also follow other security precautions such as + mlock()ing memory containing keys to prevent it from being swapped + out. + +- In general, decrypted contents and filenames in the kernel VFS + caches are freed but not wiped. Therefore, portions thereof may be + recoverable from freed memory, even after the corresponding key(s) + were wiped. To partially solve this, you may enable page poisoning + by enabling CONFIG_PAGE_POISONING in your kernel config and adding + page_poison=1 to your kernel command line. However, that has a + performance cost. + +- Secret keys might still exist in CPU registers, in crypto + accelerator hardware (if used by the crypto API to provide any of + the algorithms), or in other places not explicitly considered here. + +Limitations of v1 policies +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The original encryption policy version (which we call "v1") had some +weaknesses with respect to online attacks: + +- There was no verification that the provided master key was correct. + Therefore, malicious users could associate the wrong key with + encrypted files, even files to which they had only read-only access. + +- A compromise of any file's derived encryption key also compromised + the master key it was derived from. + +- Non-root users could not securely remove encryption keys. + +All the above problems are fixed with v2 encryption policies +(:c:type:`fscrypt_policy_v2`). For this reason, it's recommended to +use v2 encryption policies for all new encrypted directories. Key hierarchy ============= @@ -167,19 +227,27 @@ master keys or to support rotating master keys. Instead, the master keys may be wrapped in userspace, e.g. as done by the `fscrypt `_ tool. -The current KDF encrypts the master key using the 16-byte nonce as an -AES-128-ECB key. The output is used as the derived key. If the -output is longer than needed, then it is truncated to the needed -length. Truncation is the norm for directories and symlinks, since -those use the CTS-CBC encryption mode which requires a key half as -long as that required by the XTS encryption mode. - -Note: this KDF meets the primary security requirement, which is to -produce unique derived keys that preserve the entropy of the master -key, assuming that the master key is already a good pseudorandom key. -However, it is nonstandard and has some problems such as being -reversible, so it is generally considered to be a mistake! It may be -replaced with HKDF or another more standard KDF in the future. +A different KDF is used depending on the encryption policy version: + +For v1 encryption policies, the KDF is somewhat ad-hoc: we encrypt the +master key with AES-128-ECB using the file's 16-byte nonce as the AES +key, and the resulting ciphertext is used as the derived key. If the +master key is longer than the derived key, then only the needed prefix +of the ciphertext is used. Truncation is the norm for directories and +symlinks, since those use the CTS-CBC encryption mode which requires a +key half as long as that required by the XTS encryption mode. + +For v2 encryption policies, the KDF is HKDF-SHA512. HKDF is preferred +to the AES-based KDF because HKDF is standardized and has a number of +desirable properties such as being nonreversible and evenly +distributing the entropy from the master key. To derive a file's +encryption key using HKDF, the master key is used as the "input key +material", a fixed value is used as the "salt", and the file's 16-byte +nonce prefixed with a context byte is used as the +"application-specific information string". (A fixed salt is used +because there is no random salt available on a per-master-key basis, +and the master keys should already be good pseudorandom keys that are +long enough to make dictionary attacks infeasible.) Encryption modes and usage ========================== @@ -249,21 +317,38 @@ Setting an encryption policy The FS_IOC_SET_ENCRYPTION_POLICY ioctl sets an encryption policy on an empty directory or verifies that a directory or regular file already has the specified encryption policy. It takes in a pointer to a -:c:type:`struct fscrypt_policy`, defined as follows:: - - #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 +:c:type:`struct fscrypt_policy_v1` or a :c:type:`struct +fscrypt_policy_v2`, defined as follows:: - struct fscrypt_policy { + #define FSCRYPT_POLICY_VERSION_LEGACY 0 + #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 + struct fscrypt_policy_v1 { __u8 version; __u8 contents_encryption_mode; __u8 filenames_encryption_mode; __u8 flags; __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; }; + #define fscrypt_policy fscrypt_policy_v1 + + #define FSCRYPT_POLICY_VERSION_2 2 + #define FSCRYPT_KEY_IDENTIFIER_SIZE 16 + struct fscrypt_policy_v2 { + __u8 version; + __u8 contents_encryption_mode; + __u8 filenames_encryption_mode; + __u8 flags; + __u8 reserved[4]; + __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; + }; This structure must be initialized as follows: -- ``version`` must be 0. +- ``version`` must be FSCRYPT_POLICY_VERSION_LEGACY (0) if the struct + is :c:type:`fscrypt_policy_v1` or FSCRYPT_POLICY_VERSION_2 (2) if + the struct is :c:type:`fscrypt_policy_v2`. (Note: we refer to the + legacy policy version as "v1", though its version number was really + 0.) For new encrypted directories, use v2 policies. - ``contents_encryption_mode`` and ``filenames_encryption_mode`` must be set to constants from ```` which identify the @@ -276,15 +361,25 @@ This structure must be initialized as follows: identifies the amount of NUL-padding to use when encrypting filenames. If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32 (0x3). -- ``master_key_descriptor`` specifies how to find the master key in - the keyring; see `Adding keys`_. It is up to userspace to choose a - unique ``master_key_descriptor`` for each master key. The e4crypt - and fscrypt tools use the first 8 bytes of +- For v2 encryption policies, ``reserved`` must be zeroed. + +- For v1 encryption policies, ``master_key_descriptor`` specifies how + to find the master key in a keyring; see `Adding keys`_. It is up + to userspace to choose a unique ``master_key_descriptor`` for each + master key. The e4crypt and fscrypt tools use the first 8 bytes of ``SHA-512(SHA-512(master_key))``, but this particular scheme is not required. Also, the master key need not be in the keyring yet when FS_IOC_SET_ENCRYPTION_POLICY is executed. However, it must be added before any files can be created in the encrypted directory. + For v2 encryption policies, ``master_key_descriptor`` has been + replaced with ``master_key_identifier``, which is longer and cannot + be arbitrarily chosen. Instead, the key must first be added using + FS_IOC_ADD_ENCRYPTION_KEY, as described in `Adding keys`_. Then, + the ``key_spec.identifier`` the kernel returned in the + :c:type:`struct fscrypt_add_key_args` must be used as the + ``master_key_identifier`` in the ``struct fscrypt_policy_v2``. + If the file is not yet encrypted, then FS_IOC_SET_ENCRYPTION_POLICY verifies that the file is an empty directory. If so, the specified encryption policy is assigned to the directory, turning it into an @@ -300,6 +395,15 @@ policy exactly matches the actual one. If they match, then the ioctl returns 0. Otherwise, it fails with EEXIST. This works on both regular files and directories, including nonempty directories. +When a v2 encryption policy is assigned to a directory, it is also +required that either the specified key has been added by the current +user, or the caller has CAP_FOWNER in the initial user namespace. +(This is needed to prevent a user from encrypting their data with +another user's key.) The key must remain added while +FS_IOC_SET_ENCRYPTION_POLICY is executing. However, if the new +encrypted directory does not need to be accessed immediately, then the +key can be removed right away afterwards. + Note that the ext4 filesystem does not allow the root directory to be encrypted, even if it is empty. Users who want to encrypt an entire filesystem with one key should consider using dm-crypt instead. @@ -312,7 +416,9 @@ FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors: - ``EEXIST``: the file is already encrypted with an encryption policy different from the one specified - ``EINVAL``: an invalid encryption policy was specified (invalid - version, mode(s), or flags) + version, mode(s), or flags; or reserved bits were set) +- ``ENOKEY``: a v2 encryption policy was specified, but the key with + the specified ``master_key_identifier`` has not been added - ``ENOTDIR``: the file is unencrypted and is a regular file, not a directory - ``ENOTEMPTY``: the file is unencrypted and is a nonempty directory @@ -331,25 +437,82 @@ FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors: Getting an encryption policy ---------------------------- -The FS_IOC_GET_ENCRYPTION_POLICY ioctl retrieves the :c:type:`struct -fscrypt_policy`, if any, for a directory or regular file. See above -for the struct definition. No additional permissions are required -beyond the ability to open the file. +Two ioctls are available to get a file's encryption policy: + +- FS_IOC_GET_ENCRYPTION_POLICY_EX +- FS_IOC_GET_ENCRYPTION_POLICY + +The extended (_EX) version of the ioctl is more general and is +recommended to use when possible. However, on older kernels only the +original ioctl is available. Applications should try the extended +version, and if it fails with ENOTTY fall back to the original +version. + +Preferred method +~~~~~~~~~~~~~~~~ + +The FS_IOC_GET_ENCRYPTION_POLICY_EX ioctl retrieves the encryption +policy, if any, for a directory or regular file. No additional +permissions are required beyond the ability to open the file. It +takes in a pointer to a buffer formatted as a :c:type:`struct +fscrypt_get_policy_ex_args`, defined as follows:: + + struct fscrypt_get_policy_ex_args { + __u64 size; + union { + __u8 version; + struct fscrypt_policy_v1 v1; + struct fscrypt_policy_v2 v2; + } policy; + }; + +The caller must initialize ``size`` to the size of the buffer in +bytes, including both the ``size`` field and the space available for +the policy struct. It is recommended to use ``sizeof(struct +fscrypt_get_policy_ex_args)``. + +On successful return, ``size`` is set to the actual number of bytes +returned, including both the ``size`` field and the actual size of the +returned policy struct. In addition, the ``version`` field should be +used to determine the actual policy version returned. Note that the +version code for the "v1" policy is actually 0 +(FSCRYPT_POLICY_VERSION_LEGACY). -FS_IOC_GET_ENCRYPTION_POLICY can fail with the following errors: +FS_IOC_GET_ENCRYPTION_POLICY_EX can fail with the following errors: - ``EINVAL``: the file is encrypted, but it uses an unrecognized - encryption context format + encryption policy version; or, an invalid ``size`` was provided - ``ENODATA``: the file is not encrypted -- ``ENOTTY``: this type of filesystem does not implement encryption +- ``ENOTTY``: this type of filesystem does not implement encryption, + or this kernel is too old to support FS_IOC_GET_ENCRYPTION_POLICY_EX + (try FS_IOC_GET_ENCRYPTION_POLICY instead) - ``EOPNOTSUPP``: the kernel was not configured with encryption support for this filesystem +- ``EOVERFLOW``: the file is encrypted and uses a recognized + encryption policy version, but the policy struct does not fit into + the provided buffer Note: if you only need to know whether a file is encrypted or not, on most filesystems it is also possible to use the FS_IOC_GETFLAGS ioctl and check for FS_ENCRYPT_FL, or to use the statx() system call and check for STATX_ATTR_ENCRYPTED in stx_attributes. +Legacy method +~~~~~~~~~~~~~ + +The FS_IOC_GET_ENCRYPTION_POLICY ioctl can also retrieve the +encryption policy, if any, for a directory or regular file. However, +unlike the extended version (FS_IOC_GET_ENCRYPTION_POLICY_EX), +FS_IOC_GET_ENCRYPTION_POLICY only supports the original policy +version. It takes in a pointer directly to a :c:type:`struct +fscrypt_policy_v1` rather than a :c:type:`struct +fscrypt_get_policy_ex_args`. + +The error codes for FS_IOC_GET_ENCRYPTION_POLICY are the same as those +for FS_IOC_GET_ENCRYPTION_POLICY_EX, except that +FS_IOC_GET_ENCRYPTION_POLICY also returns ``EINVAL`` if the file is +encrypted using a newer encryption policy version. + Getting the per-filesystem salt ------------------------------- @@ -365,8 +528,97 @@ generate and manage any needed salt(s) in userspace. Adding keys ----------- -To provide a master key, userspace must add it to an appropriate -keyring using the add_key() system call (see: +Preferred method +~~~~~~~~~~~~~~~~ + +The FS_IOC_ADD_ENCRYPTION_KEY ioctl adds a master encryption key to +the filesystem, making all files on the filesystem which were +encrypted using that key appear "unlocked", i.e. in plaintext form. +It takes in a pointer to a :c:type:`struct fscrypt_add_key_args`, +defined as follows:: + + struct fscrypt_add_key_args { + __u32 raw_size; + __u32 reserved1; + __u64 reserved2[2]; + struct fscrypt_key_specifier key_spec; + __u8 raw[]; + }; + + struct fscrypt_key_specifier { + __u32 type; + #define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR 1 + #define FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER 2 + __u32 reserved; + union { + __u8 max_specifier[32]; + __u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; + __u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; + }; + }; + +:c:type:`struct fscrypt_add_key_args` must be initialized as follows: + +- ``raw_size`` must be the size of the ``raw`` key provided, in bytes. + +- If the key is being added for use by v1 encryption policies, then + ``key_spec.type`` must contain FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR, and + ``key_spec.descriptor`` must contain the descriptor of the key being + added, corresponding to the value in the ``master_key_descriptor`` + field of :c:type:`struct fscrypt_policy_v1`. To add this type of + key, the calling process must have the CAP_SYS_ADMIN capability in + the initial user namespace. + + Alternatively, if the key is being added for use by v2 encryption + policies, then ``key_spec.type`` must contain + FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER, and ``key_spec.identifier`` is an + *output* field which the kernel fills in with a cryptographic hash + of the key. To add this type of key, the calling process does not + need any privileges. However, the number of keys that can be added + is limited by the user's quota for the keyrings service (see + ``Documentation/security/keys/core.rst``). + +- ``raw`` is a variable-length field which must contain the actual + key, ``raw_size`` bytes long. + +- All reserved fields must be zeroed. + +FS_IOC_ADD_ENCRYPTION_KEY can fail with the following errors: + +- ``EACCES``: FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR was specified, but the + caller does not have the CAP_SYS_ADMIN capability in the initial + user namespace +- ``EDQUOT``: the key quota for this user would be exceeded by adding + the key +- ``EINVAL``: invalid key size or key specifier type, or reserved bits + were set +- ``ENOTTY``: this type of filesystem does not implement encryption +- ``EOPNOTSUPP``: the kernel was not configured with encryption + support for this filesystem, or the filesystem superblock has not + had encryption enabled on it + +Legacy method +~~~~~~~~~~~~~ + +For v1 encryption policies, a master encryption key can also be +provided by adding it to a process-subscribed keyring, e.g. to a +session keyring, or to a user keyring if the user keyring is linked +into the session keyring. + +This method is deprecated (and not supported for v2 encryption +policies) for several reasons. First, it cannot be used in +combination with FS_IOC_REMOVE_ENCRYPTION_KEY (see `Removing keys`_), +so for removing a key a workaround such as keyctl_unlink() in +combination with ``sync; echo 2 > /proc/sys/vm/drop_caches`` would +have to be used. Second, it doesn't match the fact that the +locked/unlocked status of encrypted files (i.e. whether they appear to +be in plaintext form or in ciphertext form) is global. This mismatch +has caused much confusion as well as real problems when processes +running under different UIDs, such as a ``sudo`` command, need to +access encrypted files. + +Nevertheless, to add a key to one of the process-subscribed keyrings, +the add_key() system call can be used (see: ``Documentation/security/keys/core.rst``). The key type must be "logon"; keys of this type are kept in kernel memory and cannot be read back by userspace. The key description must be "fscrypt:" @@ -391,26 +643,143 @@ with a filesystem-specific prefix such as "ext4:". However, the filesystem-specific prefixes are deprecated and should not be used in new programs. -There are several different types of keyrings in which encryption keys -may be placed, such as a session keyring, a user session keyring, or a -user keyring. Each key must be placed in a keyring that is "attached" -to all processes that might need to access files encrypted with it, in -the sense that request_key() will find the key. Generally, if only -processes belonging to a specific user need to access a given -encrypted directory and no session keyring has been installed, then -that directory's key should be placed in that user's user session -keyring or user keyring. Otherwise, a session keyring should be -installed if needed, and the key should be linked into that session -keyring, or in a keyring linked into that session keyring. - -Note: introducing the complex visibility semantics of keyrings here -was arguably a mistake --- especially given that by design, after any -process successfully opens an encrypted file (thereby setting up the -per-file key), possessing the keyring key is not actually required for -any process to read/write the file until its in-memory inode is -evicted. In the future there probably should be a way to provide keys -directly to the filesystem instead, which would make the intended -semantics clearer. +Removing keys +------------- + +The FS_IOC_REMOVE_ENCRYPTION_KEY ioctl can be used to remove a master +encryption key from the kernel, wiping the corresponding secrets from +memory and causing any files which were "unlocked" with the key to +appear "locked" again. It takes in a pointer to a :c:type:`struct +fscrypt_remove_key_args`, defined as follows:: + + struct fscrypt_remove_key_args { + __u32 flags; + #define FSCRYPT_REMOVE_KEY_FLAG_ALL_USERS 0x00000001 + __u32 reserved1; + __u64 reserved2[2]; + struct fscrypt_key_specifier key_spec; + }; + +This structure must be initialized as follows: + +- ``flags`` can contain the following flags: + + - ``FSCRYPT_REMOVE_KEY_FLAG_ALL_USERS`` specifies that the key + should be removed even if it has also been added by other users. + Specifying this flag requires the CAP_SYS_ADMIN capability in + the initial user namespace. + +- The key to remove is specified by ``key_spec``: + + - To remove a key used by v1 encryption policies, set + ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR and fill + in ``key_spec.descriptor``. To remove this type of key, the + calling process must have the CAP_SYS_ADMIN capability in the + initial user namespace. + + - To remove a key used by v2 encryption policies, set + ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER and fill + in ``key_spec.identifier``. To remove this type of key, no + privileges are needed. However, users can only remove keys that + they added themselves, subject to privileged override with + FSCRYPT_REMOVE_KEY_FLAG_ALL_USERS. + +- All reserved fields must be zeroed. + +FS_IOC_REMOVE_ENCRYPTION_KEY can fail with the following errors: + +- ``EACCES``: The FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR key specifier type + and/or the FSCRYPT_REMOVE_KEY_FLAG_ALL_USERS flag was specified, but + the caller does not have the CAP_SYS_ADMIN capability in the initial + user namespace +- ``EBUSY``: the master key secret was wiped from memory, but some + files which were unlocked with it are still in use. Such files + could not be locked, nor could their per-file keys be wiped from + memory. The ioctl may be retried later to re-attempt locking the + remaining files. +- ``EINVAL``: invalid flags or key specifier type, or reserved bits + were set +- ``ENOKEY``: the key is not present or has already been removed +- ``ENOTTY``: this type of filesystem does not implement encryption +- ``EOPNOTSUPP``: the kernel was not configured with encryption + support for this filesystem, or the filesystem superblock has not + had encryption enabled on it +- ``EUSERS``: the key cannot be removed because other users have added + it too + +Before using this ioctl, please read the `Kernel compromise`_ section +for a discussion of the security goals and limitations of this ioctl. + +Getting key status +------------------ + +The FS_IOC_GET_ENCRYPTION_KEY_STATUS ioctl retrieves the status of a +master encryption key. It takes in a pointer to a :c:type:`struct +fscrypt_get_key_status_args`, defined as follows:: + + struct fscrypt_get_key_status_args { + /* input */ + __u64 reserved1[3]; + struct fscrypt_key_specifier key_spec; + + /* output */ + __u32 status; + #define FSCRYPT_KEY_STATUS_ABSENT 1 + #define FSCRYPT_KEY_STATUS_PRESENT 2 + #define FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED 3 + __u32 status_flags; + #define FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF 0x00000001 + __u32 user_count; + __u32 reserved2; + __u64 reserved3[6]; + }; + +The caller must zero ``reserved1``, then fill in ``key_spec``: + + - To get the status of a key for v1 encryption policies, set + ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR and fill + in ``key_spec.descriptor``. + + - To get the status of a key for v2 encryption policies, set + ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER and fill + in ``key_spec.identifier``. + +On success, 0 is returned and the kernel fills in the output fields: + +- ``status`` indicates whether the key is absent, present, or + incompletely removed. Incompletely removed means that the master + secret has been removed, but some files are still in use; i.e., + FS_IOC_REMOVE_ENCRYPTION_KEY returned EBUSY. + +- ``status_flags`` can contain the following flags: + + - ``FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF`` indicates that the key + has added by the current user. This is only set for keys + identified by ``identifier`` rather than by ``descriptor``. + +- ``user_count`` specifies the number of users who have added the key. + This is only set for keys identified by ``identifier`` rather than + by ``descriptor``. + +FS_IOC_GET_ENCRYPTION_KEY_STATUS can fail with the following errors: + +- ``EINVAL``: invalid key specifier type, or reserved bits were set +- ``ENOTTY``: this type of filesystem does not implement encryption +- ``EOPNOTSUPP``: the kernel was not configured with encryption + support for this filesystem, or the filesystem superblock has not + had encryption enabled on it + +Among other use cases, FS_IOC_GET_ENCRYPTION_KEY_STATUS might be +useful for determining whether the key for a given encrypted directory +needs to be added before prompting the user for the passphrase needed +to derive the key. + +FS_IOC_GET_ENCRYPTION_KEY_STATUS can only get the status of keys in +the filesystem-level keyring, i.e. the keyring managed by +FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY. It cannot +get the status of a key that has only been added for use by v1 +encryption policies using the legacy mechanism involving +process-subscribed keyrings. Access semantics ================ @@ -459,7 +828,7 @@ Without the key Some filesystem operations may be performed on encrypted regular files, directories, and symlinks even before their encryption key has -been provided: +been added, or after their encryption key has been removed: - File metadata may be read, e.g. using stat(). @@ -524,20 +893,20 @@ Encryption context ------------------ An encryption policy is represented on-disk by a :c:type:`struct -fscrypt_context`. It is up to individual filesystems to decide where -to store it, but normally it would be stored in a hidden extended -attribute. It should *not* be exposed by the xattr-related system -calls such as getxattr() and setxattr() because of the special -semantics of the encryption xattr. (In particular, there would be -much confusion if an encryption policy were to be added to or removed -from anything other than an empty directory.) The struct is defined -as follows:: +fscrypt_context_v1` or a :c:type:`struct fscrypt_context_v2`. It is +up to individual filesystems to decide where to store it, but normally +it would be stored in a hidden extended attribute. It should *not* be +exposed by the xattr-related system calls such as getxattr() and +setxattr() because of the special semantics of the encryption xattr. +(In particular, there would be much confusion if an encryption policy +were to be added to or removed from anything other than an empty +directory.) These structs are defined as follows:: - #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 #define FS_KEY_DERIVATION_NONCE_SIZE 16 - struct fscrypt_context { - u8 format; + #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8 + struct fscrypt_context_v1 { + u8 version; u8 contents_encryption_mode; u8 filenames_encryption_mode; u8 flags; @@ -545,12 +914,22 @@ as follows:: u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; }; -Note that :c:type:`struct fscrypt_context` contains the same -information as :c:type:`struct fscrypt_policy` (see `Setting an -encryption policy`_), except that :c:type:`struct fscrypt_context` -also contains a nonce. The nonce is randomly generated by the kernel -and is used to derive the inode's encryption key as described in -`Per-file keys`_. + #define FSCRYPT_KEY_IDENTIFIER_SIZE 16 + struct fscrypt_context_v2 { + u8 version; + u8 contents_encryption_mode; + u8 filenames_encryption_mode; + u8 flags; + u8 reserved[4]; + u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; + u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE]; + }; + +Note that the context structs contain the same information as the +corresponding policy structs (see `Setting an encryption policy`_), +except that the context structs also contain a nonce. The nonce is +randomly generated by the kernel and is used to derive the inode's +encryption key as described in `Per-file keys`_. Data path changes -----------------