Commit 9fa8e762 authored by Enrico Bravi's avatar Enrico Bravi Committed by Mimi Zohar

ima: add crypto agility support for template-hash algorithm

The template hash showed by the ascii_runtime_measurements and
binary_runtime_measurements is the one calculated using sha1 and there is
no possibility to change this value, despite the fact that the template
hash is calculated using the hash algorithms corresponding to all the PCR
banks configured in the TPM.

Add the support to retrieve the ima log with the template data hash
calculated with a specific hash algorithm.
Add a new file in the securityfs ima directory for each hash algo
configured in a PCR bank of the TPM. Each new file has the name with
the following structure:

        {binary, ascii}_runtime_measurements_<hash_algo_name>

Legacy files are kept, to avoid breaking existing applications, but as
symbolic links which point to {binary, ascii}_runtime_measurements_sha1
files. These two files are created even if a TPM chip is not detected or
the sha1 bank is not configured in the TPM.

As example, in the case a TPM chip is present and sha256 is the only
configured PCR bank, the listing of the securityfs ima directory is the
following:

lr--r--r-- [...] ascii_runtime_measurements -> ascii_runtime_measurements_sha1
-r--r----- [...] ascii_runtime_measurements_sha1
-r--r----- [...] ascii_runtime_measurements_sha256
lr--r--r-- [...] binary_runtime_measurements -> binary_runtime_measurements_sha1
-r--r----- [...] binary_runtime_measurements_sha1
-r--r----- [...] binary_runtime_measurements_sha256
--w------- [...] policy
-r--r----- [...] runtime_measurements_count
-r--r----- [...] violations
Signed-off-by: default avatarEnrico Bravi <enrico.bravi@polito.it>
Signed-off-by: default avatarSilvia Sisinni <silvia.sisinni@polito.it>
Reviewed-by: default avatarRoberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: default avatarMimi Zohar <zohar@linux.ibm.com>
parent 5e2e4d0e
...@@ -49,11 +49,19 @@ extern int ima_policy_flag; ...@@ -49,11 +49,19 @@ extern int ima_policy_flag;
/* bitset of digests algorithms allowed in the setxattr hook */ /* bitset of digests algorithms allowed in the setxattr hook */
extern atomic_t ima_setxattr_allowed_hash_algorithms; extern atomic_t ima_setxattr_allowed_hash_algorithms;
/* IMA hash algorithm description */
struct ima_algo_desc {
struct crypto_shash *tfm;
enum hash_algo algo;
};
/* set during initialization */ /* set during initialization */
extern int ima_hash_algo __ro_after_init; extern int ima_hash_algo __ro_after_init;
extern int ima_sha1_idx __ro_after_init; extern int ima_sha1_idx __ro_after_init;
extern int ima_hash_algo_idx __ro_after_init; extern int ima_hash_algo_idx __ro_after_init;
extern int ima_extra_slots __ro_after_init; extern int ima_extra_slots __ro_after_init;
extern struct ima_algo_desc *ima_algo_array __ro_after_init;
extern int ima_appraise; extern int ima_appraise;
extern struct tpm_chip *ima_tpm_chip; extern struct tpm_chip *ima_tpm_chip;
extern const char boot_aggregate_name[]; extern const char boot_aggregate_name[];
......
...@@ -57,11 +57,6 @@ MODULE_PARM_DESC(ahash_bufsize, "Maximum ahash buffer size"); ...@@ -57,11 +57,6 @@ MODULE_PARM_DESC(ahash_bufsize, "Maximum ahash buffer size");
static struct crypto_shash *ima_shash_tfm; static struct crypto_shash *ima_shash_tfm;
static struct crypto_ahash *ima_ahash_tfm; static struct crypto_ahash *ima_ahash_tfm;
struct ima_algo_desc {
struct crypto_shash *tfm;
enum hash_algo algo;
};
int ima_sha1_idx __ro_after_init; int ima_sha1_idx __ro_after_init;
int ima_hash_algo_idx __ro_after_init; int ima_hash_algo_idx __ro_after_init;
/* /*
...@@ -70,7 +65,7 @@ int ima_hash_algo_idx __ro_after_init; ...@@ -70,7 +65,7 @@ int ima_hash_algo_idx __ro_after_init;
*/ */
int ima_extra_slots __ro_after_init; int ima_extra_slots __ro_after_init;
static struct ima_algo_desc *ima_algo_array; struct ima_algo_desc *ima_algo_array __ro_after_init;
static int __init ima_init_ima_crypto(void) static int __init ima_init_ima_crypto(void)
{ {
......
...@@ -116,9 +116,31 @@ void ima_putc(struct seq_file *m, void *data, int datalen) ...@@ -116,9 +116,31 @@ void ima_putc(struct seq_file *m, void *data, int datalen)
seq_putc(m, *(char *)data++); seq_putc(m, *(char *)data++);
} }
static struct dentry **ascii_securityfs_measurement_lists __ro_after_init;
static struct dentry **binary_securityfs_measurement_lists __ro_after_init;
static int securityfs_measurement_list_count __ro_after_init;
static void lookup_template_data_hash_algo(int *algo_idx, enum hash_algo *algo,
struct seq_file *m,
struct dentry **lists)
{
struct dentry *dentry;
int i;
dentry = file_dentry(m->file);
for (i = 0; i < securityfs_measurement_list_count; i++) {
if (dentry == lists[i]) {
*algo_idx = i;
*algo = ima_algo_array[i].algo;
break;
}
}
}
/* print format: /* print format:
* 32bit-le=pcr# * 32bit-le=pcr#
* char[20]=template digest * char[n]=template digest
* 32bit-le=template name size * 32bit-le=template name size
* char[n]=template name * char[n]=template name
* [eventdata length] * [eventdata length]
...@@ -132,7 +154,15 @@ int ima_measurements_show(struct seq_file *m, void *v) ...@@ -132,7 +154,15 @@ int ima_measurements_show(struct seq_file *m, void *v)
char *template_name; char *template_name;
u32 pcr, namelen, template_data_len; /* temporary fields */ u32 pcr, namelen, template_data_len; /* temporary fields */
bool is_ima_template = false; bool is_ima_template = false;
int i; enum hash_algo algo;
int i, algo_idx;
algo_idx = ima_sha1_idx;
algo = HASH_ALGO_SHA1;
if (m->file != NULL)
lookup_template_data_hash_algo(&algo_idx, &algo, m,
binary_securityfs_measurement_lists);
/* get entry */ /* get entry */
e = qe->entry; e = qe->entry;
...@@ -151,7 +181,7 @@ int ima_measurements_show(struct seq_file *m, void *v) ...@@ -151,7 +181,7 @@ int ima_measurements_show(struct seq_file *m, void *v)
ima_putc(m, &pcr, sizeof(e->pcr)); ima_putc(m, &pcr, sizeof(e->pcr));
/* 2nd: template digest */ /* 2nd: template digest */
ima_putc(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE); ima_putc(m, e->digests[algo_idx].digest, hash_digest_size[algo]);
/* 3rd: template name size */ /* 3rd: template name size */
namelen = !ima_canonical_fmt ? strlen(template_name) : namelen = !ima_canonical_fmt ? strlen(template_name) :
...@@ -220,7 +250,15 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v) ...@@ -220,7 +250,15 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
struct ima_queue_entry *qe = v; struct ima_queue_entry *qe = v;
struct ima_template_entry *e; struct ima_template_entry *e;
char *template_name; char *template_name;
int i; enum hash_algo algo;
int i, algo_idx;
algo_idx = ima_sha1_idx;
algo = HASH_ALGO_SHA1;
if (m->file != NULL)
lookup_template_data_hash_algo(&algo_idx, &algo, m,
ascii_securityfs_measurement_lists);
/* get entry */ /* get entry */
e = qe->entry; e = qe->entry;
...@@ -233,8 +271,8 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v) ...@@ -233,8 +271,8 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
/* 1st: PCR used (config option) */ /* 1st: PCR used (config option) */
seq_printf(m, "%2d ", e->pcr); seq_printf(m, "%2d ", e->pcr);
/* 2nd: SHA1 template hash */ /* 2nd: template hash */
ima_print_digest(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE); ima_print_digest(m, e->digests[algo_idx].digest, hash_digest_size[algo]);
/* 3th: template name */ /* 3th: template name */
seq_printf(m, " %s", template_name); seq_printf(m, " %s", template_name);
...@@ -379,6 +417,71 @@ static const struct seq_operations ima_policy_seqops = { ...@@ -379,6 +417,71 @@ static const struct seq_operations ima_policy_seqops = {
}; };
#endif #endif
static void __init remove_securityfs_measurement_lists(struct dentry **lists)
{
int i;
if (lists) {
for (i = 0; i < securityfs_measurement_list_count; i++)
securityfs_remove(lists[i]);
kfree(lists);
}
securityfs_measurement_list_count = 0;
}
static int __init create_securityfs_measurement_lists(void)
{
char file_name[NAME_MAX + 1];
struct dentry *dentry;
u16 algo;
int i;
securityfs_measurement_list_count = NR_BANKS(ima_tpm_chip);
if (ima_sha1_idx >= NR_BANKS(ima_tpm_chip))
securityfs_measurement_list_count++;
ascii_securityfs_measurement_lists =
kcalloc(securityfs_measurement_list_count, sizeof(struct dentry *),
GFP_KERNEL);
if (!ascii_securityfs_measurement_lists)
return -ENOMEM;
binary_securityfs_measurement_lists =
kcalloc(securityfs_measurement_list_count, sizeof(struct dentry *),
GFP_KERNEL);
if (!binary_securityfs_measurement_lists)
return -ENOMEM;
for (i = 0; i < securityfs_measurement_list_count; i++) {
algo = ima_algo_array[i].algo;
sprintf(file_name, "ascii_runtime_measurements_%s",
hash_algo_name[algo]);
dentry = securityfs_create_file(file_name, S_IRUSR | S_IRGRP,
ima_dir, NULL,
&ima_ascii_measurements_ops);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
ascii_securityfs_measurement_lists[i] = dentry;
sprintf(file_name, "binary_runtime_measurements_%s",
hash_algo_name[algo]);
dentry = securityfs_create_file(file_name, S_IRUSR | S_IRGRP,
ima_dir, NULL,
&ima_measurements_ops);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
binary_securityfs_measurement_lists[i] = dentry;
}
return 0;
}
/* /*
* ima_open_policy: sequentialize access to the policy file * ima_open_policy: sequentialize access to the policy file
*/ */
...@@ -454,6 +557,9 @@ int __init ima_fs_init(void) ...@@ -454,6 +557,9 @@ int __init ima_fs_init(void)
{ {
int ret; int ret;
ascii_securityfs_measurement_lists = NULL;
binary_securityfs_measurement_lists = NULL;
ima_dir = securityfs_create_dir("ima", integrity_dir); ima_dir = securityfs_create_dir("ima", integrity_dir);
if (IS_ERR(ima_dir)) if (IS_ERR(ima_dir))
return PTR_ERR(ima_dir); return PTR_ERR(ima_dir);
...@@ -465,19 +571,21 @@ int __init ima_fs_init(void) ...@@ -465,19 +571,21 @@ int __init ima_fs_init(void)
goto out; goto out;
} }
ret = create_securityfs_measurement_lists();
if (ret != 0)
goto out;
binary_runtime_measurements = binary_runtime_measurements =
securityfs_create_file("binary_runtime_measurements", securityfs_create_symlink("binary_runtime_measurements", ima_dir,
S_IRUSR | S_IRGRP, ima_dir, NULL, "binary_runtime_measurements_sha1", NULL);
&ima_measurements_ops);
if (IS_ERR(binary_runtime_measurements)) { if (IS_ERR(binary_runtime_measurements)) {
ret = PTR_ERR(binary_runtime_measurements); ret = PTR_ERR(binary_runtime_measurements);
goto out; goto out;
} }
ascii_runtime_measurements = ascii_runtime_measurements =
securityfs_create_file("ascii_runtime_measurements", securityfs_create_symlink("ascii_runtime_measurements", ima_dir,
S_IRUSR | S_IRGRP, ima_dir, NULL, "ascii_runtime_measurements_sha1", NULL);
&ima_ascii_measurements_ops);
if (IS_ERR(ascii_runtime_measurements)) { if (IS_ERR(ascii_runtime_measurements)) {
ret = PTR_ERR(ascii_runtime_measurements); ret = PTR_ERR(ascii_runtime_measurements);
goto out; goto out;
...@@ -515,6 +623,8 @@ int __init ima_fs_init(void) ...@@ -515,6 +623,8 @@ int __init ima_fs_init(void)
securityfs_remove(runtime_measurements_count); securityfs_remove(runtime_measurements_count);
securityfs_remove(ascii_runtime_measurements); securityfs_remove(ascii_runtime_measurements);
securityfs_remove(binary_runtime_measurements); securityfs_remove(binary_runtime_measurements);
remove_securityfs_measurement_lists(ascii_securityfs_measurement_lists);
remove_securityfs_measurement_lists(binary_securityfs_measurement_lists);
securityfs_remove(ima_symlink); securityfs_remove(ima_symlink);
securityfs_remove(ima_dir); securityfs_remove(ima_dir);
......
...@@ -30,6 +30,7 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer, ...@@ -30,6 +30,7 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
goto out; goto out;
} }
file.file = NULL;
file.size = segment_size; file.size = segment_size;
file.read_pos = 0; file.read_pos = 0;
file.count = sizeof(khdr); /* reserved space */ file.count = sizeof(khdr); /* reserved space */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment