From patchwork Fri Jun 14 08:34:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 10994691 X-Patchwork-Delegate: herbert@gondor.apana.org.au 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 930F51395 for ; Fri, 14 Jun 2019 08:34:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8633F26E55 for ; Fri, 14 Jun 2019 08:34:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7AB1B27F91; Fri, 14 Jun 2019 08:34:20 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B8A1626E55 for ; Fri, 14 Jun 2019 08:34:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726551AbfFNIeS (ORCPT ); Fri, 14 Jun 2019 04:34:18 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:34150 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726435AbfFNIeS (ORCPT ); Fri, 14 Jun 2019 04:34:18 -0400 Received: by mail-wr1-f67.google.com with SMTP id k11so1591531wrl.1 for ; Fri, 14 Jun 2019 01:34:15 -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 :mime-version:content-transfer-encoding; bh=2JnPzFNbdRwXDsysadhK09T0Ip1d7jTBj++NzJyAjtI=; b=bjQHrky/kpPTO4CIpuqkcodMkaIxzuuiRQ3KeSAZydNXshbsxs8lo3GslLVB1iA5J2 d0QA3yG1LBTb4jWx84Ne8Y05InG/O77c7M6I8JjIcVNHFcl8d7lbTggGpXEIRWrOZ3ke i7ilJeJNFQLl9vcTNJn8x/ERRJJzPmOfaH966bB3x6MyVyd/frOkYxrErOYzHxxALy7h sirh1Ejq2kOemBUD7MoOhuvgTzBVwaCXxAdlRsvFt1eobF0tfy8ZSuUY6DyDdPhl1cm0 gV6wzxYMIIDaPHXnCDivLUvc6neUrCxdqAHJHAVudUmLFOkoB3WxO/jb8OaJYs3XmNwZ W5sQ== 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:mime-version:content-transfer-encoding; bh=2JnPzFNbdRwXDsysadhK09T0Ip1d7jTBj++NzJyAjtI=; b=OmhLrwV8DKNg32A09ad2zl+4V3JvMeHjqtm6hgPnsz+2UYSs4bo9dz6bCaEbVaXwFA jZzKNPHcHNangFI/pIjcOa3S3dEtMCpHsh9Zcb7Qw3k2r7qyMHTsaq+X93ibhjDr0JpG CEnYpKaS7pVUazFd5fujEv9SUzOM5qHFGcJuRQ+ji0yAE/Nenblju8a3sherSsbAsZV2 Bw6zsAfZUBYBL15Q+6wbOdUsoWFlcgzyW2thSBqXwlbSvwCIcDwDKZ5WnZICX9timhcu Fscy4D/peX1vt8uoMZmGn4/TeuG2K0qtj0EQFV61+2AIm0ZFqnA4W9JhiSiL5gXcay4Q weYg== X-Gm-Message-State: APjAAAVRDbqJb0zsvzadsizq0HP5ASTBOfIvnBllDnARGRYzpthJlZgX FfwDT9icgLNuMEDRip9E9kDg2vZ6X1MCVQ== X-Google-Smtp-Source: APXvYqyTxcj/eMvzafhvuxQpeFKgJq/tQx3nsN1Ry85sW/xCCus5C+wro5OSpjN3aZJk0diL354CiA== X-Received: by 2002:a5d:55cb:: with SMTP id i11mr1885723wrw.62.1560501254614; Fri, 14 Jun 2019 01:34:14 -0700 (PDT) Received: from sudo.home ([2a01:cb1d:112:6f00:8d0e:a5b1:c005:e3b5]) by smtp.gmail.com with ESMTPSA id f3sm1710802wre.93.2019.06.14.01.34.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jun 2019 01:34:13 -0700 (PDT) From: Ard Biesheuvel To: linux-crypto@vger.kernel.org Cc: Ard Biesheuvel , Herbert Xu , Eric Biggers Subject: [RFC PATCH 1/3] crypto: essiv - create a new shash template for IV generation Date: Fri, 14 Jun 2019 10:34:02 +0200 Message-Id: <20190614083404.20514-2-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190614083404.20514-1-ard.biesheuvel@linaro.org> References: <20190614083404.20514-1-ard.biesheuvel@linaro.org> MIME-Version: 1.0 Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Two different users of ESSIV (encrypted salt|sector IV) implement the algorithm using bare shash and cipher transform. This is not a huge deal, since the algorithm is fairly simple, but it does require us to keep the cipher interface public. Since the cipher interface is often used incorrectly, and typically is not the correct primitive to use outside of the crypto API, the intention is to turn it into an internal primitive, only to be used by other crypto code. In anticipation of that, this driver moves the essiv handling into the crypto subsystem, where it can keep using the cipher interface. This will also permit accelerated implementations to be provided, that implement all the transformations directly rather than wiring together other transforms. Signed-off-by: Ard Biesheuvel --- crypto/Kconfig | 3 + crypto/Makefile | 1 + crypto/essiv.c | 275 ++++++++++++++++++++ 3 files changed, 279 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index efeb307c0594..2e040514fa44 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1882,6 +1882,9 @@ config CRYPTO_STATS config CRYPTO_HASH_INFO bool +config CRYPTO_ESSIV + tristate + source "drivers/crypto/Kconfig" source "crypto/asymmetric_keys/Kconfig" source "certs/Kconfig" diff --git a/crypto/Makefile b/crypto/Makefile index 266a4cdbb9e2..ad1d99ba6d56 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -148,6 +148,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_ESSIV) += essiv.o ecdh_generic-y += ecdh.o ecdh_generic-y += ecdh_helper.o diff --git a/crypto/essiv.c b/crypto/essiv.c new file mode 100644 index 000000000000..b985de394aa6 --- /dev/null +++ b/crypto/essiv.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Cryptographic API. + * + * ESSIV: encrypted sector/salt initial vector (for block encryption) + * + * Copyright (c) 2019 Ard Biesheuvel + */ + +#include +#include +#include +#include +#include + +#include + +struct essiv_instance_ctx { + struct crypto_shash_spawn hash; + struct crypto_spawn enc; +}; + +struct essiv_tfm_ctx { + struct crypto_shash *hash; + struct crypto_cipher *enc; +}; + +struct essiv_desc_ctx { + unsigned int len; + unsigned int max; + u8 buf[]; +}; + +static int essiv_setkey(struct crypto_shash *tfm, const u8 *inkey, + unsigned int keylen) +{ + struct essiv_tfm_ctx *ctx = crypto_shash_ctx(tfm); + SHASH_DESC_ON_STACK(desc, ctx->hash); + u8 *digest = NULL; + int ret; + + if (keylen) { + digest = kmalloc(crypto_shash_digestsize(ctx->hash), + GFP_KERNEL); + if (!digest) + return -ENOMEM; + + desc->tfm = ctx->hash; + crypto_shash_digest(desc, inkey, keylen, digest); + } + ret = crypto_cipher_setkey(ctx->enc, + digest ?: page_address(ZERO_PAGE(0)), + crypto_shash_digestsize(ctx->hash)); + + kzfree(digest); + return ret; +} + +static int essiv_init(struct shash_desc *desc) +{ + struct essiv_desc_ctx *ctx = shash_desc_ctx(desc); + + ctx->len = 0; + ctx->max = crypto_shash_digestsize(desc->tfm); + memset(ctx->buf, 0, ctx->max); + + return 0; +} + +static int essiv_update(struct shash_desc *desc, const u8 *p, unsigned int len) +{ + struct essiv_desc_ctx *ctx = shash_desc_ctx(desc); + int nbytes = min(len, ctx->max - ctx->len); + + /* only permit input up to the block size of the cipher */ + if (nbytes < len) + return -EINVAL; + + memcpy(ctx->buf + ctx->len, p, nbytes); + ctx->len += nbytes; + + return 0; +} + +static int essiv_final(struct shash_desc *desc, u8 *out) +{ + struct essiv_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); + struct essiv_desc_ctx *ctx = shash_desc_ctx(desc); + + crypto_cipher_encrypt_one(tctx->enc, out, ctx->buf); + + return 0; +} + +static int essiv_digest(struct shash_desc *desc, const u8 *p, unsigned int len, + u8 *out) +{ + struct essiv_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); + struct essiv_desc_ctx *ctx = shash_desc_ctx(desc); + + if (len > ctx->max) + return -EINVAL; + + memcpy(ctx->buf, p, len); + crypto_cipher_encrypt_one(tctx->enc, out, ctx->buf); + + return 0; +} + +static int essiv_init_tfm(struct crypto_tfm *tfm) +{ + struct crypto_instance *inst = (void *)tfm->__crt_alg; + struct essiv_instance_ctx *ictx = crypto_instance_ctx(inst); + struct essiv_tfm_ctx *tctx = crypto_tfm_ctx(tfm); + + tctx->hash = crypto_spawn_shash(&ictx->hash); + if (IS_ERR(tctx->hash)) + return PTR_ERR(tctx->hash); + + tctx->enc = crypto_spawn_cipher(&ictx->enc); + if (IS_ERR(tctx->enc)) { + crypto_free_shash(tctx->hash); + return PTR_ERR(tctx->hash); + } + return 0; +}; + +static void essiv_exit_tfm(struct crypto_tfm *tfm) +{ + struct essiv_tfm_ctx *tctx = crypto_tfm_ctx(tfm); + + crypto_free_cipher(tctx->enc); + crypto_free_shash(tctx->hash); +} + +static void crypto_essiv_free(struct crypto_instance *inst) +{ + struct essiv_instance_ctx *ictx = crypto_instance_ctx(inst); + + crypto_drop_shash(&ictx->hash); + crypto_drop_spawn(&ictx->enc); + kfree(inst); +} + +static int crypto_essiv_create(struct crypto_template *tmpl, + struct rtattr **tb) +{ + struct shash_instance *inst; + struct essiv_instance_ctx *ictx; + struct crypto_alg *hash_alg, *enc_alg; + struct cipher_alg *calg; + struct shash_alg *salg; + int err; + + err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH); + if (err) + return err; + + salg = shash_attr_alg(tb[1], 0, 0); + if (IS_ERR(salg)) + return PTR_ERR(salg); + hash_alg = &salg->base; + + /* The underlying hash algorithm must be unkeyed */ + err = -EINVAL; + if (crypto_shash_alg_has_setkey(salg)) { + pr_err("essiv: keyed hash algorithm '%s' not supported\n", + hash_alg->cra_driver_name); + goto out_put_hash_alg; + } + + enc_alg = crypto_attr_alg(tb[2], CRYPTO_ALG_TYPE_CIPHER, + CRYPTO_ALG_TYPE_MASK); + if (IS_ERR(enc_alg)) { + err = PTR_ERR(enc_alg); + goto out_put_hash_alg; + } + calg = &enc_alg->cra_cipher; + + if (salg->digestsize < calg->cia_min_keysize || + salg->digestsize > calg->cia_max_keysize) { + pr_err("essiv: digest size of '%s' unsupported as key size for '%s'\n", + hash_alg->cra_driver_name, enc_alg->cra_driver_name); + goto out_put_algs; + } + + inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL); + if (!inst) { + err = -ENOMEM; + goto out_put_algs; + } + ictx = shash_instance_ctx(inst); + + err = crypto_init_shash_spawn(&ictx->hash, salg, + shash_crypto_instance(inst)); + if (err) + goto out_free_inst; + + err = crypto_init_spawn(&ictx->enc, enc_alg, + shash_crypto_instance(inst), + CRYPTO_ALG_TYPE_MASK); + if (err) + goto out_drop_hash; + + err = -ENAMETOOLONG; + if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, + "essiv(%s,%s)", enc_alg->cra_name, + hash_alg->cra_name) >= CRYPTO_MAX_ALG_NAME) + goto out_drop_spawns; + if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, + "essiv(%s,%s)", enc_alg->cra_driver_name, + hash_alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) + goto out_drop_spawns; + + inst->alg.base.cra_priority = (hash_alg->cra_priority + + enc_alg->cra_priority) / 2; + inst->alg.base.cra_blocksize = enc_alg->cra_blocksize; + inst->alg.base.cra_ctxsize = sizeof(struct essiv_tfm_ctx); + + inst->alg.digestsize = enc_alg->cra_blocksize; + inst->alg.descsize = sizeof(struct essiv_desc_ctx) + + enc_alg->cra_blocksize; + inst->alg.setkey = essiv_setkey; + inst->alg.init = essiv_init; + inst->alg.update = essiv_update; + inst->alg.final = essiv_final; + inst->alg.digest = essiv_digest; + + inst->alg.base.cra_init = essiv_init_tfm; + inst->alg.base.cra_exit = essiv_exit_tfm; + + err = shash_register_instance(tmpl, inst); + if (err) + goto out_drop_spawns; + + crypto_mod_put(enc_alg); + crypto_mod_put(hash_alg); + return 0; + +out_drop_spawns: + crypto_drop_spawn(&ictx->enc); +out_drop_hash: + crypto_drop_shash(&ictx->hash); +out_free_inst: + kfree(inst); +out_put_algs: + crypto_mod_put(enc_alg); +out_put_hash_alg: + crypto_mod_put(hash_alg); + return err; +} + +static struct crypto_template crypto_essiv_tmpl = { + .name = "essiv", + .create = crypto_essiv_create, + .free = crypto_essiv_free, + .module = THIS_MODULE, +}; + +static int __init crypto_essiv_module_init(void) +{ + return crypto_register_template(&crypto_essiv_tmpl); +} + +static void __exit crypto_essiv_module_exit(void) +{ + crypto_unregister_template(&crypto_essiv_tmpl); +} + +subsys_initcall(crypto_essiv_module_init); +module_exit(crypto_essiv_module_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("shash template to generate ESSIV tags"); +MODULE_ALIAS_CRYPTO("essiv"); From patchwork Fri Jun 14 08:34:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 10994693 X-Patchwork-Delegate: herbert@gondor.apana.org.au 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 122AE14E5 for ; Fri, 14 Jun 2019 08:34:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 00F1327F81 for ; Fri, 14 Jun 2019 08:34:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E973727F92; Fri, 14 Jun 2019 08:34:20 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CF18127F81 for ; Fri, 14 Jun 2019 08:34:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726435AbfFNIeT (ORCPT ); Fri, 14 Jun 2019 04:34:19 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:37865 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726429AbfFNIeS (ORCPT ); Fri, 14 Jun 2019 04:34:18 -0400 Received: by mail-wr1-f65.google.com with SMTP id v14so1577473wrr.4 for ; Fri, 14 Jun 2019 01:34:16 -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 :mime-version:content-transfer-encoding; bh=jVi9QO7CHKBZdi2+fLpwMFoN+KF7AYiGK0YKfY/qKiM=; b=KajoO1egiIOR9nWNNH2fm5ullJAmhXmPemSugKLGhmub7m/OwqcoMcL00HrUCcNZQG GM76T7SP/PWooKtj0lMylEDTFWqv/WN1NeXmM1WDE1AFfWhHQlcKWdQ/xCtN7IRutTfi SNOmNMyQOk9qiCEv7Q04HwpnEaBs6wVXyWtLMVr2YGTjiKyH8ig/woEtfh1ksCm9UTUI 7A0FUosbcrXBcUU3Rs6gzOObrgGlv4z99bF5HdfTfF615zgI5/scnZ1nxpV/n7E7+dux e7QZvigJp3QXnvb3ydPJAbkpnpR5vV0E/MNNBuODlQ5qHPpvpadhOYLpshHn9PyX4n9Z +v8w== 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:mime-version:content-transfer-encoding; bh=jVi9QO7CHKBZdi2+fLpwMFoN+KF7AYiGK0YKfY/qKiM=; b=h57yd2iuCYqJ+J/J5owU9D1i0zgsWRMl12yw8eXMNCoooPHFcKS3xA4cf/mHio/CQC CNusKf2rOyPPo3i54+KHReHzGBonQegCC8DGO5pg+BU+rwB83ysXUOWE7hnh8DtGNRwV sUoVNKbG5Hpc8pZKZQVAou1+yjpTJaGXXOUn29+3Lk4M5l2aqmZ4TY7r0gqRdPJHBIhW WQcYQ3aqYvCPdCq2eVXrPhk6N3ZpVsJom1MBfR4cNhiPDhz/Pw3sIrE0Lzhc1TlA71WQ 9gSdUTBYu7dAHil6V7WYV1kO0fs2iekEDO9q2CFwEjqfmS39tYBv61AcJy0WI0mDJse4 WHpw== X-Gm-Message-State: APjAAAUNaq0G42QyBIFKtQjItrOQ/dLotGpC5JPKfydMlbjoYFCdHElu o8CQCZnJztYHNeyQ4bZVhIVPfj34abX1oQ== X-Google-Smtp-Source: APXvYqx9YTHS84gIPgmRDm73UK26a4NsmO0BPvni9R5bFdBUI1GN/Eqp45TdzoWwLNTOb2ytUW9GGA== X-Received: by 2002:adf:8367:: with SMTP id 94mr13146436wrd.179.1560501255767; Fri, 14 Jun 2019 01:34:15 -0700 (PDT) Received: from sudo.home ([2a01:cb1d:112:6f00:8d0e:a5b1:c005:e3b5]) by smtp.gmail.com with ESMTPSA id f3sm1710802wre.93.2019.06.14.01.34.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jun 2019 01:34:15 -0700 (PDT) From: Ard Biesheuvel To: linux-crypto@vger.kernel.org Cc: Ard Biesheuvel , Herbert Xu , Eric Biggers Subject: [RFC PATCH 2/3] dm crypt: switch to essiv shash Date: Fri, 14 Jun 2019 10:34:03 +0200 Message-Id: <20190614083404.20514-3-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190614083404.20514-1-ard.biesheuvel@linaro.org> References: <20190614083404.20514-1-ard.biesheuvel@linaro.org> MIME-Version: 1.0 Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Replace the open coded ESSIV handling with invocations into the new ESSIV shash, created specifically for this purpose. Using this more abstract interface allows the crypto subsystem to refactor the way ciphers are used, and to provide better testing coverage. Signed-off-by: Ard Biesheuvel --- drivers/md/Kconfig | 1 + drivers/md/dm-crypt.c | 137 ++++---------------- 2 files changed, 24 insertions(+), 114 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 1b16d34bb785..b66ef3de835a 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,7 +159,7 @@ struct crypt_config { unsigned short int sector_size; unsigned char sector_shift; - /* ESSIV: struct crypto_cipher *essiv_tfm */ + /* ESSIV: struct crypto_shash *essiv_tfm */ void *iv_private; union { struct crypto_skcipher **tfms; @@ -326,94 +320,27 @@ static int crypt_iv_plain64be_gen(struct crypt_config *cc, u8 *iv, /* 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; + struct crypto_shash *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; + return crypto_shash_setkey(essiv_tfm, cc->key, cc->key_size); } /* 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); + struct crypto_shash *essiv_tfm; 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; + return crypto_shash_setkey(essiv_tfm, NULL, 0); } 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; + struct crypto_shash *essiv_tfm; essiv_tfm = cc->iv_private; - if (essiv_tfm) - crypto_free_cipher(essiv_tfm); + crypto_free_shash(essiv_tfm); cc->iv_private = NULL; } @@ -421,9 +348,8 @@ static void crypt_iv_essiv_dtr(struct crypt_config *cc) 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; + struct crypto_shash *essiv_tfm = NULL; + u8 name[CRYPTO_MAX_ALG_NAME]; int err; if (!opts) { @@ -431,51 +357,34 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, 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; + snprintf(name, CRYPTO_MAX_ALG_NAME, "essiv(%s,%s)", cc->cipher, opts); - essiv_tfm = alloc_essiv_cipher(cc, ti, salt, - crypto_shash_digestsize(hash_tfm)); - if (IS_ERR(essiv_tfm)) { - crypt_iv_essiv_dtr(cc); + essiv_tfm = crypto_alloc_shash(name, 0, 0); + if (IS_ERR(essiv_tfm)) return PTR_ERR(essiv_tfm); + + err = crypto_shash_setkey(essiv_tfm, cc->key, cc->key_size); + if (err) { + ti->error = "Failed to set key for ESSIV cipher"; + crypto_free_shash(essiv_tfm); + return err; } + 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; + struct crypto_shash *essiv_tfm = cc->iv_private; + SHASH_DESC_ON_STACK(desc, essiv_tfm); memset(iv, 0, cc->iv_size); *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector); - crypto_cipher_encrypt_one(essiv_tfm, iv, iv); - - return 0; + desc->tfm = essiv_tfm; + return crypto_shash_digest(desc, iv, sizeof(__le64), iv); } static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, From patchwork Fri Jun 14 08:34:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 10994695 X-Patchwork-Delegate: herbert@gondor.apana.org.au 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 43BC518A6 for ; Fri, 14 Jun 2019 08:34:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2232D237F1 for ; Fri, 14 Jun 2019 08:34:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0EA3D27F8E; Fri, 14 Jun 2019 08:34:21 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 576DB27F8E for ; Fri, 14 Jun 2019 08:34:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726429AbfFNIeT (ORCPT ); Fri, 14 Jun 2019 04:34:19 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:34154 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726530AbfFNIeT (ORCPT ); Fri, 14 Jun 2019 04:34:19 -0400 Received: by mail-wr1-f68.google.com with SMTP id k11so1591624wrl.1 for ; Fri, 14 Jun 2019 01:34:17 -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 :mime-version:content-transfer-encoding; bh=dQGze1de3iuv2PgR54rqY+1G9v4+tWZHityhL+j8Two=; b=RMnBvrrGKo2YiaFFi80CITYkCrIZGN2v6ztzF87/44+XA+mL7doQXJq9Fu11FRAMVM ZA45RbDgsGNGTFrSDk98a50fNrx1yHF2/EWqBz9/P+gSLgSv54smG3QZpYcbfQkMBIqo JPxN8S0rSQagFHF762GaIhcxdATr8K+lQ+gMuq1nyRswAwD/bHaGzOAvJ3z98L9svLA8 EdNb8m5haWCGn7yWu/445PBY7KcovQzEiobkd1mmuKmOj+E/IO8SF9mYE/mcSBJAV3DT 6F1FG+GXS+UDQTKBFm43F1o+NWPzQFF34AS7YqShteWjBAFejXR9CvTWZqbWtC5ChAZD UXaA== 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:mime-version:content-transfer-encoding; bh=dQGze1de3iuv2PgR54rqY+1G9v4+tWZHityhL+j8Two=; b=BfrQirFOS/CYnRcHB6lmutD9fMNikOhHCcADxwbFOX26Hlj4EGvvEwdzEJ6yrR8vOs 3ytR648H2Il/KtGfOh9ylNf6Vxw5b+QPt9lAbhq5by1MC7hOMZa2iOq4CgczKS0xDynw 4DN4CtzPFhU91PPSW23p1yyOT7qwpQwTiaps6RWWYmm7GDn6aGsEnMvBS8YnoRXXpGhy PTAStapYa58gch/yLykANhoPDGiVrcx+3x/UJRplhnznPDUQ6ogQK2jbY3yXZnOjYx15 HhK4iEp4vhamyt4a8JDK75/wenMAIOKIbfCdlc9U7YKI136e9SenkqCkZ2A3gF9mKIdT WN/Q== X-Gm-Message-State: APjAAAW/t+Kmt+CedR9+271hyt+djRwq+sxTkqcTuSlLOTJXD6mY9h8v NY40gJFiUGHu3PRMmx3TgRQvcB1b46H3dQ== X-Google-Smtp-Source: APXvYqz4+WLmDL683bb+Hi0IhjLYQTrFwTMl2MxTXKJE4R+vpJkUW2HCIi7mk9Dm0i5uwgqXB2+Log== X-Received: by 2002:adf:f84a:: with SMTP id d10mr4185071wrq.319.1560501256818; Fri, 14 Jun 2019 01:34:16 -0700 (PDT) Received: from sudo.home ([2a01:cb1d:112:6f00:8d0e:a5b1:c005:e3b5]) by smtp.gmail.com with ESMTPSA id f3sm1710802wre.93.2019.06.14.01.34.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Jun 2019 01:34:16 -0700 (PDT) From: Ard Biesheuvel To: linux-crypto@vger.kernel.org Cc: Ard Biesheuvel , Herbert Xu , Eric Biggers Subject: [RFC PATCH 3/3] fscrypt: switch to ESSIV shash Date: Fri, 14 Jun 2019 10:34:04 +0200 Message-Id: <20190614083404.20514-4-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190614083404.20514-1-ard.biesheuvel@linaro.org> References: <20190614083404.20514-1-ard.biesheuvel@linaro.org> MIME-Version: 1.0 Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Instead of open coding the shash and cipher operations that make up the ESSIV transform, switch to the new ESSIV shash template that encapsulates all of this. Using this more abstract interface provides more flexibility for the crypto subsystem to do refactoring, and permits better testing. Signed-off-by: Ard Biesheuvel --- fs/crypto/Kconfig | 1 + fs/crypto/crypto.c | 11 ++-- fs/crypto/fscrypt_private.h | 4 +- fs/crypto/keyinfo.c | 64 +++----------------- 4 files changed, 18 insertions(+), 62 deletions(-) diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index 24ed99e2eca0..b0292da8613c 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig @@ -5,6 +5,7 @@ config FS_ENCRYPTION select CRYPTO_AES select CRYPTO_CBC select CRYPTO_ECB + select CRYPTO_ESSIV select CRYPTO_XTS select CRYPTO_CTS select CRYPTO_SHA256 diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 335a362ee446..93d33b55c2fa 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -137,8 +137,13 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, if (ci->ci_flags & FS_POLICY_FLAG_DIRECT_KEY) memcpy(iv->nonce, ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE); - if (ci->ci_essiv_tfm != NULL) - crypto_cipher_encrypt_one(ci->ci_essiv_tfm, iv->raw, iv->raw); + if (ci->ci_essiv_tfm != NULL) { + SHASH_DESC_ON_STACK(desc, ci->ci_essiv_tfm); + + desc->tfm = ci->ci_essiv_tfm; + crypto_shash_digest(desc, (u8 *)&iv->lblk_num, + sizeof(iv->lblk_num), iv->raw); + } } int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, @@ -492,8 +497,6 @@ static void __exit fscrypt_exit(void) destroy_workqueue(fscrypt_read_workqueue); kmem_cache_destroy(fscrypt_ctx_cachep); kmem_cache_destroy(fscrypt_info_cachep); - - fscrypt_essiv_cleanup(); } module_exit(fscrypt_exit); diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 7da276159593..67ea4ca11474 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -62,10 +62,10 @@ struct fscrypt_info { struct crypto_skcipher *ci_ctfm; /* - * Cipher for ESSIV IV generation. Only set for CBC contents + * Shash for ESSIV IV generation. Only set for CBC contents * encryption, otherwise is NULL. */ - struct crypto_cipher *ci_essiv_tfm; + struct crypto_shash *ci_essiv_tfm; /* * Encryption mode used for this inode. It corresponds to either diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index dcd91a3fbe49..c3d38f72506c 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -15,12 +15,10 @@ #include #include #include +#include #include -#include #include "fscrypt_private.h" -static struct crypto_shash *essiv_hash_tfm; - /* Table of keys referenced by FS_POLICY_FLAG_DIRECT_KEY policies */ static DEFINE_HASHTABLE(fscrypt_master_keys, 6); /* 6 bits = 64 buckets */ static DEFINE_SPINLOCK(fscrypt_master_keys_lock); @@ -377,70 +375,24 @@ fscrypt_get_master_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode, return ERR_PTR(err); } -static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) -{ - struct crypto_shash *tfm = READ_ONCE(essiv_hash_tfm); - - /* init hash transform on demand */ - if (unlikely(!tfm)) { - struct crypto_shash *prev_tfm; - - tfm = crypto_alloc_shash("sha256", 0, 0); - if (IS_ERR(tfm)) { - fscrypt_warn(NULL, - "error allocating SHA-256 transform: %ld", - PTR_ERR(tfm)); - return PTR_ERR(tfm); - } - prev_tfm = cmpxchg(&essiv_hash_tfm, NULL, tfm); - if (prev_tfm) { - crypto_free_shash(tfm); - tfm = prev_tfm; - } - } - - { - SHASH_DESC_ON_STACK(desc, tfm); - desc->tfm = tfm; - - return crypto_shash_digest(desc, key, keysize, salt); - } -} - static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key, int keysize) { int err; - struct crypto_cipher *essiv_tfm; - u8 salt[SHA256_DIGEST_SIZE]; - - essiv_tfm = crypto_alloc_cipher("aes", 0, 0); - if (IS_ERR(essiv_tfm)) - return PTR_ERR(essiv_tfm); - - ci->ci_essiv_tfm = essiv_tfm; - - err = derive_essiv_salt(raw_key, keysize, salt); - if (err) - goto out; + struct crypto_shash *essiv_tfm; /* * Using SHA256 to derive the salt/key will result in AES-256 being * used for IV generation. File contents encryption will still use the * configured keysize (AES-128) nevertheless. */ - err = crypto_cipher_setkey(essiv_tfm, salt, sizeof(salt)); - if (err) - goto out; + essiv_tfm = crypto_alloc_shash("essiv(aes,sha256)", 0, 0); + if (IS_ERR(essiv_tfm)) + return PTR_ERR(essiv_tfm); -out: - memzero_explicit(salt, sizeof(salt)); - return err; -} + ci->ci_essiv_tfm = essiv_tfm; -void __exit fscrypt_essiv_cleanup(void) -{ - crypto_free_shash(essiv_hash_tfm); + return crypto_shash_setkey(essiv_tfm, raw_key, keysize); } /* @@ -495,7 +447,7 @@ static void put_crypt_info(struct fscrypt_info *ci) put_master_key(ci->ci_master_key); } else { crypto_free_skcipher(ci->ci_ctfm); - crypto_free_cipher(ci->ci_essiv_tfm); + crypto_free_shash(ci->ci_essiv_tfm); } kmem_cache_free(fscrypt_info_cachep, ci); }