From patchwork Wed Aug 21 06:42:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "boojin.kim" X-Patchwork-Id: 11105697 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 156A813A4 for ; Wed, 21 Aug 2019 06:43:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BCB1A233A0 for ; Wed, 21 Aug 2019 06:43:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="GaaiRsWl" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727887AbfHUGnV (ORCPT ); Wed, 21 Aug 2019 02:43:21 -0400 Received: from mailout4.samsung.com ([203.254.224.34]:52553 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727448AbfHUGmV (ORCPT ); Wed, 21 Aug 2019 02:42:21 -0400 Received: from epcas2p3.samsung.com (unknown [182.195.41.55]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20190821064215epoutp048d58db974b56e7343997aa3eea02b982~83PmzHAUw1235612356epoutp04Y for ; Wed, 21 Aug 2019 06:42:15 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20190821064215epoutp048d58db974b56e7343997aa3eea02b982~83PmzHAUw1235612356epoutp04Y DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1566369735; bh=3tBehBqI5ol47OnqdVD6jgOstGMohbizIgAlADES1Zs=; h=From:To:Cc:Subject:Date:References:From; b=GaaiRsWlI1HQ+VPFn8n7o+m/5QhZkKeV/KwPb73HsbPoVy1YgBylkgwcn5NAjybql KJTGVvx2TPImiU3vAXwkS670dV43HOMuvh5Iq3nEoZsqeFe3KHfhRMOaxbcamuuteA GVEuFNtGXscBmdDL+JcFE6t3Ox81n+7bCDVHo6so= Received: from epsnrtp1.localdomain (unknown [182.195.42.162]) by epcas2p3.samsung.com (KnoxPortal) with ESMTP id 20190821064214epcas2p3a80d3627a4d4a89ca522e4a1df39ce34~83PlsBNAp0925009250epcas2p3k; Wed, 21 Aug 2019 06:42:14 +0000 (GMT) Received: from epsmges2p1.samsung.com (unknown [182.195.40.184]) by epsnrtp1.localdomain (Postfix) with ESMTP id 46Cykq5d85zMqYlr; Wed, 21 Aug 2019 06:42:11 +0000 (GMT) Received: from epcas2p4.samsung.com ( [182.195.41.56]) by epsmges2p1.samsung.com (Symantec Messaging Gateway) with SMTP id A0.CD.04156.3C7EC5D5; Wed, 21 Aug 2019 15:42:11 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas2p4.samsung.com (KnoxPortal) with ESMTPA id 20190821064211epcas2p43ed73f4fd126bcc5b470c9136db6aabc~83PjGS6jA1664116641epcas2p4w; Wed, 21 Aug 2019 06:42:11 +0000 (GMT) Received: from epsmgms1p2new.samsung.com (unknown [182.195.42.42]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20190821064211epsmtrp1d58d3b97286205f84ed9e32b917d7d97~83PjFHVz_2011020110epsmtrp1H; Wed, 21 Aug 2019 06:42:11 +0000 (GMT) X-AuditID: b6c32a45-df7ff7000000103c-3c-5d5ce7c3e480 Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2new.samsung.com (Symantec Messaging Gateway) with SMTP id F3.D2.03638.3C7EC5D5; Wed, 21 Aug 2019 15:42:11 +0900 (KST) Received: from KORDO035251 (unknown [12.36.165.204]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20190821064210epsmtip2a3dce3779191a3b2627b21e3a9f6c08f~83PimYZXg2145821458epsmtip2C; Wed, 21 Aug 2019 06:42:10 +0000 (GMT) From: "boojin.kim" To: "'Herbert Xu'" , "'David S. Miller'" , , Cc: "'Herbert Xu'" , "'David S. Miller'" , "'Eric Biggers'" , "'Theodore Y. Ts'o'" , "'Chao Yu'" , "'Jaegeuk Kim'" , "'Andreas Dilger'" , "'Theodore Ts'o'" , , "'Mike Snitzer'" , "'Alasdair Kergon'" , "'Jens Axboe'" , "'Krzysztof Kozlowski'" , "'Kukjin Kim'" , "'Jaehoon Chung'" , "'Ulf Hansson'" , , , , , , , , , , , Subject: [PATCH 1/9] crypt: Add diskcipher Date: Wed, 21 Aug 2019 15:42:10 +0900 Message-ID: <003d01d557eb$8f6ca210$ae45e630$@samsung.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 14.0 Thread-Index: AdVX6IuE1WJuT0BpQ1eJ5qpUVMZ+sg== Content-Language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA01Tf0wTZxjO17teT2eXW+3ct05nd1MjmELbrfixgDHOuYvyB4sjS0wJXsoN mP21Xos/tkw2sANlK5oskdIBbqOGLoi0RImjxNAOpuNHIoMIo3OZMGMZTBFrcFPW9krGf8/7 vM/zfe+TNy+JyTwSBVlmtnM2M2ukidX4pVAaUoXu6AvVoRMq9HChGkft1/sw9H3ERaCfvxoU Ic9wFY6Ccw1i1Nb9L4ZORdejqXY3hm4+doqR6/YMhoaHL0qQ//aYGAUntqFbvy2KUH3jJIFu fPM2ijbGcNQdvIajkSseAoWXXACdHe4RIWfHQ4BO1C5KUH/beztfZDpbx0VMVeAwc+nqZmZk 0MH4fTUEMznWTTCB744zPzQ/EDGfDfyIMX/3jBLMl50+wDzwv5y/5oAxp5RjizmbkjMbLMVl 5pJcet/+ojeLdFlqjUqTjbbTSjNr4nLp3Xn5qj1lxnh2WlnOGh1xKp/leTpzR47N4rBzylIL b8+lOWux0arRWDN41sQ7zCUZBovpDY1ardXFlQeNpUMTvxLW8AA44qqbxivAUAs4CVaRkHod Pu34NI5XkzKqC8CKvvuEUMwDOB6ZkwhFDMC6jmZs2eKt/AMTGkEAw7FYyn8XwKb2mCShIqht MNDvSzbkVBOAY5G55MMY9VQCp+Z78YRqLZUO6xpOihMYpzbDgdHGuJskpVQ2vHBOkaCl1HPw Wv1UUo5RG+HlWU9qDCXsGpxJppBTGfBOZFIkaOSwocaZ0tSQ8Mm0VsC7YZv7tEjAa2G0v1Mi YAW863Km8HE46v02mRlStQAOPF5uvAbdf34OErNhVBpsv5KZgJB6FYYnUqM9C6tDTyQCLYXV Tplg3AS/nh8RCbQC3qv9RKAZ6L0/iNWBV9wrMrpXZHSvyOL+/9tmgPvAOs7Km0o4XmvVrFy3 HyQvI/2tLnB2KK8XUCSg10gX9fpCmZgt54+aegEkMVouPeI5UCiTFrNHj3E2S5HNYeT4XqCL b+A0pnjeYInfmdlepNFps7LU2Tqky9Ii+gVp4JlxvYwqYe3cIY6zcrZln4hcpagArfo9eR/U L0Q/XPJypwos5KMc37m+vzaob75fcJ1e+sId+iXKlru858PrGjetf2k+2GHY+o9l78YZo39X yxbyzLFo5uzs+QvvXn1UGaE2zBItW/f2VBWogjda3zEc1s3J0zKro/tyFj7afu9iw62Pf/Lv DNRPN3Vv2bX/YOXl3w/tqDLQOF/KatIxG8/+ByJqADcvBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrLIsWRmVeSWpSXmKPExsWy7bCSvO7h5zGxBgfOiFl8/dLBYrH+1DFm i9V3+9ksTk89y2Qx53wLi8Xed7NZLdbu+cNs0f1KxuLJ+lnMFjd+tbFa9D9+zWxx/vwGdotN j6+xWuy9pW1x/95PJouZ8+6wWVxa5G7xat43Fos9e0+yWFzeNYfN4sj/fkaLGef3MVm0bfzK aNHa85Pd4vjacAdJjy0rbzJ5tGwu99h2QNXj8tlSj02rOtk87lzbw+axeUm9x+4Fn5k8ms4c ZfZ4v+8qm0ffllWMHp83yQXwRHHZpKTmZJalFunbJXBlnLt1m63gyBnGiv4JT1kaGM8tZexi 5OSQEDCRWNb8iLmLkYtDSGA3o8SWZ/tZIBJSElvb9zBD2MIS91uOsEIUPWeUeHl3GTtIgk1A W2Lz8VWMIAkRgYWMEm9W72QDSTALTOOQ2PVBHMQWFtCSmDC7ixXEZhFQlThzdR5QMwcHr4Cl xLqFUiBhXgFBiZMzn7CAhJkF9CTaNjJCTJGX2P52DtQNChI7zr4Gi4sAlTy/e4cJokZEYnZn G/MERsFZSCbNQpg0C8mkWUg6FjCyrGKUTC0ozk3PLTYsMMpLLdcrTswtLs1L10vOz93ECE4E Wlo7GE+ciD/EKMDBqMTDu+NmdKwQa2JZcWXuIUYJDmYlEd6KOVGxQrwpiZVVqUX58UWlOanF hxilOViUxHnl849FCgmkJ5akZqemFqQWwWSZODilGhg5+OPbT+ysuTUlSDVhZonmBo1eWX5f o7OpKim3Y+9u3H3fTmPtX6HJHlLJz7yKLofwxjcuvLm9frv8mXcf2gUu8Jr1l/VmeS5MEqqd WPx2R/6E/J9XApn755xd8vf4jbCcG/2LftkmxEVMXBPB5qm78mR/97/zAXulVv649X999O+K Hl3vE9uVWIozEg21mIuKEwElvNaVAAMAAA== X-CMS-MailID: 20190821064211epcas2p43ed73f4fd126bcc5b470c9136db6aabc X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20190821064211epcas2p43ed73f4fd126bcc5b470c9136db6aabc References: Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Diskcipher supports cryptographic operations of inline crypto engines like FMP. Inline crypto engine refers to hardware and solutions implemented to encrypt data stored in storage device. When encrypting using the FMP, Additional control is required to carry and maintain the crypto information between the encryption user(fscrypt, DM-crypt) and FMP driver. Diskcipher provides this control. Diskcipher is a symmetric key cipher in linux crypto API to support FMP. FMP are registered with the cihper algorithm that uses diskcipher. Diskcipher has three major steps. The first step is to assign a cipher and set the key. The second step is to pass the cipher through the BIO to the storage driver. The third step is to get the cipher from BIO and request a crypt to FMP algorithm. In the first step, encryption users such as fscrypt or dm-crypt allocate/release a diskcipher and set key into the diskcipher. Diskcipher provides allocate(), free(), and setkey() that are similar to existing ciphers. In the second step, BIO is used to pass the diskcipher to the storage driver. The BIO submitters such as ext4, f2fs and DM-crypt set diskcipher to BIO. Diskcipher provides the set () API for this. In the third step, the storage driver extracts the diskcipher from the BIO and requests the actual encryption behavior to inline crypto engine driver. Diskcipher provides get() and crypt() APIs for this. Cc: Herbert Xu Cc: David S. Miller Signed-off-by: Boojin Kim --- crypto/Kconfig | 9 ++ crypto/Makefile | 1 + crypto/diskcipher.c | 349 ++++++++++++++++++++++++++++++++++++++++++++ crypto/testmgr.c | 157 ++++++++++++++++++++ include/crypto/diskcipher.h | 245 +++++++++++++++++++++++++++++++ include/linux/crypto.h | 1 + 6 files changed, 762 insertions(+) create mode 100644 crypto/diskcipher.c create mode 100644 include/crypto/diskcipher.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 455a335..382d43a 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1636,6 +1636,15 @@ config CRYPTO_TWOFISH_AVX_X86_64 See also: +config CRYPTO_DISKCIPHER + bool "Diskcipher support" + default n + help + Disk cipher algorithm + + This cipher supports the crypt operation of the block host device + that has inline crypto engine. + comment "Compression" config CRYPTO_DEFLATE diff --git a/crypto/Makefile b/crypto/Makefile index 0d2cdd5..71df76a 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -165,6 +165,7 @@ obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o obj-$(CONFIG_CRYPTO_OFB) += ofb.o obj-$(CONFIG_CRYPTO_ECC) += ecc.o +obj-$(CONFIG_CRYPTO_DISKCIPHER) += diskcipher.o ecdh_generic-y += ecdh.o ecdh_generic-y += ecdh_helper.o diff --git a/crypto/diskcipher.c b/crypto/diskcipher.c new file mode 100644 index 0000000..ffe95a5 --- /dev/null +++ b/crypto/diskcipher.c @@ -0,0 +1,349 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2017 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +static int crypto_diskcipher_check(struct bio *bio) +{ + struct crypto_diskcipher *ci = NULL; + struct inode *inode = NULL; + struct page *page = NULL; + + if (!bio) { + pr_err("%s: doesn't exist bio\n", __func__); + return 0; + } + + /* enc without fscrypt */ + ci = bio->bi_aux_private; + if (!ci->inode) + return 0; + if (ci->algo == 0) + return 0; + + page = bio->bi_io_vec[0].bv_page; + if (!page || PageAnon(page) || !page->mapping || !page->mapping->host) + return 0; + + inode = page->mapping->host; + if (ci->inode != inode) { + pr_err("%s: fails to invalid inode\n", __func__); + return -EINVAL; + } + + if (!fscrypt_has_encryption_key(inode)) { + pr_err("%s: fails to invalid key\n", __func__); + return -EINVAL; + } + + ci = fscrypt_get_diskcipher(inode); + if (!ci) { + pr_err("%s: fails to invalid crypto info\n", __func__); + return -EINVAL; + } else if ((bio->bi_aux_private != ci) && + !(bio->bi_flags & REQ_OP_DISCARD)) { + pr_err("%s: fails to async crypto info\n", __func__); + return -EINVAL; + } + return 0; +} + +struct crypto_diskcipher *crypto_diskcipher_get(struct bio *bio) +{ + struct crypto_diskcipher *diskc = NULL; + + if (!bio || !virt_addr_valid(bio)) { + pr_err("%s: Invalid bio:%pK\n", __func__, bio); + return NULL; + } + if (bio->bi_opf & REQ_CRYPT) { + if (bio->bi_aux_private) { + if (!crypto_diskcipher_check(bio)) { + diskc = bio->bi_aux_private; + } else { + pr_err("%s: fail to check diskcipher bio:%pK\n", + __func__, bio); + diskc = ERR_PTR(-EINVAL); + } + } else { + pr_err("%s: no diskcipher on bio:%pK\n", + __func__, bio); + diskc = ERR_PTR(-EINVAL); + } + } + + return diskc; +} + +static inline void *bio_has_crypt(struct bio *bio) +{ + if (bio) + if (bio->bi_opf & REQ_CRYPT) + return bio->bi_aux_private; + return NULL; +} + +bool crypto_diskcipher_blk_mergeble(struct bio *bio1, struct bio *bio2) +{ + if (!bio_has_crypt(bio1) && !bio_has_crypt(bio2)) + return true; + + if (bio_has_crypt(bio1) == bio_has_crypt(bio2)) { + struct crypto_diskcipher *tfm1 = bio1->bi_aux_private; + struct crypto_diskcipher *tfm2 = bio2->bi_aux_private; + + /* no inode for DM-crypt and DM-default-key */ + if (!tfm1->inode) + return true; + + if ((tfm1->ivmode == IV_MODE_DUN) && + (tfm2->ivmode == IV_MODE_DUN)) { + if (bio_dun(bio1) && bio_dun(bio2) && + (bio_end_dun(bio1) == bio_dun(bio2))) + return true; + } else if ((tfm1->ivmode == IV_MODE_LBA) && + (tfm2->ivmode == IV_MODE_LBA)) { + return true; + } + } + return false; +} + +void crypto_diskcipher_set(struct bio *bio, struct crypto_diskcipher *tfm, + const struct inode *inode, u64 dun) +{ + if (bio && tfm) { + bio->bi_opf |= REQ_CRYPT; + bio->bi_aux_private = tfm; + tfm->inode = (struct inode *)inode; + if (dun) + bio->bi_iter.bi_dun = dun; + } +} + +int crypto_diskcipher_setkey(struct crypto_diskcipher *tfm, const char *in_key, + unsigned int key_len, bool persistent) +{ + struct crypto_tfm *base = crypto_diskcipher_tfm(tfm); + struct diskcipher_alg *cra = __crypto_diskcipher_alg(base->__crt_alg); + int ret = -EINVAL; + struct inode *inode = tfm->inode; + + if (cra) + ret = cra->setkey(tfm, in_key, key_len, persistent); + else + pr_err("%s: doesn't exist cra. base:%pK", __func__, base); + + tfm->ivmode = IV_MODE_LBA; + if (!persistent && inode) { + /* check the filesystem for fscrypt */ + if (inode->i_sb) + if (inode->i_sb->s_type) + if (!strcmp(inode->i_sb->s_type->name, "f2fs")) + tfm->ivmode = IV_MODE_DUN; + } + return ret; +} + +int crypto_diskcipher_clearkey(struct crypto_diskcipher *tfm) +{ + struct crypto_tfm *base = crypto_diskcipher_tfm(tfm); + struct diskcipher_alg *cra = __crypto_diskcipher_alg(base->__crt_alg); + int ret = -EINVAL; + + if (cra) + ret = cra->clearkey(tfm); + else + pr_err("%s: doesn't exist cra. base:%pK", __func__, base); + + return ret; +} + +int crypto_diskcipher_set_crypt(struct crypto_diskcipher *tfm, void *req) +{ + struct crypto_tfm *base = crypto_diskcipher_tfm(tfm); + struct diskcipher_alg *cra = NULL; + int ret = -EINVAL; + + if (!base) { + pr_err("%s: doesn't exist base. tfm:%pK", __func__, tfm); + goto out; + } + + cra = __crypto_diskcipher_alg(base->__crt_alg); + if (!cra) { + pr_err("%s: doesn't exist cra. base:%pK\n", __func__, base); + goto out; + } + + ret = cra->crypt(tfm, req); + if (ret) + pr_err("%s fails ret:%d, cra:%pK\n", __func__, ret, cra); +out: + return ret; +} + +int crypto_diskcipher_clear_crypt(struct crypto_diskcipher *tfm, void *req) +{ + struct crypto_tfm *base = crypto_diskcipher_tfm(tfm); + struct diskcipher_alg *cra = NULL; + int ret = -EINVAL; + + if (!base) { + pr_err("%s: doesn't exist base, tfm:%pK\n", __func__, tfm); + goto out; + } + + cra = __crypto_diskcipher_alg(base->__crt_alg); + if (!cra) { + pr_err("%s: doesn't exist cra. base:%pK\n", __func__, base); + goto out; + } + + ret = cra->clear(tfm, req); + if (ret) + pr_err("%s fails ret:%d, cra:%pK\n", __func__, ret, cra); +out: + return ret; +} + +int diskcipher_do_crypt(struct crypto_diskcipher *tfm, + struct diskcipher_test_request *req) +{ + struct crypto_tfm *base = crypto_diskcipher_tfm(tfm); + struct diskcipher_alg *cra = __crypto_diskcipher_alg(base->__crt_alg); + int ret = -EINVAL; + + if (!cra) { + pr_err("%s: doesn't exist cra. base:%pK\n", __func__, base); + return ret; + } + + if (cra->do_crypt) + ret = cra->do_crypt(tfm, req); + if (ret) + pr_err("%s fails ret:%d", __func__, ret); + return ret; +} + +static int crypto_diskcipher_init_tfm(struct crypto_tfm *base) +{ + struct crypto_diskcipher *tfm = __crypto_diskcipher_cast(base); + struct diskcipher_alg *alg = crypto_diskcipher_alg(tfm); + + if (alg->init) + alg->init(tfm); + return 0; +} + +unsigned int crypto_diskcipher_extsize(struct crypto_alg *alg) +{ + return alg->cra_ctxsize + + (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1)); +} + +static void crypto_diskcipher_show(struct seq_file *m, struct crypto_alg *alg) +{ + seq_puts(m, "type : diskcipher\n"); +} + +static const struct crypto_type crypto_diskcipher_type = { + .extsize = crypto_diskcipher_extsize, + .init_tfm = crypto_diskcipher_init_tfm, +#ifdef CONFIG_PROC_FS + .show = crypto_diskcipher_show, +#endif + .maskclear = ~CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_MASK, + .type = CRYPTO_ALG_TYPE_DISKCIPHER, + .tfmsize = offsetof(struct crypto_diskcipher, base), +}; + +#define DISKC_NAME "-disk" +#define DISKC_NAME_SIZE (5) +#define DISKCIPHER_MAX_IO_MS (1000) +struct crypto_diskcipher *crypto_alloc_diskcipher(const char *alg_name, + u32 type, u32 mask, bool force) +{ + int alg_name_len; + + if (!force) + return crypto_alloc_tfm(alg_name, + &crypto_diskcipher_type, type, mask); + + alg_name_len = strlen(alg_name); + if (alg_name_len + DISKC_NAME_SIZE < CRYPTO_MAX_ALG_NAME) { + char diskc_name[CRYPTO_MAX_ALG_NAME]; + + strscpy(diskc_name, alg_name, alg_name_len); + strcat(diskc_name, DISKC_NAME); + return crypto_alloc_tfm(diskc_name, + &crypto_diskcipher_type, type, mask); + } + return NULL; +} + +void crypto_free_diskcipher(struct crypto_diskcipher *tfm) +{ + crypto_destroy_tfm(tfm, crypto_diskcipher_tfm(tfm)); +} + +int crypto_register_diskcipher(struct diskcipher_alg *alg) +{ + struct crypto_alg *base = &alg->base; + + base->cra_type = &crypto_diskcipher_type; + base->cra_flags = CRYPTO_ALG_TYPE_DISKCIPHER; + return crypto_register_alg(base); +} + +void crypto_unregister_diskcipher(struct diskcipher_alg *alg) +{ + crypto_unregister_alg(&alg->base); +} + +int crypto_register_diskciphers(struct diskcipher_alg *algs, int count) +{ + int i, ret; + + for (i = 0; i < count; i++) { + ret = crypto_register_diskcipher(algs + i); + if (ret) + goto err; + } + return 0; + +err: + for (--i; i >= 0; --i) + crypto_unregister_diskcipher(algs + i); + return ret; +} + +void crypto_unregister_diskciphers(struct diskcipher_alg *algs, int count) +{ + int i; + + for (i = count - 1; i >= 0; --i) + crypto_unregister_diskcipher(algs + i); +} diff --git a/crypto/testmgr.c b/crypto/testmgr.c index d990eba..348dafcb 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -2291,6 +2292,146 @@ static int test_aead(const char *driver, int enc, return 0; } +#if defined(CONFIG_CRYPTO_DISKCIPHER) +static int __test_diskcipher(struct crypto_diskcipher *tfm, int enc, + const struct cipher_testvec *template, + unsigned int tcount, const int align_offset) +{ + const char *algo = + crypto_tfm_alg_driver_name(crypto_diskcipher_tfm(tfm)); + unsigned int i, j; + char *q; + struct scatterlist sg[8]; + struct scatterlist sgout[8]; + const char *e = (enc == ENCRYPT) ? "encryption" : "decryption"; + void *data; + char iv[MAX_IVLEN]; + char *xbuf[XBUFSIZE]; + char *xoutbuf[XBUFSIZE]; + int ret = -ENOMEM; + unsigned int ivsize = crypto_diskcipher_ivsize(tfm); + struct diskcipher_test_request req; + const char *input, *result; + + if (testmgr_alloc_buf(xbuf)) + goto out_nobuf; + + if (testmgr_alloc_buf(xoutbuf)) + goto out_nooutbuf; + + j = 0; + for (i = 0; i < tcount; i++) { + if (template[i].np && !template[i].also_non_np) + continue; + + if (template[i].fips_skip) + continue; + + if (template[i].iv) + memcpy(iv, template[i].iv, ivsize); + else + memset(iv, 0, MAX_IVLEN); + + input = enc ? template[i].ptext : template[i].ctext; + result = enc ? template[i].ctext : template[i].ptext; + j++; + ret = -EINVAL; + if (WARN_ON(align_offset + template[i].len > PAGE_SIZE)) + goto out; + + ret = crypto_diskcipher_setkey(tfm, template[i].key, + template[i].klen, 0); + if (ret == -ENOKEY) { + pr_err("alg: diskcipher: no support %d keylen for %s. skip it\n", + template[i].klen, algo); + continue; + } else if (ret) { + pr_err("alg: diskcipher: setkey failed on test %d for %s\n", + j, algo); + goto out; + } + + data = xbuf[0]; + data += align_offset; + memcpy(data, input, template[i].len); + sg_init_one(&sg[0], data, template[i].len); + + data = xoutbuf[0]; + data += align_offset; + sg_init_one(&sgout[0], data, template[i].len); + + diskcipher_request_set_crypt(&req, sg, sgout, + template[i].len, iv, enc ? 1 : 0); + ret = diskcipher_do_crypt(tfm, &req); + if (ret) { + pr_err("alg: diskcipher: %s failed on test %d for %s: ret=%d\n", + e, j, algo, -ret); + goto out; + } + + q = data; + if (memcmp(q, result, template[i].len)) { + pr_err("alg: diskcipher: Test %d failed (invalid result) on %s for %s\n", + j, e, algo); + hexdump(q, template[i].len); + ret = -EINVAL; + goto out; + } + } + ret = 0; + +out: + testmgr_free_buf(xoutbuf); +out_nooutbuf: + testmgr_free_buf(xbuf); +out_nobuf: + return ret; +} + +static int test_diskcipher(struct crypto_diskcipher *tfm, int enc, + const struct cipher_testvec *template, + unsigned int tcount) +{ + int ret; + + ret = __test_diskcipher(tfm, enc, template, tcount, 0); + if (ret) + return ret; + + /* test unaligned buffers, check with one byte offset */ + ret = __test_diskcipher(tfm, enc, template, tcount, 1); + if (ret) + return ret; + + return 0; +} + +static int alg_test_diskcipher(const struct alg_test_desc *desc, + const char *driver, u32 type, u32 mask) +{ + struct crypto_diskcipher *tfm; + const struct cipher_test_suite *suite = &desc->suite.cipher; + int err = 0; + + tfm = crypto_alloc_diskcipher(driver, type | CRYPTO_ALG_INTERNAL, + mask, 0); + if (!tfm || IS_ERR(tfm)) { + pr_err("alg: diskcipher: Failed to load transform for %s: %ld\n", + driver, PTR_ERR(tfm)); + return PTR_ERR(tfm); + } + + err = test_diskcipher(tfm, ENCRYPT, suite->vecs, suite->count); + if (err) + goto out; + + err = test_diskcipher(tfm, DECRYPT, suite->vecs, suite->count); +out: + crypto_free_diskcipher(tfm); + return err; +} +#endif + static int alg_test_aead(const struct alg_test_desc *desc, const char *driver, u32 type, u32 mask) { @@ -4029,6 +4170,14 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .cipher = __VECS(aes_cbc_tv_template) }, +#if defined(CONFIG_CRYPTO_DISKCIPHER) + }, { + .alg = "cbc(aes)-disk", + .test = alg_test_diskcipher, + .suite = { + .cipher = __VECS(aes_cbc_tv_template) + } +#endif }, { .alg = "cbc(anubis)", .test = alg_test_skcipher, @@ -5035,6 +5184,14 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .cipher = __VECS(aes_xts_tv_template) } +#if defined(CONFIG_CRYPTO_DISKCIPHER) + }, { + .alg = "xts(aes)-disk", + .test = alg_test_diskcipher, + .suite = { + .cipher = __VECS(aes_xts_tv_template) + } +#endif }, { .alg = "xts(camellia)", .generic_driver = "xts(ecb(camellia-generic))", diff --git a/include/crypto/diskcipher.h b/include/crypto/diskcipher.h new file mode 100644 index 0000000..a0a9879 --- /dev/null +++ b/include/crypto/diskcipher.h @@ -0,0 +1,245 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2017 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _DISKCIPHER_H_ +#define _DISKCIPHER_H_ + +#include +#include + +struct diskcipher_alg; + +enum iv_mode { + IV_MODE_LBA, /* dm-dcrypt/ext4 uses it for more blk merge */ + IV_MODE_DUN, /* f2fs should use it for garbeage colloection */ +}; + +struct crypto_diskcipher { + u32 algo; + unsigned int ivsize; + struct inode *inode; + /* for crypto_free_req_diskcipher */ + atomic_t status; + struct crypto_tfm base; + enum iv_mode ivmode; +}; + +struct diskcipher_test_request { + unsigned int cryptlen; + const u8 *iv; + struct scatterlist *src; + struct scatterlist *dst; + bool enc; +}; + +/** + * struct diskcipher_alg - disk cipher definition + * for inline crypto engine on disk host device + * + * @setkey + * @clearkey + * @crypt + * @clear + * @do_crypt + * @base: Common crypto API algorithm data structure. + * + * Diskcipher supports APIs to set crypto information for dm-crypt and fscrypt + * And pass the crypto information to disk host device via bio. + * Crypt operation executes on inline crypto on disk host device. + */ +struct diskcipher_alg { + int (*init)(struct crypto_diskcipher *tfm); + int (*exit)(struct crypto_diskcipher *tfm); + int (*setkey)(struct crypto_diskcipher *tfm, const char *key, + u32 keylen, bool persistent); + int (*clearkey)(struct crypto_diskcipher *tfm); + int (*crypt)(struct crypto_diskcipher *tfm, void *req); + int (*clear)(struct crypto_diskcipher *tfm, void *req); + int (*do_crypt)(struct crypto_diskcipher *tfm, + struct diskcipher_test_request *req); + struct device *dev; + struct crypto_alg base; +}; + +static inline unsigned int crypto_diskcipher_ivsize( + struct crypto_diskcipher *tfm) +{ + return tfm->ivsize; +} + +static inline struct crypto_tfm *crypto_diskcipher_tfm( + struct crypto_diskcipher *tfm) +{ + return &tfm->base; +} + +static inline struct diskcipher_alg *__crypto_diskcipher_alg( + struct crypto_alg *alg) +{ + return container_of(alg, struct diskcipher_alg, base); +} +static inline struct diskcipher_alg *crypto_diskcipher_alg( + struct crypto_diskcipher *tfm) +{ + return __crypto_diskcipher_alg(crypto_diskcipher_tfm(tfm)->__crt_alg); +} + +static inline struct crypto_diskcipher *__crypto_diskcipher_cast( + struct crypto_tfm *tfm) +{ + return container_of(tfm, struct crypto_diskcipher, base); +} + +int crypto_register_diskcipher(struct diskcipher_alg *alg); +void crypto_unregister_diskcipher(struct diskcipher_alg *alg); +int crypto_register_diskciphers(struct diskcipher_alg *algs, int count); +void crypto_unregister_diskciphers(struct diskcipher_alg *algs, int count); + +#if defined(CONFIG_CRYPTO_DISKCIPHER) +/** + * crypto_alloc_diskcipher() - allocate disk cipher running on disk device + * @alg_name: is the cra_name / name or cra_driver_name / driver name of the + * skcipher cipher + * @type: specifies the type of the cipher + * @mask: specifies the mask for the cipher + * @force: add diskcipher postfix '-disk' on algo_name + * + * Allocate a cipher handle for an diskcipher. The returned struct + * crypto_diskcipher is the cipher handle that is required for any subsequent + * API invocation for that diskcipher. + * + * Return: allocated cipher handle in case of success; IS_ERR() is true in case + * of an error, PTR_ERR() returns the error code. + */ +struct crypto_diskcipher *crypto_alloc_diskcipher(const char *alg_name, + u32 type, u32 mask, bool force); + +/** + * crypto_free_diskcipher() - zeroize and free cipher handle + * @tfm: cipher handle to be freed + */ +void crypto_free_diskcipher(struct crypto_diskcipher *tfm); + +/** + * crypto_diskcipher_get() - get diskcipher from bio + * @bio: bio structure + */ +struct crypto_diskcipher *crypto_diskcipher_get(struct bio *bio); + +/** + * crypto_diskcipher_set() - set diskcipher to bio + * @bio: bio structure to contain diskcipher + * @tfm: cipher handle + * + * This functions set thm to bio->bi_aux_private to pass it to host driver. + * + */ +void crypto_diskcipher_set(struct bio *bio, struct crypto_diskcipher *tfm, + const struct inode *inode, u64 dun); + +/** + * crypto_diskcipher_setkey() - set key for cipher + * @tfm: cipher handle + * @key: buffer holding the key + * @keylen: length of the key in bytes + * @persistent: option of key storage option + * + * The caller provided key is set for the skcipher referenced by the cipher + * handle. + * + * Return: 0 if the setting of the key was successful; < 0 if an error occurred + */ +int crypto_diskcipher_setkey(struct crypto_diskcipher *tfm, const char *key, + u32 keylen, bool persistent); + +/** + * crypto_diskcipher_clearkey() - clear key + * @tfm: cipher handle + */ +int crypto_diskcipher_clearkey(struct crypto_diskcipher *tfm); + +/** + * crypto_diskcipher_set_crypt() - set crypto info for inline crypto engine + * @tfm: cipher handle + * @req: request handle. it's specific structure for inline crypt hardware + * + * Return: 0 if the setting of the key was successful; < 0 if an error occurred + */ +int crypto_diskcipher_set_crypt(struct crypto_diskcipher *tfm, void *req); + +/** + * crypto_diskcipher_clear_crypt() - clear crypto info on inline crypt hardware + * @tfm: cipher handle + * @req: request handle. it's specific structure for inline crypt hardware + * + * Return: 0 if the setting of the key was successful; < 0 if an error occurred + */ +int crypto_diskcipher_clear_crypt(struct crypto_diskcipher *tfm, void *req); + +/** + * diskcipher_do_crypt() - execute crypto for test + * @tfm: cipher handle + * @req: diskcipher_test_request handle + * + * The caller uses this function to request crypto + * Diskcipher_algo allocates the block area for test and then request block I/O + * + */ +int diskcipher_do_crypt(struct crypto_diskcipher *tfm, + struct diskcipher_test_request *req); + +/** + * diskcipher_request_set_crypt() - fill diskcipher_test_requeust + * @req: request handle + * @src: source scatter / gather list + * @dst: destination scatter / gather list + * @cryptlen: number of bytes to process from @src + * @iv: IV for the cipher operation which must comply with the IV size defined + * by crypto_skcipher_ivsize + * @enc: encrypt(1) / decrypt(0) + * + * This function allows setting of the source data and destination data + * scatter / gather lists. + * + * For encryption, the source is treated as the plaintext and the + * destination is the ciphertext. For a decryption operation, the use is + * reversed - the source is the ciphertext and the destination is the plaintext. + */ +static inline void diskcipher_request_set_crypt( + struct diskcipher_test_request *req, + struct scatterlist *src, struct scatterlist *dst, + unsigned int cryptlen, void *iv, bool enc) +{ + req->src = src; + req->dst = dst; + req->cryptlen = cryptlen; + req->iv = iv; + req->enc = enc; +} + +/** + * crypto_diskcipher_blk_mergeble() - check the crypt option of bios and decide + * whether to merge or not + * @bio1: a bio to be mergeable + * @bio2: a bio to be mergeable + */ +bool crypto_diskcipher_blk_mergeble(struct bio *bio1, struct bio *bio2); + +#else + +#define crypto_alloc_diskcipher(a, b, c, d) ((void *)NULL) +#define crypto_free_diskcipher(a) ((void)0) +#define crypto_diskcipher_get(a) ((void *)NULL) +#define crypto_diskcipher_set(a, b, c, d) ((void)0) +#define crypto_diskcipher_clearkey(a) ((void)0) +#define crypto_diskcipher_setkey(a, b, c, d) (-EINVAL) +#define crypto_diskcipher_blk_mergeble(a, b) (0) +#endif +#endif /* _DISKCIPHER_H_ */ diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 19ea3a3..3a8be78 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -44,6 +44,7 @@ #define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004 #define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005 #define CRYPTO_ALG_TYPE_SKCIPHER 0x00000005 +#define CRYPTO_ALG_TYPE_DISKCIPHER 0x00000007 #define CRYPTO_ALG_TYPE_KPP 0x00000008 #define CRYPTO_ALG_TYPE_ACOMPRESS 0x0000000a #define CRYPTO_ALG_TYPE_SCOMPRESS 0x0000000b From patchwork Wed Aug 21 06:42:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "boojin.kim" X-Patchwork-Id: 11105603 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 28BF31399 for ; Wed, 21 Aug 2019 06:42:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DCF84233FC for ; Wed, 21 Aug 2019 06:42:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="QnOOWE2Z" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728100AbfHUGm2 (ORCPT ); Wed, 21 Aug 2019 02:42:28 -0400 Received: from mailout4.samsung.com ([203.254.224.34]:52605 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727817AbfHUGm1 (ORCPT ); Wed, 21 Aug 2019 02:42:27 -0400 Received: from epcas2p4.samsung.com (unknown [182.195.41.56]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20190821064219epoutp04f58e1f647dfae50a2ae0f057292ae1bb~83Pqv_Xse1235612356epoutp04f for ; Wed, 21 Aug 2019 06:42:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20190821064219epoutp04f58e1f647dfae50a2ae0f057292ae1bb~83Pqv_Xse1235612356epoutp04f DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1566369739; bh=WnbIs/qNlKp6oVnU05R1K6UO7fsp2PDSWNPY+dvDBss=; h=From:To:Cc:Subject:Date:References:From; b=QnOOWE2ZfLMetCvmT2iUOuqMs4Aj9jFvHnd8vv+McBs/OTBTEvFaEO1FCk935IYS+ gJR9Io2gVOPz6qN3NmLvgmEJGrzLx4aBAsvEHczzRsr9f6LEcIwao50Q+greiFLdIX /Oy0fIStk1lo9i0qhcJTpOMgUaWoPUGRgPV0UghA= Received: from epsnrtp1.localdomain (unknown [182.195.42.162]) by epcas2p3.samsung.com (KnoxPortal) with ESMTP id 20190821064218epcas2p3b8efd545ceb279ec179965d376a51e1e~83PqFkKCU0101901019epcas2p3l; Wed, 21 Aug 2019 06:42:18 +0000 (GMT) Received: from epsmges2p3.samsung.com (unknown [182.195.40.182]) by epsnrtp1.localdomain (Postfix) with ESMTP id 46Cykw73rZzMqYly; Wed, 21 Aug 2019 06:42:16 +0000 (GMT) Received: from epcas2p2.samsung.com ( [182.195.41.54]) by epsmges2p3.samsung.com (Symantec Messaging Gateway) with SMTP id 91.23.04068.8C7EC5D5; Wed, 21 Aug 2019 15:42:16 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p3.samsung.com (KnoxPortal) with ESMTPA id 20190821064216epcas2p37df63284df4be04ba2f51b7f7b4b270b~83PndXVbQ0101901019epcas2p3j; Wed, 21 Aug 2019 06:42:16 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20190821064216epsmtrp2794511fe5f476429faa4c2367deca968~83PnZdtGA2242122421epsmtrp2P; Wed, 21 Aug 2019 06:42:16 +0000 (GMT) X-AuditID: b6c32a47-589ff70000000fe4-62-5d5ce7c88e28 Received: from epsmtip1.samsung.com ( [182.195.34.30]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id FA.02.03706.7C7EC5D5; Wed, 21 Aug 2019 15:42:15 +0900 (KST) Received: from KORDO035251 (unknown [12.36.165.204]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20190821064215epsmtip18b35762a7fc8e5ecabba39c5d415e4a7~83PmzwwDs3087530875epsmtip1G; Wed, 21 Aug 2019 06:42:15 +0000 (GMT) From: "boojin.kim" To: "'Herbert Xu'" , "'David S. Miller'" , , Cc: "'Herbert Xu'" , "'David S. Miller'" , "'Eric Biggers'" , "'Theodore Y. Ts'o'" , "'Chao Yu'" , "'Jaegeuk Kim'" , "'Andreas Dilger'" , "'Theodore Ts'o'" , , "'Mike Snitzer'" , "'Alasdair Kergon'" , "'Jens Axboe'" , "'Krzysztof Kozlowski'" , "'Kukjin Kim'" , "'Jaehoon Chung'" , "'Ulf Hansson'" , , , , , , , , , , , Subject: [PATCH 2/9] crypto: fmp: add Flash Memory Protector driver Date: Wed, 21 Aug 2019 15:42:15 +0900 Message-ID: <003e01d557eb$921d4320$b657c960$@samsung.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 14.0 Thread-Index: AdVX6ADMbtkusay8Q0KDduCY7aX4rA== Content-Language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprLLsWRmVeSWpSXmKPExsWy7bCmme6J5zGxBv1HLC2+fulgsVh/6hiz xeq7/WwWp6eeZbKYc76FxWLvu9msFmv3/GG26H4lY/Fk/Sxmixu/2lgt+h+/ZrY4f34Du8Wm x9dYLfbe0ra4f+8nk8XMeXfYLC4tcrd4Ne8bi8WevSdZLC7vmsNmceR/P6PFjPP7mCzaNn5l tGjt+clucXxtuIOkx5aVN5k8WjaXe2w7oOpx+Wypx6ZVnWwed67tYfPYvKTeY/eCz0weTWeO Mnu833eVzaNvyypGj8+b5AJ4onJsMlITU1KLFFLzkvNTMvPSbZW8g+Od403NDAx1DS0tzJUU 8hJzU22VXHwCdN0yc4B+V1IoS8wpBQoFJBYXK+nb2RTll5akKmTkF5fYKqUWpOQUGBoW6BUn 5haX5qXrJefnWhkaGBiZAlUm5GSsu/ObuWDLHaaKFWvmMTUw3p/O1MXIySEhYCLx5eYM5i5G Lg4hgR2MEucXH4VyPjFKtG++wQ7hfGOUmPNwBTtMy5u1i1lBbCGBvYwSDbPYIIpeMkpcezwb LMEmoC2x+fgqRpCEiMB8oMTdd2BVzAL/2CWefDrEAlIlLOAscWn3erAOFgFViYlNkxlBbF4B S4lvx55D2YISJ2c+AatnFpCX2P52DjPEGQoSO86+BqsREdCTmLzhIDtEjYjE7M42sCckBBo5 JF5928MI0eAisWTSX1YIW1ji1fEtUP9ISXx+t5cNwq6XuLpsMTtEcw+jxJlfbVBFxhKznrUD DeIA2qApsX6XPogpIaAsceQW1G18Eh2H/7JDhHklOtqEIBpVJOZ+uswEEZaS+NBTBxH2kJh6 8SjzBEbFWUienIXkyVlInpmFsHYBI8sqRrHUguLc9NRiowJj5PjexAjOGlruOxi3nfM5xCjA wajEw5twPTpWiDWxrLgy9xCjBAezkghvxZyoWCHelMTKqtSi/Pii0pzU4kOMpsA4mMgsJZqc D8xoeSXxhqZGZmYGlqYWpmZGFkrivJu4b8YICaQnlqRmp6YWpBbB9DFxcEo1ME6qzS81Y9/8 T6N1udA3ZYcpWq+iPJSV6k8ds7unIR38Z5ex1puINUIvvOZM726WUMz9MFVZUOKhTFPQ9Eid wzXzl83w/izz6d/EVy2HVwUq/2T1ls+b75AQ83rrjiTD5xMuiKyNTFVfqNanE6Zmf2ie3Dre fOb6chvOh489WOXD7S2PB9zdqsRSnJFoqMVcVJwIAOm5LswwBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrLIsWRmVeSWpSXmKPExsWy7bCSnO7x5zGxBq9fW1l8/dLBYrH+1DFm i9V3+9ksTk89y2Qx53wLi8Xed7NZLdbu+cNs0f1KxuLJ+lnMFjd+tbFa9D9+zWxx/vwGdotN j6+xWuy9pW1x/95PJouZ8+6wWVxa5G7xat43Fos9e0+yWFzeNYfN4sj/fkaLGef3MVm0bfzK aNHa85Pd4vjacAdJjy0rbzJ5tGwu99h2QNXj8tlSj02rOtk87lzbw+axeUm9x+4Fn5k8ms4c ZfZ4v+8qm0ffllWMHp83yQXwRHHZpKTmZJalFunbJXBlrLvzm7lgyx2mihVr5jE1MN6fztTF yMkhIWAi8WbtYtYuRi4OIYHdjBLzF/ezQCSkJLa272GGsIUl7rccYQWxhQSeM0rMWuYJYrMJ aEtsPr6KEaRZRGAho8Sb1TvZQBLMAtM4JHZ9EAexhQWcJS7tXg/WzCKgKjGxaTIjiM0rYCnx 7dhzKFtQ4uTMJ0CLOYB69STaNjJCjJGX2P52DtQNChI7zr4Gi4sAlUzecJAdokZEYnZnG/ME RsFZSCbNQpg0C8mkWUg6FjCyrGKUTC0ozk3PLTYsMMxLLdcrTswtLs1L10vOz93ECE4EWpo7 GC8viT/EKMDBqMTDu+NmdKwQa2JZcWXuIUYJDmYlEd6KOVGxQrwpiZVVqUX58UWlOanFhxil OViUxHmf5h2LFBJITyxJzU5NLUgtgskycXBKNTCynMwznOYY38X/WUw3ZfKlS+4T4gWf1Kxu /C/d75cVn/KmnnmrabVXX4RnbeJNDSmfruzfvpdtWAJvrVrpfX2pZajD6+dS2fV6QnIGDzfP lyg4/OLDX5OInIcaR8zOC1+7HPFXmKHUqK0hsandaeKHQ9JcnSo3Eo6td8iR2FPq/6BIed6Z bUosxRmJhlrMRcWJAKq0DdQAAwAA X-CMS-MailID: 20190821064216epcas2p37df63284df4be04ba2f51b7f7b4b270b X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20190821064216epcas2p37df63284df4be04ba2f51b7f7b4b270b References: Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Exynos has FMP(Flash Memory Protector) H/W to protect data stored on storage device. FMP interworks with the storage controller to encrypt a data before writing to the storage device and decrypt the data after reading from storage device. FMP driver is registered with a cipher algorithm of diskcipher. FMP driver writes crypto information in the descriptor of the storage controller. And then, FMP H/W encrypts plan-text with every write I/O and decrypts cipher-text with every read I/O. FMP is divided into three blocks. The first is fmp driver to control FMP H/W. The second is the fmp-crypt that is responsible for the interface with the diskcipher and storage driver. The third is the fmp-test to test the fmp driver through testmgr of crypto API. Cc: Herbert Xu Cc: "David S. Miller" Signed-off-by: Boojin Kim --- drivers/crypto/Kconfig | 2 + drivers/crypto/Makefile | 1 + drivers/crypto/fmp/Kconfig | 13 + drivers/crypto/fmp/Makefile | 1 + drivers/crypto/fmp/fmp.c | 595 +++++++++++++++++++++++++++++++++++++++++ drivers/crypto/fmp/fmp_crypt.c | 243 +++++++++++++++++ drivers/crypto/fmp/fmp_test.c | 310 +++++++++++++++++++++ drivers/crypto/fmp/fmp_test.h | 30 +++ include/crypto/fmp.h | 324 ++++++++++++++++++++++ 9 files changed, 1519 insertions(+) create mode 100644 drivers/crypto/fmp/Kconfig create mode 100644 drivers/crypto/fmp/Makefile create mode 100644 drivers/crypto/fmp/fmp.c create mode 100644 drivers/crypto/fmp/fmp_crypt.c create mode 100644 drivers/crypto/fmp/fmp_test.c create mode 100644 drivers/crypto/fmp/fmp_test.h create mode 100644 include/crypto/fmp.h + uint8_t *dst, uint32_t len, bool enc, void *priv); +#endif /* _EXYNOS_FMP_H_ */ diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index b8c5087..43b8cc4 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -785,4 +785,6 @@ config CRYPTO_DEV_CCREE source "drivers/crypto/hisilicon/Kconfig" +source "drivers/crypto/fmp/Kconfig" + endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index afc4753..d43cf7a 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -48,3 +48,4 @@ obj-$(CONFIG_CRYPTO_DEV_BCM_SPU) += bcm/ obj-$(CONFIG_CRYPTO_DEV_SAFEXCEL) += inside-secure/ obj-$(CONFIG_CRYPTO_DEV_ARTPEC6) += axis/ obj-y += hisilicon/ +obj-$(CONFIG_EXYNOS_FMP) += fmp/ diff --git a/drivers/crypto/fmp/Kconfig b/drivers/crypto/fmp/Kconfig new file mode 100644 index 0000000..69cdb53 --- /dev/null +++ b/drivers/crypto/fmp/Kconfig @@ -0,0 +1,13 @@ +# +# SMU/FMP controller drivers +# + +config EXYNOS_FMP + tristate "Samsung EXYNOS FMP driver" + depends on CRYPTO_DISKCIPHER && MMC_DW_EXYNOS_FMP + help + Say yes here to build support for FMP (Flash Memory Protector) + to encrypt and decrypt userdata using inline H/W crypto module. + If unsure, say N. + + To compile this driver as a module, choose M here diff --git a/drivers/crypto/fmp/Makefile b/drivers/crypto/fmp/Makefile new file mode 100644 index 0000000..5328947 --- /dev/null +++ b/drivers/crypto/fmp/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_EXYNOS_FMP) += fmp_crypt.o fmp.o fmp_test.o diff --git a/drivers/crypto/fmp/fmp.c b/drivers/crypto/fmp/fmp.c new file mode 100644 index 0000000..475d471 --- /dev/null +++ b/drivers/crypto/fmp/fmp.c @@ -0,0 +1,595 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Exynos FMP driver + * + * Copyright (C) 2015 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fmp_test.h" + +#define WORD_SIZE 4 +#define FMP_IV_MAX_IDX (FMP_IV_SIZE_16 / WORD_SIZE) + +#ifndef __SMC_H__ +#define exynos_smc(a, b, c, d) (-EINVAL) +#endif + +#define byte2word(b0, b1, b2, b3) \ + (((unsigned int)(b0) << 24) | \ + ((unsigned int)(b1) << 16) | \ + ((unsigned int)(b2) << 8) | (b3)) +#define get_word(x, c) byte2word(((unsigned char *)(x) + 4 * (c))[0], \ + ((unsigned char *)(x) + 4 * (c))[1], \ + ((unsigned char *)(x) + 4 * (c))[2], \ + ((unsigned char *)(x) + 4 * (c))[3]) + +static inline void dump_ci(struct fmp_crypto_info *c) +{ + if (c) { + pr_info + ("%s: crypto:%p algo:%d enc:%d key_size:%d key:%p\n", + __func__, c, c->algo_mode, c->enc_mode, + c->key_size, c->key); + if (c->enc_mode == EXYNOS_FMP_FILE_ENC) + print_hex_dump(KERN_CONT, "key:", + DUMP_PREFIX_OFFSET, 16, 1, c->key, + sizeof(c->key), false); + } +} + +static inline void dump_table(struct fmp_table_setting *table) +{ + print_hex_dump(KERN_CONT, "dump:", DUMP_PREFIX_OFFSET, 16, 1, + table, sizeof(struct fmp_table_setting), false); +} + +static inline int is_set_fmp_disk_key(struct exynos_fmp *fmp) +{ + return (fmp->status_disk_key == KEY_SET) ? TRUE : FALSE; +} + +static inline int is_stored_fmp_disk_key(struct exynos_fmp *fmp) +{ + return (fmp->status_disk_key == KEY_STORED) ? TRUE : FALSE; +} + +static inline int is_supported_ivsize(u32 ivlen) +{ + if (ivlen && (ivlen <= FMP_IV_SIZE_16)) + return TRUE; + else + return FALSE; +} + +static inline int check_aes_xts_size(struct fmp_table_setting *table, + bool cmdq_enabled) +{ + int size; + + if (cmdq_enabled) + size = GET_CMDQ_LENGTH(table); + else + size = GET_LENGTH(table); + return (size > MAX_AES_XTS_TRANSFER_SIZE) ? size : 0; +} + +static inline int check_aes_xts_key(char *key, + enum fmp_crypto_key_size key_size) +{ + char *enckey, *twkey; + + enckey = key; + twkey = key + key_size; + return (memcmp(enckey, twkey, key_size)) ? 0 : -1; +} + +int fmplib_set_algo_mode(struct fmp_table_setting *table, + struct fmp_crypto_info *crypto, bool cmdq_enabled) +{ + int ret; + enum fmp_crypto_algo_mode algo_mode = crypto->algo_mode; + + if (algo_mode == EXYNOS_FMP_ALGO_MODE_AES_XTS) { + ret = check_aes_xts_size(table, cmdq_enabled); + if (ret) { + pr_err("%s: Fail FMP XTS due to invalid size(%d)\n", + __func__, ret); + return -EINVAL; + } + } + + switch (crypto->enc_mode) { + case EXYNOS_FMP_FILE_ENC: + if (cmdq_enabled) + SET_CMDQ_FAS(table, algo_mode); + else + SET_FAS(table, algo_mode); + break; + case EXYNOS_FMP_DISK_ENC: + if (cmdq_enabled) + SET_CMDQ_DAS(table, algo_mode); + else + SET_DAS(table, algo_mode); + break; + default: + pr_err("%s: Invalid fmp enc mode %d\n", __func__, + crypto->enc_mode); + return -EINVAL; + } + return 0; +} + +static int fmplib_set_file_key(struct fmp_table_setting *table, + struct fmp_crypto_info *crypto) +{ + enum fmp_crypto_algo_mode algo_mode = crypto->algo_mode; + enum fmp_crypto_key_size key_size = crypto->fmp_key_size; + char *key = crypto->key; + int idx, max; + + if (!key || (crypto->enc_mode != EXYNOS_FMP_FILE_ENC) || + ((key_size != EXYNOS_FMP_KEY_SIZE_16) && + (key_size != EXYNOS_FMP_KEY_SIZE_32))) { + pr_err("%s: Invalid crypto:%p key:%p key_size:%d enc_mode:%d\n", + __func__, crypto, key, key_size, crypto->enc_mode); + return -EINVAL; + } + + if ((algo_mode == EXYNOS_FMP_ALGO_MODE_AES_XTS) + && check_aes_xts_key(key, key_size)) { + pr_err("%s: Fail FMP XTS due to the same enc and twkey\n", + __func__); + return -EINVAL; + } + + if (algo_mode == EXYNOS_FMP_ALGO_MODE_AES_CBC) { + max = key_size / WORD_SIZE; + for (idx = 0; idx < max; idx++) + *(&table->file_enckey0 + idx) = + get_word(key, max - (idx + 1)); + } else if (algo_mode == EXYNOS_FMP_ALGO_MODE_AES_XTS) { + key_size *= 2; + max = key_size / WORD_SIZE; + for (idx = 0; idx < (max / 2); idx++) + *(&table->file_enckey0 + idx) = + get_word(key, (max / 2) - (idx + 1)); + for (idx = 0; idx < (max / 2); idx++) + *(&table->file_twkey0 + idx) = + get_word(key, max - (idx + 1)); + } + return 0; +} + +static int fmplib_set_key_size(struct fmp_table_setting *table, + struct fmp_crypto_info *crypto, bool cmdq_enabled) +{ + enum fmp_crypto_key_size key_size; + + key_size = crypto->fmp_key_size; + + if ((key_size != EXYNOS_FMP_KEY_SIZE_16) && + (key_size != EXYNOS_FMP_KEY_SIZE_32)) { + pr_err("%s: Invalid keysize %d\n", __func__, key_size); + return -EINVAL; + } + + switch (crypto->enc_mode) { + case EXYNOS_FMP_FILE_ENC: + if (cmdq_enabled) + SET_CMDQ_KEYLEN(table, + (key_size == + FMP_KEY_SIZE_32) ? FKL_CMDQ : 0); + else + SET_KEYLEN(table, + (key_size == FMP_KEY_SIZE_32) ? FKL : 0); + break; + case EXYNOS_FMP_DISK_ENC: + if (cmdq_enabled) + SET_CMDQ_KEYLEN(table, + (key_size == + FMP_KEY_SIZE_32) ? DKL_CMDQ : 0); + else + SET_KEYLEN(table, + (key_size == FMP_KEY_SIZE_32) ? DKL : 0); + break; + default: + pr_err("%s: Invalid fmp enc mode %d\n", __func__, + crypto->enc_mode); + return -EINVAL; + } + return 0; +} + +static int fmplib_set_disk_key(struct exynos_fmp *fmp, u8 *key, u32 key_size) +{ + int ret; + + /* TODO: only set for host0 */ + __flush_dcache_area(key, (size_t) FMP_MAX_KEY_SIZE); + ret = + exynos_smc(SMC_CMD_FMP_DISK_KEY_STORED, 0, virt_to_phys(key), + key_size); + if (ret) { + pr_err("%s: Fail to set FMP disk key. ret = %d\n", __func__, + ret); + fmp->status_disk_key = KEY_ERROR; + return -EINVAL; + } + fmp->status_disk_key = KEY_STORED; + return 0; +} + +static int fmplib_clear_disk_key(struct exynos_fmp *fmp) +{ + int ret; + + ret = exynos_smc(SMC_CMD_FMP_DISK_KEY_CLEAR, 0, 0, 0); + if (ret) { + pr_err("%s: Fail to clear FMP disk key. ret = %d\n", + __func__, ret); + fmp->status_disk_key = KEY_ERROR; + return -EPERM; + } + + fmp->status_disk_key = KEY_CLEAR; + return 0; +} + +static int fmplib_set_iv(struct fmp_table_setting *table, + struct fmp_crypto_info *crypto, u8 *iv) +{ + int idx; + + switch (crypto->enc_mode) { + case EXYNOS_FMP_FILE_ENC: + for (idx = 0; idx < FMP_IV_MAX_IDX; idx++) + *(&table->file_iv0 + idx) = + get_word(iv, FMP_IV_MAX_IDX - (idx + 1)); + break; + case EXYNOS_FMP_DISK_ENC: + for (idx = 0; idx < FMP_IV_MAX_IDX; idx++) + *(&table->disk_iv0 + idx) = + get_word(iv, FMP_IV_MAX_IDX - (idx + 1)); + break; + default: + pr_err("%s: Invalid fmp enc mode %d\n", __func__, + crypto->enc_mode); + return -EINVAL; + } + return 0; +} + +int exynos_fmp_crypt(struct fmp_crypto_info *ci, void *priv) +{ + struct exynos_fmp *fmp = ci->ctx; + struct fmp_request *r = priv; + int ret = 0; + u8 iv[FMP_IV_SIZE_16]; + + if (!r || !fmp) { + pr_err("%s: invalid req:%p, fmp:%p\n", __func__, r, fmp); + return -EINVAL; + } + + /* check test mode */ + if (ci->algo_mode & EXYNOS_FMP_ALGO_MODE_TEST) { + ci->algo_mode &= EXYNOS_FMP_ALGO_MODE_MASK; + if (!ci->algo_mode) + return 0; + + if (!fmp->test_data) { + pr_err("%s: no test_data for test mode\n", __func__); + goto out; + } + /* use test manager's iv instead of host driver's iv */ + r->iv = fmp->test_data->iv; + r->ivsize = sizeof(fmp->test_data->iv); + } + + /* check crypto info & input param */ + if (!ci->algo_mode || !is_supported_ivsize(r->ivsize) || + !r->table || !r->iv) { + dev_err(fmp->dev, + "%s: invalid mode:%d iv:%p ivsize:%d table:%p\n", + __func__, ci->algo_mode, r->iv, r->ivsize, r->table); + ret = -EINVAL; + goto out; + } + + /* set algo & enc mode into table */ + ret = fmplib_set_algo_mode(r->table, ci, r->cmdq_enabled); + if (ret) { + dev_err(fmp->dev, "%s: Fail to set FMP encryption mode\n", + __func__); + ret = -EINVAL; + goto out; + } + + /* set key size into table */ + switch (ci->enc_mode) { + case EXYNOS_FMP_FILE_ENC: + ret = fmplib_set_file_key(r->table, ci); + if (ret) { + dev_err(fmp->dev, "%s: Fail to set FMP key\n", + __func__); + ret = -EINVAL; + goto out; + } + break; + case EXYNOS_FMP_DISK_ENC: + if (is_stored_fmp_disk_key(fmp)) { + ret = exynos_smc(SMC_CMD_FMP_DISK_KEY_SET, 0, 0, 0); + if (ret) { + dev_err(fmp->dev, + "%s: Fail to set disk key\n", __func__); + goto out; + } + fmp->status_disk_key = KEY_SET; + } else if (!is_set_fmp_disk_key(fmp)) { + dev_err(fmp->dev, + "%s: Fail because disk key is clear\n", + __func__); + ret = -EINVAL; + goto out; + } + break; + default: + dev_err(fmp->dev, "%s: Invalid fmp enc mode %d\n", __func__, + ci->enc_mode); + ret = -EINVAL; + goto out; + } + + /* set key size into table */ + ret = fmplib_set_key_size(r->table, ci, r->cmdq_enabled); + if (ret) { + dev_err(fmp->dev, "%s: Fail to set FMP key size\n", __func__); + ret = -EINVAL; + goto out; + } + + /* set iv */ + memset(iv, 0, FMP_IV_SIZE_16); + memcpy(iv, r->iv, r->ivsize); + ret = fmplib_set_iv(r->table, ci, iv); + if (ret) { + dev_err(fmp->dev, "%s: Fail to set FMP IV\n", __func__); + ret = -EINVAL; + goto out; + } +out: + if (ret) { + dump_ci(ci); + if (r && r->table) + dump_table(r->table); + } + return ret; +} + +static inline void fmplib_clear_file_key(struct fmp_table_setting *table) +{ + memset(&table->file_iv0, 0, sizeof(__le32) * 24); +} + +int exynos_fmp_clear(struct fmp_crypto_info *ci, void *priv) +{ + struct fmp_request *r = priv; + + if (!r) { + pr_err("%s: Invalid input\n", __func__); + return -EINVAL; + } + + if (!r->table) { + pr_err("%s: Invalid input table\n", __func__); + return -EINVAL; + } + + fmplib_clear_file_key(r->table); + return 0; +} + +int exynos_fmp_setkey(struct fmp_crypto_info *ci, u8 *in_key, u32 keylen, + bool persistent) +{ + struct exynos_fmp *fmp = ci->ctx; + int ret = 0; + int keylen_org = keylen; + + if (!fmp || !in_key) { + pr_err("%s: invalid input param\n", __func__); + return -EINVAL; + } + + /* set key_size & fmp_key_size */ + if (ci->algo_mode == EXYNOS_FMP_ALGO_MODE_AES_XTS) + keylen = keylen >> 1; + switch (keylen) { + case FMP_KEY_SIZE_16: + ci->fmp_key_size = EXYNOS_FMP_KEY_SIZE_16; + break; + case FMP_KEY_SIZE_32: + ci->fmp_key_size = EXYNOS_FMP_KEY_SIZE_32; + break; + default: + pr_err("%s: FMP doesn't support key size %d\n", __func__, + keylen); + return -ENOKEY; + } + ci->key_size = keylen_org; + + /* set key */ + if (persistent) { + ci->enc_mode = EXYNOS_FMP_DISK_ENC; + ret = fmplib_set_disk_key(fmp, in_key, ci->key_size); + if (ret) + pr_err("%s: Fail to set FMP disk key\n", __func__); + } else { + ci->enc_mode = EXYNOS_FMP_FILE_ENC; + memset(ci->key, 0, sizeof(ci->key)); + memcpy(ci->key, in_key, ci->key_size); + } + return ret; +} + +int exynos_fmp_clearkey(struct fmp_crypto_info *ci) +{ + struct exynos_fmp *fmp = ci->ctx; + int ret = 0; + + if (!fmp) { + pr_err("%s: invalid input param\n", __func__); + ret = -EINVAL; + goto out; + } + + if (ci->enc_mode == EXYNOS_FMP_DISK_ENC) { + ret = fmplib_clear_disk_key(fmp); + if (ret) + pr_err("%s: fail to clear FMP disk key\n", __func__); + } else if (ci->enc_mode == EXYNOS_FMP_FILE_ENC) { + memset(ci->key, 0, sizeof(ci->key)); + ci->key_size = 0; + } else { + pr_err("%s: invalid algo mode:%d\n", __func__, ci->enc_mode); + ret = -EINVAL; + } +out: + return ret; +} + +int exynos_fmp_test_crypt(struct fmp_crypto_info *ci, + const uint8_t *iv, uint32_t ivlen, uint8_t *src, + uint8_t *dst, uint32_t len, bool enc, void *priv) +{ + struct exynos_fmp *fmp = ci->ctx; + int ret = 0; + + if (!fmp || !iv || !src || !dst) { + pr_err("%s: invalid input: fmp:%p, iv:%p, s:%p, d:%p\n", + __func__, fmp, iv, src, dst); + return -EINVAL; + } + + /* init fmp test to get test block */ + fmp->test_data = fmp_test_init(fmp); + if (!fmp->test_data) { + dev_err(fmp->dev, "%s: fail to initialize fmp test.", + __func__); + goto err; + } + + /* setiv */ + if (iv && (ivlen <= FMP_IV_SIZE_16)) { + memset(fmp->test_data->iv, 0, FMP_IV_SIZE_16); + memcpy(fmp->test_data->iv, iv, ivlen); + } else { + dev_err(fmp->dev, "%s: fail to set fmp iv. ret(%d)", + __func__, ret); + goto err; + } + + /* do crypt: priv: struct crypto_diskcipher */ + ret = fmp_test_crypt(fmp, fmp->test_data, + src, dst, len, enc ? ENCRYPT : DECRYPT, priv, ci); + if (ret) + dev_err(fmp->dev, "%s: fail to run fmp test. ret(%d)", + __func__, ret); + +err: + if (fmp->test_data) + fmp_test_exit(fmp->test_data); + return ret; +} + +int exynos_fmp_smu_abort(int id) +{ + int ret = 0; + + if (id == SMU_ID_MAX) + return 0; + + ret = exynos_smc(SMC_CMD_SMU, SMU_ABORT, id, 0); + if (ret) + pr_err("%s: Fail smc call. ret(%d)\n", __func__, ret); + + return ret; +} + +#define CFG_DESCTYPE_3 0x3 +int exynos_fmp_sec_cfg(int fmp_id, int smu_id, bool init) +{ + int ret = 0; + + if (fmp_id != SMU_ID_MAX) { + ret = exynos_smc(SMC_CMD_FMP_SECURITY, 0, + fmp_id, CFG_DESCTYPE_3); + if (ret) + pr_err("%s: Fail smc call for FMP_SECURITY. ret(%d)\n", + __func__, ret); + } + + if (smu_id != SMU_ID_MAX) { + if (init) + ret = exynos_smc(SMC_CMD_SMU, SMU_INIT, smu_id, 0); + else + ret = exynos_smc(SMC_CMD_FMP_SMU_RESUME, 0, smu_id, 0); + if (ret) + pr_err("%s: Fail smc call cmd:%d. ret(%d)\n", + __func__, init, ret); + } + + return ret; +} + +void *exynos_fmp_init(struct platform_device *pdev) +{ + struct exynos_fmp *fmp; + + if (!pdev) { + pr_err("%s: Invalid platform_device.\n", __func__); + return NULL; + } + + fmp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_fmp), GFP_KERNEL); + if (!fmp) + return NULL; + + fmp->dev = &pdev->dev; + if (!fmp->dev) { + pr_err("%s: Invalid device.\n", __func__); + goto err_dev; + } + + /* init disk key status */ + fmp->status_disk_key = KEY_CLEAR; + + dev_info(fmp->dev, "Exynos FMP Version: %s\n", FMP_DRV_VERSION); + return fmp; + +err_dev: + kzfree(fmp); + return NULL; +} + +void exynos_fmp_exit(struct exynos_fmp *fmp) +{ + kzfree(fmp); +} diff --git a/drivers/crypto/fmp/fmp_crypt.c b/drivers/crypto/fmp/fmp_crypt.c new file mode 100644 index 0000000..78becb5 --- /dev/null +++ b/drivers/crypto/fmp/fmp_crypt.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Exynos FMP crypt interface + * + * Copyright (C) 2018 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int exynos_fmp_crypt_clear(struct bio *bio, void *table_addr) +{ + struct crypto_diskcipher *dtfm = crypto_diskcipher_get(bio); + struct fmp_crypto_info *ci; + struct fmp_request req; + int ret = 0; + + if (unlikely(IS_ERR(dtfm))) { + pr_warn("%s: fails to get crypt\n", __func__); + return -EINVAL; + } else if (dtfm) { + ci = crypto_tfm_ctx(crypto_diskcipher_tfm(dtfm)); + if (ci) + if (ci->enc_mode == EXYNOS_FMP_FILE_ENC) { + req.table = table_addr; + ret = crypto_diskcipher_clear_crypt(dtfm, &req); + } + } + if (ret) + pr_err("%s: fail to config desc (bio:%p, tfm:%p, ci:%p ret:%d)\n", + __func__, bio, dtfm, ci, ret); + return ret; +} + +int exynos_fmp_crypt_cfg(struct bio *bio, void *table_addr, + u32 page_idx, u32 sector_unit) +{ + struct crypto_diskcipher *dtfm = crypto_diskcipher_get(bio); + u64 iv; + struct fmp_request req; + int ret = 0; + + if (unlikely(IS_ERR(dtfm))) { + pr_warn("%s: fails to get crypt\n", __func__); + return -EINVAL; + } else if (dtfm) { + req.table = table_addr; + req.cmdq_enabled = 0; + req.iv = &iv; + req.ivsize = sizeof(iv); + iv = (dtfm->ivmode == IV_MODE_DUN) ? (bio_dun(bio) + page_idx) : + (bio->bi_iter.bi_sector + (sector_t)sector_unit); + ret = crypto_diskcipher_set_crypt(dtfm, &req); + if (ret) + pr_err("%s: fail to config desc (bio:%p, tfm:%p, ret:%d)\n", + __func__, bio, dtfm, ret); + return ret; + } + + exynos_fmp_bypass(table_addr, 0); + return 0; +} + +static int fmp_crypt(struct crypto_diskcipher *tfm, void *priv) +{ + struct fmp_crypto_info *ci = crypto_tfm_ctx(crypto_diskcipher_tfm(tfm)); + + return exynos_fmp_crypt(ci, priv); +} + +static int fmp_clear(struct crypto_diskcipher *tfm, void *priv) +{ + struct fmp_crypto_info *ci = crypto_tfm_ctx(crypto_diskcipher_tfm(tfm)); + + return exynos_fmp_clear(ci, priv); +} + +static int fmp_setkey(struct crypto_diskcipher *tfm, const char *in_key, + u32 keylen, bool persistent) +{ + struct fmp_crypto_info *ci = crypto_tfm_ctx(crypto_diskcipher_tfm(tfm)); + + return exynos_fmp_setkey(ci, (char *)in_key, keylen, persistent); +} + +static int fmp_clearkey(struct crypto_diskcipher *tfm) +{ + struct fmp_crypto_info *ci = crypto_tfm_ctx(crypto_diskcipher_tfm(tfm)); + + return exynos_fmp_clearkey(ci); +} + +/* support crypto manager test without CRYPTO_MANAGER_DISABLE_TESTS */ +static int fmp_do_test_crypt(struct crypto_diskcipher *tfm, + struct diskcipher_test_request *req) +{ + if (!req) { + pr_err("%s: invalid parameter\n", __func__); + return -EINVAL; + } + + return exynos_fmp_test_crypt(crypto_tfm_ctx(crypto_diskcipher_tfm(tfm)), + req->iv, tfm->ivsize, + sg_virt(req->src), sg_virt(req->dst), + req->cryptlen, req->enc ? 1 : 0, tfm); +} + + +static inline void fmp_algo_init(struct crypto_tfm *tfm, + enum fmp_crypto_algo_mode algo) +{ + struct fmp_crypto_info *ci = crypto_tfm_ctx(tfm); + struct crypto_diskcipher *diskc = __crypto_diskcipher_cast(tfm); + struct diskcipher_alg *alg = crypto_diskcipher_alg(diskc); + + /* This field's stongly aligned 'fmp_crypto_info->use_diskc' */ + diskc->algo = (u32)algo; + diskc->ivsize = FMP_IV_SIZE_16; + ci->ctx = dev_get_drvdata(alg->dev); + ci->algo_mode = algo; +} + +static int fmp_aes_xts_init(struct crypto_tfm *tfm) +{ + fmp_algo_init(tfm, EXYNOS_FMP_ALGO_MODE_AES_XTS); + return 0; +} + +static int fmp_cbc_aes_init(struct crypto_tfm *tfm) +{ + fmp_algo_init(tfm, EXYNOS_FMP_ALGO_MODE_AES_CBC); + return 0; +} + +static struct diskcipher_alg fmp_algs[] = {{ + .base = { + .cra_name = "xts(aes)-disk", + .cra_driver_name = "xts(aes)-disk(fmp)", + .cra_priority = 200, + .cra_module = THIS_MODULE, + .cra_ctxsize = sizeof(struct fmp_crypto_info), + .cra_init = fmp_aes_xts_init, + } +}, { + .base = { + .cra_name = "cbc(aes)-disk", + .cra_driver_name = "cbc(aes)-disk(fmp)", + .cra_priority = 200, + .cra_module = THIS_MODULE, + .cra_ctxsize = sizeof(struct fmp_crypto_info), + .cra_init = fmp_cbc_aes_init, + } +} }; + +static int exynos_fmp_probe(struct platform_device *pdev) +{ + struct diskcipher_alg *alg; + void *fmp_ctx = exynos_fmp_init(pdev); + int ret; + int i; + + if (!fmp_ctx) { + dev_err(&pdev->dev, + "%s: Fail to register diskciphero\n", __func__); + return -EINVAL; + } + dev_set_drvdata(&pdev->dev, fmp_ctx); + + for (i = 0; i < ARRAY_SIZE(fmp_algs); i++) { + alg = &fmp_algs[i]; + alg->dev = &pdev->dev; + alg->init = NULL; + alg->setkey = fmp_setkey; + alg->clearkey = fmp_clearkey; + alg->crypt = fmp_crypt; + alg->clear = fmp_clear; + alg->do_crypt = fmp_do_test_crypt; + } + ret = crypto_register_diskciphers(fmp_algs, ARRAY_SIZE(fmp_algs)); + if (ret) { + dev_err(&pdev->dev, + "%s: Fail to register diskciphero. ret = %d\n", + __func__, ret); + return -EINVAL; + } + dev_info(&pdev->dev, "Exynos FMP driver is registered to diskcipher\n"); + return 0; +} + +static int exynos_fmp_remove(struct platform_device *pdev) +{ + void *drv_data = dev_get_drvdata(&pdev->dev); + + if (!drv_data) { + pr_err("%s: Fail to get drvdata\n", __func__); + return 0; + } + crypto_unregister_diskciphers(fmp_algs, ARRAY_SIZE(fmp_algs)); + exynos_fmp_exit(drv_data); + return 0; +} + +static const struct of_device_id exynos_fmp_match[] = { + { .compatible = "samsung,exynos-fmp" }, + {}, +}; + +static struct platform_driver exynos_fmp_driver = { + .driver = { + .name = "exynos-fmp", + .owner = THIS_MODULE, + .pm = NULL, + .of_match_table = exynos_fmp_match, + }, + .probe = exynos_fmp_probe, + .remove = exynos_fmp_remove, +}; + +static int __init fmp_init(void) +{ + return platform_driver_register(&exynos_fmp_driver); +} +late_initcall(fmp_init); + +static void __exit fmp_exit(void) +{ + platform_driver_unregister(&exynos_fmp_driver); +} +module_exit(fmp_exit); +MODULE_DESCRIPTION("Exynos Spedific crypto algo driver"); diff --git a/drivers/crypto/fmp/fmp_test.c b/drivers/crypto/fmp/fmp_test.c new file mode 100644 index 0000000..fb47bbd --- /dev/null +++ b/drivers/crypto/fmp/fmp_test.c @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Exynos FMP cipher driver + * + * Copyright (C) 2016 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fmp_test.h" + +#define MAX_SCAN_PART (50) +#define MAX_RETRY_COUNT (0x100000) + +static dev_t find_devt_for_test(struct exynos_fmp *fmp, + struct fmp_test_data *data) +{ + int i, idx = 0; + uint32_t count = 0; + uint64_t size; + uint64_t size_list[MAX_SCAN_PART]; + dev_t devt_list[MAX_SCAN_PART]; + dev_t devt_scan = 0; + dev_t devt = 0; + struct block_device *bdev = NULL; + struct device *dev = fmp->dev; + fmode_t fmode = FMODE_WRITE | FMODE_READ; + + memset(size_list, 0, sizeof(size_list)); + memset(devt_list, 0, sizeof(devt_list)); + do { + for (i = 1; i < MAX_SCAN_PART; i++) { + devt_scan = blk_lookup_devt(data->block_type, i); + bdev = blkdev_get_by_dev(devt_scan, fmode, NULL); + if (IS_ERR(bdev)) + continue; + else { + size_list[idx] = + (uint64_t) i_size_read(bdev->bd_inode); + devt_list[idx++] = devt_scan; + blkdev_put(bdev, fmode); + } + } + if (!idx) { + mdelay(100); + count++; + continue; + } + for (i = 0; i < idx; i++) { + if (i == 0) { + size = size_list[i]; + devt = devt_list[i]; + } else { + if (size < size_list[i]) + devt = devt_list[i]; + } + } + bdev = blkdev_get_by_dev(devt, fmode, NULL); + dev_dbg(dev, "Found partno %d for FMP test\n", + bdev->bd_part->partno); + blkdev_put(bdev, fmode); + return devt; + } while (count < MAX_RETRY_COUNT); + dev_err(dev, "Block device isn't initialized yet for FMP test\n"); + return (dev_t) 0; +} + +static int get_fmp_host_type(struct device *dev, + struct fmp_test_data *data) +{ + int ret; + struct device_node *node = dev->of_node; + const char *type; + + ret = + of_property_read_string_index(node, "exynos,block-type", 0, &type); + if (ret) { + pr_err("%s: Could not get block type\n", __func__); + return ret; + } + strscpy(data->block_type, type, FMP_BLOCK_TYPE_NAME_LEN); + return 0; +} + +static int get_fmp_test_block_offset(struct device *dev, + struct fmp_test_data *data) +{ + int ret = 0; + struct device_node *node = dev->of_node; + uint32_t offset; + + ret = of_property_read_u32(node, "exynos,fips-block_offset", &offset); + if (ret) { + pr_err("%s: Could not get fips test block offset\n", __func__); + ret = -EINVAL; + goto err; + } + data->test_block_offset = offset; +err: + return ret; +} + +/* test block device init for fmp test */ +struct fmp_test_data *fmp_test_init(struct exynos_fmp *fmp) +{ + int ret = 0; + struct fmp_test_data *data; + struct device *dev; + struct inode *inode; + struct super_block *sb; + unsigned long blocksize; + unsigned char blocksize_bits; + fmode_t fmode = FMODE_WRITE | FMODE_READ; + + if (!fmp) { + pr_err("%s: Invalid exynos fmp struct\n", __func__); + return NULL; + } + + dev = fmp->dev; + data = kmalloc(sizeof(struct fmp_test_data), GFP_KERNEL); + if (!data) + return NULL; + + ret = get_fmp_host_type(dev, data); + if (ret) { + dev_err(dev, "%s: Fail to get host type. ret(%d)", __func__, + ret); + goto err; + } + data->devt = find_devt_for_test(fmp, data); + if (!data->devt) { + dev_err(dev, "%s: Fail to find devt for self test\n", __func__); + goto err; + } + data->bdev = blkdev_get_by_dev(data->devt, fmode, NULL); + if (IS_ERR(data->bdev)) { + dev_err(dev, "%s: Fail to open block device\n", __func__); + goto err; + } + ret = get_fmp_test_block_offset(dev, data); + if (ret) { + dev_err(dev, "%s: Fail to get fips offset. ret(%d)\n", + __func__, ret); + goto err; + } + inode = data->bdev->bd_inode; + sb = inode->i_sb; + blocksize = sb->s_blocksize; + blocksize_bits = sb->s_blocksize_bits; + data->sector = + (i_size_read(inode) - + (blocksize * data->test_block_offset)) >> blocksize_bits; + + return data; +err: + kzfree(data); + return NULL; +} + +int fmp_cipher_run(struct exynos_fmp *fmp, struct fmp_test_data *fdata, + uint8_t *data, uint32_t len, bool bypass, uint32_t write, + void *priv, struct fmp_crypto_info *ci) +{ + int ret = 0; + struct device *dev; + static struct buffer_head *bh; + u32 org_algo_mode; + int op_flags; + + if (!fmp || !fdata || !ci) { + pr_err("%s: Invalid fmp struct: %p, %p, %p\n", + __func__, fmp, fdata, ci); + return -EINVAL; + } + dev = fmp->dev; + + bh = __getblk(fdata->bdev, fdata->sector, FMP_BLK_SIZE); + if (!bh) { + dev_err(dev, "%s: Fail to get block from bdev\n", __func__); + return -ENODEV; + } + + /* set algo_mode for test */ + org_algo_mode = ci->algo_mode; + if (bypass) + ci->algo_mode = EXYNOS_FMP_BYPASS_MODE; + ci->algo_mode |= EXYNOS_FMP_ALGO_MODE_TEST; + + get_bh(bh); + /* priv is diskc for crypto test. */ + if (!priv) { + /* ci is fmp_test_data->ci */ + fmp->test_data = fdata; + ci->ctx = fmp; + ci->use_diskc = 0; + ci->enc_mode = EXYNOS_FMP_FILE_ENC; + bh->b_private = ci; + } else { + /* ci is crypto_tfm_ctx(tfm) */ + bh->b_private = priv; + } + op_flags = REQ_CRYPT; + + if (write == WRITE_MODE) { + memcpy(bh->b_data, data, len); + set_buffer_dirty(bh); + ret = __sync_dirty_buffer(bh, op_flags | REQ_SYNC); + if (ret) { + dev_err(dev, "%s: IO error syncing for write mode\n", + __func__); + ret = -EIO; + goto out; + } + memset(bh->b_data, 0, FMP_BLK_SIZE); + } else { + lock_buffer(bh); + bh->b_end_io = end_buffer_read_sync; + submit_bh(REQ_OP_READ, REQ_SYNC | REQ_PRIO | op_flags, bh); + wait_on_buffer(bh); + if (unlikely(!buffer_uptodate(bh))) { + ret = -EIO; + goto out; + } + memcpy(data, bh->b_data, len); + } +out: + if (ci) + ci->algo_mode = org_algo_mode; + put_bh(bh); + return ret; +} + +int fmp_test_crypt(struct exynos_fmp *fmp, struct fmp_test_data *fdata, + uint8_t *src, uint8_t *dst, uint32_t len, uint32_t enc, + void *priv, struct fmp_crypto_info *ci) +{ + int ret = 0; + + if (!fdata) { + pr_err("%s: Invalid exynos fmp struct\n", __func__); + return -1; + } + + if (enc == ENCRYPT) { + ret = fmp_cipher_run(fmp, fdata, src, len, 0, + WRITE_MODE, priv, ci); + if (ret) { + pr_err("Fail to run fmp cipher ret(%d)\n", + ret); + goto err; + } + ret = fmp_cipher_run(fmp, fdata, dst, len, 1, + READ_MODE, priv, ci); + if (ret) { + pr_err("Fail to run fmp cipher ret(%d)\n", + ret); + goto err; + } + } else if (enc == DECRYPT) { + ret = fmp_cipher_run(fmp, fdata, src, len, 1, + WRITE_MODE, priv, ci); + if (ret) { + pr_err("Fail to run fmp cipher ret(%d)\n", + ret); + goto err; + } + ret = fmp_cipher_run(fmp, fdata, dst, len, 0, + READ_MODE, priv, ci); + if (ret) { + pr_err("Fail to run fmp cipher ret(%d)\n", + ret); + goto err; + } + } else { + pr_err("%s: Invalid enc %d mode\n", __func__, enc); + goto err; + } + + return 0; +err: + return -EINVAL; +} + +/* test block device release for fmp test */ +void fmp_test_exit(struct fmp_test_data *fdata) +{ + fmode_t fmode = FMODE_WRITE | FMODE_READ; + + if (!fdata) { + pr_err("%s: Invalid exynos fmp struct\n", __func__); + return; + } + if (fdata->bdev) + blkdev_put(fdata->bdev, fmode); + kzfree(fdata); +} diff --git a/drivers/crypto/fmp/fmp_test.h b/drivers/crypto/fmp/fmp_test.h new file mode 100644 index 0000000..42af22a --- /dev/null +++ b/drivers/crypto/fmp/fmp_test.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2016 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _FMP_TEST_H_ +#define _FMP_TEST_H_ + +#define FMP_BLK_SIZE (4096) + +#define WRITE_MODE 1 +#define READ_MODE 2 + +#define ENCRYPT 1 +#define DECRYPT 2 + +struct fmp_test_data *fmp_test_init(struct exynos_fmp *fmp); +int fmp_cipher_run(struct exynos_fmp *fmp, struct fmp_test_data *fdata, + uint8_t *data, uint32_t len, bool bypass, uint32_t write, + void *priv, struct fmp_crypto_info *ci); +int fmp_test_crypt(struct exynos_fmp *fmp, struct fmp_test_data *fdata, + uint8_t *src, uint8_t *dst, uint32_t len, uint32_t enc, + void *priv, struct fmp_crypto_info *ci); +void fmp_test_exit(struct fmp_test_data *fdata); +#endif /* _FMP_TEST_H_ */ diff --git a/include/crypto/fmp.h b/include/crypto/fmp.h new file mode 100644 index 0000000..b0ac483 --- /dev/null +++ b/include/crypto/fmp.h @@ -0,0 +1,324 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2016 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _EXYNOS_FMP_H_ +#define _EXYNOS_FMP_H_ + +#include +#include + +#define FMP_DRV_VERSION "1.5.0" + +#define FMP_KEY_SIZE_16 16 +#define FMP_KEY_SIZE_32 32 +#define FMP_IV_SIZE_16 16 + +#define FMP_CBC_MAX_KEY_SIZE FMP_KEY_SIZE_16 +#define FMP_XTS_MAX_KEY_SIZE ((FMP_KEY_SIZE_32) * (2)) +#define FMP_MAX_KEY_SIZE FMP_XTS_MAX_KEY_SIZE + +#define FMP_HOST_TYPE_NAME_LEN 8 +#define FMP_BLOCK_TYPE_NAME_LEN 8 + +#define FMP_SECTOR_SIZE 0x1000 +#define FMP_MIN_SECTOR_SIZE 0x200 +#define NUM_SECTOR_UNIT ((FMP_SECTOR_SIZE)/(FMP_MIN_SECTOR_SIZE)) + +#define MAX_AES_XTS_TRANSFER_SIZE 0x1000 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +enum fmp_crypto_algo_mode { + EXYNOS_FMP_BYPASS_MODE = 0, + EXYNOS_FMP_ALGO_MODE_AES_CBC = 1, + EXYNOS_FMP_ALGO_MODE_AES_XTS = 2, +}; + +enum fmp_crypto_key_size { + EXYNOS_FMP_KEY_SIZE_16 = 16, + EXYNOS_FMP_KEY_SIZE_32 = 32, +}; + +enum fmp_crypto_enc_mode { + EXYNOS_FMP_FILE_ENC = 0, + EXYNOS_FMP_DISK_ENC = 1, /* use persistent key */ + EXYNOS_FMP_ENC_MAX +}; + +enum fmp_disk_key_status { + KEY_STORED = 0, + KEY_SET = 1, + KEY_CLEAR = 2, + KEY_ERROR = -1, +}; + +struct fmp_crypto_info { + /* This field's stongly aligned 'crypto_diskcipher->algo' */ + u32 use_diskc; + u8 key[FMP_MAX_KEY_SIZE]; + u32 key_size; + enum fmp_crypto_key_size fmp_key_size; + enum fmp_crypto_enc_mode enc_mode; + enum fmp_crypto_algo_mode algo_mode; + void *ctx; +}; + +#if defined(CONFIG_MMC_DW_EXYNOS_FMP) && defined(CONFIG_SCSI_UFS_EXYNOS_FMP) +#error "FMP doesn't support muti-host" +#elif defined(CONFIG_MMC_DW_EXYNOS_FMP) +struct fmp_table_setting { + __le32 des0; /* des0 */ +#define GET_CMDQ_LENGTH(d) \ + (((d)->des0 & 0xffff0000) >> 16) + __le32 des1; /* des1 */ + __le32 des2; /* des2 */ +#define FKL BIT(26) +#define DKL BIT(27) +#define SET_KEYLEN(d, v) ((d)->des2 |= (uint32_t)v) +#define SET_FAS(d, v) \ + ((d)->des2 = ((d)->des2 & 0xcfffffff) | v << 28) +#define SET_DAS(d, v) \ + ((d)->des2 = ((d)->des2 & 0x3fffffff) | v << 30) +#define GET_FAS(d) ((d)->des2 & 0x30000000) +#define GET_DAS(d) ((d)->des2 & 0xc0000000) +#define GET_LENGTH(d) \ + ((d)->des2 & 0x3ffffff) + __le32 des3; /* des3 */ + /* CMDQ Operation */ +#define FKL_CMDQ BIT(0) +#define DKL_CMDQ BIT(1) +#define SET_CMDQ_KEYLEN(d, v) ((d)->des2 |= (uint32_t)v) +#define SET_CMDQ_FAS(d, v) \ + ((d)->des3 = ((d)->des3 & 0xfffffff3) | v << 2) +#define SET_CMDQ_DAS(d, v) \ + ((d)->des3 = ((d)->des3 & 0xffffffcf) | v << 4) +#define GET_CMDQ_FAS(d) ((d)->des3 & 0x0000000c) +#define GET_CMDQ_DAS(d) ((d)->des3 & 0x00000030) + __le32 reserved0; /* des4 */ + __le32 reserved1; + __le32 reserved2; + __le32 reserved3; + __le32 file_iv0; /* des8 */ + __le32 file_iv1; + __le32 file_iv2; + __le32 file_iv3; + __le32 file_enckey0; /* des12 */ + __le32 file_enckey1; + __le32 file_enckey2; + __le32 file_enckey3; + __le32 file_enckey4; + __le32 file_enckey5; + __le32 file_enckey6; + __le32 file_enckey7; + __le32 file_twkey0; /* des20 */ + __le32 file_twkey1; + __le32 file_twkey2; + __le32 file_twkey3; + __le32 file_twkey4; + __le32 file_twkey5; + __le32 file_twkey6; + __le32 file_twkey7; + __le32 disk_iv0; /* des28 */ + __le32 disk_iv1; + __le32 disk_iv2; + __le32 disk_iv3; +}; +#elif defined(CONFIG_SCSI_UFS_EXYNOS_FMP) +struct fmp_table_setting { + __le32 des0; /* des0 */ +#define GET_CMDQ_LENGTH(d) \ + (((d)->des0 & 0xffff0000) >> 16) + __le32 des1; /* des1 */ + __le32 des2; /* des2 */ + __le32 des3; /* des3 */ +/* Legacy Operation */ +#define FKL BIT(26) +#define DKL BIT(27) +#define SET_KEYLEN(d, v) ((d)->des3 |= (uint32_t)v) +#define SET_FAS(d, v) \ + ((d)->des3 = ((d)->des3 & 0xcfffffff) | v << 28) +#define SET_DAS(d, v) \ + ((d)->des3 = ((d)->des3 & 0x3fffffff) | v << 30) +#define GET_FAS(d) ((d)->des3 & 0x30000000) +#define GET_DAS(d) ((d)->des3 & 0xc0000000) +#define GET_LENGTH(d) \ + ((d)->des3 & 0x3ffffff) +/* CMDQ Operation */ +#define FKL_CMDQ BIT(0) +#define DKL_CMDQ BIT(1) +#define SET_CMDQ_KEYLEN(d, v) ((d)->des3 |= (uint32_t)v) +#define SET_CMDQ_FAS(d, v) \ + ((d)->des3 = ((d)->des3 & 0xfffffff3) | v << 2) +#define SET_CMDQ_DAS(d, v) \ + ((d)->des3 = ((d)->des3 & 0xffffffcf) | v << 4) +#define GET_CMDQ_FAS(d) ((d)->des3 & 0x0000000c) +#define GET_CMDQ_DAS(d) ((d)->des3 & 0x00000030) + __le32 file_iv0; /* des4 */ + __le32 file_iv1; /* des5 */ + __le32 file_iv2; /* des6 */ + __le32 file_iv3; /* des7 */ + __le32 file_enckey0; /* des8 */ + __le32 file_enckey1; /* des9 */ + __le32 file_enckey2; /* des10 */ + __le32 file_enckey3; /* des11 */ + __le32 file_enckey4; /* des12 */ + __le32 file_enckey5; /* des13 */ + __le32 file_enckey6; /* des14 */ + __le32 file_enckey7; /* des15 */ + __le32 file_twkey0; /* des16 */ + __le32 file_twkey1; /* des17 */ + __le32 file_twkey2; /* des18 */ + __le32 file_twkey3; /* des19 */ + __le32 file_twkey4; /* des20 */ + __le32 file_twkey5; /* des21 */ + __le32 file_twkey6; /* des22 */ + __le32 file_twkey7; /* des23 */ + __le32 disk_iv0; /* des24 */ + __le32 disk_iv1; /* des25 */ + __le32 disk_iv2; /* des26 */ + __le32 disk_iv3; /* des27 */ + __le32 reserved0; /* des28 */ + __le32 reserved1; /* des29 */ + __le32 reserved2; /* des30 */ + __le32 reserved3; /* des31 */ +}; +#endif + +struct fmp_data_setting { + struct fmp_crypto_info crypt[EXYNOS_FMP_ENC_MAX]; + struct fmp_table_setting *table; + bool cmdq_enabled; +}; + +#define EXYNOS_FMP_ALGO_MODE_MASK (0x3) +#define EXYNOS_FMP_ALGO_MODE_TEST_OFFSET (0xf) +#define EXYNOS_FMP_ALGO_MODE_TEST (1 << EXYNOS_FMP_ALGO_MODE_TEST_OFFSET) + +struct fmp_test_data { + char block_type[FMP_BLOCK_TYPE_NAME_LEN]; + struct block_device *bdev; + sector_t sector; + dev_t devt; + uint32_t test_block_offset; + /* iv to submitted */ + u8 iv[FMP_IV_SIZE_16]; + /* diskcipher for test */ + struct fmp_crypto_info ci; +}; + +struct exynos_fmp { + struct device *dev; + enum fmp_disk_key_status status_disk_key; + struct fmp_test_data *test_data; +}; + +struct fmp_request { + void *table; + bool cmdq_enabled; + void *iv; + u32 ivsize; +}; + +static inline void exynos_fmp_bypass(void *desc, bool cmdq_enabled) +{ +#if defined(CONFIG_MMC_DW_EXYNOS_FMP) || defined(CONFIG_SCSI_UFS_EXYNOS_FMP) + if (cmdq_enabled) { + SET_CMDQ_FAS((struct fmp_table_setting *)desc, 0); + SET_CMDQ_DAS((struct fmp_table_setting *)desc, 0); + } else { + SET_FAS((struct fmp_table_setting *)desc, 0); + SET_DAS((struct fmp_table_setting *)desc, 0); + } +#endif +} + +#define ACCESS_CONTROL_ABORT 0x14 + +#ifndef SMC_CMD_FMP_SECURITY +/* For FMP/SMU Ctrl */ +#define SMC_CMD_FMP_SECURITY (0xC2001810) +#define SMC_CMD_FMP_DISK_KEY_STORED (0xC2001820) +#define SMC_CMD_FMP_DISK_KEY_SET (0xC2001830) +#define SMC_CMD_FMP_DISK_KEY_CLEAR (0xC2001840) +#define SMC_CMD_SMU (0xC2001850) +#define SMC_CMD_FMP_SMU_RESUME (0xC2001860) +#define SMC_CMD_FMP_SMU_DUMP (0xC2001870) +#define SMC_CMD_UFS_LOG (0xC2001880) + +/* For FMP/SMU Ctrl */ +#define SMC_CMD_FMP_SECURITY (0xC2001810) +#define SMC_CMD_FMP_DISK_KEY_STORED (0xC2001820) +#define SMC_CMD_FMP_DISK_KEY_SET (0xC2001830) +#define SMC_CMD_FMP_DISK_KEY_CLEAR (0xC2001840) +#define SMC_CMD_SMU (0xC2001850) +#define SMC_CMD_FMP_SMU_RESUME (0xC2001860) +#define SMC_CMD_FMP_SMU_DUMP (0xC2001870) +#define SMC_CMD_UFS_LOG (0xC2001880) +#endif + +enum smu_id { + SMU_EMBEDDED = 0, + SMU_UFSCARD = 1, + SMU_SDCARD = 2, + SMU_ID_MAX, +}; + +enum smu_command { + SMU_INIT = 0, + SMU_SET = 1, + SMU_ABORT = 2, +}; + +/* fmp functions */ +#ifdef CONFIG_EXYNOS_FMP +int exynos_fmp_sec_cfg(int fmp_id, int smu_id, bool init); +int exynos_fmp_smu_abort(int id); +int exynos_fmp_crypt_cfg(struct bio *bio, void *table_base, + u32 page_idx, u32 sector_unit); +int exynos_fmp_crypt_clear(struct bio *bio, void *table_addr); +#else +int exynos_fmp_sec_cfg(int fmp_id, int smu_id, bool init) +{ + return 0; +} + +int exynos_fmp_smu_abort(int id) +{ + return 0; +} + +int exynos_fmp_crypt_cfg(struct bio *bio, void *table_base, + u32 page_idx, u32 sector_unit) +{ + return 0; +} + +int exynos_fmp_crypt_clear(struct bio *bio, void *table_addr) +{ + return 0; +} +#endif +int exynos_fmp_crypt(struct fmp_crypto_info *ci, void *priv); +int exynos_fmp_clear(struct fmp_crypto_info *ci, void *priv); +int exynos_fmp_setkey(struct fmp_crypto_info *ci, + u8 *in_key, u32 keylen, bool persistent); +int exynos_fmp_clearkey(struct fmp_crypto_info *ci); +void *exynos_fmp_init(struct platform_device *pdev); +void exynos_fmp_exit(struct exynos_fmp *fmp); +int exynos_fmp_test_crypt(struct fmp_crypto_info *ci, + const uint8_t *iv, uint32_t ivlen, uint8_t *src, From patchwork Wed Aug 21 06:42:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "boojin.kim" X-Patchwork-Id: 11105689 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A8B111399 for ; Wed, 21 Aug 2019 06:43:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 72054206BA for ; Wed, 21 Aug 2019 06:43:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="EyrZTewc" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728319AbfHUGnQ (ORCPT ); Wed, 21 Aug 2019 02:43:16 -0400 Received: from mailout4.samsung.com ([203.254.224.34]:52650 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727894AbfHUGmY (ORCPT ); Wed, 21 Aug 2019 02:42:24 -0400 Received: from epcas2p1.samsung.com (unknown [182.195.41.53]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20190821064221epoutp049a9fa6154317805c7f4e99192bd61ec7~83PstpqXw1247612476epoutp04W for ; Wed, 21 Aug 2019 06:42:21 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20190821064221epoutp049a9fa6154317805c7f4e99192bd61ec7~83PstpqXw1247612476epoutp04W DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1566369741; bh=XmvgRUmAe2wKYHiaDqlBZGz349t74yQ9imYtStg6lHE=; h=From:To:Cc:Subject:Date:References:From; b=EyrZTewcBbnxZ2ulz/otdpewDqEruz8Gud79PDG0yCy8/AeusfGxfVhKuVwJt8Pf2 SL0wiJqUSv0zYKfIsddwCagVIWTGRUImgR1K7TCBBnotK2s1AZAsg81SMgoJvNXp56 Rjxco0dg2OmIqVhl3gJ8bwZ39Vh4YGf39hZWq8v0= Received: from epsnrtp5.localdomain (unknown [182.195.42.166]) by epcas2p2.samsung.com (KnoxPortal) with ESMTP id 20190821064221epcas2p2684e6115ac12d837c9b5307f2df57c40~83PsF4bp_1369213692epcas2p2c; Wed, 21 Aug 2019 06:42:21 +0000 (GMT) Received: from epsmges2p3.samsung.com (unknown [182.195.40.186]) by epsnrtp5.localdomain (Postfix) with ESMTP id 46Cykz5DwgzMqYkn; Wed, 21 Aug 2019 06:42:19 +0000 (GMT) Received: from epcas2p3.samsung.com ( [182.195.41.55]) by epsmges2p3.samsung.com (Symantec Messaging Gateway) with SMTP id 2B.23.04068.BC7EC5D5; Wed, 21 Aug 2019 15:42:19 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p2.samsung.com (KnoxPortal) with ESMTPA id 20190821064219epcas2p28b42391923012ecc7875313b8b2b9a1a~83PqdlOeq1149811498epcas2p2u; Wed, 21 Aug 2019 06:42:19 +0000 (GMT) Received: from epsmgms1p2new.samsung.com (unknown [182.195.42.42]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20190821064219epsmtrp298889ca36b32f346ee40f3eadb0b6908~83PqcX4JK2201622016epsmtrp2V; Wed, 21 Aug 2019 06:42:19 +0000 (GMT) X-AuditID: b6c32a47-5a1ff70000000fe4-6f-5d5ce7cb27a6 Received: from epsmtip1.samsung.com ( [182.195.34.30]) by epsmgms1p2new.samsung.com (Symantec Messaging Gateway) with SMTP id F8.D2.03638.BC7EC5D5; Wed, 21 Aug 2019 15:42:19 +0900 (KST) Received: from KORDO035251 (unknown [12.36.165.204]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20190821064218epsmtip16b10bb697269b2ad72f00b6d9cd76543~83Pp9CBw40460704607epsmtip1E; Wed, 21 Aug 2019 06:42:18 +0000 (GMT) From: "boojin.kim" To: "'Jaehoon Chung'" , "'Ulf Hansson'" , , Cc: "'Herbert Xu'" , "'David S. Miller'" , "'Eric Biggers'" , "'Theodore Y. Ts'o'" , "'Chao Yu'" , "'Jaegeuk Kim'" , "'Andreas Dilger'" , "'Theodore Ts'o'" , , "'Mike Snitzer'" , "'Alasdair Kergon'" , "'Jens Axboe'" , "'Krzysztof Kozlowski'" , "'Kukjin Kim'" , "'Jaehoon Chung'" , "'Ulf Hansson'" , , , , , , , , , , , Subject: [PATCH 3/9] mmc: dw_mmc: support crypto operation Date: Wed, 21 Aug 2019 15:42:18 +0900 Message-ID: <003f01d557eb$94210260$bc630720$@samsung.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 14.0 Thread-Index: AdVX6DWbOAXQrOkmQ/qY5VJQXNywng== Content-Language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA01Tf0xTVxjN7fvRh6PyrIzdNZuWN1kCBmxhxUsHc3FmvmT+wVy2JU6GL/DS MtrXrq9luCwTN9YhNmNkuthSicGpWx1BW4bEUX9UBlPsKiOgJXVkk8xIFRWQBHFuLQ8z/jv3 fOfk+8798lGY0i1XUVWCnbcJnIkhl+FdF7LX5w7c3F6mOdGfgx7MNOCo41Ifho5fbyLRwP6w DHkj9TgKTrYQqL3nEYb2TjyHxjs8GLr20EmgphtxDEUiJ+TIf2OEQMHRtWjsjzkZcrfGSPR7 22Y00TqLo57gRRwNnfaSqPffJoAORM7IkPPkA4C+cM3JUX/7u68+y3b+EJWx9YGP2K5zWexQ 2MH6fXtINjbSQ7KB73axPx+alrGfXf4FY++eGSbZrzp9gJ32rypN3WYqNvJcJW9T80KFpbJK MJQwb7xV/lq5rlCjzdUWofWMWuDMfAmzaUtp7utVpkR2Rl3DmRwJqpQTRWbdK8U2i8POq40W 0V7C8NZKk1WrteaJnFl0CIa8CotZr9Vo8nUJ5Q6Tsfl8vdx6O6PWN3MEqwNeZSNIoSD9Erx0 9STRCJZRSrobwCOueVJ6TAF4/Nv7WFKlpGcBPDf84RNH29m4TOKDALonVkmGWwD2heeJZIGk 18JAvw8kcTrtThSaPkiKMPqxHI5PhfBkYSWth1dibQsYp7Pg/c/H5EmsoIvgwZFBQsIr4EX3 +IIGo1fDU3e8mDSFGnaH44sN8mDz+SAmadJhyx4nlmwG6d0U7P2+G5cMm2B09h6Q8Eo40d8p l7AKTk8GSQnvgsNHD8slswvAyw+di6IC6Pn7y4SZSnTIhh2n1yUhpF+AvaOLsy2HDRf+kUu0 AjY4F793DTw4NSSTaBW85/pUolkYntyPfw0yPUtCepaE9CwJ4/m/7SGA+0AGbxXNBl7MtxYs 3bUfLJxFzuZu0PXblhCgKcCkKnZcfa9MSXA14k5zCEAKY9IVtd5tZUpFJbfzY95mKbc5TLwY ArrEDpox1dMVlsSRCfZyrS6/sFBTpEO6wnzEPKPwPxXdrqQNnJ2v5nkrb3vik1EpqjqgXR4t 1g8W11UTb26cTOF3Z1+7XVc7emUsPHBzQx/oPHbnr2/2nk0THvXNv5xx3RlYcTj64ttVKWPu A60hB7obmM/8aV+avjHeG/x1aPUooTf8KPsk8/Gt9ngGZ3w+q+ao1jVY/U5sw/stM+z0xups wb8m7U+d/pQxYoRzdCx1awGDi0ZOm4PZRO4/ucmGcSwEAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrNIsWRmVeSWpSXmKPExsWy7bCSnO7p5zGxBi97eC2+fulgsVh/6hiz xeq7/WwWp6eeZbKYc76FxWLvu9msFmv3/GG26H4lY/Fk/Sxmixu/2lgt+h+/ZrY4f34Du8Wm x9dYLfbe0ra4f+8nk8XMeXfYLC4tcrd4Ne8bi8WevSdZLC7vmsNmceR/P6PFjPP7mCzaNn5l tGjt+clucXxtuIOkx5aVN5k8WjaXe2w7oOpx+Wypx6ZVnWwed67tYfPYvKTeY/eCz0weTWeO Mnu833eVzaNvyypGj8+b5AJ4orhsUlJzMstSi/TtErgyJh5sYS94I1ax6stS5gbGOUJdjJwc EgImEov2v2bqYuTiEBLYzSgxtfEKC0RCSmJr+x5mCFtY4n7LEVYQW0jgOaPEt8+FIDabgLbE 5uOrGEGaRQRmM0r8vfCcESTBLDCNQ2LXB3EQW1jASuLCnUVgQ1kEVCU+Nt9nB7F5BSwl5l67 yAphC0qcnPkEqIYDqFdPom0j1Bh5ie1v50DdoCCx4+xrsLgIUMnEg3uZIWpEJGZ3tjFPYBSc hWTSLIRJs5BMmoWkYwEjyypGydSC4tz03GLDAqO81HK94sTc4tK8dL3k/NxNjOAkoKW1g/HE ifhDjAIcjEo8vDtuRscKsSaWFVfmHmKU4GBWEuGtmBMVK8SbklhZlVqUH19UmpNafIhRmoNF SZxXPv9YpJBAemJJanZqakFqEUyWiYNTqoGR49ZSiUbF4w+XLgwVlV/2UZDZY92+iayFwY3L v+bcvnBgy2Hj5/d9cuZvKKx9knfhhufxzt3XzL7IF394pJ4V8+Ps/nRuD8UXam99dwm7buxL uOYx4ca6B/I1HAd3lohFZ95rkbgtb7yv68NNbfbzSq7Td97fa2Biz3mj8+X0jvWFobp6Nx96 K7EUZyQaajEXFScCAOfGz5v+AgAA X-CMS-MailID: 20190821064219epcas2p28b42391923012ecc7875313b8b2b9a1a X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20190821064219epcas2p28b42391923012ecc7875313b8b2b9a1a References: Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org This patch supports the crypto operation in mmc driver. Two vops are added to dw_mci_drv_data for it. The crypto_engine_cfg() is required to set crypto information such as key and algorithm modes before I/O. The crypto_engine_clear() is required to clear the crypto information set in the H/W after I/O. Cc: Jaehoon Chung Cc: Ulf Hansson Signed-off-by: Boojin Kim --- drivers/mmc/host/dw_mmc.c | 22 +++++++++++++++++++++- drivers/mmc/host/dw_mmc.h | 6 ++++++ 2 files changed, 27 insertions(+), 1 deletion(-) #endif /* _DW_MMC_H_ */ diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index eea52e2..0cdf574 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -470,6 +470,7 @@ static void dw_mci_dmac_complete_dma(void *arg) { struct dw_mci *host = arg; struct mmc_data *data = host->data; + const struct dw_mci_drv_data *drv_data = host->drv_data; dev_vdbg(host->dev, "DMA complete\n"); @@ -481,6 +482,9 @@ static void dw_mci_dmac_complete_dma(void *arg) data->sg_len, DMA_FROM_DEVICE); + if (drv_data && drv_data->crypto_engine_clear) + drv_data->crypto_engine_clear(host, host->sg_cpu, false); + host->dma_ops->cleanup(host); /* @@ -577,8 +581,10 @@ static inline int dw_mci_prepare_desc64(struct dw_mci *host, { unsigned int desc_len; struct idmac_desc_64addr *desc_first, *desc_last, *desc; + int i, ret; + const struct dw_mci_drv_data *drv_data = host->drv_data; + int sector_offset = 0; u32 val; - int i; desc_first = desc_last = desc = host->sg_cpu; @@ -618,6 +624,20 @@ static inline int dw_mci_prepare_desc64(struct dw_mci *host, desc->des4 = mem_addr & 0xffffffff; desc->des5 = mem_addr >> 32; + if (drv_data && drv_data->crypto_engine_cfg) { + ret = drv_data->crypto_engine_cfg(host, desc, + data, sg_page(&data->sg[i]), i, + sector_offset, false); + if (ret) { + dev_err(host->dev, + "%s: fail to set crypto(%d)\n", + __func__, ret); + return -EPERM; + } + /* mmc sector size */ + sector_offset += desc_len / 512; + } + /* Update physical address for the next desc */ mem_addr += desc_len; diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index da5923a..b32d39b 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -563,5 +563,11 @@ struct dw_mci_drv_data { struct mmc_ios *ios); int (*switch_voltage)(struct mmc_host *mmc, struct mmc_ios *ios); + int (*crypto_engine_cfg)(struct dw_mci *host, void *desc, + struct mmc_data *data, struct page *page, + int page_offset, int sector_offset, + bool cmdq_enabled); + int (*crypto_engine_clear)(struct dw_mci *host, + void *desc, bool cmdq_enabled); }; From patchwork Wed Aug 21 06:42:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "boojin.kim" X-Patchwork-Id: 11105679 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 464131399 for ; Wed, 21 Aug 2019 06:43:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 117D42089E for ; Wed, 21 Aug 2019 06:43:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="clS10835" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728091AbfHUGnM (ORCPT ); Wed, 21 Aug 2019 02:43:12 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:10161 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728086AbfHUGmb (ORCPT ); Wed, 21 Aug 2019 02:42:31 -0400 Received: from epcas2p1.samsung.com (unknown [182.195.41.53]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20190821064227epoutp01be42e9d2416edec794c39181c9de1bd4~83Px_IBtr1005210052epoutp019 for ; Wed, 21 Aug 2019 06:42:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20190821064227epoutp01be42e9d2416edec794c39181c9de1bd4~83Px_IBtr1005210052epoutp019 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1566369747; bh=RufiVNT5+Lb2KOyQZLDZhzg9HYJCDXGJWlH0uDh9Bn0=; h=From:To:Cc:Subject:Date:References:From; b=clS10835/affNGODFrWo2NUHKtnZdFS5lP+/Aw0A0qBoqhK7QHQ73e6PeySgDsPPs hA3xePmpCtsxVnPnPa6b8QZe6cCy7LM52IiYYce3ekI0ze+cbhc8gyydsTEqHxCCoq ZVGxIeV2mqit5FKe6+6VHbiGTkuA5I9Z+1LrNWcQ= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas2p1.samsung.com (KnoxPortal) with ESMTP id 20190821064226epcas2p1753a8812f10c55908a889b5f613f6935~83PxEH5Fd0242202422epcas2p1s; Wed, 21 Aug 2019 06:42:26 +0000 (GMT) Received: from epsmges2p4.samsung.com (unknown [182.195.40.189]) by epsnrtp2.localdomain (Postfix) with ESMTP id 46Cyl36Fy8zMqYkf; Wed, 21 Aug 2019 06:42:23 +0000 (GMT) Received: from epcas2p1.samsung.com ( [182.195.41.53]) by epsmges2p4.samsung.com (Symantec Messaging Gateway) with SMTP id 7C.0F.04112.FC7EC5D5; Wed, 21 Aug 2019 15:42:23 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas2p1.samsung.com (KnoxPortal) with ESMTPA id 20190821064223epcas2p18a14724427711e22c6c76b24bce1c8e0~83PuUy3oh1228312283epcas2p1R; Wed, 21 Aug 2019 06:42:23 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20190821064223epsmtrp10047dd5905b9e4fa8ae715493939ee58~83PuTsqjI2011020110epsmtrp1X; Wed, 21 Aug 2019 06:42:23 +0000 (GMT) X-AuditID: b6c32a48-f1fff70000001010-90-5d5ce7cfaa31 Received: from epsmtip1.samsung.com ( [182.195.34.30]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 8D.02.03706.FC7EC5D5; Wed, 21 Aug 2019 15:42:23 +0900 (KST) Received: from KORDO035251 (unknown [12.36.165.204]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20190821064222epsmtip169b78fa5e45597d9ba7e035be2ddd798~83PtgT-AE0460704607epsmtip1G; Wed, 21 Aug 2019 06:42:22 +0000 (GMT) From: "boojin.kim" To: "'Ulf Hansson'" , "'Kukjin Kim'" , "'Krzysztof Kozlowski'" , , , , Cc: "'Herbert Xu'" , "'David S. Miller'" , "'Eric Biggers'" , "'Theodore Y. Ts'o'" , "'Chao Yu'" , "'Jaegeuk Kim'" , "'Andreas Dilger'" , "'Theodore Ts'o'" , , "'Mike Snitzer'" , "'Alasdair Kergon'" , "'Jens Axboe'" , "'Krzysztof Kozlowski'" , "'Kukjin Kim'" , "'Jaehoon Chung'" , "'Ulf Hansson'" , , , , , , , , , , , Subject: [PATCH 4/9] mmc: dw_mmc-exynos: support FMP Date: Wed, 21 Aug 2019 15:42:22 +0900 Message-ID: <004001d557eb$9697f5d0$c3c7e170$@samsung.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 14.0 Thread-Index: AdVX6FzCeDd/I620REGbQnBHWgE56Q== Content-Language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA01TbUxTVxjOuV8taJdr6bZjs7h6h1vAgb0d7Q4OFpPpvIkuqdmPJSphN3BH if2yt3Uwk0mUVUQEpjMZbSWEmUW7mc7SuCKUmeIkKKzLmN1AYYswP2CuCyALOHEtt2T8e973 fZ7zvE/eHDmu9MnU8kqrU3BYeTNDZRKXenP0ebF7e0u08dM69Gi2jkCB69dw9NVoE4VunB7E kC9WS6DIX14SXej+F0fHJ19AEwEPjn5dcJOoaXwKR7HYNzIUHI+TKDKyEf02No+hltbbFPqp fTuabJ0jUHekn0BDl30Uuvq0CaDPYz0Ycl98BNAnDfMy1HfhvS1rudD5YYyr7fiQu3RlAzc0 6OKC/mMUdzveTXEdZw9xXW0zGHd44HucS/TcpLjGkB9wM8F1xtW7zUUmgS8XHBrBWmYrr7RW FDM73i19q1Rv0LJ5bCF6ndFYeYtQzGzdacx7u9KczM5oDvBmV7Jl5EWR2fRmkcPmcgoak010 FjOCvdxsZ1l7vshbRJe1Ir/MZtnMarU6fZL5vtk0OjVN2e/lVHXFD4MaMLC+HmTIIV0A/znS Q9aDTLmSDgPYOz6LS8U0gD/eaU0XcwCeHwxiyxJvuD09iABYk6jDpOIBgIudM2SKRdEbYUef H6QGKroeg72Nx6lUgdOLMjgxHSVSrKzkW2cW+pcwQW+A34WeUimsoAvh7IkWTMJrYH/LxBIH p1+E3z704dIeGhgenAIprKLz4czcQJqjgt5j7qX9IP1EBhe7RghJsBWeqE2kQ2TByb6QTMJq +KDJncaH4M0vv5BJ4gYABxaWB69Bz92jSTd50iEHBi5vSkFIvwSvjqR9n4F1vU9kUlsB69xK SZgNz0wPYVJbDf9u+Fhqc3D87M9kM1jvWRHSsyKkZ0UYz/+2bYDwg+cEu2ipEESdvWDluYNg 6WfkcmFw5YedUUDLAbNaER7eU6Ik+QNitSUKoBxnVIoq3+4SpaKcr/5IcNhKHS6zIEaBPnmD T3H1s2W25D+zOktZvc5g0Bbqkd6gQ8zziuCq4b1KuoJ3CvsEwS44lnWYPENdA2QO48uv7hfZ yCpN7n6nlS+q7jR36NsSgV9O/bGZzGo/yLCn+h9/VqN7SK29futip+FWZllxa4m3sfncwYLH TLNprNCt2bOODFz74J0b9wnv7/vGQDzjyGhf950tRu0O/3zPG9lHE7uKqqJ3XzFtI8XQtsBJ z/01Yu7X8eyTf6qaGUI08Wwu7hD5/wBB5vuoLwQAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrNIsWRmVeSWpSXmKPExsWy7bCSnO755zGxBqe3S1h8/dLBYrH+1DFm i9V3+9ksTk89y2Qx53wLi8Xed7NZLdbu+cNs0f1KxuLJ+lnMFjd+tbFa9D9+zWxx/vwGdotN j6+xWuy9pW1x/95PJouZ8+6wWVxa5G7xat43Fos9e0+yWFzeNYfN4sj/fkaLGef3MVm0bfzK aNHa85Pd4vjacAdJjy0rbzJ5tGwu99h2QNXj8tlSj02rOtk87lzbw+axeUm9x+4Fn5k8ms4c ZfZ4v+8qm0ffllWMHp83yQXwRHHZpKTmZJalFunbJXBl3H39ia3guWbF7mtNjA2MZxS7GDk5 JARMJGbvWMQMYgsJ7GaU+D27GCIuJbG1fQ8zhC0scb/lCGsXIxdQzXNGiW+TG1hBEmwC2hKb j69iBEmICExgkviz9SEjSIJZYBqHxK4P4iC2MNCGub9OsoDYLAKqEvu3/GcDsXkFLCW+9M5k grAFJU7OfAJUwwHUqyfRthFqjLzE9rdzoI5QkNhx9jVYXASo5PO3MywQNSISszvbmCcwCs5C MmkWwqRZSCbNQtKxgJFlFaNkakFxbnpusWGBYV5quV5xYm5xaV66XnJ+7iZGcBLQ0tzBeHlJ /CFGAQ5GJR7eHTejY4VYE8uKK3MPMUpwMCuJ8FbMiYoV4k1JrKxKLcqPLyrNSS0+xCjNwaIk zvs071ikkEB6YklqdmpqQWoRTJaJg1OqgVHhnceZwqzN89gnLRBa+uNUtFhtgx+r7833Ra3H Pk2Ve70h+GeXM8PXJm5T0/IHW018C2r0Toiryvd2cf6+saswlGdu0WK2DD0Fl4vVR51vOoRc PPrzidzTjqlut7s5m912dgVPeyi5Uucgi+N1je4DrbY39JpU66NZak7u22eZvtF/3zXldiWW 4oxEQy3mouJEAAakvEn+AgAA X-CMS-MailID: 20190821064223epcas2p18a14724427711e22c6c76b24bce1c8e0 X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20190821064223epcas2p18a14724427711e22c6c76b24bce1c8e0 References: Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Exynos MMC uses FMP to encrypt data stored on MMC device. FMP H/W reads crypto information from MMC descriptor. So, when using FMP H/W, the format of MMC descriptor should be extended. The FMP driver is registered with the diskcipher algorithm, so exynos MMC calls diskcipher API to use FMP. Cc: Ulf Hansson Cc: Kukjin Kim Cc: Krzysztof Kozlowski Signed-off-by: Boojin Kim --- drivers/mmc/host/Kconfig | 8 ++++++ drivers/mmc/host/dw_mmc-exynos.c | 62 ++++++++++++++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.c | 26 +++++++++++++++++ 3 files changed, 96 insertions(+) struct idmac_desc { diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 14d89a1..f6c5a54 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -761,6 +761,14 @@ config MMC_DW_EXYNOS Synopsys DesignWare Memory Card Interface driver. Select this option for platforms based on Exynos4 and Exynos5 SoC's. +config MMC_DW_EXYNOS_FMP + tristate "EXYNOS Flash Memory Protector for MMC_DW" + depends on MMC_DW_EXYNOS + ---help--- + This selects the EXYNOS MMC_DW FMP Driver. + + If you have a controller with this interface, say Y or M here. + config MMC_DW_HI3798CV200 tristate "Hi3798CV200 specific extensions for Synopsys DW Memory Card Interface" depends on MMC_DW diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 5e3d95b..d3848ba 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -14,10 +14,12 @@ #include #include #include +#include #include "dw_mmc.h" #include "dw_mmc-pltfm.h" #include "dw_mmc-exynos.h" +#include "../core/queue.h" /* Variations in Exynos specific dw-mshc controller */ enum dw_mci_exynos_type { @@ -508,6 +510,62 @@ static int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host, return 0; } +#ifdef CONFIG_MMC_DW_EXYNOS_FMP +static struct bio *get_bio(struct dw_mci *host, + struct mmc_data *data, bool cmdq_enabled) +{ + struct bio *bio = NULL; + struct mmc_queue_req *mq_rq = NULL; + struct request *req = NULL; + struct mmc_blk_request *brq = NULL; + + if (!host || !data) { + pr_err("%s: Invalid MMC:%p data:%p\n", __func__, host, data); + return NULL; + } + + if (cmdq_enabled) { + pr_err("%s: no support cmdq yet:%p\n", __func__, host); + bio = NULL; + } else { + brq = container_of(data, struct mmc_blk_request, data); + if (!brq) + return NULL; + + mq_rq = container_of(brq, struct mmc_queue_req, brq); + if (virt_addr_valid(mq_rq)) + req = mmc_queue_req_to_req(mq_rq); + if (virt_addr_valid(req)) + bio = req->bio; + } + return bio; +} + +static int dw_mci_exynos_crypto_engine_cfg(struct dw_mci *host, + void *desc, struct mmc_data *data, + struct page *page, int page_index, + int sector_offset, bool cmdq_enabled) +{ + struct bio *bio = get_bio(host, host->data, cmdq_enabled); + + if (!bio) + return 0; + + return exynos_fmp_crypt_cfg(bio, desc, page_index, sector_offset); +} + +static int dw_mci_exynos_crypto_engine_clear(struct dw_mci *host, + void *desc, bool cmdq_enabled) +{ + struct bio *bio = get_bio(host, host->data, cmdq_enabled); + + if (!bio) + return 0; + + return exynos_fmp_crypt_clear(bio, desc); +} +#endif + /* Common capabilities of Exynos4/Exynos5 SoC */ static unsigned long exynos_dwmmc_caps[4] = { MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, @@ -524,6 +582,10 @@ static const struct dw_mci_drv_data exynos_drv_data = { .parse_dt = dw_mci_exynos_parse_dt, .execute_tuning = dw_mci_exynos_execute_tuning, .prepare_hs400_tuning = dw_mci_exynos_prepare_hs400_tuning, +#ifdef CONFIG_MMC_DW_EXYNOS_FMP + .crypto_engine_cfg = dw_mci_exynos_crypto_engine_cfg, + .crypto_engine_clear = dw_mci_exynos_crypto_engine_clear, +#endif }; static const struct of_device_id dw_mci_exynos_match[] = { diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 0cdf574..4de476a 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -79,6 +79,32 @@ struct idmac_desc_64addr { u32 des6; /* Lower 32-bits of Next Descriptor Address */ u32 des7; /* Upper 32-bits of Next Descriptor Address */ +#if defined(CONFIG_MMC_DW_EXYNOS_FMP) + u32 des8; /* File IV 0 */ + u32 des9; /* File IV 1 */ + u32 des10; /* File IV 2 */ + u32 des11; /* File IV 3 */ + u32 des12; /* File EncKey 0 */ + u32 des13; /* File EncKey 1 */ + u32 des14; /* File EncKey 2 */ + u32 des15; /* File EncKey 3 */ + u32 des16; /* File EncKey 4 */ + u32 des17; /* File EncKey 5 */ + u32 des18; /* File EncKey 6 */ + u32 des19; /* File EncKey 7 */ + u32 des20; /* File TwKey 0 */ + u32 des21; /* File TwKey 1 */ + u32 des22; /* File TwKey 2 */ + u32 des23; /* File TwKey 3 */ + u32 des24; /* File TwKey 4 */ + u32 des25; /* File TwKey 5 */ + u32 des26; /* File TwKey 6 */ + u32 des27; /* File TwKey 7 */ + u32 des28; /* Disk IV 0 */ + u32 des29; /* Disk IV 1 */ + u32 des30; /* Disk IV 2 */ + u32 des31; /* Disk IV 3 */ +#endif }; From patchwork Wed Aug 21 06:42:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "boojin.kim" X-Patchwork-Id: 11105615 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 804791399 for ; Wed, 21 Aug 2019 06:42:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5524522CF7 for ; Wed, 21 Aug 2019 06:42:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="fVpFb1vr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728126AbfHUGmc (ORCPT ); Wed, 21 Aug 2019 02:42:32 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:10195 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728120AbfHUGmc (ORCPT ); Wed, 21 Aug 2019 02:42:32 -0400 Received: from epcas2p4.samsung.com (unknown [182.195.41.56]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20190821064229epoutp01eabf21a3161f96a16e4f7e0dc30c1af8~83PzoZ59g1005210052epoutp01C for ; Wed, 21 Aug 2019 06:42:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20190821064229epoutp01eabf21a3161f96a16e4f7e0dc30c1af8~83PzoZ59g1005210052epoutp01C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1566369749; bh=b8+pMwnDM1Y+1iXK//zi6ce3SJBaE4H69uXsKujU+38=; h=From:To:Cc:Subject:Date:References:From; b=fVpFb1vrxLo+foImejemmircRJa4mQ8udZOFQ7x9vDDE2Nn21e6P2qonsSIr0HPnH r8stAk3Sg8+o6Bt1znwpmKOjdKvcD0zPYiP8QlxkhsgLjoQs1e6UloCjzrU09PYTdp VbTsYXoyowkmnf/DoXHNLdrhos2RB1w2u+/XHqkk= Received: from epsnrtp5.localdomain (unknown [182.195.42.166]) by epcas2p3.samsung.com (KnoxPortal) with ESMTP id 20190821064228epcas2p36798da66a85912049d5fd8f3ff0d2590~83Py-NNHH0923809238epcas2p3y; Wed, 21 Aug 2019 06:42:28 +0000 (GMT) Received: from epsmges2p2.samsung.com (unknown [182.195.40.181]) by epsnrtp5.localdomain (Postfix) with ESMTP id 46Cyl72R0jzMqYkb; Wed, 21 Aug 2019 06:42:27 +0000 (GMT) Received: from epcas2p2.samsung.com ( [182.195.41.54]) by epsmges2p2.samsung.com (Symantec Messaging Gateway) with SMTP id 9E.03.04149.3D7EC5D5; Wed, 21 Aug 2019 15:42:27 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p2.samsung.com (KnoxPortal) with ESMTPA id 20190821064226epcas2p2835b8a9084988b79107e54abfc5e7dab~83PxikxcE1369213692epcas2p2w; Wed, 21 Aug 2019 06:42:26 +0000 (GMT) Received: from epsmgms1p2new.samsung.com (unknown [182.195.42.42]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20190821064226epsmtrp2483bd0cead0f3a7919ae583776a72772~83PxhkykF2201622016epsmtrp2a; Wed, 21 Aug 2019 06:42:26 +0000 (GMT) X-AuditID: b6c32a46-fedff70000001035-38-5d5ce7d3d23a Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p2new.samsung.com (Symantec Messaging Gateway) with SMTP id EC.D2.03638.2D7EC5D5; Wed, 21 Aug 2019 15:42:26 +0900 (KST) Received: from KORDO035251 (unknown [12.36.165.204]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20190821064226epsmtip2bed414e68869ed8e55860f74e737a0bd~83PxE_0pa2463324633epsmtip2C; Wed, 21 Aug 2019 06:42:26 +0000 (GMT) From: "boojin.kim" To: "'Jens Axboe'" , , Cc: "'Herbert Xu'" , "'David S. Miller'" , "'Eric Biggers'" , "'Theodore Y. Ts'o'" , "'Chao Yu'" , "'Jaegeuk Kim'" , "'Andreas Dilger'" , "'Theodore Ts'o'" , , "'Mike Snitzer'" , "'Alasdair Kergon'" , "'Jens Axboe'" , "'Krzysztof Kozlowski'" , "'Kukjin Kim'" , "'Jaehoon Chung'" , "'Ulf Hansson'" , , , , , , , , , , , Subject: [PATCH 5/9] block: support diskcipher Date: Wed, 21 Aug 2019 15:42:26 +0900 Message-ID: <004101d557eb$98b00060$ca100120$@samsung.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 14.0 Thread-Index: AdVX6NYgX/inL1D6QG+VYW/5L6wNPg== Content-Language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA01TfUwTZxzee3e9q86aW+2214Zs3TmNSsC2W7sXJ9syjbsFl5AtxviBeIEL JetXei2DmU1GWEVGBDVbsGWMCFHAMLQ02Cito+CqSOki0Yk6F2MDG4hTPnQ0qGt7NeO/531+ z5Pn9+SXV4rLXZRSWmy28zYzZ2TIxUR33xp9xvDYrjz10xNyNDtTRaDOgV9xdPKPWhJd/j6M oYZIJYH8990S1NEzj6PvxtNQtNOFo+sxpwTV3p3AUSRyikKeu9ckyH8jHf15ew5DRxtvkejK sY/QeOMjAvX4LxFo+GwDifqf1QJUHwlgyHl6FqBva+YoFOrY9sFy1ts2grGVXV+w3b+sZIfD DtbTfoBkb13rIdmuln3suaZpjK0YvICz/wSukuxBbztgpz2v5S7ZYdxg4LlC3qbizQWWwmJz UTaT81n+xnydXq3J0GShdxiVmTPx2cymLbkZm4uN8e6MqoQzOuJULicIzLr3NtgsDjuvMlgE ezbDWwuNVo3GmilwJsFhLsossJjWa9RqrS6u3GM0DJ6uIKx1utKQN0iVA1d6NVgkhfTbsP5g TFINFkvltA9At/NnID6mANx/MpSaPAKw7WIl/twye3iASGA57Y9bagtE0d8A1sz1gsSApNNh V6g9iRU0D0cfPsMTIpx+SsHoVDDpXkZnwomWY0lM0Cth670ImcAyOgtOnothIn4JXjoaTWpw +nV4ZrIhtYUK+sITqYBM2PawSSJqFNB9wJkMg/QcBedvhzHRsAk+HutImZfB8ZCXErESTt/3 kyLeB68eb6ZEcw2AgzFnSvQWdI3uj6dJ4wlrYOfZdQkI6RWw/0Zqt6Wwqu8JJdIyWOWUi8Y3 4Y9Tw5hIK+GDmq9FmoXzM/VYHXjDtaCka0FJ14Iyrv9jmwDRDl7hrYKpiBe0Vu3CY3tA8l+s 3ewDLUNbgoCWAmaJzDeyM08u4UqEMlMQQCnOKGSlDTvy5LJCruxL3mbJtzmMvBAEuvgNDuHK lwss8V9mtudrdFq9Xp2lQzq9FjGvyjwvjuyS00Wcnf+c56287bkPky5SloPmZt379wKXvenl rdW7/7UGLto/pX7q/m179+rzmFux6nHFhTtbgwOuBz+sMOR9crgpp+TJmPrEV76NvVH4wqR9 D3NlVSR3/fXjN/cuHT/invhLWRIt3ZvTmBbuvaNoPRJb/W7Fx9Kyb4aWd2zrG/odT6N3a011 /TcPfQjUga6tdTOnRhlCMHCatbhN4P4DeUtx9C0EAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA02SXUhTYRzGe3c+dhRHxyn4aqWxMHDWTDF8BxHddS69CUsTG3lSaZvrHHXa RYroTAuVQeHmErFBOhG/P3JTcn5MTRlpmoa6Cy3DZWWmpIXlnJF3P3ie5/e+F38KE7vxECpD ncVyaoVSQvriXYOSsPNTqzeTL7x4Hoe2fjzEUfP4CIYaFytI9PrJpACZnEU46vtSTaAm228M PVo7iVaajRia29URqGLZjSGns0WI2pZnCdT3PhK5lnYEyFCzQKKpuqtorWYbR7a+MRxN95pI NPSnAqAqZ78A6Vq3ACp+vCNEjqaEK8FMR8O8gClq1zJdr8KZ6clsps1SSjILszaSaTfnM9ba TQFTODGMMV/7Z0imvMMCmM220Hi/RN9LqawyI4floi7f8k2faC3ENZUXcx0ddmEBMEaWAR8K 0rFwSz+OlwFfSkxbAdxr7ya8QQjsLLFhXg6ArqIhwltaBbDLpSc9AUlHwnaHBXg4kE6DP1/2 CjyM0U8p2PstyMMBtAy6zXW4h3E6HNZ/dh5sRbQcrlt3BV72h2OGlf0Otb+VQV0r8GrCYPe6 6fAPp2HPpPvwKRls2KglvJ1AWF2qwyqBv/GIyfjfZDxiMh5Z1ALcAoJZDa9KU/HRmhg1q5Xx ChWfrU6T3c5UtYGDE5BKe8DoaIod0BSQ+Il65pOSxYQih89T2QGkMEmgKNeUmCwWpSry7rNc ZgqXrWR5OzhB4ZIgUVjmyA0xnabIYu+yrIbl/qUCyiekAOS/7eeGW7IWEtHutfIH1jl6dsr5 TholUW7jSfdGO9jFTY05S6tvHIiNFmq1x6z5ef0lDlBneHacnRkqOTu7E3H93J2qrfr4lUG9 HO+UB0S8WZInhC6Gr8bMa4M4pHN9tIgbNnIM5u1P/nvDcfKBD6fiznyPIMqni82dGb8kOJ+u iJZiHK/4C+t4TdD+AgAA X-CMS-MailID: 20190821064226epcas2p2835b8a9084988b79107e54abfc5e7dab X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20190821064226epcas2p2835b8a9084988b79107e54abfc5e7dab References: Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org This patch supports crypto information to be maintained via BIO and passed to the storage driver. To do this, 'bi_aux_private', 'REQ_CYPTE' and 'bi_dun' are added to the block layer. 'bi_aux_private' is added for loading additional private information into BIO. 'REQ_CRYPT' is added to distinguish that bi_aux_private is being used for diskcipher. F2FS among encryption users uses DUN(device unit number) as the IV(initial vector) for cryptographic operations. DUN is stored in 'bi_dun' of bi_iter as a specific value for each BIO. Before attempting to merge the two BIOs, the operation is also added to verify that the crypto information contained in two BIOs is consistent. Cc: Jens Axboe Signed-off-by: Boojin Kim --- block/bio.c | 1 + block/blk-merge.c | 19 +++++++++++++++++-- block/bounce.c | 5 ++++- include/linux/bio.h | 10 ++++++++++ include/linux/blk_types.h | 4 ++++ include/linux/bvec.h | 3 +++ 6 files changed, 39 insertions(+), 3 deletions(-) struct bvec_iter_all { diff --git a/block/bio.c b/block/bio.c index 5476965..c60eb8e 100644 --- a/block/bio.c +++ b/block/bio.c @@ -588,6 +588,7 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src) bio->bi_write_hint = bio_src->bi_write_hint; bio->bi_iter = bio_src->bi_iter; bio->bi_io_vec = bio_src->bi_io_vec; + bio->bi_aux_private = bio_src->bi_aux_private; bio_clone_blkg_association(bio, bio_src); blkcg_bio_issue_init(bio); diff --git a/block/blk-merge.c b/block/blk-merge.c index 48e6725..d031257 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -576,6 +577,8 @@ int ll_back_merge_fn(struct request *req, struct bio *bio, unsigned int nr_segs) if (blk_integrity_rq(req) && integrity_req_gap_back_merge(req, bio)) return 0; + if (blk_try_merge(req, bio) != ELEVATOR_BACK_MERGE) + return 0; if (blk_rq_sectors(req) + bio_sectors(bio) > blk_rq_get_max_sectors(req, blk_rq_pos(req))) { req_set_nomerge(req->q, req); @@ -592,6 +595,8 @@ int ll_front_merge_fn(struct request *req, struct bio *bio, unsigned int nr_segs if (blk_integrity_rq(req) && integrity_req_gap_front_merge(req, bio)) return 0; + if (blk_try_merge(req, bio) != ELEVATOR_FRONT_MERGE) + return 0; if (blk_rq_sectors(req) + bio_sectors(bio) > blk_rq_get_max_sectors(req, bio->bi_iter.bi_sector)) { req_set_nomerge(req->q, req); @@ -738,6 +743,9 @@ static struct request *attempt_merge(struct request_queue *q, !blk_write_same_mergeable(req->bio, next->bio)) return NULL; + if (!crypto_diskcipher_blk_mergeble(req->bio, next->bio)) + return NULL; + /* * Don't allow merge of different write hints, or for a hint with * non-hint IO. @@ -887,9 +895,16 @@ enum elv_merge blk_try_merge(struct request *rq, struct bio *bio) { if (blk_discard_mergable(rq)) return ELEVATOR_DISCARD_MERGE; - else if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector) + else if (blk_rq_pos(rq) + blk_rq_sectors(rq) == + bio->bi_iter.bi_sector) { + if (!crypto_diskcipher_blk_mergeble(rq->bio, bio)) + return ELEVATOR_NO_MERGE; return ELEVATOR_BACK_MERGE; - else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_iter.bi_sector) + } else if (blk_rq_pos(rq) - bio_sectors(bio) == + bio->bi_iter.bi_sector) { + if (!crypto_diskcipher_blk_mergeble(bio, rq->bio)) + return ELEVATOR_NO_MERGE; return ELEVATOR_FRONT_MERGE; + } return ELEVATOR_NO_MERGE; } diff --git a/block/bounce.c b/block/bounce.c index f8ed677..720b065 100644 --- a/block/bounce.c +++ b/block/bounce.c @@ -252,7 +252,10 @@ static struct bio *bounce_clone_bio(struct bio *bio_src, gfp_t gfp_mask, bio->bi_write_hint = bio_src->bi_write_hint; bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; - + bio->bi_aux_private = bio_src->bi_aux_private; +#ifdef CONFIG_CRYPTO_DISKCIPHER + bio->bi_iter.bi_dun = bio_src->bi_iter.bi_dun; +#endif switch (bio_op(bio)) { case REQ_OP_DISCARD: case REQ_OP_SECURE_ERASE: diff --git a/include/linux/bio.h b/include/linux/bio.h index 3cdb84c..351e65e 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -49,6 +49,12 @@ #define bio_sectors(bio) bvec_iter_sectors((bio)->bi_iter) #define bio_end_sector(bio) bvec_iter_end_sector((bio)->bi_iter) +#ifdef CONFIG_CRYPTO_DISKCIPHER +#define bio_dun(bio) ((bio)->bi_iter.bi_dun) +#define bio_duns(bio) (bio_sectors(bio) >> 3) /* 4KB unit */ +#define bio_end_dun(bio) (bio_dun(bio) + bio_duns(bio)) +#endif + /* * Return the data direction, READ or WRITE. */ @@ -143,6 +149,10 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter, { iter->bi_sector += bytes >> 9; +#ifdef CONFIG_CRYPTO_DISKCIPHER + if (iter->bi_dun) + iter->bi_dun += bytes >> 12; +#endif if (bio_no_advance_iter(bio)) iter->bi_size -= bytes; else diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 75059c1..117119a 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -160,6 +160,8 @@ struct bio { bio_end_io_t *bi_end_io; void *bi_private; + void *bi_aux_private; + #ifdef CONFIG_BLK_CGROUP /* * Represents the association of the css and request_queue for the bio. @@ -311,6 +313,7 @@ enum req_flag_bits { __REQ_INTEGRITY, /* I/O includes block integrity payload */ __REQ_FUA, /* forced unit access */ __REQ_PREFLUSH, /* request for cache flush */ + __REQ_CRYPT, /* request inline crypt */ __REQ_RAHEAD, /* read ahead, can fail anytime */ __REQ_BACKGROUND, /* background IO */ __REQ_NOWAIT, /* Don't wait if request will block */ @@ -343,6 +346,7 @@ enum req_flag_bits { #define REQ_NOMERGE (1ULL << __REQ_NOMERGE) #define REQ_IDLE (1ULL << __REQ_IDLE) #define REQ_INTEGRITY (1ULL << __REQ_INTEGRITY) +#define REQ_CRYPT (1ULL << __REQ_CRYPT) #define REQ_FUA (1ULL << __REQ_FUA) #define REQ_PREFLUSH (1ULL << __REQ_PREFLUSH) #define REQ_RAHEAD (1ULL << __REQ_RAHEAD) diff --git a/include/linux/bvec.h b/include/linux/bvec.h index a032f01..5f89641 100644 --- a/include/linux/bvec.h +++ b/include/linux/bvec.h @@ -30,6 +30,9 @@ struct bvec_iter { unsigned int bi_bvec_done; /* number of bytes completed in current bvec */ +#ifdef CONFIG_CRYPTO_DISKCIPHER + u64 bi_dun; +#endif }; From patchwork Wed Aug 21 06:42:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "boojin.kim" X-Patchwork-Id: 11105627 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CC1AB1399 for ; Wed, 21 Aug 2019 06:42:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 96FE72087E for ; Wed, 21 Aug 2019 06:42:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="TuEd8Kw0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728178AbfHUGmh (ORCPT ); Wed, 21 Aug 2019 02:42:37 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:10267 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728164AbfHUGmh (ORCPT ); Wed, 21 Aug 2019 02:42:37 -0400 Received: from epcas2p4.samsung.com (unknown [182.195.41.56]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20190821064234epoutp0107761e50929f67ac24419c3ac15d853e~83P5AUZtT1005410054epoutp01P for ; Wed, 21 Aug 2019 06:42:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20190821064234epoutp0107761e50929f67ac24419c3ac15d853e~83P5AUZtT1005410054epoutp01P DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1566369755; bh=lXH3d3b7N+K3mylwot5v8bTO+J7LAkcQhHDSqMe7C/M=; h=From:To:Cc:Subject:Date:References:From; b=TuEd8Kw0zTaI7r4uZxnSqmJVW4fzUnL/LG1UWCso2OV8NSVcJIP5eWeRkwcT1zClX wP3b+6scxLvqa3gsV7yksHye4RuOc+mULYe/3smLGMGNIPwz6R6ksjYYoU8pK9MsvN MUzdzgDOpw8tkrflUCrlFA4hTjKyDVDwBF07TI9I= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas2p4.samsung.com (KnoxPortal) with ESMTP id 20190821064234epcas2p489f837a13ef14307261c52ca8b5cc5c7~83P4Otjor1664116641epcas2p4d; Wed, 21 Aug 2019 06:42:34 +0000 (GMT) Received: from epsmges2p1.samsung.com (unknown [182.195.40.189]) by epsnrtp2.localdomain (Postfix) with ESMTP id 46CylC3sMHzMqYkW; Wed, 21 Aug 2019 06:42:31 +0000 (GMT) Received: from epcas2p2.samsung.com ( [182.195.41.54]) by epsmges2p1.samsung.com (Symantec Messaging Gateway) with SMTP id 93.FD.04156.7D7EC5D5; Wed, 21 Aug 2019 15:42:31 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas2p1.samsung.com (KnoxPortal) with ESMTPA id 20190821064230epcas2p1ad7301f2b1331bcab3126e6e37c0e272~83P1P4DLo0242202422epcas2p13; Wed, 21 Aug 2019 06:42:30 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20190821064230epsmtrp199195e636f4cb974d74d7f324f642ead~83P1Oh0Pg2011020110epsmtrp1g; Wed, 21 Aug 2019 06:42:30 +0000 (GMT) X-AuditID: b6c32a45-df7ff7000000103c-8b-5d5ce7d7c3ef Received: from epsmtip2.samsung.com ( [182.195.34.31]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 02.12.03706.6D7EC5D5; Wed, 21 Aug 2019 15:42:30 +0900 (KST) Received: from KORDO035251 (unknown [12.36.165.204]) by epsmtip2.samsung.com (KnoxPortal) with ESMTPA id 20190821064230epsmtip269d9197aa07172ce59821d07762311d0~83P0vUduR2463324633epsmtip2F; Wed, 21 Aug 2019 06:42:30 +0000 (GMT) From: "boojin.kim" To: "'Alasdair Kergon'" , "'Mike Snitzer'" , , Cc: "'Herbert Xu'" , "'David S. Miller'" , "'Eric Biggers'" , "'Theodore Y. Ts'o'" , "'Chao Yu'" , "'Jaegeuk Kim'" , "'Andreas Dilger'" , "'Theodore Ts'o'" , , "'Mike Snitzer'" , "'Alasdair Kergon'" , "'Jens Axboe'" , "'Krzysztof Kozlowski'" , "'Kukjin Kim'" , "'Jaehoon Chung'" , "'Ulf Hansson'" , , , , , , , , , , , Subject: [PATCH 6/9] dm crypt: support diskcipher Date: Wed, 21 Aug 2019 15:42:30 +0900 Message-ID: <004201d557eb$9b0a4410$d11ecc30$@samsung.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 14.0 Thread-Index: AdVX6H6LclDwZf4gTNyTqFNYN8nzeA== Content-Language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA01Tf0wTZxjO17veVUbdWRl+q5vrjpmgptB2a/ehsJDMH+fmEhaXLHEQdoFb Yeuv9FpRl01HXCnKVow22gMZbsRtqPxoOySs7RZwIlNWJ9ENAroIborR8VOEDLe2Jxn/Pd/z Ps/3vG/evDJMIZBKWanFwdktrIkmkvC2rjUG9W9/5RdowtOpaHrKjaPmn89j6NSQh0AXvb0S VBvdj6Pw/RopOhP6B0MHR59BI80Chn6fc0mRZ/guhqLRFhL5h69JUXhgHbpxfVaCfHWDBLry 5RY0WvcAR6FwD476OmoJdO5fD0DHohEJcrVOA/Rp1SyJus+8nfs0E/y2X8LsD5QxbT+uZvp6 nYy/sZJgBq+FCCbQsJf5vn5SwpRf+glj/o5cJZjPg42AmfSvykveYcou4dhizq7iLEXW4lKL MYd+fXvhq4V6g0ar1mahl2mVhTVzOfTGbXnqzaWm2Oy0aidrcsaoPJbn6cxXsu1Wp4NTlVh5 Rw7N2YpNNq3WlsGzZt5pMWYUWc3rtRqNTh9TvmsqGf9jEred3Lpr5usQvg/c2nAALJFB6iU4 f6KFPACSZAqqHcCh29VS8TEB4GW/gMdVCuoBgK397y84poauEyIfBrDat0c03AFwRDhCxgsE tQ4GuhtBvJBCuQGsO9KfyMCoRyQcmehMfLuc0sKeihoQxzi1GjZExhO8nMqCY0f7gIiXwR7f SILHqOfg2Xu1mNiGCrb33k1oUqgMWB8oB6ImBdZUurB4GKTmSfjJIR8hGjbCG99VSkW8HI52 B0kRK+Edj+sx3guvnvyKFM1VAF6aWyi8CIU/K2IJsljCGtjckRmHkEqD5wYe97YUurvmSZGW Q7dLIRpfgMcn+iQirYRjVR+LNAPDJy5KqsHzwqIhhUVDCouGEf6PrQd4I0jlbLzZyPE6m3bx sv0gcRdrN7WDY79s6wSUDNDJ8tn8/AKFlN3J7zZ3AijD6BT5rtodBQp5Mbt7D2e3FtqdJo7v BPrYDg5hyqeKrLErszgKtXqdwaDJ0iO9QYfoFfLAE/35CsrIOrgPOM7G2Rd8EtkS5T7w1soL lyuUH0VzS99oS3vvh2BPRys5JizVrPrC2IQdjsgPNq1Qa6rfFNI+S09Vq77pRd7hliuPPkzy 3gv6Bm5Peecix92ed1Qh3eax09mHt+Y+NN9/0p2sSS8bvznjPn3L215u/7Vr0/kZ+fpnz7Lp bYMbmrbU5C27cLMhs2GmTPJagMb5Ela7FrPz7H9WNVOBLQQAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrDIsWRmVeSWpSXmKPExsWy7bCSvO615zGxBgsmGlt8/dLBYrH+1DFm i9V3+9ksTk89y2Qx53wLi8Xed7NZLdbu+cNs0f1KxuLJ+lnMFjd+tbFa9D9+zWxx/vwGdotN j6+xWuy9pW1x/95PJouZ8+6wWVxa5G7xat43Fos9e0+yWFzeNYfN4sj/fkaLGef3MVm0bfzK aNHa85Pd4vjacAdJjy0rbzJ5tGwu99h2QNXj8tlSj02rOtk87lzbw+axeUm9x+4Fn5k8ms4c ZfZ4v+8qm0ffllWMHp83yQXwRHHZpKTmZJalFunbJXBlfHzwmaVgmWfF9+V7WBoYn1p3MXJy SAiYSHy5e4+ti5GLQ0hgN6PE6+vtLBAJKYmt7XuYIWxhifstR1ghip4zSsx90sAIkmAT0JbY fHwVI0hCRKCHUeL5rd9gHcwC0zgkdn0QB7GFBQwlTrbPBmtgEVCVWLLvI9gGXgFLiQ/TLzNC 2IISJ2c+AYpzAPXqSbRtZIQYIy+x/e0cqCMUJHacfQ0WFwEqWbC5CapGRGJ2ZxvzBEbBWUgm zUKYNAvJpFlIOhYwsqxilEwtKM5Nzy02LDDMSy3XK07MLS7NS9dLzs/dxAhOA1qaOxgvL4k/ xCjAwajEw7vjZnSsEGtiWXFl7iFGCQ5mJRHeijlRsUK8KYmVValF+fFFpTmpxYcYpTlYlMR5 n+YdixQSSE8sSc1OTS1ILYLJMnFwSjUw8jptKBfLLF1seeqra83FCxqBsgte5j2X2rq33pdp qun1uybnfFY8mqqx4FZdh/Wl0OOB0843e8dpJC5+eS8usD1XpEPjou+bjfmtiSsWtwmazr03 LSf4oYpHVuSFSf6f8/svFMzKmHB4zoGYEt0jOybb8s2cnlqpNn0P050Lh7QuxiqVBZ4qUWIp zkg01GIuKk4EAEdkX0f/AgAA X-CMS-MailID: 20190821064230epcas2p1ad7301f2b1331bcab3126e6e37c0e272 X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20190821064230epcas2p1ad7301f2b1331bcab3126e6e37c0e272 References: Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org This patch supports dm-crypt to use diskcipher in a specific ivmode (disk or fmp). Dm-crypt allocates diskcipher and sets the key on it. Then, dm-crypt sets diskcipher into BIO and submits the BIO without any additional data encryption. Cc: Alasdair Kergon Cc: Mike Snitzer Cc: dm-devel@redhat.com Signed-off-by: Boojin Kim --- drivers/md/dm-crypt.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 103 insertions(+), 9 deletions(-) /* @@ -170,6 +173,7 @@ struct crypt_config { union { struct crypto_skcipher **tfms; struct crypto_aead **tfms_aead; + struct crypto_diskcipher **tfms_diskc; } cipher_tfm; unsigned tfms_count; unsigned long cipher_flags; @@ -955,6 +959,17 @@ static bool crypt_integrity_hmac(struct crypt_config *cc) return crypt_integrity_aead(cc) && cc->key_mac_size; } +static bool crypt_mode_diskcipher(struct crypt_config *cc) +{ + return test_bit(CRYPT_MODE_DISKCIPHER, &cc->cipher_flags); +} + +static bool crypt_mode_skcipher(struct crypt_config *cc) +{ + return test_bit(CRYPT_MODE_SKCIPHER, &cc->cipher_flags); +} + + /* Get sg containing data */ static struct scatterlist *crypt_get_sg_data(struct crypt_config *cc, struct scatterlist *sg) @@ -1573,13 +1588,13 @@ static void crypt_endio(struct bio *clone) /* * free the processed pages */ - if (rw == WRITE) + if ((rw == WRITE) && !crypt_mode_diskcipher(cc)) crypt_free_buffer_pages(cc, clone); error = clone->bi_status; bio_put(clone); - if (rw == READ && !error) { + if (rw == READ && !error && !crypt_mode_diskcipher(cc)) { kcryptd_queue_crypt(io); return; } @@ -1618,6 +1633,11 @@ static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) crypt_inc_pending(io); clone_init(io, clone); + + if (crypt_mode_diskcipher(cc)) + crypto_diskcipher_set(clone, + cc->cipher_tfm.tfms_diskc[0], NULL, 0); + clone->bi_iter.bi_sector = cc->start + io->sector; if (dm_crypt_integrity_io_alloc(io, clone)) { @@ -1907,10 +1927,29 @@ static void crypt_free_tfms_skcipher(struct crypt_config *cc) cc->cipher_tfm.tfms = NULL; } +static void crypt_free_tfms_diskcipher(struct crypt_config *cc) +{ + if (!crypt_mode_diskcipher(cc)) + return; + + if (cc->cipher_tfm.tfms_diskc[0] && + !IS_ERR(cc->cipher_tfm.tfms_diskc[0])) { + crypto_diskcipher_clearkey(cc->cipher_tfm.tfms_diskc[0]); + crypto_free_diskcipher(cc->cipher_tfm.tfms_diskc[0]); + cc->cipher_tfm.tfms_diskc[0] = NULL; + } + + kfree(cc->cipher_tfm.tfms_diskc); + cc->cipher_tfm.tfms_diskc = NULL; +} + + static void crypt_free_tfms(struct crypt_config *cc) { if (crypt_integrity_aead(cc)) crypt_free_tfms_aead(cc); + else if (crypt_mode_diskcipher(cc)) + crypt_free_tfms_diskcipher(cc); else crypt_free_tfms_skcipher(cc); } @@ -1934,6 +1973,7 @@ static int crypt_alloc_tfms_skcipher(struct crypt_config *cc, char *ciphermode) return err; } } + set_bit(CRYPT_MODE_SKCIPHER, &cc->cipher_flags); /* * dm-crypt performance can vary greatly depending on which crypto @@ -1965,10 +2005,34 @@ static int crypt_alloc_tfms_aead(struct crypt_config *cc, char *ciphermode) return 0; } +static int crypt_alloc_tfms_diskcipher(struct crypt_config *cc, + char *ciphermode) +{ + int err; + + cc->cipher_tfm.tfms = kmalloc(sizeof(struct crypto_aead *), GFP_KERNEL); + if (!cc->cipher_tfm.tfms) + return -ENOMEM; + + cc->cipher_tfm.tfms_diskc[0] = + crypto_alloc_diskcipher(ciphermode, 0, 0, 1); + if (IS_ERR(cc->cipher_tfm.tfms_diskc[0])) { + err = PTR_ERR(cc->cipher_tfm.tfms_diskc[0]); + crypt_free_tfms(cc); + pr_err("%s: no diskcipher with %s\n", __func__, ciphermode); + return err; + } + pr_info("%s is done with %s\n", __func__, ciphermode); + + return 0; +} + static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode) { if (crypt_integrity_aead(cc)) return crypt_alloc_tfms_aead(cc, ciphermode); + else if (crypt_mode_diskcipher(cc)) + return crypt_alloc_tfms_diskcipher(cc, ciphermode); else return crypt_alloc_tfms_skcipher(cc, ciphermode); } @@ -2030,6 +2094,11 @@ static int crypt_setkey(struct crypt_config *cc) r = crypto_aead_setkey(cc->cipher_tfm.tfms_aead[i], cc->key + (i * subkey_size), subkey_size); + else if (crypt_mode_diskcipher(cc)) + r = crypto_diskcipher_setkey( + cc->cipher_tfm.tfms_diskc[i], + cc->key + (i * subkey_size), + subkey_size, 1); else r = crypto_skcipher_setkey(cc->cipher_tfm.tfms[i], cc->key + (i * subkey_size), @@ -2510,7 +2579,7 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key return -ENOMEM; } cc->iv_size = crypto_aead_ivsize(any_tfm_aead(cc)); - } else + } else if (crypt_mode_skcipher(cc)) cc->iv_size = crypto_skcipher_ivsize(any_tfm(cc)); ret = crypt_ctr_blkdev_cipher(cc); @@ -2560,6 +2629,9 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key chainmode = strsep(&tmp, "-"); *ivmode = strsep(&tmp, ":"); *ivopts = tmp; + if (*ivmode) + if (!strcmp(*ivmode, "disk") || !strcmp(*ivmode, "fmp")) + set_bit(CRYPT_MODE_DISKCIPHER, &cc->cipher_flags); /* * For compatibility with the original dm-crypt mapping format, if @@ -2621,9 +2693,11 @@ static int crypt_ctr_cipher(struct dm_target *ti, char *cipher_in, char *key) return ret; /* Initialize IV */ - ret = crypt_ctr_ivmode(ti, ivmode); - if (ret < 0) - return ret; + if (!crypt_mode_diskcipher(cc)) { + ret = crypt_ctr_ivmode(ti, ivmode); + if (ret < 0) + return ret; + } /* Initialize and set key */ ret = crypt_set_key(cc, key); @@ -2654,6 +2728,11 @@ static int crypt_ctr_cipher(struct dm_target *ti, char *cipher_in, char *key) if (cc->key_string) memset(cc->key, 0, cc->key_size * sizeof(u8)); + pr_info("%s with ivmode:%s, ivopts:%s, aead:%d, diskcipher:%d(%p), skcipher:%d\n", + __func__, ivmode, ivopts, crypt_integrity_aead(cc), + crypt_mode_diskcipher(cc), cc->cipher_tfm.tfms_diskc[0], + crypt_mode_skcipher(cc)); + return ret; } @@ -2788,11 +2867,15 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) ret = crypt_ctr_cipher(ti, argv[0], argv[1]); if (ret < 0) goto bad; - if (crypt_integrity_aead(cc)) { cc->dmreq_start = sizeof(struct aead_request); cc->dmreq_start += crypto_aead_reqsize(any_tfm_aead(cc)); align_mask = crypto_aead_alignmask(any_tfm_aead(cc)); + } else if (crypt_mode_diskcipher(cc)) { + cc->per_bio_data_size = ti->per_io_data_size = + ALIGN(sizeof(struct dm_crypt_io), + ARCH_KMALLOC_MINALIGN); + goto get_bio; } else { cc->dmreq_start = sizeof(struct skcipher_request); cc->dmreq_start += crypto_skcipher_reqsize(any_tfm(cc)); @@ -2836,6 +2919,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad; } +get_bio: ret = bioset_init(&cc->bs, MIN_IOS, 0, BIOSET_NEED_BVECS); if (ret) { ti->error = "Cannot allocate crypt bioset"; @@ -2893,6 +2977,12 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad; } + if (crypt_mode_diskcipher(cc)) { + cc->crypt_queue = NULL; + cc->write_thread = NULL; + goto out; + } + if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags)) cc->crypt_queue = alloc_workqueue("kcryptd/%s", WQ_HIGHPRI | WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, @@ -2918,6 +3008,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) } wake_up_process(cc->write_thread); +out: ti->num_flush_bios = 1; return 0; @@ -2981,10 +3072,10 @@ static int crypt_map(struct dm_target *ti, struct bio *bio) if (crypt_integrity_aead(cc)) io->ctx.r.req_aead = (struct aead_request *)(io + 1); - else + else if (crypt_mode_skcipher(cc)) io->ctx.r.req = (struct skcipher_request *)(io + 1); - if (bio_data_dir(io->base_bio) == READ) { + if ((bio_data_dir(io->base_bio) == READ) || crypt_mode_diskcipher(cc)) { if (kcryptd_io_read(io, GFP_NOWAIT)) kcryptd_queue_read(io); } else @@ -3143,6 +3234,9 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits) limits->physical_block_size = max_t(unsigned, limits->physical_block_size, cc->sector_size); limits->io_min = max_t(unsigned, limits->io_min, cc->sector_size); + + if (crypt_mode_diskcipher(cc)) + limits->logical_block_size = PAGE_SIZE; } static struct target_type crypt_target = { diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 9f8b654..271cfcc 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -37,6 +37,7 @@ #include #include +#include #define DM_MSG_PREFIX "crypt" @@ -130,6 +131,8 @@ enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID, enum cipher_flags { CRYPT_MODE_INTEGRITY_AEAD, /* Use authenticated mode for cihper */ CRYPT_IV_LARGE_SECTORS, /* Calculate IV from sector_size, not 512B sectors */ + CRYPT_MODE_DISKCIPHER, + CRYPT_MODE_SKCIPHER, }; From patchwork Wed Aug 21 06:42:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "boojin.kim" X-Patchwork-Id: 11105665 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D6C2E1399 for ; Wed, 21 Aug 2019 06:43:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9809C233A0 for ; Wed, 21 Aug 2019 06:43:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="idcoeYfT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728306AbfHUGnF (ORCPT ); Wed, 21 Aug 2019 02:43:05 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:10324 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728215AbfHUGmp (ORCPT ); Wed, 21 Aug 2019 02:42:45 -0400 Received: from epcas2p4.samsung.com (unknown [182.195.41.56]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20190821064241epoutp018f807e9154aca2a652e7f8f39356e491~83P_0zv-B1114111141epoutp01S for ; Wed, 21 Aug 2019 06:42:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20190821064241epoutp018f807e9154aca2a652e7f8f39356e491~83P_0zv-B1114111141epoutp01S DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1566369761; bh=nePUznyEzQN2tvbKGNQVLTfqjckap+uH4JSQl4+ch64=; h=From:To:Cc:Subject:Date:References:From; b=idcoeYfTBC26p7Bs0H2u7rIF85oHBnNl8TRRMx+p8x7RqhMLT7LG/pgu3kvIv3NCT RY9CtviB5HNhLxGly4+IWB6aKGFhdi5bHI7or/zna8Z03UIC4eLfy3jWy3crFDAzJ1 iYU38G+AB3qhPe6Q5fe3BX1snc7JxgAU4iT1qx5A= Received: from epsnrtp2.localdomain (unknown [182.195.42.163]) by epcas2p2.samsung.com (KnoxPortal) with ESMTP id 20190821064240epcas2p20900643c8de55a181c2996aac1b0833a~83P_NaVe12515525155epcas2p29; Wed, 21 Aug 2019 06:42:40 +0000 (GMT) Received: from epsmges2p3.samsung.com (unknown [182.195.40.191]) by epsnrtp2.localdomain (Postfix) with ESMTP id 46CylL0jTBzMqYkV; Wed, 21 Aug 2019 06:42:38 +0000 (GMT) Received: from epcas2p2.samsung.com ( [182.195.41.54]) by epsmges2p3.samsung.com (Symantec Messaging Gateway) with SMTP id 0A.53.04068.DD7EC5D5; Wed, 21 Aug 2019 15:42:38 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p4.samsung.com (KnoxPortal) with ESMTPA id 20190821064237epcas2p4d8bc4858fda55be213eb51b19e52fc71~83P7Z1Gqi1664116641epcas2p4j; Wed, 21 Aug 2019 06:42:37 +0000 (GMT) Received: from epsmgms1p2new.samsung.com (unknown [182.195.42.42]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20190821064237epsmtrp270332e118998ecd0be549cd882da5d56~83P7Y218Z2242122421epsmtrp2g; Wed, 21 Aug 2019 06:42:37 +0000 (GMT) X-AuditID: b6c32a47-5a1ff70000000fe4-b9-5d5ce7dd8159 Received: from epsmtip1.samsung.com ( [182.195.34.30]) by epsmgms1p2new.samsung.com (Symantec Messaging Gateway) with SMTP id 46.E2.03638.DD7EC5D5; Wed, 21 Aug 2019 15:42:37 +0900 (KST) Received: from KORDO035251 (unknown [12.36.165.204]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20190821064236epsmtip19eaf3f73889496a58e92a8bc022c5984~83P61ZcSp0421904219epsmtip1l; Wed, 21 Aug 2019 06:42:36 +0000 (GMT) From: "boojin.kim" To: "'Theodore Y. Ts'o'" , "'Jaegeuk Kim'" , "'Eric Biggers'" , , , Cc: "'Herbert Xu'" , "'David S. Miller'" , "'Eric Biggers'" , "'Theodore Y. Ts'o'" , "'Chao Yu'" , "'Jaegeuk Kim'" , "'Andreas Dilger'" , "'Theodore Ts'o'" , , "'Mike Snitzer'" , "'Alasdair Kergon'" , "'Jens Axboe'" , "'Krzysztof Kozlowski'" , "'Kukjin Kim'" , "'Jaehoon Chung'" , "'Ulf Hansson'" , , , , , , , , , , , Subject: [PATCH 7/9] fscrypt: support diskcipher Date: Wed, 21 Aug 2019 15:42:36 +0900 Message-ID: <004301d557eb$9ef2c8e0$dcd85aa0$@samsung.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 14.0 Thread-Index: AdVX6NYYas7Ah3LbRl6gWv/zKu666g== Content-Language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprOLsWRmVeSWpSXmKPExsWy7bCmme695zGxBmcSLb5+6WCxWH/qGLPF 6rv9bBanp55lsphzvoXFYu+72awWa/f8YbbofiVj8WT9LGaLG7/aWC36H79mtjh/fgO7xabH 11gt9t7Strh/7yeTxcx5d9gsLi1yt3g17xuLxZ69J1ksLu+aw2Zx5H8/o8WM8/uYLNo2fmW0 aO35yW5xfG24g6THlpU3mTxaNpd7bDug6nH5bKnHplWdbB53ru1h89i8pN5j94LPTB5NZ44y e7zfd5XNo2/LKkaPz5vkAniicmwyUhNTUosUUvOS81My89JtlbyD453jTc0MDHUNLS3MlRTy EnNTbZVcfAJ03TJzgF5XUihLzCkFCgUkFhcr6dvZFOWXlqQqZOQXl9gqpRak5BQYGhboFSfm Fpfmpesl5+daGRoYGJkCVSbkZMw7/5O5YGZkxcz7CxgbGKd7djFyckgImEgsO/aBvYuRi0NI YAejxJ6mJiYI5xOjxOzvF6Ccb4wSnz7vYodpOXPhChtEYi+jxKXpa6Ccl4wS618vZgOpYhPQ lth8fBUjSEJE4B6jxK4lM8GqmAX+sUs8+XSIBaRKWMBA4sClHjCbRUBVYv6cyUBFHBy8ApYS P86Wg4R5BQQlTs58AlbCLCAvsf3tHGaIMxQkdpx9zQhSLiKgJ/GiSwaiRERidmcbVEkrh8SR 7hoI20Xix98eNghbWOLV8S1Q30hJfH63FypeL3F12WJwYEgI9DBKnPnVBlVkLDHrWTvYLmYB TYn1u/RBTAkBZYkjt6Au45PoOPyXHSLMK9HRJgTRqCIx99NlJoiwlMSHnjoI00PidhPTBEbF WUg+nIXkw1lIXpmFsHUBI8sqRrHUguLc9NRiowJj5KjexAjOFFruOxi3nfM5xCjAwajEw5tw PTpWiDWxrLgy9xCjBAezkghvxZyoWCHelMTKqtSi/Pii0pzU4kOMpsDwn8gsJZqcD8xieSXx hqZGZmYGlqYWpmZGFkrivJu4b8YICaQnlqRmp6YWpBbB9DFxcEo1MO5nitrMvedP2a3tiZmb 7RfeVw3iE5t5rCvkj4F/0c9P6n93Jsnl/WWZ12sv9lPuy5UfZoJRtUlRl2PzMrXz1yQz+4mI PNBc5Ni+XWpTOfMZJn5bX06vnwd6pyz4GKnwx8rjqbYMw4VrkR9O5pwxvH/zpsEfEefbngbX DxYKVW+5VSRrJvIvTImlOCPRUIu5qDgRALv6JuYqBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrFIsWRmVeSWpSXmKPExsWy7bCSnO7d5zGxBjv2yFh8/dLBYrH+1DFm i9V3+9ksTk89y2Qx53wLi8Xed7NZLdbu+cNs0f1KxuLJ+lnMFjd+tbFa9D9+zWxx/vwGdotN j6+xWuy9pW1x/95PJouZ8+6wWVxa5G7xat43Fos9e0+yWFzeNYfN4sj/fkaLGef3MVm0bfzK aNHa85Pd4vjacAdJjy0rbzJ5tGwu99h2QNXj8tlSj02rOtk87lzbw+axeUm9x+4Fn5k8ms4c ZfZ4v+8qm0ffllWMHp83yQXwRHHZpKTmZJalFunbJXBlzDv/k7lgZmTFzPsLGBsYp3t2MXJy SAiYSJy5cIWti5GLQ0hgN6PEuWMHWCESUhJb2/cwQ9jCEvdbjrBCFD1nlFjQ8IcdJMEmoC2x +fgqRpCEiMAjRon/LxeAJZgFpnFI7PogDmILCxhIHLjUwwJiswioSsyfMxloHQcHr4ClxI+z 5SBhXgFBiZMzn7CAhJkF9CTaNjJCTJGX2P52DtQNChI7zr5mBCkRASp50SUDUSIiMbuzjXkC o+AsJINmIQyahWTQLCQdCxhZVjFKphYU56bnFhsWGOWllusVJ+YWl+al6yXn525iBKcALa0d jCdOxB9iFOBgVOLh3XEzOlaINbGsuDL3EKMEB7OSCG/FnKhYId6UxMqq1KL8+KLSnNTiQ4zS HCxK4rzy+ccihQTSE0tSs1NTC1KLYLJMHJxSDYzSXX/3Xt60OXLd8k2d33IeCFlefJUwnamu pS5k77/dBWGz9bZmCnAsjt978jWvSbFwYnmzZpL05kvH8hp+qN3+pdHFv/R4n5viBR5j0RuT NsyrqzKR3sxdtXLr5E3v9204xJLvdmDaCxeLzrci35/wnL1y5S6vn+mJpR4+3538uTa6H2RI O3dGiaU4I9FQi7moOBEAcCg2h/0CAAA= X-CMS-MailID: 20190821064237epcas2p4d8bc4858fda55be213eb51b19e52fc71 X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20190821064237epcas2p4d8bc4858fda55be213eb51b19e52fc71 References: Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org This patch support fscrypt to use diskcipher in a specific crypto mode (FSCRYPT_MODE_PRIVATE). Fscrypt allocates diskcipher and sets the key on diskcipher. Fscrypt doesn't handle additional data encryption when using diskcipher. Cc: Theodore Y. Ts'o Cc: Jaegeuk Kim Cc: Eric Biggers Signed-off-by: Boojin Kim --- fs/buffer.c | 2 ++ fs/crypto/bio.c | 43 ++++++++++++++++++++++++++----- fs/crypto/fscrypt_private.h | 28 +++++++++++++++++++- fs/crypto/keysetup.c | 60 +++++++++++++++++++++++++++++++++++++++++-- fs/crypto/keysetup_v1.c | 2 +- include/linux/fscrypt.h | 19 ++++++++++++++ include/uapi/linux/fscrypt.h | 2 ++ tools/include/uapi/linux/fs.h | 1 + 8 files changed, 147 insertions(+), 10 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 131d39e..a7de079 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -3129,6 +3129,8 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh, wbc_account_cgroup_owner(wbc, bh->b_page, bh->b_size); } + if (bio->bi_opf & REQ_CRYPT) + bio->bi_aux_private = bh->b_private; submit_bio(bio); return 0; } diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c index 82da251..9e4bf9b 100644 --- a/fs/crypto/bio.c +++ b/fs/crypto/bio.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "fscrypt_private.h" static void __fscrypt_decrypt_bio(struct bio *bio, bool done) @@ -81,13 +82,19 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, if (!ciphertext_page) return -ENOMEM; - while (len--) { - err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk, - ZERO_PAGE(0), ciphertext_page, - blocksize, 0, GFP_NOFS); - if (err) - goto errout; + if (__fscrypt_disk_encrypted(inode)) { + memset(page_address(ciphertext_page), 0, PAGE_SIZE); + ciphertext_page->mapping = inode->i_mapping; + } + while (len--) { + if (!__fscrypt_disk_encrypted(inode)) { + err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk, + ZERO_PAGE(0), ciphertext_page, + blocksize, 0, GFP_NOFS); + if (err) + goto errout; + } bio = bio_alloc(GFP_NOWAIT, 1); if (!bio) { err = -ENOMEM; @@ -103,6 +110,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, err = -EIO; goto errout; } + fscrypt_set_bio(inode, bio, 0); err = submit_bio_wait(bio); if (err == 0 && bio->bi_status) err = -EIO; @@ -118,3 +126,26 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, return err; } EXPORT_SYMBOL(fscrypt_zeroout_range); + +int fscrypt_disk_encrypted(const struct inode *inode) +{ + return __fscrypt_disk_encrypted(inode); +} + +void fscrypt_set_bio(const struct inode *inode, struct bio *bio, u64 dun) +{ +#ifdef CONFIG_CRYPTO_DISKCIPHER + if (__fscrypt_disk_encrypted(inode)) + crypto_diskcipher_set(bio, inode->i_crypt_info->ci_dtfm, + inode, dun); +#endif +} + +void *fscrypt_get_diskcipher(const struct inode *inode) +{ +#ifdef CONFIG_CRYPTO_DISKCIPHER + if (fscrypt_has_encryption_key(inode)) + return inode->i_crypt_info->ci_dtfm; +#endif + return NULL; +} diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index e84efc0..d2b5fb6 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -163,6 +163,10 @@ struct fscrypt_info { /* The actual crypto transform used for encryption and decryption */ struct crypto_skcipher *ci_ctfm; + /* Cipher for inline encryption engine */ +#ifdef CONFIG_CRYPTO_DISKCIPHER + struct crypto_diskcipher *ci_dtfm; +#endif /* * Cipher for ESSIV IV generation. Only set for CBC contents * encryption, otherwise is NULL. @@ -226,6 +230,10 @@ static inline bool fscrypt_valid_enc_modes(u32 contents_mode, filenames_mode == FSCRYPT_MODE_ADIANTUM) return true; + if (contents_mode == FSCRYPT_MODE_PRIVATE && + filenames_mode == FSCRYPT_MODE_AES_256_CTS) + return true; + return false; } @@ -438,13 +446,19 @@ extern int __init fscrypt_init_keyring(void); /* keysetup.c */ +enum cipher_flags { + CRYPT_MODE_SKCIPHER, + CRYPT_MODE_ESSIV, + CRYPT_MODE_DISKCIPHER, +}; + struct fscrypt_mode { const char *friendly_name; const char *cipher_str; int keysize; int ivsize; bool logged_impl_name; - bool needs_essiv; + enum cipher_flags flags; }; static inline bool @@ -453,6 +467,18 @@ fscrypt_mode_supports_direct_key(const struct fscrypt_mode *mode) return mode->ivsize >= offsetofend(union fscrypt_iv, nonce); } +static inline int __fscrypt_disk_encrypted(const struct inode *inode) +{ +#if IS_ENABLED(CONFIG_FS_ENCRYPTION) +#if IS_ENABLED(CONFIG_CRYPTO_DISKCIPHER) + if (inode && inode->i_crypt_info) + return S_ISREG(inode->i_mode) && + (inode->i_crypt_info->ci_dtfm != NULL); +#endif +#endif + return 0; +} + extern struct crypto_skcipher * fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, const struct inode *inode); diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index d71c2d6..06d9609 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "fscrypt_private.h" @@ -35,7 +36,7 @@ static struct fscrypt_mode available_modes[] = { .cipher_str = "cbc(aes)", .keysize = 16, .ivsize = 16, - .needs_essiv = true, + .flags = CRYPT_MODE_ESSIV, }, [FSCRYPT_MODE_AES_128_CTS] = { .friendly_name = "AES-128-CTS-CBC", @@ -49,6 +50,13 @@ static struct fscrypt_mode available_modes[] = { .keysize = 32, .ivsize = 32, }, + [FSCRYPT_MODE_PRIVATE] = { + .friendly_name = "AES-256-XTS-DISK", + .cipher_str = "xts(aes)-disk", + .keysize = 64, + .ivsize = 16, + .flags = CRYPT_MODE_DISKCIPHER, + }, }; static struct fscrypt_mode * @@ -111,6 +119,35 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, return ERR_PTR(err); } +#if defined(CONFIG_CRYPTO_DISKCIPHER) +/* Create a diskcipher cipher object for the given encryption mode and key */ +static struct crypto_diskcipher *fscrypt_allocate_diskcipher( + struct fscrypt_mode *mode, const u8 *raw_key, + const struct inode *inode) +{ + struct crypto_diskcipher *tfm; + int err; + bool force = (mode->flags == CRYPT_MODE_DISKCIPHER) ? 0 : 1; + + tfm = crypto_alloc_diskcipher(mode->cipher_str, 0, 0, force); + if (IS_ERR(tfm)) { + fscrypt_warn(inode->i_sb, + "error allocating '%s' transform for inode %lu: %ld", + mode->cipher_str, inode->i_ino, PTR_ERR(tfm)); + return tfm; + } + err = crypto_diskcipher_setkey(tfm, raw_key, mode->keysize, 0); + if (err) + goto err_free_dtfm; + + return tfm; + +err_free_dtfm: + crypto_free_diskcipher(tfm); + return ERR_PTR(err); +} +#endif + static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) { struct crypto_shash *tfm = READ_ONCE(essiv_hash_tfm); @@ -187,13 +224,29 @@ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) struct crypto_skcipher *ctfm; int err; +#if defined(CONFIG_CRYPTO_DISKCIPHER) + if (S_ISREG(ci->ci_inode->i_mode) && + (mode->flags == CRYPT_MODE_DISKCIPHER)) { + ci->ci_dtfm = fscrypt_allocate_diskcipher(mode, derived_key, + ci->ci_inode); + if (IS_ERR(ci->ci_dtfm)) { + fscrypt_warn(ci->ci_inode, + "Error allocating Diskcipher: %p", + PTR_ERR(ci->ci_dtfm)); + ci->ci_dtfm = NULL; + return -EINVAL; + } + return 0; + } +#endif + ctfm = fscrypt_allocate_skcipher(mode, derived_key, ci->ci_inode); if (IS_ERR(ctfm)) return PTR_ERR(ctfm); ci->ci_ctfm = ctfm; - if (mode->needs_essiv) { + if (mode->flags == CRYPT_MODE_ESSIV) { err = init_essiv_generator(ci, derived_key, mode->keysize); if (err) { fscrypt_warn(ci->ci_inode, @@ -394,6 +447,9 @@ static void put_crypt_info(struct fscrypt_info *ci) !fscrypt_is_direct_key_policy(&ci->ci_policy)) { crypto_free_skcipher(ci->ci_ctfm); crypto_free_cipher(ci->ci_essiv_tfm); +#if defined(CONFIG_CRYPTO_DISKCIPHER) + crypto_free_diskcipher(ci->ci_dtfm); +#endif } key = ci->ci_master_key; diff --git a/fs/crypto/keysetup_v1.c b/fs/crypto/keysetup_v1.c index 0727251..22d0330 100644 --- a/fs/crypto/keysetup_v1.c +++ b/fs/crypto/keysetup_v1.c @@ -271,7 +271,7 @@ static int setup_v1_file_key_direct(struct fscrypt_info *ci, } /* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */ - if (WARN_ON(mode->needs_essiv)) + if (WARN_ON(mode->flags == CRYPT_MODE_ESSIV)) return -EINVAL; dk = fscrypt_get_direct_key(ci, raw_master_key); diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index f622f74..e0f99db 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -274,6 +274,11 @@ static inline void fscrypt_set_ops(struct super_block *sb, { sb->s_cop = s_cop; } + +void fscrypt_set_bio(const struct inode *inode, struct bio *bio, u64 dun); +void *fscrypt_get_diskcipher(const struct inode *inode); +int fscrypt_disk_encrypted(const struct inode *inode); + #else /* !CONFIG_FS_ENCRYPTION */ static inline bool fscrypt_has_encryption_key(const struct inode *inode) @@ -556,6 +561,20 @@ static inline void fscrypt_set_ops(struct super_block *sb, { } +static inline int fscrypt_disk_encrypted(const struct inode *inode) +{ + return 0; +} + +static inline void fscrypt_set_bio(const struct inode *inode, + struct bio *bio, u64 dun) +{ +} + +static inline void *fscrypt_get_diskcipher(const struct inode *inode) +{ + return NULL; +} #endif /* !CONFIG_FS_ENCRYPTION */ /** diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 39ccfe9..b9978c4 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -25,6 +25,7 @@ #define FSCRYPT_MODE_AES_128_CBC 5 #define FSCRYPT_MODE_AES_128_CTS 6 #define FSCRYPT_MODE_ADIANTUM 9 +#define FSCRYPT_MODE_PRIVATE 127 #define __FSCRYPT_MODE_MAX 9 /* @@ -173,6 +174,7 @@ struct fscrypt_get_key_status_arg { #define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 /* removed */ #define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 /* removed */ #define FS_ENCRYPTION_MODE_ADIANTUM FSCRYPT_MODE_ADIANTUM +#define FS_ENCRYPTION_MODE_PRIVATE FSCRYPT_MODE_PRIVATE #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 diff --git a/tools/include/uapi/linux/fs.h b/tools/include/uapi/linux/fs.h index 2a616aa..dd3566a 100644 --- a/tools/include/uapi/linux/fs.h +++ b/tools/include/uapi/linux/fs.h @@ -237,6 +237,7 @@ struct fsxattr { #define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 /* Removed, do not use. */ #define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 /* Removed, do not use. */ #define FS_ENCRYPTION_MODE_ADIANTUM 9 +#define FS_ENCRYPTION_MODE_PRIVATE 127 struct fscrypt_policy { __u8 version; From patchwork Wed Aug 21 06:42:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "boojin.kim" X-Patchwork-Id: 11105657 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 154D51399 for ; Wed, 21 Aug 2019 06:43:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D418C233A0 for ; Wed, 21 Aug 2019 06:43:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="kp+wYQgR" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728304AbfHUGnC (ORCPT ); Wed, 21 Aug 2019 02:43:02 -0400 Received: from mailout2.samsung.com ([203.254.224.25]:60371 "EHLO mailout2.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728221AbfHUGmq (ORCPT ); Wed, 21 Aug 2019 02:42:46 -0400 Received: from epcas2p2.samsung.com (unknown [182.195.41.54]) by mailout2.samsung.com (KnoxPortal) with ESMTP id 20190821064244epoutp02a4e9f1d0182ddb548a485e7dafd3bce5~83QB8iMAJ1267012670epoutp02g for ; Wed, 21 Aug 2019 06:42:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.samsung.com 20190821064244epoutp02a4e9f1d0182ddb548a485e7dafd3bce5~83QB8iMAJ1267012670epoutp02g DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1566369764; bh=VSDGagmX1Sh84QSpP/Zxc7H3ZzEBBEugPOm00XWkwx0=; h=From:To:Cc:Subject:Date:References:From; b=kp+wYQgRZgOk30PDx/G0sx/S9JGS+WMOAxGeYQOhxCwTFhWXPjRLlfq8V9XoQIv0d kHIa7c4cXTlVNxtlfwoIdCtGC/wTh4kmgGazf6okMXcPFgpg3rvBuzO43DuhAjt4p8 oOf7qdS2iGASi+TD52hxrG8LkB+SI6sEhePULqAM= Received: from epsnrtp3.localdomain (unknown [182.195.42.164]) by epcas2p1.samsung.com (KnoxPortal) with ESMTP id 20190821064243epcas2p1513f6c689a79a36dc0dc1754286752d7~83QBVTBwc0977609776epcas2p1p; Wed, 21 Aug 2019 06:42:43 +0000 (GMT) Received: from epsmges2p3.samsung.com (unknown [182.195.40.185]) by epsnrtp3.localdomain (Postfix) with ESMTP id 46CylQ4jGyzMqYkc; Wed, 21 Aug 2019 06:42:42 +0000 (GMT) Received: from epcas2p3.samsung.com ( [182.195.41.55]) by epsmges2p3.samsung.com (Symantec Messaging Gateway) with SMTP id 29.63.04068.2E7EC5D5; Wed, 21 Aug 2019 15:42:42 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p2.samsung.com (KnoxPortal) with ESMTPA id 20190821064241epcas2p2bf71ad8055188f8b47870b06480c8368~83P-e0YIv2515525155epcas2p2D; Wed, 21 Aug 2019 06:42:41 +0000 (GMT) Received: from epsmgms1p2new.samsung.com (unknown [182.195.42.42]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20190821064241epsmtrp2ffa0d72b199a07928d6700dafdc21bfb~83P-dxpZv2242122421epsmtrp2m; Wed, 21 Aug 2019 06:42:41 +0000 (GMT) X-AuditID: b6c32a47-5a1ff70000000fe4-d0-5d5ce7e276af Received: from epsmtip1.samsung.com ( [182.195.34.30]) by epsmgms1p2new.samsung.com (Symantec Messaging Gateway) with SMTP id E8.E2.03638.1E7EC5D5; Wed, 21 Aug 2019 15:42:41 +0900 (KST) Received: from KORDO035251 (unknown [12.36.165.204]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20190821064241epsmtip103e0e63af169ffafdce3a6511ac306af~83P_uPq-h0421904219epsmtip1n; Wed, 21 Aug 2019 06:42:41 +0000 (GMT) From: "boojin.kim" To: "'Theodore Ts'o'" , "'Andreas Dilger'" , , , Cc: "'Herbert Xu'" , "'David S. Miller'" , "'Eric Biggers'" , "'Theodore Y. Ts'o'" , "'Chao Yu'" , "'Jaegeuk Kim'" , "'Andreas Dilger'" , "'Theodore Ts'o'" , , "'Mike Snitzer'" , "'Alasdair Kergon'" , "'Jens Axboe'" , "'Krzysztof Kozlowski'" , "'Kukjin Kim'" , "'Jaehoon Chung'" , "'Ulf Hansson'" , , , , , , , , , , , Subject: [PATCH 8/9] fs: ext4: support diskcipher Date: Wed, 21 Aug 2019 15:42:41 +0900 Message-ID: <004401d557eb$a1989480$e4c9bd80$@samsung.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 14.0 Thread-Index: AdVX6KvjWZDiSF7MRaiKA5mSaSDrOQ== Content-Language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA01Tf0wTZxjed3e9O5ldbpVtn82m3U2WCSm2sOLHIm5RI5fIEozJXFwbOOEC zP5Kr0VdFmsMdNiRASE6WzqjqCOrIltLkDBgBgSqwFhGcJbAWEaDGwTdysQA6tZ6NeO/533e 53l/5M1L4woPpaTLzHbBZuaNLJlEtPVu3qr+/a7eoPENpaAH/1QRqOVWP44uT9aQaPDUMIZ8 IxUE6rrXIEPNnY9w9PnsqyjS4sXRnWWXDNVMz+FoZORbCgWmb8tQ13gamvp1CUOesxMk+rkx F82eXSRQZ9dNAo12+Eh0498agM6MdGPI9d0DgCqrlyg00Lz/vfVc6zdhjKsIHubarqdwo8MO LuA/SXITtztJLnjRyX1/bgHjTgz14dz97jGS+6LVD7iFwIb8tQeM20oFvliwqQRzkaW4zFyS w+7ZV7CzQJel0aq12WgrqzLzJiGH3ZWXr95dZoztzqrKeaMjRuXzoshu2b7NZnHYBVWpRbTn sIK12GjVaq3pIm8SHeaS9CKL6R2tRpOhiykLjaXu5nqZdVF95LcvV6jj4HyKG6yhIfM27Bxf IdwgiVYw7QBe9DfJpCAK4N8//UFKwSKAXncV/szyqC6USHQBOFlRl/D/CeD4w5AsriKZNBgc 8IN4Ipm5BqB76cnTAGeeUDAS7YlZaHodo4VXfHvjBoJJgb3hMBbHciYbzgTnKAm/CG96IkQc 48xGeG3elxhDBduH50AcJzPp8P5yEylpkmHDSVdC85iCF/pfi7eCzC541QUleh2cHWilJKyE C/e6SAk74djXF6j4mJCpBnBo2ZUQZULvzGcgXgdnNsOWji1SyTfgjfHEZC/Aqt7HlETLYZVL IRk3wa+io5hEK+Ff1cckmoMzTaexWvC6d9WK3lUrelet4v2/7TlA+MHLglU0lQhihjVz9a0D 4OlbpOa2g7Yf83oAQwN2rbzwl48MChlfLh419QBI42yy/IjvgEEhL+aPfiLYLAU2h1EQe4Au doE6XPlSkSX2ZGZ7gVaXkZWlydYhXVYGYl+RB54P6xVMCW8XDgmCVbA982H0GuVxkLuj+kTb 6VDImbN+sNF5K1NVbgre7T/sntA34JsawHOGJL2n3iO8uT1p7+WD6lMHm/r24O8eG/508EPn pd75UNrAB3kr+h8ifZeEjzcgn2ls/tCO6fMbp/Kmoo3LtWFf5EplVFNpqa85s/P9/XR3x4wh Fbs6Ueu7vq/wregkuvOQJcRSXpuK20T+P4eFjIYsBAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrNIsWRmVeSWpSXmKPExsWy7bCSnO7D5zGxBucmmlh8/dLBYrH+1DFm i9V3+9ksTk89y2Qx53wLi8Xed7NZLdbu+cNs0f1KxuLJ+lnMFjd+tbFa9D9+zWxx/vwGdotN j6+xWuy9pW1x/95PJouZ8+6wWVxa5G7xat43Fos9e0+yWFzeNYfN4sj/fkaLGef3MVm0bfzK aNHa85Pd4vjacAdJjy0rbzJ5tGwu99h2QNXj8tlSj02rOtk87lzbw+axeUm9x+4Fn5k8ms4c ZfZ4v+8qm0ffllWMHp83yQXwRHHZpKTmZJalFunbJXBldK2dzFrwTbfiwfTf7A2MC1W7GDk5 JARMJP5MPMHWxcjFISSwm1Fi0enpzBAJKYmt7XugbGGJ+y1HWCGKnjNKrFjRxwKSYBPQlth8 fBUjSEIEpPvVqY2MIAlmgWkcErs+iHcxcnAICxhKrJkTCBJmEVCVOHzzJhOIzStgKfFs82t2 CFtQ4uTMJywg5cwCehJtMFPkJba/nQN1g4LEjrOvweIiQCXvfy1ng6gRkZjd2cY8gVFwFpJJ sxAmzUIyaRaSjgWMLKsYJVMLinPTc4sNC4zyUsv1ihNzi0vz0vWS83M3MYKTgJbWDsYTJ+IP MQpwMCrx8O64GR0rxJpYVlyZe4hRgoNZSYS3Yk5UrBBvSmJlVWpRfnxRaU5q8SFGaQ4WJXFe +fxjkUIC6YklqdmpqQWpRTBZJg5OqQbG1j+X7p0ojljf0sTdnBLg/IotLzPO5cnquTv/Kex8 9Ek2b7r81+i/PGV67/55MljZOEgETd3B97fnlLDkLI2LH5pTlU7yX/27L+7F3b885SK7D9Q2 r+59+J/plWpgl83hdP4X20qjImp16mawORmfZxFZL7Fnb4SEvXlfcc/d9nmG3J+abPSVWIoz Eg21mIuKEwEfL/cX/gIAAA== X-CMS-MailID: 20190821064241epcas2p2bf71ad8055188f8b47870b06480c8368 X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20190821064241epcas2p2bf71ad8055188f8b47870b06480c8368 References: Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Ext4 checks the crypto properties of the inode, and if it is a diskcipher, sets it to BIO before submitting the BIO. When using diskcipher, Ext4 does not encrypt the data before submitting the BIO and decrypt the data on complete of the BIO. Cc: Theodore Ts'o Cc: Andreas Dilger Signed-off-by: Boojin Kim --- fs/ext4/inode.c | 39 +++++++++++++++++++++++++++++++++------ fs/ext4/page-io.c | 8 +++++++- fs/ext4/readpage.c | 7 +++++++ 3 files changed, 47 insertions(+), 7 deletions(-) @@ -376,6 +379,10 @@ int ext4_mpage_readpages(struct address_space *mapping, bio->bi_private = ctx; bio_set_op_attrs(bio, REQ_OP_READ, is_readahead ? REQ_RAHEAD : 0); +#if defined(CONFIG_FS_ENCRYPTION) && defined(CONFIG_CRYPTO_DISKCIPHER) + if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) + fscrypt_set_bio(inode, bio, 0); +#endif } length = first_hole << blkbits; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 5bcc96f..7f9e1fa 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1223,7 +1223,14 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len, if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh) && (block_start < from || block_end > to)) { - ll_rw_block(REQ_OP_READ, 0, 1, &bh); + if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode) + && fscrypt_has_encryption_key(inode)) { + bh->b_private = fscrypt_get_diskcipher(inode); + ll_rw_block(REQ_OP_READ, + bh->b_private ? REQ_CRYPT : 0, 1, &bh); + } else { + ll_rw_block(REQ_OP_READ, 0, 1, &bh); + } wait[nr_wait++] = bh; } } @@ -1237,7 +1244,8 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len, } if (unlikely(err)) { page_zero_new_buffers(page, from, to); - } else if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) { + } else if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && + !bh->b_private) { for (i = 0; i < nr_wait; i++) { int err2; @@ -3670,6 +3678,13 @@ const struct iomap_ops ext4_iomap_ops = { .iomap_end = ext4_iomap_end, }; +static void ext4_submit_dio(struct bio *bio, struct inode *inode, + loff_t file_offset) +{ + fscrypt_set_bio(inode, bio, 0); + submit_bio(bio); +} + static int ext4_end_io_dio(struct kiocb *iocb, loff_t offset, ssize_t size, void *private) { @@ -3801,7 +3816,9 @@ static ssize_t ext4_direct_IO_write(struct kiocb *iocb, struct iov_iter *iter) dio_flags = DIO_LOCKING; } ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter, - get_block_func, ext4_end_io_dio, NULL, + get_block_func, ext4_end_io_dio, + !fscrypt_disk_encrypted(inode) ? + NULL : ext4_submit_dio, dio_flags); if (ret > 0 && !overwrite && ext4_test_inode_state(inode, @@ -3909,7 +3926,8 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter) ssize_t ret; #ifdef CONFIG_FS_ENCRYPTION - if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) + if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) + && !fscrypt_disk_encrypted(inode)) return 0; #endif if (fsverity_active(inode)) @@ -4090,7 +4108,15 @@ static int __ext4_block_zero_page_range(handle_t *handle, if (!buffer_uptodate(bh)) { err = -EIO; - ll_rw_block(REQ_OP_READ, 0, 1, &bh); + if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode) + && fscrypt_has_encryption_key(inode)) { + bh->b_private = fscrypt_get_diskcipher(inode); + ll_rw_block(REQ_OP_READ, bh->b_private ? REQ_CRYPT : 0, + 1, &bh); + } else { + ll_rw_block(REQ_OP_READ, 0, 1, &bh); + } + wait_on_buffer(bh); /* Uhhuh. Read error. Complain and punt. */ if (!buffer_uptodate(bh)) @@ -4098,7 +4124,8 @@ static int __ext4_block_zero_page_range(handle_t *handle, if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) { /* We expect the key to be set. */ BUG_ON(!fscrypt_has_encryption_key(inode)); - WARN_ON_ONCE(fscrypt_decrypt_pagecache_blocks( + if (!bh->b_private) + WARN_ON_ONCE(fscrypt_decrypt_pagecache_blocks( page, blocksize, bh_offset(bh))); } } diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 12ceadef..3e41788 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -345,6 +345,11 @@ void ext4_io_submit(struct ext4_io_submit *io) REQ_SYNC : 0; io->io_bio->bi_write_hint = io->io_end->inode->i_write_hint; bio_set_op_attrs(io->io_bio, REQ_OP_WRITE, io_op_flags); +#if defined(CONFIG_FS_ENCRYPTION) && defined(CONFIG_CRYPTO_DISKCIPHER) + if (IS_ENCRYPTED(io->io_end->inode) && + S_ISREG(io->io_end->inode->i_mode)) + fscrypt_set_bio(io->io_end->inode, io->io_bio, 0); +#endif submit_bio(io->io_bio); } io->io_bio = NULL; @@ -474,7 +479,8 @@ int ext4_bio_write_page(struct ext4_io_submit *io, * (e.g. holes) to be unnecessarily encrypted, but this is rare and * can't happen in the common case of blocksize == PAGE_SIZE. */ - if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) { + if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit && + !fscrypt_disk_encrypted(inode)) { gfp_t gfp_flags = GFP_NOFS; unsigned int enc_bytes = round_up(len, i_blocksize(inode)); diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c index a30b203..aab2cf7c 100644 --- a/fs/ext4/readpage.c +++ b/fs/ext4/readpage.c @@ -183,6 +183,9 @@ static struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode, unsigned int post_read_steps = 0; struct bio_post_read_ctx *ctx = NULL; + if (fscrypt_disk_encrypted(inode)) + return NULL; + if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) post_read_steps |= 1 << STEP_DECRYPT; From patchwork Wed Aug 21 06:42:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "boojin.kim" X-Patchwork-Id: 11105647 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CB10F13A4 for ; Wed, 21 Aug 2019 06:42:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 95880233A2 for ; Wed, 21 Aug 2019 06:42:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="TVv8ux+x" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728267AbfHUGmv (ORCPT ); Wed, 21 Aug 2019 02:42:51 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:10396 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728163AbfHUGmu (ORCPT ); Wed, 21 Aug 2019 02:42:50 -0400 Received: from epcas2p3.samsung.com (unknown [182.195.41.55]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20190821064246epoutp01f336c57160295cfc9140dd15fa7737e1~83QEHMPPx1005210052epoutp01e for ; Wed, 21 Aug 2019 06:42:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20190821064246epoutp01f336c57160295cfc9140dd15fa7737e1~83QEHMPPx1005210052epoutp01e DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1566369766; bh=5IRlHuEkcQOCy+sESryaGK2Vl6raRZeU9YxYhLk96AY=; h=From:To:Cc:Subject:Date:References:From; b=TVv8ux+xnM0kzSu9X5T+yL6124jIoIZhVT908IdSRYCpRjPYXl2fk0Bj7h7uTDBhc PlUPwkm3fhUR/DK7QcL6f28c+CAh6IrqMYEKTdNsmM3VR5hCTXIfETB6Vffx7cIS/W h93zUelUxLBuQwgmbOisxoaJZMq96xBqAzSILO2Q= Received: from epsnrtp4.localdomain (unknown [182.195.42.165]) by epcas2p4.samsung.com (KnoxPortal) with ESMTP id 20190821064246epcas2p46aa2363c453d0816b5eae31671ceaab1~83QDXRLKm1664716647epcas2p44; Wed, 21 Aug 2019 06:42:46 +0000 (GMT) Received: from epsmges2p4.samsung.com (unknown [182.195.40.181]) by epsnrtp4.localdomain (Postfix) with ESMTP id 46CylS647jzMqYkb; Wed, 21 Aug 2019 06:42:44 +0000 (GMT) Received: from epcas2p4.samsung.com ( [182.195.41.56]) by epsmges2p4.samsung.com (Symantec Messaging Gateway) with SMTP id 93.3F.04112.4E7EC5D5; Wed, 21 Aug 2019 15:42:44 +0900 (KST) Received: from epsmtrp2.samsung.com (unknown [182.195.40.14]) by epcas2p1.samsung.com (KnoxPortal) with ESMTPA id 20190821064244epcas2p1e3d77667eed99670611d9353cf365f8b~83QB6TTuq0242202422epcas2p1e; Wed, 21 Aug 2019 06:42:44 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp2.samsung.com (KnoxPortal) with ESMTP id 20190821064244epsmtrp29678be437d037ce9caa184fdd262a64c~83QB5MerG2242122421epsmtrp2o; Wed, 21 Aug 2019 06:42:44 +0000 (GMT) X-AuditID: b6c32a48-f1fff70000001010-de-5d5ce7e49cf8 Received: from epsmtip1.samsung.com ( [182.195.34.30]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 17.12.03706.4E7EC5D5; Wed, 21 Aug 2019 15:42:44 +0900 (KST) Received: from KORDO035251 (unknown [12.36.165.204]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20190821064243epsmtip1e5ee582abd1b9fa164ad5cc11fb9592e~83QBWXge90467104671epsmtip1E; Wed, 21 Aug 2019 06:42:43 +0000 (GMT) From: "boojin.kim" To: "'Jaegeuk Kim'" , "'Chao Yu'" , , , Cc: "'Herbert Xu'" , "'David S. Miller'" , "'Eric Biggers'" , "'Theodore Y. Ts'o'" , "'Chao Yu'" , "'Jaegeuk Kim'" , "'Andreas Dilger'" , "'Theodore Ts'o'" , , "'Mike Snitzer'" , "'Alasdair Kergon'" , "'Jens Axboe'" , "'Krzysztof Kozlowski'" , "'Kukjin Kim'" , "'Jaehoon Chung'" , "'Ulf Hansson'" , , , , , , , , , , , Subject: [PATCH 9/9] fs: f2fs: support diskcipher Date: Wed, 21 Aug 2019 15:42:43 +0900 Message-ID: <004501d557eb$a31dd4f0$e9597ed0$@samsung.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 14.0 Thread-Index: AdVX6LxzK3qdVI3wS/yWqol0XSZg9A== Content-Language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA02TfUwbdRjH/d1d7465mluH+lt9qzeJbpPS6yj+MGO+ke3itojxjykb4oWe lHh9Sa/FsahjZnSAxG4mYtsVsuA0W80EC2LdKCFdXTMEayQssKBzAdGxwUwZxM1NbXss8t/n efJ8n+f55slD45oApaVrbC7RaRMkllxB9J5Zh/Knft9dYfCeNaCF640E6hw8i6MvfvaS6PuP hzEUTB4gUHTuiAqd7LuFow9mHkRTnQEcjd30qJB38gqOkskuCoUnz6tQ9MIGdPGXGxjyt0+Q 6KeOrWimfZFAfdFzBBo5FSRR/F8vQL5kP4Y8Xy0A1NByg0KJkzufXcP3nBjH+APdb/O9A3n8 yLCbD4eaSH7ifB/Jdx/bx58+Oo/x7w99h/PX+kdJ/sOeEODnww+XrSyXNllEwSw6daKtym6u sVWXsNteqXyh0lRk4PK5YvQUq7MJVrGELd1elr+lRkp7Z3W1guROp8oEWWYLNm9y2t0uUWex y64SVnSYJQfHOfSyYJXdtmp9ld36NGcwGE3pyjcky+TVi8ARf2bPYEOHqh7MbGwGOTRkCuHk 6I+gGaygNUwEwOZEw1KQAjA2348rwSKAvtBV4o4kmPSTGdYwUQAXw1qFLwMYP1GbYZLZALsT oWynXKYXwIH9o0QmwJl/KDiVimU7rWY4eKi9PssEkwe/jXVhGVYzxfDv4ACh8Cp4zj+VZZx5 BH4zG8SVLXQwMnwFZDiX0cPOnjim1OTCI02e7NqQ2U/D2YNNS4JS+Ov1SyqFV8OZRA+lsBbO z0VJhffB0c8/pRRxC4BDNz1LRRthYPpgehqdnrAOdp4qyCBk1sL4haXd7oGNZ25TSloNGz0a RfgYbEuNYEpaC/9seU9J8/DWJ73gEHg0sMxkYJnJwDIzgf/HHgVECNwnOmRrtSgbHYXLjx0G 2b9Yz0fAwA/bY4ChAbtSHRnfVaFRCbVynTUGII2zueo9wfIKjdos1O0VnfZKp1sS5RgwpW9w GNfeW2VPf5nNVcmZjEVFhmITMhUZEXu/Onz3+G4NUy24xLdE0SE67+gwOkdbD3aqce/ruo5W O+Ur3TGWNO3Fy9800nGtPvlR/9w79gJ5hzS4NpKcmE7dHupY89Clx6Uq77acxHHQ5p7b6p5d 5Q8eX9gy3faZ47D0ZGnhc1+2YiaKvusP21+pJy57TrcOtXzNbH6Xu/Yi43v1eX1X3kuW+G/8 2GvGB3y7zP6Xjw3WsYRsEbj1uFMW/gMNo7CALQQAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrNIsWRmVeSWpSXmKPExsWy7bCSnO6T5zGxBnM/iFl8/dLBYrH+1DFm i9V3+9ksTk89y2Qx53wLi8Xed7NZLdbu+cNs0f1KxuLJ+lnMFjd+tbFa9D9+zWxx/vwGdotN j6+xWuy9pW1x/95PJouZ8+6wWVxa5G7xat43Fos9e0+yWFzeNYfN4sj/fkaLGef3MVm0bfzK aNHa85Pd4vjacAdJjy0rbzJ5tGwu99h2QNXj8tlSj02rOtk87lzbw+axeUm9x+4Fn5k8ms4c ZfZ4v+8qm0ffllWMHp83yQXwRHHZpKTmZJalFunbJXBlPH5zn7HgiH3FqdZFrA2Mr4y7GDk5 JARMJOacn8nWxcjFISSwm1Fi9f4fzBAJKYmt7XugbGGJ+y1HWEFsIYHnjBLH+rJBbDYBbYnN x1cxgjSLCOxilDi6s5sNJMEsMI1DYtcHcRBbWMBQYsK8BhYQm0VAVWLnoQ1MIDavgKXE7zkH WCBsQYmTM58A2RxAvXoSbRsZIcbIS2x/OwfqBgWJHWdfg8VFgErWbznCBFEjIjG7s415AqPg LCSTZiFMmoVk0iwkHQsYWVYxSqYWFOem5xYbFhjmpZbrFSfmFpfmpesl5+duYgQnAS3NHYyX l8QfYhTgYFTi4d1xMzpWiDWxrLgy9xCjBAezkghvxZyoWCHelMTKqtSi/Pii0pzU4kOM0hws SuK8T/OORQoJpCeWpGanphakFsFkmTg4pRoYp387Uzvve4emXIrU/YToF0zq/051vg7NYSlT qDRWr9TJELWe3mih13/ukJJZ7tJ7F4/ULTpzQTQx2k6lwXqnwonfE3Jz77o1Vrh+PvldI6Z3 890tbEEzXHPM73Y9+LDtwcxJv3/xWehoTf8wr53ZaWpYn2CZ1cQrAr/mbTr9/efZBct+z5Pc o8RSnJFoqMVcVJwIAG6nrC7+AgAA X-CMS-MailID: 20190821064244epcas2p1e3d77667eed99670611d9353cf365f8b X-Msg-Generator: CA X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20190821064244epcas2p1e3d77667eed99670611d9353cf365f8b References: Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org F2FS checks the crypto properties of the inode, and if it is a diskcipher, sets it to BIO before submitting the BIO. When using diskcipher, F2FS does not encrypt the data before submitting the bio and decrypt the data on complete of the BIO. F2FS uses DUN(device unit number) as the IV(initial vector) for cryptographic operations. DUN can support the Garbage collection of f2fs. Even if a data is moved in the storage device by garbage collection, the data has same DUN, so that the data can be decrypted. F2FS calculates DUN of data and sets it to BIO. Cc: Jaegeuk Kim Cc: Chao Yu Signed-off-by: Boojin Kim --- fs/f2fs/data.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- fs/f2fs/f2fs.h | 2 +- 2 files changed, 97 insertions(+), 3 deletions(-) if (f2fs_is_multi_device(sbi)) return true; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 3dfefab..c8252bf 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -85,6 +85,52 @@ struct bio_post_read_ctx { unsigned int enabled_steps; }; +/* device unit number for iv sector */ +#define PG_DUN(i, p) \ + ((((i)->i_ino & 0xffffffff) << 32) | (p & 0xffffffff)) + +static inline bool f2fs_may_encrypt_bio(struct inode *inode, + struct f2fs_io_info *fio) +{ +#ifdef CONFIG_CRYPTO_DISKCIPHER + if (fio && (fio->type != DATA || fio->encrypted_page)) + return false; + + return (f2fs_encrypted_file(inode) && + fscrypt_disk_encrypted(inode)); +#else + return false; +#endif +} + +static inline bool f2fs_bio_disk_encrypted(unsigned int bi_opf) +{ + if (bi_opf & REQ_CRYPT) + return true; + else + return false; +} + +static bool f2fs_mergeable_bio(struct bio *bio, u64 dun, void *ci, + bool bio_encrypted) +{ +#ifdef CONFIG_CRYPTO_DISKCIPHER + if (!bio) + return true; + + /* if both of them are not encrypted, no further check is needed */ + if (!f2fs_bio_disk_encrypted(bio->bi_opf) && !bio_encrypted) + return true; + + if (bio->bi_aux_private == ci) + return bio_end_dun(bio) == dun; + else + return false; +#else + return true; +#endif +} + static void __read_end_io(struct bio *bio) { struct page *page; @@ -174,6 +220,9 @@ static void f2fs_read_end_io(struct bio *bio) bio->bi_status = BLK_STS_IOERR; } + if (f2fs_bio_disk_encrypted(bio->bi_opf)) + goto end_io; + if (f2fs_bio_post_read_required(bio)) { struct bio_post_read_ctx *ctx = bio->bi_private; @@ -182,6 +231,7 @@ static void f2fs_read_end_io(struct bio *bio) return; } +end_io: __read_end_io(bio); } @@ -362,7 +412,10 @@ static void __submit_merged_bio(struct f2fs_bio_info *io) if (!io->bio) return; - bio_set_op_attrs(io->bio, fio->op, fio->op_flags); + if (f2fs_bio_disk_encrypted(io->bio->bi_opf)) + bio_set_op_attrs(io->bio, fio->op, fio->op_flags | REQ_CRYPT); + else + bio_set_op_attrs(io->bio, fio->op, fio->op_flags); if (is_read_io(fio->op)) trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio); @@ -476,6 +529,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) struct bio *bio; struct page *page = fio->encrypted_page ? fio->encrypted_page : fio->page; + struct inode *inode = fio->page->mapping->host; if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, fio->is_por ? META_POR : (__is_meta_io(fio) ? @@ -502,6 +556,9 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) inc_page_count(fio->sbi, is_read_io(fio->op) ? __read_io_type(page): WB_DATA_TYPE(fio->page)); + if (f2fs_may_encrypt_bio(inode, fio)) + fscrypt_set_bio(inode, bio, PG_DUN(inode, fio->page->index)); + __submit_bio(fio->sbi, bio, fio->type); return 0; } @@ -604,6 +661,9 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) enum page_type btype = PAGE_TYPE_OF_BIO(fio->type); struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp; struct page *bio_page; + struct inode *inode; + bool bio_encrypted; + u64 dun; f2fs_bug_on(sbi, is_read_io(fio->op)); @@ -624,6 +684,9 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) verify_fio_blkaddr(fio); bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page; + inode = fio->page->mapping->host; + dun = PG_DUN(inode, fio->page->index); + bio_encrypted = f2fs_may_encrypt_bio(inode, fio); /* set submitted = true as a return value */ fio->submitted = true; @@ -633,6 +696,10 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) if (io->bio && !io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio, fio->new_blkaddr)) __submit_merged_bio(io); + + if (!f2fs_mergeable_bio(io->bio, dun, + fscrypt_get_diskcipher(inode), bio_encrypted)) + __submit_merged_bio(io); alloc_new: if (io->bio == NULL) { if ((fio->type == DATA || fio->type == NODE) && @@ -644,6 +711,9 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) io->bio = __bio_alloc(sbi, fio->new_blkaddr, fio->io_wbc, BIO_MAX_PAGES, false, fio->type, fio->temp); + if (bio_encrypted) + fscrypt_set_bio(inode, io->bio, dun); + io->fio = *fio; } @@ -691,7 +761,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, bio->bi_end_io = f2fs_read_end_io; bio_set_op_attrs(bio, REQ_OP_READ, op_flag); - if (f2fs_encrypted_file(inode)) + if (f2fs_encrypted_file(inode) && !fscrypt_disk_encrypted(inode)) post_read_steps |= 1 << STEP_DECRYPT; if (f2fs_need_verity(inode, first_idx)) @@ -731,6 +801,10 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page, } ClearPageError(page); inc_page_count(sbi, F2FS_RD_DATA); + + if (f2fs_may_encrypt_bio(inode, NULL)) + fscrypt_set_bio(inode, bio, PG_DUN(inode, page->index)); + __submit_bio(sbi, bio, DATA); return 0; } @@ -1665,6 +1739,8 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page, sector_t last_block_in_file; sector_t block_nr; int ret = 0; + bool bio_encrypted; + u64 dun; block_in_file = (sector_t)page_index(page); last_block = block_in_file + nr_pages; @@ -1734,6 +1810,15 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page, __submit_bio(F2FS_I_SB(inode), bio, DATA); bio = NULL; } + + dun = PG_DUN(inode, page->index); + bio_encrypted = f2fs_may_encrypt_bio(inode, NULL); + if (!f2fs_mergeable_bio(bio, dun, fscrypt_get_diskcipher(inode), + bio_encrypted)) { + __submit_bio(F2FS_I_SB(inode), bio, DATA); + bio = NULL; + } + if (bio == NULL) { bio = f2fs_grab_read_bio(inode, block_nr, nr_pages, is_readahead ? REQ_RAHEAD : 0, page->index); @@ -1742,6 +1827,8 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page, bio = NULL; goto out; } + if (f2fs_may_encrypt_bio(inode, NULL)) + fscrypt_set_bio(inode, bio, dun); } /* @@ -1870,6 +1957,9 @@ static int encrypt_one_page(struct f2fs_io_info *fio) f2fs_wait_on_block_writeback(inode, fio->old_blkaddr); retry_encrypt: + if (fscrypt_disk_encrypted(inode)) + return 0; + fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(fio->page, PAGE_SIZE, 0, gfp_flags); @@ -2804,6 +2894,10 @@ static void f2fs_dio_submit_bio(struct bio *bio, struct inode *inode, if (!dio) goto out; + if (dio->inode && fscrypt_has_encryption_key(dio->inode)) + fscrypt_set_bio(inode, bio, PG_DUN(inode, + file_offset >> PAGE_SHIFT)); + dio->inode = inode; dio->orig_end_io = bio->bi_end_io; dio->orig_private = bio->bi_private; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 0cbf1d4..8447542 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3706,7 +3706,7 @@ static inline bool f2fs_force_buffered_io(struct inode *inode, struct f2fs_sb_info *sbi = F2FS_I_SB(inode); int rw = iov_iter_rw(iter); - if (f2fs_post_read_required(inode)) + if (f2fs_post_read_required(inode) && !fscrypt_disk_encrypted(inode)) return true;