mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 23:32:14 +00:00
TPM: integrity interface
This patch adds internal kernel support for: - reading/extending a pcr value - looking up the tpm_chip for a given chip number Signed-off-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com> Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
0883743825
commit
659aaf2bb5
3 changed files with 163 additions and 19 deletions
|
@ -661,28 +661,125 @@ ssize_t tpm_show_temp_deactivated(struct device * dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
|
EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
|
||||||
|
|
||||||
static const u8 pcrread[] = {
|
/*
|
||||||
0, 193, /* TPM_TAG_RQU_COMMAND */
|
* tpm_chip_find_get - return tpm_chip for given chip number
|
||||||
0, 0, 0, 14, /* length */
|
*/
|
||||||
0, 0, 0, 21, /* TPM_ORD_PcrRead */
|
static struct tpm_chip *tpm_chip_find_get(int chip_num)
|
||||||
0, 0, 0, 0 /* PCR index */
|
{
|
||||||
|
struct tpm_chip *pos;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
|
||||||
|
if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (try_module_get(pos->dev->driver->owner))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TPM_ORDINAL_PCRREAD cpu_to_be32(21)
|
||||||
|
#define READ_PCR_RESULT_SIZE 30
|
||||||
|
static struct tpm_input_header pcrread_header = {
|
||||||
|
.tag = TPM_TAG_RQU_COMMAND,
|
||||||
|
.length = cpu_to_be32(14),
|
||||||
|
.ordinal = TPM_ORDINAL_PCRREAD
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct tpm_cmd_t cmd;
|
||||||
|
|
||||||
|
cmd.header.in = pcrread_header;
|
||||||
|
cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
|
||||||
|
BUILD_BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE);
|
||||||
|
rc = transmit_cmd(chip, &cmd, cmd.header.in.length,
|
||||||
|
"attempting to read a pcr value");
|
||||||
|
|
||||||
|
if (rc == 0)
|
||||||
|
memcpy(res_buf, cmd.params.pcrread_out.pcr_result,
|
||||||
|
TPM_DIGEST_SIZE);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_pcr_read - read a pcr value
|
||||||
|
* @chip_num: tpm idx # or ANY
|
||||||
|
* @pcr_idx: pcr idx to retrieve
|
||||||
|
* @res_buf: TPM_PCR value
|
||||||
|
* size of res_buf is 20 bytes (or NULL if you don't care)
|
||||||
|
*
|
||||||
|
* The TPM driver should be built-in, but for whatever reason it
|
||||||
|
* isn't, protect against the chip disappearing, by incrementing
|
||||||
|
* the module usage count.
|
||||||
|
*/
|
||||||
|
int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
|
||||||
|
{
|
||||||
|
struct tpm_chip *chip;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
chip = tpm_chip_find_get(chip_num);
|
||||||
|
if (chip == NULL)
|
||||||
|
return -ENODEV;
|
||||||
|
rc = __tpm_pcr_read(chip, pcr_idx, res_buf);
|
||||||
|
module_put(chip->dev->driver->owner);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tpm_pcr_read);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tpm_pcr_extend - extend pcr value with hash
|
||||||
|
* @chip_num: tpm idx # or AN&
|
||||||
|
* @pcr_idx: pcr idx to extend
|
||||||
|
* @hash: hash value used to extend pcr value
|
||||||
|
*
|
||||||
|
* The TPM driver should be built-in, but for whatever reason it
|
||||||
|
* isn't, protect against the chip disappearing, by incrementing
|
||||||
|
* the module usage count.
|
||||||
|
*/
|
||||||
|
#define TPM_ORD_PCR_EXTEND cpu_to_be32(20)
|
||||||
|
#define EXTEND_PCR_SIZE 34
|
||||||
|
static struct tpm_input_header pcrextend_header = {
|
||||||
|
.tag = TPM_TAG_RQU_COMMAND,
|
||||||
|
.length = cpu_to_be32(34),
|
||||||
|
.ordinal = TPM_ORD_PCR_EXTEND
|
||||||
|
};
|
||||||
|
|
||||||
|
int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
|
||||||
|
{
|
||||||
|
struct tpm_cmd_t cmd;
|
||||||
|
int rc;
|
||||||
|
struct tpm_chip *chip;
|
||||||
|
|
||||||
|
chip = tpm_chip_find_get(chip_num);
|
||||||
|
if (chip == NULL)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
cmd.header.in = pcrextend_header;
|
||||||
|
BUILD_BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE);
|
||||||
|
cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
|
||||||
|
memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
|
||||||
|
rc = transmit_cmd(chip, &cmd, cmd.header.in.length,
|
||||||
|
"attempting extend a PCR value");
|
||||||
|
|
||||||
|
module_put(chip->dev->driver->owner);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tpm_pcr_extend);
|
||||||
|
|
||||||
ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
|
ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
cap_t cap;
|
cap_t cap;
|
||||||
u8 *data;
|
u8 digest[TPM_DIGEST_SIZE];
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
int i, j, num_pcrs;
|
int i, j, num_pcrs;
|
||||||
__be32 index;
|
|
||||||
char *str = buf;
|
char *str = buf;
|
||||||
struct tpm_chip *chip = dev_get_drvdata(dev);
|
struct tpm_chip *chip = dev_get_drvdata(dev);
|
||||||
|
|
||||||
data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL);
|
|
||||||
if (!data)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap,
|
rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap,
|
||||||
"attempting to determine the number of PCRS");
|
"attempting to determine the number of PCRS");
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -690,20 +787,14 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
|
||||||
|
|
||||||
num_pcrs = be32_to_cpu(cap.num_pcrs);
|
num_pcrs = be32_to_cpu(cap.num_pcrs);
|
||||||
for (i = 0; i < num_pcrs; i++) {
|
for (i = 0; i < num_pcrs; i++) {
|
||||||
memcpy(data, pcrread, sizeof(pcrread));
|
rc = __tpm_pcr_read(chip, i, digest);
|
||||||
index = cpu_to_be32(i);
|
|
||||||
memcpy(data + 10, &index, 4);
|
|
||||||
rc = transmit_cmd(chip, (struct tpm_cmd_t *)data,
|
|
||||||
TPM_INTERNAL_RESULT_SIZE,
|
|
||||||
"attempting to read a PCR");
|
|
||||||
if (rc)
|
if (rc)
|
||||||
break;
|
break;
|
||||||
str += sprintf(str, "PCR-%02d: ", i);
|
str += sprintf(str, "PCR-%02d: ", i);
|
||||||
for (j = 0; j < TPM_DIGEST_SIZE; j++)
|
for (j = 0; j < TPM_DIGEST_SIZE; j++)
|
||||||
str += sprintf(str, "%02X ", *(data + 10 + j));
|
str += sprintf(str, "%02X ", digest[j]);
|
||||||
str += sprintf(str, "\n");
|
str += sprintf(str, "\n");
|
||||||
}
|
}
|
||||||
kfree(data);
|
|
||||||
return str - buf;
|
return str - buf;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tpm_show_pcrs);
|
EXPORT_SYMBOL_GPL(tpm_show_pcrs);
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/tpm.h>
|
||||||
|
|
||||||
enum tpm_timeout {
|
enum tpm_timeout {
|
||||||
TPM_TIMEOUT = 5, /* msecs */
|
TPM_TIMEOUT = 5, /* msecs */
|
||||||
|
@ -234,11 +235,28 @@ typedef union {
|
||||||
struct tpm_output_header out;
|
struct tpm_output_header out;
|
||||||
} tpm_cmd_header;
|
} tpm_cmd_header;
|
||||||
|
|
||||||
|
#define TPM_DIGEST_SIZE 20
|
||||||
|
struct tpm_pcrread_out {
|
||||||
|
u8 pcr_result[TPM_DIGEST_SIZE];
|
||||||
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
struct tpm_pcrread_in {
|
||||||
|
__be32 pcr_idx;
|
||||||
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
struct tpm_pcrextend_in {
|
||||||
|
__be32 pcr_idx;
|
||||||
|
u8 hash[TPM_DIGEST_SIZE];
|
||||||
|
}__attribute__((packed));
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
struct tpm_getcap_params_out getcap_out;
|
struct tpm_getcap_params_out getcap_out;
|
||||||
struct tpm_readpubek_params_out readpubek_out;
|
struct tpm_readpubek_params_out readpubek_out;
|
||||||
u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
|
u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
|
||||||
struct tpm_getcap_params_in getcap_in;
|
struct tpm_getcap_params_in getcap_in;
|
||||||
|
struct tpm_pcrread_in pcrread_in;
|
||||||
|
struct tpm_pcrread_out pcrread_out;
|
||||||
|
struct tpm_pcrextend_in pcrextend_in;
|
||||||
} tpm_cmd_params;
|
} tpm_cmd_params;
|
||||||
|
|
||||||
struct tpm_cmd_t {
|
struct tpm_cmd_t {
|
||||||
|
|
35
include/linux/tpm.h
Normal file
35
include/linux/tpm.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2004,2007,2008 IBM Corporation
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Leendert van Doorn <leendert@watson.ibm.com>
|
||||||
|
* Dave Safford <safford@watson.ibm.com>
|
||||||
|
* Reiner Sailer <sailer@watson.ibm.com>
|
||||||
|
* Kylene Hall <kjhall@us.ibm.com>
|
||||||
|
* Debora Velarde <dvelarde@us.ibm.com>
|
||||||
|
*
|
||||||
|
* Maintained by: <tpmdd_devel@lists.sourceforge.net>
|
||||||
|
*
|
||||||
|
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||||
|
* Specifications at www.trustedcomputinggroup.org
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation, version 2 of the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef __LINUX_TPM_H__
|
||||||
|
#define __LINUX_TPM_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chip num is this value or a valid tpm idx
|
||||||
|
*/
|
||||||
|
#define TPM_ANY_NUM 0xFFFF
|
||||||
|
|
||||||
|
#if defined(CONFIG_TCG_TPM)
|
||||||
|
|
||||||
|
extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
|
||||||
|
extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
|
||||||
|
#endif
|
||||||
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue