Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 283246
b: refs/heads/master
c: 15647eb
h: refs/heads/master
v: v3
  • Loading branch information
Dmitry Kasatkin committed Nov 9, 2011
1 parent 9391bea commit c4d6bc1
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8607c501478432b23654739c7321bc7456053cb6
refs/heads/master: 15647eb3985ef30dfd657038924dc85c03026733
12 changes: 12 additions & 0 deletions trunk/security/integrity/evm/evm.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,21 @@
* File: evm.h
*
*/

#ifndef __INTEGRITY_EVM_H
#define __INTEGRITY_EVM_H

#include <linux/xattr.h>
#include <linux/security.h>

#include "../integrity.h"

extern int evm_initialized;
extern char *evm_hmac;
extern char *evm_hash;

extern struct crypto_shash *hmac_tfm;
extern struct crypto_shash *hash_tfm;

/* List of EVM protected security xattrs */
extern char *evm_config_xattrnames[];
Expand All @@ -32,7 +39,12 @@ extern int evm_update_evmxattr(struct dentry *dentry,
extern 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);
extern int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
const char *req_xattr_value,
size_t req_xattr_value_len, char *digest);
extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
char *hmac_val);
extern int evm_init_secfs(void);
extern void evm_cleanup_secfs(void);

#endif
66 changes: 49 additions & 17 deletions trunk/security/integrity/evm/evm_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,48 @@ 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 shash_desc *init_desc(void)
static struct shash_desc *init_desc(const char type)
{
int rc;
char *algo;
struct crypto_shash **tfm;
struct shash_desc *desc;

if (hmac_tfm == NULL) {
hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(hmac_tfm)) {
if (type == EVM_XATTR_HMAC) {
tfm = &hmac_tfm;
algo = evm_hmac;
} else {
tfm = &hash_tfm;
algo = evm_hash;
}

if (*tfm == NULL) {
*tfm = crypto_alloc_shash(algo, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(*tfm)) {
pr_err("Can not allocate %s (reason: %ld)\n",
evm_hmac, PTR_ERR(hmac_tfm));
rc = PTR_ERR(hmac_tfm);
hmac_tfm = NULL;
algo, PTR_ERR(*tfm));
rc = PTR_ERR(*tfm);
*tfm = NULL;
return ERR_PTR(rc);
}
}

desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm),
desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(*tfm),
GFP_KERNEL);
if (!desc)
return ERR_PTR(-ENOMEM);

desc->tfm = hmac_tfm;
desc->tfm = *tfm;
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;

rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len);
if (rc)
goto out;
if (type == EVM_XATTR_HMAC) {
rc = crypto_shash_setkey(*tfm, evmkey, evmkey_len);
if (rc)
goto out;
}

rc = crypto_shash_init(desc);
out:
if (rc) {
Expand Down Expand Up @@ -97,9 +111,11 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
* the hmac using the requested xattr value. Don't alloc/free memory for
* each xattr, but attempt to re-use the previously allocated memory.
*/
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)
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)
{
struct inode *inode = dentry->d_inode;
struct shash_desc *desc;
Expand All @@ -111,7 +127,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,

if (!inode->i_op || !inode->i_op->getxattr)
return -EOPNOTSUPP;
desc = init_desc();
desc = init_desc(type);
if (IS_ERR(desc))
return PTR_ERR(desc);

Expand Down Expand Up @@ -145,6 +161,22 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
return error;
}

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)
{
return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
req_xattr_value_len, EVM_XATTR_HMAC, digest);
}

int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
const char *req_xattr_value, size_t req_xattr_value_len,
char *digest)
{
return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
req_xattr_value_len, IMA_XATTR_DIGEST, digest);
}

/*
* Calculate the hmac and update security.evm xattr
*
Expand Down Expand Up @@ -175,7 +207,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
{
struct shash_desc *desc;

desc = init_desc();
desc = init_desc(EVM_XATTR_HMAC);
if (IS_ERR(desc)) {
printk(KERN_INFO "init_desc failed\n");
return PTR_ERR(desc);
Expand Down
94 changes: 81 additions & 13 deletions trunk/security/integrity/evm/evm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
int evm_initialized;

char *evm_hmac = "hmac(sha1)";
char *evm_hash = "sha1";

char *evm_config_xattrnames[] = {
#ifdef CONFIG_SECURITY_SELINUX
Expand All @@ -46,6 +47,29 @@ static int __init evm_set_fixmode(char *str)
}
__setup("evm=", evm_set_fixmode);

static int evm_find_protected_xattrs(struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
char **xattr;
int error;
int count = 0;

if (!inode->i_op || !inode->i_op->getxattr)
return -EOPNOTSUPP;

for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
error = inode->i_op->getxattr(dentry, *xattr, NULL, 0);
if (error < 0) {
if (error == -ENODATA)
continue;
return error;
}
count++;
}

return count;
}

/*
* evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
*
Expand All @@ -65,32 +89,72 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
size_t xattr_value_len,
struct integrity_iint_cache *iint)
{
struct evm_ima_xattr_data xattr_data;
struct evm_ima_xattr_data *xattr_data = NULL;
struct evm_ima_xattr_data calc;
enum integrity_status evm_status = INTEGRITY_PASS;
int rc;
int rc, xattr_len;

if (iint && iint->evm_status == INTEGRITY_PASS)
return iint->evm_status;

/* if status is not PASS, try to check again - against -ENOMEM */

rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
xattr_value_len, xattr_data.digest);
if (rc < 0) {
evm_status = (rc == -ENODATA)
? INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
/* first need to know the sig type */
rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
GFP_NOFS);
if (rc <= 0) {
if (rc == 0)
evm_status = INTEGRITY_FAIL; /* empty */
else if (rc == -ENODATA) {
rc = evm_find_protected_xattrs(dentry);
if (rc > 0)
evm_status = INTEGRITY_NOLABEL;
else if (rc == 0)
evm_status = INTEGRITY_NOXATTRS; /* new file */
}
goto out;
}

xattr_data.type = EVM_XATTR_HMAC;
rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data,
sizeof xattr_data, GFP_NOFS);
if (rc < 0)
evm_status = (rc == -ENODATA)
? INTEGRITY_NOLABEL : INTEGRITY_FAIL;
xattr_len = rc - 1;

/* check value type */
switch (xattr_data->type) {
case EVM_XATTR_HMAC:
rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
xattr_value_len, calc.digest);
if (rc)
break;
rc = memcmp(xattr_data->digest, calc.digest,
sizeof(calc.digest));
if (rc)
rc = -EINVAL;
break;
case EVM_IMA_XATTR_DIGSIG:
rc = evm_calc_hash(dentry, xattr_name, xattr_value,
xattr_value_len, calc.digest);
if (rc)
break;
rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
xattr_data->digest, xattr_len,
calc.digest, sizeof(calc.digest));
if (!rc) {
/* we probably want to replace rsa with hmac here */
evm_update_evmxattr(dentry, xattr_name, xattr_value,
xattr_value_len);
}
break;
default:
rc = -EINVAL;
break;
}

if (rc)
evm_status = (rc == -ENODATA) ?
INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
out:
if (iint)
iint->evm_status = evm_status;
kfree(xattr_data);
return evm_status;
}

Expand Down Expand Up @@ -354,6 +418,8 @@ static int __init init_evm(void)
printk(KERN_INFO "EVM: Error registering secfs\n");
goto err;
}

return 0;
err:
return error;
}
Expand All @@ -363,6 +429,8 @@ static void __exit cleanup_evm(void)
evm_cleanup_secfs();
if (hmac_tfm)
crypto_free_shash(hmac_tfm);
if (hash_tfm)
crypto_free_shash(hash_tfm);
}

/*
Expand Down

0 comments on commit c4d6bc1

Please sign in to comment.