Skip to content

Commit c4a78df

Browse files
committed
Add unmarshall_offset to UnMarshall trait
Adding a second method to the UnMarshall trait - unmarshall_offset - which takes a second parameter, a mutable offset, which is modified during unmarshalling to point to the first position in the input buffer that was not used for unmarshalling. The new method can be easily used to implement the basic `unmarshall` method by passing `&mut 0` as the offset. Also adding `Marshall` and `UnMarshall` for `CommandCode` and `u32`. Signed-off-by: Ionut Mihalcea <ionut.mihalcea@arm.com>
1 parent 750f1d9 commit c4a78df

File tree

6 files changed

+191
-3
lines changed

6 files changed

+191
-3
lines changed

tss-esapi/src/constants/command_code.rs

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22
// SPDX-License-Identifier: Apache-2.0
33
mod structure;
44

5-
use crate::{tss2_esys::TPM2_CC, Error, Result, WrapperErrorKind};
5+
use crate::{
6+
traits::{Marshall, UnMarshall},
7+
tss2_esys::TPM2_CC,
8+
Error, Result, ReturnCode, WrapperErrorKind,
9+
};
610
use log::error;
711
use num_derive::{FromPrimitive, ToPrimitive};
812
use num_traits::{FromPrimitive, ToPrimitive};
9-
use std::convert::TryFrom;
13+
use std::convert::{TryFrom, TryInto};
1014
use structure::CommandCodeStructure;
1115

1216
/// Enum representing the command code constants.
@@ -150,3 +154,70 @@ impl From<CommandCode> for TPM2_CC {
150154
command_code.to_u32().unwrap()
151155
}
152156
}
157+
158+
impl Marshall for CommandCode {
159+
const BUFFER_SIZE: usize = std::mem::size_of::<TPM2_CC>();
160+
161+
/// Produce a marshalled [TPM2_CC]
162+
fn marshall(&self) -> Result<Vec<u8>> {
163+
let mut buffer = vec![0; Self::BUFFER_SIZE];
164+
let mut offset = 0;
165+
166+
ReturnCode::ensure_success(
167+
unsafe {
168+
crate::tss2_esys::Tss2_MU_TPM2_CC_Marshal(
169+
(*self).into(),
170+
buffer.as_mut_ptr(),
171+
Self::BUFFER_SIZE.try_into().map_err(|e| {
172+
error!("Failed to convert size of buffer to TSS size_t type: {}", e);
173+
Error::local_error(WrapperErrorKind::InvalidParam)
174+
})?,
175+
&mut offset,
176+
)
177+
},
178+
|ret| {
179+
error!("Failed to marshal CommandCode: {}", ret);
180+
},
181+
)?;
182+
183+
let checked_offset = usize::try_from(offset).map_err(|e| {
184+
error!("Failed to parse offset as usize: {}", e);
185+
Error::local_error(WrapperErrorKind::InvalidParam)
186+
})?;
187+
188+
buffer.truncate(checked_offset);
189+
190+
Ok(buffer)
191+
}
192+
}
193+
194+
impl UnMarshall for CommandCode {
195+
/// Unmarshall the structure from [`TPM2_CC`]
196+
fn unmarshall(marshalled_data: &[u8]) -> Result<Self> {
197+
CommandCode::unmarshall_offset(marshalled_data, &mut 0)
198+
}
199+
200+
fn unmarshall_offset(
201+
marshalled_data: &[u8],
202+
offset: &mut std::os::raw::c_ulong,
203+
) -> Result<Self> {
204+
let mut dest = TPM2_CC::default();
205+
206+
ReturnCode::ensure_success(
207+
unsafe {
208+
crate::tss2_esys::Tss2_MU_TPM2_CC_Unmarshal(
209+
marshalled_data.as_ptr(),
210+
marshalled_data.len().try_into().map_err(|e| {
211+
error!("Failed to convert length of marshalled data: {}", e);
212+
Error::local_error(WrapperErrorKind::InvalidParam)
213+
})?,
214+
offset,
215+
&mut dest,
216+
)
217+
},
218+
|ret| error!("Failed to unmarshal SensitiveCreate: {}", ret),
219+
)?;
220+
221+
CommandCode::try_from(dest)
222+
}
223+
}

tss-esapi/src/traits.rs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
use std::convert::{TryFrom, TryInto};
2+
3+
use log::error;
4+
use tss_esapi_sys::UINT32;
5+
16
// Copyright 2021 Contributors to the Parsec project.
27
// SPDX-License-Identifier: Apache-2.0
3-
use crate::Result;
8+
use crate::{Error, Result, ReturnCode, WrapperErrorKind};
49

510
/// Trait for types that can be converted into
611
/// TPM marshalled data.
@@ -15,4 +20,80 @@ pub trait Marshall: Sized {
1520
pub trait UnMarshall: Sized {
1621
/// Creates the type from marshalled data.
1722
fn unmarshall(marshalled_data: &[u8]) -> Result<Self>;
23+
24+
/// Creates the type from the marshalled data, and modifies
25+
/// the `offset` to point to the first byte in the `marshalled_data`
26+
/// buffer which was not used in the conversion.
27+
fn unmarshall_offset(
28+
_marshalled_data: &[u8],
29+
_offset: &mut std::os::raw::c_ulong,
30+
) -> Result<Self> {
31+
unimplemented!();
32+
}
33+
}
34+
35+
impl Marshall for u32 {
36+
const BUFFER_SIZE: usize = std::mem::size_of::<UINT32>();
37+
38+
/// Produce a marshalled [UINT32]
39+
fn marshall(&self) -> Result<Vec<u8>> {
40+
let mut buffer = vec![0; Self::BUFFER_SIZE];
41+
let mut offset = 0;
42+
43+
ReturnCode::ensure_success(
44+
unsafe {
45+
crate::tss2_esys::Tss2_MU_UINT32_Marshal(
46+
*self,
47+
buffer.as_mut_ptr(),
48+
Self::BUFFER_SIZE.try_into().map_err(|e| {
49+
error!("Failed to convert size of buffer to TSS size_t type: {}", e);
50+
Error::local_error(WrapperErrorKind::InvalidParam)
51+
})?,
52+
&mut offset,
53+
)
54+
},
55+
|ret| {
56+
error!("Failed to marshall u32: {}", ret);
57+
},
58+
)?;
59+
60+
let checked_offset = usize::try_from(offset).map_err(|e| {
61+
error!("Failed to parse offset as usize: {}", e);
62+
Error::local_error(WrapperErrorKind::InvalidParam)
63+
})?;
64+
65+
buffer.truncate(checked_offset);
66+
67+
Ok(buffer)
68+
}
69+
}
70+
71+
impl UnMarshall for u32 {
72+
fn unmarshall(marshalled_data: &[u8]) -> Result<Self> {
73+
u32::unmarshall_offset(marshalled_data, &mut 0)
74+
}
75+
76+
fn unmarshall_offset(
77+
marshalled_data: &[u8],
78+
offset: &mut std::os::raw::c_ulong,
79+
) -> Result<Self> {
80+
let mut dest = 0_u32;
81+
82+
ReturnCode::ensure_success(
83+
unsafe {
84+
crate::tss2_esys::Tss2_MU_UINT32_Unmarshal(
85+
marshalled_data.as_ptr(),
86+
marshalled_data.len().try_into().map_err(|e| {
87+
error!("Failed to convert length of marshalled data: {}", e);
88+
Error::local_error(WrapperErrorKind::InvalidParam)
89+
})?,
90+
offset,
91+
&mut dest,
92+
)
93+
},
94+
|ret| error!("Failed to unmarshal SensitiveCreate: {}", ret),
95+
)?;
96+
97+
Ok(dest)
98+
}
1899
}

tss-esapi/tests/integration_tests/common/marshall.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,22 @@ pub fn check_marshall_unmarshall<T: Marshall + UnMarshall + Eq + std::fmt::Debug
99

1010
assert_eq!(val, &unmarshalled);
1111
}
12+
13+
pub fn check_marshall_unmarshall_offset<T: Marshall + UnMarshall + Eq + std::fmt::Debug>(val: &T) {
14+
let mut buf = val.marshall().expect("Failed to marshall value");
15+
let len = buf.len();
16+
let mut offset = 0;
17+
18+
buf.append(&mut buf.clone());
19+
buf.append(&mut vec![0xff; 256]);
20+
21+
let unmarshalled_one =
22+
T::unmarshall_offset(&buf, &mut offset).expect("Failed to unmarshall first copy");
23+
assert_eq!(offset, len as u64);
24+
assert_eq!(val, &unmarshalled_one);
25+
26+
let unmarshalled_two =
27+
T::unmarshall_offset(&buf, &mut offset).expect("Failed to unmarshall second copy");
28+
assert_eq!(offset, (len * 2) as u64);
29+
assert_eq!(val, &unmarshalled_two);
30+
}

tss-esapi/tests/integration_tests/constants_tests/command_code_tests.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,10 @@ fn test_invalid_conversions() {
218218
"A value representing a non existing command code did not produce the expected error"
219219
);
220220
}
221+
222+
#[test]
223+
fn test_marshall_unmarshall() {
224+
let cc = CommandCode::EvictControl;
225+
crate::common::check_marshall_unmarshall(&cc);
226+
crate::common::check_marshall_unmarshall_offset(&cc);
227+
}

tss-esapi/tests/integration_tests/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ mod handles_tests;
1515
mod interface_types_tests;
1616
mod structures_tests;
1717
mod tcti_ldr_tests;
18+
mod traits;
1819
mod utils_tests;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2023 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
#[test]
5+
fn test_u32_marshall_unmarshall() {
6+
let val = 0xdeadbeef_u32;
7+
crate::common::check_marshall_unmarshall(&val);
8+
crate::common::check_marshall_unmarshall_offset(&val);
9+
}

0 commit comments

Comments
 (0)