Skip to content

Commit

Permalink
Merge branch 'fixes-v5.1' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/jmorris/linux-security

Pull TPM fixes from James Morris:
 "From Jarkko: These are critical fixes for v5.1. Contains also couple
  of new selftests for v5.1 features (partial reads in /dev/tpm0)"

* 'fixes-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  selftests/tpm2: Open tpm dev in unbuffered mode
  selftests/tpm2: Extend tests to cover partial reads
  KEYS: trusted: fix -Wvarags warning
  tpm: Fix the type of the return value in calc_tpm2_event_size()
  KEYS: trusted: allow trusted.ko to initialize w/o a TPM
  tpm: fix an invalid condition in tpm_common_poll
  tpm: turn on TPM on suspend for TPM 1.x
  • Loading branch information
Linus Torvalds committed Apr 9, 2019
2 parents 10d4339 + 6da7058 commit a556810
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 21 deletions.
4 changes: 2 additions & 2 deletions drivers/char/tpm/eventlog/tpm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
*
* Returns size of the event. If it is an invalid event, returns 0.
*/
static int calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
struct tcg_pcr_event *event_header)
static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
struct tcg_pcr_event *event_header)
{
struct tcg_efi_specid_event_head *efispecid;
struct tcg_event_field *event_field;
Expand Down
9 changes: 8 additions & 1 deletion drivers/char/tpm/tpm-dev-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,19 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait)
__poll_t mask = 0;

poll_wait(file, &priv->async_wait, wait);
mutex_lock(&priv->buffer_mutex);

if (!priv->response_read || priv->response_length)
/*
* The response_length indicates if there is still response
* (or part of it) to be consumed. Partial reads decrease it
* by the number of bytes read, and write resets it the zero.
*/
if (priv->response_length)
mask = EPOLLIN | EPOLLRDNORM;
else
mask = EPOLLOUT | EPOLLWRNORM;

mutex_unlock(&priv->buffer_mutex);
return mask;
}

Expand Down
14 changes: 6 additions & 8 deletions drivers/char/tpm/tpm-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,15 +402,13 @@ int tpm_pm_suspend(struct device *dev)
if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
return 0;

if (chip->flags & TPM_CHIP_FLAG_TPM2) {
mutex_lock(&chip->tpm_mutex);
if (!tpm_chip_start(chip)) {
if (!tpm_chip_start(chip)) {
if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_STATE);
tpm_chip_stop(chip);
}
mutex_unlock(&chip->tpm_mutex);
} else {
rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
else
rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);

tpm_chip_stop(chip);
}

return rc;
Expand Down
2 changes: 1 addition & 1 deletion include/keys/trusted.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ enum {

int TSS_authhmac(unsigned char *digest, const unsigned char *key,
unsigned int keylen, unsigned char *h1,
unsigned char *h2, unsigned char h3, ...);
unsigned char *h2, unsigned int h3, ...);
int TSS_checkhmac1(unsigned char *buffer,
const uint32_t command,
const unsigned char *ononce,
Expand Down
32 changes: 25 additions & 7 deletions security/keys/trusted.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,
*/
int TSS_authhmac(unsigned char *digest, const unsigned char *key,
unsigned int keylen, unsigned char *h1,
unsigned char *h2, unsigned char h3, ...)
unsigned char *h2, unsigned int h3, ...)
{
unsigned char paramdigest[SHA1_DIGEST_SIZE];
struct sdesc *sdesc;
Expand All @@ -135,13 +135,16 @@ int TSS_authhmac(unsigned char *digest, const unsigned char *key,
int ret;
va_list argp;

if (!chip)
return -ENODEV;

sdesc = init_sdesc(hashalg);
if (IS_ERR(sdesc)) {
pr_info("trusted_key: can't alloc %s\n", hash_alg);
return PTR_ERR(sdesc);
}

c = h3;
c = !!h3;
ret = crypto_shash_init(&sdesc->shash);
if (ret < 0)
goto out;
Expand Down Expand Up @@ -196,6 +199,9 @@ int TSS_checkhmac1(unsigned char *buffer,
va_list argp;
int ret;

if (!chip)
return -ENODEV;

bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
tag = LOAD16(buffer, 0);
ordinal = command;
Expand Down Expand Up @@ -363,6 +369,9 @@ int trusted_tpm_send(unsigned char *cmd, size_t buflen)
{
int rc;

if (!chip)
return -ENODEV;

dump_tpm_buf(cmd);
rc = tpm_send(chip, cmd, buflen);
dump_tpm_buf(cmd);
Expand Down Expand Up @@ -429,6 +438,9 @@ int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
{
int ret;

if (!chip)
return -ENODEV;

INIT_BUF(tb);
store16(tb, TPM_TAG_RQU_COMMAND);
store32(tb, TPM_OIAP_SIZE);
Expand Down Expand Up @@ -1245,9 +1257,13 @@ static int __init init_trusted(void)
{
int ret;

/* encrypted_keys.ko depends on successful load of this module even if
* TPM is not used.
*/
chip = tpm_default_chip();
if (!chip)
return -ENOENT;
return 0;

ret = init_digests();
if (ret < 0)
goto err_put;
Expand All @@ -1269,10 +1285,12 @@ static int __init init_trusted(void)

static void __exit cleanup_trusted(void)
{
put_device(&chip->dev);
kfree(digests);
trusted_shash_release();
unregister_key_type(&key_type_trusted);
if (chip) {
put_device(&chip->dev);
kfree(digests);
trusted_shash_release();
unregister_key_type(&key_type_trusted);
}
}

late_initcall(init_trusted);
Expand Down
5 changes: 3 additions & 2 deletions tools/testing/selftests/tpm2/tpm2.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
TPM2_CC_FLUSH_CONTEXT = 0x0165
TPM2_CC_START_AUTH_SESSION = 0x0176
TPM2_CC_GET_CAPABILITY = 0x017A
TPM2_CC_GET_RANDOM = 0x017B
TPM2_CC_PCR_READ = 0x017E
TPM2_CC_POLICY_PCR = 0x017F
TPM2_CC_PCR_EXTEND = 0x0182
Expand Down Expand Up @@ -357,9 +358,9 @@ def __init__(self, flags = 0):
self.flags = flags

if (self.flags & Client.FLAG_SPACE) == 0:
self.tpm = open('/dev/tpm0', 'r+b')
self.tpm = open('/dev/tpm0', 'r+b', buffering=0)
else:
self.tpm = open('/dev/tpmrm0', 'r+b')
self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0)

def close(self):
self.tpm.close()
Expand Down
63 changes: 63 additions & 0 deletions tools/testing/selftests/tpm2/tpm2_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,69 @@ def test_too_short_cmd(self):
pass
self.assertEqual(rejected, True)

def test_read_partial_resp(self):
try:
fmt = '>HIIH'
cmd = struct.pack(fmt,
tpm2.TPM2_ST_NO_SESSIONS,
struct.calcsize(fmt),
tpm2.TPM2_CC_GET_RANDOM,
0x20)
self.client.tpm.write(cmd)
hdr = self.client.tpm.read(10)
sz = struct.unpack('>I', hdr[2:6])[0]
rsp = self.client.tpm.read()
except:
pass
self.assertEqual(sz, 10 + 2 + 32)
self.assertEqual(len(rsp), 2 + 32)

def test_read_partial_overwrite(self):
try:
fmt = '>HIIH'
cmd = struct.pack(fmt,
tpm2.TPM2_ST_NO_SESSIONS,
struct.calcsize(fmt),
tpm2.TPM2_CC_GET_RANDOM,
0x20)
self.client.tpm.write(cmd)
# Read part of the respone
rsp1 = self.client.tpm.read(15)

# Send a new cmd
self.client.tpm.write(cmd)

# Read the whole respone
rsp2 = self.client.tpm.read()
except:
pass
self.assertEqual(len(rsp1), 15)
self.assertEqual(len(rsp2), 10 + 2 + 32)

def test_send_two_cmds(self):
rejected = False
try:
fmt = '>HIIH'
cmd = struct.pack(fmt,
tpm2.TPM2_ST_NO_SESSIONS,
struct.calcsize(fmt),
tpm2.TPM2_CC_GET_RANDOM,
0x20)
self.client.tpm.write(cmd)

# expect the second one to raise -EBUSY error
self.client.tpm.write(cmd)
rsp = self.client.tpm.read()

except IOError, e:
# read the response
rsp = self.client.tpm.read()
rejected = True
pass
except:
pass
self.assertEqual(rejected, True)

class SpaceTest(unittest.TestCase):
def setUp(self):
logging.basicConfig(filename='SpaceTest.log', level=logging.DEBUG)
Expand Down

0 comments on commit a556810

Please sign in to comment.