Commit bd0d97b7 authored by Eric Biggers's avatar Eric Biggers

fscrypt: switch fscrypt_do_sha256() to use the SHA-256 library

fscrypt_do_sha256() is only used for hashing encrypted filenames to
create no-key tokens, which isn't performance-critical.  Therefore a C
implementation of SHA-256 is sufficient.

Also, the logic to create no-key tokens is always potentially needed.
This differs from fscrypt's other dependencies on crypto API algorithms,
which are conditionally needed depending on what encryption policies
userspace is using.  Therefore, for fscrypt there isn't much benefit to
allowing SHA-256 to be a loadable module.

So, make fscrypt_do_sha256() use the SHA-256 library instead of the
crypto_shash API.  This is much simpler, since it avoids having to
implement one-time-init (which is hard to do correctly, and in fact was
implemented incorrectly) and handle failures to allocate the
crypto_shash object.

Fixes: edc440e3 ("fscrypt: improve format of no-key names")
Cc: Daniel Rosenberg <drosen@google.com>
Link: https://lore.kernel.org/r/20200721225920.114347-2-ebiggers@kernel.orgSigned-off-by: default avatarEric Biggers <ebiggers@google.com>
parent f000223c
...@@ -4,6 +4,7 @@ config FS_ENCRYPTION ...@@ -4,6 +4,7 @@ config FS_ENCRYPTION
select CRYPTO select CRYPTO
select CRYPTO_HASH select CRYPTO_HASH
select CRYPTO_SKCIPHER select CRYPTO_SKCIPHER
select CRYPTO_LIB_SHA256
select KEYS select KEYS
help help
Enable encryption of files and directories. This Enable encryption of files and directories. This
...@@ -21,7 +22,6 @@ config FS_ENCRYPTION_ALGS ...@@ -21,7 +22,6 @@ config FS_ENCRYPTION_ALGS
select CRYPTO_CTS select CRYPTO_CTS
select CRYPTO_ECB select CRYPTO_ECB
select CRYPTO_HMAC select CRYPTO_HMAC
select CRYPTO_SHA256
select CRYPTO_SHA512 select CRYPTO_SHA512
select CRYPTO_XTS select CRYPTO_XTS
......
...@@ -61,30 +61,13 @@ struct fscrypt_nokey_name { ...@@ -61,30 +61,13 @@ struct fscrypt_nokey_name {
*/ */
#define FSCRYPT_NOKEY_NAME_MAX offsetofend(struct fscrypt_nokey_name, sha256) #define FSCRYPT_NOKEY_NAME_MAX offsetofend(struct fscrypt_nokey_name, sha256)
static struct crypto_shash *sha256_hash_tfm; static void fscrypt_do_sha256(const u8 *data, unsigned int data_len, u8 *result)
static int fscrypt_do_sha256(const u8 *data, unsigned int data_len, u8 *result)
{ {
struct crypto_shash *tfm = READ_ONCE(sha256_hash_tfm); struct sha256_state sctx;
if (unlikely(!tfm)) {
struct crypto_shash *prev_tfm;
tfm = crypto_alloc_shash("sha256", 0, 0);
if (IS_ERR(tfm)) {
fscrypt_err(NULL,
"Error allocating SHA-256 transform: %ld",
PTR_ERR(tfm));
return PTR_ERR(tfm);
}
prev_tfm = cmpxchg(&sha256_hash_tfm, NULL, tfm);
if (prev_tfm) {
crypto_free_shash(tfm);
tfm = prev_tfm;
}
}
return crypto_shash_tfm_digest(tfm, data, data_len, result); sha256_init(&sctx);
sha256_update(&sctx, data, data_len);
sha256_final(&sctx, result);
} }
static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
...@@ -349,7 +332,6 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode, ...@@ -349,7 +332,6 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
const struct qstr qname = FSTR_TO_QSTR(iname); const struct qstr qname = FSTR_TO_QSTR(iname);
struct fscrypt_nokey_name nokey_name; struct fscrypt_nokey_name nokey_name;
u32 size; /* size of the unencoded no-key name */ u32 size; /* size of the unencoded no-key name */
int err;
if (fscrypt_is_dot_dotdot(&qname)) { if (fscrypt_is_dot_dotdot(&qname)) {
oname->name[0] = '.'; oname->name[0] = '.';
...@@ -387,11 +369,9 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode, ...@@ -387,11 +369,9 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
} else { } else {
memcpy(nokey_name.bytes, iname->name, sizeof(nokey_name.bytes)); memcpy(nokey_name.bytes, iname->name, sizeof(nokey_name.bytes));
/* Compute strong hash of remaining part of name. */ /* Compute strong hash of remaining part of name. */
err = fscrypt_do_sha256(&iname->name[sizeof(nokey_name.bytes)], fscrypt_do_sha256(&iname->name[sizeof(nokey_name.bytes)],
iname->len - sizeof(nokey_name.bytes), iname->len - sizeof(nokey_name.bytes),
nokey_name.sha256); nokey_name.sha256);
if (err)
return err;
size = FSCRYPT_NOKEY_NAME_MAX; size = FSCRYPT_NOKEY_NAME_MAX;
} }
oname->len = base64_encode((const u8 *)&nokey_name, size, oname->name); oname->len = base64_encode((const u8 *)&nokey_name, size, oname->name);
...@@ -530,9 +510,8 @@ bool fscrypt_match_name(const struct fscrypt_name *fname, ...@@ -530,9 +510,8 @@ bool fscrypt_match_name(const struct fscrypt_name *fname,
return false; return false;
if (memcmp(de_name, nokey_name->bytes, sizeof(nokey_name->bytes))) if (memcmp(de_name, nokey_name->bytes, sizeof(nokey_name->bytes)))
return false; return false;
if (fscrypt_do_sha256(&de_name[sizeof(nokey_name->bytes)], fscrypt_do_sha256(&de_name[sizeof(nokey_name->bytes)],
de_name_len - sizeof(nokey_name->bytes), sha256)) de_name_len - sizeof(nokey_name->bytes), sha256);
return false;
return !memcmp(sha256, nokey_name->sha256, sizeof(sha256)); return !memcmp(sha256, nokey_name->sha256, sizeof(sha256));
} }
EXPORT_SYMBOL_GPL(fscrypt_match_name); EXPORT_SYMBOL_GPL(fscrypt_match_name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment