|
@@ -16,8 +16,8 @@
|
|
#include <linux/module.h>
|
|
#include <linux/module.h>
|
|
#include <linux/crypto.h>
|
|
#include <linux/crypto.h>
|
|
#include <linux/xattr.h>
|
|
#include <linux/xattr.h>
|
|
-#include <linux/scatterlist.h>
|
|
|
|
#include <keys/encrypted-type.h>
|
|
#include <keys/encrypted-type.h>
|
|
|
|
+#include <crypto/hash.h>
|
|
#include "evm.h"
|
|
#include "evm.h"
|
|
|
|
|
|
#define EVMKEY "evm-key"
|
|
#define EVMKEY "evm-key"
|
|
@@ -25,26 +25,42 @@
|
|
static unsigned char evmkey[MAX_KEY_SIZE];
|
|
static unsigned char evmkey[MAX_KEY_SIZE];
|
|
static int evmkey_len = MAX_KEY_SIZE;
|
|
static int evmkey_len = MAX_KEY_SIZE;
|
|
|
|
|
|
-static int init_desc(struct hash_desc *desc)
|
|
|
|
|
|
+struct crypto_shash *hmac_tfm;
|
|
|
|
+
|
|
|
|
+static struct shash_desc *init_desc(void)
|
|
{
|
|
{
|
|
int rc;
|
|
int rc;
|
|
-
|
|
|
|
- desc->tfm = crypto_alloc_hash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
|
|
|
|
- if (IS_ERR(desc->tfm)) {
|
|
|
|
- pr_info("Can not allocate %s (reason: %ld)\n",
|
|
|
|
- evm_hmac, PTR_ERR(desc->tfm));
|
|
|
|
- rc = PTR_ERR(desc->tfm);
|
|
|
|
- return rc;
|
|
|
|
|
|
+ struct shash_desc *desc;
|
|
|
|
+
|
|
|
|
+ if (hmac_tfm == NULL) {
|
|
|
|
+ hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
|
|
|
|
+ if (IS_ERR(hmac_tfm)) {
|
|
|
|
+ pr_err("Can not allocate %s (reason: %ld)\n",
|
|
|
|
+ evm_hmac, PTR_ERR(hmac_tfm));
|
|
|
|
+ rc = PTR_ERR(hmac_tfm);
|
|
|
|
+ hmac_tfm = NULL;
|
|
|
|
+ return ERR_PTR(rc);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- desc->flags = 0;
|
|
|
|
- rc = crypto_hash_setkey(desc->tfm, evmkey, evmkey_len);
|
|
|
|
|
|
+
|
|
|
|
+ desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm),
|
|
|
|
+ GFP_KERNEL);
|
|
|
|
+ if (!desc)
|
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
|
+
|
|
|
|
+ desc->tfm = hmac_tfm;
|
|
|
|
+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
|
|
|
|
+
|
|
|
|
+ rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len);
|
|
if (rc)
|
|
if (rc)
|
|
goto out;
|
|
goto out;
|
|
- rc = crypto_hash_init(desc);
|
|
|
|
|
|
+ rc = crypto_shash_init(desc);
|
|
out:
|
|
out:
|
|
- if (rc)
|
|
|
|
- crypto_free_hash(desc->tfm);
|
|
|
|
- return rc;
|
|
|
|
|
|
+ if (rc) {
|
|
|
|
+ kfree(desc);
|
|
|
|
+ return ERR_PTR(rc);
|
|
|
|
+ }
|
|
|
|
+ return desc;
|
|
}
|
|
}
|
|
|
|
|
|
/* Protect against 'cutting & pasting' security.evm xattr, include inode
|
|
/* Protect against 'cutting & pasting' security.evm xattr, include inode
|
|
@@ -53,7 +69,7 @@ out:
|
|
* (Additional directory/file metadata needs to be added for more complete
|
|
* (Additional directory/file metadata needs to be added for more complete
|
|
* protection.)
|
|
* protection.)
|
|
*/
|
|
*/
|
|
-static void hmac_add_misc(struct hash_desc *desc, struct inode *inode,
|
|
|
|
|
|
+static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
|
|
char *digest)
|
|
char *digest)
|
|
{
|
|
{
|
|
struct h_misc {
|
|
struct h_misc {
|
|
@@ -63,7 +79,6 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode,
|
|
gid_t gid;
|
|
gid_t gid;
|
|
umode_t mode;
|
|
umode_t mode;
|
|
} hmac_misc;
|
|
} hmac_misc;
|
|
- struct scatterlist sg[1];
|
|
|
|
|
|
|
|
memset(&hmac_misc, 0, sizeof hmac_misc);
|
|
memset(&hmac_misc, 0, sizeof hmac_misc);
|
|
hmac_misc.ino = inode->i_ino;
|
|
hmac_misc.ino = inode->i_ino;
|
|
@@ -71,9 +86,8 @@ static void hmac_add_misc(struct hash_desc *desc, struct inode *inode,
|
|
hmac_misc.uid = inode->i_uid;
|
|
hmac_misc.uid = inode->i_uid;
|
|
hmac_misc.gid = inode->i_gid;
|
|
hmac_misc.gid = inode->i_gid;
|
|
hmac_misc.mode = inode->i_mode;
|
|
hmac_misc.mode = inode->i_mode;
|
|
- sg_init_one(sg, &hmac_misc, sizeof hmac_misc);
|
|
|
|
- crypto_hash_update(desc, sg, sizeof hmac_misc);
|
|
|
|
- crypto_hash_final(desc, digest);
|
|
|
|
|
|
+ crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc);
|
|
|
|
+ crypto_shash_final(desc, digest);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -88,8 +102,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
|
|
char *digest)
|
|
char *digest)
|
|
{
|
|
{
|
|
struct inode *inode = dentry->d_inode;
|
|
struct inode *inode = dentry->d_inode;
|
|
- struct hash_desc desc;
|
|
|
|
- struct scatterlist sg[1];
|
|
|
|
|
|
+ struct shash_desc *desc;
|
|
char **xattrname;
|
|
char **xattrname;
|
|
size_t xattr_size = 0;
|
|
size_t xattr_size = 0;
|
|
char *xattr_value = NULL;
|
|
char *xattr_value = NULL;
|
|
@@ -98,17 +111,17 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
|
|
|
|
|
|
if (!inode->i_op || !inode->i_op->getxattr)
|
|
if (!inode->i_op || !inode->i_op->getxattr)
|
|
return -EOPNOTSUPP;
|
|
return -EOPNOTSUPP;
|
|
- error = init_desc(&desc);
|
|
|
|
- if (error)
|
|
|
|
- return error;
|
|
|
|
|
|
+ desc = init_desc();
|
|
|
|
+ if (IS_ERR(desc))
|
|
|
|
+ return PTR_ERR(desc);
|
|
|
|
|
|
error = -ENODATA;
|
|
error = -ENODATA;
|
|
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
|
|
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
|
|
if ((req_xattr_name && req_xattr_value)
|
|
if ((req_xattr_name && req_xattr_value)
|
|
&& !strcmp(*xattrname, req_xattr_name)) {
|
|
&& !strcmp(*xattrname, req_xattr_name)) {
|
|
error = 0;
|
|
error = 0;
|
|
- sg_init_one(sg, req_xattr_value, req_xattr_value_len);
|
|
|
|
- crypto_hash_update(&desc, sg, req_xattr_value_len);
|
|
|
|
|
|
+ crypto_shash_update(desc, (const u8 *)req_xattr_value,
|
|
|
|
+ req_xattr_value_len);
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
size = vfs_getxattr_alloc(dentry, *xattrname,
|
|
size = vfs_getxattr_alloc(dentry, *xattrname,
|
|
@@ -122,13 +135,13 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
|
|
|
|
|
|
error = 0;
|
|
error = 0;
|
|
xattr_size = size;
|
|
xattr_size = size;
|
|
- sg_init_one(sg, xattr_value, xattr_size);
|
|
|
|
- crypto_hash_update(&desc, sg, xattr_size);
|
|
|
|
|
|
+ crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
|
|
}
|
|
}
|
|
- hmac_add_misc(&desc, inode, digest);
|
|
|
|
- kfree(xattr_value);
|
|
|
|
|
|
+ hmac_add_misc(desc, inode, digest);
|
|
|
|
+
|
|
out:
|
|
out:
|
|
- crypto_free_hash(desc.tfm);
|
|
|
|
|
|
+ kfree(xattr_value);
|
|
|
|
+ kfree(desc);
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -160,20 +173,17 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
|
|
int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
|
|
int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
|
|
char *hmac_val)
|
|
char *hmac_val)
|
|
{
|
|
{
|
|
- struct hash_desc desc;
|
|
|
|
- struct scatterlist sg[1];
|
|
|
|
- int error;
|
|
|
|
|
|
+ struct shash_desc *desc;
|
|
|
|
|
|
- error = init_desc(&desc);
|
|
|
|
- if (error != 0) {
|
|
|
|
|
|
+ desc = init_desc();
|
|
|
|
+ if (IS_ERR(desc)) {
|
|
printk(KERN_INFO "init_desc failed\n");
|
|
printk(KERN_INFO "init_desc failed\n");
|
|
- return error;
|
|
|
|
|
|
+ return PTR_ERR(desc);
|
|
}
|
|
}
|
|
|
|
|
|
- sg_init_one(sg, lsm_xattr->value, lsm_xattr->value_len);
|
|
|
|
- crypto_hash_update(&desc, sg, lsm_xattr->value_len);
|
|
|
|
- hmac_add_misc(&desc, inode, hmac_val);
|
|
|
|
- crypto_free_hash(desc.tfm);
|
|
|
|
|
|
+ crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len);
|
|
|
|
+ hmac_add_misc(desc, inode, hmac_val);
|
|
|
|
+ kfree(desc);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|