Hi,
Contents: - Restrict linking of keys to .ima and .evm keyrings based on digitalSignature attribute in the certificate. - PowerVM: load machine owner keys into the .machine [1] keyring. - PowerVM: load module signing keys into the secondary trusted keyring (keys blessed by the vendor). - tpm_tis_spi: half-duplex transfer mode - tpm_tis: retry corrupted transfers - Apply revocation list (.mokx) to an all system keyrings (e.g. .machine keyring). [1] https://blogs.oracle.com/linux/post/the-machine-keyring BR, Jarkko -----BEGIN PGP SIGNATURE----- iIgEABYIADAWIQRE6pSOnaBC00OEHEIaerohdGur0gUCZN5/qBIcamFya2tvQGtl cm5lbC5vcmcACgkQGnq6IXRrq9J4GQEAstTtQfGGrx5KInOTMWOvaq/Cum5iW4AD NefVfbUtCCQBANvFtxoPYQS5u6+rIdxzIwFiNUlOyt2uR2bkk4UUiPML =Vvs8 -----END PGP SIGNATURE----- Merge tag 'tpmdd-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd Pull tpm updates from Jarkko Sakkinen: - Restrict linking of keys to .ima and .evm keyrings based on digitalSignature attribute in the certificate - PowerVM: load machine owner keys into the .machine [1] keyring - PowerVM: load module signing keys into the secondary trusted keyring (keys blessed by the vendor) - tpm_tis_spi: half-duplex transfer mode - tpm_tis: retry corrupted transfers - Apply revocation list (.mokx) to an all system keyrings (e.g. .machine keyring) Link: https://blogs.oracle.com/linux/post/the-machine-keyring [1] * tag 'tpmdd-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd: certs: Reference revocation list for all keyrings tpm/tpm_tis_synquacer: Use module_platform_driver macro to simplify the code tpm: remove redundant variable len tpm_tis: Resend command to recover from data transfer errors tpm_tis: Use responseRetry to recover from data transfer errors tpm_tis: Move CRC check to generic send routine tpm_tis_spi: Add hardware wait polling KEYS: Replace all non-returning strlcpy with strscpy integrity: PowerVM support for loading third party code signing keys integrity: PowerVM machine keyring enablement integrity: check whether imputed trust is enabled integrity: remove global variable from machine_keyring.c integrity: ignore keys failing CA restrictions on non-UEFI platform integrity: PowerVM support for loading CA keys on machine keyring integrity: Enforce digitalSignature usage in the ima and evm keyrings KEYS: DigitalSignature link restriction tpm_tis: Revert "tpm_tis: Disable interrupts on ThinkPad T490s"
This commit is contained in:
commit
f2586d921c
@ -6394,6 +6394,13 @@
|
||||
This will guarantee that all the other pcrs
|
||||
are saved.
|
||||
|
||||
tpm_tis.interrupts= [HW,TPM]
|
||||
Enable interrupts for the MMIO based physical layer
|
||||
for the FIFO interface. By default it is set to false
|
||||
(0). For more information about TPM hardware interfaces
|
||||
defined by Trusted Computing Group (TCG) see
|
||||
https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
|
||||
|
||||
tp_printk [FTRACE]
|
||||
Have the tracepoints sent to printk as well as the
|
||||
tracing ring buffer. This is useful for early boot up
|
||||
|
@ -51,6 +51,26 @@ int restrict_link_by_builtin_trusted(struct key *dest_keyring,
|
||||
builtin_trusted_keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* restrict_link_by_digsig_builtin - Restrict digitalSignature key additions by the built-in keyring
|
||||
* @dest_keyring: Keyring being linked to.
|
||||
* @type: The type of key being added.
|
||||
* @payload: The payload of the new key.
|
||||
* @restriction_key: A ring of keys that can be used to vouch for the new cert.
|
||||
*
|
||||
* Restrict the addition of keys into a keyring based on the key-to-be-added
|
||||
* being vouched for by a key in the built in system keyring. The new key
|
||||
* must have the digitalSignature usage field set.
|
||||
*/
|
||||
int restrict_link_by_digsig_builtin(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *restriction_key)
|
||||
{
|
||||
return restrict_link_by_digsig(dest_keyring, type, payload,
|
||||
builtin_trusted_keys);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
|
||||
/**
|
||||
* restrict_link_by_builtin_and_secondary_trusted - Restrict keyring
|
||||
@ -83,6 +103,35 @@ int restrict_link_by_builtin_and_secondary_trusted(
|
||||
secondary_trusted_keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* restrict_link_by_digsig_builtin_and_secondary - Restrict by digitalSignature.
|
||||
* @dest_keyring: Keyring being linked to.
|
||||
* @type: The type of key being added.
|
||||
* @payload: The payload of the new key.
|
||||
* @restrict_key: A ring of keys that can be used to vouch for the new cert.
|
||||
*
|
||||
* Restrict the addition of keys into a keyring based on the key-to-be-added
|
||||
* being vouched for by a key in either the built-in or the secondary system
|
||||
* keyrings. The new key must have the digitalSignature usage field set.
|
||||
*/
|
||||
int restrict_link_by_digsig_builtin_and_secondary(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *restrict_key)
|
||||
{
|
||||
/* If we have a secondary trusted keyring, then that contains a link
|
||||
* through to the builtin keyring and the search will follow that link.
|
||||
*/
|
||||
if (type == &key_type_keyring &&
|
||||
dest_keyring == secondary_trusted_keys &&
|
||||
payload == &builtin_trusted_keys->payload)
|
||||
/* Allow the builtin keyring to be added to the secondary */
|
||||
return 0;
|
||||
|
||||
return restrict_link_by_digsig(dest_keyring, type, payload,
|
||||
secondary_trusted_keys);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a struct key_restriction for the "builtin and secondary trust"
|
||||
* keyring. Only for use in system_trusted_keyring_init().
|
||||
@ -103,6 +152,36 @@ static __init struct key_restriction *get_builtin_and_secondary_restriction(void
|
||||
|
||||
return restriction;
|
||||
}
|
||||
|
||||
/**
|
||||
* add_to_secondary_keyring - Add to secondary keyring.
|
||||
* @source: Source of key
|
||||
* @data: The blob holding the key
|
||||
* @len: The length of the data blob
|
||||
*
|
||||
* Add a key to the secondary keyring. The key must be vouched for by a key in the builtin,
|
||||
* machine or secondary keyring itself.
|
||||
*/
|
||||
void __init add_to_secondary_keyring(const char *source, const void *data, size_t len)
|
||||
{
|
||||
key_ref_t key;
|
||||
key_perm_t perm;
|
||||
|
||||
perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW;
|
||||
|
||||
key = key_create_or_update(make_key_ref(secondary_trusted_keys, 1),
|
||||
"asymmetric",
|
||||
NULL, data, len, perm,
|
||||
KEY_ALLOC_NOT_IN_QUOTA);
|
||||
if (IS_ERR(key)) {
|
||||
pr_err("Problem loading X.509 certificate from %s to secondary keyring %ld\n",
|
||||
source, PTR_ERR(key));
|
||||
return;
|
||||
}
|
||||
|
||||
pr_notice("Loaded X.509 cert '%s'\n", key_ref_to_ptr(key)->description);
|
||||
key_ref_put(key);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
|
||||
void __init set_machine_trusted_keys(struct key *keyring)
|
||||
@ -251,6 +330,12 @@ int verify_pkcs7_message_sig(const void *data, size_t len,
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = is_key_on_revocation_list(pkcs7);
|
||||
if (ret != -ENOKEY) {
|
||||
pr_devel("PKCS#7 key is on revocation list\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!trusted_keys) {
|
||||
trusted_keys = builtin_trusted_keys;
|
||||
} else if (trusted_keys == VERIFY_USE_SECONDARY_KEYRING) {
|
||||
@ -270,12 +355,6 @@ int verify_pkcs7_message_sig(const void *data, size_t len,
|
||||
pr_devel("PKCS#7 platform keyring is not available\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = is_key_on_revocation_list(pkcs7);
|
||||
if (ret != -ENOKEY) {
|
||||
pr_devel("PKCS#7 platform key is on revocation list\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
ret = pkcs7_validate_trust(pkcs7, trusted_keys);
|
||||
if (ret < 0) {
|
||||
|
@ -148,6 +148,50 @@ int restrict_link_by_ca(struct key *dest_keyring,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* restrict_link_by_digsig - Restrict additions to a ring of digsig keys
|
||||
* @dest_keyring: Keyring being linked to.
|
||||
* @type: The type of key being added.
|
||||
* @payload: The payload of the new key.
|
||||
* @trust_keyring: A ring of keys that can be used to vouch for the new cert.
|
||||
*
|
||||
* Check if the new certificate has digitalSignature usage set. If it is,
|
||||
* then mark the new certificate as being ok to link. Afterwards verify
|
||||
* the new certificate against the ones in the trust_keyring.
|
||||
*
|
||||
* Returns 0 if the new certificate was accepted, -ENOKEY if the
|
||||
* certificate is not a digsig. -ENOPKG if the signature uses unsupported
|
||||
* crypto, or some other error if there is a matching certificate but
|
||||
* the signature check cannot be performed.
|
||||
*/
|
||||
int restrict_link_by_digsig(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *trust_keyring)
|
||||
{
|
||||
const struct public_key *pkey;
|
||||
|
||||
if (type != &key_type_asymmetric)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
pkey = payload->data[asym_crypto];
|
||||
|
||||
if (!pkey)
|
||||
return -ENOPKG;
|
||||
|
||||
if (!test_bit(KEY_EFLAG_DIGITALSIG, &pkey->key_eflags))
|
||||
return -ENOKEY;
|
||||
|
||||
if (test_bit(KEY_EFLAG_CA, &pkey->key_eflags))
|
||||
return -ENOKEY;
|
||||
|
||||
if (test_bit(KEY_EFLAG_KEYCERTSIGN, &pkey->key_eflags))
|
||||
return -ENOKEY;
|
||||
|
||||
return restrict_link_by_signature(dest_keyring, type, payload,
|
||||
trust_keyring);
|
||||
}
|
||||
|
||||
static bool match_either_id(const struct asymmetric_key_id **pair,
|
||||
const struct asymmetric_key_id *single)
|
||||
{
|
||||
|
@ -251,7 +251,6 @@ static int tpm1_binary_bios_measurements_show(struct seq_file *m, void *v)
|
||||
|
||||
static int tpm1_ascii_bios_measurements_show(struct seq_file *m, void *v)
|
||||
{
|
||||
int len = 0;
|
||||
char *eventname;
|
||||
struct tcpa_event *event = v;
|
||||
unsigned char *event_entry =
|
||||
@ -273,7 +272,7 @@ static int tpm1_ascii_bios_measurements_show(struct seq_file *m, void *v)
|
||||
/* 3rd: event type identifier */
|
||||
seq_printf(m, " %02x", do_endian_conversion(event->event_type));
|
||||
|
||||
len += get_event_name(eventname, event, event_entry);
|
||||
get_event_name(eventname, event, event_entry);
|
||||
|
||||
/* 4th: eventname <= max + \'0' delimiter */
|
||||
seq_printf(m, " %s\n", eventname);
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/dmi.h>
|
||||
#include "tpm.h"
|
||||
#include "tpm_tis_core.h"
|
||||
|
||||
@ -89,8 +88,8 @@ static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr)
|
||||
tpm_tis_flush(iobase);
|
||||
}
|
||||
|
||||
static int interrupts;
|
||||
module_param(interrupts, int, 0444);
|
||||
static bool interrupts;
|
||||
module_param(interrupts, bool, 0444);
|
||||
MODULE_PARM_DESC(interrupts, "Enable interrupts");
|
||||
|
||||
static bool itpm;
|
||||
@ -103,92 +102,6 @@ module_param(force, bool, 0444);
|
||||
MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
|
||||
#endif
|
||||
|
||||
static int tpm_tis_disable_irq(const struct dmi_system_id *d)
|
||||
{
|
||||
if (interrupts == -1) {
|
||||
pr_notice("tpm_tis: %s detected: disabling interrupts.\n", d->ident);
|
||||
interrupts = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id tpm_tis_dmi_table[] = {
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "Framework Laptop (12th Gen Intel Core)",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Laptop (12th Gen Intel Core)"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "Framework Laptop (13th Gen Intel Core)",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Laptop (13th Gen Intel Core)"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "ThinkPad T490s",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T490s"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "ThinkStation P360 Tiny",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P360 Tiny"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "ThinkPad L490",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L490"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "ThinkPad L590",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L590"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "ThinkStation P620",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P620"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "TUXEDO InfinityBook S 15/17 Gen7",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TUXEDO InfinityBook S 15/17 Gen7"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "UPX-TGL",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UPX-TGL01"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
#if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
|
||||
static int has_hid(struct acpi_device *dev, const char *hid)
|
||||
{
|
||||
@ -312,8 +225,6 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info)
|
||||
int irq = -1;
|
||||
int rc;
|
||||
|
||||
dmi_check_system(tpm_tis_dmi_table);
|
||||
|
||||
rc = check_acpi_tpm2(dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
@ -340,7 +340,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
return size;
|
||||
}
|
||||
|
||||
static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
static int tpm_tis_try_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int size = 0;
|
||||
@ -348,11 +348,6 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
u32 expected;
|
||||
int rc;
|
||||
|
||||
if (count < TPM_HEADER_SIZE) {
|
||||
size = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
size = recv_data(chip, buf, TPM_HEADER_SIZE);
|
||||
/* read first 10 bytes, including tag, paramsize, and result */
|
||||
if (size < TPM_HEADER_SIZE) {
|
||||
@ -385,7 +380,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
goto out;
|
||||
}
|
||||
status = tpm_tis_status(chip);
|
||||
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
|
||||
if (status & TPM_STS_DATA_AVAIL) {
|
||||
dev_err(&chip->dev, "Error left over data\n");
|
||||
size = -EIO;
|
||||
goto out;
|
||||
@ -399,10 +394,36 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
}
|
||||
|
||||
out:
|
||||
tpm_tis_ready(chip);
|
||||
return size;
|
||||
}
|
||||
|
||||
static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
unsigned int try;
|
||||
int rc = 0;
|
||||
|
||||
if (count < TPM_HEADER_SIZE)
|
||||
return -EIO;
|
||||
|
||||
for (try = 0; try < TPM_RETRY; try++) {
|
||||
rc = tpm_tis_try_recv(chip, buf, count);
|
||||
|
||||
if (rc == -EIO)
|
||||
/* Data transfer errors, indicated by EIO, can be
|
||||
* recovered by rereading the response.
|
||||
*/
|
||||
tpm_tis_write8(priv, TPM_STS(priv->locality),
|
||||
TPM_STS_RESPONSE_RETRY);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
tpm_tis_ready(chip);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* If interrupts are used (signaled by an irq set in the vendor structure)
|
||||
* tpm.c can skip polling for the data to be available as the interrupt is
|
||||
@ -469,6 +490,12 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
rc = tpm_tis_verify_crc(priv, len, buf);
|
||||
if (rc < 0) {
|
||||
dev_err(&chip->dev, "CRC mismatch for command.\n");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
@ -512,15 +539,16 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
|
||||
int rc;
|
||||
u32 ordinal;
|
||||
unsigned long dur;
|
||||
unsigned int try;
|
||||
|
||||
rc = tpm_tis_send_data(chip, buf, len);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = tpm_tis_verify_crc(priv, len, buf);
|
||||
if (rc < 0) {
|
||||
dev_err(&chip->dev, "CRC mismatch for command.\n");
|
||||
return rc;
|
||||
for (try = 0; try < TPM_RETRY; try++) {
|
||||
rc = tpm_tis_send_data(chip, buf, len);
|
||||
if (rc >= 0)
|
||||
/* Data transfer done successfully */
|
||||
break;
|
||||
else if (rc != -EIO)
|
||||
/* Data transfer failed, not recoverable */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* go and do it */
|
||||
|
@ -34,6 +34,7 @@ enum tis_status {
|
||||
TPM_STS_GO = 0x20,
|
||||
TPM_STS_DATA_AVAIL = 0x10,
|
||||
TPM_STS_DATA_EXPECT = 0x08,
|
||||
TPM_STS_RESPONSE_RETRY = 0x02,
|
||||
TPM_STS_READ_ZERO = 0x23, /* bits that must be zero on read */
|
||||
};
|
||||
|
||||
|
@ -71,8 +71,74 @@ static int tpm_tis_spi_flow_control(struct tpm_tis_spi_phy *phy,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
|
||||
u8 *in, const u8 *out)
|
||||
/*
|
||||
* Half duplex controller with support for TPM wait state detection like
|
||||
* Tegra QSPI need CMD, ADDR & DATA sent in single message to manage HW flow
|
||||
* control. Each phase sent in different transfer for controller to idenity
|
||||
* phase.
|
||||
*/
|
||||
static int tpm_tis_spi_transfer_half(struct tpm_tis_data *data, u32 addr,
|
||||
u16 len, u8 *in, const u8 *out)
|
||||
{
|
||||
struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
|
||||
struct spi_transfer spi_xfer[3];
|
||||
struct spi_message m;
|
||||
u8 transfer_len;
|
||||
int ret;
|
||||
|
||||
while (len) {
|
||||
transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
|
||||
|
||||
spi_message_init(&m);
|
||||
phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
|
||||
phy->iobuf[1] = 0xd4;
|
||||
phy->iobuf[2] = addr >> 8;
|
||||
phy->iobuf[3] = addr;
|
||||
|
||||
memset(&spi_xfer, 0, sizeof(spi_xfer));
|
||||
|
||||
spi_xfer[0].tx_buf = phy->iobuf;
|
||||
spi_xfer[0].len = 1;
|
||||
spi_message_add_tail(&spi_xfer[0], &m);
|
||||
|
||||
spi_xfer[1].tx_buf = phy->iobuf + 1;
|
||||
spi_xfer[1].len = 3;
|
||||
spi_message_add_tail(&spi_xfer[1], &m);
|
||||
|
||||
if (out) {
|
||||
spi_xfer[2].tx_buf = &phy->iobuf[4];
|
||||
spi_xfer[2].rx_buf = NULL;
|
||||
memcpy(&phy->iobuf[4], out, transfer_len);
|
||||
out += transfer_len;
|
||||
}
|
||||
|
||||
if (in) {
|
||||
spi_xfer[2].tx_buf = NULL;
|
||||
spi_xfer[2].rx_buf = &phy->iobuf[4];
|
||||
}
|
||||
|
||||
spi_xfer[2].len = transfer_len;
|
||||
spi_message_add_tail(&spi_xfer[2], &m);
|
||||
|
||||
reinit_completion(&phy->ready);
|
||||
|
||||
ret = spi_sync(phy->spi_device, &m);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (in) {
|
||||
memcpy(in, &phy->iobuf[4], transfer_len);
|
||||
in += transfer_len;
|
||||
}
|
||||
|
||||
len -= transfer_len;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tpm_tis_spi_transfer_full(struct tpm_tis_data *data, u32 addr,
|
||||
u16 len, u8 *in, const u8 *out)
|
||||
{
|
||||
struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
|
||||
int ret = 0;
|
||||
@ -148,6 +214,24 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
|
||||
u8 *in, const u8 *out)
|
||||
{
|
||||
struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
|
||||
struct spi_controller *ctlr = phy->spi_device->controller;
|
||||
|
||||
/*
|
||||
* TPM flow control over SPI requires full duplex support.
|
||||
* Send entire message to a half duplex controller to handle
|
||||
* wait polling in controller.
|
||||
* Set TPM HW flow control flag..
|
||||
*/
|
||||
if (ctlr->flags & SPI_CONTROLLER_HALF_DUPLEX)
|
||||
return tpm_tis_spi_transfer_half(data, addr, len, in, out);
|
||||
else
|
||||
return tpm_tis_spi_transfer_full(data, addr, len, in, out);
|
||||
}
|
||||
|
||||
static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
|
||||
u16 len, u8 *result, enum tpm_tis_io_mode io_mode)
|
||||
{
|
||||
@ -189,6 +273,9 @@ static int tpm_tis_spi_probe(struct spi_device *dev)
|
||||
|
||||
phy->flow_control = tpm_tis_spi_flow_control;
|
||||
|
||||
if (dev->controller->flags & SPI_CONTROLLER_HALF_DUPLEX)
|
||||
dev->mode |= SPI_TPM_HW_FLOW;
|
||||
|
||||
/* If the SPI device has an IRQ then use that */
|
||||
if (dev->irq > 0)
|
||||
irq = dev->irq;
|
||||
|
@ -162,23 +162,7 @@ static struct platform_driver tis_synquacer_drv = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tpm_tis_synquacer_module_init(void)
|
||||
{
|
||||
int rc;
|
||||
module_platform_driver(tis_synquacer_drv);
|
||||
|
||||
rc = platform_driver_register(&tis_synquacer_drv);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit tpm_tis_synquacer_module_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tis_synquacer_drv);
|
||||
}
|
||||
|
||||
module_init(tpm_tis_synquacer_module_init);
|
||||
module_exit(tpm_tis_synquacer_module_exit);
|
||||
MODULE_DESCRIPTION("TPM MMIO Driver for Socionext SynQuacer platform");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -78,6 +78,10 @@ extern int restrict_link_by_ca(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *trust_keyring);
|
||||
int restrict_link_by_digsig(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *trust_keyring);
|
||||
#else
|
||||
static inline int restrict_link_by_ca(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
@ -86,6 +90,14 @@ static inline int restrict_link_by_ca(struct key *dest_keyring,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int restrict_link_by_digsig(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *trust_keyring)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern int query_asymmetric_key(const struct kernel_pkey_params *,
|
||||
|
@ -23,10 +23,15 @@ extern int restrict_link_by_builtin_trusted(struct key *keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *restriction_key);
|
||||
int restrict_link_by_digsig_builtin(struct key *dest_keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *restriction_key);
|
||||
extern __init int load_module_cert(struct key *keyring);
|
||||
|
||||
#else
|
||||
#define restrict_link_by_builtin_trusted restrict_link_reject
|
||||
#define restrict_link_by_digsig_builtin restrict_link_reject
|
||||
|
||||
static inline __init int load_module_cert(struct key *keyring)
|
||||
{
|
||||
@ -41,8 +46,17 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *restriction_key);
|
||||
int restrict_link_by_digsig_builtin_and_secondary(struct key *keyring,
|
||||
const struct key_type *type,
|
||||
const union key_payload *payload,
|
||||
struct key *restriction_key);
|
||||
void __init add_to_secondary_keyring(const char *source, const void *data, size_t len);
|
||||
#else
|
||||
#define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted
|
||||
#define restrict_link_by_digsig_builtin_and_secondary restrict_link_by_digsig_builtin
|
||||
static inline void __init add_to_secondary_keyring(const char *source, const void *data, size_t len)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
|
||||
|
@ -67,7 +67,9 @@ config INTEGRITY_MACHINE_KEYRING
|
||||
depends on SECONDARY_TRUSTED_KEYRING
|
||||
depends on INTEGRITY_ASYMMETRIC_KEYS
|
||||
depends on SYSTEM_BLACKLIST_KEYRING
|
||||
depends on LOAD_UEFI_KEYS
|
||||
depends on LOAD_UEFI_KEYS || LOAD_PPC_KEYS
|
||||
select INTEGRITY_CA_MACHINE_KEYRING if LOAD_PPC_KEYS
|
||||
select INTEGRITY_CA_MACHINE_KEYRING_MAX if LOAD_PPC_KEYS
|
||||
help
|
||||
If set, provide a keyring to which Machine Owner Keys (MOK) may
|
||||
be added. This keyring shall contain just MOK keys. Unlike keys
|
||||
|
@ -34,9 +34,9 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
|
||||
#define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted
|
||||
#define restrict_link_to_ima restrict_link_by_digsig_builtin_and_secondary
|
||||
#else
|
||||
#define restrict_link_to_ima restrict_link_by_builtin_trusted
|
||||
#define restrict_link_to_ima restrict_link_by_digsig_builtin
|
||||
#endif
|
||||
|
||||
static struct key *integrity_keyring_from_id(const unsigned int id)
|
||||
@ -113,7 +113,7 @@ static int __init __integrity_init_keyring(const unsigned int id,
|
||||
} else {
|
||||
if (id == INTEGRITY_KEYRING_PLATFORM)
|
||||
set_platform_trusted_keys(keyring[id]);
|
||||
if (id == INTEGRITY_KEYRING_MACHINE && trust_moklist())
|
||||
if (id == INTEGRITY_KEYRING_MACHINE && imputed_trust_enabled())
|
||||
set_machine_trusted_keys(keyring[id]);
|
||||
if (id == INTEGRITY_KEYRING_IMA)
|
||||
load_module_cert(keyring[id]);
|
||||
|
@ -64,7 +64,8 @@ config EVM_LOAD_X509
|
||||
|
||||
This option enables X509 certificate loading from the kernel
|
||||
onto the '.evm' trusted keyring. A public key can be used to
|
||||
verify EVM integrity starting from the 'init' process.
|
||||
verify EVM integrity starting from the 'init' process. The
|
||||
key must have digitalSignature usage set.
|
||||
|
||||
config EVM_X509_PATH
|
||||
string "EVM X509 certificate path"
|
||||
|
@ -270,7 +270,8 @@ config IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
|
||||
help
|
||||
Keys may be added to the IMA or IMA blacklist keyrings, if the
|
||||
key is validly signed by a CA cert in the system built-in or
|
||||
secondary trusted keyrings.
|
||||
secondary trusted keyrings. The key must also have the
|
||||
digitalSignature usage set.
|
||||
|
||||
Intermediate keys between those the kernel has compiled in and the
|
||||
IMA keys to be added may be added to the system secondary keyring,
|
||||
|
@ -320,13 +320,14 @@ static inline void __init add_to_platform_keyring(const char *source,
|
||||
|
||||
#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
|
||||
void __init add_to_machine_keyring(const char *source, const void *data, size_t len);
|
||||
bool __init trust_moklist(void);
|
||||
bool __init imputed_trust_enabled(void);
|
||||
#else
|
||||
static inline void __init add_to_machine_keyring(const char *source,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
}
|
||||
static inline bool __init trust_moklist(void)
|
||||
|
||||
static inline bool __init imputed_trust_enabled(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -61,7 +61,8 @@ __init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type)
|
||||
__init efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type)
|
||||
{
|
||||
if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0) {
|
||||
if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) && trust_moklist())
|
||||
if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) &&
|
||||
imputed_trust_enabled())
|
||||
return add_to_machine_keyring;
|
||||
else
|
||||
return add_to_platform_keyring;
|
||||
@ -69,6 +70,22 @@ __init efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__init efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type)
|
||||
{
|
||||
if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
|
||||
return add_to_machine_keyring;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__init efi_element_handler_t get_handler_for_code_signing_keys(const efi_guid_t *sig_type)
|
||||
{
|
||||
if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
|
||||
return add_to_secondary_keyring;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the appropriate handler for particular signature list types found in
|
||||
* the UEFI dbx and MokListXRT tables.
|
||||
|
@ -29,6 +29,16 @@ efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type);
|
||||
*/
|
||||
efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type);
|
||||
|
||||
/*
|
||||
* Return the handler for particular signature list types for CA keys.
|
||||
*/
|
||||
efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type);
|
||||
|
||||
/*
|
||||
* Return the handler for particular signature list types for code signing keys.
|
||||
*/
|
||||
efi_element_handler_t get_handler_for_code_signing_keys(const efi_guid_t *sig_type);
|
||||
|
||||
/*
|
||||
* Return the handler for particular signature list types found in the dbx.
|
||||
*/
|
||||
|
@ -59,6 +59,8 @@ static __init void *get_cert_list(u8 *key, unsigned long keylen, u64 *size)
|
||||
static int __init load_powerpc_certs(void)
|
||||
{
|
||||
void *db = NULL, *dbx = NULL, *data = NULL;
|
||||
void *trustedca;
|
||||
void *moduledb;
|
||||
u64 dsize = 0;
|
||||
u64 offset = 0;
|
||||
int rc = 0;
|
||||
@ -120,6 +122,38 @@ static int __init load_powerpc_certs(void)
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
data = get_cert_list("trustedcadb", 12, &dsize);
|
||||
if (!data) {
|
||||
pr_info("Couldn't get trustedcadb list from firmware\n");
|
||||
} else if (IS_ERR(data)) {
|
||||
rc = PTR_ERR(data);
|
||||
pr_err("Error reading trustedcadb from firmware: %d\n", rc);
|
||||
} else {
|
||||
extract_esl(trustedca, data, dsize, offset);
|
||||
|
||||
rc = parse_efi_signature_list("powerpc:trustedca", trustedca, dsize,
|
||||
get_handler_for_ca_keys);
|
||||
if (rc)
|
||||
pr_err("Couldn't parse trustedcadb signatures: %d\n", rc);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
data = get_cert_list("moduledb", 9, &dsize);
|
||||
if (!data) {
|
||||
pr_info("Couldn't get moduledb list from firmware\n");
|
||||
} else if (IS_ERR(data)) {
|
||||
rc = PTR_ERR(data);
|
||||
pr_err("Error reading moduledb from firmware: %d\n", rc);
|
||||
} else {
|
||||
extract_esl(moduledb, data, dsize, offset);
|
||||
|
||||
rc = parse_efi_signature_list("powerpc:moduledb", moduledb, dsize,
|
||||
get_handler_for_code_signing_keys);
|
||||
if (rc)
|
||||
pr_err("Couldn't parse moduledb signatures: %d\n", rc);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
late_initcall(load_powerpc_certs);
|
||||
|
@ -8,8 +8,6 @@
|
||||
#include <linux/efi.h>
|
||||
#include "../integrity.h"
|
||||
|
||||
static bool trust_mok;
|
||||
|
||||
static __init int machine_keyring_init(void)
|
||||
{
|
||||
int rc;
|
||||
@ -36,7 +34,8 @@ void __init add_to_machine_keyring(const char *source, const void *data, size_t
|
||||
* If the restriction check does not pass and the platform keyring
|
||||
* is configured, try to add it into that keyring instead.
|
||||
*/
|
||||
if (rc && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
|
||||
if (rc && efi_enabled(EFI_BOOT) &&
|
||||
IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
|
||||
rc = integrity_load_cert(INTEGRITY_KEYRING_PLATFORM, source,
|
||||
data, len, perm);
|
||||
|
||||
@ -62,12 +61,14 @@ static __init bool uefi_check_trust_mok_keys(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool __init trust_moklist(void)
|
||||
static bool __init trust_moklist(void)
|
||||
{
|
||||
static bool initialized;
|
||||
static bool trust_mok;
|
||||
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
trust_mok = false;
|
||||
|
||||
if (uefi_check_trust_mok_keys())
|
||||
trust_mok = true;
|
||||
@ -75,3 +76,16 @@ bool __init trust_moklist(void)
|
||||
|
||||
return trust_mok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Provides platform specific check for trusting imputed keys before loading
|
||||
* on .machine keyring. UEFI systems enable this trust based on a variable,
|
||||
* and for other platforms, it is always enabled.
|
||||
*/
|
||||
bool __init imputed_trust_enabled(void)
|
||||
{
|
||||
if (efi_enabled(EFI_BOOT))
|
||||
return trust_moklist();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ struct key *request_key_auth_new(struct key *target, const char *op,
|
||||
if (!rka->callout_info)
|
||||
goto error_free_rka;
|
||||
rka->callout_len = callout_len;
|
||||
strlcpy(rka->op, op, sizeof(rka->op));
|
||||
strscpy(rka->op, op, sizeof(rka->op));
|
||||
|
||||
/* see if the calling process is already servicing the key request of
|
||||
* another process */
|
||||
|
Loading…
Reference in New Issue
Block a user