From patchwork Fri Mar 23 19:23:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 890167 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-ext4-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Gv3C2sZO"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 407DDf3Wh4z9rxs for ; Sat, 24 Mar 2018 06:31:30 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752573AbeCWTb1 (ORCPT ); Fri, 23 Mar 2018 15:31:27 -0400 Received: from mail-pl0-f67.google.com ([209.85.160.67]:41377 "EHLO mail-pl0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752575AbeCWTbZ (ORCPT ); Fri, 23 Mar 2018 15:31:25 -0400 Received: by mail-pl0-f67.google.com with SMTP id b7-v6so8031054plr.8; Fri, 23 Mar 2018 12:31:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=WEchPWaRQLQniiPIj+sl10TxVPcDKRMiXIxFk/rWxTQ=; b=Gv3C2sZO6+/GqyW3ryoC+8QxZglFx/jTDh48TbsV12KOJcze2pDFe+wquFfeFOIxGk Ma2vLl+Ff3dihZO0vHlcJYwp6ezvmNeeQ1l9rKH9FCWxU8DL/BUe/pzUrUiTbjpVyY12 hY4iY4dtYm2HG52um5HtcsutRvRr2rF+kH3ebgm5oCyaA9bnovp7+7ybFqNCCnQFEPPg owPoQ2MPFCcqxOi3hBVQ95S7dzVThidfIQQm1ae9wLtJS/o8IoE4nJ2p1ckdiedd41fb bTQr7EP7ZM+4kfchtP6/DXADLWiMqfhcp2DX+hU5qdpm7FYmmd4d/+yhkRuXQwFzpHSi xP6Q== 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=WEchPWaRQLQniiPIj+sl10TxVPcDKRMiXIxFk/rWxTQ=; b=CDeqm/fG064W61ve/kHlUoA0g0ZE3G8AYN6dGqX18QuODdAAT+lcJwvmyqvp8g9m8o 9wh3wTCHtonwrb/6jzeZreCeeMNbilGLuLYgsROTdP5lB1SEf6ZM5G7wkdkoLeyhV0JY fNxWTmReMwbZHwhUFdlmAxmZJsrfBTwMhG5ZgQw5G9DbU+MWdxupEBgqXgcf2QbwCThY eErHp2rTzlYjba6/ixFBzLiyfSnp5W2d2IfE6IYpBwksOVW1rR80ddhXn/RRjiQL6JcW lbZQF95/b4SS0jxs5QTX3SJXlX0VEijsaKGsCT8++4gdm+5J9lYh70fb2wDj7JznG2fe ZjWg== X-Gm-Message-State: AElRT7F0uPSCLCQBiqYx1SGc7tYdQviON8m3f+20yIf/aMHXa/a+tH59 fX1YSSLd7A1zukotrXEI5MsOJYsw X-Google-Smtp-Source: AG47ELsfNe/jKPDh4MQ2KdrXy1eK/8GmjDJ1cXE5X9c5VaUKdlxTxUq1nUPGt3FDZcS7E9a6S1hxoA== X-Received: by 2002:a17:902:9a05:: with SMTP id v5-v6mr30559786plp.69.1521833484344; Fri, 23 Mar 2018 12:31:24 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([2620:15c:17:3:dc28:5c82:b905:e8a8]) by smtp.gmail.com with ESMTPSA id x1sm20924545pfk.144.2018.03.23.12.31.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Mar 2018 12:31:23 -0700 (PDT) From: Eric Biggers To: linux-fscrypt@vger.kernel.org, "Theodore Y . Ts'o" Cc: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-mtd@lists.infradead.org, Jaegeuk Kim , Eric Biggers Subject: [PATCH 14/14] fscrypt: only derive the needed portion of the key Date: Fri, 23 Mar 2018 12:23:58 -0700 Message-Id: <20180323192358.95691-15-ebiggers3@gmail.com> X-Mailer: git-send-email 2.17.0.rc0.231.g781580f067-goog In-Reply-To: <20180323192358.95691-1-ebiggers3@gmail.com> References: <20180323192358.95691-1-ebiggers3@gmail.com> Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org From: Eric Biggers Currently the key derivation function in fscrypt uses the master key length as the amount of output key material to derive. This works, but it means we can waste time deriving more key material than is actually used, e.g. most commonly, deriving 64 bytes for directories which only take a 32-byte AES-256-CTS-CBC key. It also forces us to validate that the master key length is a multiple of AES_BLOCK_SIZE, which wouldn't otherwise be necessary. Fix it to only derive the needed length key. Signed-off-by: Eric Biggers --- fs/crypto/keyinfo.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index f00bf1437c3c..81cd7ea86c07 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -19,17 +19,16 @@ static struct crypto_shash *essiv_hash_tfm; -/** - * derive_key_aes() - Derive a key using AES-128-ECB - * @deriving_key: Encryption key used for derivation. - * @source_key: Source key to which to apply derivation. - * @derived_raw_key: Derived raw key. +/* + * Key derivation function. This generates the derived key by encrypting the + * master key with AES-128-ECB using the inode's nonce as the AES key. * - * Return: Zero on success; non-zero otherwise. + * The master key must be at least as long as the derived key. If the master + * key is longer, then only the first 'derived_keysize' bytes are used. */ -static int derive_key_aes(const u8 deriving_key[FS_KEY_DERIVATION_NONCE_SIZE], - const struct fscrypt_key *source_key, - u8 derived_raw_key[FS_MAX_KEY_SIZE]) +static int derive_key_aes(const u8 *master_key, + const struct fscrypt_context *ctx, + u8 *derived_key, unsigned int derived_keysize) { int res = 0; struct skcipher_request *req = NULL; @@ -51,14 +50,13 @@ static int derive_key_aes(const u8 deriving_key[FS_KEY_DERIVATION_NONCE_SIZE], skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done, &wait); - res = crypto_skcipher_setkey(tfm, deriving_key, - FS_KEY_DERIVATION_NONCE_SIZE); + res = crypto_skcipher_setkey(tfm, ctx->nonce, sizeof(ctx->nonce)); if (res < 0) goto out; - sg_init_one(&src_sg, source_key->raw, source_key->size); - sg_init_one(&dst_sg, derived_raw_key, source_key->size); - skcipher_request_set_crypt(req, &src_sg, &dst_sg, source_key->size, + sg_init_one(&src_sg, master_key, derived_keysize); + sg_init_one(&dst_sg, derived_key, derived_keysize); + skcipher_request_set_crypt(req, &src_sg, &dst_sg, derived_keysize, NULL); res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); out: @@ -109,10 +107,9 @@ find_and_lock_process_key(const char *prefix, goto invalid; } - if (payload->size < min_keysize || - payload->size % AES_BLOCK_SIZE != 0) { + if (payload->size < min_keysize) { fscrypt_warn(NULL, - "key with description '%s' is too short or is misaligned (got %u bytes, need %u+ bytes)", + "key with description '%s' is too short (got %u bytes, need %u+ bytes)", key->description, payload->size, min_keysize); goto invalid; } @@ -145,7 +142,7 @@ static int find_and_derive_key(const struct inode *inode, } if (IS_ERR(key)) return PTR_ERR(key); - err = derive_key_aes(ctx->nonce, payload, derived_key); + err = derive_key_aes(payload->raw, ctx, derived_key, derived_keysize); up_read(&key->sem); key_put(key); return err; @@ -327,7 +324,7 @@ int fscrypt_get_encryption_info(struct inode *inode) * crypto API as part of key derivation. */ res = -ENOMEM; - raw_key = kmalloc(FS_MAX_KEY_SIZE, GFP_NOFS); + raw_key = kmalloc(keysize, GFP_NOFS); if (!raw_key) goto out; @@ -345,10 +342,6 @@ int fscrypt_get_encryption_info(struct inode *inode) } crypt_info->ci_ctfm = ctfm; crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY); - /* - * if the provided key is longer than keysize, we use the first - * keysize bytes of the derived key only - */ res = crypto_skcipher_setkey(ctfm, raw_key, keysize); if (res) goto out;