forked from Minki/linux
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
This commit is contained in:
commit
a556810d8e
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -125,7 +125,7 @@ out:
|
||||
*/
|
||||
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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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;
|
||||
@ -1269,10 +1285,12 @@ err_put:
|
||||
|
||||
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);
|
||||
|
@ -22,6 +22,7 @@ TPM2_CC_UNSEAL = 0x015E
|
||||
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
|
||||
@ -357,9 +358,9 @@ class Client:
|
||||
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()
|
||||
|
@ -158,6 +158,69 @@ class SmokeTest(unittest.TestCase):
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user