From patchwork Tue Jun 18 21:27:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 11002901 X-Patchwork-Delegate: snitzer@redhat.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 571AB76 for ; Tue, 18 Jun 2019 21:29:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4713328AD9 for ; Tue, 18 Jun 2019 21:29:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3B7F528B53; Tue, 18 Jun 2019 21:29:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 951C428B56 for ; Tue, 18 Jun 2019 21:29:11 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D115E356C4; Tue, 18 Jun 2019 21:28:43 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id ED426383F; Tue, 18 Jun 2019 21:28:35 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 866BA1806B19; Tue, 18 Jun 2019 21:28:28 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x5ILSP9H018878 for ; Tue, 18 Jun 2019 17:28:25 -0400 Received: by smtp.corp.redhat.com (Postfix) id C75CD19C69; Tue, 18 Jun 2019 21:28:25 +0000 (UTC) Delivered-To: dm-devel@redhat.com Received: from mx1.redhat.com (ext-mx01.extmail.prod.ext.phx2.redhat.com [10.5.110.25]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C161A19C5B for ; Tue, 18 Jun 2019 21:28:23 +0000 (UTC) Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B4FF281DFA for ; Tue, 18 Jun 2019 21:28:11 +0000 (UTC) Received: by mail-wm1-f68.google.com with SMTP id s15so4732191wmj.3 for ; Tue, 18 Jun 2019 14:28:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=t1z9+TDQfHPW/smtTmewGAgWAJLuzsbWWpgKygwvzhI=; b=od4ihnPXfC0cbv6Q6JphpdB71CghciGPrihK+4yU4BrAkXSUhGty0VQ2wLQEgm86U6 CyDurd6QJWXxbBES0t+UAEIJEg9XMGlODlu9vj2x7EU2r/AMEqSZEFViG80fBJIBPB/k ++v/uVQXEHoaGsWcmHN1JHzF4qmeMGu3PF1cFk3WsG0K26DHRFM9ddJcjDBL+CBKqyJa t4EIyL/fGaHGguQyzcqMLiCfa3BHdgrMOnGTgnRtPddgL/MGl9NtdQiDh4xjpyebsA35 viQ8tvmuSK7rHDl0f781lssw1KtWjFImXmd5noxFlauDqBzaHi9VWAHQIswXlnGBmdPy jGGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=t1z9+TDQfHPW/smtTmewGAgWAJLuzsbWWpgKygwvzhI=; b=F7sGUfmrTg3ng1BNRjKzgOscWxLPre9jZzTF/mbAHcKBUJW8jFX7BV6yUc6WvFkIa2 6aiStpYgjZJ58ayCvB+hl+IQ8SvfijwbH4+Glb6pPuo8IXKNe4YrIgzPVSrbPGDm+K5w MIocqqOeLKk7ZQw8kuunIK4kfQEDrSt7vZlN94EFctpDnfSMLgTjvkX8osL0L3Valhxn J2T/osXlMzRJbVYsWgoyuuOsXpteHLEMWC3frQeFR7FrqjJveNgvFZrfvusPDILZ5z8M bsN++rrmaqOkGiQkJlasacnQxxEzGWyxBCcbXxLGguRUWSirmSezPalgOcvCZusNavPQ D+jg== X-Gm-Message-State: APjAAAVCt7/wyBv++HuDF3Ptd7f9SgsCRsJ0YlrLRYX0XJZKk0/H8d/p CM9lHOhxEwImtoItRAynFMBQ8g== X-Google-Smtp-Source: APXvYqwO2NrP+BPLIoMEwq49uhANfaSU0kE09Ly2YfqKzrPSp5rp1ZujAVnjygP2dF542hoFv6PH9Q== X-Received: by 2002:a1c:480a:: with SMTP id v10mr5120117wma.120.1560893290234; Tue, 18 Jun 2019 14:28:10 -0700 (PDT) Received: from e111045-lin.arm.com (lfbn-nic-1-216-10.w2-15.abo.wanadoo.fr. [2.15.62.10]) by smtp.gmail.com with ESMTPSA id h21sm2273831wmb.47.2019.06.18.14.28.09 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 14:28:09 -0700 (PDT) From: Ard Biesheuvel To: linux-crypto@vger.kernel.org Date: Tue, 18 Jun 2019 23:27:49 +0200 Message-Id: <20190618212749.8995-5-ard.biesheuvel@linaro.org> In-Reply-To: <20190618212749.8995-1-ard.biesheuvel@linaro.org> References: <20190618212749.8995-1-ard.biesheuvel@linaro.org> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 18 Jun 2019 21:28:12 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 18 Jun 2019 21:28:12 +0000 (UTC) for IP:'209.85.128.68' DOMAIN:'mail-wm1-f68.google.com' HELO:'mail-wm1-f68.google.com' FROM:'ard.biesheuvel@linaro.org' RCPT:'' X-RedHat-Spam-Score: -0.11 (DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS) 209.85.128.68 mail-wm1-f68.google.com 209.85.128.68 mail-wm1-f68.google.com X-Scanned-By: MIMEDefang 2.83 on 10.5.110.25 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-loop: dm-devel@redhat.com Cc: Herbert Xu , Eric Biggers , Ard Biesheuvel , linux-fscrypt@vger.kernel.org, Gilad Ben-Yossef , dm-devel@redhat.com, Milan Broz Subject: [dm-devel] [PATCH v2 4/4] md: dm-crypt: switch to ESSIV crypto API template X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 18 Jun 2019 21:29:07 +0000 (UTC) X-Virus-Scanned: ClamAV using ClamSMTP Replace the explicit ESSIV handling in the dm-crypt driver with calls into the crypto API, which now possesses the capability to perform this processing within the crypto subsystem. Signed-off-by: Ard Biesheuvel --- drivers/md/Kconfig | 1 + drivers/md/dm-crypt.c | 208 +++----------------- 2 files changed, 31 insertions(+), 178 deletions(-) diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 45254b3ef715..30ca87cf25db 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -271,6 +271,7 @@ config DM_CRYPT depends on BLK_DEV_DM select CRYPTO select CRYPTO_CBC + select CRYPTO_ESSIV ---help--- This device-mapper target allows you to create a device that transparently encrypts the data on it. You'll need to activate diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index f001f1104cb5..89efd7d249fd 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -98,11 +98,6 @@ struct crypt_iv_operations { struct dm_crypt_request *dmreq); }; -struct iv_essiv_private { - struct crypto_shash *hash_tfm; - u8 *salt; -}; - struct iv_benbi_private { int shift; }; @@ -155,7 +150,6 @@ struct crypt_config { const struct crypt_iv_operations *iv_gen_ops; union { - struct iv_essiv_private essiv; struct iv_benbi_private benbi; struct iv_lmk_private lmk; struct iv_tcw_private tcw; @@ -165,8 +159,6 @@ struct crypt_config { unsigned short int sector_size; unsigned char sector_shift; - /* ESSIV: struct crypto_cipher *essiv_tfm */ - void *iv_private; union { struct crypto_skcipher **tfms; struct crypto_aead **tfms_aead; @@ -323,161 +315,6 @@ static int crypt_iv_plain64be_gen(struct crypt_config *cc, u8 *iv, return 0; } -/* Initialise ESSIV - compute salt but no local memory allocations */ -static int crypt_iv_essiv_init(struct crypt_config *cc) -{ - struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; - SHASH_DESC_ON_STACK(desc, essiv->hash_tfm); - struct crypto_cipher *essiv_tfm; - int err; - - desc->tfm = essiv->hash_tfm; - - err = crypto_shash_digest(desc, cc->key, cc->key_size, essiv->salt); - shash_desc_zero(desc); - if (err) - return err; - - essiv_tfm = cc->iv_private; - - err = crypto_cipher_setkey(essiv_tfm, essiv->salt, - crypto_shash_digestsize(essiv->hash_tfm)); - if (err) - return err; - - return 0; -} - -/* Wipe salt and reset key derived from volume key */ -static int crypt_iv_essiv_wipe(struct crypt_config *cc) -{ - struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; - unsigned salt_size = crypto_shash_digestsize(essiv->hash_tfm); - struct crypto_cipher *essiv_tfm; - int r, err = 0; - - memset(essiv->salt, 0, salt_size); - - essiv_tfm = cc->iv_private; - r = crypto_cipher_setkey(essiv_tfm, essiv->salt, salt_size); - if (r) - err = r; - - return err; -} - -/* Allocate the cipher for ESSIV */ -static struct crypto_cipher *alloc_essiv_cipher(struct crypt_config *cc, - struct dm_target *ti, - const u8 *salt, - unsigned int saltsize) -{ - struct crypto_cipher *essiv_tfm; - int err; - - /* Setup the essiv_tfm with the given salt */ - essiv_tfm = crypto_alloc_cipher(cc->cipher, 0, 0); - if (IS_ERR(essiv_tfm)) { - ti->error = "Error allocating crypto tfm for ESSIV"; - return essiv_tfm; - } - - if (crypto_cipher_blocksize(essiv_tfm) != cc->iv_size) { - ti->error = "Block size of ESSIV cipher does " - "not match IV size of block cipher"; - crypto_free_cipher(essiv_tfm); - return ERR_PTR(-EINVAL); - } - - err = crypto_cipher_setkey(essiv_tfm, salt, saltsize); - if (err) { - ti->error = "Failed to set key for ESSIV cipher"; - crypto_free_cipher(essiv_tfm); - return ERR_PTR(err); - } - - return essiv_tfm; -} - -static void crypt_iv_essiv_dtr(struct crypt_config *cc) -{ - struct crypto_cipher *essiv_tfm; - struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; - - crypto_free_shash(essiv->hash_tfm); - essiv->hash_tfm = NULL; - - kzfree(essiv->salt); - essiv->salt = NULL; - - essiv_tfm = cc->iv_private; - - if (essiv_tfm) - crypto_free_cipher(essiv_tfm); - - cc->iv_private = NULL; -} - -static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, - const char *opts) -{ - struct crypto_cipher *essiv_tfm = NULL; - struct crypto_shash *hash_tfm = NULL; - u8 *salt = NULL; - int err; - - if (!opts) { - ti->error = "Digest algorithm missing for ESSIV mode"; - return -EINVAL; - } - - /* Allocate hash algorithm */ - hash_tfm = crypto_alloc_shash(opts, 0, 0); - if (IS_ERR(hash_tfm)) { - ti->error = "Error initializing ESSIV hash"; - err = PTR_ERR(hash_tfm); - goto bad; - } - - salt = kzalloc(crypto_shash_digestsize(hash_tfm), GFP_KERNEL); - if (!salt) { - ti->error = "Error kmallocing salt storage in ESSIV"; - err = -ENOMEM; - goto bad; - } - - cc->iv_gen_private.essiv.salt = salt; - cc->iv_gen_private.essiv.hash_tfm = hash_tfm; - - essiv_tfm = alloc_essiv_cipher(cc, ti, salt, - crypto_shash_digestsize(hash_tfm)); - if (IS_ERR(essiv_tfm)) { - crypt_iv_essiv_dtr(cc); - return PTR_ERR(essiv_tfm); - } - cc->iv_private = essiv_tfm; - - return 0; - -bad: - if (hash_tfm && !IS_ERR(hash_tfm)) - crypto_free_shash(hash_tfm); - kfree(salt); - return err; -} - -static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, - struct dm_crypt_request *dmreq) -{ - struct crypto_cipher *essiv_tfm = cc->iv_private; - - memset(iv, 0, cc->iv_size); - *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector); - crypto_cipher_encrypt_one(essiv_tfm, iv, iv); - - return 0; -} - static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, const char *opts) { @@ -853,14 +690,6 @@ static const struct crypt_iv_operations crypt_iv_plain64be_ops = { .generator = crypt_iv_plain64be_gen }; -static const struct crypt_iv_operations crypt_iv_essiv_ops = { - .ctr = crypt_iv_essiv_ctr, - .dtr = crypt_iv_essiv_dtr, - .init = crypt_iv_essiv_init, - .wipe = crypt_iv_essiv_wipe, - .generator = crypt_iv_essiv_gen -}; - static const struct crypt_iv_operations crypt_iv_benbi_ops = { .ctr = crypt_iv_benbi_ctr, .dtr = crypt_iv_benbi_dtr, @@ -2283,7 +2112,7 @@ static int crypt_ctr_ivmode(struct dm_target *ti, const char *ivmode) else if (strcmp(ivmode, "plain64be") == 0) cc->iv_gen_ops = &crypt_iv_plain64be_ops; else if (strcmp(ivmode, "essiv") == 0) - cc->iv_gen_ops = &crypt_iv_essiv_ops; + cc->iv_gen_ops = &crypt_iv_plain64_ops; else if (strcmp(ivmode, "benbi") == 0) cc->iv_gen_ops = &crypt_iv_benbi_ops; else if (strcmp(ivmode, "null") == 0) @@ -2397,7 +2226,7 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key char **ivmode, char **ivopts) { struct crypt_config *cc = ti->private; - char *tmp, *cipher_api; + char *tmp, *cipher_api, buf[CRYPTO_MAX_ALG_NAME]; int ret = -EINVAL; cc->tfms_count = 1; @@ -2435,9 +2264,19 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key } ret = crypt_ctr_blkdev_cipher(cc, cipher_api); - if (ret < 0) { - ti->error = "Cannot allocate cipher string"; - return -ENOMEM; + if (ret < 0) + goto bad_mem; + + if (*ivmode && !strcmp(*ivmode, "essiv")) { + if (!*ivopts) { + ti->error = "Digest algorithm missing for ESSIV mode"; + return -EINVAL; + } + ret = snprintf(buf, CRYPTO_MAX_ALG_NAME, "essiv(%s,%s,%s)", + cipher_api, cc->cipher, *ivopts); + if (ret < 0) + goto bad_mem; + cipher_api = buf; } cc->key_parts = cc->tfms_count; @@ -2456,6 +2295,9 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key cc->iv_size = crypto_skcipher_ivsize(any_tfm(cc)); return 0; +bad_mem: + ti->error = "Cannot allocate cipher string"; + return -ENOMEM; } static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key, @@ -2515,8 +2357,18 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key if (!cipher_api) goto bad_mem; - ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME, - "%s(%s)", chainmode, cipher); + if (!strcmp(*ivmode, "essiv")) { + if (!*ivopts) { + ti->error = "Digest algorithm missing for ESSIV mode"; + return -EINVAL; + } + ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME, + "essiv(%s(%s),%s,%s)", chainmode, cipher, + cipher, *ivopts); + } else { + ret = snprintf(cipher_api, CRYPTO_MAX_ALG_NAME, + "%s(%s)", chainmode, cipher); + } if (ret < 0) { kfree(cipher_api); goto bad_mem;