Linux Audio

Check our new training course

Loading...
  1/*
  2 * Copyright (C) 2005-2010 IBM Corporation
  3 *
  4 * Authors:
  5 * Mimi Zohar <zohar@us.ibm.com>
  6 * Kylene Hall <kjhall@us.ibm.com>
  7 *
  8 * This program is free software; you can redistribute it and/or modify
  9 * it under the terms of the GNU General Public License as published by
 10 * the Free Software Foundation, version 2 of the License.
 11 *
 12 * File: evm_crypto.c
 13 *	 Using root's kernel master key (kmk), calculate the HMAC
 14 */
 15
 16#include <linux/module.h>
 17#include <linux/crypto.h>
 18#include <linux/xattr.h>
 19#include <keys/encrypted-type.h>
 20#include <crypto/hash.h>
 21#include "evm.h"
 22
 23#define EVMKEY "evm-key"
 24#define MAX_KEY_SIZE 128
 25static unsigned char evmkey[MAX_KEY_SIZE];
 26static int evmkey_len = MAX_KEY_SIZE;
 27
 28struct crypto_shash *hmac_tfm;
 29struct crypto_shash *hash_tfm;
 30
 31static DEFINE_MUTEX(mutex);
 32
 33static struct shash_desc *init_desc(char type)
 34{
 35	long rc;
 36	char *algo;
 37	struct crypto_shash **tfm;
 38	struct shash_desc *desc;
 39
 40	if (type == EVM_XATTR_HMAC) {
 41		tfm = &hmac_tfm;
 42		algo = evm_hmac;
 43	} else {
 44		tfm = &hash_tfm;
 45		algo = evm_hash;
 46	}
 47
 48	if (*tfm == NULL) {
 49		mutex_lock(&mutex);
 50		if (*tfm)
 51			goto out;
 52		*tfm = crypto_alloc_shash(algo, 0, CRYPTO_ALG_ASYNC);
 53		if (IS_ERR(*tfm)) {
 54			rc = PTR_ERR(*tfm);
 55			pr_err("Can not allocate %s (reason: %ld)\n", algo, rc);
 56			*tfm = NULL;
 57			mutex_unlock(&mutex);
 58			return ERR_PTR(rc);
 59		}
 60		if (type == EVM_XATTR_HMAC) {
 61			rc = crypto_shash_setkey(*tfm, evmkey, evmkey_len);
 62			if (rc) {
 63				crypto_free_shash(*tfm);
 64				*tfm = NULL;
 65				mutex_unlock(&mutex);
 66				return ERR_PTR(rc);
 67			}
 68		}
 69out:
 70		mutex_unlock(&mutex);
 71	}
 72
 73	desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(*tfm),
 74			GFP_KERNEL);
 75	if (!desc)
 76		return ERR_PTR(-ENOMEM);
 77
 78	desc->tfm = *tfm;
 79	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
 80
 81	rc = crypto_shash_init(desc);
 82	if (rc) {
 83		kfree(desc);
 84		return ERR_PTR(rc);
 85	}
 86	return desc;
 87}
 88
 89/* Protect against 'cutting & pasting' security.evm xattr, include inode
 90 * specific info.
 91 *
 92 * (Additional directory/file metadata needs to be added for more complete
 93 * protection.)
 94 */
 95static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
 96			  char *digest)
 97{
 98	struct h_misc {
 99		unsigned long ino;
100		__u32 generation;
101		uid_t uid;
102		gid_t gid;
103		umode_t mode;
104	} hmac_misc;
105
106	memset(&hmac_misc, 0, sizeof hmac_misc);
107	hmac_misc.ino = inode->i_ino;
108	hmac_misc.generation = inode->i_generation;
109	hmac_misc.uid = inode->i_uid;
110	hmac_misc.gid = inode->i_gid;
111	hmac_misc.mode = inode->i_mode;
112	crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc);
113	crypto_shash_final(desc, digest);
114}
115
116/*
117 * Calculate the HMAC value across the set of protected security xattrs.
118 *
119 * Instead of retrieving the requested xattr, for performance, calculate
120 * the hmac using the requested xattr value. Don't alloc/free memory for
121 * each xattr, but attempt to re-use the previously allocated memory.
122 */
123static int evm_calc_hmac_or_hash(struct dentry *dentry,
124				const char *req_xattr_name,
125				const char *req_xattr_value,
126				size_t req_xattr_value_len,
127				char type, char *digest)
128{
129	struct inode *inode = dentry->d_inode;
130	struct shash_desc *desc;
131	char **xattrname;
132	size_t xattr_size = 0;
133	char *xattr_value = NULL;
134	int error;
135	int size;
136
137	if (!inode->i_op || !inode->i_op->getxattr)
138		return -EOPNOTSUPP;
139	desc = init_desc(type);
140	if (IS_ERR(desc))
141		return PTR_ERR(desc);
142
143	error = -ENODATA;
144	for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
145		if ((req_xattr_name && req_xattr_value)
146		    && !strcmp(*xattrname, req_xattr_name)) {
147			error = 0;
148			crypto_shash_update(desc, (const u8 *)req_xattr_value,
149					     req_xattr_value_len);
150			continue;
151		}
152		size = vfs_getxattr_alloc(dentry, *xattrname,
153					  &xattr_value, xattr_size, GFP_NOFS);
154		if (size == -ENOMEM) {
155			error = -ENOMEM;
156			goto out;
157		}
158		if (size < 0)
159			continue;
160
161		error = 0;
162		xattr_size = size;
163		crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
164	}
165	hmac_add_misc(desc, inode, digest);
166
167out:
168	kfree(xattr_value);
169	kfree(desc);
170	return error;
171}
172
173int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
174		  const char *req_xattr_value, size_t req_xattr_value_len,
175		  char *digest)
176{
177	return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
178				req_xattr_value_len, EVM_XATTR_HMAC, digest);
179}
180
181int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
182		  const char *req_xattr_value, size_t req_xattr_value_len,
183		  char *digest)
184{
185	return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
186				req_xattr_value_len, IMA_XATTR_DIGEST, digest);
187}
188
189/*
190 * Calculate the hmac and update security.evm xattr
191 *
192 * Expects to be called with i_mutex locked.
193 */
194int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
195			const char *xattr_value, size_t xattr_value_len)
196{
197	struct inode *inode = dentry->d_inode;
198	struct evm_ima_xattr_data xattr_data;
199	int rc = 0;
200
201	rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
202			   xattr_value_len, xattr_data.digest);
203	if (rc == 0) {
204		xattr_data.type = EVM_XATTR_HMAC;
205		rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
206					   &xattr_data,
207					   sizeof(xattr_data), 0);
208	}
209	else if (rc == -ENODATA)
210		rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
211	return rc;
212}
213
214int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
215		  char *hmac_val)
216{
217	struct shash_desc *desc;
218
219	desc = init_desc(EVM_XATTR_HMAC);
220	if (IS_ERR(desc)) {
221		printk(KERN_INFO "init_desc failed\n");
222		return PTR_ERR(desc);
223	}
224
225	crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len);
226	hmac_add_misc(desc, inode, hmac_val);
227	kfree(desc);
228	return 0;
229}
230
231/*
232 * Get the key from the TPM for the SHA1-HMAC
233 */
234int evm_init_key(void)
235{
236	struct key *evm_key;
237	struct encrypted_key_payload *ekp;
238	int rc = 0;
239
240	evm_key = request_key(&key_type_encrypted, EVMKEY, NULL);
241	if (IS_ERR(evm_key))
242		return -ENOENT;
243
244	down_read(&evm_key->sem);
245	ekp = evm_key->payload.data;
246	if (ekp->decrypted_datalen > MAX_KEY_SIZE) {
247		rc = -EINVAL;
248		goto out;
249	}
250	memcpy(evmkey, ekp->decrypted_data, ekp->decrypted_datalen);
251out:
252	/* burn the original key contents */
253	memset(ekp->decrypted_data, 0, ekp->decrypted_datalen);
254	up_read(&evm_key->sem);
255	key_put(evm_key);
256	return rc;
257}