ima: add crypto agility support for template-hash algorithm
[sfrench/cifs-2.6.git] / security / integrity / ima / ima_fs.c
index cd1683dad3bf016e8d1189bef8616361c1eed80b..abdd22007ed83ba8ccd6b6336fa99baaf6740fee 100644 (file)
@@ -116,9 +116,31 @@ void ima_putc(struct seq_file *m, void *data, int datalen)
                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:
  *       32bit-le=pcr#
- *       char[20]=template digest
+ *       char[n]=template digest
  *       32bit-le=template name size
  *       char[n]=template name
  *       [eventdata length]
@@ -132,7 +154,15 @@ int ima_measurements_show(struct seq_file *m, void *v)
        char *template_name;
        u32 pcr, namelen, template_data_len; /* temporary fields */
        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 */
        e = qe->entry;
@@ -151,7 +181,7 @@ int ima_measurements_show(struct seq_file *m, void *v)
        ima_putc(m, &pcr, sizeof(e->pcr));
 
        /* 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 */
        namelen = !ima_canonical_fmt ? strlen(template_name) :
@@ -220,7 +250,15 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
        struct ima_queue_entry *qe = v;
        struct ima_template_entry *e;
        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 */
        e = qe->entry;
@@ -233,8 +271,8 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
        /* 1st: PCR used (config option) */
        seq_printf(m, "%2d ", e->pcr);
 
-       /* 2nd: SHA1 template hash */
-       ima_print_digest(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
+       /* 2nd: template hash */
+       ima_print_digest(m, e->digests[algo_idx].digest, hash_digest_size[algo]);
 
        /* 3th:  template name */
        seq_printf(m, " %s", template_name);
@@ -379,6 +417,71 @@ static const struct seq_operations ima_policy_seqops = {
 };
 #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
  */
@@ -454,6 +557,9 @@ int __init ima_fs_init(void)
 {
        int ret;
 
+       ascii_securityfs_measurement_lists = NULL;
+       binary_securityfs_measurement_lists = NULL;
+
        ima_dir = securityfs_create_dir("ima", integrity_dir);
        if (IS_ERR(ima_dir))
                return PTR_ERR(ima_dir);
@@ -465,19 +571,21 @@ int __init ima_fs_init(void)
                goto out;
        }
 
+       ret = create_securityfs_measurement_lists();
+       if (ret != 0)
+               goto out;
+
        binary_runtime_measurements =
-           securityfs_create_file("binary_runtime_measurements",
-                                  S_IRUSR | S_IRGRP, ima_dir, NULL,
-                                  &ima_measurements_ops);
+           securityfs_create_symlink("binary_runtime_measurements", ima_dir,
+                                     "binary_runtime_measurements_sha1", NULL);
        if (IS_ERR(binary_runtime_measurements)) {
                ret = PTR_ERR(binary_runtime_measurements);
                goto out;
        }
 
        ascii_runtime_measurements =
-           securityfs_create_file("ascii_runtime_measurements",
-                                  S_IRUSR | S_IRGRP, ima_dir, NULL,
-                                  &ima_ascii_measurements_ops);
+           securityfs_create_symlink("ascii_runtime_measurements", ima_dir,
+                                     "ascii_runtime_measurements_sha1", NULL);
        if (IS_ERR(ascii_runtime_measurements)) {
                ret = PTR_ERR(ascii_runtime_measurements);
                goto out;
@@ -515,6 +623,8 @@ out:
        securityfs_remove(runtime_measurements_count);
        securityfs_remove(ascii_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_dir);