diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-10 20:37:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-10 20:37:29 -0400 |
commit | 5af7f115886f7ec193171e2e49b8000ddd1e7147 (patch) | |
tree | 117b9e99650b0772f683e6b8f734e2c94f6a6c3b | |
parent | c3665a6be5de16cf6670a00003642114c44d8a70 (diff) | |
parent | 5da10728037afea6743b76afddfdc9950cd711b3 (diff) |
Merge branch 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull tpm updates from James Morris:
- Clean up the transmission flow
Cleaned up the whole transmission flow. Locking of the chip is now
done in the level of tpm_try_get_ops() and tpm_put_ops() instead
taking the chip lock inside tpm_transmit(). The nested calls inside
tpm_transmit(), used with the resource manager, have been refactored
out.
Should make easier to perform more complex transactions with the TPM
without making the subsystem a bigger mess (e.g. encrypted channel
patches by James Bottomley).
- PPI 1.3 support
TPM PPI 1.3 introduces an additional optional command parameter that
may be needed for some commands. Display the parameter if the command
requires such a parameter. Only command 23 (SetPCRBanks) needs one.
The PPI request file will show output like this then:
# echo "23 16" > request
# cat request
23 16
# echo "5" > request
# cat request
5
- Extend all PCR banks in IMA
Instead of static PCR banks array, the array of available PCR banks
is now allocated dynamically. The digests sizes are determined
dynamically using a probe PCR read without relying crypto's static
list of hash algorithms.
This should finally make sealing of measurements in IMA safe and
secure.
- TPM 2.0 selftests
Added a test suite to tools/testing/selftests/tpm2 previously outside
of the kernel tree: https://github.com/jsakkine-intel/tpm2-scripts
* 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (37 commits)
tpm/ppi: Enable submission of optional command parameter for PPI 1.3
tpm/ppi: Possibly show command parameter if TPM PPI 1.3 is used
tpm/ppi: Display up to 101 operations as define for version 1.3
tpm/ppi: rename TPM_PPI_REVISION_ID to TPM_PPI_REVISION_ID_1
tpm/ppi: pass function revision ID to tpm_eval_dsm()
tpm: pass an array of tpm_extend_digest structures to tpm_pcr_extend()
KEYS: trusted: explicitly use tpm_chip structure from tpm_default_chip()
tpm: move tpm_chip definition to include/linux/tpm.h
tpm: retrieve digest size of unknown algorithms with PCR read
tpm: rename and export tpm2_digest and tpm2_algorithms
tpm: dynamically allocate the allocated_banks array
tpm: remove @flags from tpm_transmit()
tpm: take TPM chip power gating out of tpm_transmit()
tpm: introduce tpm_chip_start() and tpm_chip_stop()
tpm: remove TPM_TRANSMIT_UNLOCKED flag
tpm: use tpm_try_get_ops() in tpm-sysfs.c.
tpm: remove @space from tpm_transmit()
tpm: move TPM space code out of tpm_transmit()
tpm: move tpm_validate_commmand() to tpm2-space.c
tpm: clean up tpm_try_transmit() error handling flow
...
39 files changed, 1876 insertions, 744 deletions
diff --git a/drivers/char/tpm/eventlog/tpm1.c b/drivers/char/tpm/eventlog/tpm1.c index 58c84784ba25..bfdff9271be0 100644 --- a/drivers/char/tpm/eventlog/tpm1.c +++ b/drivers/char/tpm/eventlog/tpm1.c | |||
@@ -74,7 +74,7 @@ static const char* tcpa_pc_event_id_strings[] = { | |||
74 | /* returns pointer to start of pos. entry of tcg log */ | 74 | /* returns pointer to start of pos. entry of tcg log */ |
75 | static void *tpm1_bios_measurements_start(struct seq_file *m, loff_t *pos) | 75 | static void *tpm1_bios_measurements_start(struct seq_file *m, loff_t *pos) |
76 | { | 76 | { |
77 | loff_t i; | 77 | loff_t i = 0; |
78 | struct tpm_chip *chip = m->private; | 78 | struct tpm_chip *chip = m->private; |
79 | struct tpm_bios_log *log = &chip->log; | 79 | struct tpm_bios_log *log = &chip->log; |
80 | void *addr = log->bios_event_log; | 80 | void *addr = log->bios_event_log; |
@@ -83,38 +83,29 @@ static void *tpm1_bios_measurements_start(struct seq_file *m, loff_t *pos) | |||
83 | u32 converted_event_size; | 83 | u32 converted_event_size; |
84 | u32 converted_event_type; | 84 | u32 converted_event_type; |
85 | 85 | ||
86 | |||
87 | /* read over *pos measurements */ | 86 | /* read over *pos measurements */ |
88 | for (i = 0; i < *pos; i++) { | 87 | do { |
89 | event = addr; | 88 | event = addr; |
90 | 89 | ||
90 | /* check if current entry is valid */ | ||
91 | if (addr + sizeof(struct tcpa_event) > limit) | ||
92 | return NULL; | ||
93 | |||
91 | converted_event_size = | 94 | converted_event_size = |
92 | do_endian_conversion(event->event_size); | 95 | do_endian_conversion(event->event_size); |
93 | converted_event_type = | 96 | converted_event_type = |
94 | do_endian_conversion(event->event_type); | 97 | do_endian_conversion(event->event_type); |
95 | 98 | ||
96 | if ((addr + sizeof(struct tcpa_event)) < limit) { | 99 | if (((converted_event_type == 0) && (converted_event_size == 0)) |
97 | if ((converted_event_type == 0) && | 100 | || ((addr + sizeof(struct tcpa_event) + converted_event_size) |
98 | (converted_event_size == 0)) | 101 | > limit)) |
99 | return NULL; | 102 | return NULL; |
100 | addr += (sizeof(struct tcpa_event) + | ||
101 | converted_event_size); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* now check if current entry is valid */ | ||
106 | if ((addr + sizeof(struct tcpa_event)) >= limit) | ||
107 | return NULL; | ||
108 | |||
109 | event = addr; | ||
110 | 103 | ||
111 | converted_event_size = do_endian_conversion(event->event_size); | 104 | if (i++ == *pos) |
112 | converted_event_type = do_endian_conversion(event->event_type); | 105 | break; |
113 | 106 | ||
114 | if (((converted_event_type == 0) && (converted_event_size == 0)) | 107 | addr += (sizeof(struct tcpa_event) + converted_event_size); |
115 | || ((addr + sizeof(struct tcpa_event) + converted_event_size) | 108 | } while (1); |
116 | >= limit)) | ||
117 | return NULL; | ||
118 | 109 | ||
119 | return addr; | 110 | return addr; |
120 | } | 111 | } |
@@ -134,7 +125,7 @@ static void *tpm1_bios_measurements_next(struct seq_file *m, void *v, | |||
134 | v += sizeof(struct tcpa_event) + converted_event_size; | 125 | v += sizeof(struct tcpa_event) + converted_event_size; |
135 | 126 | ||
136 | /* now check if current entry is valid */ | 127 | /* now check if current entry is valid */ |
137 | if ((v + sizeof(struct tcpa_event)) >= limit) | 128 | if ((v + sizeof(struct tcpa_event)) > limit) |
138 | return NULL; | 129 | return NULL; |
139 | 130 | ||
140 | event = v; | 131 | event = v; |
@@ -143,7 +134,7 @@ static void *tpm1_bios_measurements_next(struct seq_file *m, void *v, | |||
143 | converted_event_type = do_endian_conversion(event->event_type); | 134 | converted_event_type = do_endian_conversion(event->event_type); |
144 | 135 | ||
145 | if (((converted_event_type == 0) && (converted_event_size == 0)) || | 136 | if (((converted_event_type == 0) && (converted_event_size == 0)) || |
146 | ((v + sizeof(struct tcpa_event) + converted_event_size) >= limit)) | 137 | ((v + sizeof(struct tcpa_event) + converted_event_size) > limit)) |
147 | return NULL; | 138 | return NULL; |
148 | 139 | ||
149 | (*pos)++; | 140 | (*pos)++; |
diff --git a/drivers/char/tpm/eventlog/tpm2.c b/drivers/char/tpm/eventlog/tpm2.c index 1b8fa9de2cac..d8b77133a83a 100644 --- a/drivers/char/tpm/eventlog/tpm2.c +++ b/drivers/char/tpm/eventlog/tpm2.c | |||
@@ -37,10 +37,10 @@ | |||
37 | * | 37 | * |
38 | * Returns size of the event. If it is an invalid event, returns 0. | 38 | * Returns size of the event. If it is an invalid event, returns 0. |
39 | */ | 39 | */ |
40 | static int calc_tpm2_event_size(struct tcg_pcr_event2 *event, | 40 | static int calc_tpm2_event_size(struct tcg_pcr_event2_head *event, |
41 | struct tcg_pcr_event *event_header) | 41 | struct tcg_pcr_event *event_header) |
42 | { | 42 | { |
43 | struct tcg_efi_specid_event *efispecid; | 43 | struct tcg_efi_specid_event_head *efispecid; |
44 | struct tcg_event_field *event_field; | 44 | struct tcg_event_field *event_field; |
45 | void *marker; | 45 | void *marker; |
46 | void *marker_start; | 46 | void *marker_start; |
@@ -55,7 +55,7 @@ static int calc_tpm2_event_size(struct tcg_pcr_event2 *event, | |||
55 | marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type) | 55 | marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type) |
56 | + sizeof(event->count); | 56 | + sizeof(event->count); |
57 | 57 | ||
58 | efispecid = (struct tcg_efi_specid_event *)event_header->event; | 58 | efispecid = (struct tcg_efi_specid_event_head *)event_header->event; |
59 | 59 | ||
60 | /* Check if event is malformed. */ | 60 | /* Check if event is malformed. */ |
61 | if (event->count > efispecid->num_algs) | 61 | if (event->count > efispecid->num_algs) |
@@ -95,7 +95,7 @@ static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos) | |||
95 | void *addr = log->bios_event_log; | 95 | void *addr = log->bios_event_log; |
96 | void *limit = log->bios_event_log_end; | 96 | void *limit = log->bios_event_log_end; |
97 | struct tcg_pcr_event *event_header; | 97 | struct tcg_pcr_event *event_header; |
98 | struct tcg_pcr_event2 *event; | 98 | struct tcg_pcr_event2_head *event; |
99 | size_t size; | 99 | size_t size; |
100 | int i; | 100 | int i; |
101 | 101 | ||
@@ -136,7 +136,7 @@ static void *tpm2_bios_measurements_next(struct seq_file *m, void *v, | |||
136 | loff_t *pos) | 136 | loff_t *pos) |
137 | { | 137 | { |
138 | struct tcg_pcr_event *event_header; | 138 | struct tcg_pcr_event *event_header; |
139 | struct tcg_pcr_event2 *event; | 139 | struct tcg_pcr_event2_head *event; |
140 | struct tpm_chip *chip = m->private; | 140 | struct tpm_chip *chip = m->private; |
141 | struct tpm_bios_log *log = &chip->log; | 141 | struct tpm_bios_log *log = &chip->log; |
142 | void *limit = log->bios_event_log_end; | 142 | void *limit = log->bios_event_log_end; |
@@ -180,7 +180,7 @@ static int tpm2_binary_bios_measurements_show(struct seq_file *m, void *v) | |||
180 | struct tpm_chip *chip = m->private; | 180 | struct tpm_chip *chip = m->private; |
181 | struct tpm_bios_log *log = &chip->log; | 181 | struct tpm_bios_log *log = &chip->log; |
182 | struct tcg_pcr_event *event_header = log->bios_event_log; | 182 | struct tcg_pcr_event *event_header = log->bios_event_log; |
183 | struct tcg_pcr_event2 *event = v; | 183 | struct tcg_pcr_event2_head *event = v; |
184 | void *temp_ptr; | 184 | void *temp_ptr; |
185 | size_t size; | 185 | size_t size; |
186 | 186 | ||
diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c index be5d1abd3e8e..8390c5b54c3b 100644 --- a/drivers/char/tpm/st33zp24/i2c.c +++ b/drivers/char/tpm/st33zp24/i2c.c | |||
@@ -33,7 +33,7 @@ | |||
33 | 33 | ||
34 | struct st33zp24_i2c_phy { | 34 | struct st33zp24_i2c_phy { |
35 | struct i2c_client *client; | 35 | struct i2c_client *client; |
36 | u8 buf[TPM_BUFSIZE + 1]; | 36 | u8 buf[ST33ZP24_BUFSIZE + 1]; |
37 | int io_lpcpd; | 37 | int io_lpcpd; |
38 | }; | 38 | }; |
39 | 39 | ||
diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c index d7909ab287a8..ff019a1e3c68 100644 --- a/drivers/char/tpm/st33zp24/spi.c +++ b/drivers/char/tpm/st33zp24/spi.c | |||
@@ -63,7 +63,7 @@ | |||
63 | * some latency byte before the answer is available (max 15). | 63 | * some latency byte before the answer is available (max 15). |
64 | * We have 2048 + 1024 + 15. | 64 | * We have 2048 + 1024 + 15. |
65 | */ | 65 | */ |
66 | #define ST33ZP24_SPI_BUFFER_SIZE (TPM_BUFSIZE + (TPM_BUFSIZE / 2) +\ | 66 | #define ST33ZP24_SPI_BUFFER_SIZE (ST33ZP24_BUFSIZE + (ST33ZP24_BUFSIZE / 2) +\ |
67 | MAX_SPI_LATENCY) | 67 | MAX_SPI_LATENCY) |
68 | 68 | ||
69 | 69 | ||
diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c index 64dc560859f2..13dc614b7ebc 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c | |||
@@ -436,7 +436,7 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, | |||
436 | goto out_err; | 436 | goto out_err; |
437 | } | 437 | } |
438 | 438 | ||
439 | return len; | 439 | return 0; |
440 | out_err: | 440 | out_err: |
441 | st33zp24_cancel(chip); | 441 | st33zp24_cancel(chip); |
442 | release_locality(chip); | 442 | release_locality(chip); |
diff --git a/drivers/char/tpm/st33zp24/st33zp24.h b/drivers/char/tpm/st33zp24/st33zp24.h index 6f4a4198af6a..20da0a84988d 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.h +++ b/drivers/char/tpm/st33zp24/st33zp24.h | |||
@@ -18,8 +18,8 @@ | |||
18 | #ifndef __LOCAL_ST33ZP24_H__ | 18 | #ifndef __LOCAL_ST33ZP24_H__ |
19 | #define __LOCAL_ST33ZP24_H__ | 19 | #define __LOCAL_ST33ZP24_H__ |
20 | 20 | ||
21 | #define TPM_WRITE_DIRECTION 0x80 | 21 | #define TPM_WRITE_DIRECTION 0x80 |
22 | #define TPM_BUFSIZE 2048 | 22 | #define ST33ZP24_BUFSIZE 2048 |
23 | 23 | ||
24 | struct st33zp24_dev { | 24 | struct st33zp24_dev { |
25 | struct tpm_chip *chip; | 25 | struct tpm_chip *chip; |
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 32db84683c40..8804c9e916fd 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c | |||
@@ -37,6 +37,103 @@ struct class *tpm_class; | |||
37 | struct class *tpmrm_class; | 37 | struct class *tpmrm_class; |
38 | dev_t tpm_devt; | 38 | dev_t tpm_devt; |
39 | 39 | ||
40 | static int tpm_request_locality(struct tpm_chip *chip) | ||
41 | { | ||
42 | int rc; | ||
43 | |||
44 | if (!chip->ops->request_locality) | ||
45 | return 0; | ||
46 | |||
47 | rc = chip->ops->request_locality(chip, 0); | ||
48 | if (rc < 0) | ||
49 | return rc; | ||
50 | |||
51 | chip->locality = rc; | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static void tpm_relinquish_locality(struct tpm_chip *chip) | ||
56 | { | ||
57 | int rc; | ||
58 | |||
59 | if (!chip->ops->relinquish_locality) | ||
60 | return; | ||
61 | |||
62 | rc = chip->ops->relinquish_locality(chip, chip->locality); | ||
63 | if (rc) | ||
64 | dev_err(&chip->dev, "%s: : error %d\n", __func__, rc); | ||
65 | |||
66 | chip->locality = -1; | ||
67 | } | ||
68 | |||
69 | static int tpm_cmd_ready(struct tpm_chip *chip) | ||
70 | { | ||
71 | if (!chip->ops->cmd_ready) | ||
72 | return 0; | ||
73 | |||
74 | return chip->ops->cmd_ready(chip); | ||
75 | } | ||
76 | |||
77 | static int tpm_go_idle(struct tpm_chip *chip) | ||
78 | { | ||
79 | if (!chip->ops->go_idle) | ||
80 | return 0; | ||
81 | |||
82 | return chip->ops->go_idle(chip); | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * tpm_chip_start() - power on the TPM | ||
87 | * @chip: a TPM chip to use | ||
88 | * | ||
89 | * Return: | ||
90 | * * The response length - OK | ||
91 | * * -errno - A system error | ||
92 | */ | ||
93 | int tpm_chip_start(struct tpm_chip *chip) | ||
94 | { | ||
95 | int ret; | ||
96 | |||
97 | if (chip->ops->clk_enable) | ||
98 | chip->ops->clk_enable(chip, true); | ||
99 | |||
100 | if (chip->locality == -1) { | ||
101 | ret = tpm_request_locality(chip); | ||
102 | if (ret) { | ||
103 | chip->ops->clk_enable(chip, false); | ||
104 | return ret; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | ret = tpm_cmd_ready(chip); | ||
109 | if (ret) { | ||
110 | tpm_relinquish_locality(chip); | ||
111 | if (chip->ops->clk_enable) | ||
112 | chip->ops->clk_enable(chip, false); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | EXPORT_SYMBOL_GPL(tpm_chip_start); | ||
119 | |||
120 | /** | ||
121 | * tpm_chip_stop() - power off the TPM | ||
122 | * @chip: a TPM chip to use | ||
123 | * | ||
124 | * Return: | ||
125 | * * The response length - OK | ||
126 | * * -errno - A system error | ||
127 | */ | ||
128 | void tpm_chip_stop(struct tpm_chip *chip) | ||
129 | { | ||
130 | tpm_go_idle(chip); | ||
131 | tpm_relinquish_locality(chip); | ||
132 | if (chip->ops->clk_enable) | ||
133 | chip->ops->clk_enable(chip, false); | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(tpm_chip_stop); | ||
136 | |||
40 | /** | 137 | /** |
41 | * tpm_try_get_ops() - Get a ref to the tpm_chip | 138 | * tpm_try_get_ops() - Get a ref to the tpm_chip |
42 | * @chip: Chip to ref | 139 | * @chip: Chip to ref |
@@ -56,10 +153,17 @@ int tpm_try_get_ops(struct tpm_chip *chip) | |||
56 | 153 | ||
57 | down_read(&chip->ops_sem); | 154 | down_read(&chip->ops_sem); |
58 | if (!chip->ops) | 155 | if (!chip->ops) |
156 | goto out_ops; | ||
157 | |||
158 | mutex_lock(&chip->tpm_mutex); | ||
159 | rc = tpm_chip_start(chip); | ||
160 | if (rc) | ||
59 | goto out_lock; | 161 | goto out_lock; |
60 | 162 | ||
61 | return 0; | 163 | return 0; |
62 | out_lock: | 164 | out_lock: |
165 | mutex_unlock(&chip->tpm_mutex); | ||
166 | out_ops: | ||
63 | up_read(&chip->ops_sem); | 167 | up_read(&chip->ops_sem); |
64 | put_device(&chip->dev); | 168 | put_device(&chip->dev); |
65 | return rc; | 169 | return rc; |
@@ -75,6 +179,8 @@ EXPORT_SYMBOL_GPL(tpm_try_get_ops); | |||
75 | */ | 179 | */ |
76 | void tpm_put_ops(struct tpm_chip *chip) | 180 | void tpm_put_ops(struct tpm_chip *chip) |
77 | { | 181 | { |
182 | tpm_chip_stop(chip); | ||
183 | mutex_unlock(&chip->tpm_mutex); | ||
78 | up_read(&chip->ops_sem); | 184 | up_read(&chip->ops_sem); |
79 | put_device(&chip->dev); | 185 | put_device(&chip->dev); |
80 | } | 186 | } |
@@ -160,6 +266,7 @@ static void tpm_dev_release(struct device *dev) | |||
160 | kfree(chip->log.bios_event_log); | 266 | kfree(chip->log.bios_event_log); |
161 | kfree(chip->work_space.context_buf); | 267 | kfree(chip->work_space.context_buf); |
162 | kfree(chip->work_space.session_buf); | 268 | kfree(chip->work_space.session_buf); |
269 | kfree(chip->allocated_banks); | ||
163 | kfree(chip); | 270 | kfree(chip); |
164 | } | 271 | } |
165 | 272 | ||
@@ -189,7 +296,10 @@ static int tpm_class_shutdown(struct device *dev) | |||
189 | 296 | ||
190 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | 297 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
191 | down_write(&chip->ops_sem); | 298 | down_write(&chip->ops_sem); |
192 | tpm2_shutdown(chip, TPM2_SU_CLEAR); | 299 | if (!tpm_chip_start(chip)) { |
300 | tpm2_shutdown(chip, TPM2_SU_CLEAR); | ||
301 | tpm_chip_stop(chip); | ||
302 | } | ||
193 | chip->ops = NULL; | 303 | chip->ops = NULL; |
194 | up_write(&chip->ops_sem); | 304 | up_write(&chip->ops_sem); |
195 | } | 305 | } |
@@ -368,8 +478,12 @@ static void tpm_del_char_device(struct tpm_chip *chip) | |||
368 | 478 | ||
369 | /* Make the driver uncallable. */ | 479 | /* Make the driver uncallable. */ |
370 | down_write(&chip->ops_sem); | 480 | down_write(&chip->ops_sem); |
371 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 481 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
372 | tpm2_shutdown(chip, TPM2_SU_CLEAR); | 482 | if (!tpm_chip_start(chip)) { |
483 | tpm2_shutdown(chip, TPM2_SU_CLEAR); | ||
484 | tpm_chip_stop(chip); | ||
485 | } | ||
486 | } | ||
373 | chip->ops = NULL; | 487 | chip->ops = NULL; |
374 | up_write(&chip->ops_sem); | 488 | up_write(&chip->ops_sem); |
375 | } | 489 | } |
@@ -451,7 +565,11 @@ int tpm_chip_register(struct tpm_chip *chip) | |||
451 | { | 565 | { |
452 | int rc; | 566 | int rc; |
453 | 567 | ||
568 | rc = tpm_chip_start(chip); | ||
569 | if (rc) | ||
570 | return rc; | ||
454 | rc = tpm_auto_startup(chip); | 571 | rc = tpm_auto_startup(chip); |
572 | tpm_chip_stop(chip); | ||
455 | if (rc) | 573 | if (rc) |
456 | return rc; | 574 | return rc; |
457 | 575 | ||
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 5eecad233ea1..8856cce5a23b 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c | |||
@@ -27,7 +27,38 @@ | |||
27 | static struct workqueue_struct *tpm_dev_wq; | 27 | static struct workqueue_struct *tpm_dev_wq; |
28 | static DEFINE_MUTEX(tpm_dev_wq_lock); | 28 | static DEFINE_MUTEX(tpm_dev_wq_lock); |
29 | 29 | ||
30 | static void tpm_async_work(struct work_struct *work) | 30 | static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space, |
31 | u8 *buf, size_t bufsiz) | ||
32 | { | ||
33 | struct tpm_header *header = (void *)buf; | ||
34 | ssize_t ret, len; | ||
35 | |||
36 | ret = tpm2_prepare_space(chip, space, buf, bufsiz); | ||
37 | /* If the command is not implemented by the TPM, synthesize a | ||
38 | * response with a TPM2_RC_COMMAND_CODE return for user-space. | ||
39 | */ | ||
40 | if (ret == -EOPNOTSUPP) { | ||
41 | header->length = cpu_to_be32(sizeof(*header)); | ||
42 | header->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); | ||
43 | header->return_code = cpu_to_be32(TPM2_RC_COMMAND_CODE | | ||
44 | TSS2_RESMGR_TPM_RC_LAYER); | ||
45 | ret = sizeof(*header); | ||
46 | } | ||
47 | if (ret) | ||
48 | goto out_rc; | ||
49 | |||
50 | len = tpm_transmit(chip, buf, bufsiz); | ||
51 | if (len < 0) | ||
52 | ret = len; | ||
53 | |||
54 | if (!ret) | ||
55 | ret = tpm2_commit_space(chip, space, buf, &len); | ||
56 | |||
57 | out_rc: | ||
58 | return ret ? ret : len; | ||
59 | } | ||
60 | |||
61 | static void tpm_dev_async_work(struct work_struct *work) | ||
31 | { | 62 | { |
32 | struct file_priv *priv = | 63 | struct file_priv *priv = |
33 | container_of(work, struct file_priv, async_work); | 64 | container_of(work, struct file_priv, async_work); |
@@ -35,9 +66,8 @@ static void tpm_async_work(struct work_struct *work) | |||
35 | 66 | ||
36 | mutex_lock(&priv->buffer_mutex); | 67 | mutex_lock(&priv->buffer_mutex); |
37 | priv->command_enqueued = false; | 68 | priv->command_enqueued = false; |
38 | ret = tpm_transmit(priv->chip, priv->space, priv->data_buffer, | 69 | ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer, |
39 | sizeof(priv->data_buffer), 0); | 70 | sizeof(priv->data_buffer)); |
40 | |||
41 | tpm_put_ops(priv->chip); | 71 | tpm_put_ops(priv->chip); |
42 | if (ret > 0) { | 72 | if (ret > 0) { |
43 | priv->response_length = ret; | 73 | priv->response_length = ret; |
@@ -80,7 +110,7 @@ void tpm_common_open(struct file *file, struct tpm_chip *chip, | |||
80 | mutex_init(&priv->buffer_mutex); | 110 | mutex_init(&priv->buffer_mutex); |
81 | timer_setup(&priv->user_read_timer, user_reader_timeout, 0); | 111 | timer_setup(&priv->user_read_timer, user_reader_timeout, 0); |
82 | INIT_WORK(&priv->timeout_work, tpm_timeout_work); | 112 | INIT_WORK(&priv->timeout_work, tpm_timeout_work); |
83 | INIT_WORK(&priv->async_work, tpm_async_work); | 113 | INIT_WORK(&priv->async_work, tpm_dev_async_work); |
84 | init_waitqueue_head(&priv->async_wait); | 114 | init_waitqueue_head(&priv->async_wait); |
85 | file->private_data = priv; | 115 | file->private_data = priv; |
86 | } | 116 | } |
@@ -183,8 +213,8 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, | |||
183 | return size; | 213 | return size; |
184 | } | 214 | } |
185 | 215 | ||
186 | ret = tpm_transmit(priv->chip, priv->space, priv->data_buffer, | 216 | ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer, |
187 | sizeof(priv->data_buffer), 0); | 217 | sizeof(priv->data_buffer)); |
188 | tpm_put_ops(priv->chip); | 218 | tpm_put_ops(priv->chip); |
189 | 219 | ||
190 | if (ret > 0) { | 220 | if (ret > 0) { |
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index d9439f9abe78..83ece5639f86 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
@@ -62,137 +62,22 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) | |||
62 | } | 62 | } |
63 | EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); | 63 | EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); |
64 | 64 | ||
65 | static int tpm_validate_command(struct tpm_chip *chip, | 65 | static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz) |
66 | struct tpm_space *space, | ||
67 | const u8 *cmd, | ||
68 | size_t len) | ||
69 | { | ||
70 | const struct tpm_input_header *header = (const void *)cmd; | ||
71 | int i; | ||
72 | u32 cc; | ||
73 | u32 attrs; | ||
74 | unsigned int nr_handles; | ||
75 | |||
76 | if (len < TPM_HEADER_SIZE) | ||
77 | return -EINVAL; | ||
78 | |||
79 | if (!space) | ||
80 | return 0; | ||
81 | |||
82 | if (chip->flags & TPM_CHIP_FLAG_TPM2 && chip->nr_commands) { | ||
83 | cc = be32_to_cpu(header->ordinal); | ||
84 | |||
85 | i = tpm2_find_cc(chip, cc); | ||
86 | if (i < 0) { | ||
87 | dev_dbg(&chip->dev, "0x%04X is an invalid command\n", | ||
88 | cc); | ||
89 | return -EOPNOTSUPP; | ||
90 | } | ||
91 | |||
92 | attrs = chip->cc_attrs_tbl[i]; | ||
93 | nr_handles = | ||
94 | 4 * ((attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0)); | ||
95 | if (len < TPM_HEADER_SIZE + 4 * nr_handles) | ||
96 | goto err_len; | ||
97 | } | ||
98 | |||
99 | return 0; | ||
100 | err_len: | ||
101 | dev_dbg(&chip->dev, | ||
102 | "%s: insufficient command length %zu", __func__, len); | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | static int tpm_request_locality(struct tpm_chip *chip, unsigned int flags) | ||
107 | { | 66 | { |
108 | int rc; | 67 | struct tpm_header *header = buf; |
109 | |||
110 | if (flags & TPM_TRANSMIT_NESTED) | ||
111 | return 0; | ||
112 | |||
113 | if (!chip->ops->request_locality) | ||
114 | return 0; | ||
115 | |||
116 | rc = chip->ops->request_locality(chip, 0); | ||
117 | if (rc < 0) | ||
118 | return rc; | ||
119 | |||
120 | chip->locality = rc; | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static void tpm_relinquish_locality(struct tpm_chip *chip, unsigned int flags) | ||
126 | { | ||
127 | int rc; | ||
128 | |||
129 | if (flags & TPM_TRANSMIT_NESTED) | ||
130 | return; | ||
131 | |||
132 | if (!chip->ops->relinquish_locality) | ||
133 | return; | ||
134 | |||
135 | rc = chip->ops->relinquish_locality(chip, chip->locality); | ||
136 | if (rc) | ||
137 | dev_err(&chip->dev, "%s: : error %d\n", __func__, rc); | ||
138 | |||
139 | chip->locality = -1; | ||
140 | } | ||
141 | |||
142 | static int tpm_cmd_ready(struct tpm_chip *chip, unsigned int flags) | ||
143 | { | ||
144 | if (flags & TPM_TRANSMIT_NESTED) | ||
145 | return 0; | ||
146 | |||
147 | if (!chip->ops->cmd_ready) | ||
148 | return 0; | ||
149 | |||
150 | return chip->ops->cmd_ready(chip); | ||
151 | } | ||
152 | |||
153 | static int tpm_go_idle(struct tpm_chip *chip, unsigned int flags) | ||
154 | { | ||
155 | if (flags & TPM_TRANSMIT_NESTED) | ||
156 | return 0; | ||
157 | |||
158 | if (!chip->ops->go_idle) | ||
159 | return 0; | ||
160 | |||
161 | return chip->ops->go_idle(chip); | ||
162 | } | ||
163 | |||
164 | static ssize_t tpm_try_transmit(struct tpm_chip *chip, | ||
165 | struct tpm_space *space, | ||
166 | u8 *buf, size_t bufsiz, | ||
167 | unsigned int flags) | ||
168 | { | ||
169 | struct tpm_output_header *header = (void *)buf; | ||
170 | int rc; | 68 | int rc; |
171 | ssize_t len = 0; | 69 | ssize_t len = 0; |
172 | u32 count, ordinal; | 70 | u32 count, ordinal; |
173 | unsigned long stop; | 71 | unsigned long stop; |
174 | bool need_locality; | ||
175 | 72 | ||
176 | rc = tpm_validate_command(chip, space, buf, bufsiz); | 73 | if (bufsiz < TPM_HEADER_SIZE) |
177 | if (rc == -EINVAL) | 74 | return -EINVAL; |
178 | return rc; | ||
179 | /* | ||
180 | * If the command is not implemented by the TPM, synthesize a | ||
181 | * response with a TPM2_RC_COMMAND_CODE return for user-space. | ||
182 | */ | ||
183 | if (rc == -EOPNOTSUPP) { | ||
184 | header->length = cpu_to_be32(sizeof(*header)); | ||
185 | header->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); | ||
186 | header->return_code = cpu_to_be32(TPM2_RC_COMMAND_CODE | | ||
187 | TSS2_RESMGR_TPM_RC_LAYER); | ||
188 | return sizeof(*header); | ||
189 | } | ||
190 | 75 | ||
191 | if (bufsiz > TPM_BUFSIZE) | 76 | if (bufsiz > TPM_BUFSIZE) |
192 | bufsiz = TPM_BUFSIZE; | 77 | bufsiz = TPM_BUFSIZE; |
193 | 78 | ||
194 | count = be32_to_cpu(*((__be32 *) (buf + 2))); | 79 | count = be32_to_cpu(header->length); |
195 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | 80 | ordinal = be32_to_cpu(header->ordinal); |
196 | if (count == 0) | 81 | if (count == 0) |
197 | return -ENODATA; | 82 | return -ENODATA; |
198 | if (count > bufsiz) { | 83 | if (count > bufsiz) { |
@@ -201,37 +86,21 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, | |||
201 | return -E2BIG; | 86 | return -E2BIG; |
202 | } | 87 | } |
203 | 88 | ||
204 | if (!(flags & TPM_TRANSMIT_UNLOCKED) && !(flags & TPM_TRANSMIT_NESTED)) | ||
205 | mutex_lock(&chip->tpm_mutex); | ||
206 | |||
207 | if (chip->ops->clk_enable != NULL) | ||
208 | chip->ops->clk_enable(chip, true); | ||
209 | |||
210 | /* Store the decision as chip->locality will be changed. */ | ||
211 | need_locality = chip->locality == -1; | ||
212 | |||
213 | if (need_locality) { | ||
214 | rc = tpm_request_locality(chip, flags); | ||
215 | if (rc < 0) { | ||
216 | need_locality = false; | ||
217 | goto out_locality; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | rc = tpm_cmd_ready(chip, flags); | ||
222 | if (rc) | ||
223 | goto out_locality; | ||
224 | |||
225 | rc = tpm2_prepare_space(chip, space, ordinal, buf); | ||
226 | if (rc) | ||
227 | goto out; | ||
228 | |||
229 | rc = chip->ops->send(chip, buf, count); | 89 | rc = chip->ops->send(chip, buf, count); |
230 | if (rc < 0) { | 90 | if (rc < 0) { |
231 | if (rc != -EPIPE) | 91 | if (rc != -EPIPE) |
232 | dev_err(&chip->dev, | 92 | dev_err(&chip->dev, |
233 | "%s: tpm_send: error %d\n", __func__, rc); | 93 | "%s: send(): error %d\n", __func__, rc); |
234 | goto out; | 94 | return rc; |
95 | } | ||
96 | |||
97 | /* A sanity check. send() should just return zero on success e.g. | ||
98 | * not the command length. | ||
99 | */ | ||
100 | if (rc > 0) { | ||
101 | dev_warn(&chip->dev, | ||
102 | "%s: send(): invalid value %d\n", __func__, rc); | ||
103 | rc = 0; | ||
235 | } | 104 | } |
236 | 105 | ||
237 | if (chip->flags & TPM_CHIP_FLAG_IRQ) | 106 | if (chip->flags & TPM_CHIP_FLAG_IRQ) |
@@ -246,8 +115,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, | |||
246 | 115 | ||
247 | if (chip->ops->req_canceled(chip, status)) { | 116 | if (chip->ops->req_canceled(chip, status)) { |
248 | dev_err(&chip->dev, "Operation Canceled\n"); | 117 | dev_err(&chip->dev, "Operation Canceled\n"); |
249 | rc = -ECANCELED; | 118 | return -ECANCELED; |
250 | goto out; | ||
251 | } | 119 | } |
252 | 120 | ||
253 | tpm_msleep(TPM_TIMEOUT_POLL); | 121 | tpm_msleep(TPM_TIMEOUT_POLL); |
@@ -256,77 +124,45 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, | |||
256 | 124 | ||
257 | chip->ops->cancel(chip); | 125 | chip->ops->cancel(chip); |
258 | dev_err(&chip->dev, "Operation Timed out\n"); | 126 | dev_err(&chip->dev, "Operation Timed out\n"); |
259 | rc = -ETIME; | 127 | return -ETIME; |
260 | goto out; | ||
261 | 128 | ||
262 | out_recv: | 129 | out_recv: |
263 | len = chip->ops->recv(chip, buf, bufsiz); | 130 | len = chip->ops->recv(chip, buf, bufsiz); |
264 | if (len < 0) { | 131 | if (len < 0) { |
265 | rc = len; | 132 | rc = len; |
266 | dev_err(&chip->dev, | 133 | dev_err(&chip->dev, "tpm_transmit: tpm_recv: error %d\n", rc); |
267 | "tpm_transmit: tpm_recv: error %d\n", rc); | 134 | } else if (len < TPM_HEADER_SIZE || len != be32_to_cpu(header->length)) |
268 | goto out; | ||
269 | } else if (len < TPM_HEADER_SIZE) { | ||
270 | rc = -EFAULT; | 135 | rc = -EFAULT; |
271 | goto out; | ||
272 | } | ||
273 | 136 | ||
274 | if (len != be32_to_cpu(header->length)) { | ||
275 | rc = -EFAULT; | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | rc = tpm2_commit_space(chip, space, ordinal, buf, &len); | ||
280 | if (rc) | ||
281 | dev_err(&chip->dev, "tpm2_commit_space: error %d\n", rc); | ||
282 | |||
283 | out: | ||
284 | /* may fail but do not override previous error value in rc */ | ||
285 | tpm_go_idle(chip, flags); | ||
286 | |||
287 | out_locality: | ||
288 | if (need_locality) | ||
289 | tpm_relinquish_locality(chip, flags); | ||
290 | |||
291 | if (chip->ops->clk_enable != NULL) | ||
292 | chip->ops->clk_enable(chip, false); | ||
293 | |||
294 | if (!(flags & TPM_TRANSMIT_UNLOCKED) && !(flags & TPM_TRANSMIT_NESTED)) | ||
295 | mutex_unlock(&chip->tpm_mutex); | ||
296 | return rc ? rc : len; | 137 | return rc ? rc : len; |
297 | } | 138 | } |
298 | 139 | ||
299 | /** | 140 | /** |
300 | * tpm_transmit - Internal kernel interface to transmit TPM commands. | 141 | * tpm_transmit - Internal kernel interface to transmit TPM commands. |
142 | * @chip: a TPM chip to use | ||
143 | * @buf: a TPM command buffer | ||
144 | * @bufsiz: length of the TPM command buffer | ||
301 | * | 145 | * |
302 | * @chip: TPM chip to use | 146 | * A wrapper around tpm_try_transmit() that handles TPM2_RC_RETRY returns from |
303 | * @space: tpm space | 147 | * the TPM and retransmits the command after a delay up to a maximum wait of |
304 | * @buf: TPM command buffer | 148 | * TPM2_DURATION_LONG. |
305 | * @bufsiz: length of the TPM command buffer | ||
306 | * @flags: tpm transmit flags - bitmap | ||
307 | * | ||
308 | * A wrapper around tpm_try_transmit that handles TPM2_RC_RETRY | ||
309 | * returns from the TPM and retransmits the command after a delay up | ||
310 | * to a maximum wait of TPM2_DURATION_LONG. | ||
311 | * | 149 | * |
312 | * Note: TPM1 never returns TPM2_RC_RETRY so the retry logic is TPM2 | 150 | * Note that TPM 1.x never returns TPM2_RC_RETRY so the retry logic is TPM 2.0 |
313 | * only | 151 | * only. |
314 | * | 152 | * |
315 | * Return: | 153 | * Return: |
316 | * the length of the return when the operation is successful. | 154 | * * The response length - OK |
317 | * A negative number for system errors (errno). | 155 | * * -errno - A system error |
318 | */ | 156 | */ |
319 | ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | 157 | ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz) |
320 | u8 *buf, size_t bufsiz, unsigned int flags) | ||
321 | { | 158 | { |
322 | struct tpm_output_header *header = (struct tpm_output_header *)buf; | 159 | struct tpm_header *header = (struct tpm_header *)buf; |
323 | /* space for header and handles */ | 160 | /* space for header and handles */ |
324 | u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)]; | 161 | u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)]; |
325 | unsigned int delay_msec = TPM2_DURATION_SHORT; | 162 | unsigned int delay_msec = TPM2_DURATION_SHORT; |
326 | u32 rc = 0; | 163 | u32 rc = 0; |
327 | ssize_t ret; | 164 | ssize_t ret; |
328 | const size_t save_size = min(space ? sizeof(save) : TPM_HEADER_SIZE, | 165 | const size_t save_size = min(sizeof(save), bufsiz); |
329 | bufsiz); | ||
330 | /* the command code is where the return code will be */ | 166 | /* the command code is where the return code will be */ |
331 | u32 cc = be32_to_cpu(header->return_code); | 167 | u32 cc = be32_to_cpu(header->return_code); |
332 | 168 | ||
@@ -338,7 +174,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | |||
338 | memcpy(save, buf, save_size); | 174 | memcpy(save, buf, save_size); |
339 | 175 | ||
340 | for (;;) { | 176 | for (;;) { |
341 | ret = tpm_try_transmit(chip, space, buf, bufsiz, flags); | 177 | ret = tpm_try_transmit(chip, buf, bufsiz); |
342 | if (ret < 0) | 178 | if (ret < 0) |
343 | break; | 179 | break; |
344 | rc = be32_to_cpu(header->return_code); | 180 | rc = be32_to_cpu(header->return_code); |
@@ -365,39 +201,33 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | |||
365 | } | 201 | } |
366 | return ret; | 202 | return ret; |
367 | } | 203 | } |
204 | |||
368 | /** | 205 | /** |
369 | * tpm_transmit_cmd - send a tpm command to the device | 206 | * tpm_transmit_cmd - send a tpm command to the device |
370 | * The function extracts tpm out header return code | 207 | * @chip: a TPM chip to use |
371 | * | 208 | * @buf: a TPM command buffer |
372 | * @chip: TPM chip to use | 209 | * @min_rsp_body_length: minimum expected length of response body |
373 | * @space: tpm space | 210 | * @desc: command description used in the error message |
374 | * @buf: TPM command buffer | ||
375 | * @bufsiz: length of the buffer | ||
376 | * @min_rsp_body_length: minimum expected length of response body | ||
377 | * @flags: tpm transmit flags - bitmap | ||
378 | * @desc: command description used in the error message | ||
379 | * | 211 | * |
380 | * Return: | 212 | * Return: |
381 | * 0 when the operation is successful. | 213 | * * 0 - OK |
382 | * A negative number for system errors (errno). | 214 | * * -errno - A system error |
383 | * A positive number for a TPM error. | 215 | * * TPM_RC - A TPM error |
384 | */ | 216 | */ |
385 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, | 217 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf, |
386 | void *buf, size_t bufsiz, | 218 | size_t min_rsp_body_length, const char *desc) |
387 | size_t min_rsp_body_length, unsigned int flags, | ||
388 | const char *desc) | ||
389 | { | 219 | { |
390 | const struct tpm_output_header *header = buf; | 220 | const struct tpm_header *header = (struct tpm_header *)buf->data; |
391 | int err; | 221 | int err; |
392 | ssize_t len; | 222 | ssize_t len; |
393 | 223 | ||
394 | len = tpm_transmit(chip, space, buf, bufsiz, flags); | 224 | len = tpm_transmit(chip, buf->data, PAGE_SIZE); |
395 | if (len < 0) | 225 | if (len < 0) |
396 | return len; | 226 | return len; |
397 | 227 | ||
398 | err = be32_to_cpu(header->return_code); | 228 | err = be32_to_cpu(header->return_code); |
399 | if (err != 0 && err != TPM_ERR_DISABLED && err != TPM_ERR_DEACTIVATED | 229 | if (err != 0 && err != TPM_ERR_DISABLED && err != TPM_ERR_DEACTIVATED |
400 | && desc) | 230 | && err != TPM2_RC_TESTING && desc) |
401 | dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err, | 231 | dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err, |
402 | desc); | 232 | desc); |
403 | if (err) | 233 | if (err) |
@@ -451,11 +281,12 @@ EXPORT_SYMBOL_GPL(tpm_is_tpm2); | |||
451 | * tpm_pcr_read - read a PCR value from SHA1 bank | 281 | * tpm_pcr_read - read a PCR value from SHA1 bank |
452 | * @chip: a &struct tpm_chip instance, %NULL for the default chip | 282 | * @chip: a &struct tpm_chip instance, %NULL for the default chip |
453 | * @pcr_idx: the PCR to be retrieved | 283 | * @pcr_idx: the PCR to be retrieved |
454 | * @res_buf: the value of the PCR | 284 | * @digest: the PCR bank and buffer current PCR value is written to |
455 | * | 285 | * |
456 | * Return: same as with tpm_transmit_cmd() | 286 | * Return: same as with tpm_transmit_cmd() |
457 | */ | 287 | */ |
458 | int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) | 288 | int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, |
289 | struct tpm_digest *digest) | ||
459 | { | 290 | { |
460 | int rc; | 291 | int rc; |
461 | 292 | ||
@@ -464,9 +295,9 @@ int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) | |||
464 | return -ENODEV; | 295 | return -ENODEV; |
465 | 296 | ||
466 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 297 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
467 | rc = tpm2_pcr_read(chip, pcr_idx, res_buf); | 298 | rc = tpm2_pcr_read(chip, pcr_idx, digest, NULL); |
468 | else | 299 | else |
469 | rc = tpm1_pcr_read(chip, pcr_idx, res_buf); | 300 | rc = tpm1_pcr_read(chip, pcr_idx, digest->digest); |
470 | 301 | ||
471 | tpm_put_ops(chip); | 302 | tpm_put_ops(chip); |
472 | return rc; | 303 | return rc; |
@@ -477,41 +308,34 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read); | |||
477 | * tpm_pcr_extend - extend a PCR value in SHA1 bank. | 308 | * tpm_pcr_extend - extend a PCR value in SHA1 bank. |
478 | * @chip: a &struct tpm_chip instance, %NULL for the default chip | 309 | * @chip: a &struct tpm_chip instance, %NULL for the default chip |
479 | * @pcr_idx: the PCR to be retrieved | 310 | * @pcr_idx: the PCR to be retrieved |
480 | * @hash: the hash value used to extend the PCR value | 311 | * @digests: array of tpm_digest structures used to extend PCRs |
481 | * | 312 | * |
482 | * Note: with TPM 2.0 extends also those banks with a known digest size to the | 313 | * Note: callers must pass a digest for every allocated PCR bank, in the same |
483 | * cryto subsystem in order to prevent malicious use of those PCR banks. In the | 314 | * order of the banks in chip->allocated_banks. |
484 | * future we should dynamically determine digest sizes. | ||
485 | * | 315 | * |
486 | * Return: same as with tpm_transmit_cmd() | 316 | * Return: same as with tpm_transmit_cmd() |
487 | */ | 317 | */ |
488 | int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash) | 318 | int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, |
319 | struct tpm_digest *digests) | ||
489 | { | 320 | { |
490 | int rc; | 321 | int rc; |
491 | struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)]; | ||
492 | u32 count = 0; | ||
493 | int i; | 322 | int i; |
494 | 323 | ||
495 | chip = tpm_find_get_ops(chip); | 324 | chip = tpm_find_get_ops(chip); |
496 | if (!chip) | 325 | if (!chip) |
497 | return -ENODEV; | 326 | return -ENODEV; |
498 | 327 | ||
499 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | 328 | for (i = 0; i < chip->nr_allocated_banks; i++) |
500 | memset(digest_list, 0, sizeof(digest_list)); | 329 | if (digests[i].alg_id != chip->allocated_banks[i].alg_id) |
501 | 330 | return -EINVAL; | |
502 | for (i = 0; i < ARRAY_SIZE(chip->active_banks) && | ||
503 | chip->active_banks[i] != TPM2_ALG_ERROR; i++) { | ||
504 | digest_list[i].alg_id = chip->active_banks[i]; | ||
505 | memcpy(digest_list[i].digest, hash, TPM_DIGEST_SIZE); | ||
506 | count++; | ||
507 | } | ||
508 | 331 | ||
509 | rc = tpm2_pcr_extend(chip, pcr_idx, count, digest_list); | 332 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
333 | rc = tpm2_pcr_extend(chip, pcr_idx, digests); | ||
510 | tpm_put_ops(chip); | 334 | tpm_put_ops(chip); |
511 | return rc; | 335 | return rc; |
512 | } | 336 | } |
513 | 337 | ||
514 | rc = tpm1_pcr_extend(chip, pcr_idx, hash, | 338 | rc = tpm1_pcr_extend(chip, pcr_idx, digests[0].digest, |
515 | "attempting extend a PCR value"); | 339 | "attempting extend a PCR value"); |
516 | tpm_put_ops(chip); | 340 | tpm_put_ops(chip); |
517 | return rc; | 341 | return rc; |
@@ -528,14 +352,21 @@ EXPORT_SYMBOL_GPL(tpm_pcr_extend); | |||
528 | */ | 352 | */ |
529 | int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) | 353 | int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) |
530 | { | 354 | { |
355 | struct tpm_buf buf; | ||
531 | int rc; | 356 | int rc; |
532 | 357 | ||
533 | chip = tpm_find_get_ops(chip); | 358 | chip = tpm_find_get_ops(chip); |
534 | if (!chip) | 359 | if (!chip) |
535 | return -ENODEV; | 360 | return -ENODEV; |
536 | 361 | ||
537 | rc = tpm_transmit_cmd(chip, NULL, cmd, buflen, 0, 0, | 362 | rc = tpm_buf_init(&buf, 0, 0); |
538 | "attempting to a send a command"); | 363 | if (rc) |
364 | goto out; | ||
365 | |||
366 | memcpy(buf.data, cmd, buflen); | ||
367 | rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to a send a command"); | ||
368 | tpm_buf_destroy(&buf); | ||
369 | out: | ||
539 | tpm_put_ops(chip); | 370 | tpm_put_ops(chip); |
540 | return rc; | 371 | return rc; |
541 | } | 372 | } |
@@ -571,10 +402,16 @@ int tpm_pm_suspend(struct device *dev) | |||
571 | if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED) | 402 | if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED) |
572 | return 0; | 403 | return 0; |
573 | 404 | ||
574 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 405 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
575 | tpm2_shutdown(chip, TPM2_SU_STATE); | 406 | mutex_lock(&chip->tpm_mutex); |
576 | else | 407 | if (!tpm_chip_start(chip)) { |
408 | tpm2_shutdown(chip, TPM2_SU_STATE); | ||
409 | tpm_chip_stop(chip); | ||
410 | } | ||
411 | mutex_unlock(&chip->tpm_mutex); | ||
412 | } else { | ||
577 | rc = tpm1_pm_suspend(chip, tpm_suspend_pcr); | 413 | rc = tpm1_pm_suspend(chip, tpm_suspend_pcr); |
414 | } | ||
578 | 415 | ||
579 | return rc; | 416 | return rc; |
580 | } | 417 | } |
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index b88e08ec2c59..533a260d744e 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c | |||
@@ -39,7 +39,6 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | |||
39 | { | 39 | { |
40 | struct tpm_buf tpm_buf; | 40 | struct tpm_buf tpm_buf; |
41 | struct tpm_readpubek_out *out; | 41 | struct tpm_readpubek_out *out; |
42 | ssize_t rc; | ||
43 | int i; | 42 | int i; |
44 | char *str = buf; | 43 | char *str = buf; |
45 | struct tpm_chip *chip = to_tpm_chip(dev); | 44 | struct tpm_chip *chip = to_tpm_chip(dev); |
@@ -47,19 +46,17 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | |||
47 | 46 | ||
48 | memset(&anti_replay, 0, sizeof(anti_replay)); | 47 | memset(&anti_replay, 0, sizeof(anti_replay)); |
49 | 48 | ||
50 | rc = tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK); | 49 | if (tpm_try_get_ops(chip)) |
51 | if (rc) | 50 | return 0; |
52 | return rc; | 51 | |
52 | if (tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK)) | ||
53 | goto out_ops; | ||
53 | 54 | ||
54 | tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay)); | 55 | tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay)); |
55 | 56 | ||
56 | rc = tpm_transmit_cmd(chip, NULL, tpm_buf.data, PAGE_SIZE, | 57 | if (tpm_transmit_cmd(chip, &tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE, |
57 | READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, | 58 | "attempting to read the PUBEK")) |
58 | "attempting to read the PUBEK"); | 59 | goto out_buf; |
59 | if (rc) { | ||
60 | tpm_buf_destroy(&tpm_buf); | ||
61 | return 0; | ||
62 | } | ||
63 | 60 | ||
64 | out = (struct tpm_readpubek_out *)&tpm_buf.data[10]; | 61 | out = (struct tpm_readpubek_out *)&tpm_buf.data[10]; |
65 | str += | 62 | str += |
@@ -90,9 +87,11 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | |||
90 | str += sprintf(str, "\n"); | 87 | str += sprintf(str, "\n"); |
91 | } | 88 | } |
92 | 89 | ||
93 | rc = str - buf; | 90 | out_buf: |
94 | tpm_buf_destroy(&tpm_buf); | 91 | tpm_buf_destroy(&tpm_buf); |
95 | return rc; | 92 | out_ops: |
93 | tpm_put_ops(chip); | ||
94 | return str - buf; | ||
96 | } | 95 | } |
97 | static DEVICE_ATTR_RO(pubek); | 96 | static DEVICE_ATTR_RO(pubek); |
98 | 97 | ||
@@ -101,27 +100,32 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr, | |||
101 | { | 100 | { |
102 | cap_t cap; | 101 | cap_t cap; |
103 | u8 digest[TPM_DIGEST_SIZE]; | 102 | u8 digest[TPM_DIGEST_SIZE]; |
104 | ssize_t rc; | ||
105 | u32 i, j, num_pcrs; | 103 | u32 i, j, num_pcrs; |
106 | char *str = buf; | 104 | char *str = buf; |
107 | struct tpm_chip *chip = to_tpm_chip(dev); | 105 | struct tpm_chip *chip = to_tpm_chip(dev); |
108 | 106 | ||
109 | rc = tpm1_getcap(chip, TPM_CAP_PROP_PCR, &cap, | 107 | if (tpm_try_get_ops(chip)) |
110 | "attempting to determine the number of PCRS", | ||
111 | sizeof(cap.num_pcrs)); | ||
112 | if (rc) | ||
113 | return 0; | 108 | return 0; |
114 | 109 | ||
110 | if (tpm1_getcap(chip, TPM_CAP_PROP_PCR, &cap, | ||
111 | "attempting to determine the number of PCRS", | ||
112 | sizeof(cap.num_pcrs))) { | ||
113 | tpm_put_ops(chip); | ||
114 | return 0; | ||
115 | } | ||
116 | |||
115 | num_pcrs = be32_to_cpu(cap.num_pcrs); | 117 | num_pcrs = be32_to_cpu(cap.num_pcrs); |
116 | for (i = 0; i < num_pcrs; i++) { | 118 | for (i = 0; i < num_pcrs; i++) { |
117 | rc = tpm1_pcr_read(chip, i, digest); | 119 | if (tpm1_pcr_read(chip, i, digest)) { |
118 | if (rc) | 120 | str = buf; |
119 | break; | 121 | break; |
122 | } | ||
120 | str += sprintf(str, "PCR-%02d: ", i); | 123 | str += sprintf(str, "PCR-%02d: ", i); |
121 | for (j = 0; j < TPM_DIGEST_SIZE; j++) | 124 | for (j = 0; j < TPM_DIGEST_SIZE; j++) |
122 | str += sprintf(str, "%02X ", digest[j]); | 125 | str += sprintf(str, "%02X ", digest[j]); |
123 | str += sprintf(str, "\n"); | 126 | str += sprintf(str, "\n"); |
124 | } | 127 | } |
128 | tpm_put_ops(chip); | ||
125 | return str - buf; | 129 | return str - buf; |
126 | } | 130 | } |
127 | static DEVICE_ATTR_RO(pcrs); | 131 | static DEVICE_ATTR_RO(pcrs); |
@@ -129,16 +133,21 @@ static DEVICE_ATTR_RO(pcrs); | |||
129 | static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, | 133 | static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, |
130 | char *buf) | 134 | char *buf) |
131 | { | 135 | { |
136 | struct tpm_chip *chip = to_tpm_chip(dev); | ||
137 | ssize_t rc = 0; | ||
132 | cap_t cap; | 138 | cap_t cap; |
133 | ssize_t rc; | ||
134 | 139 | ||
135 | rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, | 140 | if (tpm_try_get_ops(chip)) |
136 | "attempting to determine the permanent enabled state", | ||
137 | sizeof(cap.perm_flags)); | ||
138 | if (rc) | ||
139 | return 0; | 141 | return 0; |
140 | 142 | ||
143 | if (tpm1_getcap(chip, TPM_CAP_FLAG_PERM, &cap, | ||
144 | "attempting to determine the permanent enabled state", | ||
145 | sizeof(cap.perm_flags))) | ||
146 | goto out_ops; | ||
147 | |||
141 | rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); | 148 | rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); |
149 | out_ops: | ||
150 | tpm_put_ops(chip); | ||
142 | return rc; | 151 | return rc; |
143 | } | 152 | } |
144 | static DEVICE_ATTR_RO(enabled); | 153 | static DEVICE_ATTR_RO(enabled); |
@@ -146,16 +155,21 @@ static DEVICE_ATTR_RO(enabled); | |||
146 | static ssize_t active_show(struct device *dev, struct device_attribute *attr, | 155 | static ssize_t active_show(struct device *dev, struct device_attribute *attr, |
147 | char *buf) | 156 | char *buf) |
148 | { | 157 | { |
158 | struct tpm_chip *chip = to_tpm_chip(dev); | ||
159 | ssize_t rc = 0; | ||
149 | cap_t cap; | 160 | cap_t cap; |
150 | ssize_t rc; | ||
151 | 161 | ||
152 | rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, | 162 | if (tpm_try_get_ops(chip)) |
153 | "attempting to determine the permanent active state", | ||
154 | sizeof(cap.perm_flags)); | ||
155 | if (rc) | ||
156 | return 0; | 163 | return 0; |
157 | 164 | ||
165 | if (tpm1_getcap(chip, TPM_CAP_FLAG_PERM, &cap, | ||
166 | "attempting to determine the permanent active state", | ||
167 | sizeof(cap.perm_flags))) | ||
168 | goto out_ops; | ||
169 | |||
158 | rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); | 170 | rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); |
171 | out_ops: | ||
172 | tpm_put_ops(chip); | ||
159 | return rc; | 173 | return rc; |
160 | } | 174 | } |
161 | static DEVICE_ATTR_RO(active); | 175 | static DEVICE_ATTR_RO(active); |
@@ -163,16 +177,21 @@ static DEVICE_ATTR_RO(active); | |||
163 | static ssize_t owned_show(struct device *dev, struct device_attribute *attr, | 177 | static ssize_t owned_show(struct device *dev, struct device_attribute *attr, |
164 | char *buf) | 178 | char *buf) |
165 | { | 179 | { |
180 | struct tpm_chip *chip = to_tpm_chip(dev); | ||
181 | ssize_t rc = 0; | ||
166 | cap_t cap; | 182 | cap_t cap; |
167 | ssize_t rc; | ||
168 | 183 | ||
169 | rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap, | 184 | if (tpm_try_get_ops(chip)) |
170 | "attempting to determine the owner state", | ||
171 | sizeof(cap.owned)); | ||
172 | if (rc) | ||
173 | return 0; | 185 | return 0; |
174 | 186 | ||
187 | if (tpm1_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap, | ||
188 | "attempting to determine the owner state", | ||
189 | sizeof(cap.owned))) | ||
190 | goto out_ops; | ||
191 | |||
175 | rc = sprintf(buf, "%d\n", cap.owned); | 192 | rc = sprintf(buf, "%d\n", cap.owned); |
193 | out_ops: | ||
194 | tpm_put_ops(chip); | ||
176 | return rc; | 195 | return rc; |
177 | } | 196 | } |
178 | static DEVICE_ATTR_RO(owned); | 197 | static DEVICE_ATTR_RO(owned); |
@@ -180,16 +199,21 @@ static DEVICE_ATTR_RO(owned); | |||
180 | static ssize_t temp_deactivated_show(struct device *dev, | 199 | static ssize_t temp_deactivated_show(struct device *dev, |
181 | struct device_attribute *attr, char *buf) | 200 | struct device_attribute *attr, char *buf) |
182 | { | 201 | { |
202 | struct tpm_chip *chip = to_tpm_chip(dev); | ||
203 | ssize_t rc = 0; | ||
183 | cap_t cap; | 204 | cap_t cap; |
184 | ssize_t rc; | ||
185 | 205 | ||
186 | rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap, | 206 | if (tpm_try_get_ops(chip)) |
187 | "attempting to determine the temporary state", | ||
188 | sizeof(cap.stclear_flags)); | ||
189 | if (rc) | ||
190 | return 0; | 207 | return 0; |
191 | 208 | ||
209 | if (tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap, | ||
210 | "attempting to determine the temporary state", | ||
211 | sizeof(cap.stclear_flags))) | ||
212 | goto out_ops; | ||
213 | |||
192 | rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); | 214 | rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); |
215 | out_ops: | ||
216 | tpm_put_ops(chip); | ||
193 | return rc; | 217 | return rc; |
194 | } | 218 | } |
195 | static DEVICE_ATTR_RO(temp_deactivated); | 219 | static DEVICE_ATTR_RO(temp_deactivated); |
@@ -198,15 +222,18 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr, | |||
198 | char *buf) | 222 | char *buf) |
199 | { | 223 | { |
200 | struct tpm_chip *chip = to_tpm_chip(dev); | 224 | struct tpm_chip *chip = to_tpm_chip(dev); |
201 | cap_t cap; | 225 | ssize_t rc = 0; |
202 | ssize_t rc; | ||
203 | char *str = buf; | 226 | char *str = buf; |
227 | cap_t cap; | ||
204 | 228 | ||
205 | rc = tpm1_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap, | 229 | if (tpm_try_get_ops(chip)) |
206 | "attempting to determine the manufacturer", | ||
207 | sizeof(cap.manufacturer_id)); | ||
208 | if (rc) | ||
209 | return 0; | 230 | return 0; |
231 | |||
232 | if (tpm1_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap, | ||
233 | "attempting to determine the manufacturer", | ||
234 | sizeof(cap.manufacturer_id))) | ||
235 | goto out_ops; | ||
236 | |||
210 | str += sprintf(str, "Manufacturer: 0x%x\n", | 237 | str += sprintf(str, "Manufacturer: 0x%x\n", |
211 | be32_to_cpu(cap.manufacturer_id)); | 238 | be32_to_cpu(cap.manufacturer_id)); |
212 | 239 | ||
@@ -223,11 +250,10 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr, | |||
223 | cap.tpm_version_1_2.revMinor); | 250 | cap.tpm_version_1_2.revMinor); |
224 | } else { | 251 | } else { |
225 | /* Otherwise just use TPM_STRUCT_VER */ | 252 | /* Otherwise just use TPM_STRUCT_VER */ |
226 | rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, | 253 | if (tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, |
227 | "attempting to determine the 1.1 version", | 254 | "attempting to determine the 1.1 version", |
228 | sizeof(cap.tpm_version)); | 255 | sizeof(cap.tpm_version))) |
229 | if (rc) | 256 | goto out_ops; |
230 | return 0; | ||
231 | str += sprintf(str, | 257 | str += sprintf(str, |
232 | "TCG version: %d.%d\nFirmware version: %d.%d\n", | 258 | "TCG version: %d.%d\nFirmware version: %d.%d\n", |
233 | cap.tpm_version.Major, | 259 | cap.tpm_version.Major, |
@@ -235,8 +261,10 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr, | |||
235 | cap.tpm_version.revMajor, | 261 | cap.tpm_version.revMajor, |
236 | cap.tpm_version.revMinor); | 262 | cap.tpm_version.revMinor); |
237 | } | 263 | } |
238 | 264 | rc = str - buf; | |
239 | return str - buf; | 265 | out_ops: |
266 | tpm_put_ops(chip); | ||
267 | return rc; | ||
240 | } | 268 | } |
241 | static DEVICE_ATTR_RO(caps); | 269 | static DEVICE_ATTR_RO(caps); |
242 | 270 | ||
@@ -244,10 +272,12 @@ static ssize_t cancel_store(struct device *dev, struct device_attribute *attr, | |||
244 | const char *buf, size_t count) | 272 | const char *buf, size_t count) |
245 | { | 273 | { |
246 | struct tpm_chip *chip = to_tpm_chip(dev); | 274 | struct tpm_chip *chip = to_tpm_chip(dev); |
247 | if (chip == NULL) | 275 | |
276 | if (tpm_try_get_ops(chip)) | ||
248 | return 0; | 277 | return 0; |
249 | 278 | ||
250 | chip->ops->cancel(chip); | 279 | chip->ops->cancel(chip); |
280 | tpm_put_ops(chip); | ||
251 | return count; | 281 | return count; |
252 | } | 282 | } |
253 | static DEVICE_ATTR_WO(cancel); | 283 | static DEVICE_ATTR_WO(cancel); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index f27d1f38a93d..2cce072f25b5 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -25,30 +25,22 @@ | |||
25 | 25 | ||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/fs.h> | ||
29 | #include <linux/hw_random.h> | ||
30 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
31 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
32 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
33 | #include <linux/io.h> | 31 | #include <linux/io.h> |
34 | #include <linux/tpm.h> | 32 | #include <linux/tpm.h> |
35 | #include <linux/acpi.h> | ||
36 | #include <linux/cdev.h> | ||
37 | #include <linux/highmem.h> | 33 | #include <linux/highmem.h> |
38 | #include <linux/tpm_eventlog.h> | 34 | #include <linux/tpm_eventlog.h> |
39 | #include <crypto/hash_info.h> | ||
40 | 35 | ||
41 | #ifdef CONFIG_X86 | 36 | #ifdef CONFIG_X86 |
42 | #include <asm/intel-family.h> | 37 | #include <asm/intel-family.h> |
43 | #endif | 38 | #endif |
44 | 39 | ||
45 | enum tpm_const { | 40 | #define TPM_MINOR 224 /* officially assigned */ |
46 | TPM_MINOR = 224, /* officially assigned */ | 41 | #define TPM_BUFSIZE 4096 |
47 | TPM_BUFSIZE = 4096, | 42 | #define TPM_NUM_DEVICES 65536 |
48 | TPM_NUM_DEVICES = 65536, | 43 | #define TPM_RETRY 50 |
49 | TPM_RETRY = 50, /* 5 seconds */ | ||
50 | TPM_NUM_EVENT_LOG_FILES = 3, | ||
51 | }; | ||
52 | 44 | ||
53 | enum tpm_timeout { | 45 | enum tpm_timeout { |
54 | TPM_TIMEOUT = 5, /* msecs */ | 46 | TPM_TIMEOUT = 5, /* msecs */ |
@@ -65,16 +57,6 @@ enum tpm_addr { | |||
65 | TPM_ADDR = 0x4E, | 57 | TPM_ADDR = 0x4E, |
66 | }; | 58 | }; |
67 | 59 | ||
68 | /* Indexes the duration array */ | ||
69 | enum tpm_duration { | ||
70 | TPM_SHORT = 0, | ||
71 | TPM_MEDIUM = 1, | ||
72 | TPM_LONG = 2, | ||
73 | TPM_LONG_LONG = 3, | ||
74 | TPM_UNDEFINED, | ||
75 | TPM_NUM_DURATIONS = TPM_UNDEFINED, | ||
76 | }; | ||
77 | |||
78 | #define TPM_WARN_RETRY 0x800 | 60 | #define TPM_WARN_RETRY 0x800 |
79 | #define TPM_WARN_DOING_SELFTEST 0x802 | 61 | #define TPM_WARN_DOING_SELFTEST 0x802 |
80 | #define TPM_ERR_DEACTIVATED 0x6 | 62 | #define TPM_ERR_DEACTIVATED 0x6 |
@@ -122,17 +104,6 @@ enum tpm2_return_codes { | |||
122 | TPM2_RC_RETRY = 0x0922, | 104 | TPM2_RC_RETRY = 0x0922, |
123 | }; | 105 | }; |
124 | 106 | ||
125 | enum tpm2_algorithms { | ||
126 | TPM2_ALG_ERROR = 0x0000, | ||
127 | TPM2_ALG_SHA1 = 0x0004, | ||
128 | TPM2_ALG_KEYEDHASH = 0x0008, | ||
129 | TPM2_ALG_SHA256 = 0x000B, | ||
130 | TPM2_ALG_SHA384 = 0x000C, | ||
131 | TPM2_ALG_SHA512 = 0x000D, | ||
132 | TPM2_ALG_NULL = 0x0010, | ||
133 | TPM2_ALG_SM3_256 = 0x0012, | ||
134 | }; | ||
135 | |||
136 | enum tpm2_command_codes { | 107 | enum tpm2_command_codes { |
137 | TPM2_CC_FIRST = 0x011F, | 108 | TPM2_CC_FIRST = 0x011F, |
138 | TPM2_CC_HIERARCHY_CONTROL = 0x0121, | 109 | TPM2_CC_HIERARCHY_CONTROL = 0x0121, |
@@ -190,15 +161,6 @@ enum tpm2_cc_attrs { | |||
190 | #define TPM_VID_WINBOND 0x1050 | 161 | #define TPM_VID_WINBOND 0x1050 |
191 | #define TPM_VID_STM 0x104A | 162 | #define TPM_VID_STM 0x104A |
192 | 163 | ||
193 | #define TPM_PPI_VERSION_LEN 3 | ||
194 | |||
195 | struct tpm_space { | ||
196 | u32 context_tbl[3]; | ||
197 | u8 *context_buf; | ||
198 | u32 session_tbl[3]; | ||
199 | u8 *session_buf; | ||
200 | }; | ||
201 | |||
202 | enum tpm_chip_flags { | 164 | enum tpm_chip_flags { |
203 | TPM_CHIP_FLAG_TPM2 = BIT(1), | 165 | TPM_CHIP_FLAG_TPM2 = BIT(1), |
204 | TPM_CHIP_FLAG_IRQ = BIT(2), | 166 | TPM_CHIP_FLAG_IRQ = BIT(2), |
@@ -207,82 +169,15 @@ enum tpm_chip_flags { | |||
207 | TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5), | 169 | TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5), |
208 | }; | 170 | }; |
209 | 171 | ||
210 | struct tpm_bios_log { | ||
211 | void *bios_event_log; | ||
212 | void *bios_event_log_end; | ||
213 | }; | ||
214 | |||
215 | struct tpm_chip_seqops { | ||
216 | struct tpm_chip *chip; | ||
217 | const struct seq_operations *seqops; | ||
218 | }; | ||
219 | |||
220 | struct tpm_chip { | ||
221 | struct device dev; | ||
222 | struct device devs; | ||
223 | struct cdev cdev; | ||
224 | struct cdev cdevs; | ||
225 | |||
226 | /* A driver callback under ops cannot be run unless ops_sem is held | ||
227 | * (sometimes implicitly, eg for the sysfs code). ops becomes null | ||
228 | * when the driver is unregistered, see tpm_try_get_ops. | ||
229 | */ | ||
230 | struct rw_semaphore ops_sem; | ||
231 | const struct tpm_class_ops *ops; | ||
232 | |||
233 | struct tpm_bios_log log; | ||
234 | struct tpm_chip_seqops bin_log_seqops; | ||
235 | struct tpm_chip_seqops ascii_log_seqops; | ||
236 | |||
237 | unsigned int flags; | ||
238 | |||
239 | int dev_num; /* /dev/tpm# */ | ||
240 | unsigned long is_open; /* only one allowed */ | ||
241 | |||
242 | char hwrng_name[64]; | ||
243 | struct hwrng hwrng; | ||
244 | |||
245 | struct mutex tpm_mutex; /* tpm is processing */ | ||
246 | |||
247 | unsigned long timeout_a; /* jiffies */ | ||
248 | unsigned long timeout_b; /* jiffies */ | ||
249 | unsigned long timeout_c; /* jiffies */ | ||
250 | unsigned long timeout_d; /* jiffies */ | ||
251 | bool timeout_adjusted; | ||
252 | unsigned long duration[TPM_NUM_DURATIONS]; /* jiffies */ | ||
253 | bool duration_adjusted; | ||
254 | |||
255 | struct dentry *bios_dir[TPM_NUM_EVENT_LOG_FILES]; | ||
256 | |||
257 | const struct attribute_group *groups[3]; | ||
258 | unsigned int groups_cnt; | ||
259 | |||
260 | u16 active_banks[7]; | ||
261 | #ifdef CONFIG_ACPI | ||
262 | acpi_handle acpi_dev_handle; | ||
263 | char ppi_version[TPM_PPI_VERSION_LEN + 1]; | ||
264 | #endif /* CONFIG_ACPI */ | ||
265 | |||
266 | struct tpm_space work_space; | ||
267 | u32 nr_commands; | ||
268 | u32 *cc_attrs_tbl; | ||
269 | |||
270 | /* active locality */ | ||
271 | int locality; | ||
272 | }; | ||
273 | |||
274 | #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) | 172 | #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) |
275 | 173 | ||
276 | struct tpm_input_header { | 174 | struct tpm_header { |
277 | __be16 tag; | 175 | __be16 tag; |
278 | __be32 length; | 176 | __be32 length; |
279 | __be32 ordinal; | 177 | union { |
280 | } __packed; | 178 | __be32 ordinal; |
281 | 179 | __be32 return_code; | |
282 | struct tpm_output_header { | 180 | }; |
283 | __be16 tag; | ||
284 | __be32 length; | ||
285 | __be32 return_code; | ||
286 | } __packed; | 181 | } __packed; |
287 | 182 | ||
288 | #define TPM_TAG_RQU_COMMAND 193 | 183 | #define TPM_TAG_RQU_COMMAND 193 |
@@ -401,8 +296,8 @@ struct tpm_buf { | |||
401 | 296 | ||
402 | static inline void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal) | 297 | static inline void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal) |
403 | { | 298 | { |
404 | struct tpm_input_header *head; | 299 | struct tpm_header *head = (struct tpm_header *)buf->data; |
405 | head = (struct tpm_input_header *)buf->data; | 300 | |
406 | head->tag = cpu_to_be16(tag); | 301 | head->tag = cpu_to_be16(tag); |
407 | head->length = cpu_to_be32(sizeof(*head)); | 302 | head->length = cpu_to_be32(sizeof(*head)); |
408 | head->ordinal = cpu_to_be32(ordinal); | 303 | head->ordinal = cpu_to_be32(ordinal); |
@@ -428,14 +323,14 @@ static inline void tpm_buf_destroy(struct tpm_buf *buf) | |||
428 | 323 | ||
429 | static inline u32 tpm_buf_length(struct tpm_buf *buf) | 324 | static inline u32 tpm_buf_length(struct tpm_buf *buf) |
430 | { | 325 | { |
431 | struct tpm_input_header *head = (struct tpm_input_header *) buf->data; | 326 | struct tpm_header *head = (struct tpm_header *)buf->data; |
432 | 327 | ||
433 | return be32_to_cpu(head->length); | 328 | return be32_to_cpu(head->length); |
434 | } | 329 | } |
435 | 330 | ||
436 | static inline u16 tpm_buf_tag(struct tpm_buf *buf) | 331 | static inline u16 tpm_buf_tag(struct tpm_buf *buf) |
437 | { | 332 | { |
438 | struct tpm_input_header *head = (struct tpm_input_header *) buf->data; | 333 | struct tpm_header *head = (struct tpm_header *)buf->data; |
439 | 334 | ||
440 | return be16_to_cpu(head->tag); | 335 | return be16_to_cpu(head->tag); |
441 | } | 336 | } |
@@ -444,7 +339,7 @@ static inline void tpm_buf_append(struct tpm_buf *buf, | |||
444 | const unsigned char *new_data, | 339 | const unsigned char *new_data, |
445 | unsigned int new_len) | 340 | unsigned int new_len) |
446 | { | 341 | { |
447 | struct tpm_input_header *head = (struct tpm_input_header *) buf->data; | 342 | struct tpm_header *head = (struct tpm_header *)buf->data; |
448 | u32 len = tpm_buf_length(buf); | 343 | u32 len = tpm_buf_length(buf); |
449 | 344 | ||
450 | /* Return silently if overflow has already happened. */ | 345 | /* Return silently if overflow has already happened. */ |
@@ -487,25 +382,9 @@ extern const struct file_operations tpm_fops; | |||
487 | extern const struct file_operations tpmrm_fops; | 382 | extern const struct file_operations tpmrm_fops; |
488 | extern struct idr dev_nums_idr; | 383 | extern struct idr dev_nums_idr; |
489 | 384 | ||
490 | /** | 385 | ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz); |
491 | * enum tpm_transmit_flags - flags for tpm_transmit() | 386 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf, |
492 | * | 387 | size_t min_rsp_body_length, const char *desc); |
493 | * @TPM_TRANSMIT_UNLOCKED: do not lock the chip | ||
494 | * @TPM_TRANSMIT_NESTED: discard setup steps (power management, | ||
495 | * locality) including locking (i.e. implicit | ||
496 | * UNLOCKED) | ||
497 | */ | ||
498 | enum tpm_transmit_flags { | ||
499 | TPM_TRANSMIT_UNLOCKED = BIT(0), | ||
500 | TPM_TRANSMIT_NESTED = BIT(1), | ||
501 | }; | ||
502 | |||
503 | ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | ||
504 | u8 *buf, size_t bufsiz, unsigned int flags); | ||
505 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, | ||
506 | void *buf, size_t bufsiz, | ||
507 | size_t min_rsp_body_length, unsigned int flags, | ||
508 | const char *desc); | ||
509 | int tpm_get_timeouts(struct tpm_chip *); | 388 | int tpm_get_timeouts(struct tpm_chip *); |
510 | int tpm_auto_startup(struct tpm_chip *chip); | 389 | int tpm_auto_startup(struct tpm_chip *chip); |
511 | 390 | ||
@@ -530,6 +409,8 @@ static inline void tpm_msleep(unsigned int delay_msec) | |||
530 | delay_msec * 1000); | 409 | delay_msec * 1000); |
531 | }; | 410 | }; |
532 | 411 | ||
412 | int tpm_chip_start(struct tpm_chip *chip); | ||
413 | void tpm_chip_stop(struct tpm_chip *chip); | ||
533 | struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip); | 414 | struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip); |
534 | __must_check int tpm_try_get_ops(struct tpm_chip *chip); | 415 | __must_check int tpm_try_get_ops(struct tpm_chip *chip); |
535 | void tpm_put_ops(struct tpm_chip *chip); | 416 | void tpm_put_ops(struct tpm_chip *chip); |
@@ -558,12 +439,12 @@ static inline u32 tpm2_rc_value(u32 rc) | |||
558 | } | 439 | } |
559 | 440 | ||
560 | int tpm2_get_timeouts(struct tpm_chip *chip); | 441 | int tpm2_get_timeouts(struct tpm_chip *chip); |
561 | int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf); | 442 | int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, |
562 | int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, u32 count, | 443 | struct tpm_digest *digest, u16 *digest_size_ptr); |
563 | struct tpm2_digest *digests); | 444 | int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, |
445 | struct tpm_digest *digests); | ||
564 | int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max); | 446 | int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max); |
565 | void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, | 447 | void tpm2_flush_context(struct tpm_chip *chip, u32 handle); |
566 | unsigned int flags); | ||
567 | int tpm2_seal_trusted(struct tpm_chip *chip, | 448 | int tpm2_seal_trusted(struct tpm_chip *chip, |
568 | struct trusted_key_payload *payload, | 449 | struct trusted_key_payload *payload, |
569 | struct trusted_key_options *options); | 450 | struct trusted_key_options *options); |
@@ -580,10 +461,11 @@ int tpm2_probe(struct tpm_chip *chip); | |||
580 | int tpm2_find_cc(struct tpm_chip *chip, u32 cc); | 461 | int tpm2_find_cc(struct tpm_chip *chip, u32 cc); |
581 | int tpm2_init_space(struct tpm_space *space); | 462 | int tpm2_init_space(struct tpm_space *space); |
582 | void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space); | 463 | void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space); |
583 | int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc, | 464 | void tpm2_flush_space(struct tpm_chip *chip); |
584 | u8 *cmd); | 465 | int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd, |
585 | int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, | 466 | size_t cmdsiz); |
586 | u32 cc, u8 *buf, size_t *bufsiz); | 467 | int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, void *buf, |
468 | size_t *bufsiz); | ||
587 | 469 | ||
588 | int tpm_bios_log_setup(struct tpm_chip *chip); | 470 | int tpm_bios_log_setup(struct tpm_chip *chip); |
589 | void tpm_bios_log_teardown(struct tpm_chip *chip); | 471 | void tpm_bios_log_teardown(struct tpm_chip *chip); |
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c index 6f306338953b..85dcf2654d11 100644 --- a/drivers/char/tpm/tpm1-cmd.c +++ b/drivers/char/tpm/tpm1-cmd.c | |||
@@ -334,11 +334,8 @@ static int tpm1_startup(struct tpm_chip *chip) | |||
334 | 334 | ||
335 | tpm_buf_append_u16(&buf, TPM_ST_CLEAR); | 335 | tpm_buf_append_u16(&buf, TPM_ST_CLEAR); |
336 | 336 | ||
337 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, | 337 | rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM"); |
338 | "attempting to start the TPM"); | ||
339 | |||
340 | tpm_buf_destroy(&buf); | 338 | tpm_buf_destroy(&buf); |
341 | |||
342 | return rc; | 339 | return rc; |
343 | } | 340 | } |
344 | 341 | ||
@@ -380,8 +377,7 @@ int tpm1_get_timeouts(struct tpm_chip *chip) | |||
380 | * of misreporting. | 377 | * of misreporting. |
381 | */ | 378 | */ |
382 | if (chip->ops->update_timeouts) | 379 | if (chip->ops->update_timeouts) |
383 | chip->timeout_adjusted = | 380 | chip->ops->update_timeouts(chip, timeout_eff); |
384 | chip->ops->update_timeouts(chip, timeout_eff); | ||
385 | 381 | ||
386 | if (!chip->timeout_adjusted) { | 382 | if (!chip->timeout_adjusted) { |
387 | /* Restore default if chip reported 0 */ | 383 | /* Restore default if chip reported 0 */ |
@@ -462,9 +458,7 @@ int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash, | |||
462 | tpm_buf_append_u32(&buf, pcr_idx); | 458 | tpm_buf_append_u32(&buf, pcr_idx); |
463 | tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE); | 459 | tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE); |
464 | 460 | ||
465 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, | 461 | rc = tpm_transmit_cmd(chip, &buf, TPM_DIGEST_SIZE, log_msg); |
466 | TPM_DIGEST_SIZE, 0, log_msg); | ||
467 | |||
468 | tpm_buf_destroy(&buf); | 462 | tpm_buf_destroy(&buf); |
469 | return rc; | 463 | return rc; |
470 | } | 464 | } |
@@ -494,11 +488,9 @@ ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, | |||
494 | tpm_buf_append_u32(&buf, 4); | 488 | tpm_buf_append_u32(&buf, 4); |
495 | tpm_buf_append_u32(&buf, subcap_id); | 489 | tpm_buf_append_u32(&buf, subcap_id); |
496 | } | 490 | } |
497 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, | 491 | rc = tpm_transmit_cmd(chip, &buf, min_cap_length, desc); |
498 | min_cap_length, 0, desc); | ||
499 | if (!rc) | 492 | if (!rc) |
500 | *cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4]; | 493 | *cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4]; |
501 | |||
502 | tpm_buf_destroy(&buf); | 494 | tpm_buf_destroy(&buf); |
503 | return rc; | 495 | return rc; |
504 | } | 496 | } |
@@ -537,8 +529,7 @@ int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max) | |||
537 | do { | 529 | do { |
538 | tpm_buf_append_u32(&buf, num_bytes); | 530 | tpm_buf_append_u32(&buf, num_bytes); |
539 | 531 | ||
540 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, | 532 | rc = tpm_transmit_cmd(chip, &buf, sizeof(out->rng_data_len), |
541 | sizeof(out->rng_data_len), 0, | ||
542 | "attempting get random"); | 533 | "attempting get random"); |
543 | if (rc) | 534 | if (rc) |
544 | goto out; | 535 | goto out; |
@@ -583,8 +574,7 @@ int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) | |||
583 | 574 | ||
584 | tpm_buf_append_u32(&buf, pcr_idx); | 575 | tpm_buf_append_u32(&buf, pcr_idx); |
585 | 576 | ||
586 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, | 577 | rc = tpm_transmit_cmd(chip, &buf, TPM_DIGEST_SIZE, |
587 | TPM_DIGEST_SIZE, 0, | ||
588 | "attempting to read a pcr value"); | 578 | "attempting to read a pcr value"); |
589 | if (rc) | 579 | if (rc) |
590 | goto out; | 580 | goto out; |
@@ -618,11 +608,8 @@ static int tpm1_continue_selftest(struct tpm_chip *chip) | |||
618 | if (rc) | 608 | if (rc) |
619 | return rc; | 609 | return rc; |
620 | 610 | ||
621 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, | 611 | rc = tpm_transmit_cmd(chip, &buf, 0, "continue selftest"); |
622 | 0, 0, "continue selftest"); | ||
623 | |||
624 | tpm_buf_destroy(&buf); | 612 | tpm_buf_destroy(&buf); |
625 | |||
626 | return rc; | 613 | return rc; |
627 | } | 614 | } |
628 | 615 | ||
@@ -709,6 +696,18 @@ int tpm1_auto_startup(struct tpm_chip *chip) | |||
709 | goto out; | 696 | goto out; |
710 | } | 697 | } |
711 | 698 | ||
699 | chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks), | ||
700 | GFP_KERNEL); | ||
701 | if (!chip->allocated_banks) { | ||
702 | rc = -ENOMEM; | ||
703 | goto out; | ||
704 | } | ||
705 | |||
706 | chip->allocated_banks[0].alg_id = TPM_ALG_SHA1; | ||
707 | chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1]; | ||
708 | chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1; | ||
709 | chip->nr_allocated_banks = 1; | ||
710 | |||
712 | return rc; | 711 | return rc; |
713 | out: | 712 | out: |
714 | if (rc > 0) | 713 | if (rc > 0) |
@@ -747,9 +746,7 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr) | |||
747 | return rc; | 746 | return rc; |
748 | /* now do the actual savestate */ | 747 | /* now do the actual savestate */ |
749 | for (try = 0; try < TPM_RETRY; try++) { | 748 | for (try = 0; try < TPM_RETRY; try++) { |
750 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, | 749 | rc = tpm_transmit_cmd(chip, &buf, 0, NULL); |
751 | 0, 0, NULL); | ||
752 | |||
753 | /* | 750 | /* |
754 | * If the TPM indicates that it is too busy to respond to | 751 | * If the TPM indicates that it is too busy to respond to |
755 | * this command then retry before giving up. It can take | 752 | * this command then retry before giving up. It can take |
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index a6bec13afa69..e74c5b7b64bf 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
@@ -33,11 +33,11 @@ struct tpm2_hash { | |||
33 | }; | 33 | }; |
34 | 34 | ||
35 | static struct tpm2_hash tpm2_hash_map[] = { | 35 | static struct tpm2_hash tpm2_hash_map[] = { |
36 | {HASH_ALGO_SHA1, TPM2_ALG_SHA1}, | 36 | {HASH_ALGO_SHA1, TPM_ALG_SHA1}, |
37 | {HASH_ALGO_SHA256, TPM2_ALG_SHA256}, | 37 | {HASH_ALGO_SHA256, TPM_ALG_SHA256}, |
38 | {HASH_ALGO_SHA384, TPM2_ALG_SHA384}, | 38 | {HASH_ALGO_SHA384, TPM_ALG_SHA384}, |
39 | {HASH_ALGO_SHA512, TPM2_ALG_SHA512}, | 39 | {HASH_ALGO_SHA512, TPM_ALG_SHA512}, |
40 | {HASH_ALGO_SM3_256, TPM2_ALG_SM3_256}, | 40 | {HASH_ALGO_SM3_256, TPM_ALG_SM3_256}, |
41 | }; | 41 | }; |
42 | 42 | ||
43 | int tpm2_get_timeouts(struct tpm_chip *chip) | 43 | int tpm2_get_timeouts(struct tpm_chip *chip) |
@@ -171,20 +171,36 @@ struct tpm2_pcr_read_out { | |||
171 | * tpm2_pcr_read() - read a PCR value | 171 | * tpm2_pcr_read() - read a PCR value |
172 | * @chip: TPM chip to use. | 172 | * @chip: TPM chip to use. |
173 | * @pcr_idx: index of the PCR to read. | 173 | * @pcr_idx: index of the PCR to read. |
174 | * @res_buf: buffer to store the resulting hash. | 174 | * @digest: PCR bank and buffer current PCR value is written to. |
175 | * @digest_size_ptr: pointer to variable that stores the digest size. | ||
175 | * | 176 | * |
176 | * Return: Same as with tpm_transmit_cmd. | 177 | * Return: Same as with tpm_transmit_cmd. |
177 | */ | 178 | */ |
178 | int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) | 179 | int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, |
180 | struct tpm_digest *digest, u16 *digest_size_ptr) | ||
179 | { | 181 | { |
182 | int i; | ||
180 | int rc; | 183 | int rc; |
181 | struct tpm_buf buf; | 184 | struct tpm_buf buf; |
182 | struct tpm2_pcr_read_out *out; | 185 | struct tpm2_pcr_read_out *out; |
183 | u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0}; | 186 | u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0}; |
187 | u16 digest_size; | ||
188 | u16 expected_digest_size = 0; | ||
184 | 189 | ||
185 | if (pcr_idx >= TPM2_PLATFORM_PCR) | 190 | if (pcr_idx >= TPM2_PLATFORM_PCR) |
186 | return -EINVAL; | 191 | return -EINVAL; |
187 | 192 | ||
193 | if (!digest_size_ptr) { | ||
194 | for (i = 0; i < chip->nr_allocated_banks && | ||
195 | chip->allocated_banks[i].alg_id != digest->alg_id; i++) | ||
196 | ; | ||
197 | |||
198 | if (i == chip->nr_allocated_banks) | ||
199 | return -EINVAL; | ||
200 | |||
201 | expected_digest_size = chip->allocated_banks[i].digest_size; | ||
202 | } | ||
203 | |||
188 | rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ); | 204 | rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ); |
189 | if (rc) | 205 | if (rc) |
190 | return rc; | 206 | return rc; |
@@ -192,18 +208,28 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) | |||
192 | pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); | 208 | pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); |
193 | 209 | ||
194 | tpm_buf_append_u32(&buf, 1); | 210 | tpm_buf_append_u32(&buf, 1); |
195 | tpm_buf_append_u16(&buf, TPM2_ALG_SHA1); | 211 | tpm_buf_append_u16(&buf, digest->alg_id); |
196 | tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN); | 212 | tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN); |
197 | tpm_buf_append(&buf, (const unsigned char *)pcr_select, | 213 | tpm_buf_append(&buf, (const unsigned char *)pcr_select, |
198 | sizeof(pcr_select)); | 214 | sizeof(pcr_select)); |
199 | 215 | ||
200 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, | 216 | rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to read a pcr value"); |
201 | res_buf ? "attempting to read a pcr value" : NULL); | 217 | if (rc) |
202 | if (rc == 0 && res_buf) { | 218 | goto out; |
203 | out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE]; | 219 | |
204 | memcpy(res_buf, out->digest, SHA1_DIGEST_SIZE); | 220 | out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE]; |
221 | digest_size = be16_to_cpu(out->digest_size); | ||
222 | if (digest_size > sizeof(digest->digest) || | ||
223 | (!digest_size_ptr && digest_size != expected_digest_size)) { | ||
224 | rc = -EINVAL; | ||
225 | goto out; | ||
205 | } | 226 | } |
206 | 227 | ||
228 | if (digest_size_ptr) | ||
229 | *digest_size_ptr = digest_size; | ||
230 | |||
231 | memcpy(digest->digest, out->digest, digest_size); | ||
232 | out: | ||
207 | tpm_buf_destroy(&buf); | 233 | tpm_buf_destroy(&buf); |
208 | return rc; | 234 | return rc; |
209 | } | 235 | } |
@@ -220,22 +246,17 @@ struct tpm2_null_auth_area { | |||
220 | * | 246 | * |
221 | * @chip: TPM chip to use. | 247 | * @chip: TPM chip to use. |
222 | * @pcr_idx: index of the PCR. | 248 | * @pcr_idx: index of the PCR. |
223 | * @count: number of digests passed. | ||
224 | * @digests: list of pcr banks and corresponding digest values to extend. | 249 | * @digests: list of pcr banks and corresponding digest values to extend. |
225 | * | 250 | * |
226 | * Return: Same as with tpm_transmit_cmd. | 251 | * Return: Same as with tpm_transmit_cmd. |
227 | */ | 252 | */ |
228 | int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, u32 count, | 253 | int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, |
229 | struct tpm2_digest *digests) | 254 | struct tpm_digest *digests) |
230 | { | 255 | { |
231 | struct tpm_buf buf; | 256 | struct tpm_buf buf; |
232 | struct tpm2_null_auth_area auth_area; | 257 | struct tpm2_null_auth_area auth_area; |
233 | int rc; | 258 | int rc; |
234 | int i; | 259 | int i; |
235 | int j; | ||
236 | |||
237 | if (count > ARRAY_SIZE(chip->active_banks)) | ||
238 | return -EINVAL; | ||
239 | 260 | ||
240 | rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND); | 261 | rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND); |
241 | if (rc) | 262 | if (rc) |
@@ -251,21 +272,15 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, u32 count, | |||
251 | tpm_buf_append_u32(&buf, sizeof(struct tpm2_null_auth_area)); | 272 | tpm_buf_append_u32(&buf, sizeof(struct tpm2_null_auth_area)); |
252 | tpm_buf_append(&buf, (const unsigned char *)&auth_area, | 273 | tpm_buf_append(&buf, (const unsigned char *)&auth_area, |
253 | sizeof(auth_area)); | 274 | sizeof(auth_area)); |
254 | tpm_buf_append_u32(&buf, count); | 275 | tpm_buf_append_u32(&buf, chip->nr_allocated_banks); |
255 | 276 | ||
256 | for (i = 0; i < count; i++) { | 277 | for (i = 0; i < chip->nr_allocated_banks; i++) { |
257 | for (j = 0; j < ARRAY_SIZE(tpm2_hash_map); j++) { | 278 | tpm_buf_append_u16(&buf, digests[i].alg_id); |
258 | if (digests[i].alg_id != tpm2_hash_map[j].tpm_id) | 279 | tpm_buf_append(&buf, (const unsigned char *)&digests[i].digest, |
259 | continue; | 280 | chip->allocated_banks[i].digest_size); |
260 | tpm_buf_append_u16(&buf, digests[i].alg_id); | ||
261 | tpm_buf_append(&buf, (const unsigned char | ||
262 | *)&digests[i].digest, | ||
263 | hash_digest_size[tpm2_hash_map[j].crypto_id]); | ||
264 | } | ||
265 | } | 281 | } |
266 | 282 | ||
267 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, | 283 | rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value"); |
268 | "attempting extend a PCR value"); | ||
269 | 284 | ||
270 | tpm_buf_destroy(&buf); | 285 | tpm_buf_destroy(&buf); |
271 | 286 | ||
@@ -309,10 +324,10 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) | |||
309 | do { | 324 | do { |
310 | tpm_buf_reset(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_RANDOM); | 325 | tpm_buf_reset(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_RANDOM); |
311 | tpm_buf_append_u16(&buf, num_bytes); | 326 | tpm_buf_append_u16(&buf, num_bytes); |
312 | err = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, | 327 | err = tpm_transmit_cmd(chip, &buf, |
313 | offsetof(struct tpm2_get_random_out, | 328 | offsetof(struct tpm2_get_random_out, |
314 | buffer), | 329 | buffer), |
315 | 0, "attempting get random"); | 330 | "attempting get random"); |
316 | if (err) | 331 | if (err) |
317 | goto out; | 332 | goto out; |
318 | 333 | ||
@@ -341,14 +356,11 @@ out: | |||
341 | } | 356 | } |
342 | 357 | ||
343 | /** | 358 | /** |
344 | * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command | 359 | * tpm2_flush_context() - execute a TPM2_FlushContext command |
345 | * @chip: TPM chip to use | 360 | * @chip: TPM chip to use |
346 | * @handle: context handle | 361 | * @handle: context handle |
347 | * @flags: tpm transmit flags - bitmap | ||
348 | * | ||
349 | */ | 362 | */ |
350 | void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, | 363 | void tpm2_flush_context(struct tpm_chip *chip, u32 handle) |
351 | unsigned int flags) | ||
352 | { | 364 | { |
353 | struct tpm_buf buf; | 365 | struct tpm_buf buf; |
354 | int rc; | 366 | int rc; |
@@ -362,9 +374,7 @@ void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, | |||
362 | 374 | ||
363 | tpm_buf_append_u32(&buf, handle); | 375 | tpm_buf_append_u32(&buf, handle); |
364 | 376 | ||
365 | (void) tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, flags, | 377 | tpm_transmit_cmd(chip, &buf, 0, "flushing context"); |
366 | "flushing context"); | ||
367 | |||
368 | tpm_buf_destroy(&buf); | 378 | tpm_buf_destroy(&buf); |
369 | } | 379 | } |
370 | 380 | ||
@@ -449,7 +459,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, | |||
449 | 459 | ||
450 | /* public */ | 460 | /* public */ |
451 | tpm_buf_append_u16(&buf, 14 + options->policydigest_len); | 461 | tpm_buf_append_u16(&buf, 14 + options->policydigest_len); |
452 | tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH); | 462 | tpm_buf_append_u16(&buf, TPM_ALG_KEYEDHASH); |
453 | tpm_buf_append_u16(&buf, hash); | 463 | tpm_buf_append_u16(&buf, hash); |
454 | 464 | ||
455 | /* policy */ | 465 | /* policy */ |
@@ -464,7 +474,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, | |||
464 | } | 474 | } |
465 | 475 | ||
466 | /* public parameters */ | 476 | /* public parameters */ |
467 | tpm_buf_append_u16(&buf, TPM2_ALG_NULL); | 477 | tpm_buf_append_u16(&buf, TPM_ALG_NULL); |
468 | tpm_buf_append_u16(&buf, 0); | 478 | tpm_buf_append_u16(&buf, 0); |
469 | 479 | ||
470 | /* outside info */ | 480 | /* outside info */ |
@@ -478,8 +488,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, | |||
478 | goto out; | 488 | goto out; |
479 | } | 489 | } |
480 | 490 | ||
481 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 4, 0, | 491 | rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data"); |
482 | "sealing data"); | ||
483 | if (rc) | 492 | if (rc) |
484 | goto out; | 493 | goto out; |
485 | 494 | ||
@@ -516,7 +525,6 @@ out: | |||
516 | * @payload: the key data in clear and encrypted form | 525 | * @payload: the key data in clear and encrypted form |
517 | * @options: authentication values and other options | 526 | * @options: authentication values and other options |
518 | * @blob_handle: returned blob handle | 527 | * @blob_handle: returned blob handle |
519 | * @flags: tpm transmit flags | ||
520 | * | 528 | * |
521 | * Return: 0 on success. | 529 | * Return: 0 on success. |
522 | * -E2BIG on wrong payload size. | 530 | * -E2BIG on wrong payload size. |
@@ -526,7 +534,7 @@ out: | |||
526 | static int tpm2_load_cmd(struct tpm_chip *chip, | 534 | static int tpm2_load_cmd(struct tpm_chip *chip, |
527 | struct trusted_key_payload *payload, | 535 | struct trusted_key_payload *payload, |
528 | struct trusted_key_options *options, | 536 | struct trusted_key_options *options, |
529 | u32 *blob_handle, unsigned int flags) | 537 | u32 *blob_handle) |
530 | { | 538 | { |
531 | struct tpm_buf buf; | 539 | struct tpm_buf buf; |
532 | unsigned int private_len; | 540 | unsigned int private_len; |
@@ -561,8 +569,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip, | |||
561 | goto out; | 569 | goto out; |
562 | } | 570 | } |
563 | 571 | ||
564 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 4, flags, | 572 | rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob"); |
565 | "loading blob"); | ||
566 | if (!rc) | 573 | if (!rc) |
567 | *blob_handle = be32_to_cpup( | 574 | *blob_handle = be32_to_cpup( |
568 | (__be32 *) &buf.data[TPM_HEADER_SIZE]); | 575 | (__be32 *) &buf.data[TPM_HEADER_SIZE]); |
@@ -583,7 +590,6 @@ out: | |||
583 | * @payload: the key data in clear and encrypted form | 590 | * @payload: the key data in clear and encrypted form |
584 | * @options: authentication values and other options | 591 | * @options: authentication values and other options |
585 | * @blob_handle: blob handle | 592 | * @blob_handle: blob handle |
586 | * @flags: tpm_transmit_cmd flags | ||
587 | * | 593 | * |
588 | * Return: 0 on success | 594 | * Return: 0 on success |
589 | * -EPERM on tpm error status | 595 | * -EPERM on tpm error status |
@@ -592,7 +598,7 @@ out: | |||
592 | static int tpm2_unseal_cmd(struct tpm_chip *chip, | 598 | static int tpm2_unseal_cmd(struct tpm_chip *chip, |
593 | struct trusted_key_payload *payload, | 599 | struct trusted_key_payload *payload, |
594 | struct trusted_key_options *options, | 600 | struct trusted_key_options *options, |
595 | u32 blob_handle, unsigned int flags) | 601 | u32 blob_handle) |
596 | { | 602 | { |
597 | struct tpm_buf buf; | 603 | struct tpm_buf buf; |
598 | u16 data_len; | 604 | u16 data_len; |
@@ -612,8 +618,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, | |||
612 | options->blobauth /* hmac */, | 618 | options->blobauth /* hmac */, |
613 | TPM_DIGEST_SIZE); | 619 | TPM_DIGEST_SIZE); |
614 | 620 | ||
615 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 6, flags, | 621 | rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing"); |
616 | "unsealing"); | ||
617 | if (rc > 0) | 622 | if (rc > 0) |
618 | rc = -EPERM; | 623 | rc = -EPERM; |
619 | 624 | ||
@@ -657,17 +662,12 @@ int tpm2_unseal_trusted(struct tpm_chip *chip, | |||
657 | u32 blob_handle; | 662 | u32 blob_handle; |
658 | int rc; | 663 | int rc; |
659 | 664 | ||
660 | mutex_lock(&chip->tpm_mutex); | 665 | rc = tpm2_load_cmd(chip, payload, options, &blob_handle); |
661 | rc = tpm2_load_cmd(chip, payload, options, &blob_handle, | ||
662 | TPM_TRANSMIT_UNLOCKED); | ||
663 | if (rc) | 666 | if (rc) |
664 | goto out; | 667 | return rc; |
665 | 668 | ||
666 | rc = tpm2_unseal_cmd(chip, payload, options, blob_handle, | 669 | rc = tpm2_unseal_cmd(chip, payload, options, blob_handle); |
667 | TPM_TRANSMIT_UNLOCKED); | 670 | tpm2_flush_context(chip, blob_handle); |
668 | tpm2_flush_context_cmd(chip, blob_handle, TPM_TRANSMIT_UNLOCKED); | ||
669 | out: | ||
670 | mutex_unlock(&chip->tpm_mutex); | ||
671 | return rc; | 671 | return rc; |
672 | } | 672 | } |
673 | 673 | ||
@@ -703,7 +703,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, | |||
703 | tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES); | 703 | tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES); |
704 | tpm_buf_append_u32(&buf, property_id); | 704 | tpm_buf_append_u32(&buf, property_id); |
705 | tpm_buf_append_u32(&buf, 1); | 705 | tpm_buf_append_u32(&buf, 1); |
706 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, NULL); | 706 | rc = tpm_transmit_cmd(chip, &buf, 0, NULL); |
707 | if (!rc) { | 707 | if (!rc) { |
708 | out = (struct tpm2_get_cap_out *) | 708 | out = (struct tpm2_get_cap_out *) |
709 | &buf.data[TPM_HEADER_SIZE]; | 709 | &buf.data[TPM_HEADER_SIZE]; |
@@ -733,8 +733,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) | |||
733 | if (rc) | 733 | if (rc) |
734 | return; | 734 | return; |
735 | tpm_buf_append_u16(&buf, shutdown_type); | 735 | tpm_buf_append_u16(&buf, shutdown_type); |
736 | tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, | 736 | tpm_transmit_cmd(chip, &buf, 0, "stopping the TPM"); |
737 | "stopping the TPM"); | ||
738 | tpm_buf_destroy(&buf); | 737 | tpm_buf_destroy(&buf); |
739 | } | 738 | } |
740 | 739 | ||
@@ -763,7 +762,7 @@ static int tpm2_do_selftest(struct tpm_chip *chip) | |||
763 | return rc; | 762 | return rc; |
764 | 763 | ||
765 | tpm_buf_append_u8(&buf, full); | 764 | tpm_buf_append_u8(&buf, full); |
766 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, | 765 | rc = tpm_transmit_cmd(chip, &buf, 0, |
767 | "attempting the self test"); | 766 | "attempting the self test"); |
768 | tpm_buf_destroy(&buf); | 767 | tpm_buf_destroy(&buf); |
769 | 768 | ||
@@ -790,7 +789,7 @@ static int tpm2_do_selftest(struct tpm_chip *chip) | |||
790 | */ | 789 | */ |
791 | int tpm2_probe(struct tpm_chip *chip) | 790 | int tpm2_probe(struct tpm_chip *chip) |
792 | { | 791 | { |
793 | struct tpm_output_header *out; | 792 | struct tpm_header *out; |
794 | struct tpm_buf buf; | 793 | struct tpm_buf buf; |
795 | int rc; | 794 | int rc; |
796 | 795 | ||
@@ -800,10 +799,10 @@ int tpm2_probe(struct tpm_chip *chip) | |||
800 | tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES); | 799 | tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES); |
801 | tpm_buf_append_u32(&buf, TPM_PT_TOTAL_COMMANDS); | 800 | tpm_buf_append_u32(&buf, TPM_PT_TOTAL_COMMANDS); |
802 | tpm_buf_append_u32(&buf, 1); | 801 | tpm_buf_append_u32(&buf, 1); |
803 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, NULL); | 802 | rc = tpm_transmit_cmd(chip, &buf, 0, NULL); |
804 | /* We ignore TPM return codes on purpose. */ | 803 | /* We ignore TPM return codes on purpose. */ |
805 | if (rc >= 0) { | 804 | if (rc >= 0) { |
806 | out = (struct tpm_output_header *)buf.data; | 805 | out = (struct tpm_header *)buf.data; |
807 | if (be16_to_cpu(out->tag) == TPM2_ST_NO_SESSIONS) | 806 | if (be16_to_cpu(out->tag) == TPM2_ST_NO_SESSIONS) |
808 | chip->flags |= TPM_CHIP_FLAG_TPM2; | 807 | chip->flags |= TPM_CHIP_FLAG_TPM2; |
809 | } | 808 | } |
@@ -812,6 +811,30 @@ int tpm2_probe(struct tpm_chip *chip) | |||
812 | } | 811 | } |
813 | EXPORT_SYMBOL_GPL(tpm2_probe); | 812 | EXPORT_SYMBOL_GPL(tpm2_probe); |
814 | 813 | ||
814 | static int tpm2_init_bank_info(struct tpm_chip *chip, u32 bank_index) | ||
815 | { | ||
816 | struct tpm_bank_info *bank = chip->allocated_banks + bank_index; | ||
817 | struct tpm_digest digest = { .alg_id = bank->alg_id }; | ||
818 | int i; | ||
819 | |||
820 | /* | ||
821 | * Avoid unnecessary PCR read operations to reduce overhead | ||
822 | * and obtain identifiers of the crypto subsystem. | ||
823 | */ | ||
824 | for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) { | ||
825 | enum hash_algo crypto_algo = tpm2_hash_map[i].crypto_id; | ||
826 | |||
827 | if (bank->alg_id != tpm2_hash_map[i].tpm_id) | ||
828 | continue; | ||
829 | |||
830 | bank->digest_size = hash_digest_size[crypto_algo]; | ||
831 | bank->crypto_id = crypto_algo; | ||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | return tpm2_pcr_read(chip, 0, &digest, &bank->digest_size); | ||
836 | } | ||
837 | |||
815 | struct tpm2_pcr_selection { | 838 | struct tpm2_pcr_selection { |
816 | __be16 hash_alg; | 839 | __be16 hash_alg; |
817 | u8 size_of_select; | 840 | u8 size_of_select; |
@@ -825,8 +848,10 @@ static ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) | |||
825 | void *marker; | 848 | void *marker; |
826 | void *end; | 849 | void *end; |
827 | void *pcr_select_offset; | 850 | void *pcr_select_offset; |
828 | unsigned int count; | ||
829 | u32 sizeof_pcr_selection; | 851 | u32 sizeof_pcr_selection; |
852 | u32 nr_possible_banks; | ||
853 | u32 nr_alloc_banks = 0; | ||
854 | u16 hash_alg; | ||
830 | u32 rsp_len; | 855 | u32 rsp_len; |
831 | int rc; | 856 | int rc; |
832 | int i = 0; | 857 | int i = 0; |
@@ -839,16 +864,18 @@ static ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) | |||
839 | tpm_buf_append_u32(&buf, 0); | 864 | tpm_buf_append_u32(&buf, 0); |
840 | tpm_buf_append_u32(&buf, 1); | 865 | tpm_buf_append_u32(&buf, 1); |
841 | 866 | ||
842 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 9, 0, | 867 | rc = tpm_transmit_cmd(chip, &buf, 9, "get tpm pcr allocation"); |
843 | "get tpm pcr allocation"); | ||
844 | if (rc) | 868 | if (rc) |
845 | goto out; | 869 | goto out; |
846 | 870 | ||
847 | count = be32_to_cpup( | 871 | nr_possible_banks = be32_to_cpup( |
848 | (__be32 *)&buf.data[TPM_HEADER_SIZE + 5]); | 872 | (__be32 *)&buf.data[TPM_HEADER_SIZE + 5]); |
849 | 873 | ||
850 | if (count > ARRAY_SIZE(chip->active_banks)) { | 874 | chip->allocated_banks = kcalloc(nr_possible_banks, |
851 | rc = -ENODEV; | 875 | sizeof(*chip->allocated_banks), |
876 | GFP_KERNEL); | ||
877 | if (!chip->allocated_banks) { | ||
878 | rc = -ENOMEM; | ||
852 | goto out; | 879 | goto out; |
853 | } | 880 | } |
854 | 881 | ||
@@ -857,7 +884,7 @@ static ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) | |||
857 | rsp_len = be32_to_cpup((__be32 *)&buf.data[2]); | 884 | rsp_len = be32_to_cpup((__be32 *)&buf.data[2]); |
858 | end = &buf.data[rsp_len]; | 885 | end = &buf.data[rsp_len]; |
859 | 886 | ||
860 | for (i = 0; i < count; i++) { | 887 | for (i = 0; i < nr_possible_banks; i++) { |
861 | pcr_select_offset = marker + | 888 | pcr_select_offset = marker + |
862 | offsetof(struct tpm2_pcr_selection, size_of_select); | 889 | offsetof(struct tpm2_pcr_selection, size_of_select); |
863 | if (pcr_select_offset >= end) { | 890 | if (pcr_select_offset >= end) { |
@@ -866,17 +893,28 @@ static ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) | |||
866 | } | 893 | } |
867 | 894 | ||
868 | memcpy(&pcr_selection, marker, sizeof(pcr_selection)); | 895 | memcpy(&pcr_selection, marker, sizeof(pcr_selection)); |
869 | chip->active_banks[i] = be16_to_cpu(pcr_selection.hash_alg); | 896 | hash_alg = be16_to_cpu(pcr_selection.hash_alg); |
897 | |||
898 | pcr_select_offset = memchr_inv(pcr_selection.pcr_select, 0, | ||
899 | pcr_selection.size_of_select); | ||
900 | if (pcr_select_offset) { | ||
901 | chip->allocated_banks[nr_alloc_banks].alg_id = hash_alg; | ||
902 | |||
903 | rc = tpm2_init_bank_info(chip, nr_alloc_banks); | ||
904 | if (rc < 0) | ||
905 | break; | ||
906 | |||
907 | nr_alloc_banks++; | ||
908 | } | ||
909 | |||
870 | sizeof_pcr_selection = sizeof(pcr_selection.hash_alg) + | 910 | sizeof_pcr_selection = sizeof(pcr_selection.hash_alg) + |
871 | sizeof(pcr_selection.size_of_select) + | 911 | sizeof(pcr_selection.size_of_select) + |
872 | pcr_selection.size_of_select; | 912 | pcr_selection.size_of_select; |
873 | marker = marker + sizeof_pcr_selection; | 913 | marker = marker + sizeof_pcr_selection; |
874 | } | 914 | } |
875 | 915 | ||
916 | chip->nr_allocated_banks = nr_alloc_banks; | ||
876 | out: | 917 | out: |
877 | if (i < ARRAY_SIZE(chip->active_banks)) | ||
878 | chip->active_banks[i] = TPM2_ALG_ERROR; | ||
879 | |||
880 | tpm_buf_destroy(&buf); | 918 | tpm_buf_destroy(&buf); |
881 | 919 | ||
882 | return rc; | 920 | return rc; |
@@ -911,8 +949,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) | |||
911 | tpm_buf_append_u32(&buf, TPM2_CC_FIRST); | 949 | tpm_buf_append_u32(&buf, TPM2_CC_FIRST); |
912 | tpm_buf_append_u32(&buf, nr_commands); | 950 | tpm_buf_append_u32(&buf, nr_commands); |
913 | 951 | ||
914 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, | 952 | rc = tpm_transmit_cmd(chip, &buf, 9 + 4 * nr_commands, NULL); |
915 | 9 + 4 * nr_commands, 0, NULL); | ||
916 | if (rc) { | 953 | if (rc) { |
917 | tpm_buf_destroy(&buf); | 954 | tpm_buf_destroy(&buf); |
918 | goto out; | 955 | goto out; |
@@ -969,8 +1006,7 @@ static int tpm2_startup(struct tpm_chip *chip) | |||
969 | return rc; | 1006 | return rc; |
970 | 1007 | ||
971 | tpm_buf_append_u16(&buf, TPM2_SU_CLEAR); | 1008 | tpm_buf_append_u16(&buf, TPM2_SU_CLEAR); |
972 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, | 1009 | rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM"); |
973 | "attempting to start the TPM"); | ||
974 | tpm_buf_destroy(&buf); | 1010 | tpm_buf_destroy(&buf); |
975 | 1011 | ||
976 | return rc; | 1012 | return rc; |
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index dcdfde3c253e..4a2773c3374f 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c | |||
@@ -38,8 +38,7 @@ static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space) | |||
38 | 38 | ||
39 | for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++) { | 39 | for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++) { |
40 | if (space->session_tbl[i]) | 40 | if (space->session_tbl[i]) |
41 | tpm2_flush_context_cmd(chip, space->session_tbl[i], | 41 | tpm2_flush_context(chip, space->session_tbl[i]); |
42 | TPM_TRANSMIT_NESTED); | ||
43 | } | 42 | } |
44 | } | 43 | } |
45 | 44 | ||
@@ -61,7 +60,10 @@ int tpm2_init_space(struct tpm_space *space) | |||
61 | void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space) | 60 | void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space) |
62 | { | 61 | { |
63 | mutex_lock(&chip->tpm_mutex); | 62 | mutex_lock(&chip->tpm_mutex); |
64 | tpm2_flush_sessions(chip, space); | 63 | if (!tpm_chip_start(chip)) { |
64 | tpm2_flush_sessions(chip, space); | ||
65 | tpm_chip_stop(chip); | ||
66 | } | ||
65 | mutex_unlock(&chip->tpm_mutex); | 67 | mutex_unlock(&chip->tpm_mutex); |
66 | kfree(space->context_buf); | 68 | kfree(space->context_buf); |
67 | kfree(space->session_buf); | 69 | kfree(space->session_buf); |
@@ -83,8 +85,7 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 *buf, | |||
83 | body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size); | 85 | body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size); |
84 | tpm_buf_append(&tbuf, &buf[*offset], body_size); | 86 | tpm_buf_append(&tbuf, &buf[*offset], body_size); |
85 | 87 | ||
86 | rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 4, | 88 | rc = tpm_transmit_cmd(chip, &tbuf, 4, NULL); |
87 | TPM_TRANSMIT_NESTED, NULL); | ||
88 | if (rc < 0) { | 89 | if (rc < 0) { |
89 | dev_warn(&chip->dev, "%s: failed with a system error %d\n", | 90 | dev_warn(&chip->dev, "%s: failed with a system error %d\n", |
90 | __func__, rc); | 91 | __func__, rc); |
@@ -132,8 +133,7 @@ static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf, | |||
132 | 133 | ||
133 | tpm_buf_append_u32(&tbuf, handle); | 134 | tpm_buf_append_u32(&tbuf, handle); |
134 | 135 | ||
135 | rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 0, | 136 | rc = tpm_transmit_cmd(chip, &tbuf, 0, NULL); |
136 | TPM_TRANSMIT_NESTED, NULL); | ||
137 | if (rc < 0) { | 137 | if (rc < 0) { |
138 | dev_warn(&chip->dev, "%s: failed with a system error %d\n", | 138 | dev_warn(&chip->dev, "%s: failed with a system error %d\n", |
139 | __func__, rc); | 139 | __func__, rc); |
@@ -162,15 +162,14 @@ static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf, | |||
162 | return 0; | 162 | return 0; |
163 | } | 163 | } |
164 | 164 | ||
165 | static void tpm2_flush_space(struct tpm_chip *chip) | 165 | void tpm2_flush_space(struct tpm_chip *chip) |
166 | { | 166 | { |
167 | struct tpm_space *space = &chip->work_space; | 167 | struct tpm_space *space = &chip->work_space; |
168 | int i; | 168 | int i; |
169 | 169 | ||
170 | for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) | 170 | for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) |
171 | if (space->context_tbl[i] && ~space->context_tbl[i]) | 171 | if (space->context_tbl[i] && ~space->context_tbl[i]) |
172 | tpm2_flush_context_cmd(chip, space->context_tbl[i], | 172 | tpm2_flush_context(chip, space->context_tbl[i]); |
173 | TPM_TRANSMIT_NESTED); | ||
174 | 173 | ||
175 | tpm2_flush_sessions(chip, space); | 174 | tpm2_flush_sessions(chip, space); |
176 | } | 175 | } |
@@ -264,14 +263,54 @@ static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd) | |||
264 | return 0; | 263 | return 0; |
265 | } | 264 | } |
266 | 265 | ||
267 | int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc, | 266 | static int tpm_find_and_validate_cc(struct tpm_chip *chip, |
268 | u8 *cmd) | 267 | struct tpm_space *space, |
268 | const void *cmd, size_t len) | ||
269 | { | ||
270 | const struct tpm_header *header = (const void *)cmd; | ||
271 | int i; | ||
272 | u32 cc; | ||
273 | u32 attrs; | ||
274 | unsigned int nr_handles; | ||
275 | |||
276 | if (len < TPM_HEADER_SIZE || !chip->nr_commands) | ||
277 | return -EINVAL; | ||
278 | |||
279 | cc = be32_to_cpu(header->ordinal); | ||
280 | |||
281 | i = tpm2_find_cc(chip, cc); | ||
282 | if (i < 0) { | ||
283 | dev_dbg(&chip->dev, "0x%04X is an invalid command\n", | ||
284 | cc); | ||
285 | return -EOPNOTSUPP; | ||
286 | } | ||
287 | |||
288 | attrs = chip->cc_attrs_tbl[i]; | ||
289 | nr_handles = | ||
290 | 4 * ((attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0)); | ||
291 | if (len < TPM_HEADER_SIZE + 4 * nr_handles) | ||
292 | goto err_len; | ||
293 | |||
294 | return cc; | ||
295 | err_len: | ||
296 | dev_dbg(&chip->dev, "%s: insufficient command length %zu", __func__, | ||
297 | len); | ||
298 | return -EINVAL; | ||
299 | } | ||
300 | |||
301 | int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd, | ||
302 | size_t cmdsiz) | ||
269 | { | 303 | { |
270 | int rc; | 304 | int rc; |
305 | int cc; | ||
271 | 306 | ||
272 | if (!space) | 307 | if (!space) |
273 | return 0; | 308 | return 0; |
274 | 309 | ||
310 | cc = tpm_find_and_validate_cc(chip, space, cmd, cmdsiz); | ||
311 | if (cc < 0) | ||
312 | return cc; | ||
313 | |||
275 | memcpy(&chip->work_space.context_tbl, &space->context_tbl, | 314 | memcpy(&chip->work_space.context_tbl, &space->context_tbl, |
276 | sizeof(space->context_tbl)); | 315 | sizeof(space->context_tbl)); |
277 | memcpy(&chip->work_space.session_tbl, &space->session_tbl, | 316 | memcpy(&chip->work_space.session_tbl, &space->session_tbl, |
@@ -291,6 +330,7 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc, | |||
291 | return rc; | 330 | return rc; |
292 | } | 331 | } |
293 | 332 | ||
333 | chip->last_cc = cc; | ||
294 | return 0; | 334 | return 0; |
295 | } | 335 | } |
296 | 336 | ||
@@ -334,7 +374,7 @@ static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp, | |||
334 | size_t len) | 374 | size_t len) |
335 | { | 375 | { |
336 | struct tpm_space *space = &chip->work_space; | 376 | struct tpm_space *space = &chip->work_space; |
337 | struct tpm_output_header *header = (void *)rsp; | 377 | struct tpm_header *header = (struct tpm_header *)rsp; |
338 | u32 phandle; | 378 | u32 phandle; |
339 | u32 phandle_type; | 379 | u32 phandle_type; |
340 | u32 vhandle; | 380 | u32 vhandle; |
@@ -377,7 +417,7 @@ static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp, | |||
377 | 417 | ||
378 | return 0; | 418 | return 0; |
379 | out_no_slots: | 419 | out_no_slots: |
380 | tpm2_flush_context_cmd(chip, phandle, TPM_TRANSMIT_NESTED); | 420 | tpm2_flush_context(chip, phandle); |
381 | dev_warn(&chip->dev, "%s: out of slots for 0x%08X\n", __func__, | 421 | dev_warn(&chip->dev, "%s: out of slots for 0x%08X\n", __func__, |
382 | phandle); | 422 | phandle); |
383 | return -ENOMEM; | 423 | return -ENOMEM; |
@@ -394,7 +434,7 @@ static int tpm2_map_response_body(struct tpm_chip *chip, u32 cc, u8 *rsp, | |||
394 | size_t len) | 434 | size_t len) |
395 | { | 435 | { |
396 | struct tpm_space *space = &chip->work_space; | 436 | struct tpm_space *space = &chip->work_space; |
397 | struct tpm_output_header *header = (void *)rsp; | 437 | struct tpm_header *header = (struct tpm_header *)rsp; |
398 | struct tpm2_cap_handles *data; | 438 | struct tpm2_cap_handles *data; |
399 | u32 phandle; | 439 | u32 phandle; |
400 | u32 phandle_type; | 440 | u32 phandle_type; |
@@ -464,8 +504,7 @@ static int tpm2_save_space(struct tpm_chip *chip) | |||
464 | } else if (rc) | 504 | } else if (rc) |
465 | return rc; | 505 | return rc; |
466 | 506 | ||
467 | tpm2_flush_context_cmd(chip, space->context_tbl[i], | 507 | tpm2_flush_context(chip, space->context_tbl[i]); |
468 | TPM_TRANSMIT_NESTED); | ||
469 | space->context_tbl[i] = ~0; | 508 | space->context_tbl[i] = ~0; |
470 | } | 509 | } |
471 | 510 | ||
@@ -490,30 +529,30 @@ static int tpm2_save_space(struct tpm_chip *chip) | |||
490 | } | 529 | } |
491 | 530 | ||
492 | int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, | 531 | int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, |
493 | u32 cc, u8 *buf, size_t *bufsiz) | 532 | void *buf, size_t *bufsiz) |
494 | { | 533 | { |
495 | struct tpm_output_header *header = (void *)buf; | 534 | struct tpm_header *header = buf; |
496 | int rc; | 535 | int rc; |
497 | 536 | ||
498 | if (!space) | 537 | if (!space) |
499 | return 0; | 538 | return 0; |
500 | 539 | ||
501 | rc = tpm2_map_response_header(chip, cc, buf, *bufsiz); | 540 | rc = tpm2_map_response_header(chip, chip->last_cc, buf, *bufsiz); |
502 | if (rc) { | 541 | if (rc) { |
503 | tpm2_flush_space(chip); | 542 | tpm2_flush_space(chip); |
504 | return rc; | 543 | goto out; |
505 | } | 544 | } |
506 | 545 | ||
507 | rc = tpm2_map_response_body(chip, cc, buf, *bufsiz); | 546 | rc = tpm2_map_response_body(chip, chip->last_cc, buf, *bufsiz); |
508 | if (rc) { | 547 | if (rc) { |
509 | tpm2_flush_space(chip); | 548 | tpm2_flush_space(chip); |
510 | return rc; | 549 | goto out; |
511 | } | 550 | } |
512 | 551 | ||
513 | rc = tpm2_save_space(chip); | 552 | rc = tpm2_save_space(chip); |
514 | if (rc) { | 553 | if (rc) { |
515 | tpm2_flush_space(chip); | 554 | tpm2_flush_space(chip); |
516 | return rc; | 555 | goto out; |
517 | } | 556 | } |
518 | 557 | ||
519 | *bufsiz = be32_to_cpu(header->length); | 558 | *bufsiz = be32_to_cpu(header->length); |
@@ -526,4 +565,7 @@ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, | |||
526 | memcpy(space->session_buf, chip->work_space.session_buf, PAGE_SIZE); | 565 | memcpy(space->session_buf, chip->work_space.session_buf, PAGE_SIZE); |
527 | 566 | ||
528 | return 0; | 567 | return 0; |
568 | out: | ||
569 | dev_err(&chip->dev, "%s: error %d\n", __func__, rc); | ||
570 | return rc; | ||
529 | } | 571 | } |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 66a14526aaf4..a290b30a0c35 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -105,7 +105,7 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
105 | iowrite8(buf[i], priv->iobase); | 105 | iowrite8(buf[i], priv->iobase); |
106 | } | 106 | } |
107 | 107 | ||
108 | return count; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static void tpm_atml_cancel(struct tpm_chip *chip) | 111 | static void tpm_atml_cancel(struct tpm_chip *chip) |
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 36952ef98f90..763fc7e6c005 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
@@ -287,19 +287,29 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
287 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); | 287 | struct crb_priv *priv = dev_get_drvdata(&chip->dev); |
288 | unsigned int expected; | 288 | unsigned int expected; |
289 | 289 | ||
290 | /* sanity check */ | 290 | /* A sanity check that the upper layer wants to get at least the header |
291 | if (count < 6) | 291 | * as that is the minimum size for any TPM response. |
292 | */ | ||
293 | if (count < TPM_HEADER_SIZE) | ||
292 | return -EIO; | 294 | return -EIO; |
293 | 295 | ||
296 | /* If this bit is set, according to the spec, the TPM is in | ||
297 | * unrecoverable condition. | ||
298 | */ | ||
294 | if (ioread32(&priv->regs_t->ctrl_sts) & CRB_CTRL_STS_ERROR) | 299 | if (ioread32(&priv->regs_t->ctrl_sts) & CRB_CTRL_STS_ERROR) |
295 | return -EIO; | 300 | return -EIO; |
296 | 301 | ||
297 | memcpy_fromio(buf, priv->rsp, 6); | 302 | /* Read the first 8 bytes in order to get the length of the response. |
298 | expected = be32_to_cpup((__be32 *) &buf[2]); | 303 | * We read exactly a quad word in order to make sure that the remaining |
299 | if (expected > count || expected < 6) | 304 | * reads will be aligned. |
305 | */ | ||
306 | memcpy_fromio(buf, priv->rsp, 8); | ||
307 | |||
308 | expected = be32_to_cpup((__be32 *)&buf[2]); | ||
309 | if (expected > count || expected < TPM_HEADER_SIZE) | ||
300 | return -EIO; | 310 | return -EIO; |
301 | 311 | ||
302 | memcpy_fromio(&buf[6], &priv->rsp[6], expected - 6); | 312 | memcpy_fromio(&buf[8], &priv->rsp[8], expected - 8); |
303 | 313 | ||
304 | return expected; | 314 | return expected; |
305 | } | 315 | } |
diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c index 95ce2e9ccdc6..8a7e80923091 100644 --- a/drivers/char/tpm/tpm_i2c_atmel.c +++ b/drivers/char/tpm/tpm_i2c_atmel.c | |||
@@ -46,7 +46,7 @@ struct priv_data { | |||
46 | /* This is the amount we read on the first try. 25 was chosen to fit a | 46 | /* This is the amount we read on the first try. 25 was chosen to fit a |
47 | * fair number of read responses in the buffer so a 2nd retry can be | 47 | * fair number of read responses in the buffer so a 2nd retry can be |
48 | * avoided in small message cases. */ | 48 | * avoided in small message cases. */ |
49 | u8 buffer[sizeof(struct tpm_output_header) + 25]; | 49 | u8 buffer[sizeof(struct tpm_header) + 25]; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) | 52 | static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) |
@@ -65,15 +65,22 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
65 | dev_dbg(&chip->dev, | 65 | dev_dbg(&chip->dev, |
66 | "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__, | 66 | "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__, |
67 | (int)min_t(size_t, 64, len), buf, len, status); | 67 | (int)min_t(size_t, 64, len), buf, len, status); |
68 | return status; | 68 | |
69 | if (status < 0) | ||
70 | return status; | ||
71 | |||
72 | /* The upper layer does not support incomplete sends. */ | ||
73 | if (status != len) | ||
74 | return -E2BIG; | ||
75 | |||
76 | return 0; | ||
69 | } | 77 | } |
70 | 78 | ||
71 | static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) | 79 | static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) |
72 | { | 80 | { |
73 | struct priv_data *priv = dev_get_drvdata(&chip->dev); | 81 | struct priv_data *priv = dev_get_drvdata(&chip->dev); |
74 | struct i2c_client *client = to_i2c_client(chip->dev.parent); | 82 | struct i2c_client *client = to_i2c_client(chip->dev.parent); |
75 | struct tpm_output_header *hdr = | 83 | struct tpm_header *hdr = (struct tpm_header *)priv->buffer; |
76 | (struct tpm_output_header *)priv->buffer; | ||
77 | u32 expected_len; | 84 | u32 expected_len; |
78 | int rc; | 85 | int rc; |
79 | 86 | ||
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 9086edc9066b..3b4e9672ff6c 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c | |||
@@ -26,8 +26,7 @@ | |||
26 | #include <linux/wait.h> | 26 | #include <linux/wait.h> |
27 | #include "tpm.h" | 27 | #include "tpm.h" |
28 | 28 | ||
29 | /* max. buffer size supported by our TPM */ | 29 | #define TPM_I2C_INFINEON_BUFSIZE 1260 |
30 | #define TPM_BUFSIZE 1260 | ||
31 | 30 | ||
32 | /* max. number of iterations after I2C NAK */ | 31 | /* max. number of iterations after I2C NAK */ |
33 | #define MAX_COUNT 3 | 32 | #define MAX_COUNT 3 |
@@ -63,11 +62,13 @@ enum i2c_chip_type { | |||
63 | UNKNOWN, | 62 | UNKNOWN, |
64 | }; | 63 | }; |
65 | 64 | ||
66 | /* Structure to store I2C TPM specific stuff */ | ||
67 | struct tpm_inf_dev { | 65 | struct tpm_inf_dev { |
68 | struct i2c_client *client; | 66 | struct i2c_client *client; |
69 | int locality; | 67 | int locality; |
70 | u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ | 68 | /* In addition to the data itself, the buffer must fit the 7-bit I2C |
69 | * address and the direction bit. | ||
70 | */ | ||
71 | u8 buf[TPM_I2C_INFINEON_BUFSIZE + 1]; | ||
71 | struct tpm_chip *chip; | 72 | struct tpm_chip *chip; |
72 | enum i2c_chip_type chip_type; | 73 | enum i2c_chip_type chip_type; |
73 | unsigned int adapterlimit; | 74 | unsigned int adapterlimit; |
@@ -219,7 +220,7 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, | |||
219 | .buf = tpm_dev.buf | 220 | .buf = tpm_dev.buf |
220 | }; | 221 | }; |
221 | 222 | ||
222 | if (len > TPM_BUFSIZE) | 223 | if (len > TPM_I2C_INFINEON_BUFSIZE) |
223 | return -EINVAL; | 224 | return -EINVAL; |
224 | 225 | ||
225 | if (!tpm_dev.client->adapter->algo->master_xfer) | 226 | if (!tpm_dev.client->adapter->algo->master_xfer) |
@@ -527,8 +528,8 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
527 | u8 retries = 0; | 528 | u8 retries = 0; |
528 | u8 sts = TPM_STS_GO; | 529 | u8 sts = TPM_STS_GO; |
529 | 530 | ||
530 | if (len > TPM_BUFSIZE) | 531 | if (len > TPM_I2C_INFINEON_BUFSIZE) |
531 | return -E2BIG; /* command is too long for our tpm, sorry */ | 532 | return -E2BIG; |
532 | 533 | ||
533 | if (request_locality(chip, 0) < 0) | 534 | if (request_locality(chip, 0) < 0) |
534 | return -EBUSY; | 535 | return -EBUSY; |
@@ -587,7 +588,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
587 | /* go and do it */ | 588 | /* go and do it */ |
588 | iic_tpm_write(TPM_STS(tpm_dev.locality), &sts, 1); | 589 | iic_tpm_write(TPM_STS(tpm_dev.locality), &sts, 1); |
589 | 590 | ||
590 | return len; | 591 | return 0; |
591 | out_err: | 592 | out_err: |
592 | tpm_tis_i2c_ready(chip); | 593 | tpm_tis_i2c_ready(chip); |
593 | /* The TPM needs some time to clean up here, | 594 | /* The TPM needs some time to clean up here, |
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index 217f7f1cbde8..315a3b4548f7 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c | |||
@@ -35,14 +35,12 @@ | |||
35 | #include "tpm.h" | 35 | #include "tpm.h" |
36 | 36 | ||
37 | /* I2C interface offsets */ | 37 | /* I2C interface offsets */ |
38 | #define TPM_STS 0x00 | 38 | #define TPM_STS 0x00 |
39 | #define TPM_BURST_COUNT 0x01 | 39 | #define TPM_BURST_COUNT 0x01 |
40 | #define TPM_DATA_FIFO_W 0x20 | 40 | #define TPM_DATA_FIFO_W 0x20 |
41 | #define TPM_DATA_FIFO_R 0x40 | 41 | #define TPM_DATA_FIFO_R 0x40 |
42 | #define TPM_VID_DID_RID 0x60 | 42 | #define TPM_VID_DID_RID 0x60 |
43 | /* TPM command header size */ | 43 | #define TPM_I2C_RETRIES 5 |
44 | #define TPM_HEADER_SIZE 10 | ||
45 | #define TPM_RETRY 5 | ||
46 | /* | 44 | /* |
47 | * I2C bus device maximum buffer size w/o counting I2C address or command | 45 | * I2C bus device maximum buffer size w/o counting I2C address or command |
48 | * i.e. max size required for I2C write is 34 = addr, command, 32 bytes data | 46 | * i.e. max size required for I2C write is 34 = addr, command, 32 bytes data |
@@ -292,7 +290,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
292 | dev_err(dev, "%s() count < header size\n", __func__); | 290 | dev_err(dev, "%s() count < header size\n", __func__); |
293 | return -EIO; | 291 | return -EIO; |
294 | } | 292 | } |
295 | for (retries = 0; retries < TPM_RETRY; retries++) { | 293 | for (retries = 0; retries < TPM_I2C_RETRIES; retries++) { |
296 | if (retries > 0) { | 294 | if (retries > 0) { |
297 | /* if this is not the first trial, set responseRetry */ | 295 | /* if this is not the first trial, set responseRetry */ |
298 | i2c_nuvoton_write_status(client, | 296 | i2c_nuvoton_write_status(client, |
@@ -467,7 +465,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
467 | } | 465 | } |
468 | 466 | ||
469 | dev_dbg(dev, "%s() -> %zd\n", __func__, len); | 467 | dev_dbg(dev, "%s() -> %zd\n", __func__, len); |
470 | return len; | 468 | return 0; |
471 | } | 469 | } |
472 | 470 | ||
473 | static bool i2c_nuvoton_req_canceled(struct tpm_chip *chip, u8 status) | 471 | static bool i2c_nuvoton_req_canceled(struct tpm_chip *chip, u8 status) |
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index 07b5a487d0c8..757ca45b39b8 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c | |||
@@ -139,14 +139,14 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
139 | } | 139 | } |
140 | 140 | ||
141 | /** | 141 | /** |
142 | * tpm_ibmvtpm_send - Send tpm request | 142 | * tpm_ibmvtpm_send() - Send a TPM command |
143 | * | ||
144 | * @chip: tpm chip struct | 143 | * @chip: tpm chip struct |
145 | * @buf: buffer contains data to send | 144 | * @buf: buffer contains data to send |
146 | * @count: size of buffer | 145 | * @count: size of buffer |
147 | * | 146 | * |
148 | * Return: | 147 | * Return: |
149 | * Number of bytes sent or < 0 on error. | 148 | * 0 on success, |
149 | * -errno on error | ||
150 | */ | 150 | */ |
151 | static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) | 151 | static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) |
152 | { | 152 | { |
@@ -192,7 +192,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
192 | rc = 0; | 192 | rc = 0; |
193 | ibmvtpm->tpm_processing_cmd = false; | 193 | ibmvtpm->tpm_processing_cmd = false; |
194 | } else | 194 | } else |
195 | rc = count; | 195 | rc = 0; |
196 | 196 | ||
197 | spin_unlock(&ibmvtpm->rtce_lock); | 197 | spin_unlock(&ibmvtpm->rtce_lock); |
198 | return rc; | 198 | return rc; |
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index d8f10047fbba..97f6d4fe0aee 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
@@ -354,7 +354,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
354 | for (i = 0; i < count; i++) { | 354 | for (i = 0; i < count; i++) { |
355 | wait_and_send(chip, buf[i]); | 355 | wait_and_send(chip, buf[i]); |
356 | } | 356 | } |
357 | return count; | 357 | return 0; |
358 | } | 358 | } |
359 | 359 | ||
360 | static void tpm_inf_cancel(struct tpm_chip *chip) | 360 | static void tpm_inf_cancel(struct tpm_chip *chip) |
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 5d6cce74cd3f..9bee3c5eb4bf 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
@@ -226,7 +226,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
226 | } | 226 | } |
227 | outb(NSC_COMMAND_EOC, priv->base + NSC_COMMAND); | 227 | outb(NSC_COMMAND_EOC, priv->base + NSC_COMMAND); |
228 | 228 | ||
229 | return count; | 229 | return 0; |
230 | } | 230 | } |
231 | 231 | ||
232 | static void tpm_nsc_cancel(struct tpm_chip *chip) | 232 | static void tpm_nsc_cancel(struct tpm_chip *chip) |
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index 86dd8521feef..75e7a856177c 100644 --- a/drivers/char/tpm/tpm_ppi.c +++ b/drivers/char/tpm/tpm_ppi.c | |||
@@ -20,7 +20,8 @@ | |||
20 | #include <linux/acpi.h> | 20 | #include <linux/acpi.h> |
21 | #include "tpm.h" | 21 | #include "tpm.h" |
22 | 22 | ||
23 | #define TPM_PPI_REVISION_ID 1 | 23 | #define TPM_PPI_REVISION_ID_1 1 |
24 | #define TPM_PPI_REVISION_ID_2 2 | ||
24 | #define TPM_PPI_FN_VERSION 1 | 25 | #define TPM_PPI_FN_VERSION 1 |
25 | #define TPM_PPI_FN_SUBREQ 2 | 26 | #define TPM_PPI_FN_SUBREQ 2 |
26 | #define TPM_PPI_FN_GETREQ 3 | 27 | #define TPM_PPI_FN_GETREQ 3 |
@@ -28,7 +29,7 @@ | |||
28 | #define TPM_PPI_FN_GETRSP 5 | 29 | #define TPM_PPI_FN_GETRSP 5 |
29 | #define TPM_PPI_FN_SUBREQ2 7 | 30 | #define TPM_PPI_FN_SUBREQ2 7 |
30 | #define TPM_PPI_FN_GETOPR 8 | 31 | #define TPM_PPI_FN_GETOPR 8 |
31 | #define PPI_TPM_REQ_MAX 22 | 32 | #define PPI_TPM_REQ_MAX 101 /* PPI 1.3 for TPM 2 */ |
32 | #define PPI_VS_REQ_START 128 | 33 | #define PPI_VS_REQ_START 128 |
33 | #define PPI_VS_REQ_END 255 | 34 | #define PPI_VS_REQ_END 255 |
34 | 35 | ||
@@ -36,14 +37,18 @@ static const guid_t tpm_ppi_guid = | |||
36 | GUID_INIT(0x3DDDFAA6, 0x361B, 0x4EB4, | 37 | GUID_INIT(0x3DDDFAA6, 0x361B, 0x4EB4, |
37 | 0xA4, 0x24, 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53); | 38 | 0xA4, 0x24, 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53); |
38 | 39 | ||
40 | static bool tpm_ppi_req_has_parameter(u64 req) | ||
41 | { | ||
42 | return req == 23; | ||
43 | } | ||
44 | |||
39 | static inline union acpi_object * | 45 | static inline union acpi_object * |
40 | tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type, | 46 | tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type, |
41 | union acpi_object *argv4) | 47 | union acpi_object *argv4, u64 rev) |
42 | { | 48 | { |
43 | BUG_ON(!ppi_handle); | 49 | BUG_ON(!ppi_handle); |
44 | return acpi_evaluate_dsm_typed(ppi_handle, &tpm_ppi_guid, | 50 | return acpi_evaluate_dsm_typed(ppi_handle, &tpm_ppi_guid, |
45 | TPM_PPI_REVISION_ID, | 51 | rev, func, argv4, type); |
46 | func, argv4, type); | ||
47 | } | 52 | } |
48 | 53 | ||
49 | static ssize_t tpm_show_ppi_version(struct device *dev, | 54 | static ssize_t tpm_show_ppi_version(struct device *dev, |
@@ -60,9 +65,14 @@ static ssize_t tpm_show_ppi_request(struct device *dev, | |||
60 | ssize_t size = -EINVAL; | 65 | ssize_t size = -EINVAL; |
61 | union acpi_object *obj; | 66 | union acpi_object *obj; |
62 | struct tpm_chip *chip = to_tpm_chip(dev); | 67 | struct tpm_chip *chip = to_tpm_chip(dev); |
68 | u64 rev = TPM_PPI_REVISION_ID_2; | ||
69 | u64 req; | ||
70 | |||
71 | if (strcmp(chip->ppi_version, "1.2") < 0) | ||
72 | rev = TPM_PPI_REVISION_ID_1; | ||
63 | 73 | ||
64 | obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ, | 74 | obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ, |
65 | ACPI_TYPE_PACKAGE, NULL); | 75 | ACPI_TYPE_PACKAGE, NULL, rev); |
66 | if (!obj) | 76 | if (!obj) |
67 | return -ENXIO; | 77 | return -ENXIO; |
68 | 78 | ||
@@ -72,7 +82,23 @@ static ssize_t tpm_show_ppi_request(struct device *dev, | |||
72 | * error. The second is pending TPM operation requested by the OS, 0 | 82 | * error. The second is pending TPM operation requested by the OS, 0 |
73 | * means none and >0 means operation value. | 83 | * means none and >0 means operation value. |
74 | */ | 84 | */ |
75 | if (obj->package.count == 2 && | 85 | if (obj->package.count == 3 && |
86 | obj->package.elements[0].type == ACPI_TYPE_INTEGER && | ||
87 | obj->package.elements[1].type == ACPI_TYPE_INTEGER && | ||
88 | obj->package.elements[2].type == ACPI_TYPE_INTEGER) { | ||
89 | if (obj->package.elements[0].integer.value) | ||
90 | size = -EFAULT; | ||
91 | else { | ||
92 | req = obj->package.elements[1].integer.value; | ||
93 | if (tpm_ppi_req_has_parameter(req)) | ||
94 | size = scnprintf(buf, PAGE_SIZE, | ||
95 | "%llu %llu\n", req, | ||
96 | obj->package.elements[2].integer.value); | ||
97 | else | ||
98 | size = scnprintf(buf, PAGE_SIZE, | ||
99 | "%llu\n", req); | ||
100 | } | ||
101 | } else if (obj->package.count == 2 && | ||
76 | obj->package.elements[0].type == ACPI_TYPE_INTEGER && | 102 | obj->package.elements[0].type == ACPI_TYPE_INTEGER && |
77 | obj->package.elements[1].type == ACPI_TYPE_INTEGER) { | 103 | obj->package.elements[1].type == ACPI_TYPE_INTEGER) { |
78 | if (obj->package.elements[0].integer.value) | 104 | if (obj->package.elements[0].integer.value) |
@@ -94,9 +120,10 @@ static ssize_t tpm_store_ppi_request(struct device *dev, | |||
94 | u32 req; | 120 | u32 req; |
95 | u64 ret; | 121 | u64 ret; |
96 | int func = TPM_PPI_FN_SUBREQ; | 122 | int func = TPM_PPI_FN_SUBREQ; |
97 | union acpi_object *obj, tmp; | 123 | union acpi_object *obj, tmp[2]; |
98 | union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp); | 124 | union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(2, tmp); |
99 | struct tpm_chip *chip = to_tpm_chip(dev); | 125 | struct tpm_chip *chip = to_tpm_chip(dev); |
126 | u64 rev = TPM_PPI_REVISION_ID_1; | ||
100 | 127 | ||
101 | /* | 128 | /* |
102 | * the function to submit TPM operation request to pre-os environment | 129 | * the function to submit TPM operation request to pre-os environment |
@@ -104,7 +131,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev, | |||
104 | * version 1.1 | 131 | * version 1.1 |
105 | */ | 132 | */ |
106 | if (acpi_check_dsm(chip->acpi_dev_handle, &tpm_ppi_guid, | 133 | if (acpi_check_dsm(chip->acpi_dev_handle, &tpm_ppi_guid, |
107 | TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_SUBREQ2)) | 134 | TPM_PPI_REVISION_ID_1, 1 << TPM_PPI_FN_SUBREQ2)) |
108 | func = TPM_PPI_FN_SUBREQ2; | 135 | func = TPM_PPI_FN_SUBREQ2; |
109 | 136 | ||
110 | /* | 137 | /* |
@@ -113,20 +140,29 @@ static ssize_t tpm_store_ppi_request(struct device *dev, | |||
113 | * string/package type. For PPI version 1.0 and 1.1, use buffer type | 140 | * string/package type. For PPI version 1.0 and 1.1, use buffer type |
114 | * for compatibility, and use package type since 1.2 according to spec. | 141 | * for compatibility, and use package type since 1.2 according to spec. |
115 | */ | 142 | */ |
116 | if (strcmp(chip->ppi_version, "1.2") < 0) { | 143 | if (strcmp(chip->ppi_version, "1.3") == 0) { |
144 | if (sscanf(buf, "%llu %llu", &tmp[0].integer.value, | ||
145 | &tmp[1].integer.value) != 2) | ||
146 | goto ppi12; | ||
147 | rev = TPM_PPI_REVISION_ID_2; | ||
148 | tmp[0].type = ACPI_TYPE_INTEGER; | ||
149 | tmp[1].type = ACPI_TYPE_INTEGER; | ||
150 | } else if (strcmp(chip->ppi_version, "1.2") < 0) { | ||
117 | if (sscanf(buf, "%d", &req) != 1) | 151 | if (sscanf(buf, "%d", &req) != 1) |
118 | return -EINVAL; | 152 | return -EINVAL; |
119 | argv4.type = ACPI_TYPE_BUFFER; | 153 | argv4.type = ACPI_TYPE_BUFFER; |
120 | argv4.buffer.length = sizeof(req); | 154 | argv4.buffer.length = sizeof(req); |
121 | argv4.buffer.pointer = (u8 *)&req; | 155 | argv4.buffer.pointer = (u8 *)&req; |
122 | } else { | 156 | } else { |
123 | tmp.type = ACPI_TYPE_INTEGER; | 157 | ppi12: |
124 | if (sscanf(buf, "%llu", &tmp.integer.value) != 1) | 158 | argv4.package.count = 1; |
159 | tmp[0].type = ACPI_TYPE_INTEGER; | ||
160 | if (sscanf(buf, "%llu", &tmp[0].integer.value) != 1) | ||
125 | return -EINVAL; | 161 | return -EINVAL; |
126 | } | 162 | } |
127 | 163 | ||
128 | obj = tpm_eval_dsm(chip->acpi_dev_handle, func, ACPI_TYPE_INTEGER, | 164 | obj = tpm_eval_dsm(chip->acpi_dev_handle, func, ACPI_TYPE_INTEGER, |
129 | &argv4); | 165 | &argv4, rev); |
130 | if (!obj) { | 166 | if (!obj) { |
131 | return -ENXIO; | 167 | return -ENXIO; |
132 | } else { | 168 | } else { |
@@ -170,7 +206,7 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev, | |||
170 | if (strcmp(chip->ppi_version, "1.2") < 0) | 206 | if (strcmp(chip->ppi_version, "1.2") < 0) |
171 | obj = &tmp; | 207 | obj = &tmp; |
172 | obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETACT, | 208 | obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETACT, |
173 | ACPI_TYPE_INTEGER, obj); | 209 | ACPI_TYPE_INTEGER, obj, TPM_PPI_REVISION_ID_1); |
174 | if (!obj) { | 210 | if (!obj) { |
175 | return -ENXIO; | 211 | return -ENXIO; |
176 | } else { | 212 | } else { |
@@ -196,7 +232,7 @@ static ssize_t tpm_show_ppi_response(struct device *dev, | |||
196 | struct tpm_chip *chip = to_tpm_chip(dev); | 232 | struct tpm_chip *chip = to_tpm_chip(dev); |
197 | 233 | ||
198 | obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP, | 234 | obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP, |
199 | ACPI_TYPE_PACKAGE, NULL); | 235 | ACPI_TYPE_PACKAGE, NULL, TPM_PPI_REVISION_ID_1); |
200 | if (!obj) | 236 | if (!obj) |
201 | return -ENXIO; | 237 | return -ENXIO; |
202 | 238 | ||
@@ -264,7 +300,7 @@ static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start, | |||
264 | "User not required", | 300 | "User not required", |
265 | }; | 301 | }; |
266 | 302 | ||
267 | if (!acpi_check_dsm(dev_handle, &tpm_ppi_guid, TPM_PPI_REVISION_ID, | 303 | if (!acpi_check_dsm(dev_handle, &tpm_ppi_guid, TPM_PPI_REVISION_ID_1, |
268 | 1 << TPM_PPI_FN_GETOPR)) | 304 | 1 << TPM_PPI_FN_GETOPR)) |
269 | return -EPERM; | 305 | return -EPERM; |
270 | 306 | ||
@@ -272,7 +308,8 @@ static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start, | |||
272 | for (i = start; i <= end; i++) { | 308 | for (i = start; i <= end; i++) { |
273 | tmp.integer.value = i; | 309 | tmp.integer.value = i; |
274 | obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR, | 310 | obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR, |
275 | ACPI_TYPE_INTEGER, &argv); | 311 | ACPI_TYPE_INTEGER, &argv, |
312 | TPM_PPI_REVISION_ID_1); | ||
276 | if (!obj) { | 313 | if (!obj) { |
277 | return -ENOMEM; | 314 | return -ENOMEM; |
278 | } else { | 315 | } else { |
@@ -338,12 +375,13 @@ void tpm_add_ppi(struct tpm_chip *chip) | |||
338 | return; | 375 | return; |
339 | 376 | ||
340 | if (!acpi_check_dsm(chip->acpi_dev_handle, &tpm_ppi_guid, | 377 | if (!acpi_check_dsm(chip->acpi_dev_handle, &tpm_ppi_guid, |
341 | TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_VERSION)) | 378 | TPM_PPI_REVISION_ID_1, 1 << TPM_PPI_FN_VERSION)) |
342 | return; | 379 | return; |
343 | 380 | ||
344 | /* Cache PPI version string. */ | 381 | /* Cache PPI version string. */ |
345 | obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, &tpm_ppi_guid, | 382 | obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, &tpm_ppi_guid, |
346 | TPM_PPI_REVISION_ID, TPM_PPI_FN_VERSION, | 383 | TPM_PPI_REVISION_ID_1, |
384 | TPM_PPI_FN_VERSION, | ||
347 | NULL, ACPI_TYPE_STRING); | 385 | NULL, ACPI_TYPE_STRING); |
348 | if (obj) { | 386 | if (obj) { |
349 | strlcpy(chip->ppi_version, obj->string.pointer, | 387 | strlcpy(chip->ppi_version, obj->string.pointer, |
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index bf7e49cfa643..b9f64684c3fb 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c | |||
@@ -481,7 +481,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) | |||
481 | goto out_err; | 481 | goto out_err; |
482 | } | 482 | } |
483 | } | 483 | } |
484 | return len; | 484 | return 0; |
485 | out_err: | 485 | out_err: |
486 | tpm_tis_ready(chip); | 486 | tpm_tis_ready(chip); |
487 | return rc; | 487 | return rc; |
@@ -521,35 +521,38 @@ static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = { | |||
521 | (TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } }, | 521 | (TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } }, |
522 | }; | 522 | }; |
523 | 523 | ||
524 | static bool tpm_tis_update_timeouts(struct tpm_chip *chip, | 524 | static void tpm_tis_update_timeouts(struct tpm_chip *chip, |
525 | unsigned long *timeout_cap) | 525 | unsigned long *timeout_cap) |
526 | { | 526 | { |
527 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | 527 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
528 | int i, rc; | 528 | int i, rc; |
529 | u32 did_vid; | 529 | u32 did_vid; |
530 | 530 | ||
531 | chip->timeout_adjusted = false; | ||
532 | |||
531 | if (chip->ops->clk_enable != NULL) | 533 | if (chip->ops->clk_enable != NULL) |
532 | chip->ops->clk_enable(chip, true); | 534 | chip->ops->clk_enable(chip, true); |
533 | 535 | ||
534 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); | 536 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); |
535 | if (rc < 0) | 537 | if (rc < 0) { |
538 | dev_warn(&chip->dev, "%s: failed to read did_vid: %d\n", | ||
539 | __func__, rc); | ||
536 | goto out; | 540 | goto out; |
541 | } | ||
537 | 542 | ||
538 | for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { | 543 | for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { |
539 | if (vendor_timeout_overrides[i].did_vid != did_vid) | 544 | if (vendor_timeout_overrides[i].did_vid != did_vid) |
540 | continue; | 545 | continue; |
541 | memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, | 546 | memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, |
542 | sizeof(vendor_timeout_overrides[i].timeout_us)); | 547 | sizeof(vendor_timeout_overrides[i].timeout_us)); |
543 | rc = true; | 548 | chip->timeout_adjusted = true; |
544 | } | 549 | } |
545 | 550 | ||
546 | rc = false; | ||
547 | |||
548 | out: | 551 | out: |
549 | if (chip->ops->clk_enable != NULL) | 552 | if (chip->ops->clk_enable != NULL) |
550 | chip->ops->clk_enable(chip, false); | 553 | chip->ops->clk_enable(chip, false); |
551 | 554 | ||
552 | return rc; | 555 | return; |
553 | } | 556 | } |
554 | 557 | ||
555 | /* | 558 | /* |
@@ -913,7 +916,11 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, | |||
913 | intmask &= ~TPM_GLOBAL_INT_ENABLE; | 916 | intmask &= ~TPM_GLOBAL_INT_ENABLE; |
914 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); | 917 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); |
915 | 918 | ||
919 | rc = tpm_chip_start(chip); | ||
920 | if (rc) | ||
921 | goto out_err; | ||
916 | rc = tpm2_probe(chip); | 922 | rc = tpm2_probe(chip); |
923 | tpm_chip_stop(chip); | ||
917 | if (rc) | 924 | if (rc) |
918 | goto out_err; | 925 | goto out_err; |
919 | 926 | ||
diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index 87a0ce47f201..d74f3de74ae6 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c | |||
@@ -303,9 +303,9 @@ out: | |||
303 | static int vtpm_proxy_is_driver_command(struct tpm_chip *chip, | 303 | static int vtpm_proxy_is_driver_command(struct tpm_chip *chip, |
304 | u8 *buf, size_t count) | 304 | u8 *buf, size_t count) |
305 | { | 305 | { |
306 | struct tpm_input_header *hdr = (struct tpm_input_header *)buf; | 306 | struct tpm_header *hdr = (struct tpm_header *)buf; |
307 | 307 | ||
308 | if (count < sizeof(struct tpm_input_header)) | 308 | if (count < sizeof(struct tpm_header)) |
309 | return 0; | 309 | return 0; |
310 | 310 | ||
311 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | 311 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
@@ -335,7 +335,6 @@ static int vtpm_proxy_is_driver_command(struct tpm_chip *chip, | |||
335 | static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count) | 335 | static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count) |
336 | { | 336 | { |
337 | struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); | 337 | struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); |
338 | int rc = 0; | ||
339 | 338 | ||
340 | if (count > sizeof(proxy_dev->buffer)) { | 339 | if (count > sizeof(proxy_dev->buffer)) { |
341 | dev_err(&chip->dev, | 340 | dev_err(&chip->dev, |
@@ -366,7 +365,7 @@ static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
366 | 365 | ||
367 | wake_up_interruptible(&proxy_dev->wq); | 366 | wake_up_interruptible(&proxy_dev->wq); |
368 | 367 | ||
369 | return rc; | 368 | return 0; |
370 | } | 369 | } |
371 | 370 | ||
372 | static void vtpm_proxy_tpm_op_cancel(struct tpm_chip *chip) | 371 | static void vtpm_proxy_tpm_op_cancel(struct tpm_chip *chip) |
@@ -402,7 +401,7 @@ static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) | |||
402 | { | 401 | { |
403 | struct tpm_buf buf; | 402 | struct tpm_buf buf; |
404 | int rc; | 403 | int rc; |
405 | const struct tpm_output_header *header; | 404 | const struct tpm_header *header; |
406 | struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); | 405 | struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); |
407 | 406 | ||
408 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 407 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
@@ -417,9 +416,7 @@ static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) | |||
417 | 416 | ||
418 | proxy_dev->state |= STATE_DRIVER_COMMAND; | 417 | proxy_dev->state |= STATE_DRIVER_COMMAND; |
419 | 418 | ||
420 | rc = tpm_transmit_cmd(chip, NULL, buf.data, tpm_buf_length(&buf), 0, | 419 | rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to set locality"); |
421 | TPM_TRANSMIT_NESTED, | ||
422 | "attempting to set locality"); | ||
423 | 420 | ||
424 | proxy_dev->state &= ~STATE_DRIVER_COMMAND; | 421 | proxy_dev->state &= ~STATE_DRIVER_COMMAND; |
425 | 422 | ||
@@ -428,7 +425,7 @@ static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) | |||
428 | goto out; | 425 | goto out; |
429 | } | 426 | } |
430 | 427 | ||
431 | header = (const struct tpm_output_header *)buf.data; | 428 | header = (const struct tpm_header *)buf.data; |
432 | rc = be32_to_cpu(header->return_code); | 429 | rc = be32_to_cpu(header->return_code); |
433 | if (rc) | 430 | if (rc) |
434 | locality = -1; | 431 | locality = -1; |
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c index b150f87f38f5..4e2d00cb0d81 100644 --- a/drivers/char/tpm/xen-tpmfront.c +++ b/drivers/char/tpm/xen-tpmfront.c | |||
@@ -163,7 +163,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
163 | wmb(); | 163 | wmb(); |
164 | notify_remote_via_evtchn(priv->evtchn); | 164 | notify_remote_via_evtchn(priv->evtchn); |
165 | 165 | ||
166 | ordinal = be32_to_cpu(((struct tpm_input_header*)buf)->ordinal); | 166 | ordinal = be32_to_cpu(((struct tpm_header *)buf)->ordinal); |
167 | duration = tpm_calc_ordinal_duration(chip, ordinal); | 167 | duration = tpm_calc_ordinal_duration(chip, ordinal); |
168 | 168 | ||
169 | if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration, | 169 | if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration, |
@@ -173,7 +173,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
173 | return -ETIME; | 173 | return -ETIME; |
174 | } | 174 | } |
175 | 175 | ||
176 | return count; | 176 | return 0; |
177 | } | 177 | } |
178 | 178 | ||
179 | static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) | 179 | static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) |
diff --git a/include/linux/tpm.h b/include/linux/tpm.h index b49a55cf775f..1b5436b213a2 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h | |||
@@ -22,12 +22,41 @@ | |||
22 | #ifndef __LINUX_TPM_H__ | 22 | #ifndef __LINUX_TPM_H__ |
23 | #define __LINUX_TPM_H__ | 23 | #define __LINUX_TPM_H__ |
24 | 24 | ||
25 | #include <linux/hw_random.h> | ||
26 | #include <linux/acpi.h> | ||
27 | #include <linux/cdev.h> | ||
28 | #include <linux/fs.h> | ||
29 | #include <crypto/hash_info.h> | ||
30 | |||
25 | #define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ | 31 | #define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ |
32 | #define TPM_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE | ||
26 | 33 | ||
27 | struct tpm_chip; | 34 | struct tpm_chip; |
28 | struct trusted_key_payload; | 35 | struct trusted_key_payload; |
29 | struct trusted_key_options; | 36 | struct trusted_key_options; |
30 | 37 | ||
38 | enum tpm_algorithms { | ||
39 | TPM_ALG_ERROR = 0x0000, | ||
40 | TPM_ALG_SHA1 = 0x0004, | ||
41 | TPM_ALG_KEYEDHASH = 0x0008, | ||
42 | TPM_ALG_SHA256 = 0x000B, | ||
43 | TPM_ALG_SHA384 = 0x000C, | ||
44 | TPM_ALG_SHA512 = 0x000D, | ||
45 | TPM_ALG_NULL = 0x0010, | ||
46 | TPM_ALG_SM3_256 = 0x0012, | ||
47 | }; | ||
48 | |||
49 | struct tpm_digest { | ||
50 | u16 alg_id; | ||
51 | u8 digest[TPM_MAX_DIGEST_SIZE]; | ||
52 | } __packed; | ||
53 | |||
54 | struct tpm_bank_info { | ||
55 | u16 alg_id; | ||
56 | u16 digest_size; | ||
57 | u16 crypto_id; | ||
58 | }; | ||
59 | |||
31 | enum TPM_OPS_FLAGS { | 60 | enum TPM_OPS_FLAGS { |
32 | TPM_OPS_AUTO_STARTUP = BIT(0), | 61 | TPM_OPS_AUTO_STARTUP = BIT(0), |
33 | }; | 62 | }; |
@@ -41,7 +70,7 @@ struct tpm_class_ops { | |||
41 | int (*send) (struct tpm_chip *chip, u8 *buf, size_t len); | 70 | int (*send) (struct tpm_chip *chip, u8 *buf, size_t len); |
42 | void (*cancel) (struct tpm_chip *chip); | 71 | void (*cancel) (struct tpm_chip *chip); |
43 | u8 (*status) (struct tpm_chip *chip); | 72 | u8 (*status) (struct tpm_chip *chip); |
44 | bool (*update_timeouts)(struct tpm_chip *chip, | 73 | void (*update_timeouts)(struct tpm_chip *chip, |
45 | unsigned long *timeout_cap); | 74 | unsigned long *timeout_cap); |
46 | int (*go_idle)(struct tpm_chip *chip); | 75 | int (*go_idle)(struct tpm_chip *chip); |
47 | int (*cmd_ready)(struct tpm_chip *chip); | 76 | int (*cmd_ready)(struct tpm_chip *chip); |
@@ -50,11 +79,100 @@ struct tpm_class_ops { | |||
50 | void (*clk_enable)(struct tpm_chip *chip, bool value); | 79 | void (*clk_enable)(struct tpm_chip *chip, bool value); |
51 | }; | 80 | }; |
52 | 81 | ||
82 | #define TPM_NUM_EVENT_LOG_FILES 3 | ||
83 | |||
84 | /* Indexes the duration array */ | ||
85 | enum tpm_duration { | ||
86 | TPM_SHORT = 0, | ||
87 | TPM_MEDIUM = 1, | ||
88 | TPM_LONG = 2, | ||
89 | TPM_LONG_LONG = 3, | ||
90 | TPM_UNDEFINED, | ||
91 | TPM_NUM_DURATIONS = TPM_UNDEFINED, | ||
92 | }; | ||
93 | |||
94 | #define TPM_PPI_VERSION_LEN 3 | ||
95 | |||
96 | struct tpm_space { | ||
97 | u32 context_tbl[3]; | ||
98 | u8 *context_buf; | ||
99 | u32 session_tbl[3]; | ||
100 | u8 *session_buf; | ||
101 | }; | ||
102 | |||
103 | struct tpm_bios_log { | ||
104 | void *bios_event_log; | ||
105 | void *bios_event_log_end; | ||
106 | }; | ||
107 | |||
108 | struct tpm_chip_seqops { | ||
109 | struct tpm_chip *chip; | ||
110 | const struct seq_operations *seqops; | ||
111 | }; | ||
112 | |||
113 | struct tpm_chip { | ||
114 | struct device dev; | ||
115 | struct device devs; | ||
116 | struct cdev cdev; | ||
117 | struct cdev cdevs; | ||
118 | |||
119 | /* A driver callback under ops cannot be run unless ops_sem is held | ||
120 | * (sometimes implicitly, eg for the sysfs code). ops becomes null | ||
121 | * when the driver is unregistered, see tpm_try_get_ops. | ||
122 | */ | ||
123 | struct rw_semaphore ops_sem; | ||
124 | const struct tpm_class_ops *ops; | ||
125 | |||
126 | struct tpm_bios_log log; | ||
127 | struct tpm_chip_seqops bin_log_seqops; | ||
128 | struct tpm_chip_seqops ascii_log_seqops; | ||
129 | |||
130 | unsigned int flags; | ||
131 | |||
132 | int dev_num; /* /dev/tpm# */ | ||
133 | unsigned long is_open; /* only one allowed */ | ||
134 | |||
135 | char hwrng_name[64]; | ||
136 | struct hwrng hwrng; | ||
137 | |||
138 | struct mutex tpm_mutex; /* tpm is processing */ | ||
139 | |||
140 | unsigned long timeout_a; /* jiffies */ | ||
141 | unsigned long timeout_b; /* jiffies */ | ||
142 | unsigned long timeout_c; /* jiffies */ | ||
143 | unsigned long timeout_d; /* jiffies */ | ||
144 | bool timeout_adjusted; | ||
145 | unsigned long duration[TPM_NUM_DURATIONS]; /* jiffies */ | ||
146 | bool duration_adjusted; | ||
147 | |||
148 | struct dentry *bios_dir[TPM_NUM_EVENT_LOG_FILES]; | ||
149 | |||
150 | const struct attribute_group *groups[3]; | ||
151 | unsigned int groups_cnt; | ||
152 | |||
153 | u32 nr_allocated_banks; | ||
154 | struct tpm_bank_info *allocated_banks; | ||
155 | #ifdef CONFIG_ACPI | ||
156 | acpi_handle acpi_dev_handle; | ||
157 | char ppi_version[TPM_PPI_VERSION_LEN + 1]; | ||
158 | #endif /* CONFIG_ACPI */ | ||
159 | |||
160 | struct tpm_space work_space; | ||
161 | u32 last_cc; | ||
162 | u32 nr_commands; | ||
163 | u32 *cc_attrs_tbl; | ||
164 | |||
165 | /* active locality */ | ||
166 | int locality; | ||
167 | }; | ||
168 | |||
53 | #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) | 169 | #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) |
54 | 170 | ||
55 | extern int tpm_is_tpm2(struct tpm_chip *chip); | 171 | extern int tpm_is_tpm2(struct tpm_chip *chip); |
56 | extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf); | 172 | extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, |
57 | extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash); | 173 | struct tpm_digest *digest); |
174 | extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, | ||
175 | struct tpm_digest *digests); | ||
58 | extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen); | 176 | extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen); |
59 | extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max); | 177 | extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max); |
60 | extern int tpm_seal_trusted(struct tpm_chip *chip, | 178 | extern int tpm_seal_trusted(struct tpm_chip *chip, |
@@ -70,13 +188,14 @@ static inline int tpm_is_tpm2(struct tpm_chip *chip) | |||
70 | return -ENODEV; | 188 | return -ENODEV; |
71 | } | 189 | } |
72 | 190 | ||
73 | static inline int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) | 191 | static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, |
192 | struct tpm_digest *digest) | ||
74 | { | 193 | { |
75 | return -ENODEV; | 194 | return -ENODEV; |
76 | } | 195 | } |
77 | 196 | ||
78 | static inline int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, | 197 | static inline int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, |
79 | const u8 *hash) | 198 | struct tpm_digest *digests) |
80 | { | 199 | { |
81 | return -ENODEV; | 200 | return -ENODEV; |
82 | } | 201 | } |
diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h index 20d9da77fc11..81519f163211 100644 --- a/include/linux/tpm_eventlog.h +++ b/include/linux/tpm_eventlog.h | |||
@@ -3,12 +3,11 @@ | |||
3 | #ifndef __LINUX_TPM_EVENTLOG_H__ | 3 | #ifndef __LINUX_TPM_EVENTLOG_H__ |
4 | #define __LINUX_TPM_EVENTLOG_H__ | 4 | #define __LINUX_TPM_EVENTLOG_H__ |
5 | 5 | ||
6 | #include <crypto/hash_info.h> | 6 | #include <linux/tpm.h> |
7 | 7 | ||
8 | #define TCG_EVENT_NAME_LEN_MAX 255 | 8 | #define TCG_EVENT_NAME_LEN_MAX 255 |
9 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ | 9 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ |
10 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ | 10 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ |
11 | #define TPM2_ACTIVE_PCR_BANKS 3 | ||
12 | 11 | ||
13 | #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x1 | 12 | #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x1 |
14 | #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x2 | 13 | #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x2 |
@@ -82,7 +81,7 @@ struct tcg_efi_specid_event_algs { | |||
82 | u16 digest_size; | 81 | u16 digest_size; |
83 | } __packed; | 82 | } __packed; |
84 | 83 | ||
85 | struct tcg_efi_specid_event { | 84 | struct tcg_efi_specid_event_head { |
86 | u8 signature[16]; | 85 | u8 signature[16]; |
87 | u32 platform_class; | 86 | u32 platform_class; |
88 | u8 spec_version_minor; | 87 | u8 spec_version_minor; |
@@ -90,9 +89,7 @@ struct tcg_efi_specid_event { | |||
90 | u8 spec_errata; | 89 | u8 spec_errata; |
91 | u8 uintnsize; | 90 | u8 uintnsize; |
92 | u32 num_algs; | 91 | u32 num_algs; |
93 | struct tcg_efi_specid_event_algs digest_sizes[TPM2_ACTIVE_PCR_BANKS]; | 92 | struct tcg_efi_specid_event_algs digest_sizes[]; |
94 | u8 vendor_info_size; | ||
95 | u8 vendor_info[0]; | ||
96 | } __packed; | 93 | } __packed; |
97 | 94 | ||
98 | struct tcg_pcr_event { | 95 | struct tcg_pcr_event { |
@@ -108,17 +105,11 @@ struct tcg_event_field { | |||
108 | u8 event[0]; | 105 | u8 event[0]; |
109 | } __packed; | 106 | } __packed; |
110 | 107 | ||
111 | struct tpm2_digest { | 108 | struct tcg_pcr_event2_head { |
112 | u16 alg_id; | ||
113 | u8 digest[SHA512_DIGEST_SIZE]; | ||
114 | } __packed; | ||
115 | |||
116 | struct tcg_pcr_event2 { | ||
117 | u32 pcr_idx; | 109 | u32 pcr_idx; |
118 | u32 event_type; | 110 | u32 event_type; |
119 | u32 count; | 111 | u32 count; |
120 | struct tpm2_digest digests[TPM2_ACTIVE_PCR_BANKS]; | 112 | struct tpm_digest digests[]; |
121 | struct tcg_event_field event; | ||
122 | } __packed; | 113 | } __packed; |
123 | 114 | ||
124 | #endif | 115 | #endif |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 026163f37ba1..d213e835c498 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -153,6 +153,7 @@ int ima_measurements_show(struct seq_file *m, void *v); | |||
153 | unsigned long ima_get_binary_runtime_size(void); | 153 | unsigned long ima_get_binary_runtime_size(void); |
154 | int ima_init_template(void); | 154 | int ima_init_template(void); |
155 | void ima_init_template_list(void); | 155 | void ima_init_template_list(void); |
156 | int __init ima_init_digests(void); | ||
156 | 157 | ||
157 | /* | 158 | /* |
158 | * used to protect h_table and sha_table | 159 | * used to protect h_table and sha_table |
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index acf2c7df7145..16a4f45863b1 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c | |||
@@ -643,12 +643,12 @@ int ima_calc_buffer_hash(const void *buf, loff_t len, | |||
643 | return calc_buffer_shash(buf, len, hash); | 643 | return calc_buffer_shash(buf, len, hash); |
644 | } | 644 | } |
645 | 645 | ||
646 | static void __init ima_pcrread(u32 idx, u8 *pcr) | 646 | static void __init ima_pcrread(u32 idx, struct tpm_digest *d) |
647 | { | 647 | { |
648 | if (!ima_tpm_chip) | 648 | if (!ima_tpm_chip) |
649 | return; | 649 | return; |
650 | 650 | ||
651 | if (tpm_pcr_read(ima_tpm_chip, idx, pcr) != 0) | 651 | if (tpm_pcr_read(ima_tpm_chip, idx, d) != 0) |
652 | pr_err("Error Communicating to TPM chip\n"); | 652 | pr_err("Error Communicating to TPM chip\n"); |
653 | } | 653 | } |
654 | 654 | ||
@@ -658,7 +658,7 @@ static void __init ima_pcrread(u32 idx, u8 *pcr) | |||
658 | static int __init ima_calc_boot_aggregate_tfm(char *digest, | 658 | static int __init ima_calc_boot_aggregate_tfm(char *digest, |
659 | struct crypto_shash *tfm) | 659 | struct crypto_shash *tfm) |
660 | { | 660 | { |
661 | u8 pcr_i[TPM_DIGEST_SIZE]; | 661 | struct tpm_digest d = { .alg_id = TPM_ALG_SHA1, .digest = {0} }; |
662 | int rc; | 662 | int rc; |
663 | u32 i; | 663 | u32 i; |
664 | SHASH_DESC_ON_STACK(shash, tfm); | 664 | SHASH_DESC_ON_STACK(shash, tfm); |
@@ -672,9 +672,9 @@ static int __init ima_calc_boot_aggregate_tfm(char *digest, | |||
672 | 672 | ||
673 | /* cumulative sha1 over tpm registers 0-7 */ | 673 | /* cumulative sha1 over tpm registers 0-7 */ |
674 | for (i = TPM_PCR0; i < TPM_PCR8; i++) { | 674 | for (i = TPM_PCR0; i < TPM_PCR8; i++) { |
675 | ima_pcrread(i, pcr_i); | 675 | ima_pcrread(i, &d); |
676 | /* now accumulate with current aggregate */ | 676 | /* now accumulate with current aggregate */ |
677 | rc = crypto_shash_update(shash, pcr_i, TPM_DIGEST_SIZE); | 677 | rc = crypto_shash_update(shash, d.digest, TPM_DIGEST_SIZE); |
678 | } | 678 | } |
679 | if (!rc) | 679 | if (!rc) |
680 | crypto_shash_final(shash, digest); | 680 | crypto_shash_final(shash, digest); |
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 6bb42a9c5e47..6c9295449751 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c | |||
@@ -123,8 +123,12 @@ int __init ima_init(void) | |||
123 | if (rc != 0) | 123 | if (rc != 0) |
124 | return rc; | 124 | return rc; |
125 | 125 | ||
126 | /* It can be called before ima_init_digests(), it does not use TPM. */ | ||
126 | ima_load_kexec_buffer(); | 127 | ima_load_kexec_buffer(); |
127 | 128 | ||
129 | rc = ima_init_digests(); | ||
130 | if (rc != 0) | ||
131 | return rc; | ||
128 | rc = ima_add_boot_aggregate(); /* boot aggregate must be first entry */ | 132 | rc = ima_add_boot_aggregate(); /* boot aggregate must be first entry */ |
129 | if (rc != 0) | 133 | if (rc != 0) |
130 | return rc; | 134 | return rc; |
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 0e41dc1df1d4..6b6d044e0440 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c | |||
@@ -27,6 +27,9 @@ | |||
27 | 27 | ||
28 | #define AUDIT_CAUSE_LEN_MAX 32 | 28 | #define AUDIT_CAUSE_LEN_MAX 32 |
29 | 29 | ||
30 | /* pre-allocated array of tpm_digest structures to extend a PCR */ | ||
31 | static struct tpm_digest *digests; | ||
32 | |||
30 | LIST_HEAD(ima_measurements); /* list of all measurements */ | 33 | LIST_HEAD(ima_measurements); /* list of all measurements */ |
31 | #ifdef CONFIG_IMA_KEXEC | 34 | #ifdef CONFIG_IMA_KEXEC |
32 | static unsigned long binary_runtime_size; | 35 | static unsigned long binary_runtime_size; |
@@ -140,11 +143,15 @@ unsigned long ima_get_binary_runtime_size(void) | |||
140 | static int ima_pcr_extend(const u8 *hash, int pcr) | 143 | static int ima_pcr_extend(const u8 *hash, int pcr) |
141 | { | 144 | { |
142 | int result = 0; | 145 | int result = 0; |
146 | int i; | ||
143 | 147 | ||
144 | if (!ima_tpm_chip) | 148 | if (!ima_tpm_chip) |
145 | return result; | 149 | return result; |
146 | 150 | ||
147 | result = tpm_pcr_extend(ima_tpm_chip, pcr, hash); | 151 | for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) |
152 | memcpy(digests[i].digest, hash, TPM_DIGEST_SIZE); | ||
153 | |||
154 | result = tpm_pcr_extend(ima_tpm_chip, pcr, digests); | ||
148 | if (result != 0) | 155 | if (result != 0) |
149 | pr_err("Error Communicating to TPM chip, result: %d\n", result); | 156 | pr_err("Error Communicating to TPM chip, result: %d\n", result); |
150 | return result; | 157 | return result; |
@@ -211,3 +218,21 @@ int ima_restore_measurement_entry(struct ima_template_entry *entry) | |||
211 | mutex_unlock(&ima_extend_list_mutex); | 218 | mutex_unlock(&ima_extend_list_mutex); |
212 | return result; | 219 | return result; |
213 | } | 220 | } |
221 | |||
222 | int __init ima_init_digests(void) | ||
223 | { | ||
224 | int i; | ||
225 | |||
226 | if (!ima_tpm_chip) | ||
227 | return 0; | ||
228 | |||
229 | digests = kcalloc(ima_tpm_chip->nr_allocated_banks, sizeof(*digests), | ||
230 | GFP_NOFS); | ||
231 | if (!digests) | ||
232 | return -ENOMEM; | ||
233 | |||
234 | for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) | ||
235 | digests[i].alg_id = ima_tpm_chip->allocated_banks[i].alg_id; | ||
236 | |||
237 | return 0; | ||
238 | } | ||
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 4d98f4f87236..bcc9c6ead7fd 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
@@ -34,6 +34,8 @@ | |||
34 | 34 | ||
35 | static const char hmac_alg[] = "hmac(sha1)"; | 35 | static const char hmac_alg[] = "hmac(sha1)"; |
36 | static const char hash_alg[] = "sha1"; | 36 | static const char hash_alg[] = "sha1"; |
37 | static struct tpm_chip *chip; | ||
38 | static struct tpm_digest *digests; | ||
37 | 39 | ||
38 | struct sdesc { | 40 | struct sdesc { |
39 | struct shash_desc shash; | 41 | struct shash_desc shash; |
@@ -362,7 +364,7 @@ int trusted_tpm_send(unsigned char *cmd, size_t buflen) | |||
362 | int rc; | 364 | int rc; |
363 | 365 | ||
364 | dump_tpm_buf(cmd); | 366 | dump_tpm_buf(cmd); |
365 | rc = tpm_send(NULL, cmd, buflen); | 367 | rc = tpm_send(chip, cmd, buflen); |
366 | dump_tpm_buf(cmd); | 368 | dump_tpm_buf(cmd); |
367 | if (rc > 0) | 369 | if (rc > 0) |
368 | /* Can't return positive return codes values to keyctl */ | 370 | /* Can't return positive return codes values to keyctl */ |
@@ -379,15 +381,10 @@ EXPORT_SYMBOL_GPL(trusted_tpm_send); | |||
379 | */ | 381 | */ |
380 | static int pcrlock(const int pcrnum) | 382 | static int pcrlock(const int pcrnum) |
381 | { | 383 | { |
382 | unsigned char hash[SHA1_DIGEST_SIZE]; | ||
383 | int ret; | ||
384 | |||
385 | if (!capable(CAP_SYS_ADMIN)) | 384 | if (!capable(CAP_SYS_ADMIN)) |
386 | return -EPERM; | 385 | return -EPERM; |
387 | ret = tpm_get_random(NULL, hash, SHA1_DIGEST_SIZE); | 386 | |
388 | if (ret != SHA1_DIGEST_SIZE) | 387 | return tpm_pcr_extend(chip, pcrnum, digests) ? -EINVAL : 0; |
389 | return ret; | ||
390 | return tpm_pcr_extend(NULL, pcrnum, hash) ? -EINVAL : 0; | ||
391 | } | 388 | } |
392 | 389 | ||
393 | /* | 390 | /* |
@@ -400,7 +397,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, | |||
400 | unsigned char ononce[TPM_NONCE_SIZE]; | 397 | unsigned char ononce[TPM_NONCE_SIZE]; |
401 | int ret; | 398 | int ret; |
402 | 399 | ||
403 | ret = tpm_get_random(NULL, ononce, TPM_NONCE_SIZE); | 400 | ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE); |
404 | if (ret != TPM_NONCE_SIZE) | 401 | if (ret != TPM_NONCE_SIZE) |
405 | return ret; | 402 | return ret; |
406 | 403 | ||
@@ -496,7 +493,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, | |||
496 | if (ret < 0) | 493 | if (ret < 0) |
497 | goto out; | 494 | goto out; |
498 | 495 | ||
499 | ret = tpm_get_random(NULL, td->nonceodd, TPM_NONCE_SIZE); | 496 | ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE); |
500 | if (ret != TPM_NONCE_SIZE) | 497 | if (ret != TPM_NONCE_SIZE) |
501 | goto out; | 498 | goto out; |
502 | ordinal = htonl(TPM_ORD_SEAL); | 499 | ordinal = htonl(TPM_ORD_SEAL); |
@@ -606,7 +603,7 @@ static int tpm_unseal(struct tpm_buf *tb, | |||
606 | 603 | ||
607 | ordinal = htonl(TPM_ORD_UNSEAL); | 604 | ordinal = htonl(TPM_ORD_UNSEAL); |
608 | keyhndl = htonl(SRKHANDLE); | 605 | keyhndl = htonl(SRKHANDLE); |
609 | ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE); | 606 | ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE); |
610 | if (ret != TPM_NONCE_SIZE) { | 607 | if (ret != TPM_NONCE_SIZE) { |
611 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); | 608 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); |
612 | return ret; | 609 | return ret; |
@@ -751,7 +748,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay, | |||
751 | int i; | 748 | int i; |
752 | int tpm2; | 749 | int tpm2; |
753 | 750 | ||
754 | tpm2 = tpm_is_tpm2(NULL); | 751 | tpm2 = tpm_is_tpm2(chip); |
755 | if (tpm2 < 0) | 752 | if (tpm2 < 0) |
756 | return tpm2; | 753 | return tpm2; |
757 | 754 | ||
@@ -920,7 +917,7 @@ static struct trusted_key_options *trusted_options_alloc(void) | |||
920 | struct trusted_key_options *options; | 917 | struct trusted_key_options *options; |
921 | int tpm2; | 918 | int tpm2; |
922 | 919 | ||
923 | tpm2 = tpm_is_tpm2(NULL); | 920 | tpm2 = tpm_is_tpm2(chip); |
924 | if (tpm2 < 0) | 921 | if (tpm2 < 0) |
925 | return NULL; | 922 | return NULL; |
926 | 923 | ||
@@ -970,7 +967,7 @@ static int trusted_instantiate(struct key *key, | |||
970 | size_t key_len; | 967 | size_t key_len; |
971 | int tpm2; | 968 | int tpm2; |
972 | 969 | ||
973 | tpm2 = tpm_is_tpm2(NULL); | 970 | tpm2 = tpm_is_tpm2(chip); |
974 | if (tpm2 < 0) | 971 | if (tpm2 < 0) |
975 | return tpm2; | 972 | return tpm2; |
976 | 973 | ||
@@ -1011,7 +1008,7 @@ static int trusted_instantiate(struct key *key, | |||
1011 | switch (key_cmd) { | 1008 | switch (key_cmd) { |
1012 | case Opt_load: | 1009 | case Opt_load: |
1013 | if (tpm2) | 1010 | if (tpm2) |
1014 | ret = tpm_unseal_trusted(NULL, payload, options); | 1011 | ret = tpm_unseal_trusted(chip, payload, options); |
1015 | else | 1012 | else |
1016 | ret = key_unseal(payload, options); | 1013 | ret = key_unseal(payload, options); |
1017 | dump_payload(payload); | 1014 | dump_payload(payload); |
@@ -1021,13 +1018,13 @@ static int trusted_instantiate(struct key *key, | |||
1021 | break; | 1018 | break; |
1022 | case Opt_new: | 1019 | case Opt_new: |
1023 | key_len = payload->key_len; | 1020 | key_len = payload->key_len; |
1024 | ret = tpm_get_random(NULL, payload->key, key_len); | 1021 | ret = tpm_get_random(chip, payload->key, key_len); |
1025 | if (ret != key_len) { | 1022 | if (ret != key_len) { |
1026 | pr_info("trusted_key: key_create failed (%d)\n", ret); | 1023 | pr_info("trusted_key: key_create failed (%d)\n", ret); |
1027 | goto out; | 1024 | goto out; |
1028 | } | 1025 | } |
1029 | if (tpm2) | 1026 | if (tpm2) |
1030 | ret = tpm_seal_trusted(NULL, payload, options); | 1027 | ret = tpm_seal_trusted(chip, payload, options); |
1031 | else | 1028 | else |
1032 | ret = key_seal(payload, options); | 1029 | ret = key_seal(payload, options); |
1033 | if (ret < 0) | 1030 | if (ret < 0) |
@@ -1221,21 +1218,59 @@ hashalg_fail: | |||
1221 | return ret; | 1218 | return ret; |
1222 | } | 1219 | } |
1223 | 1220 | ||
1221 | static int __init init_digests(void) | ||
1222 | { | ||
1223 | u8 digest[TPM_MAX_DIGEST_SIZE]; | ||
1224 | int ret; | ||
1225 | int i; | ||
1226 | |||
1227 | ret = tpm_get_random(chip, digest, TPM_MAX_DIGEST_SIZE); | ||
1228 | if (ret < 0) | ||
1229 | return ret; | ||
1230 | if (ret < TPM_MAX_DIGEST_SIZE) | ||
1231 | return -EFAULT; | ||
1232 | |||
1233 | digests = kcalloc(chip->nr_allocated_banks, sizeof(*digests), | ||
1234 | GFP_KERNEL); | ||
1235 | if (!digests) | ||
1236 | return -ENOMEM; | ||
1237 | |||
1238 | for (i = 0; i < chip->nr_allocated_banks; i++) | ||
1239 | memcpy(digests[i].digest, digest, TPM_MAX_DIGEST_SIZE); | ||
1240 | |||
1241 | return 0; | ||
1242 | } | ||
1243 | |||
1224 | static int __init init_trusted(void) | 1244 | static int __init init_trusted(void) |
1225 | { | 1245 | { |
1226 | int ret; | 1246 | int ret; |
1227 | 1247 | ||
1248 | chip = tpm_default_chip(); | ||
1249 | if (!chip) | ||
1250 | return -ENOENT; | ||
1251 | ret = init_digests(); | ||
1252 | if (ret < 0) | ||
1253 | goto err_put; | ||
1228 | ret = trusted_shash_alloc(); | 1254 | ret = trusted_shash_alloc(); |
1229 | if (ret < 0) | 1255 | if (ret < 0) |
1230 | return ret; | 1256 | goto err_free; |
1231 | ret = register_key_type(&key_type_trusted); | 1257 | ret = register_key_type(&key_type_trusted); |
1232 | if (ret < 0) | 1258 | if (ret < 0) |
1233 | trusted_shash_release(); | 1259 | goto err_release; |
1260 | return 0; | ||
1261 | err_release: | ||
1262 | trusted_shash_release(); | ||
1263 | err_free: | ||
1264 | kfree(digests); | ||
1265 | err_put: | ||
1266 | put_device(&chip->dev); | ||
1234 | return ret; | 1267 | return ret; |
1235 | } | 1268 | } |
1236 | 1269 | ||
1237 | static void __exit cleanup_trusted(void) | 1270 | static void __exit cleanup_trusted(void) |
1238 | { | 1271 | { |
1272 | put_device(&chip->dev); | ||
1273 | kfree(digests); | ||
1239 | trusted_shash_release(); | 1274 | trusted_shash_release(); |
1240 | unregister_key_type(&key_type_trusted); | 1275 | unregister_key_type(&key_type_trusted); |
1241 | } | 1276 | } |
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 313dc1091e6f..fb5758ac469e 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile | |||
@@ -50,6 +50,7 @@ ifneq (1, $(quicktest)) | |||
50 | TARGETS += timers | 50 | TARGETS += timers |
51 | endif | 51 | endif |
52 | TARGETS += tmpfs | 52 | TARGETS += tmpfs |
53 | TARGETS += tpm2 | ||
53 | TARGETS += user | 54 | TARGETS += user |
54 | TARGETS += vm | 55 | TARGETS += vm |
55 | TARGETS += x86 | 56 | TARGETS += x86 |
diff --git a/tools/testing/selftests/tpm2/Makefile b/tools/testing/selftests/tpm2/Makefile new file mode 100644 index 000000000000..9dd848427a7b --- /dev/null +++ b/tools/testing/selftests/tpm2/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) | ||
2 | include ../lib.mk | ||
3 | |||
4 | TEST_PROGS := test_smoke.sh test_space.sh | ||
diff --git a/tools/testing/selftests/tpm2/test_smoke.sh b/tools/testing/selftests/tpm2/test_smoke.sh new file mode 100755 index 000000000000..80521d46220c --- /dev/null +++ b/tools/testing/selftests/tpm2/test_smoke.sh | |||
@@ -0,0 +1,4 @@ | |||
1 | #!/bin/bash | ||
2 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) | ||
3 | |||
4 | python -m unittest -v tpm2_tests.SmokeTest | ||
diff --git a/tools/testing/selftests/tpm2/test_space.sh b/tools/testing/selftests/tpm2/test_space.sh new file mode 100755 index 000000000000..a6f5e346635e --- /dev/null +++ b/tools/testing/selftests/tpm2/test_space.sh | |||
@@ -0,0 +1,4 @@ | |||
1 | #!/bin/bash | ||
2 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) | ||
3 | |||
4 | python -m unittest -v tpm2_tests.SpaceTest | ||
diff --git a/tools/testing/selftests/tpm2/tpm2.py b/tools/testing/selftests/tpm2/tpm2.py new file mode 100644 index 000000000000..40ea95ce2ead --- /dev/null +++ b/tools/testing/selftests/tpm2/tpm2.py | |||
@@ -0,0 +1,696 @@ | |||
1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) | ||
2 | |||
3 | import hashlib | ||
4 | import os | ||
5 | import socket | ||
6 | import struct | ||
7 | import sys | ||
8 | import unittest | ||
9 | from fcntl import ioctl | ||
10 | |||
11 | |||
12 | TPM2_ST_NO_SESSIONS = 0x8001 | ||
13 | TPM2_ST_SESSIONS = 0x8002 | ||
14 | |||
15 | TPM2_CC_FIRST = 0x01FF | ||
16 | |||
17 | TPM2_CC_CREATE_PRIMARY = 0x0131 | ||
18 | TPM2_CC_DICTIONARY_ATTACK_LOCK_RESET = 0x0139 | ||
19 | TPM2_CC_CREATE = 0x0153 | ||
20 | TPM2_CC_LOAD = 0x0157 | ||
21 | TPM2_CC_UNSEAL = 0x015E | ||
22 | TPM2_CC_FLUSH_CONTEXT = 0x0165 | ||
23 | TPM2_CC_START_AUTH_SESSION = 0x0176 | ||
24 | TPM2_CC_GET_CAPABILITY = 0x017A | ||
25 | TPM2_CC_PCR_READ = 0x017E | ||
26 | TPM2_CC_POLICY_PCR = 0x017F | ||
27 | TPM2_CC_PCR_EXTEND = 0x0182 | ||
28 | TPM2_CC_POLICY_PASSWORD = 0x018C | ||
29 | TPM2_CC_POLICY_GET_DIGEST = 0x0189 | ||
30 | |||
31 | TPM2_SE_POLICY = 0x01 | ||
32 | TPM2_SE_TRIAL = 0x03 | ||
33 | |||
34 | TPM2_ALG_RSA = 0x0001 | ||
35 | TPM2_ALG_SHA1 = 0x0004 | ||
36 | TPM2_ALG_AES = 0x0006 | ||
37 | TPM2_ALG_KEYEDHASH = 0x0008 | ||
38 | TPM2_ALG_SHA256 = 0x000B | ||
39 | TPM2_ALG_NULL = 0x0010 | ||
40 | TPM2_ALG_CBC = 0x0042 | ||
41 | TPM2_ALG_CFB = 0x0043 | ||
42 | |||
43 | TPM2_RH_OWNER = 0x40000001 | ||
44 | TPM2_RH_NULL = 0x40000007 | ||
45 | TPM2_RH_LOCKOUT = 0x4000000A | ||
46 | TPM2_RS_PW = 0x40000009 | ||
47 | |||
48 | TPM2_RC_SIZE = 0x01D5 | ||
49 | TPM2_RC_AUTH_FAIL = 0x098E | ||
50 | TPM2_RC_POLICY_FAIL = 0x099D | ||
51 | TPM2_RC_COMMAND_CODE = 0x0143 | ||
52 | |||
53 | TSS2_RC_LAYER_SHIFT = 16 | ||
54 | TSS2_RESMGR_TPM_RC_LAYER = (11 << TSS2_RC_LAYER_SHIFT) | ||
55 | |||
56 | TPM2_CAP_HANDLES = 0x00000001 | ||
57 | TPM2_CAP_COMMANDS = 0x00000002 | ||
58 | TPM2_CAP_TPM_PROPERTIES = 0x00000006 | ||
59 | |||
60 | TPM2_PT_FIXED = 0x100 | ||
61 | TPM2_PT_TOTAL_COMMANDS = TPM2_PT_FIXED + 41 | ||
62 | |||
63 | HR_SHIFT = 24 | ||
64 | HR_LOADED_SESSION = 0x02000000 | ||
65 | HR_TRANSIENT = 0x80000000 | ||
66 | |||
67 | SHA1_DIGEST_SIZE = 20 | ||
68 | SHA256_DIGEST_SIZE = 32 | ||
69 | |||
70 | TPM2_VER0_ERRORS = { | ||
71 | 0x000: "TPM_RC_SUCCESS", | ||
72 | 0x030: "TPM_RC_BAD_TAG", | ||
73 | } | ||
74 | |||
75 | TPM2_VER1_ERRORS = { | ||
76 | 0x000: "TPM_RC_FAILURE", | ||
77 | 0x001: "TPM_RC_FAILURE", | ||
78 | 0x003: "TPM_RC_SEQUENCE", | ||
79 | 0x00B: "TPM_RC_PRIVATE", | ||
80 | 0x019: "TPM_RC_HMAC", | ||
81 | 0x020: "TPM_RC_DISABLED", | ||
82 | 0x021: "TPM_RC_EXCLUSIVE", | ||
83 | 0x024: "TPM_RC_AUTH_TYPE", | ||
84 | 0x025: "TPM_RC_AUTH_MISSING", | ||
85 | 0x026: "TPM_RC_POLICY", | ||
86 | 0x027: "TPM_RC_PCR", | ||
87 | 0x028: "TPM_RC_PCR_CHANGED", | ||
88 | 0x02D: "TPM_RC_UPGRADE", | ||
89 | 0x02E: "TPM_RC_TOO_MANY_CONTEXTS", | ||
90 | 0x02F: "TPM_RC_AUTH_UNAVAILABLE", | ||
91 | 0x030: "TPM_RC_REBOOT", | ||
92 | 0x031: "TPM_RC_UNBALANCED", | ||
93 | 0x042: "TPM_RC_COMMAND_SIZE", | ||
94 | 0x043: "TPM_RC_COMMAND_CODE", | ||
95 | 0x044: "TPM_RC_AUTHSIZE", | ||
96 | 0x045: "TPM_RC_AUTH_CONTEXT", | ||
97 | 0x046: "TPM_RC_NV_RANGE", | ||
98 | 0x047: "TPM_RC_NV_SIZE", | ||
99 | 0x048: "TPM_RC_NV_LOCKED", | ||
100 | 0x049: "TPM_RC_NV_AUTHORIZATION", | ||
101 | 0x04A: "TPM_RC_NV_UNINITIALIZED", | ||
102 | 0x04B: "TPM_RC_NV_SPACE", | ||
103 | 0x04C: "TPM_RC_NV_DEFINED", | ||
104 | 0x050: "TPM_RC_BAD_CONTEXT", | ||
105 | 0x051: "TPM_RC_CPHASH", | ||
106 | 0x052: "TPM_RC_PARENT", | ||
107 | 0x053: "TPM_RC_NEEDS_TEST", | ||
108 | 0x054: "TPM_RC_NO_RESULT", | ||
109 | 0x055: "TPM_RC_SENSITIVE", | ||
110 | 0x07F: "RC_MAX_FM0", | ||
111 | } | ||
112 | |||
113 | TPM2_FMT1_ERRORS = { | ||
114 | 0x001: "TPM_RC_ASYMMETRIC", | ||
115 | 0x002: "TPM_RC_ATTRIBUTES", | ||
116 | 0x003: "TPM_RC_HASH", | ||
117 | 0x004: "TPM_RC_VALUE", | ||
118 | 0x005: "TPM_RC_HIERARCHY", | ||
119 | 0x007: "TPM_RC_KEY_SIZE", | ||
120 | 0x008: "TPM_RC_MGF", | ||
121 | 0x009: "TPM_RC_MODE", | ||
122 | 0x00A: "TPM_RC_TYPE", | ||
123 | 0x00B: "TPM_RC_HANDLE", | ||
124 | 0x00C: "TPM_RC_KDF", | ||
125 | 0x00D: "TPM_RC_RANGE", | ||
126 | 0x00E: "TPM_RC_AUTH_FAIL", | ||
127 | 0x00F: "TPM_RC_NONCE", | ||
128 | 0x010: "TPM_RC_PP", | ||
129 | 0x012: "TPM_RC_SCHEME", | ||
130 | 0x015: "TPM_RC_SIZE", | ||
131 | 0x016: "TPM_RC_SYMMETRIC", | ||
132 | 0x017: "TPM_RC_TAG", | ||
133 | 0x018: "TPM_RC_SELECTOR", | ||
134 | 0x01A: "TPM_RC_INSUFFICIENT", | ||
135 | 0x01B: "TPM_RC_SIGNATURE", | ||
136 | 0x01C: "TPM_RC_KEY", | ||
137 | 0x01D: "TPM_RC_POLICY_FAIL", | ||
138 | 0x01F: "TPM_RC_INTEGRITY", | ||
139 | 0x020: "TPM_RC_TICKET", | ||
140 | 0x021: "TPM_RC_RESERVED_BITS", | ||
141 | 0x022: "TPM_RC_BAD_AUTH", | ||
142 | 0x023: "TPM_RC_EXPIRED", | ||
143 | 0x024: "TPM_RC_POLICY_CC", | ||
144 | 0x025: "TPM_RC_BINDING", | ||
145 | 0x026: "TPM_RC_CURVE", | ||
146 | 0x027: "TPM_RC_ECC_POINT", | ||
147 | } | ||
148 | |||
149 | TPM2_WARN_ERRORS = { | ||
150 | 0x001: "TPM_RC_CONTEXT_GAP", | ||
151 | 0x002: "TPM_RC_OBJECT_MEMORY", | ||
152 | 0x003: "TPM_RC_SESSION_MEMORY", | ||
153 | 0x004: "TPM_RC_MEMORY", | ||
154 | 0x005: "TPM_RC_SESSION_HANDLES", | ||
155 | 0x006: "TPM_RC_OBJECT_HANDLES", | ||
156 | 0x007: "TPM_RC_LOCALITY", | ||
157 | 0x008: "TPM_RC_YIELDED", | ||
158 | 0x009: "TPM_RC_CANCELED", | ||
159 | 0x00A: "TPM_RC_TESTING", | ||
160 | 0x010: "TPM_RC_REFERENCE_H0", | ||
161 | 0x011: "TPM_RC_REFERENCE_H1", | ||
162 | 0x012: "TPM_RC_REFERENCE_H2", | ||
163 | 0x013: "TPM_RC_REFERENCE_H3", | ||
164 | 0x014: "TPM_RC_REFERENCE_H4", | ||
165 | 0x015: "TPM_RC_REFERENCE_H5", | ||
166 | 0x016: "TPM_RC_REFERENCE_H6", | ||
167 | 0x018: "TPM_RC_REFERENCE_S0", | ||
168 | 0x019: "TPM_RC_REFERENCE_S1", | ||
169 | 0x01A: "TPM_RC_REFERENCE_S2", | ||
170 | 0x01B: "TPM_RC_REFERENCE_S3", | ||
171 | 0x01C: "TPM_RC_REFERENCE_S4", | ||
172 | 0x01D: "TPM_RC_REFERENCE_S5", | ||
173 | 0x01E: "TPM_RC_REFERENCE_S6", | ||
174 | 0x020: "TPM_RC_NV_RATE", | ||
175 | 0x021: "TPM_RC_LOCKOUT", | ||
176 | 0x022: "TPM_RC_RETRY", | ||
177 | 0x023: "TPM_RC_NV_UNAVAILABLE", | ||
178 | 0x7F: "TPM_RC_NOT_USED", | ||
179 | } | ||
180 | |||
181 | RC_VER1 = 0x100 | ||
182 | RC_FMT1 = 0x080 | ||
183 | RC_WARN = 0x900 | ||
184 | |||
185 | ALG_DIGEST_SIZE_MAP = { | ||
186 | TPM2_ALG_SHA1: SHA1_DIGEST_SIZE, | ||
187 | TPM2_ALG_SHA256: SHA256_DIGEST_SIZE, | ||
188 | } | ||
189 | |||
190 | ALG_HASH_FUNCTION_MAP = { | ||
191 | TPM2_ALG_SHA1: hashlib.sha1, | ||
192 | TPM2_ALG_SHA256: hashlib.sha256 | ||
193 | } | ||
194 | |||
195 | NAME_ALG_MAP = { | ||
196 | "sha1": TPM2_ALG_SHA1, | ||
197 | "sha256": TPM2_ALG_SHA256, | ||
198 | } | ||
199 | |||
200 | |||
201 | class UnknownAlgorithmIdError(Exception): | ||
202 | def __init__(self, alg): | ||
203 | self.alg = alg | ||
204 | |||
205 | def __str__(self): | ||
206 | return '0x%0x' % (alg) | ||
207 | |||
208 | |||
209 | class UnknownAlgorithmNameError(Exception): | ||
210 | def __init__(self, name): | ||
211 | self.name = name | ||
212 | |||
213 | def __str__(self): | ||
214 | return name | ||
215 | |||
216 | |||
217 | class UnknownPCRBankError(Exception): | ||
218 | def __init__(self, alg): | ||
219 | self.alg = alg | ||
220 | |||
221 | def __str__(self): | ||
222 | return '0x%0x' % (alg) | ||
223 | |||
224 | |||
225 | class ProtocolError(Exception): | ||
226 | def __init__(self, cc, rc): | ||
227 | self.cc = cc | ||
228 | self.rc = rc | ||
229 | |||
230 | if (rc & RC_FMT1) == RC_FMT1: | ||
231 | self.name = TPM2_FMT1_ERRORS.get(rc & 0x3f, "TPM_RC_UNKNOWN") | ||
232 | elif (rc & RC_WARN) == RC_WARN: | ||
233 | self.name = TPM2_WARN_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN") | ||
234 | elif (rc & RC_VER1) == RC_VER1: | ||
235 | self.name = TPM2_VER1_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN") | ||
236 | else: | ||
237 | self.name = TPM2_VER0_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN") | ||
238 | |||
239 | def __str__(self): | ||
240 | if self.cc: | ||
241 | return '%s: cc=0x%08x, rc=0x%08x' % (self.name, self.cc, self.rc) | ||
242 | else: | ||
243 | return '%s: rc=0x%08x' % (self.name, self.rc) | ||
244 | |||
245 | |||
246 | class AuthCommand(object): | ||
247 | """TPMS_AUTH_COMMAND""" | ||
248 | |||
249 | def __init__(self, session_handle=TPM2_RS_PW, nonce='', session_attributes=0, | ||
250 | hmac=''): | ||
251 | self.session_handle = session_handle | ||
252 | self.nonce = nonce | ||
253 | self.session_attributes = session_attributes | ||
254 | self.hmac = hmac | ||
255 | |||
256 | def __str__(self): | ||
257 | fmt = '>I H%us B H%us' % (len(self.nonce), len(self.hmac)) | ||
258 | return struct.pack(fmt, self.session_handle, len(self.nonce), | ||
259 | self.nonce, self.session_attributes, len(self.hmac), | ||
260 | self.hmac) | ||
261 | |||
262 | def __len__(self): | ||
263 | fmt = '>I H%us B H%us' % (len(self.nonce), len(self.hmac)) | ||
264 | return struct.calcsize(fmt) | ||
265 | |||
266 | |||
267 | class SensitiveCreate(object): | ||
268 | """TPMS_SENSITIVE_CREATE""" | ||
269 | |||
270 | def __init__(self, user_auth='', data=''): | ||
271 | self.user_auth = user_auth | ||
272 | self.data = data | ||
273 | |||
274 | def __str__(self): | ||
275 | fmt = '>H%us H%us' % (len(self.user_auth), len(self.data)) | ||
276 | return struct.pack(fmt, len(self.user_auth), self.user_auth, | ||
277 | len(self.data), self.data) | ||
278 | |||
279 | def __len__(self): | ||
280 | fmt = '>H%us H%us' % (len(self.user_auth), len(self.data)) | ||
281 | return struct.calcsize(fmt) | ||
282 | |||
283 | |||
284 | class Public(object): | ||
285 | """TPMT_PUBLIC""" | ||
286 | |||
287 | FIXED_TPM = (1 << 1) | ||
288 | FIXED_PARENT = (1 << 4) | ||
289 | SENSITIVE_DATA_ORIGIN = (1 << 5) | ||
290 | USER_WITH_AUTH = (1 << 6) | ||
291 | RESTRICTED = (1 << 16) | ||
292 | DECRYPT = (1 << 17) | ||
293 | |||
294 | def __fmt(self): | ||
295 | return '>HHIH%us%usH%us' % \ | ||
296 | (len(self.auth_policy), len(self.parameters), len(self.unique)) | ||
297 | |||
298 | def __init__(self, object_type, name_alg, object_attributes, auth_policy='', | ||
299 | parameters='', unique=''): | ||
300 | self.object_type = object_type | ||
301 | self.name_alg = name_alg | ||
302 | self.object_attributes = object_attributes | ||
303 | self.auth_policy = auth_policy | ||
304 | self.parameters = parameters | ||
305 | self.unique = unique | ||
306 | |||
307 | def __str__(self): | ||
308 | return struct.pack(self.__fmt(), | ||
309 | self.object_type, | ||
310 | self.name_alg, | ||
311 | self.object_attributes, | ||
312 | len(self.auth_policy), | ||
313 | self.auth_policy, | ||
314 | self.parameters, | ||
315 | len(self.unique), | ||
316 | self.unique) | ||
317 | |||
318 | def __len__(self): | ||
319 | return struct.calcsize(self.__fmt()) | ||
320 | |||
321 | |||
322 | def get_digest_size(alg): | ||
323 | ds = ALG_DIGEST_SIZE_MAP.get(alg) | ||
324 | if not ds: | ||
325 | raise UnknownAlgorithmIdError(alg) | ||
326 | return ds | ||
327 | |||
328 | |||
329 | def get_hash_function(alg): | ||
330 | f = ALG_HASH_FUNCTION_MAP.get(alg) | ||
331 | if not f: | ||
332 | raise UnknownAlgorithmIdError(alg) | ||
333 | return f | ||
334 | |||
335 | |||
336 | def get_algorithm(name): | ||
337 | alg = NAME_ALG_MAP.get(name) | ||
338 | if not alg: | ||
339 | raise UnknownAlgorithmNameError(name) | ||
340 | return alg | ||
341 | |||
342 | |||
343 | def hex_dump(d): | ||
344 | d = [format(ord(x), '02x') for x in d] | ||
345 | d = [d[i: i + 16] for i in xrange(0, len(d), 16)] | ||
346 | d = [' '.join(x) for x in d] | ||
347 | d = os.linesep.join(d) | ||
348 | |||
349 | return d | ||
350 | |||
351 | class Client: | ||
352 | FLAG_DEBUG = 0x01 | ||
353 | FLAG_SPACE = 0x02 | ||
354 | TPM_IOC_NEW_SPACE = 0xa200 | ||
355 | |||
356 | def __init__(self, flags = 0): | ||
357 | self.flags = flags | ||
358 | |||
359 | if (self.flags & Client.FLAG_SPACE) == 0: | ||
360 | self.tpm = open('/dev/tpm0', 'r+b') | ||
361 | else: | ||
362 | self.tpm = open('/dev/tpmrm0', 'r+b') | ||
363 | |||
364 | def close(self): | ||
365 | self.tpm.close() | ||
366 | |||
367 | def send_cmd(self, cmd): | ||
368 | self.tpm.write(cmd) | ||
369 | rsp = self.tpm.read() | ||
370 | |||
371 | if (self.flags & Client.FLAG_DEBUG) != 0: | ||
372 | sys.stderr.write('cmd' + os.linesep) | ||
373 | sys.stderr.write(hex_dump(cmd) + os.linesep) | ||
374 | sys.stderr.write('rsp' + os.linesep) | ||
375 | sys.stderr.write(hex_dump(rsp) + os.linesep) | ||
376 | |||
377 | rc = struct.unpack('>I', rsp[6:10])[0] | ||
378 | if rc != 0: | ||
379 | cc = struct.unpack('>I', cmd[6:10])[0] | ||
380 | raise ProtocolError(cc, rc) | ||
381 | |||
382 | return rsp | ||
383 | |||
384 | def read_pcr(self, i, bank_alg = TPM2_ALG_SHA1): | ||
385 | pcrsel_len = max((i >> 3) + 1, 3) | ||
386 | pcrsel = [0] * pcrsel_len | ||
387 | pcrsel[i >> 3] = 1 << (i & 7) | ||
388 | pcrsel = ''.join(map(chr, pcrsel)) | ||
389 | |||
390 | fmt = '>HII IHB%us' % (pcrsel_len) | ||
391 | cmd = struct.pack(fmt, | ||
392 | TPM2_ST_NO_SESSIONS, | ||
393 | struct.calcsize(fmt), | ||
394 | TPM2_CC_PCR_READ, | ||
395 | 1, | ||
396 | bank_alg, | ||
397 | pcrsel_len, pcrsel) | ||
398 | |||
399 | rsp = self.send_cmd(cmd) | ||
400 | |||
401 | pcr_update_cnt, pcr_select_cnt = struct.unpack('>II', rsp[10:18]) | ||
402 | assert pcr_select_cnt == 1 | ||
403 | rsp = rsp[18:] | ||
404 | |||
405 | alg2, pcrsel_len2 = struct.unpack('>HB', rsp[:3]) | ||
406 | assert bank_alg == alg2 and pcrsel_len == pcrsel_len2 | ||
407 | rsp = rsp[3 + pcrsel_len:] | ||
408 | |||
409 | digest_cnt = struct.unpack('>I', rsp[:4])[0] | ||
410 | if digest_cnt == 0: | ||
411 | return None | ||
412 | rsp = rsp[6:] | ||
413 | |||
414 | return rsp | ||
415 | |||
416 | def extend_pcr(self, i, dig, bank_alg = TPM2_ALG_SHA1): | ||
417 | ds = get_digest_size(bank_alg) | ||
418 | assert(ds == len(dig)) | ||
419 | |||
420 | auth_cmd = AuthCommand() | ||
421 | |||
422 | fmt = '>HII I I%us IH%us' % (len(auth_cmd), ds) | ||
423 | cmd = struct.pack( | ||
424 | fmt, | ||
425 | TPM2_ST_SESSIONS, | ||
426 | struct.calcsize(fmt), | ||
427 | TPM2_CC_PCR_EXTEND, | ||
428 | i, | ||
429 | len(auth_cmd), | ||
430 | str(auth_cmd), | ||
431 | 1, bank_alg, dig) | ||
432 | |||
433 | self.send_cmd(cmd) | ||
434 | |||
435 | def start_auth_session(self, session_type, name_alg = TPM2_ALG_SHA1): | ||
436 | fmt = '>HII IIH16sHBHH' | ||
437 | cmd = struct.pack(fmt, | ||
438 | TPM2_ST_NO_SESSIONS, | ||
439 | struct.calcsize(fmt), | ||
440 | TPM2_CC_START_AUTH_SESSION, | ||
441 | TPM2_RH_NULL, | ||
442 | TPM2_RH_NULL, | ||
443 | 16, | ||
444 | '\0' * 16, | ||
445 | 0, | ||
446 | session_type, | ||
447 | TPM2_ALG_NULL, | ||
448 | name_alg) | ||
449 | |||
450 | return struct.unpack('>I', self.send_cmd(cmd)[10:14])[0] | ||
451 | |||
452 | def __calc_pcr_digest(self, pcrs, bank_alg = TPM2_ALG_SHA1, | ||
453 | digest_alg = TPM2_ALG_SHA1): | ||
454 | x = [] | ||
455 | f = get_hash_function(digest_alg) | ||
456 | |||
457 | for i in pcrs: | ||
458 | pcr = self.read_pcr(i, bank_alg) | ||
459 | if pcr == None: | ||
460 | return None | ||
461 | x += pcr | ||
462 | |||
463 | return f(bytearray(x)).digest() | ||
464 | |||
465 | def policy_pcr(self, handle, pcrs, bank_alg = TPM2_ALG_SHA1, | ||
466 | name_alg = TPM2_ALG_SHA1): | ||
467 | ds = get_digest_size(name_alg) | ||
468 | dig = self.__calc_pcr_digest(pcrs, bank_alg, name_alg) | ||
469 | if not dig: | ||
470 | raise UnknownPCRBankError(bank_alg) | ||
471 | |||
472 | pcrsel_len = max((max(pcrs) >> 3) + 1, 3) | ||
473 | pcrsel = [0] * pcrsel_len | ||
474 | for i in pcrs: | ||
475 | pcrsel[i >> 3] |= 1 << (i & 7) | ||
476 | pcrsel = ''.join(map(chr, pcrsel)) | ||
477 | |||
478 | fmt = '>HII IH%usIHB3s' % ds | ||
479 | cmd = struct.pack(fmt, | ||
480 | TPM2_ST_NO_SESSIONS, | ||
481 | struct.calcsize(fmt), | ||
482 | TPM2_CC_POLICY_PCR, | ||
483 | handle, | ||
484 | len(dig), str(dig), | ||
485 | 1, | ||
486 | bank_alg, | ||
487 | pcrsel_len, pcrsel) | ||
488 | |||
489 | self.send_cmd(cmd) | ||
490 | |||
491 | def policy_password(self, handle): | ||
492 | fmt = '>HII I' | ||
493 | cmd = struct.pack(fmt, | ||
494 | TPM2_ST_NO_SESSIONS, | ||
495 | struct.calcsize(fmt), | ||
496 | TPM2_CC_POLICY_PASSWORD, | ||
497 | handle) | ||
498 | |||
499 | self.send_cmd(cmd) | ||
500 | |||
501 | def get_policy_digest(self, handle): | ||
502 | fmt = '>HII I' | ||
503 | cmd = struct.pack(fmt, | ||
504 | TPM2_ST_NO_SESSIONS, | ||
505 | struct.calcsize(fmt), | ||
506 | TPM2_CC_POLICY_GET_DIGEST, | ||
507 | handle) | ||
508 | |||
509 | return self.send_cmd(cmd)[12:] | ||
510 | |||
511 | def flush_context(self, handle): | ||
512 | fmt = '>HIII' | ||
513 | cmd = struct.pack(fmt, | ||
514 | TPM2_ST_NO_SESSIONS, | ||
515 | struct.calcsize(fmt), | ||
516 | TPM2_CC_FLUSH_CONTEXT, | ||
517 | handle) | ||
518 | |||
519 | self.send_cmd(cmd) | ||
520 | |||
521 | def create_root_key(self, auth_value = ''): | ||
522 | attributes = \ | ||
523 | Public.FIXED_TPM | \ | ||
524 | Public.FIXED_PARENT | \ | ||
525 | Public.SENSITIVE_DATA_ORIGIN | \ | ||
526 | Public.USER_WITH_AUTH | \ | ||
527 | Public.RESTRICTED | \ | ||
528 | Public.DECRYPT | ||
529 | |||
530 | auth_cmd = AuthCommand() | ||
531 | sensitive = SensitiveCreate(user_auth=auth_value) | ||
532 | |||
533 | public_parms = struct.pack( | ||
534 | '>HHHHHI', | ||
535 | TPM2_ALG_AES, | ||
536 | 128, | ||
537 | TPM2_ALG_CFB, | ||
538 | TPM2_ALG_NULL, | ||
539 | 2048, | ||
540 | 0) | ||
541 | |||
542 | public = Public( | ||
543 | object_type=TPM2_ALG_RSA, | ||
544 | name_alg=TPM2_ALG_SHA1, | ||
545 | object_attributes=attributes, | ||
546 | parameters=public_parms) | ||
547 | |||
548 | fmt = '>HIII I%us H%us H%us HI' % \ | ||
549 | (len(auth_cmd), len(sensitive), len(public)) | ||
550 | cmd = struct.pack( | ||
551 | fmt, | ||
552 | TPM2_ST_SESSIONS, | ||
553 | struct.calcsize(fmt), | ||
554 | TPM2_CC_CREATE_PRIMARY, | ||
555 | TPM2_RH_OWNER, | ||
556 | len(auth_cmd), | ||
557 | str(auth_cmd), | ||
558 | len(sensitive), | ||
559 | str(sensitive), | ||
560 | len(public), | ||
561 | str(public), | ||
562 | 0, 0) | ||
563 | |||
564 | return struct.unpack('>I', self.send_cmd(cmd)[10:14])[0] | ||
565 | |||
566 | def seal(self, parent_key, data, auth_value, policy_dig, | ||
567 | name_alg = TPM2_ALG_SHA1): | ||
568 | ds = get_digest_size(name_alg) | ||
569 | assert(not policy_dig or ds == len(policy_dig)) | ||
570 | |||
571 | attributes = 0 | ||
572 | if not policy_dig: | ||
573 | attributes |= Public.USER_WITH_AUTH | ||
574 | policy_dig = '' | ||
575 | |||
576 | auth_cmd = AuthCommand() | ||
577 | sensitive = SensitiveCreate(user_auth=auth_value, data=data) | ||
578 | |||
579 | public = Public( | ||
580 | object_type=TPM2_ALG_KEYEDHASH, | ||
581 | name_alg=name_alg, | ||
582 | object_attributes=attributes, | ||
583 | auth_policy=policy_dig, | ||
584 | parameters=struct.pack('>H', TPM2_ALG_NULL)) | ||
585 | |||
586 | fmt = '>HIII I%us H%us H%us HI' % \ | ||
587 | (len(auth_cmd), len(sensitive), len(public)) | ||
588 | cmd = struct.pack( | ||
589 | fmt, | ||
590 | TPM2_ST_SESSIONS, | ||
591 | struct.calcsize(fmt), | ||
592 | TPM2_CC_CREATE, | ||
593 | parent_key, | ||
594 | len(auth_cmd), | ||
595 | str(auth_cmd), | ||
596 | len(sensitive), | ||
597 | str(sensitive), | ||
598 | len(public), | ||
599 | str(public), | ||
600 | 0, 0) | ||
601 | |||
602 | rsp = self.send_cmd(cmd) | ||
603 | |||
604 | return rsp[14:] | ||
605 | |||
606 | def unseal(self, parent_key, blob, auth_value, policy_handle): | ||
607 | private_len = struct.unpack('>H', blob[0:2])[0] | ||
608 | public_start = private_len + 2 | ||
609 | public_len = struct.unpack('>H', blob[public_start:public_start + 2])[0] | ||
610 | blob = blob[:private_len + public_len + 4] | ||
611 | |||
612 | auth_cmd = AuthCommand() | ||
613 | |||
614 | fmt = '>HII I I%us %us' % (len(auth_cmd), len(blob)) | ||
615 | cmd = struct.pack( | ||
616 | fmt, | ||
617 | TPM2_ST_SESSIONS, | ||
618 | struct.calcsize(fmt), | ||
619 | TPM2_CC_LOAD, | ||
620 | parent_key, | ||
621 | len(auth_cmd), | ||
622 | str(auth_cmd), | ||
623 | blob) | ||
624 | |||
625 | data_handle = struct.unpack('>I', self.send_cmd(cmd)[10:14])[0] | ||
626 | |||
627 | if policy_handle: | ||
628 | auth_cmd = AuthCommand(session_handle=policy_handle, hmac=auth_value) | ||
629 | else: | ||
630 | auth_cmd = AuthCommand(hmac=auth_value) | ||
631 | |||
632 | fmt = '>HII I I%us' % (len(auth_cmd)) | ||
633 | cmd = struct.pack( | ||
634 | fmt, | ||
635 | TPM2_ST_SESSIONS, | ||
636 | struct.calcsize(fmt), | ||
637 | TPM2_CC_UNSEAL, | ||
638 | data_handle, | ||
639 | len(auth_cmd), | ||
640 | str(auth_cmd)) | ||
641 | |||
642 | try: | ||
643 | rsp = self.send_cmd(cmd) | ||
644 | finally: | ||
645 | self.flush_context(data_handle) | ||
646 | |||
647 | data_len = struct.unpack('>I', rsp[10:14])[0] - 2 | ||
648 | |||
649 | return rsp[16:16 + data_len] | ||
650 | |||
651 | def reset_da_lock(self): | ||
652 | auth_cmd = AuthCommand() | ||
653 | |||
654 | fmt = '>HII I I%us' % (len(auth_cmd)) | ||
655 | cmd = struct.pack( | ||
656 | fmt, | ||
657 | TPM2_ST_SESSIONS, | ||
658 | struct.calcsize(fmt), | ||
659 | TPM2_CC_DICTIONARY_ATTACK_LOCK_RESET, | ||
660 | TPM2_RH_LOCKOUT, | ||
661 | len(auth_cmd), | ||
662 | str(auth_cmd)) | ||
663 | |||
664 | self.send_cmd(cmd) | ||
665 | |||
666 | def __get_cap_cnt(self, cap, pt, cnt): | ||
667 | handles = [] | ||
668 | fmt = '>HII III' | ||
669 | |||
670 | cmd = struct.pack(fmt, | ||
671 | TPM2_ST_NO_SESSIONS, | ||
672 | struct.calcsize(fmt), | ||
673 | TPM2_CC_GET_CAPABILITY, | ||
674 | cap, pt, cnt) | ||
675 | |||
676 | rsp = self.send_cmd(cmd)[10:] | ||
677 | more_data, cap, cnt = struct.unpack('>BII', rsp[:9]) | ||
678 | rsp = rsp[9:] | ||
679 | |||
680 | for i in xrange(0, cnt): | ||
681 | handle = struct.unpack('>I', rsp[:4])[0] | ||
682 | handles.append(handle) | ||
683 | rsp = rsp[4:] | ||
684 | |||
685 | return handles, more_data | ||
686 | |||
687 | def get_cap(self, cap, pt): | ||
688 | handles = [] | ||
689 | |||
690 | more_data = True | ||
691 | while more_data: | ||
692 | next_handles, more_data = self.__get_cap_cnt(cap, pt, 1) | ||
693 | handles += next_handles | ||
694 | pt += 1 | ||
695 | |||
696 | return handles | ||
diff --git a/tools/testing/selftests/tpm2/tpm2_tests.py b/tools/testing/selftests/tpm2/tpm2_tests.py new file mode 100644 index 000000000000..3bb066fea4a0 --- /dev/null +++ b/tools/testing/selftests/tpm2/tpm2_tests.py | |||
@@ -0,0 +1,227 @@ | |||
1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) | ||
2 | |||
3 | from argparse import ArgumentParser | ||
4 | from argparse import FileType | ||
5 | import os | ||
6 | import sys | ||
7 | import tpm2 | ||
8 | from tpm2 import ProtocolError | ||
9 | import unittest | ||
10 | import logging | ||
11 | import struct | ||
12 | |||
13 | class SmokeTest(unittest.TestCase): | ||
14 | def setUp(self): | ||
15 | self.client = tpm2.Client() | ||
16 | self.root_key = self.client.create_root_key() | ||
17 | |||
18 | def tearDown(self): | ||
19 | self.client.flush_context(self.root_key) | ||
20 | self.client.close() | ||
21 | |||
22 | def test_seal_with_auth(self): | ||
23 | data = 'X' * 64 | ||
24 | auth = 'A' * 15 | ||
25 | |||
26 | blob = self.client.seal(self.root_key, data, auth, None) | ||
27 | result = self.client.unseal(self.root_key, blob, auth, None) | ||
28 | self.assertEqual(data, result) | ||
29 | |||
30 | def test_seal_with_policy(self): | ||
31 | handle = self.client.start_auth_session(tpm2.TPM2_SE_TRIAL) | ||
32 | |||
33 | data = 'X' * 64 | ||
34 | auth = 'A' * 15 | ||
35 | pcrs = [16] | ||
36 | |||
37 | try: | ||
38 | self.client.policy_pcr(handle, pcrs) | ||
39 | self.client.policy_password(handle) | ||
40 | |||
41 | policy_dig = self.client.get_policy_digest(handle) | ||
42 | finally: | ||
43 | self.client.flush_context(handle) | ||
44 | |||
45 | blob = self.client.seal(self.root_key, data, auth, policy_dig) | ||
46 | |||
47 | handle = self.client.start_auth_session(tpm2.TPM2_SE_POLICY) | ||
48 | |||
49 | try: | ||
50 | self.client.policy_pcr(handle, pcrs) | ||
51 | self.client.policy_password(handle) | ||
52 | |||
53 | result = self.client.unseal(self.root_key, blob, auth, handle) | ||
54 | except: | ||
55 | self.client.flush_context(handle) | ||
56 | raise | ||
57 | |||
58 | self.assertEqual(data, result) | ||
59 | |||
60 | def test_unseal_with_wrong_auth(self): | ||
61 | data = 'X' * 64 | ||
62 | auth = 'A' * 20 | ||
63 | rc = 0 | ||
64 | |||
65 | blob = self.client.seal(self.root_key, data, auth, None) | ||
66 | try: | ||
67 | result = self.client.unseal(self.root_key, blob, auth[:-1] + 'B', None) | ||
68 | except ProtocolError, e: | ||
69 | rc = e.rc | ||
70 | |||
71 | self.assertEqual(rc, tpm2.TPM2_RC_AUTH_FAIL) | ||
72 | |||
73 | def test_unseal_with_wrong_policy(self): | ||
74 | handle = self.client.start_auth_session(tpm2.TPM2_SE_TRIAL) | ||
75 | |||
76 | data = 'X' * 64 | ||
77 | auth = 'A' * 17 | ||
78 | pcrs = [16] | ||
79 | |||
80 | try: | ||
81 | self.client.policy_pcr(handle, pcrs) | ||
82 | self.client.policy_password(handle) | ||
83 | |||
84 | policy_dig = self.client.get_policy_digest(handle) | ||
85 | finally: | ||
86 | self.client.flush_context(handle) | ||
87 | |||
88 | blob = self.client.seal(self.root_key, data, auth, policy_dig) | ||
89 | |||
90 | # Extend first a PCR that is not part of the policy and try to unseal. | ||
91 | # This should succeed. | ||
92 | |||
93 | ds = tpm2.get_digest_size(tpm2.TPM2_ALG_SHA1) | ||
94 | self.client.extend_pcr(1, 'X' * ds) | ||
95 | |||
96 | handle = self.client.start_auth_session(tpm2.TPM2_SE_POLICY) | ||
97 | |||
98 | try: | ||
99 | self.client.policy_pcr(handle, pcrs) | ||
100 | self.client.policy_password(handle) | ||
101 | |||
102 | result = self.client.unseal(self.root_key, blob, auth, handle) | ||
103 | except: | ||
104 | self.client.flush_context(handle) | ||
105 | raise | ||
106 | |||
107 | self.assertEqual(data, result) | ||
108 | |||
109 | # Then, extend a PCR that is part of the policy and try to unseal. | ||
110 | # This should fail. | ||
111 | self.client.extend_pcr(16, 'X' * ds) | ||
112 | |||
113 | handle = self.client.start_auth_session(tpm2.TPM2_SE_POLICY) | ||
114 | |||
115 | rc = 0 | ||
116 | |||
117 | try: | ||
118 | self.client.policy_pcr(handle, pcrs) | ||
119 | self.client.policy_password(handle) | ||
120 | |||
121 | result = self.client.unseal(self.root_key, blob, auth, handle) | ||
122 | except ProtocolError, e: | ||
123 | rc = e.rc | ||
124 | self.client.flush_context(handle) | ||
125 | except: | ||
126 | self.client.flush_context(handle) | ||
127 | raise | ||
128 | |||
129 | self.assertEqual(rc, tpm2.TPM2_RC_POLICY_FAIL) | ||
130 | |||
131 | def test_seal_with_too_long_auth(self): | ||
132 | ds = tpm2.get_digest_size(tpm2.TPM2_ALG_SHA1) | ||
133 | data = 'X' * 64 | ||
134 | auth = 'A' * (ds + 1) | ||
135 | |||
136 | rc = 0 | ||
137 | try: | ||
138 | blob = self.client.seal(self.root_key, data, auth, None) | ||
139 | except ProtocolError, e: | ||
140 | rc = e.rc | ||
141 | |||
142 | self.assertEqual(rc, tpm2.TPM2_RC_SIZE) | ||
143 | |||
144 | def test_too_short_cmd(self): | ||
145 | rejected = False | ||
146 | try: | ||
147 | fmt = '>HIII' | ||
148 | cmd = struct.pack(fmt, | ||
149 | tpm2.TPM2_ST_NO_SESSIONS, | ||
150 | struct.calcsize(fmt) + 1, | ||
151 | tpm2.TPM2_CC_FLUSH_CONTEXT, | ||
152 | 0xDEADBEEF) | ||
153 | |||
154 | self.client.send_cmd(cmd) | ||
155 | except IOError, e: | ||
156 | rejected = True | ||
157 | except: | ||
158 | pass | ||
159 | self.assertEqual(rejected, True) | ||
160 | |||
161 | class SpaceTest(unittest.TestCase): | ||
162 | def setUp(self): | ||
163 | logging.basicConfig(filename='SpaceTest.log', level=logging.DEBUG) | ||
164 | |||
165 | def test_make_two_spaces(self): | ||
166 | log = logging.getLogger(__name__) | ||
167 | log.debug("test_make_two_spaces") | ||
168 | |||
169 | space1 = tpm2.Client(tpm2.Client.FLAG_SPACE) | ||
170 | root1 = space1.create_root_key() | ||
171 | space2 = tpm2.Client(tpm2.Client.FLAG_SPACE) | ||
172 | root2 = space2.create_root_key() | ||
173 | root3 = space2.create_root_key() | ||
174 | |||
175 | log.debug("%08x" % (root1)) | ||
176 | log.debug("%08x" % (root2)) | ||
177 | log.debug("%08x" % (root3)) | ||
178 | |||
179 | def test_flush_context(self): | ||
180 | log = logging.getLogger(__name__) | ||
181 | log.debug("test_flush_context") | ||
182 | |||
183 | space1 = tpm2.Client(tpm2.Client.FLAG_SPACE) | ||
184 | root1 = space1.create_root_key() | ||
185 | log.debug("%08x" % (root1)) | ||
186 | |||
187 | space1.flush_context(root1) | ||
188 | |||
189 | def test_get_handles(self): | ||
190 | log = logging.getLogger(__name__) | ||
191 | log.debug("test_get_handles") | ||
192 | |||
193 | space1 = tpm2.Client(tpm2.Client.FLAG_SPACE) | ||
194 | space1.create_root_key() | ||
195 | space2 = tpm2.Client(tpm2.Client.FLAG_SPACE) | ||
196 | space2.create_root_key() | ||
197 | space2.create_root_key() | ||
198 | |||
199 | handles = space2.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_TRANSIENT) | ||
200 | |||
201 | self.assertEqual(len(handles), 2) | ||
202 | |||
203 | log.debug("%08x" % (handles[0])) | ||
204 | log.debug("%08x" % (handles[1])) | ||
205 | |||
206 | def test_invalid_cc(self): | ||
207 | log = logging.getLogger(__name__) | ||
208 | log.debug(sys._getframe().f_code.co_name) | ||
209 | |||
210 | TPM2_CC_INVALID = tpm2.TPM2_CC_FIRST - 1 | ||
211 | |||
212 | space1 = tpm2.Client(tpm2.Client.FLAG_SPACE) | ||
213 | root1 = space1.create_root_key() | ||
214 | log.debug("%08x" % (root1)) | ||
215 | |||
216 | fmt = '>HII' | ||
217 | cmd = struct.pack(fmt, tpm2.TPM2_ST_NO_SESSIONS, struct.calcsize(fmt), | ||
218 | TPM2_CC_INVALID) | ||
219 | |||
220 | rc = 0 | ||
221 | try: | ||
222 | space1.send_cmd(cmd) | ||
223 | except ProtocolError, e: | ||
224 | rc = e.rc | ||
225 | |||
226 | self.assertEqual(rc, tpm2.TPM2_RC_COMMAND_CODE | | ||
227 | tpm2.TSS2_RESMGR_TPM_RC_LAYER) | ||