@@ -27,39 +27,71 @@ type marshallableWithHint interface {
2727// This structure is marshaled to bytes using [Marshal] for storage/transmission
2828// and can be converted to the raw cpHash preimage format for hashing.
2929//
30- // Format when marshaled:
31- // - CommandCode: 4 bytes (TPMCC)
32- // - Names: sized list of TPM2BName
33- // - Parameters: sized buffer
34- //
3530// See definition in Part 1: Architecture, section 16.7.
3631type CommandPreimage struct {
37- marshalByReflection
3832 // CommandCode is the TPM command code
3933 CommandCode TPMCC
4034 // Names are the names of the handles referenced by the command
41- Names []TPM2BName `gotpm:"list"`
35+ Names []TPM2BName
4236 // Parameters are the marshaled command parameters
4337 Parameters TPM2BData
4438}
4539
46- // ToCPHashPreimage converts the CommandPreimage to the raw buffer format
47- // used to compute cpHash according to TPM 2.0 spec.
48- func (cp * CommandPreimage ) ToCPHashPreimage () []byte {
49- var buf bytes.Buffer
50-
51- // Write command code (4 bytes, big endian)
52- binary .Write (& buf , binary .BigEndian , cp .CommandCode )
53-
54- // Write names (raw buffers without size prefix)
40+ // Marshal converts the CommandPreimage to its byte representation.
41+ //
42+ // Format:
43+ // - CommandCode: 4 bytes (TPMCC)
44+ // - NameCount: 4 bytes (uint32)
45+ // - For each Name:
46+ // - NameSize: 4 bytes (uint32)
47+ // - Parameters: remaining bytes
48+ func (cp * CommandPreimage ) Marshal () ([]byte , error ) {
49+ buf := new (bytes.Buffer )
50+ if err := binary .Write (buf , binary .BigEndian , cp .CommandCode ); err != nil {
51+ return nil , err
52+ }
53+ if err := binary .Write (buf , binary .BigEndian , uint32 (len (cp .Names ))); err != nil {
54+ return nil , err
55+ }
5556 for _ , name := range cp .Names {
57+ if err := binary .Write (buf , binary .BigEndian , uint32 (len (name .Buffer ))); err != nil {
58+ return nil , err
59+ }
5660 buf .Write (name .Buffer )
5761 }
58-
59- // Write parameters
6062 buf .Write (cp .Parameters .Buffer )
63+ return buf .Bytes (), nil
64+ }
6165
62- return buf .Bytes ()
66+ // Unmarshal populates the [CommandPreimage] from its byte representation.
67+ func (cp * CommandPreimage ) Unmarshal (b []byte ) error {
68+ buf := bytes .NewBuffer (b )
69+
70+ if err := binary .Read (buf , binary .BigEndian , & cp .CommandCode ); err != nil {
71+ return fmt .Errorf ("unmarshalling CommandCode: %w" , err )
72+ }
73+
74+ var nameCount uint32
75+ if err := binary .Read (buf , binary .BigEndian , & nameCount ); err != nil {
76+ return fmt .Errorf ("unmarshalling Names count: %w" , err )
77+ }
78+
79+ cp .Names = make ([]TPM2BName , nameCount )
80+ for i := uint32 (0 ); i < nameCount ; i ++ {
81+ var name TPM2BName
82+
83+ var nameSize uint32
84+ if err := binary .Read (buf , binary .BigEndian , & nameSize ); err != nil {
85+ return fmt .Errorf ("unmarshalling Name size %d: %w" , i , err )
86+ }
87+ name .Buffer = make ([]byte , nameSize )
88+ if _ , err := buf .Read (name .Buffer ); err != nil {
89+ return fmt .Errorf ("unmarshalling Name %d: %w" , i , err )
90+ }
91+ cp .Names [i ] = name
92+ }
93+ cp .Parameters .Buffer = buf .Bytes ()
94+ return nil
6395}
6496
6597// Unmarshallable represents any TPM type that can be marshalled or unmarshalled.
@@ -196,15 +228,16 @@ func toCommandPreimage[C Command[R, *R], R any](cmd C) (*CommandPreimage, error)
196228// - Names (sized list)
197229// - Parameters (sized buffer)
198230//
199- // This can be stored, transmitted, or later unmarshaled.
231+ // This can be stored, transmitted, or later unmarshaled [UnmarshalCommand] .
200232//
201- // To compute cpHash use [CommandPreimage.ToCPHashPreimage].
233+ // Note: Encrypted command parameters (via sessions) are not currently supported.
234+ // The marshaled parameters are in their unencrypted form.
202235func MarshalCommand [C Command [R , * R ], R any ](cmd C ) ([]byte , error ) {
203236 preimage , err := toCommandPreimage (cmd )
204237 if err != nil {
205238 return nil , err
206239 }
207- return Marshal (preimage ), nil
240+ return preimage . Marshal ()
208241}
209242
210243// unmarshalCommandPreimage unmarshals serialized data into CommandPreimage components.
@@ -214,8 +247,8 @@ func unmarshalCommandPreimage(data []byte) (TPMCC, []TPM2BName, []byte, error) {
214247 return 0 , nil , nil , fmt .Errorf ("data cannot be nil" )
215248 }
216249
217- preimage , err := Unmarshal [ CommandPreimage ]( data )
218- if err != nil {
250+ var preimage CommandPreimage
251+ if err := preimage . Unmarshal ( data ); err != nil {
219252 return 0 , nil , nil , fmt .Errorf ("unmarshalling CommandPreimage: %w" , err )
220253 }
221254
@@ -225,8 +258,10 @@ func unmarshalCommandPreimage(data []byte) (TPMCC, []TPM2BName, []byte, error) {
225258// UnmarshalCommand unmarshals a serialized [CommandPreimage] back into a TPM command.
226259// The data should be the output from [MarshalCommand].
227260//
228- // Note: command produced from this function is not meant to be executed directly on a TPM,
229- // instead it is expected to be used for purposes such as auditing or inspection.
261+ // Notes:
262+ // - command produced from this function is not meant to be executed directly on a TPM,
263+ // instead it is expected to be used for purposes such as auditing or inspection.
264+ // - encrypted command parameters (via sessions) are not currently supported.
230265func UnmarshalCommand [C Command [R , * R ], R any ](data []byte ) (C , error ) {
231266 var cmd C
232267
@@ -271,7 +306,10 @@ func MarshalResponse[R any](rsp *R) ([]byte, error) {
271306
272307// UnmarshalResponse unmarshals a TPM response.
273308//
274- // Note: the result from this function is expected to be used for purposes such as auditing or inspection.
309+ // Notes:
310+ // - the result from this function is expected to be used for purposes such as auditing or inspection.
311+ // - encrypted response parameters (via sessions) are not currently supported.
312+ // The marshaled parameters are always in their unencrypted form.
275313func UnmarshalResponse [R any ](data []byte ) (* R , error ) {
276314 var rsp R
277315 if data == nil {
0 commit comments