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]; }; };