diff --git a/src/Kconfig b/src/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..ba88aecbc445d2702b7b39669176d96fde2cbe74 --- /dev/null +++ b/src/Kconfig @@ -0,0 +1,22 @@ +config DIM_CORE + tristate "Dynamic Integrity Measurement (DIM) Core" + select SECURITYFS + select CRYPTO_SHA256 + select CRYPTO_HASH_INFO + default y + help + The Dynamic Integrity Measurement(DIM) Core maintains + a list of hash values of code segment of executables + files, as they are read only and executed. If an attacker + manages to change the contents of the code segment in + process, we can tell. + If your system has a TPM chip, then DIM Core also maintains + an aggregate integrity value over this list inside the + TPM hardware. + If unsure, say N. + +config DIM_CORE_SIGNATURE_SUPPORT + bool "Enable signature verification in DIM Core" + depends on DIM_CORE + default n + select ASYMMETRIC_KEY_TYPE diff --git a/src/Makefile b/src/Makefile index 6782fd1f8b5dae3b74066961446c248aaa68341f..df4c729fec1f8bfa9b61ffbc5c74b18e09610338 100644 --- a/src/Makefile +++ b/src/Makefile @@ -32,7 +32,9 @@ dim_core-objs += common/dim_utils.o dim_core-objs += common/dim_baseline.o dim_core-objs += common/dim_hash.o dim_core-objs += common/dim_measure_log.o -dim_core-objs += common/dim_tpm.o +dim_core-objs += common/dim_rot.o +dim_core-objs += common/dim_rot_tpm.o +dim_core-objs += common/dim_rot_virtcca.o dim_core-objs += common/dim_symbol.o dim_core-objs += common/dim_safe_func.o dim_core-objs += measure/dim_measure.o @@ -54,7 +56,9 @@ dim_monitor-objs += common/dim_hash.o dim_monitor-objs += common/dim_utils.o dim_monitor-objs += common/dim_measure_log.o dim_monitor-objs += common/dim_baseline.o -dim_monitor-objs += common/dim_tpm.o +dim_monitor-objs += common/dim_rot.o +dim_monitor-objs += common/dim_rot_tpm.o +dim_monitor-objs += common/dim_rot_virtcca.o dim_monitor-objs += common/dim_symbol.o dim_monitor-objs += common/dim_safe_func.o dim_monitor-objs += measure/dim_measure.o diff --git a/src/Makefile.kernel b/src/Makefile.kernel new file mode 100644 index 0000000000000000000000000000000000000000..b293d95e64e55864ab3a389a6d42339801ff84a9 --- /dev/null +++ b/src/Makefile.kernel @@ -0,0 +1,49 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + +obj-$(CONFIG_DIM_CORE) += dim_core.o + +dim_core-objs += core/dim_core_main.o +dim_core-objs += core/dim_core_fs.o +dim_core-objs += core/dim_core_mem_pool.o +dim_core-objs += core/dim_core_measure.o +dim_core-objs += core/dim_core_symbol.o +dim_core-$(CONFIG_DIM_CORE_SIGNATURE_SUPPORT) += core/dim_core_sig.o + +dim_core-objs += core/tasks/dim_core_measure_kernel.o +dim_core-objs += core/tasks/dim_core_measure_module.o +dim_core-objs += core/tasks/dim_core_measure_process/dim_vm_hash.o +dim_core-objs += core/tasks/dim_core_measure_process/dim_core_measure_process.o +dim_core-objs += core/tasks/dim_core_measure_process/dim_core_measure_process_vma.o + +dim_core-objs += core/policy/dim_core_policy.o +dim_core-objs += core/policy/dim_core_policy_complex.o + +dim_core-objs += core/static_baseline/dim_core_static_baseline.o +dim_core-objs += core/static_baseline/dim_core_static_baseline_complex.o + +dim_core-objs += common/dim_entry.o +dim_core-objs += common/dim_utils.o +dim_core-objs += common/dim_baseline.o +dim_core-objs += common/dim_hash.o +dim_core-objs += common/dim_measure_log.o +dim_core-objs += common/dim_rot.o +dim_core-objs += common/dim_rot_tpm.o +dim_core-objs += common/dim_rot_virtcca.o +dim_core-objs += common/dim_symbol.o +dim_core-objs += common/dim_safe_func.o +dim_core-objs += measure/dim_measure.o +dim_core-objs += measure/dim_measure_baseline.o +dim_core-objs += measure/dim_measure_task.o +dim_core-objs += measure/dim_measure_utils.o +dim_core-objs += measure/dim_measure_status.o + +ccflags-y := -I$(src)/core +ccflags-y += -I$(src)/core/static_baseline +ccflags-y += -I$(src)/core/tasks +ccflags-y += -I$(src)/core/tasks/dim_core_measure_process +ccflags-y += -I$(src)/core/policy +ccflags-y += -I$(src)/monitor +ccflags-y += -I$(src)/monitor/measure_task +ccflags-y += -I$(src)/common +ccflags-y += -I$(src)/measure + diff --git a/src/common/.dim_measure_log.c.swp b/src/common/.dim_measure_log.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..a02fbe55094aa14328d6759111520cbf7cc0890a Binary files /dev/null and b/src/common/.dim_measure_log.c.swp differ diff --git a/src/common/dim_entry.h b/src/common/dim_entry.h index bb023b63369b6207c52080949c58553c3923537d..ff25708d78388e9026fa8052761c5d4d15c402c3 100644 --- a/src/common/dim_entry.h +++ b/src/common/dim_entry.h @@ -24,6 +24,11 @@ struct dim_entry { struct dentry *dentry; }; +#ifndef THIS_MODULE +#define THIS_MODULE NULL +#endif + + /* the file interface for trigger by 'echo 1 > file_path' */ #define dim_trigger_entry(sname, fname, function) \ static ssize_t sname##_trigger(struct file *file, \ @@ -60,37 +65,37 @@ static struct dim_entry sname##_entry = { \ }; /* the file interface for reading measure log */ -#define dim_measure_log_entry(sname, fname, root_ptr) \ -static void *measure_log_read_start(struct seq_file *m, loff_t *pos) \ +#define dim_measure_log_entry(sname, fname, root_ptr, format) \ +static void *measure_log##format##_read_start(struct seq_file *m, loff_t *pos) \ { \ read_lock(&(root_ptr)->lock); \ return seq_list_start(&(root_ptr)->list_root, *pos); \ } \ \ -static void *measure_log_read_next(struct seq_file *m, \ +static void *measure_log##format##_read_next(struct seq_file *m, \ void *v, loff_t *pos) \ { \ return seq_list_next(v, &(root_ptr)->list_root, pos); \ } \ \ -static void measure_log_read_stop(struct seq_file *m, void *v) \ +static void measure_log##format##_read_stop(struct seq_file *m, void *v) \ { \ read_unlock(&(root_ptr)->lock); \ } \ \ -static int measure_log_read_show(struct seq_file *m, void *v) \ +static int measure_log##format##_read_show(struct seq_file *m, void *v) \ { \ struct dim_measure_log *log = \ list_entry(v, struct dim_measure_log, node_order); \ \ - return dim_measure_log_seq_show(m, log); \ + return dim_measure_log_seq_show_##format(m, log); \ } \ \ const struct seq_operations sname##_seqops = { \ - .start = measure_log_read_start, \ - .next = measure_log_read_next, \ - .stop = measure_log_read_stop, \ - .show = measure_log_read_show, \ + .start = measure_log##format##_read_start, \ + .next = measure_log##format##_read_next, \ + .stop = measure_log##format##_read_stop, \ + .show = measure_log##format##_read_show, \ }; \ \ static int sname##_open(struct inode *inode, struct file *file) \ diff --git a/src/common/dim_measure_log.c b/src/common/dim_measure_log.c index 59654a59589892a9ae28415d459ee2bc05f117a2..24664aa691e0ec9d5a1fe37f6a0b1d446710b199 100644 --- a/src/common/dim_measure_log.c +++ b/src/common/dim_measure_log.c @@ -5,10 +5,12 @@ #include #include "dim_rb.h" -#include "dim_tpm.h" +#include "dim_rot.h" #include "dim_safe_func.h" #include "dim_measure_log.h" +#define DIM_TEMPLATE "ima-ng" + /* static int dim_measure_name_rb_add(struct rb_root *root, struct dim_baseline *data, @@ -57,7 +59,65 @@ static int cal_measure_log_digest(const char *name, return crypto_shash_final(shash, info->log_digest.data); } -int dim_measure_log_seq_show(struct seq_file *m, struct dim_measure_log *info) +static void dim_putc(struct seq_file *m, const void *data, int datelen) +{ + while (datelen--) + seq_putc(m, *(char *)data++); +} + +int dim_measure_log_seq_show_binary(struct seq_file *m, + struct dim_measure_log *info) +{ + u32 pcr, len, name_len, digest_len; + char digest_buf[(DIM_MAX_DIGEST_SIZE << 1) + 1] = { 0 }; + const char *name = NULL; + + /* Print slot index */ + pcr = dim_rot_slot(); + dim_putc(m, &pcr, sizeof(pcr)); + + /* template digest + * Note: This length does not match the actual value. It is currently + * specified as SHA1 for compatibility with some remote attestation + * tools. However, the digest value of the measurement log is not + * actually used in the attestation. + * */ + dim_putc(m, &info->log_digest.data, dim_digest_size(HASH_ALGO_SHA1)); + + /* template name */ + len = strlen(DIM_TEMPLATE); + dim_putc(m, &len, sizeof(len)); + dim_putc(m, DIM_TEMPLATE, len); + + /* calculate the length of rest data */ + digest_len = strlen(dim_hash_name(info->log_digest.algo)) + \ + strlen(":") + 1 + \ + dim_digest_size(info->log_digest.algo); + + name = dim_measure_log_name(info); + name_len = strlen(name) + 1; + len = digest_len + name_len + sizeof(name_len) + sizeof(digest_len); + + /* print len */ + dim_putc(m, &len, sizeof(len)); + /* digest buf*/ + strcat(digest_buf, dim_hash_name(info->digest.algo)); + strcat(digest_buf, ":"); + strncpy(digest_buf + strlen(digest_buf) + 1, info->digest.data, dim_digest_size(info->log_digest.algo)); + dim_putc(m, &digest_len, sizeof(digest_len)); + dim_putc(m, digest_buf, digest_len); + + /* measure log name */ + dim_putc(m, &name_len, sizeof(name_len)); + dim_putc(m, name, name_len); + + /* to do list: measure log type*/ + + return 0; +} + +int dim_measure_log_seq_show_ascii(struct seq_file *m, + struct dim_measure_log *info) { char log_digest_buf[(DIM_MAX_DIGEST_SIZE << 1) + 1] = { 0 }; char digest_buf[(DIM_MAX_DIGEST_SIZE << 1) + 1] = { 0 }; @@ -68,13 +128,21 @@ int dim_measure_log_seq_show(struct seq_file *m, struct dim_measure_log *info) bin2hex(digest_buf, info->digest.data, dim_digest_size(info->digest.algo)); - seq_printf(m, "%d %s %s:%s %s %s\n", - info->pcr, + seq_printf(m, "%d %s %s %s:%s %s", + dim_rot_slot(), log_digest_buf, + DIM_TEMPLATE, dim_hash_name(info->digest.algo), digest_buf, - dim_measure_log_name(info), - dim_measure_log_type_to_name(info->type)); + dim_measure_log_name(info)); + + /* Print the log flag */ + if (info->type == LOC_MEASURE) + seq_printf(m, "\n"); + else + seq_printf(m, " %s\n", + dim_measure_log_type_to_name(info->type)); + return 0; } @@ -143,8 +211,8 @@ static int measure_log_create_name(const char *name_str, return 0; } -static int measure_log_create_info(char pcr, struct dim_digest *digest, - int flag, struct dim_measure_log **info) +static int measure_log_create_info(struct dim_digest *digest, int flag, + struct dim_measure_log **info) { int ret = 0; struct dim_measure_log *new = NULL; @@ -153,7 +221,6 @@ static int measure_log_create_info(char pcr, struct dim_digest *digest, if (new == NULL) return -ENOMEM; - new->pcr = pcr; new->type = flag; ret = dim_digest_copy(&new->digest, digest); if (ret < 0) { @@ -204,9 +271,7 @@ static int measure_log_add_info(struct dim_measure_log_tree *root, root->count++; write_unlock(&root->lock); - return root->tpm == NULL && root->pcr != 0 ? 0 : - dim_tpm_pcr_extend(root->tpm, root->pcr, - &info->log_digest); + return dim_rot_extend(&info->log_digest); } static bool measure_log_is_full(struct dim_measure_log_tree *root) @@ -233,7 +298,7 @@ int dim_measure_log_add(struct dim_measure_log_tree *root, if (measure_log_is_full(root)) return -ENOSPC; - ret = measure_log_create_info(root->pcr, digest, flag, &info); + ret = measure_log_create_info(digest, flag, &info); if (ret < 0) return ret; @@ -271,11 +336,27 @@ void dim_measure_log_destroy_tree(struct dim_measure_log_tree *root) write_unlock(&root->lock); } +static int calc_boot_aggregate(struct dim_measure_log_tree *root) +{ + int ret = 0; + struct dim_digest boot_aggregate = { + .algo = root->hash->algo, + }; + + ret = dim_calc_boot_aggregate(&boot_aggregate, root->hash); + if (ret < 0) + dim_warn("Failed to calculate boot_aggregate: %d\n", ret); + + ret = dim_measure_log_add(root, "boot_aggregate", + &boot_aggregate, LOC_MEASURE); + if (ret < 0) + dim_warn("Failed to add boot_aggregate log: %d\n", ret); + + return 0; +} + int dim_measure_log_init_tree(struct dim_measure_log_tree *root, - struct dim_hash *hash, - struct dim_tpm *tpm, - unsigned int cap, - unsigned int pcr) + struct dim_hash *hash, unsigned int cap) { if (root == NULL || hash == NULL) return -EINVAL; @@ -284,8 +365,7 @@ int dim_measure_log_init_tree(struct dim_measure_log_tree *root, INIT_LIST_HEAD(&root->list_root); root->hash = hash; root->rb_root = RB_ROOT; - root->pcr = pcr; - root->tpm = tpm; root->cap = cap; - return 0; + + return calc_boot_aggregate(root); } diff --git a/src/common/dim_measure_log.h b/src/common/dim_measure_log.h index 125de30dcc015ae0ae2549e165d7be0a0660aa18..a44326460db32fc4c6aab17da603ef7c330d8ce5 100644 --- a/src/common/dim_measure_log.h +++ b/src/common/dim_measure_log.h @@ -21,6 +21,7 @@ enum dim_measure_log_type { LOG_DYNAMIC_BASELINE, LOG_TAMPERED, LOG_MATCHED, + LOC_MEASURE, LOG_LAST, }; @@ -30,14 +31,13 @@ static const char *dim_measure_log_type_name[LOG_LAST] = { [LOG_DYNAMIC_BASELINE] = "[dynamic baseline]", [LOG_TAMPERED] = "[tampered]", [LOG_MATCHED] = "[matched]", + [LOC_MEASURE] = "" /* No extra flag, keep consistent with IMA */ }; struct dim_measure_log_tree { struct rb_root rb_root; /* rb tree root for searching measure log */ struct list_head list_root; /* list root for printing logs in order */ struct dim_hash *hash; /* algorithm for calculating log hash */ - struct dim_tpm *tpm; - unsigned int pcr; rwlock_t lock; unsigned int count; /* number of log */ unsigned int cap; /* capacity of log */ @@ -54,7 +54,6 @@ struct dim_measure_log { struct list_head node; struct list_head node_order; struct dim_measure_name *name_head; - char pcr; int type; /* enum log_type */ struct dim_digest digest; /* measure digest */ struct dim_digest log_digest; /* measure log digest */ @@ -92,13 +91,15 @@ static inline bool is_same_dim_measure_log(struct dim_measure_log *x, } int dim_measure_log_init_tree(struct dim_measure_log_tree *root, - struct dim_hash *hash, struct dim_tpm *tpm, - unsigned int cap, unsigned int pcr); + struct dim_hash *hash, unsigned int cap); void dim_measure_log_destroy_tree(struct dim_measure_log_tree *root); int dim_measure_log_add(struct dim_measure_log_tree *root, const char *name_str, struct dim_digest *digest, int flag); -int dim_measure_log_seq_show(struct seq_file *m, struct dim_measure_log *log); +int dim_measure_log_seq_show_ascii(struct seq_file *m, + struct dim_measure_log *log); +int dim_measure_log_seq_show_binary(struct seq_file *m, + struct dim_measure_log *info); void dim_measure_log_refresh(struct dim_measure_log_tree *root); #endif diff --git a/src/common/dim_rot.c b/src/common/dim_rot.c new file mode 100644 index 0000000000000000000000000000000000000000..76992e4954750a489e2032fc43f0879a6c9da2f0 --- /dev/null +++ b/src/common/dim_rot.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + */ + +#include "dim_utils.h" +#include "dim_rot.h" + +/* Selected RoT device */ +static struct dim_rot *dim_rot_prefered = NULL; + +/* Support list: TPM, virtCCA */ +static struct dim_rot *dim_supported_rots[] = { +#ifdef CONFIG_TCG_TPM + &dim_rot_tpm, +#endif +#ifdef CONFIG_HISI_VIRTCCA_GUEST + &dim_rot_virtcca, +#endif +}; + +int dim_rot_init(const char *name, int algo, int slot) +{ + int i = 0; + int ret = 0; + + if (name == NULL || name[0] == '\0') { + dim_info("No specified RoT device\n"); + return 0; + } + + if (DIM_ARRAY_LEN(dim_supported_rots) == 0) { + dim_info("No supported RoT device\n"); + return 0; + } + + for (i = 0; i < DIM_ARRAY_LEN(dim_supported_rots); i++) { + if (strcmp(name, dim_supported_rots[i]->name) == 0) { + dim_rot_prefered = dim_supported_rots[i]; + break; + } + } + + if (dim_rot_prefered == NULL) { + dim_info("Cannot find the specified RoT %s\n", + dim_rot_prefered->name); + return -ENODEV; + } + + ret = dim_rot_prefered->init(dim_rot_prefered, algo, slot); + if (ret < 0) { + dim_err("Failed to initialize RoT device %s: %d\n", + dim_rot_prefered->name, ret); + dim_rot_prefered = NULL; + } else { + dim_info("Initialize RoT device: %s\n", + dim_rot_prefered->name); + } + + return ret; +} + +int dim_rot_extend(struct dim_digest *digest) +{ + if (dim_rot_prefered == NULL) + return 0; + + return dim_rot_prefered->extend(dim_rot_prefered, digest); +} + +int dim_calc_boot_aggregate(struct dim_digest *digest, struct dim_hash *hash) +{ + if (dim_rot_prefered == NULL) + return -ENODEV; + + return dim_rot_prefered->calc_boot_aggregate(digest, hash); +} + +void dim_rot_destroy(void) +{ + if (dim_rot_prefered == NULL) + return; + + dim_rot_prefered->destroy(dim_rot_prefered); +} + +int dim_rot_slot(void) +{ + if (dim_rot_prefered == NULL) + return 0; + + return dim_rot_prefered->slot(dim_rot_prefered); +} \ No newline at end of file diff --git a/src/common/dim_rot.h b/src/common/dim_rot.h new file mode 100644 index 0000000000000000000000000000000000000000..f656ca913c40be29c98252e34b22e18c05347fd5 --- /dev/null +++ b/src/common/dim_rot.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + */ +#ifndef __DIM_ROT_H +#define __DIM_ROT_H + +#include "dim_hash.h" + +struct dim_rot { + const char *name; + + int (*init)(struct dim_rot *rot, int algo, int slot); + void (*destroy)(struct dim_rot *rot); + int (*slot)(struct dim_rot *rot); + int (*extend)(struct dim_rot *rot, struct dim_digest *digest); + int (*calc_boot_aggregate)(struct dim_digest *digest, + struct dim_hash *hash); +}; + +#ifdef CONFIG_TCG_TPM +extern struct dim_rot dim_rot_tpm; +#endif +#ifdef CONFIG_HISI_VIRTCCA_GUEST +extern struct dim_rot dim_rot_virtcca; +#endif + +int dim_rot_init(const char *name, int algo, int slot); +int dim_rot_extend(struct dim_digest *digest); +int dim_calc_boot_aggregate(struct dim_digest *digest, struct dim_hash *hash); +int dim_rot_slot(void); +void dim_rot_destroy(void); + +#endif \ No newline at end of file diff --git a/src/common/dim_rot_tpm.c b/src/common/dim_rot_tpm.c new file mode 100644 index 0000000000000000000000000000000000000000..8a84fd870e9ab80c052af4c3f4b26ed8b0c37e36 --- /dev/null +++ b/src/common/dim_rot_tpm.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + */ + +#ifdef CONFIG_TCG_TPM + +#include +#include + +#include "dim_rot.h" +#include "dim_safe_func.h" +#include "dim_utils.h" + +#define DIM_PCR_MAX 128 +enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR10 = 10 }; + +/* TPM chip instance */ +static struct tpm_chip *dim_tpm_chip = NULL; +/* Buffer for TPM digest extending */ +struct tpm_digest *dim_tpm_digests = NULL; +/* TPM algorithm bank */ +static int dim_tpm_bank = 0; +/* TPM pcr index */ +static unsigned int dim_tpm_pcr = 0; + +static int dim_tpm_init(struct dim_rot *rot, int algo, int pcr) +{ + int ret = 0; + int i = 0; + + dim_tpm_chip = tpm_default_chip(); + if (dim_tpm_chip == NULL) + return -ENODEV; + + dim_tpm_digests = dim_kcalloc_gfp(dim_tpm_chip->nr_allocated_banks, + sizeof(struct tpm_digest)); + if (dim_tpm_digests == NULL) { + ret = -ENOMEM; + goto err; + } + + dim_tpm_bank = -1; + for (i = 0; i < dim_tpm_chip->nr_allocated_banks; i++) { + dim_tpm_digests[i].alg_id = + dim_tpm_chip->allocated_banks[i].alg_id; + if (dim_tpm_chip->allocated_banks[i].crypto_id == algo) + dim_tpm_bank = i; + + memset(dim_tpm_digests[i].digest, 0xff, TPM_MAX_DIGEST_SIZE); + } + + if (dim_tpm_bank == -1) { + ret = -ENOENT; /* fail to find matched TPM bank */ + goto err; + } + + dim_tpm_pcr = pcr; + if (dim_tpm_pcr > DIM_PCR_MAX) + return -EINVAL; + + return 0; +err: + put_device(&dim_tpm_chip->dev); + if (dim_tpm_digests != NULL) { + dim_kfree(dim_tpm_digests); + dim_tpm_digests = NULL; + } + + dim_tpm_chip = NULL; + return ret; +} + +static int dim_tpm_extend(struct dim_rot *rot, struct dim_digest *digest) +{ + int size = 0; + + if (digest == NULL) + return -EINVAL; + + if (dim_tpm_chip == NULL) + return 0; + + size = dim_digest_size(digest->algo); + if (size == 0 || size > TPM_MAX_DIGEST_SIZE) + return -EINVAL; + + memcpy(dim_tpm_digests[dim_tpm_bank].digest, digest->data, size); + return tpm_pcr_extend(dim_tpm_chip, dim_tpm_pcr, dim_tpm_digests); +} + +static int dim_tpm_get_pcr(struct dim_rot *rot) +{ + if (dim_tpm_chip == NULL) + return 0; + + return dim_tpm_pcr; +} + +static void dim_tpm_destroy(struct dim_rot *rot) +{ + if (dim_tpm_chip == NULL) + return; + + put_device(&dim_tpm_chip->dev); + dim_kfree(dim_tpm_digests); + dim_tpm_chip = NULL; + dim_tpm_digests = NULL; +} + +static int tpm_hash_algo(int algo) +{ + int tpm_algo = -1; + + switch (algo) { + case HASH_ALGO_SHA256: + tpm_algo = TPM_ALG_SHA256; + break; + case HASH_ALGO_SM3_256: + tpm_algo = TPM_ALG_SM3_256; + break; + default: + break; + } + + return tpm_algo; +} + +static int dim_tpm_calc_boot_aggregate(struct dim_digest *digest, + struct dim_hash *hash) +{ + int ret = 0; + int i = 0; + struct tpm_digest d = { 0 }; + SHASH_DESC_ON_STACK(shash, hash->tfm); + + shash->tfm = hash->tfm; + ret = crypto_shash_init(shash); + if (ret < 0) + return ret; + + /* cumulative digest over TPM registers 0-10 */ + d.alg_id = tpm_hash_algo(digest->algo); + for (i = TPM_PCR0; i < TPM_PCR10; i++) { + ret = tpm_pcr_read(dim_tpm_chip, i, &d); + if (ret < 0) + return ret; + + ret = crypto_shash_update(shash, d.digest, + dim_digest_size(digest->algo)); + if (ret < 0) + return ret; + } + + return crypto_shash_final(shash, digest->data); +} + +struct dim_rot dim_rot_tpm = { + .name = "tpm", + .init = dim_tpm_init, + .destroy = dim_tpm_destroy, + .slot = dim_tpm_get_pcr, + .extend = dim_tpm_extend, + .calc_boot_aggregate = dim_tpm_calc_boot_aggregate, +}; + +#endif \ No newline at end of file diff --git a/src/common/dim_rot_virtcca.c b/src/common/dim_rot_virtcca.c new file mode 100644 index 0000000000000000000000000000000000000000..5076e0bbdff17840ec4aea779e57bed6a089c2c6 --- /dev/null +++ b/src/common/dim_rot_virtcca.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024. Huawei Technologies Co., Ltd. All rights reserved. + */ + +#ifdef CONFIG_HISI_VIRTCCA_GUEST + +#include +#include +#include + +#include "dim_utils.h" +#include "dim_hash.h" +#include "dim_rot.h" + +#define DIM_VIRTCCA_REM 4 + +/* Algorithm of virtCCA */ +static enum hash_algo virtcca_algo; +/* Enable flag of virtCCA */ +static int virtcca_enable = 0; +/* virtCCA REM index */ +static int virtcca_rem_idx = 0; + +static int dim_virtcca_init_algo(void) +{ + unsigned long result; + struct virtcca_cvm_config cfg = { 0 }; + + result = tsi_get_cvm_config(&cfg); + if (result != TSI_SUCCESS) { + pr_info("Error reading cvm config\n"); + return -EFAULT; + } + + /* 0: SHA256, 1: SHA512 */ + virtcca_algo = cfg.algorithm ? HASH_ALGO_SHA512 : + HASH_ALGO_SHA256; + return 0; +} + +static int dim_virtcca_init(struct dim_rot *rot, int algo, int rem) +{ + int ret = 0; + + if (!is_virtcca_cvm_world() || + tsi_get_version() == SMCCC_RET_NOT_SUPPORTED) + return -ENODEV; + + if (rem != DIM_VIRTCCA_REM) { + dim_warn("Now DIM can only use REM4, reset the REM index\n"); + virtcca_rem_idx = DIM_VIRTCCA_REM; + } + + ret = dim_virtcca_init_algo(); + if (ret < 0) + return ret; + + virtcca_enable = 1; + virtcca_rem_idx = rem; + return 0; +} + +static int dim_virtcca_get_rem(struct dim_rot *rot) +{ + if (virtcca_enable == 0) + return 0; + + return virtcca_rem_idx; +} + +static int dim_virtcca_extend(struct dim_rot *rot, struct dim_digest *digest) +{ + struct virtcca_cvm_measurement_extend cme = { 0 }; + + if (virtcca_enable == 0) + return 0; + + cme.index = virtcca_rem_idx; + cme.size = hash_digest_size[virtcca_algo]; + memcpy(cme.value, digest->data, dim_digest_size(digest->algo)); + + return tsi_measurement_extend(&cme) == TSI_SUCCESS ? 0 : -EFAULT; +} + +static int dim_virtcca_calc_boot_aggregate(struct dim_digest *digest, + struct dim_hash *hash) +{ + unsigned long result = 0; + struct virtcca_cvm_measurement cm = { + .index = RIM_MEASUREMENT_SLOT, + }; + + /* Read the measurement result of RIM as the boot aggregate */ + result = tsi_measurement_read(&cm); + if (result != TSI_SUCCESS) { + pr_err("Failed to read RIM 0 for boot aggregate\n"); + return -EFAULT; + } + + digest->algo = virtcca_algo; + memcpy(digest->data, cm.value, dim_digest_size(virtcca_algo)); + return 0; +} + +static void dim_virtcca_destroy(struct dim_rot *rot) +{ + return; +} + +struct dim_rot dim_rot_virtcca = { + .name = "virtcca", + .init = dim_virtcca_init, + .destroy = dim_virtcca_destroy, + .slot = dim_virtcca_get_rem, + .extend = dim_virtcca_extend, + .calc_boot_aggregate = dim_virtcca_calc_boot_aggregate, +}; + +#endif \ No newline at end of file diff --git a/src/common/dim_tpm.c b/src/common/dim_tpm.c deleted file mode 100644 index 35f3fac6236022ce70145e2288f5ac9390ed6342..0000000000000000000000000000000000000000 --- a/src/common/dim_tpm.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. - */ - -#include - -#include "dim_safe_func.h" -#include "dim_tpm.h" - -int dim_tpm_init(struct dim_tpm *tpm, int algo) -{ - int ret = 0; - int i = 0; - - tpm->chip = tpm_default_chip(); - if (tpm->chip == NULL) - return -ENODEV; - - tpm->digests = dim_kcalloc_gfp(tpm->chip->nr_allocated_banks, - sizeof(struct tpm_digest)); - if (tpm->digests == NULL) { - ret = -ENOMEM; - goto err; - } - - tpm->bank = -1; - for (i = 0; i < tpm->chip->nr_allocated_banks; i++) { - tpm->digests[i].alg_id = tpm->chip->allocated_banks[i].alg_id; - if (tpm->chip->allocated_banks[i].crypto_id == algo) - tpm->bank = i; - - memset(tpm->digests[i].digest, 0xff, TPM_MAX_DIGEST_SIZE); - } - - if (tpm->bank == -1) { - ret = -ENOENT; /* fail to find matched TPM bank */ - goto err; - } - - return 0; -err: - put_device(&tpm->chip->dev); - if (tpm->digests != NULL) { - dim_kfree(tpm->digests); - tpm->digests = NULL; - } - - tpm->chip = NULL; - return ret; -} - -int dim_tpm_pcr_extend(struct dim_tpm *tpm, int pcr, struct dim_digest *digest) -{ - int size = 0; - - if (tpm == NULL || digest == NULL) - return -EINVAL; - - if (tpm->chip == NULL) - return 0; - - size = dim_digest_size(digest->algo); - if (size == 0 || size > TPM_MAX_DIGEST_SIZE) - return -EINVAL; - - memcpy(tpm->digests[tpm->bank].digest, digest->data, size); - return tpm_pcr_extend(tpm->chip, pcr, tpm->digests); -} - -void dim_tpm_destroy(struct dim_tpm *tpm) -{ - if (tpm == NULL || tpm->chip == NULL) - return; - - put_device(&tpm->chip->dev); - dim_kfree(tpm->digests); - tpm->chip = NULL; - tpm->digests = NULL; -} diff --git a/src/common/dim_tpm.h b/src/common/dim_tpm.h deleted file mode 100644 index c4c715fa2d4dc2c8d47b66b5d2ab3710a2490ba8..0000000000000000000000000000000000000000 --- a/src/common/dim_tpm.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. - */ - -#ifndef __DIM_TPM_H -#define __DIM_TPM_H - -#include -#include "dim_hash.h" - -#define DIM_PCR_MAX 128 - -struct dim_tpm { - struct tpm_chip *chip; - struct tpm_digest *digests; - int bank; -}; - -int dim_tpm_init(struct dim_tpm *tpm, int algo); -int dim_tpm_pcr_extend(struct dim_tpm *tpm, int pcr, struct dim_digest *digest); -void dim_tpm_destroy(struct dim_tpm *tpm); - -#endif \ No newline at end of file diff --git a/src/common/dim_utils.c b/src/common/dim_utils.c index 6746d88b7e44445c048f8f618c12e2ea7f91b4c0..2f7f2fff879aacea6e3f4ed2f40bb731dbefd56d 100644 --- a/src/common/dim_utils.c +++ b/src/common/dim_utils.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "dim_safe_func.h" #include "dim_utils.h" @@ -100,3 +101,33 @@ out: return ret; } + +int dim_read_file(struct path *root, const char *name, void **buf) +{ + int ret = 0; + struct file *file = NULL; + + if (root == NULL) { + ret = kernel_read_file_from_path(name, 0, buf, + DIM_MAX_FILE_SIZE, + NULL, READING_UNKNOWN); +#ifdef DIM_DEBUG_MEMORY_LEAK + if (*buf != NULL) + dim_alloc_debug_inc(); +#endif + return ret; + } + + file = file_open_root(root, name, O_RDONLY, 0); + if (IS_ERR(file)) + return PTR_ERR(file); + + ret = kernel_read_file(file, 0, buf, DIM_MAX_FILE_SIZE, + NULL, READING_UNKNOWN); +#ifdef DIM_DEBUG_MEMORY_LEAK + if (*buf != NULL) + dim_alloc_debug_inc(); +#endif + (void)filp_close(file, NULL); + return ret; +} diff --git a/src/common/dim_utils.h b/src/common/dim_utils.h index db43546715f506cc09a7e4e4c4cb1fda09e2d301..00cec59a68ea72a2d6b77ab86a6f2c6dbbdab247 100644 --- a/src/common/dim_utils.h +++ b/src/common/dim_utils.h @@ -9,15 +9,24 @@ #include #define DIM_ARRAY_LEN(ARR) (sizeof(ARR) / sizeof(ARR[0])) +#define DIM_MAX_FILE_SIZE (10 * 1024 * 1024) -#define dim_fmt(fmt) "%s: " fmt +#define DIM_KERNEL "dim_kernel" + +#ifdef MODULE +#define DIM_FMT_FLAG (THIS_MODULE->name) +#else +#define DIM_FMT_FLAG DIM_KERNEL +#endif -#define dim_err(fmt, ...) pr_err(dim_fmt(fmt), THIS_MODULE->name, ##__VA_ARGS__) -#define dim_warn(fmt, ...) pr_warn(dim_fmt(fmt), THIS_MODULE->name, ##__VA_ARGS__) -#define dim_info(fmt, ...) pr_info(dim_fmt(fmt), THIS_MODULE->name, ##__VA_ARGS__) +#define dim_fmt(fmt) "%s: " fmt +#define dim_err(fmt, ...) pr_err(dim_fmt(fmt), DIM_FMT_FLAG, ##__VA_ARGS__) +#define dim_warn(fmt, ...) pr_warn(dim_fmt(fmt), DIM_FMT_FLAG, ##__VA_ARGS__) +#define dim_info(fmt, ...) pr_info(dim_fmt(fmt), DIM_FMT_FLAG, ##__VA_ARGS__) #define dim_devel(fmt, ...) int dim_get_absolute_path(const char *path, const char **result); int dim_parse_line_buf(char *buf, loff_t len, int (*line_parser)(char *, int, void *), void *data); +int dim_read_file(struct path *root, const char *name, void **buf); #endif diff --git a/src/core/dim_core_fs.c b/src/core/dim_core_fs.c index 4a82e53206fde0f076351f92c5a887a44f13e756..a6448c482513111cc94fbce3d7ec5b389ba66a5d 100644 --- a/src/core/dim_core_fs.c +++ b/src/core/dim_core_fs.c @@ -32,8 +32,21 @@ dim_trigger_entry(dim_baseline_init, baseline_init, * file entry name: runtime_status * status to read: dim_measure_log_tree */ -dim_measure_log_entry(dim_measure_log, ascii_runtime_measurements, - &dim_core_handle.log); +dim_measure_log_entry(dim_measure_log, + ascii_runtime_measurements, + &dim_core_handle.log, + ascii); + +/* + * binary measure log read interface + * dim_entry struct: dim_measure_log_entry + * file entry name: runtime_status + * status to read: dim_measure_log_tree + */ +dim_measure_log_entry(dim_measure_log_binary, + binary_runtime_measurements, + &dim_core_handle.log, + binary); /* * status print interface @@ -77,6 +90,7 @@ static struct dim_entry *dim_core_files[] = { &dim_measure_entry, &dim_baseline_init_entry, &dim_measure_log_entry, + &dim_measure_log_binary_entry, &dim_status_entry, &dim_interval_entry, &dim_tampered_action_entry, diff --git a/src/core/dim_core_main.c b/src/core/dim_core_main.c index d4cc870eefa21fa4c5aa7699c2cdfd84fcadab08..c54041e4dda763864e94bf361f115a288b7d5ee5 100644 --- a/src/core/dim_core_main.c +++ b/src/core/dim_core_main.c @@ -11,7 +11,9 @@ #include "dim_core_fs.h" #include "dim_core_measure.h" #include "dim_core_mem_pool.h" +#ifdef CONFIG_DIM_CORE_SIGNATURE_SUPPORT #include "dim_core_sig.h" +#endif /* common measurement configuration */ static struct dim_measure_cfg cfg = { @@ -19,27 +21,66 @@ static struct dim_measure_cfg cfg = { .log_cap = DIM_CORE_LOG_CAP_DEFAULT, }; +#ifdef MODULE module_param_named(measure_log_capacity, cfg.log_cap, uint, 0); MODULE_PARM_DESC(measure_log_capacity, "Max number of measure log"); +#else +core_param(dim_measure_log_capacity, cfg.log_cap, uint, 0); +#endif +#ifdef MODULE module_param_named(measure_schedule, cfg.schedule_ms, uint, 0); MODULE_PARM_DESC(measure_schedule, "Schedule time (ms) for each measure object"); +#else +core_param(dim_measure_schedule, cfg.schedule_ms, uint, 0); +#endif +#ifdef MODULE module_param_named(measure_hash, cfg.alg_name, charp, 0); MODULE_PARM_DESC(measure_hash, "Hash algorithm for measurement"); +#else +core_param(dim_measure_hash, cfg.alg_name, charp, 0); +#endif +#ifdef MODULE module_param_named(measure_pcr, cfg.pcr, uint, 0); MODULE_PARM_DESC(measure_pcr, "TPM PCR index to extend measure log"); +#else +core_param(dim_measure_pcr, cfg.pcr, uint, 0); +#endif + +#ifdef MODULE +module_param_named(measure_rot, cfg.rot, charp, 0); +MODULE_PARM_DESC(measure_rot, "Rot device to extend measure log"); +#else +core_param(dim_measure_rot, cfg.rot, charp, 0); +#endif + +#ifdef MODULE +module_param_named(measure_only, cfg.measure_only, bool, 0); +MODULE_PARM_DESC(measure_only, "Only do measurement, no verification"); +#else +core_param(dim_measure_only, cfg.measure_only, bool, 0); +#endif /* special measurement configuration for dim_core */ static unsigned int measure_interval = 0; -static bool signature = false; - +#ifdef MODULE module_param(measure_interval, uint, 0); MODULE_PARM_DESC(measure_interval, "Interval time (min) for automatic measurement"); +#else +core_param(dim_measure_interval, measure_interval, uint, 0); +#endif +#ifdef CONFIG_DIM_CORE_SIGNATURE_SUPPORT +static bool signature = false; + #ifdef MODULE module_param(signature, bool, 0); MODULE_PARM_DESC(signature, "Require signature for policy and static baseline"); + #else +core_param(dim_signature, signature, bool, 0); + #endif +#endif static int __init dim_core_init(void) { @@ -56,7 +97,7 @@ static int __init dim_core_init(void) dim_err("failed to initialize dim memory pool: %d\n", ret); goto err; } - +#ifdef CONFIG_DIM_CORE_SIGNATURE_SUPPORT if (signature) { ret = dim_core_sig_init(); if (ret < 0) { @@ -64,7 +105,7 @@ static int __init dim_core_init(void) goto err; } } - +#endif ret = dim_core_measure_init(&cfg, measure_interval); if (ret < 0) { dim_err("failed to initialize dim measurement: %d\n", ret); @@ -82,10 +123,10 @@ err: dim_core_destroy_fs(); dim_core_measure_destroy(); dim_mem_pool_destroy(); - +#ifdef CONFIG_DIM_CORE_SIGNATURE_SUPPORT if (signature) dim_core_sig_destroy(); - +#endif return ret; } @@ -94,9 +135,10 @@ static void __exit dim_core_exit(void) dim_core_destroy_fs(); dim_core_measure_destroy(); dim_mem_pool_destroy(); - +#ifdef CONFIG_DIM_CORE_SIGNATURE_SUPPORT if (signature) dim_core_sig_destroy(); +#endif #ifdef DIM_DEBUG_MEMORY_LEAK dim_check_memory_leak(); diff --git a/src/core/dim_core_measure.c b/src/core/dim_core_measure.c index caf767cc6e9abef830a8a983859dc764055b1676..60cedf7dde830b85e64d05800ed6d5549dedd406 100644 --- a/src/core/dim_core_measure.c +++ b/src/core/dim_core_measure.c @@ -14,7 +14,9 @@ static struct dim_measure_task *dim_core_tasks[] = { &dim_core_measure_task_user_text, &dim_core_measure_task_kernel_text, +#ifdef CONFIG_MODULES &dim_core_measure_task_module_text, +#endif }; /* the global measurement handle */ @@ -100,6 +102,10 @@ static int baseline_prepare(struct dim_measure *m) return ret; } + /* For measure_only mode, we only need to reload policy */ + if (m->measure_only) + return 0; + /* 2. clear dim baseline */ dim_baseline_destroy_tree(&m->static_baseline); dim_baseline_destroy_tree(&m->dynamic_baseline); @@ -157,6 +163,7 @@ int dim_core_measure_blocking(void) /* clean the running work */ flush_delayed_work(&dim_measure_work); cancel_delayed_work_sync(&dim_measure_work); + /* queue and flush measure work */ queue_delayed_work(dim_work_queue, &dim_measure_work, 0); flush_delayed_work(&dim_measure_work); diff --git a/src/core/dim_core_mem_pool.c b/src/core/dim_core_mem_pool.c index a9f017740a94b4160ec7f6b4d79d561aebb9d874..8575f8c5c9770e7223d6ec39344561252846d340 100644 --- a/src/core/dim_core_mem_pool.c +++ b/src/core/dim_core_mem_pool.c @@ -30,6 +30,7 @@ static int dim_mem_pool_expand(unsigned int order) ret = gen_pool_add(dim_pool, pages_addr, size, -1); if (ret < 0) { dim_err("failed to add pages to memory pool: %d\n", ret); + __free_pages(pages, order); return ret; } diff --git a/src/core/dim_core_sig.c b/src/core/dim_core_sig.c index 07e11d8cc9c9c016ddee58bf07a1cebd9ff42daf..643471e0f763dde534e9667de89107702abe0913 100644 --- a/src/core/dim_core_sig.c +++ b/src/core/dim_core_sig.c @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include #include "dim_hash.h" #include "dim_utils.h" @@ -35,35 +35,6 @@ static char *add_suffix(const char *str, const char *suffix) return buf; } -static int read_file_root(struct path *root, const char *name, void **buf) -{ - int ret = 0; - struct file *file = NULL; - - if (root == NULL) { - ret = kernel_read_file_from_path(name, 0, buf, - DIM_CORE_MAX_FILE_SIZE, - NULL, READING_UNKNOWN); -#ifdef DIM_DEBUG_MEMORY_LEAK - if (*buf != NULL) - dim_alloc_debug_inc(); -#endif - return ret; - } - - file = file_open_root(root, name, O_RDONLY, 0); - if (IS_ERR(file)) - return PTR_ERR(file); - - ret = kernel_read_file(file, 0, buf, DIM_CORE_MAX_FILE_SIZE, - NULL, READING_UNKNOWN); -#ifdef DIM_DEBUG_MEMORY_LEAK - if (*buf != NULL) - dim_alloc_debug_inc(); -#endif - (void)filp_close(file, NULL); - return ret; -} static int dim_core_sig_verify(const char *buf, loff_t buf_len, const char *sbuf, loff_t sbuf_len) @@ -108,7 +79,7 @@ int dim_read_verify_file(struct path *root, const char *name, void **buf) if (sig_name == NULL) return -ENOMEM; - ret = read_file_root(root, name, &file_buf); + ret = dim_read_file(root, name, &file_buf); if (ret < 0) goto out; @@ -118,7 +89,7 @@ int dim_read_verify_file(struct path *root, const char *name, void **buf) if (dim_core_key == NULL) goto out; /* no need to verify signature */ - ret = read_file_root(root, sig_name, &sig_buf); + ret = dim_read_file(root, sig_name, &sig_buf); if (ret < 0) goto out; @@ -154,7 +125,7 @@ int dim_core_sig_init(void) } ret = kernel_read_file_from_path(DIM_CORE_CERT_PATH, 0, &data, - DIM_CORE_MAX_FILE_SIZE, NULL, + DIM_MAX_FILE_SIZE, NULL, READING_X509_CERTIFICATE); if (ret < 0) { dim_err("failed to read DIM cert file: %ld\n", ret); diff --git a/src/core/dim_core_sig.h b/src/core/dim_core_sig.h index 45dd0bb2912f635c1501dcbe47b2c26972f578b7..cceed9fe8f2664e4a34ccff4c2cccf07653a25ed 100644 --- a/src/core/dim_core_sig.h +++ b/src/core/dim_core_sig.h @@ -7,7 +7,6 @@ #include -#define DIM_CORE_MAX_FILE_SIZE (10 * 1024 * 1024) #define DIM_CORE_KEYRING_NAME "_dim" #define DIM_CORE_CERT_PATH "/etc/keys/x509_dim.der" #define DIM_CORE_SIG_FILE_SUFFIX ".sig" diff --git a/src/core/dim_core_symbol.c b/src/core/dim_core_symbol.c index 97bb5fe439ef9250babaa6e665b83a7a51a8d2b7..5085e85d1fc350624943a15effa12d77ddc026ab 100644 --- a/src/core/dim_core_symbol.c +++ b/src/core/dim_core_symbol.c @@ -3,7 +3,9 @@ */ #include +#ifdef CONFIG_JUMP_LABEL #include +#endif #include "dim_symbol.h" #include "dim_utils.h" @@ -17,8 +19,7 @@ int dim_core_kallsyms_init(void) struct dim_core_kallsyms *k = &dim_core_kernel_symbol; DIM_SYMBOL_LOOKUP_FUNC dim_kallsyms_lookup_name = NULL; - if (memset(k, 0, - sizeof(struct dim_core_kallsyms)) != k) + if (memset(k, 0, sizeof(struct dim_core_kallsyms)) != k) return -EINVAL; dim_kallsyms_lookup_name = dim_get_symbol_lookup_func(); @@ -26,9 +27,11 @@ int dim_core_kallsyms_init(void) dim_err("failed to get symbol_lookup_func\n"); return -EINVAL; } + k->stext = (char *)dim_kallsyms_lookup_name("_stext"); k->etext = (char *)dim_kallsyms_lookup_name("_etext"); +#ifdef CONFIG_JUMP_LABEL k->start_jump_table = (struct jump_entry *) dim_kallsyms_lookup_name("__start___jump_table"); k->stop_jump_table = (struct jump_entry *) @@ -37,20 +40,30 @@ int dim_core_kallsyms_init(void) dim_kallsyms_lookup_name("jump_label_lock"); k->jump_label_unlock = (DIM_JUMP_LABEL_UNLOCK) dim_kallsyms_lookup_name("jump_label_unlock"); +#endif + k->walk_process_tree = (DIM_WALK_PROCESS_TREE) dim_kallsyms_lookup_name("walk_process_tree"); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) + #ifdef CONFIG_MODULES k->find_module = (DIM_FIND_MODULE) dim_kallsyms_lookup_name("find_module"); + #endif k->find_get_task_by_vpid = (DIM_FIND_GET_TASK_BY_VPID) dim_kallsyms_lookup_name("find_get_task_by_vpid"); #endif return (k->stext == NULL || k->etext == NULL || -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) - k->find_module == NULL || k->find_get_task_by_vpid == NULL || -#endif +#ifdef CONFIG_JUMP_LABEL k->start_jump_table == NULL || k->stop_jump_table == NULL || k->jump_label_lock == NULL || k->jump_label_unlock == NULL || +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) + #ifdef CONFIG_MODULES + k->find_module == NULL || + #endif + k->find_get_task_by_vpid == NULL || +#endif k->walk_process_tree == NULL) ? -ENOENT : 0; } diff --git a/src/core/dim_core_symbol.h b/src/core/dim_core_symbol.h index 5f3ee4b391a5a49399764e111555d9926e36c738..3ac0d2611f40d34702b0bb1439deeb5f5af47390 100644 --- a/src/core/dim_core_symbol.h +++ b/src/core/dim_core_symbol.h @@ -17,26 +17,32 @@ typedef void (*DIM_WALK_PROCESS_TREE)(struct task_struct *, typedef struct module *(*DIM_FIND_MODULE)(const char *); typedef struct task_struct *(*DIM_FIND_GET_TASK_BY_VPID)(pid_t); #endif -#ifndef JUMP_LABEL_NOP_SIZE + +#ifdef CONFIG_JUMP_LABEL + #ifndef JUMP_LABEL_NOP_SIZE typedef int (*DIM_ARCH_JUMP_ENTRY_SIZE)(struct jump_entry *); + #endif #endif - struct dim_core_kallsyms { char *stext; char *etext; +#ifdef CONFIG_JUMP_LABEL struct jump_entry *start_jump_table; struct jump_entry *stop_jump_table; DIM_JUMP_LABEL_LOCK jump_label_lock; DIM_JUMP_LABEL_LOCK jump_label_unlock; - DIM_WALK_PROCESS_TREE walk_process_tree; + #ifndef JUMP_LABEL_NOP_SIZE + DIM_ARCH_JUMP_ENTRY_SIZE arch_jump_entry_size; + #endif +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) + #ifdef CONFIG_MODULES DIM_FIND_MODULE find_module; + #endif DIM_FIND_GET_TASK_BY_VPID find_get_task_by_vpid; #endif -#ifndef JUMP_LABEL_NOP_SIZE - DIM_ARCH_JUMP_ENTRY_SIZE arch_jump_entry_size; -#endif + DIM_WALK_PROCESS_TREE walk_process_tree; }; extern struct dim_core_kallsyms dim_core_kernel_symbol; diff --git a/src/core/policy/dim_core_policy.c b/src/core/policy/dim_core_policy.c index e18aca72eb8e314772582a4ee7af7283c46a60a0..a72bd6a3de7980e2c44717e48654c58c295e401e 100644 --- a/src/core/policy/dim_core_policy.c +++ b/src/core/policy/dim_core_policy.c @@ -174,8 +174,11 @@ int dim_core_policy_load(void) if (!RB_EMPTY_ROOT(&policy_root)) dim_core_policy_destroy(); - +#ifdef CONFIG_DIM_CORE_SIGNATURE_SUPPORT ret = dim_read_verify_file(NULL, DIM_POLICY_PATH, &buf); +#else + ret = dim_read_file(NULL, DIM_POLICY_PATH, &buf); +#endif if (ret < 0 || buf == NULL) { dim_err("failed to read policy file: %d\n", ret); return ret; diff --git a/src/core/static_baseline/dim_core_static_baseline.c b/src/core/static_baseline/dim_core_static_baseline.c index 7ae5171620e6d65becb76ff3a0d9c1447f392da5..f723b3196c31332bcf6cd90116f4b316ea4b0dfc 100644 --- a/src/core/static_baseline/dim_core_static_baseline.c +++ b/src/core/static_baseline/dim_core_static_baseline.c @@ -147,7 +147,11 @@ int dim_core_static_baseline_load(struct dim_measure *m) filp_close(file, NULL); list_for_each_entry_safe(entry, tmp, &ctx.name_list, list) { +#ifdef CONFIG_DIM_CORE_SIGNATURE_SUPPORT ret = dim_read_verify_file(&kpath, entry->name, &buf); +#else + ret = dim_read_file(&kpath, entry->name, &buf); +#endif if (ret < 0 || buf == NULL) { dim_err("failed to read and verify %s: %d\n", entry->name, ret); dim_kfree(entry); diff --git a/src/core/tasks/dim_core_measure_kernel.c b/src/core/tasks/dim_core_measure_kernel.c index bb7fd74c86086f9293aa337ca632036e4aa0ccbe..502817c95acf9fc61168302d6c7b7c519384db86 100644 --- a/src/core/tasks/dim_core_measure_kernel.c +++ b/src/core/tasks/dim_core_measure_kernel.c @@ -3,11 +3,14 @@ */ #include -#include #include #include #include +#ifdef CONFIG_JUMP_LABEL +#include +#endif + #include "dim_measure.h" #include "dim_core_symbol.h" @@ -16,6 +19,8 @@ #include "dim_core_measure_task.h" +#ifdef CONFIG_JUMP_LABEL + /* max size of x86 */ #define DIM_JUMP_LABEL_NOP_SIZE_MAX 5 @@ -134,6 +139,22 @@ static int calc_kernel_digest(struct dim_hash *hash, struct dim_digest *digest) dim_vfree(jcode_sort); return ret; } +#else +/* If kernel doesn't support jumplabel, calculate text directly */ +static int calc_kernel_digest(struct dim_hash *hash, struct dim_digest *digest) +{ + uintptr_t stext = (uintptr_t)dim_core_kernel_symbol.stext; + uintptr_t etext = (uintptr_t)dim_core_kernel_symbol.etext; + SHASH_DESC_ON_STACK(shash, hash->tfm); + + shash->tfm = hash->tfm; + if (shash->tfm == NULL || stext >= etext) + return -EINVAL; + + return crypto_shash_digest(shash, (char *)stext, etext - stext, + digest->data); +} +#endif static int kernel_text_measure(int mode, struct dim_measure *m) { diff --git a/src/core/tasks/dim_core_measure_module.c b/src/core/tasks/dim_core_measure_module.c index 613e0e593873f0cf882830787947bd659ac291c0..d2554138b2681d0b86923adab4cff3eea6000d30 100644 --- a/src/core/tasks/dim_core_measure_module.c +++ b/src/core/tasks/dim_core_measure_module.c @@ -1,6 +1,7 @@ /* * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. */ +#ifdef CONFIG_MODULES #include #include @@ -114,3 +115,5 @@ struct dim_measure_task dim_core_measure_task_module_text = { .destroy = NULL, .measure = module_text_measure, }; + +#endif diff --git a/src/core/tasks/dim_core_measure_process/dim_core_measure_process.c b/src/core/tasks/dim_core_measure_process/dim_core_measure_process.c index 5efbeb455fd510f684cdb493c38cc135fc99b6c9..f28c0f9c02fdde989ecfdd647f5cc25627334caa 100644 --- a/src/core/tasks/dim_core_measure_process/dim_core_measure_process.c +++ b/src/core/tasks/dim_core_measure_process/dim_core_measure_process.c @@ -82,7 +82,7 @@ static bool vm_file_match_policy(struct file *vm_file, return false; } - if (ctx->mode == DIM_BASELINE) + if (ctx->mode == DIM_BASELINE || ctx->m->measure_only) return dim_core_policy_match(DIM_POLICY_OBJ_BPRM_TEXT, DIM_POLICY_KEY_PATH, ctx->path); diff --git a/src/measure/dim_measure.c b/src/measure/dim_measure.c index c40be0e5d33e3c80a648e32fea4417597df6d2e2..9b0a21348c2b0d4c093d7b56e78b4f2bd9d493e5 100644 --- a/src/measure/dim_measure.c +++ b/src/measure/dim_measure.c @@ -17,11 +17,6 @@ static int cfg_check(struct dim_measure_cfg *cfg) return -ERANGE; } - if (cfg->pcr > DIM_PCR_MAX) { - dim_err("invalid TPM pcr number: %d\n", cfg->pcr); - return -ERANGE; - } - return 0; } @@ -41,35 +36,32 @@ int dim_measure_init(struct dim_measure *m, struct dim_measure_cfg *cfg) goto err; } - /* 2. init TPM, dont break if init fail */ - if (cfg->pcr > 0) { - ret = dim_tpm_init(&m->tpm, HASH_ALGO_SHA256); - if (ret < 0) { - cfg->pcr = 0; - dim_warn("failed to init tpm chip: %d\n", ret); - } - } else { - memset(&m->tpm, 0, sizeof(struct dim_tpm)); - } + /* 2. init RoT, dont break if init fail */ + ret = dim_rot_init(cfg->rot, HASH_ALGO_SHA256, cfg->pcr); + if (ret < 0) + dim_warn("failed to init RoT device: %d\n", ret); /* 3. init baseline data (static and dynamic) */ - ret = dim_baseline_init_tree(cfg->sta_malloc, cfg->sta_free, - &m->static_baseline); - if (ret < 0) { - dim_err("failed to init static baseline root: %d\n", ret); - goto err; - } + m->measure_only = cfg->measure_only; + /* for measure_only mode, no need to process baseline data */ + if (!m->measure_only) { + ret = dim_baseline_init_tree(cfg->sta_malloc, cfg->sta_free, + &m->static_baseline); + if (ret < 0) { + dim_err("failed to init static baseline: %d\n", ret); + goto err; + } - ret = dim_baseline_init_tree(cfg->dyn_malloc, cfg->dyn_free, - &m->dynamic_baseline); - if (ret < 0) { - dim_err("failed to init dynamic baseline root: %d\n", ret); - goto err; + ret = dim_baseline_init_tree(cfg->dyn_malloc, cfg->dyn_free, + &m->dynamic_baseline); + if (ret < 0) { + dim_err("failed to init dynamic baseline: %d\n", ret); + goto err; + } } /* 4. init measure log */ - ret = dim_measure_log_init_tree(&m->log, &m->hash, &m->tpm, - cfg->log_cap, cfg->pcr); + ret = dim_measure_log_init_tree(&m->log, &m->hash, cfg->log_cap); if (ret < 0) { dim_err("failed to init measure log: %d\n", ret); goto err; @@ -81,6 +73,7 @@ int dim_measure_init(struct dim_measure *m, struct dim_measure_cfg *cfg) /* 6. set initial status */ atomic_set(&m->status, MEASURE_STATUS_NO_BASELINE); + return 0; err: dim_measure_destroy(m); @@ -97,7 +90,7 @@ void dim_measure_destroy(struct dim_measure *m) dim_measure_log_destroy_tree(&m->log); dim_baseline_destroy_tree(&m->static_baseline); dim_baseline_destroy_tree(&m->dynamic_baseline); - dim_tpm_destroy(&m->tpm); + dim_rot_destroy(); dim_hash_destroy(&m->hash); mutex_unlock(&m->measure_lock); } diff --git a/src/measure/dim_measure.h b/src/measure/dim_measure.h index f5140f03721cb186ee66ed54d02bb405ae0451bf..d614f12bccd88441c95578d223bb76bdaa7f2d4b 100644 --- a/src/measure/dim_measure.h +++ b/src/measure/dim_measure.h @@ -11,7 +11,7 @@ #include "dim_baseline.h" #include "dim_hash.h" #include "dim_measure_log.h" -#include "dim_tpm.h" +#include "dim_rot.h" #include "dim_utils.h" #define DIM_MEASURE 0 @@ -35,12 +35,16 @@ enum dim_measure_status { /* the common configuration for measurement */ struct dim_measure_cfg { + /* no baseline, only measure */ + bool measure_only; /* hash algorithm for measurement */ char *alg_name; /* schedule time (ms) after one valid measurement */ unsigned int schedule_ms; /* PCR number for TPM extending */ unsigned int pcr; + /* device to extend measure log */ + char *rot; /* max measure log number */ unsigned int log_cap; /* memory function for baseline store */ @@ -52,14 +56,14 @@ struct dim_measure_cfg { /* the dim measurement global handle */ struct dim_measure { + /* no baseline, only measure */ + bool measure_only; /* schedule time (jittfies) after one valid measurement */ unsigned long schedule_jiffies; /* lock to prevent concurrent measurement */ struct mutex measure_lock; /* measure hash algorithm */ struct dim_hash hash; - /* TPM chip handle */ - struct dim_tpm tpm; /* measure log */ struct dim_measure_log_tree log; /* measure baseline */ diff --git a/src/measure/dim_measure_baseline.c b/src/measure/dim_measure_baseline.c index 0b2c9ff0f6df3ba1b903cc79949bbe82c0077a5b..195fd5a86b5c29c4bda7126ca7ae858cb56d0ceb 100644 --- a/src/measure/dim_measure_baseline.c +++ b/src/measure/dim_measure_baseline.c @@ -196,6 +196,12 @@ int dim_measure_process_static_result(struct dim_measure *m, int mode, !is_valid_mode(mode)) return -EINVAL; + /* For measure only mode, add measure log directly */ + if (m->measure_only) { + *log_flag = LOC_MEASURE; + return measure_log_add(m, name, digest, LOC_MEASURE); + } + return mode == DIM_BASELINE ? process_static_baseline(m, name, digest, log_flag) : process_static_measure(m, name, digest, log_flag); @@ -210,6 +216,10 @@ int dim_measure_process_dynamic_result(struct dim_measure *m, int mode, !is_valid_mode(mode)) return -EINVAL; + /* For measure only mode, add measure log directly */ + if (m->measure_only) + return measure_log_add(m, name, digest, LOC_MEASURE); + return mode == DIM_BASELINE ? process_dynamic_baseline(m, name, digest, log_flag) : process_dynamic_measure(m, name, digest, log_flag); diff --git a/src/measure/dim_measure_task.c b/src/measure/dim_measure_task.c index adfc57d8a91b8636e4c362974d0d9633727a3467..50486e5062f66a529f3e69079fb577eae91a87eb 100644 --- a/src/measure/dim_measure_task.c +++ b/src/measure/dim_measure_task.c @@ -9,10 +9,8 @@ static void call_measure_func(int mode, struct dim_measure_task *t, { int ret = 0; - if (t->measure == NULL) { - dim_warn("no measure function in %s task", t->name); + if (t->measure == NULL) return; - } dim_info("start to call %s measure task\n", t->name); ret = t->measure(mode, m); @@ -44,7 +42,7 @@ void dim_measure_task_measure(int mode, struct dim_measure *m) MEASURE_STATUS_BASELINE_RUNNING : MEASURE_STATUS_MEASURE_RUNNING); - if (mode == DIM_BASELINE && m->baseline_prepare != NULL) { + if (mode == DIM_BASELINE) { ret = m->baseline_prepare(m); if (ret < 0) { atomic_set(&m->status, MEASURE_STATUS_ERROR); diff --git a/src/measure/dim_measure_utils.c b/src/measure/dim_measure_utils.c index 049d36241190733e54743a433a6958a383f88c33..1faa8d85cbbe1cea53ebbe7b6ba95bb22ad423ec 100644 --- a/src/measure/dim_measure_utils.c +++ b/src/measure/dim_measure_utils.c @@ -2,6 +2,8 @@ * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. */ +#include + #include "dim_measure.h" void dim_measure_schedule(struct dim_measure *m) diff --git a/src/monitor/dim_monitor_fs.c b/src/monitor/dim_monitor_fs.c index 8bb3120c58fb61b1f1c199c41ed6fb192da683ea..383a565f2facacb37d29d5dc93f80ebfe363fe49 100644 --- a/src/monitor/dim_monitor_fs.c +++ b/src/monitor/dim_monitor_fs.c @@ -44,7 +44,7 @@ dim_string_print_entry(dim_monitor_status, monitor_status, dim_monitor_status_pr * status to read: dim_measure_log_tree */ dim_measure_log_entry(dim_monitor_log, monitor_ascii_runtime_measurements, - &dim_monitor_handle.log); + &dim_monitor_handle.log, ascii); static struct dim_entry *dim_monitor_files[] = { &dim_monitor_measure_entry, diff --git a/src/monitor/dim_monitor_main.c b/src/monitor/dim_monitor_main.c index d0e89f13daf9a462d42c591d53a5bc809c027f95..6a78934d46f43ab50d7360e5fa07292dc6cf6de7 100644 --- a/src/monitor/dim_monitor_main.c +++ b/src/monitor/dim_monitor_main.c @@ -24,6 +24,9 @@ MODULE_PARM_DESC(measure_hash, "Hash algorithm for measurement"); module_param_named(measure_pcr, cfg.pcr, uint, 0); MODULE_PARM_DESC(measure_pcr, "TPM PCR index to extend measure log"); +module_param_named(measure_rot, cfg.rot, charp, 0); +MODULE_PARM_DESC(measure_rot, "Rot device to extend measure log"); + static int __init dim_monitor_init(void) { int ret;