|
@@ -21,6 +21,7 @@
|
|
|
#include <linux/evm.h>
|
|
|
#include <keys/encrypted-type.h>
|
|
|
#include <crypto/hash.h>
|
|
|
+#include <crypto/hash_info.h>
|
|
|
#include "evm.h"
|
|
|
|
|
|
#define EVMKEY "evm-key"
|
|
@@ -29,7 +30,7 @@ static unsigned char evmkey[MAX_KEY_SIZE];
|
|
|
static int evmkey_len = MAX_KEY_SIZE;
|
|
|
|
|
|
struct crypto_shash *hmac_tfm;
|
|
|
-struct crypto_shash *hash_tfm;
|
|
|
+static struct crypto_shash *evm_tfm[HASH_ALGO__LAST];
|
|
|
|
|
|
static DEFINE_MUTEX(mutex);
|
|
|
|
|
@@ -38,7 +39,6 @@ static DEFINE_MUTEX(mutex);
|
|
|
static unsigned long evm_set_key_flags;
|
|
|
|
|
|
static char * const evm_hmac = "hmac(sha1)";
|
|
|
-static char * const evm_hash = "sha1";
|
|
|
|
|
|
/**
|
|
|
* evm_set_key() - set EVM HMAC key from the kernel
|
|
@@ -74,10 +74,10 @@ busy:
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(evm_set_key);
|
|
|
|
|
|
-static struct shash_desc *init_desc(char type)
|
|
|
+static struct shash_desc *init_desc(char type, uint8_t hash_algo)
|
|
|
{
|
|
|
long rc;
|
|
|
- char *algo;
|
|
|
+ const char *algo;
|
|
|
struct crypto_shash **tfm;
|
|
|
struct shash_desc *desc;
|
|
|
|
|
@@ -89,15 +89,16 @@ static struct shash_desc *init_desc(char type)
|
|
|
tfm = &hmac_tfm;
|
|
|
algo = evm_hmac;
|
|
|
} else {
|
|
|
- tfm = &hash_tfm;
|
|
|
- algo = evm_hash;
|
|
|
+ tfm = &evm_tfm[hash_algo];
|
|
|
+ algo = hash_algo_name[hash_algo];
|
|
|
}
|
|
|
|
|
|
if (*tfm == NULL) {
|
|
|
mutex_lock(&mutex);
|
|
|
if (*tfm)
|
|
|
goto out;
|
|
|
- *tfm = crypto_alloc_shash(algo, 0, CRYPTO_ALG_ASYNC);
|
|
|
+ *tfm = crypto_alloc_shash(algo, 0,
|
|
|
+ CRYPTO_ALG_ASYNC | CRYPTO_NOLOAD);
|
|
|
if (IS_ERR(*tfm)) {
|
|
|
rc = PTR_ERR(*tfm);
|
|
|
pr_err("Can not allocate %s (reason: %ld)\n", algo, rc);
|
|
@@ -186,10 +187,10 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
|
|
|
* each xattr, but attempt to re-use the previously allocated memory.
|
|
|
*/
|
|
|
static int evm_calc_hmac_or_hash(struct dentry *dentry,
|
|
|
- const char *req_xattr_name,
|
|
|
- const char *req_xattr_value,
|
|
|
- size_t req_xattr_value_len,
|
|
|
- char type, char *digest)
|
|
|
+ const char *req_xattr_name,
|
|
|
+ const char *req_xattr_value,
|
|
|
+ size_t req_xattr_value_len,
|
|
|
+ uint8_t type, struct evm_digest *data)
|
|
|
{
|
|
|
struct inode *inode = d_backing_inode(dentry);
|
|
|
struct xattr_list *xattr;
|
|
@@ -204,10 +205,12 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
|
|
|
inode->i_sb->s_user_ns != &init_user_ns)
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
- desc = init_desc(type);
|
|
|
+ desc = init_desc(type, data->hdr.algo);
|
|
|
if (IS_ERR(desc))
|
|
|
return PTR_ERR(desc);
|
|
|
|
|
|
+ data->hdr.length = crypto_shash_digestsize(desc->tfm);
|
|
|
+
|
|
|
error = -ENODATA;
|
|
|
list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) {
|
|
|
bool is_ima = false;
|
|
@@ -239,7 +242,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
|
|
|
if (is_ima)
|
|
|
ima_present = true;
|
|
|
}
|
|
|
- hmac_add_misc(desc, inode, type, digest);
|
|
|
+ hmac_add_misc(desc, inode, type, data->digest);
|
|
|
|
|
|
/* Portable EVM signatures must include an IMA hash */
|
|
|
if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present)
|
|
@@ -252,18 +255,18 @@ out:
|
|
|
|
|
|
int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
|
|
|
const char *req_xattr_value, size_t req_xattr_value_len,
|
|
|
- char *digest)
|
|
|
+ struct evm_digest *data)
|
|
|
{
|
|
|
return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
|
|
|
- req_xattr_value_len, EVM_XATTR_HMAC, digest);
|
|
|
+ req_xattr_value_len, EVM_XATTR_HMAC, data);
|
|
|
}
|
|
|
|
|
|
int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
|
|
|
const char *req_xattr_value, size_t req_xattr_value_len,
|
|
|
- char type, char *digest)
|
|
|
+ char type, struct evm_digest *data)
|
|
|
{
|
|
|
return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
|
|
|
- req_xattr_value_len, type, digest);
|
|
|
+ req_xattr_value_len, type, data);
|
|
|
}
|
|
|
|
|
|
static int evm_is_immutable(struct dentry *dentry, struct inode *inode)
|
|
@@ -303,7 +306,7 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
|
|
|
const char *xattr_value, size_t xattr_value_len)
|
|
|
{
|
|
|
struct inode *inode = d_backing_inode(dentry);
|
|
|
- struct evm_ima_xattr_data xattr_data;
|
|
|
+ struct evm_digest data;
|
|
|
int rc = 0;
|
|
|
|
|
|
/*
|
|
@@ -316,13 +319,14 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
|
|
|
if (rc)
|
|
|
return -EPERM;
|
|
|
|
|
|
+ data.hdr.algo = HASH_ALGO_SHA1;
|
|
|
rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
|
|
|
- xattr_value_len, xattr_data.digest);
|
|
|
+ xattr_value_len, &data);
|
|
|
if (rc == 0) {
|
|
|
- xattr_data.type = EVM_XATTR_HMAC;
|
|
|
+ data.hdr.xattr.sha1.type = EVM_XATTR_HMAC;
|
|
|
rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
|
|
|
- &xattr_data,
|
|
|
- sizeof(xattr_data), 0);
|
|
|
+ &data.hdr.xattr.data[1],
|
|
|
+ SHA1_DIGEST_SIZE + 1, 0);
|
|
|
} else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) {
|
|
|
rc = __vfs_removexattr(dentry, XATTR_NAME_EVM);
|
|
|
}
|
|
@@ -334,7 +338,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
|
|
|
{
|
|
|
struct shash_desc *desc;
|
|
|
|
|
|
- desc = init_desc(EVM_XATTR_HMAC);
|
|
|
+ desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1);
|
|
|
if (IS_ERR(desc)) {
|
|
|
pr_info("init_desc failed\n");
|
|
|
return PTR_ERR(desc);
|