Skip to content

Commit 91aa6b8

Browse files
tpm: Add v2 Tcg method for submitting raw TPM commands
1 parent 82011f8 commit 91aa6b8

File tree

2 files changed

+92
-1
lines changed
  • uefi/src/proto/tcg
  • uefi-test-runner/src/proto

2 files changed

+92
-1
lines changed

uefi-test-runner/src/proto/tcg.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,63 @@ fn test_tcg_v1(bt: &BootServices) {
157157
assert_eq!(event_last, event);
158158
}
159159

160+
/// Get the SHA-1 digest stored in the given PCR index.
161+
fn tcg_v2_read_pcr_8(tcg: &mut v2::Tcg) -> v1::Sha1Digest {
162+
// Input command block.
163+
#[rustfmt::skip]
164+
let input = [
165+
// tag: TPM_ST_NO_SESSIONS
166+
0x80, 0x01,
167+
// commandSize
168+
0x00, 0x00, 0x00, 0x14,
169+
// commandCode: TPM_CC_PCR_Read
170+
0x00, 0x00, 0x01, 0x7e,
171+
172+
// pcrSelectionIn.count: 1
173+
0x00, 0x00, 0x00, 0x01,
174+
// pcrSelectionIn.pcrSelections[0].hash: SHA-1
175+
0x00, 0x04,
176+
// pcrSelectionIn.pcrSelections[0].sizeofSelect: 3 bytes
177+
0x03,
178+
// pcrSelectionIn.pcrSelections[0].pcrSelect: bitmask array
179+
// PCR 0-7: don't select
180+
0x00,
181+
// PCR 8-15: select only PCR 8
182+
0x01,
183+
// PCR 16-23: don't select
184+
0x00,
185+
];
186+
187+
let mut output = [0; 50];
188+
tcg.submit_command(&input, &mut output)
189+
.expect("failed to get PCR value");
190+
191+
// tag: TPM_ST_NO_SESSIONS
192+
assert_eq!(output[0..2], [0x80, 0x01]);
193+
// responseSize
194+
assert_eq!(output[2..6], [0x00, 0x00, 0x00, 0x32]);
195+
// responseCode: TPM_RC_SUCCESS
196+
assert_eq!(output[6..10], [0x00, 0x00, 0x00, 0x00]);
197+
// Bytes 10..14 are the TPM update counter, ignore.
198+
199+
// pcrSelectionIn.count: 1
200+
assert_eq!(output[14..18], [0x00, 0x00, 0x00, 0x01]);
201+
// pcrSelectionIn.pcrSelections[0].hash: SHA-1
202+
assert_eq!(output[18..20], [0x00, 0x04]);
203+
// pcrSelectionIn.pcrSelections[0].sizeofSelect: 3 bytes
204+
assert_eq!(output[20], 0x03);
205+
// pcrSelectionIn.pcrSelections[0].pcrSelect: bitmap selecting PCR 8
206+
assert_eq!(output[21..24], [0x00, 0x01, 0x00]);
207+
208+
// pcrValues.count: 1
209+
assert_eq!(output[24..28], [0x00, 0x00, 0x00, 0x01]);
210+
// pcrValues.digests[0].size: 20 bytes
211+
assert_eq!(output[28..30], [0x00, 0x14]);
212+
213+
// The rest of the output is the SHA-1 digest.
214+
output[30..].try_into().unwrap()
215+
}
216+
160217
pub fn test_tcg_v2(bt: &BootServices) {
161218
info!("Running TCG v2 test");
162219

@@ -216,6 +273,9 @@ pub fn test_tcg_v2(bt: &BootServices) {
216273
.get_result_of_set_active_pcr_banks()
217274
.expect("get_result_of_set_active_pcr_banks failed")
218275
.is_none());
276+
277+
// PCR 8 is initially zero.
278+
assert_eq!(tcg_v2_read_pcr_8(&mut tcg), [0; 20]);
219279
}
220280

221281
pub fn test(bt: &BootServices) {

uefi/src/proto/tcg/v2.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use super::HashAlgorithm;
1414
use crate::data_types::PhysicalAddress;
1515
use crate::proto::unsafe_protocol;
16-
use crate::{Result, Status};
16+
use crate::{Error, Result, Status};
1717
use bitflags::bitflags;
1818
use core::mem;
1919

@@ -191,6 +191,37 @@ impl Tcg {
191191
unsafe { (self.get_capability)(self, &mut capability).into_with_val(|| capability) }
192192
}
193193

194+
/// Send a command directly to the TPM.
195+
///
196+
/// Constructing the input block and parsing the output block are outside
197+
/// the scope of this crate. See the [TPM 2.0 Specification][spec], in
198+
/// particular Part 2 (Structures) and Part 3 (Commands).
199+
///
200+
/// Note that TPM structures are big endian.
201+
///
202+
/// [spec]: https://trustedcomputinggroup.org/resource/tpm-library-specification/
203+
pub fn submit_command(
204+
&mut self,
205+
input_parameter_block: &[u8],
206+
output_parameter_block: &mut [u8],
207+
) -> Result {
208+
let input_parameter_block_len = u32::try_from(input_parameter_block.len())
209+
.map_err(|_| Error::from(Status::BAD_BUFFER_SIZE))?;
210+
let output_parameter_block_len = u32::try_from(output_parameter_block.len())
211+
.map_err(|_| Error::from(Status::BAD_BUFFER_SIZE))?;
212+
213+
unsafe {
214+
(self.submit_command)(
215+
self,
216+
input_parameter_block_len,
217+
input_parameter_block.as_ptr(),
218+
output_parameter_block_len,
219+
output_parameter_block.as_mut_ptr(),
220+
)
221+
.into()
222+
}
223+
}
224+
194225
/// Get a bitmap of the active PCR banks. Each bank corresponds to a hash
195226
/// algorithm.
196227
pub fn get_active_pcr_banks(&mut self) -> Result<HashAlgorithm> {

0 commit comments

Comments
 (0)