- Update to aed51c7 commit - Require keylime-base on Fedora >= 36 - Update clap dependency - Drop rustc-serialize and flate2 dependencies - Make wiremock an optional dependency and re-enable tests - Fix serialization of structures in quotes to fix issue on big-endian - Add systemd services for the agent and secure mount - BuildRequire systemd for the services - Use more descriptive error messages on missing files errors - Set supplementary groups when dropping privileges - Create /usr/libexec/keylime directory Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
218 lines
7.8 KiB
Diff
218 lines
7.8 KiB
Diff
From 423f7337d991ec5085914a361e68260bdd513ac6 Mon Sep 17 00:00:00 2001
|
|
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
|
Date: Mon, 20 Jun 2022 11:51:46 +0200
|
|
Subject: [PATCH] tpm: Add serialization functions for structures in quotes
|
|
|
|
Add serialization and deserialization functions for the data in quotes
|
|
to avoid endianness issues when the arch is big-endian.
|
|
|
|
The added serialization and deserialization functions will convert the
|
|
data endianness as necessary.
|
|
|
|
Note: the official marshalling and unmarshalling functions cannot be
|
|
used directly because the tpm2-tools uses a custom format.
|
|
|
|
Fixes: #407
|
|
|
|
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
|
---
|
|
src/tpm.rs | 139 +++++++++++++++++++++++++++++++++++++++++------------
|
|
1 file changed, 107 insertions(+), 32 deletions(-)
|
|
|
|
diff --git a/src/tpm.rs b/src/tpm.rs
|
|
index 9002c29..5521892 100644
|
|
--- a/src/tpm.rs
|
|
+++ b/src/tpm.rs
|
|
@@ -52,15 +52,20 @@ use tss_esapi::{
|
|
tss2_esys::{
|
|
Tss2_MU_TPM2B_PUBLIC_Marshal, Tss2_MU_TPMS_ATTEST_Marshal,
|
|
Tss2_MU_TPMS_ATTEST_Unmarshal, Tss2_MU_TPMT_SIGNATURE_Marshal,
|
|
- TPM2B_ATTEST, TPM2B_PUBLIC, TPML_DIGEST, TPML_PCR_SELECTION,
|
|
- TPMS_ATTEST, TPMS_SCHEME_HASH, TPMT_SIGNATURE, TPMT_SIG_SCHEME,
|
|
- TPMU_SIG_SCHEME,
|
|
+ TPM2B_ATTEST, TPM2B_DIGEST, TPM2B_PUBLIC, TPML_DIGEST,
|
|
+ TPML_PCR_SELECTION, TPMS_ATTEST, TPMS_PCR_SELECTION,
|
|
+ TPMS_SCHEME_HASH, TPMT_SIGNATURE, TPMT_SIG_SCHEME, TPMU_SIG_SCHEME,
|
|
},
|
|
utils::TpmsContext,
|
|
Context,
|
|
};
|
|
|
|
pub const MAX_NONCE_SIZE: usize = 64;
|
|
+pub const TPML_DIGEST_SIZE: usize = std::mem::size_of::<TPML_DIGEST>();
|
|
+pub const TPML_PCR_SELECTION_SIZE: usize =
|
|
+ std::mem::size_of::<TPML_PCR_SELECTION>();
|
|
+pub const TPMS_PCR_SELECTION_SIZE: usize =
|
|
+ std::mem::size_of::<TPMS_PCR_SELECTION>();
|
|
|
|
/*
|
|
* Input: None
|
|
@@ -123,6 +128,95 @@ pub(crate) fn create_ek(
|
|
assert_eq_size!(TPML_PCR_SELECTION, [u8; 132]);
|
|
assert_eq_size!(TPML_DIGEST, [u8; 532]);
|
|
|
|
+// Serialize a TPML_PCR_SELECTION into a Vec<u8>
|
|
+// The serialization will adjust the data endianness as necessary and add paddings to keep the
|
|
+// memory aligment.
|
|
+pub(crate) fn serialize_pcrsel(
|
|
+ pcr_selection: &TPML_PCR_SELECTION,
|
|
+) -> Vec<u8> {
|
|
+ let mut output = Vec::with_capacity(TPML_PCR_SELECTION_SIZE);
|
|
+ output.extend(u32::to_le_bytes(pcr_selection.count));
|
|
+ for selection in pcr_selection.pcrSelections.iter() {
|
|
+ output.extend(selection.hash.to_le_bytes());
|
|
+ output.extend(selection.sizeofSelect.to_le_bytes());
|
|
+ output.extend(selection.pcrSelect);
|
|
+ output.extend([0u8; 1]); // padding to keep the memory alignment
|
|
+ }
|
|
+ output
|
|
+}
|
|
+
|
|
+// Deserialize a TPML_PCR_SELECTION from a &[u8] slice.
|
|
+// The deserialization will adjust the data endianness as necessary.
|
|
+pub(crate) fn deserialize_pcrsel(
|
|
+ pcrsel_vec: &[u8],
|
|
+) -> Result<TPML_PCR_SELECTION> {
|
|
+ if pcrsel_vec.len() != TPML_PCR_SELECTION_SIZE {
|
|
+ return Err(KeylimeError::InvalidRequest);
|
|
+ }
|
|
+
|
|
+ let mut reader = std::io::Cursor::new(pcrsel_vec);
|
|
+ let mut count_vec = [0u8; 4];
|
|
+ reader.read_exact(&mut count_vec)?;
|
|
+ let count = u32::from_le_bytes(count_vec);
|
|
+
|
|
+ let mut pcr_selections: [TPMS_PCR_SELECTION; 16] =
|
|
+ [TPMS_PCR_SELECTION::default(); 16];
|
|
+
|
|
+ for selection in &mut pcr_selections {
|
|
+ let mut hash_vec = [0u8; 2];
|
|
+ reader.read_exact(&mut hash_vec)?;
|
|
+ selection.hash = u16::from_le_bytes(hash_vec);
|
|
+
|
|
+ let mut size_vec = [0u8; 1];
|
|
+ reader.read_exact(&mut size_vec)?;
|
|
+ selection.sizeofSelect = u8::from_le_bytes(size_vec);
|
|
+
|
|
+ reader.read_exact(&mut selection.pcrSelect)?;
|
|
+ }
|
|
+
|
|
+ Ok(TPML_PCR_SELECTION {
|
|
+ count,
|
|
+ pcrSelections: pcr_selections,
|
|
+ })
|
|
+}
|
|
+
|
|
+// Serialize a TPML_DIGEST into a Vec<u8>
|
|
+// The serialization will adjust the data endianness as necessary.
|
|
+pub(crate) fn serialize_digest(digest_list: &TPML_DIGEST) -> Vec<u8> {
|
|
+ let mut output = Vec::with_capacity(TPML_DIGEST_SIZE);
|
|
+ output.extend(u32::to_le_bytes(digest_list.count));
|
|
+ for digest in digest_list.digests.iter() {
|
|
+ output.extend(digest.size.to_le_bytes());
|
|
+ output.extend(digest.buffer);
|
|
+ }
|
|
+ output
|
|
+}
|
|
+
|
|
+// Deserialize a TPML_DIGEST from a &[u8] slice.
|
|
+// The deserialization will adjust the data endianness as necessary.
|
|
+pub(crate) fn deserialize_digest(digest_vec: &[u8]) -> Result<TPML_DIGEST> {
|
|
+ if digest_vec.len() != TPML_DIGEST_SIZE {
|
|
+ return Err(KeylimeError::InvalidRequest);
|
|
+ }
|
|
+
|
|
+ let mut reader = std::io::Cursor::new(digest_vec);
|
|
+ let mut count_vec = [0u8; 4];
|
|
+
|
|
+ reader.read_exact(&mut count_vec)?;
|
|
+ let count = u32::from_le_bytes(count_vec);
|
|
+
|
|
+ let mut digests: [TPM2B_DIGEST; 8] = [TPM2B_DIGEST::default(); 8];
|
|
+
|
|
+ for digest in &mut digests {
|
|
+ let mut size_vec = [0u8; 2];
|
|
+ reader.read_exact(&mut size_vec)?;
|
|
+ digest.size = u16::from_le_bytes(size_vec);
|
|
+ reader.read_exact(&mut digest.buffer)?;
|
|
+ }
|
|
+
|
|
+ Ok(TPML_DIGEST { count, digests })
|
|
+}
|
|
+
|
|
// Recreate how tpm2-tools creates the PCR out file. Roughly, this is a
|
|
// TPML_PCR_SELECTION + number of TPML_DIGESTS + TPML_DIGESTs.
|
|
// Reference:
|
|
@@ -140,16 +234,14 @@ pub(crate) fn pcrdata_to_vec(
|
|
const DIGEST_SIZE: usize = std::mem::size_of::<TPML_DIGEST>();
|
|
|
|
let mut pcrsel: TPML_PCR_SELECTION = selection_list.into();
|
|
- pcrsel.count = pcrsel.count.to_le();
|
|
- let pcrsel_vec: [u8; PCRSEL_SIZE] =
|
|
- unsafe { std::mem::transmute(pcrsel) };
|
|
+ let pcrsel_vec = serialize_pcrsel(&pcrsel);
|
|
|
|
let digest: Vec<TPML_DIGEST> = pcrdata.into();
|
|
let num_tpml_digests = digest.len() as u32;
|
|
let mut digest_vec = Vec::with_capacity(digest.len() * DIGEST_SIZE);
|
|
|
|
for d in digest {
|
|
- let vec: [u8; DIGEST_SIZE] = unsafe { std::mem::transmute(d) };
|
|
+ let vec = serialize_digest(&d);
|
|
digest_vec.extend(vec);
|
|
}
|
|
|
|
@@ -665,41 +757,24 @@ pub mod testing {
|
|
);
|
|
|
|
fn vec_to_pcrdata(val: &[u8]) -> Result<(PcrSelectionList, PcrData)> {
|
|
- const PCRSEL_SIZE: usize = std::mem::size_of::<TPML_PCR_SELECTION>();
|
|
- const DIGEST_SIZE: usize = std::mem::size_of::<TPML_DIGEST>();
|
|
-
|
|
let mut reader = std::io::Cursor::new(val);
|
|
- let mut pcrsel_vec = [0u8; PCRSEL_SIZE];
|
|
- let len = reader.read(&mut pcrsel_vec)?;
|
|
- if len != pcrsel_vec.len() {
|
|
- return Err(KeylimeError::InvalidRequest);
|
|
- }
|
|
- let mut pcrsel = unsafe {
|
|
- std::mem::transmute::<[u8; PCRSEL_SIZE], TPML_PCR_SELECTION>(
|
|
- pcrsel_vec,
|
|
- )
|
|
- };
|
|
+ let mut pcrsel_vec = [0u8; TPML_PCR_SELECTION_SIZE];
|
|
+ reader.read_exact(&mut pcrsel_vec)?;
|
|
+
|
|
+ let pcrsel = deserialize_pcrsel(&pcrsel_vec)?;
|
|
let pcrlist: PcrSelectionList = pcrsel.try_into()?;
|
|
|
|
let mut count_vec = [0u8; 4];
|
|
- let len = reader.read(&mut count_vec)?;
|
|
- if len < count_vec.len() {
|
|
- return Err(KeylimeError::InvalidRequest);
|
|
- }
|
|
+ reader.read_exact(&mut count_vec)?;
|
|
let count = u32::from_le_bytes(count_vec);
|
|
// Always 1 PCR digest should follow
|
|
if count != 1 {
|
|
return Err(KeylimeError::InvalidRequest);
|
|
}
|
|
|
|
- let mut digest_vec = [0u8; DIGEST_SIZE];
|
|
- let len = reader.read(&mut digest_vec)?;
|
|
- if len != digest_vec.len() {
|
|
- return Err(KeylimeError::InvalidRequest);
|
|
- }
|
|
- let mut digest = unsafe {
|
|
- std::mem::transmute::<[u8; DIGEST_SIZE], TPML_DIGEST>(digest_vec)
|
|
- };
|
|
+ let mut digest_vec = [0u8; TPML_DIGEST_SIZE];
|
|
+ reader.read_exact(&mut digest_vec)?;
|
|
+ let digest = deserialize_digest(&digest_vec)?;
|
|
let mut digest_list = DigestList::new();
|
|
for i in 0..digest.count {
|
|
digest_list.add(digest.digests[i as usize].try_into()?);
|
|
--
|
|
2.35.3
|
|
|