Commit a556810d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'fixes-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/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
parents 10d43397 6da70580
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* *
* Returns size of the event. If it is an invalid event, returns 0. * 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, static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
struct tcg_pcr_event *event_header) struct tcg_pcr_event *event_header)
{ {
struct tcg_efi_specid_event_head *efispecid; struct tcg_efi_specid_event_head *efispecid;
......
...@@ -233,12 +233,19 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait) ...@@ -233,12 +233,19 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait)
__poll_t mask = 0; __poll_t mask = 0;
poll_wait(file, &priv->async_wait, wait); 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; mask = EPOLLIN | EPOLLRDNORM;
else else
mask = EPOLLOUT | EPOLLWRNORM; mask = EPOLLOUT | EPOLLWRNORM;
mutex_unlock(&priv->buffer_mutex);
return mask; return mask;
} }
......
...@@ -402,15 +402,13 @@ int tpm_pm_suspend(struct device *dev) ...@@ -402,15 +402,13 @@ int tpm_pm_suspend(struct device *dev)
if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED) if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
return 0; 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); tpm2_shutdown(chip, TPM2_SU_STATE);
tpm_chip_stop(chip); else
}
mutex_unlock(&chip->tpm_mutex);
} else {
rc = tpm1_pm_suspend(chip, tpm_suspend_pcr); rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
tpm_chip_stop(chip);
} }
return rc; return rc;
......
...@@ -38,7 +38,7 @@ enum { ...@@ -38,7 +38,7 @@ enum {
int TSS_authhmac(unsigned char *digest, const unsigned char *key, int TSS_authhmac(unsigned char *digest, const unsigned char *key,
unsigned int keylen, unsigned char *h1, unsigned int keylen, unsigned char *h1,
unsigned char *h2, unsigned char h3, ...); unsigned char *h2, unsigned int h3, ...);
int TSS_checkhmac1(unsigned char *buffer, int TSS_checkhmac1(unsigned char *buffer,
const uint32_t command, const uint32_t command,
const unsigned char *ononce, const unsigned char *ononce,
......
...@@ -125,7 +125,7 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, ...@@ -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, int TSS_authhmac(unsigned char *digest, const unsigned char *key,
unsigned int keylen, unsigned char *h1, unsigned int keylen, unsigned char *h1,
unsigned char *h2, unsigned char h3, ...) unsigned char *h2, unsigned int h3, ...)
{ {
unsigned char paramdigest[SHA1_DIGEST_SIZE]; unsigned char paramdigest[SHA1_DIGEST_SIZE];
struct sdesc *sdesc; struct sdesc *sdesc;
...@@ -135,13 +135,16 @@ int TSS_authhmac(unsigned char *digest, const unsigned char *key, ...@@ -135,13 +135,16 @@ int TSS_authhmac(unsigned char *digest, const unsigned char *key,
int ret; int ret;
va_list argp; va_list argp;
if (!chip)
return -ENODEV;
sdesc = init_sdesc(hashalg); sdesc = init_sdesc(hashalg);
if (IS_ERR(sdesc)) { if (IS_ERR(sdesc)) {
pr_info("trusted_key: can't alloc %s\n", hash_alg); pr_info("trusted_key: can't alloc %s\n", hash_alg);
return PTR_ERR(sdesc); return PTR_ERR(sdesc);
} }
c = h3; c = !!h3;
ret = crypto_shash_init(&sdesc->shash); ret = crypto_shash_init(&sdesc->shash);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -196,6 +199,9 @@ int TSS_checkhmac1(unsigned char *buffer, ...@@ -196,6 +199,9 @@ int TSS_checkhmac1(unsigned char *buffer,
va_list argp; va_list argp;
int ret; int ret;
if (!chip)
return -ENODEV;
bufsize = LOAD32(buffer, TPM_SIZE_OFFSET); bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
tag = LOAD16(buffer, 0); tag = LOAD16(buffer, 0);
ordinal = command; ordinal = command;
...@@ -363,6 +369,9 @@ int trusted_tpm_send(unsigned char *cmd, size_t buflen) ...@@ -363,6 +369,9 @@ int trusted_tpm_send(unsigned char *cmd, size_t buflen)
{ {
int rc; int rc;
if (!chip)
return -ENODEV;
dump_tpm_buf(cmd); dump_tpm_buf(cmd);
rc = tpm_send(chip, cmd, buflen); rc = tpm_send(chip, cmd, buflen);
dump_tpm_buf(cmd); dump_tpm_buf(cmd);
...@@ -429,6 +438,9 @@ int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) ...@@ -429,6 +438,9 @@ int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
{ {
int ret; int ret;
if (!chip)
return -ENODEV;
INIT_BUF(tb); INIT_BUF(tb);
store16(tb, TPM_TAG_RQU_COMMAND); store16(tb, TPM_TAG_RQU_COMMAND);
store32(tb, TPM_OIAP_SIZE); store32(tb, TPM_OIAP_SIZE);
...@@ -1245,9 +1257,13 @@ static int __init init_trusted(void) ...@@ -1245,9 +1257,13 @@ static int __init init_trusted(void)
{ {
int ret; int ret;
/* encrypted_keys.ko depends on successful load of this module even if
* TPM is not used.
*/
chip = tpm_default_chip(); chip = tpm_default_chip();
if (!chip) if (!chip)
return -ENOENT; return 0;
ret = init_digests(); ret = init_digests();
if (ret < 0) if (ret < 0)
goto err_put; goto err_put;
...@@ -1269,10 +1285,12 @@ static int __init init_trusted(void) ...@@ -1269,10 +1285,12 @@ static int __init init_trusted(void)
static void __exit cleanup_trusted(void) static void __exit cleanup_trusted(void)
{ {
if (chip) {
put_device(&chip->dev); put_device(&chip->dev);
kfree(digests); kfree(digests);
trusted_shash_release(); trusted_shash_release();
unregister_key_type(&key_type_trusted); unregister_key_type(&key_type_trusted);
}
} }
late_initcall(init_trusted); late_initcall(init_trusted);
......
...@@ -22,6 +22,7 @@ TPM2_CC_UNSEAL = 0x015E ...@@ -22,6 +22,7 @@ TPM2_CC_UNSEAL = 0x015E
TPM2_CC_FLUSH_CONTEXT = 0x0165 TPM2_CC_FLUSH_CONTEXT = 0x0165
TPM2_CC_START_AUTH_SESSION = 0x0176 TPM2_CC_START_AUTH_SESSION = 0x0176
TPM2_CC_GET_CAPABILITY = 0x017A TPM2_CC_GET_CAPABILITY = 0x017A
TPM2_CC_GET_RANDOM = 0x017B
TPM2_CC_PCR_READ = 0x017E TPM2_CC_PCR_READ = 0x017E
TPM2_CC_POLICY_PCR = 0x017F TPM2_CC_POLICY_PCR = 0x017F
TPM2_CC_PCR_EXTEND = 0x0182 TPM2_CC_PCR_EXTEND = 0x0182
...@@ -357,9 +358,9 @@ class Client: ...@@ -357,9 +358,9 @@ class Client:
self.flags = flags self.flags = flags
if (self.flags & Client.FLAG_SPACE) == 0: if (self.flags & Client.FLAG_SPACE) == 0:
self.tpm = open('/dev/tpm0', 'r+b') self.tpm = open('/dev/tpm0', 'r+b', buffering=0)
else: else:
self.tpm = open('/dev/tpmrm0', 'r+b') self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0)
def close(self): def close(self):
self.tpm.close() self.tpm.close()
......
...@@ -158,6 +158,69 @@ class SmokeTest(unittest.TestCase): ...@@ -158,6 +158,69 @@ class SmokeTest(unittest.TestCase):
pass pass
self.assertEqual(rejected, True) 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): class SpaceTest(unittest.TestCase):
def setUp(self): def setUp(self):
logging.basicConfig(filename='SpaceTest.log', level=logging.DEBUG) logging.basicConfig(filename='SpaceTest.log', level=logging.DEBUG)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment