From 64d00ca2fbcae21dd6c58299d2b8e5903d67b14d Mon Sep 17 00:00:00 2001 From: Sergio Arroutbi <sarroutb@redhat.com> Date: Fri, 11 Aug 2023 16:23:42 +0200 Subject: [PATCH] Use cpu_endian to check local endianness Resolves: #283 Signed-off-by: Sergio Arroutbi <sarroutb@redhat.com> --- Cargo.lock | 10 ++++++++++ keylime/Cargo.toml | 1 + keylime/src/endian.rs | 29 +++++++++++++++++++++++++++++ keylime/src/ima/entry.rs | 22 ++++++++++++++++------ keylime/src/lib.rs | 1 + keylime/src/tpm.rs | 13 +++++++------ 6 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 keylime/src/endian.rs diff --git a/Cargo.lock b/Cargo.lock index b91be43c..7a137109 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -538,6 +538,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "cpu-endian" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512746971686a86c7b8aee38244eaa7e04696e612790d593f1d73059536beee8" +dependencies = [ + "cc", +] + [[package]] name = "cpufeatures" version = "0.2.5" @@ -1097,6 +1106,7 @@ name = "keylime" version = "0.2.2" dependencies = [ "base64 0.21.0", + "cpu-endian", "hex", "log", "openssl", diff --git a/keylime/Cargo.toml b/keylime/Cargo.toml index 61ad8b72..e1ac5b85 100644 --- a/keylime/Cargo.toml +++ b/keylime/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] base64 = "0.21" +cpu-endian = "0.1.1" hex = "0.4" log = "0.4" openssl = "0.10.15" diff --git a/keylime/src/endian.rs b/keylime/src/endian.rs new file mode 100644 index 00000000..0dc92476 --- /dev/null +++ b/keylime/src/endian.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Keylime Authors + +use cpu_endian; + +// TODO: templatize +pub fn local_endianness_32(input: u32) -> [u8; 4] { + match cpu_endian::working() { + cpu_endian::Endian::Little => input.to_le_bytes(), + cpu_endian::Endian::Big => input.to_be_bytes(), + _ => input.to_le_bytes(), + } +} + +pub fn local_endianness_16(input: u16) -> [u8; 2] { + match cpu_endian::working() { + cpu_endian::Endian::Little => input.to_le_bytes(), + cpu_endian::Endian::Big => input.to_be_bytes(), + _ => input.to_le_bytes(), + } +} + +pub fn local_endianness_8(input: u8) -> [u8; 1] { + match cpu_endian::working() { + cpu_endian::Endian::Little => input.to_le_bytes(), + cpu_endian::Endian::Big => input.to_be_bytes(), + _ => input.to_le_bytes(), + } +} diff --git a/keylime/src/ima/entry.rs b/keylime/src/ima/entry.rs index 1168b3c8..1b438cdc 100644 --- a/keylime/src/ima/entry.rs +++ b/keylime/src/ima/entry.rs @@ -8,6 +8,7 @@ // https://www.kernel.org/doc/html/v5.12/security/IMA-templates.html use crate::algorithms::HashAlgorithm; +use crate::endian; use openssl::hash::MessageDigest; use std::convert::{TryFrom, TryInto}; use std::io::{Error, ErrorKind, Result, Write}; @@ -107,12 +108,15 @@ impl TryFrom<&str> for Digest { impl Encode for Digest { fn encode(&self, writer: &mut dyn Write) -> Result<()> { if self.algorithm == HashAlgorithm::Sha1 { - writer.write_all(&(self.value.len() as u32).to_le_bytes())?; + writer.write_all(&endian::local_endianness_32( + self.value.len() as u32, + ))?; writer.write_all(&self.value)?; } else { let algorithm = format!("{}", self.algorithm); let total_len = algorithm.len() + 2 + self.value.len(); - writer.write_all(&(total_len as u32).to_le_bytes())?; + writer + .write_all(&endian::local_endianness_32(total_len as u32))?; writer.write_all(algorithm.as_bytes())?; writer.write_all(&[58u8, 0u8])?; writer.write_all(&self.value)?; @@ -147,7 +151,9 @@ const TCG_EVENT_NAME_LEN_MAX: usize = 255; impl Encode for Name { fn encode(&self, writer: &mut dyn Write) -> Result<()> { let bytes = self.name.as_bytes(); - writer.write_all(&((bytes.len() + 1) as u32).to_le_bytes())?; + writer.write_all(&endian::local_endianness_32( + (bytes.len() + 1) as u32, + ))?; writer.write_all(bytes)?; writer.write_all(&[0u8])?; // NUL Ok(()) @@ -194,7 +200,9 @@ impl TryFrom<&str> for Signature { impl Encode for Signature { fn encode(&self, writer: &mut dyn Write) -> Result<()> { - writer.write_all(&(self.value.len() as u32).to_le_bytes())?; + writer.write_all(&endian::local_endianness_32( + self.value.len() as u32 + ))?; writer.write_all(&self.value)?; Ok(()) } @@ -218,7 +226,9 @@ impl TryFrom<&str> for Buffer { impl Encode for Buffer { fn encode(&self, writer: &mut dyn Write) -> Result<()> { - writer.write_all(&(self.value.len() as u32).to_le_bytes())?; + writer.write_all(&endian::local_endianness_32( + self.value.len() as u32 + ))?; writer.write_all(&self.value)?; Ok(()) } @@ -347,7 +357,7 @@ impl Encode for ImaSig { if let Some(signature) = &self.signature { signature.encode(writer)?; } else { - writer.write_all(&0u32.to_le_bytes())?; + writer.write_all(&endian::local_endianness_32(0u32))?; } Ok(()) } diff --git a/keylime/src/lib.rs b/keylime/src/lib.rs index b5374ae6..bda0e1d9 100644 --- a/keylime/src/lib.rs +++ b/keylime/src/lib.rs @@ -1,4 +1,5 @@ pub mod algorithms; +pub mod endian; pub mod ima; pub mod list_parser; pub mod tpm; diff --git a/keylime/src/tpm.rs b/keylime/src/tpm.rs index 4b83e1fa..274f049c 100644 --- a/keylime/src/tpm.rs +++ b/keylime/src/tpm.rs @@ -2,6 +2,7 @@ // Copyright 2021 Keylime Authors use crate::algorithms::{EncryptionAlgorithm, HashAlgorithm, SignAlgorithm}; +use crate::endian; use base64::{engine::general_purpose, Engine as _}; use log::*; use std::convert::{TryFrom, TryInto}; @@ -357,10 +358,10 @@ assert_eq_size!(TPML_DIGEST, [u8; 532]); // memory aligment. 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)); + output.extend(endian::local_endianness_32(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(endian::local_endianness_16(selection.hash)); + output.extend(endian::local_endianness_8(selection.sizeofSelect)); output.extend(selection.pcrSelect); output.extend([0u8; 1]); // padding to keep the memory alignment } @@ -371,9 +372,9 @@ fn serialize_pcrsel(pcr_selection: &TPML_PCR_SELECTION) -> Vec<u8> { // The serialization will adjust the data endianness as necessary. 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)); + output.extend(endian::local_endianness_32(digest_list.count)); for digest in digest_list.digests.iter() { - output.extend(digest.size.to_le_bytes()); + output.extend(endian::local_endianness_16(digest.size)); output.extend(digest.buffer); } output @@ -410,7 +411,7 @@ fn pcrdata_to_vec( Vec::with_capacity(pcrsel_vec.len() + 4 + digest_vec.len()); data_vec.extend(&pcrsel_vec); - data_vec.extend(num_tpml_digests.to_le_bytes()); + data_vec.extend(endian::local_endianness_32(num_tpml_digests)); data_vec.extend(&digest_vec); data_vec