@@ -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
@@ -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);
@@ -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
@@ -15,12 +15,10 @@
#include <linux/ratelimit.h>
#include <crypto/aes.h>
#include <crypto/algapi.h>
+#include <crypto/hash.h>
#include <crypto/sha.h>
-#include <crypto/skcipher.h>
#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);
}
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 <ard.biesheuvel@linaro.org> --- 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(-) -- 2.20.1