Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jmorris/linux-security

Pull security subsystem updates from James Morris:

 - EVM gains support for loading an x509 cert from the kernel
   (EVM_LOAD_X509), into the EVM trusted kernel keyring.

 - Smack implements 'file receive' process-based permission checking for
   sockets, rather than just depending on inode checks.

 - Misc enhancments for TPM & TPM2.

 - Cleanups and bugfixes for SELinux, Keys, and IMA.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (41 commits)
  selinux: Inode label revalidation performance fix
  KEYS: refcount bug fix
  ima: ima_write_policy() limit locking
  IMA: policy can be updated zero times
  selinux: rate-limit netlink message warnings in selinux_nlmsg_perm()
  selinux: export validatetrans decisions
  gfs2: Invalid security labels of inodes when they go invalid
  selinux: Revalidate invalid inode security labels
  security: Add hook to invalidate inode security labels
  selinux: Add accessor functions for inode->i_security
  security: Make inode argument of inode_getsecid non-const
  security: Make inode argument of inode_getsecurity non-const
  selinux: Remove unused variable in selinux_inode_init_security
  keys, trusted: seal with a TPM2 authorization policy
  keys, trusted: select hash algorithm for TPM2 chips
  keys, trusted: fix: *do not* allow duplicate key options
  tpm_ibmvtpm: properly handle interrupted packet receptions
  tpm_tis: Tighten IRQ auto-probing
  tpm_tis: Refactor the interrupt setup
  tpm_tis: Get rid of the duplicate IRQ probing code
  ...
  • Loading branch information
torvalds committed Jan 18, 2016
2 parents 2d663b5 + acb2cfd commit 5807fca
Show file tree
Hide file tree
Showing 53 changed files with 1,281 additions and 374 deletions.
31 changes: 20 additions & 11 deletions Documentation/security/keys-trusted-encrypted.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,26 @@ Usage:
keyctl print keyid

options:
keyhandle= ascii hex value of sealing key default 0x40000000 (SRK)
keyauth= ascii hex auth for sealing key default 0x00...i
(40 ascii zeros)
blobauth= ascii hex auth for sealed data default 0x00...
(40 ascii zeros)
blobauth= ascii hex auth for sealed data default 0x00...
(40 ascii zeros)
pcrinfo= ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
pcrlock= pcr number to be extended to "lock" blob
migratable= 0|1 indicating permission to reseal to new PCR values,
default 1 (resealing allowed)
keyhandle= ascii hex value of sealing key default 0x40000000 (SRK)
keyauth= ascii hex auth for sealing key default 0x00...i
(40 ascii zeros)
blobauth= ascii hex auth for sealed data default 0x00...
(40 ascii zeros)
blobauth= ascii hex auth for sealed data default 0x00...
(40 ascii zeros)
pcrinfo= ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
pcrlock= pcr number to be extended to "lock" blob
migratable= 0|1 indicating permission to reseal to new PCR values,
default 1 (resealing allowed)
hash= hash algorithm name as a string. For TPM 1.x the only
allowed value is sha1. For TPM 2.x the allowed values
are sha1, sha256, sha384, sha512 and sm3-256.
policydigest= digest for the authorization policy. must be calculated
with the same hash algorithm as specified by the 'hash='
option.
policyhandle= handle to an authorization policy session that defines the
same policy and with the same hash algorithm as was used to
seal the key.

"keyctl print" returns an ascii hex copy of the sealed key, which is in standard
TPM_STORED_DATA format. The key length for new keys are always in bytes.
Expand Down
2 changes: 2 additions & 0 deletions crypto/asymmetric_keys/x509_public_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
goto error_free_cert;
} else if (!prep->trusted) {
ret = x509_validate_trust(cert, get_system_trusted_keyring());
if (ret)
ret = x509_validate_trust(cert, get_ima_mok_keyring());
if (!ret)
prep->trusted = 1;
}
Expand Down
2 changes: 2 additions & 0 deletions crypto/hash_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const char *const hash_algo_name[HASH_ALGO__LAST] = {
[HASH_ALGO_TGR_128] = "tgr128",
[HASH_ALGO_TGR_160] = "tgr160",
[HASH_ALGO_TGR_192] = "tgr192",
[HASH_ALGO_SM3_256] = "sm3-256",
};
EXPORT_SYMBOL_GPL(hash_algo_name);

Expand All @@ -52,5 +53,6 @@ const int hash_digest_size[HASH_ALGO__LAST] = {
[HASH_ALGO_TGR_128] = TGR128_DIGEST_SIZE,
[HASH_ALGO_TGR_160] = TGR160_DIGEST_SIZE,
[HASH_ALGO_TGR_192] = TGR192_DIGEST_SIZE,
[HASH_ALGO_SM3_256] = SM3256_DIGEST_SIZE,
};
EXPORT_SYMBOL_GPL(hash_digest_size);
23 changes: 20 additions & 3 deletions drivers/char/tpm/tpm-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,12 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
{
int duration_idx = TPM_UNDEFINED;
int duration = 0;
u8 category = (ordinal >> 24) & 0xFF;

if ((category == TPM_PROTECTED_COMMAND && ordinal < TPM_MAX_ORDINAL) ||
(category == TPM_CONNECTION_COMMAND && ordinal < TSC_MAX_ORDINAL))
/*
* We only have a duration table for protected commands, where the upper
* 16 bits are 0. For the few other ordinals the fallback will be used.
*/
if (ordinal < TPM_MAX_ORDINAL)
duration_idx = tpm_ordinal_duration[ordinal];

if (duration_idx != TPM_UNDEFINED)
Expand Down Expand Up @@ -501,6 +503,21 @@ int tpm_get_timeouts(struct tpm_chip *chip)
struct duration_t *duration_cap;
ssize_t rc;

if (chip->flags & TPM_CHIP_FLAG_TPM2) {
/* Fixed timeouts for TPM2 */
chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
chip->vendor.timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
chip->vendor.timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
chip->vendor.timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);
chip->vendor.duration[TPM_SHORT] =
msecs_to_jiffies(TPM2_DURATION_SHORT);
chip->vendor.duration[TPM_MEDIUM] =
msecs_to_jiffies(TPM2_DURATION_MEDIUM);
chip->vendor.duration[TPM_LONG] =
msecs_to_jiffies(TPM2_DURATION_LONG);
return 0;
}

tpm_cmd.header.in = tpm_getcap_header;
tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
Expand Down
11 changes: 7 additions & 4 deletions drivers/char/tpm/tpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,20 @@ enum tpm2_structures {
};

enum tpm2_return_codes {
TPM2_RC_INITIALIZE = 0x0100,
TPM2_RC_TESTING = 0x090A,
TPM2_RC_HASH = 0x0083, /* RC_FMT1 */
TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */
TPM2_RC_DISABLED = 0x0120,
TPM2_RC_TESTING = 0x090A, /* RC_WARN */
};

enum tpm2_algorithms {
TPM2_ALG_SHA1 = 0x0004,
TPM2_ALG_KEYEDHASH = 0x0008,
TPM2_ALG_SHA256 = 0x000B,
TPM2_ALG_NULL = 0x0010
TPM2_ALG_SHA384 = 0x000C,
TPM2_ALG_SHA512 = 0x000D,
TPM2_ALG_NULL = 0x0010,
TPM2_ALG_SM3_256 = 0x0012,
};

enum tpm2_command_codes {
Expand Down Expand Up @@ -138,7 +142,6 @@ struct tpm_vendor_specific {
unsigned long base; /* TPM base address */

int irq;
int probed_irq;

int region_size;
int have_region;
Expand Down
60 changes: 53 additions & 7 deletions drivers/char/tpm/tpm2-cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include "tpm.h"
#include <crypto/hash_info.h>
#include <keys/trusted-type.h>

enum tpm2_object_attributes {
Expand Down Expand Up @@ -104,6 +105,19 @@ struct tpm2_cmd {
union tpm2_cmd_params params;
} __packed;

struct tpm2_hash {
unsigned int crypto_id;
unsigned int tpm_id;
};

static struct tpm2_hash tpm2_hash_map[] = {
{HASH_ALGO_SHA1, TPM2_ALG_SHA1},
{HASH_ALGO_SHA256, TPM2_ALG_SHA256},
{HASH_ALGO_SHA384, TPM2_ALG_SHA384},
{HASH_ALGO_SHA512, TPM2_ALG_SHA512},
{HASH_ALGO_SM3_256, TPM2_ALG_SM3_256},
};

/*
* Array with one entry per ordinal defining the maximum amount
* of time the chip could take to return the result. The values
Expand Down Expand Up @@ -429,8 +443,20 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
{
unsigned int blob_len;
struct tpm_buf buf;
u32 hash;
int i;
int rc;

for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
if (options->hash == tpm2_hash_map[i].crypto_id) {
hash = tpm2_hash_map[i].tpm_id;
break;
}
}

if (i == ARRAY_SIZE(tpm2_hash_map))
return -EINVAL;

rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
if (rc)
return rc;
Expand All @@ -452,12 +478,26 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
tpm_buf_append_u8(&buf, payload->migratable);

/* public */
tpm_buf_append_u16(&buf, 14);
if (options->policydigest)
tpm_buf_append_u16(&buf, 14 + options->digest_len);
else
tpm_buf_append_u16(&buf, 14);

tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
tpm_buf_append_u16(&buf, TPM2_ALG_SHA256);
tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
tpm_buf_append_u16(&buf, 0); /* policy digest size */
tpm_buf_append_u16(&buf, hash);

/* policy */
if (options->policydigest) {
tpm_buf_append_u32(&buf, 0);
tpm_buf_append_u16(&buf, options->digest_len);
tpm_buf_append(&buf, options->policydigest,
options->digest_len);
} else {
tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
tpm_buf_append_u16(&buf, 0);
}

/* public parameters */
tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
tpm_buf_append_u16(&buf, 0);

Expand Down Expand Up @@ -488,8 +528,12 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
out:
tpm_buf_destroy(&buf);

if (rc > 0)
rc = -EPERM;
if (rc > 0) {
if ((rc & TPM2_RC_HASH) == TPM2_RC_HASH)
rc = -EINVAL;
else
rc = -EPERM;
}

return rc;
}
Expand Down Expand Up @@ -583,7 +627,9 @@ static int tpm2_unseal(struct tpm_chip *chip,
return rc;

tpm_buf_append_u32(&buf, blob_handle);
tpm2_buf_append_auth(&buf, TPM2_RS_PW,
tpm2_buf_append_auth(&buf,
options->policyhandle ?
options->policyhandle : TPM2_RS_PW,
NULL /* nonce */, 0,
0 /* session_attributes */,
options->blobauth /* hmac */,
Expand Down
14 changes: 3 additions & 11 deletions drivers/char/tpm/tpm_crb.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,17 +284,9 @@ static int crb_acpi_add(struct acpi_device *device)

chip->vendor.priv = priv;

/* Default timeouts and durations */
chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
chip->vendor.timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
chip->vendor.timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
chip->vendor.timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);
chip->vendor.duration[TPM_SHORT] =
msecs_to_jiffies(TPM2_DURATION_SHORT);
chip->vendor.duration[TPM_MEDIUM] =
msecs_to_jiffies(TPM2_DURATION_MEDIUM);
chip->vendor.duration[TPM_LONG] =
msecs_to_jiffies(TPM2_DURATION_LONG);
rc = tpm_get_timeouts(chip);
if (rc)
return rc;

chip->acpi_dev_handle = device->handle;

Expand Down
22 changes: 20 additions & 2 deletions drivers/char/tpm/tpm_ibmvtpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return 0;
}

sig = wait_event_interruptible(ibmvtpm->wq, ibmvtpm->res_len != 0);
sig = wait_event_interruptible(ibmvtpm->wq, !ibmvtpm->tpm_processing_cmd);
if (sig)
return -EINTR;

Expand Down Expand Up @@ -125,7 +125,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
struct ibmvtpm_dev *ibmvtpm;
struct ibmvtpm_crq crq;
__be64 *word = (__be64 *)&crq;
int rc;
int rc, sig;

ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);

Expand All @@ -141,18 +141,35 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
return -EIO;
}

if (ibmvtpm->tpm_processing_cmd) {
dev_info(ibmvtpm->dev,
"Need to wait for TPM to finish\n");
/* wait for previous command to finish */
sig = wait_event_interruptible(ibmvtpm->wq, !ibmvtpm->tpm_processing_cmd);
if (sig)
return -EINTR;
}

spin_lock(&ibmvtpm->rtce_lock);
ibmvtpm->res_len = 0;
memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
crq.valid = (u8)IBMVTPM_VALID_CMD;
crq.msg = (u8)VTPM_TPM_COMMAND;
crq.len = cpu_to_be16(count);
crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle);

/*
* set the processing flag before the Hcall, since we may get the
* result (interrupt) before even being able to check rc.
*/
ibmvtpm->tpm_processing_cmd = true;

rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]),
be64_to_cpu(word[1]));
if (rc != H_SUCCESS) {
dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
rc = 0;
ibmvtpm->tpm_processing_cmd = false;
} else
rc = count;

Expand Down Expand Up @@ -515,6 +532,7 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
case VTPM_TPM_COMMAND_RES:
/* len of the data in rtce buffer */
ibmvtpm->res_len = be16_to_cpu(crq->len);
ibmvtpm->tpm_processing_cmd = false;
wake_up_interruptible(&ibmvtpm->wq);
return;
default:
Expand Down
1 change: 1 addition & 0 deletions drivers/char/tpm/tpm_ibmvtpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct ibmvtpm_dev {
wait_queue_head_t wq;
u16 res_len;
u32 vtpm_version;
bool tpm_processing_cmd;
};

#define CRQ_RES_BUF_SIZE PAGE_SIZE
Expand Down
Loading

0 comments on commit 5807fca

Please sign in to comment.