aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/evm/evm_main.c
diff options
context:
space:
mode:
authorDmitry Kasatkin <dmitry.kasatkin@intel.com>2011-09-01 07:41:40 -0400
committerDmitry Kasatkin <dmitry.kasatkin@intel.com>2011-11-09 09:51:14 -0500
commit15647eb3985ef30dfd657038924dc85c03026733 (patch)
tree5d4629ef3b687ff56a446f42a8ee5aa35ec9322b /security/integrity/evm/evm_main.c
parent8607c501478432b23654739c7321bc7456053cb6 (diff)
evm: digital signature verification support
This patch adds support for digital signature verification to EVM. With this feature file metadata can be protected using digital signature instead of an HMAC. When building an image, which has to be flashed to different devices, an HMAC cannot be used to sign file metadata, because the HMAC key should be different on every device. Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com> Acked-by: Mimi Zohar <zohar@us.ibm.com>
Diffstat (limited to 'security/integrity/evm/evm_main.c')
-rw-r--r--security/integrity/evm/evm_main.c94
1 files changed, 81 insertions, 13 deletions
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 92d3d99a9f7b..8901501425f4 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -25,6 +25,7 @@
25int evm_initialized; 25int evm_initialized;
26 26
27char *evm_hmac = "hmac(sha1)"; 27char *evm_hmac = "hmac(sha1)";
28char *evm_hash = "sha1";
28 29
29char *evm_config_xattrnames[] = { 30char *evm_config_xattrnames[] = {
30#ifdef CONFIG_SECURITY_SELINUX 31#ifdef CONFIG_SECURITY_SELINUX
@@ -46,6 +47,29 @@ static int __init evm_set_fixmode(char *str)
46} 47}
47__setup("evm=", evm_set_fixmode); 48__setup("evm=", evm_set_fixmode);
48 49
50static int evm_find_protected_xattrs(struct dentry *dentry)
51{
52 struct inode *inode = dentry->d_inode;
53 char **xattr;
54 int error;
55 int count = 0;
56
57 if (!inode->i_op || !inode->i_op->getxattr)
58 return -EOPNOTSUPP;
59
60 for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
61 error = inode->i_op->getxattr(dentry, *xattr, NULL, 0);
62 if (error < 0) {
63 if (error == -ENODATA)
64 continue;
65 return error;
66 }
67 count++;
68 }
69
70 return count;
71}
72
49/* 73/*
50 * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr 74 * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
51 * 75 *
@@ -65,32 +89,72 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
65 size_t xattr_value_len, 89 size_t xattr_value_len,
66 struct integrity_iint_cache *iint) 90 struct integrity_iint_cache *iint)
67{ 91{
68 struct evm_ima_xattr_data xattr_data; 92 struct evm_ima_xattr_data *xattr_data = NULL;
93 struct evm_ima_xattr_data calc;
69 enum integrity_status evm_status = INTEGRITY_PASS; 94 enum integrity_status evm_status = INTEGRITY_PASS;
70 int rc; 95 int rc, xattr_len;
71 96
72 if (iint && iint->evm_status == INTEGRITY_PASS) 97 if (iint && iint->evm_status == INTEGRITY_PASS)
73 return iint->evm_status; 98 return iint->evm_status;
74 99
75 /* if status is not PASS, try to check again - against -ENOMEM */ 100 /* if status is not PASS, try to check again - against -ENOMEM */
76 101
77 rc = evm_calc_hmac(dentry, xattr_name, xattr_value, 102 /* first need to know the sig type */
78 xattr_value_len, xattr_data.digest); 103 rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
79 if (rc < 0) { 104 GFP_NOFS);
80 evm_status = (rc == -ENODATA) 105 if (rc <= 0) {
81 ? INTEGRITY_NOXATTRS : INTEGRITY_FAIL; 106 if (rc == 0)
107 evm_status = INTEGRITY_FAIL; /* empty */
108 else if (rc == -ENODATA) {
109 rc = evm_find_protected_xattrs(dentry);
110 if (rc > 0)
111 evm_status = INTEGRITY_NOLABEL;
112 else if (rc == 0)
113 evm_status = INTEGRITY_NOXATTRS; /* new file */
114 }
82 goto out; 115 goto out;
83 } 116 }
84 117
85 xattr_data.type = EVM_XATTR_HMAC; 118 xattr_len = rc - 1;
86 rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data, 119
87 sizeof xattr_data, GFP_NOFS); 120 /* check value type */
88 if (rc < 0) 121 switch (xattr_data->type) {
89 evm_status = (rc == -ENODATA) 122 case EVM_XATTR_HMAC:
90 ? INTEGRITY_NOLABEL : INTEGRITY_FAIL; 123 rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
124 xattr_value_len, calc.digest);
125 if (rc)
126 break;
127 rc = memcmp(xattr_data->digest, calc.digest,
128 sizeof(calc.digest));
129 if (rc)
130 rc = -EINVAL;
131 break;
132 case EVM_IMA_XATTR_DIGSIG:
133 rc = evm_calc_hash(dentry, xattr_name, xattr_value,
134 xattr_value_len, calc.digest);
135 if (rc)
136 break;
137 rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
138 xattr_data->digest, xattr_len,
139 calc.digest, sizeof(calc.digest));
140 if (!rc) {
141 /* we probably want to replace rsa with hmac here */
142 evm_update_evmxattr(dentry, xattr_name, xattr_value,
143 xattr_value_len);
144 }
145 break;
146 default:
147 rc = -EINVAL;
148 break;
149 }
150
151 if (rc)
152 evm_status = (rc == -ENODATA) ?
153 INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
91out: 154out:
92 if (iint) 155 if (iint)
93 iint->evm_status = evm_status; 156 iint->evm_status = evm_status;
157 kfree(xattr_data);
94 return evm_status; 158 return evm_status;
95} 159}
96 160
@@ -354,6 +418,8 @@ static int __init init_evm(void)
354 printk(KERN_INFO "EVM: Error registering secfs\n"); 418 printk(KERN_INFO "EVM: Error registering secfs\n");
355 goto err; 419 goto err;
356 } 420 }
421
422 return 0;
357err: 423err:
358 return error; 424 return error;
359} 425}
@@ -363,6 +429,8 @@ static void __exit cleanup_evm(void)
363 evm_cleanup_secfs(); 429 evm_cleanup_secfs();
364 if (hmac_tfm) 430 if (hmac_tfm)
365 crypto_free_shash(hmac_tfm); 431 crypto_free_shash(hmac_tfm);
432 if (hash_tfm)
433 crypto_free_shash(hash_tfm);
366} 434}
367 435
368/* 436/*