1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2024-2005 Intel Corporation. All rights reserved. */
#define pr_fmt(x) KBUILD_MODNAME ": " x
#include <linux/module.h>
#include <linux/tsm-mr.h>
#include <linux/miscdevice.h>
#include <crypto/hash.h>
static struct {
u8 static_mr[SHA384_DIGEST_SIZE];
u8 config_mr[SHA512_DIGEST_SIZE];
u8 rtmr0[SHA256_DIGEST_SIZE];
u8 rtmr1[SHA384_DIGEST_SIZE];
u8 report_digest[SHA512_DIGEST_SIZE];
} sample_report = {
.static_mr = "static_mr",
.config_mr = "config_mr",
.rtmr0 = "rtmr0",
.rtmr1 = "rtmr1",
};
static int sample_report_refresh(const struct tsm_measurements *tm)
{
struct crypto_shash *tfm;
int rc;
tfm = crypto_alloc_shash(hash_algo_name[HASH_ALGO_SHA512], 0, 0);
if (IS_ERR(tfm)) {
pr_err("crypto_alloc_shash failed: %ld\n", PTR_ERR(tfm));
return PTR_ERR(tfm);
}
rc = crypto_shash_tfm_digest(tfm, (u8 *)&sample_report,
offsetof(typeof(sample_report),
report_digest),
sample_report.report_digest);
crypto_free_shash(tfm);
if (rc)
pr_err("crypto_shash_tfm_digest failed: %d\n", rc);
return rc;
}
static int sample_report_extend_mr(const struct tsm_measurements *tm,
const struct tsm_measurement_register *mr,
const u8 *data)
{
SHASH_DESC_ON_STACK(desc, 0);
int rc;
desc->tfm = crypto_alloc_shash(hash_algo_name[mr->mr_hash], 0, 0);
if (IS_ERR(desc->tfm)) {
pr_err("crypto_alloc_shash failed: %ld\n", PTR_ERR(desc->tfm));
return PTR_ERR(desc->tfm);
}
rc = crypto_shash_init(desc);
if (!rc)
rc = crypto_shash_update(desc, mr->mr_value, mr->mr_size);
if (!rc)
rc = crypto_shash_finup(desc, data, mr->mr_size, mr->mr_value);
crypto_free_shash(desc->tfm);
if (rc)
pr_err("SHA calculation failed: %d\n", rc);
return rc;
}
#define MR_(mr, hash) .mr_value = &sample_report.mr, TSM_MR_(mr, hash)
static const struct tsm_measurement_register sample_mrs[] = {
/* static MR, read-only */
{ MR_(static_mr, SHA384) },
/* config MR, read-only */
{ MR_(config_mr, SHA512) | TSM_MR_F_NOHASH },
/* RTMR, direct extension prohibited */
{ MR_(rtmr0, SHA256) | TSM_MR_F_LIVE },
/* RTMR, direct extension allowed */
{ MR_(rtmr1, SHA384) | TSM_MR_F_RTMR },
/* RTMR, crypto agile, alaised to rtmr0 and rtmr1, respectively */
{ .mr_value = &sample_report.rtmr0,
TSM_MR_(rtmr_crypto_agile, SHA256) | TSM_MR_F_RTMR },
{ .mr_value = &sample_report.rtmr1,
TSM_MR_(rtmr_crypto_agile, SHA384) | TSM_MR_F_RTMR },
/* sha512 digest of the whole structure */
{ MR_(report_digest, SHA512) | TSM_MR_F_LIVE },
};
#undef MR_
static struct tsm_measurements sample_tm = {
.mrs = sample_mrs,
.nr_mrs = ARRAY_SIZE(sample_mrs),
.refresh = sample_report_refresh,
.write = sample_report_extend_mr,
};
static const struct attribute_group *sample_groups[] = {
NULL,
NULL,
};
static struct miscdevice sample_misc_dev = {
.name = KBUILD_MODNAME,
.minor = MISC_DYNAMIC_MINOR,
.groups = sample_groups,
};
static int __init tsm_mr_sample_init(void)
{
int rc;
sample_groups[0] = tsm_mr_create_attribute_group(&sample_tm);
if (IS_ERR(sample_groups[0]))
return PTR_ERR(sample_groups[0]);
rc = misc_register(&sample_misc_dev);
if (rc)
tsm_mr_free_attribute_group(sample_groups[0]);
return rc;
}
static void __exit tsm_mr_sample_exit(void)
{
misc_deregister(&sample_misc_dev);
tsm_mr_free_attribute_group(sample_groups[0]);
}
module_init(tsm_mr_sample_init);
module_exit(tsm_mr_sample_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Sample module using tsm-mr to expose emulated MRs");
|