@@ -23,32 +23,49 @@ import (
2323 "reflect"
2424)
2525
26- // lengthPrefixSize is the size in bytes of length prefix for byte slices.
27- //
28- // In TPM 1.2 this is 4 bytes.
29- // In TPM 2.0 this is 2 bytes.
30- var lengthPrefixSize int
26+ // Encoding implements encoding logic for different versions of the TPM
27+ // specification.
28+ type Encoding struct {
29+ // lengthPrefixSize is the size in bytes of length prefix for byte slices.
30+ //
31+ // In TPM 1.2 this is 4 bytes.
32+ // In TPM 2.0 this is 2 bytes.
33+ lengthPrefixSize int
34+ }
35+
36+ var (
37+ // TPM implements TPM 1.2 encoding.
38+ TPM = & Encoding {
39+ lengthPrefixSize : tpm12PrefixSize ,
40+ }
41+ // TPM implements TPM 2.0 encoding.
42+ TPM2 = & Encoding {
43+ lengthPrefixSize : tpm20PrefixSize ,
44+ }
45+
46+ defaultEncoding * Encoding
47+ )
3148
3249const (
3350 tpm12PrefixSize = 4
3451 tpm20PrefixSize = 2
3552)
3653
37- // UseTPM12LengthPrefixSize makes Pack/Unpack use TPM 1.2 encoding for byte
38- // arrays.
54+ // UseTPM12LengthPrefixSize makes the package level Pack/Unpack functions use
55+ // TPM 1.2 encoding for byte arrays.
3956func UseTPM12LengthPrefixSize () {
40- lengthPrefixSize = tpm12PrefixSize
57+ defaultEncoding = TPM
4158}
4259
43- // UseTPM20LengthPrefixSize makes Pack/Unpack use TPM 2.0 encoding for byte
44- // arrays.
60+ // UseTPM20LengthPrefixSize makes the package level Pack/Unpack functions use
61+ // TPM 2.0 encoding for byte arrays.
4562func UseTPM20LengthPrefixSize () {
46- lengthPrefixSize = tpm20PrefixSize
63+ defaultEncoding = TPM2
4764}
4865
4966// packedSize computes the size of a sequence of types that can be passed to
5067// binary.Read or binary.Write.
51- func packedSize (elts ... interface {}) (int , error ) {
68+ func ( enc * Encoding ) packedSize (elts ... interface {}) (int , error ) {
5269 var size int
5370 for _ , e := range elts {
5471 marshaler , ok := e .(SelfMarshaler )
@@ -59,15 +76,15 @@ func packedSize(elts ...interface{}) (int, error) {
5976 v := reflect .ValueOf (e )
6077 switch v .Kind () {
6178 case reflect .Ptr :
62- s , err := packedSize (reflect .Indirect (v ).Interface ())
79+ s , err := enc . packedSize (reflect .Indirect (v ).Interface ())
6380 if err != nil {
6481 return 0 , err
6582 }
6683
6784 size += s
6885 case reflect .Struct :
6986 for i := 0 ; i < v .NumField (); i ++ {
70- s , err := packedSize (v .Field (i ).Interface ())
87+ s , err := enc . packedSize (v .Field (i ).Interface ())
7188 if err != nil {
7289 return 0 , err
7390 }
@@ -77,7 +94,7 @@ func packedSize(elts ...interface{}) (int, error) {
7794 case reflect .Slice :
7895 switch s := e .(type ) {
7996 case []byte :
80- size += lengthPrefixSize + len (s )
97+ size += enc . lengthPrefixSize + len (s )
8198 case RawBytes :
8299 size += len (s )
83100 default :
@@ -100,9 +117,9 @@ func packedSize(elts ...interface{}) (int, error) {
100117// fixed length or slices of fixed-length types and packs them into a single
101118// byte array using binary.Write. It updates the CommandHeader to have the right
102119// length.
103- func packWithHeader (ch commandHeader , cmd ... interface {}) ([]byte , error ) {
120+ func ( enc * Encoding ) packWithHeader (ch commandHeader , cmd ... interface {}) ([]byte , error ) {
104121 hdrSize := binary .Size (ch )
105- bodySize , err := packedSize (cmd ... )
122+ bodySize , err := enc . packedSize (cmd ... )
106123 if err != nil {
107124 return nil , fmt .Errorf ("couldn't compute packed size for message body: %v" , err )
108125 }
@@ -112,20 +129,27 @@ func packWithHeader(ch commandHeader, cmd ...interface{}) ([]byte, error) {
112129 return Pack (in ... )
113130}
114131
132+ // Pack encodes a set of elements using the package's default encoding.
133+ //
134+ // Callers must call UseTPM12LengthPrefixSize() or UseTPM20LengthPrefixSize()
135+ // before calling this method.
136+ func Pack (elts ... interface {}) ([]byte , error ) {
137+ if defaultEncoding == nil {
138+ return nil , errors .New ("default encoding not initialized" )
139+ }
140+ return defaultEncoding .Pack (elts ... )
141+ }
142+
115143// Pack encodes a set of elements into a single byte array, using
116144// encoding/binary. This means that all the elements must be encodeable
117145// according to the rules of encoding/binary.
118146//
119147// It has one difference from encoding/binary: it encodes byte slices with a
120148// prepended length, to match how the TPM encodes variable-length arrays. If
121149// you wish to add a byte slice without length prefix, use RawBytes.
122- func Pack (elts ... interface {}) ([]byte , error ) {
123- if lengthPrefixSize == 0 {
124- return nil , errors .New ("lengthPrefixSize must be initialized" )
125- }
126-
150+ func (enc * Encoding ) Pack (elts ... interface {}) ([]byte , error ) {
127151 buf := new (bytes.Buffer )
128- if err := packType (buf , elts ... ); err != nil {
152+ if err := enc . packType (buf , elts ... ); err != nil {
129153 return nil , err
130154 }
131155
@@ -137,7 +161,7 @@ func Pack(elts ...interface{}) ([]byte, error) {
137161// lengthPrefixSize size followed by the bytes. The function unpackType
138162// performs the inverse operation of unpacking slices stored in this manner and
139163// using encoding/binary for everything else.
140- func packType (buf io.Writer , elts ... interface {}) error {
164+ func ( enc * Encoding ) packType (buf io.Writer , elts ... interface {}) error {
141165 for _ , e := range elts {
142166 marshaler , ok := e .(SelfMarshaler )
143167 if ok {
@@ -149,20 +173,20 @@ func packType(buf io.Writer, elts ...interface{}) error {
149173 v := reflect .ValueOf (e )
150174 switch v .Kind () {
151175 case reflect .Ptr :
152- if err := packType (buf , reflect .Indirect (v ).Interface ()); err != nil {
176+ if err := enc . packType (buf , reflect .Indirect (v ).Interface ()); err != nil {
153177 return err
154178 }
155179 case reflect .Struct :
156180 // TODO(awly): Currently packType cannot handle non-struct fields that implement SelfMarshaler
157181 for i := 0 ; i < v .NumField (); i ++ {
158- if err := packType (buf , v .Field (i ).Interface ()); err != nil {
182+ if err := enc . packType (buf , v .Field (i ).Interface ()); err != nil {
159183 return err
160184 }
161185 }
162186 case reflect .Slice :
163187 switch s := e .(type ) {
164188 case []byte :
165- switch lengthPrefixSize {
189+ switch enc . lengthPrefixSize {
166190 case tpm20PrefixSize :
167191 if err := binary .Write (buf , binary .BigEndian , uint16 (len (s ))); err != nil {
168192 return err
@@ -172,7 +196,7 @@ func packType(buf io.Writer, elts ...interface{}) error {
172196 return err
173197 }
174198 default :
175- return fmt .Errorf ("lengthPrefixSize is %d, must be either 2 or 4" , lengthPrefixSize )
199+ return fmt .Errorf ("lengthPrefixSize is %d, must be either 2 or 4" , enc . lengthPrefixSize )
176200 }
177201 if err := binary .Write (buf , binary .BigEndian , s ); err != nil {
178202 return err
@@ -204,12 +228,24 @@ func Unpack(b []byte, elts ...interface{}) (int, error) {
204228 return read , err
205229}
206230
231+ // UnpackBuf recursively unpacks types from a reader using the package's default
232+ // encoder.
233+ //
234+ // Callers must call UseTPM12LengthPrefixSize() or UseTPM20LengthPrefixSize()
235+ // before calling this method.
236+ func UnpackBuf (buf io.Reader , elts ... interface {}) error {
237+ if defaultEncoding == nil {
238+ return errors .New ("default encoding not initialized" )
239+ }
240+ return defaultEncoding .UnpackBuf (buf , elts ... )
241+ }
242+
207243// UnpackBuf recursively unpacks types from a reader just as encoding/binary
208244// does under binary.BigEndian, but with one difference: it unpacks a byte
209245// slice by first reading an integer with lengthPrefixSize bytes, then reading
210246// that many bytes. It assumes that incoming values are pointers to values so
211247// that, e.g., underlying slices can be resized as needed.
212- func UnpackBuf (buf io.Reader , elts ... interface {}) error {
248+ func ( enc * Encoding ) UnpackBuf (buf io.Reader , elts ... interface {}) error {
213249 for _ , e := range elts {
214250 v := reflect .ValueOf (e )
215251 k := v .Kind ()
@@ -250,21 +286,21 @@ func UnpackBuf(buf io.Reader, elts ...interface{}) error {
250286 }
251287 size = int (tmpSize )
252288 // TPM 2.0
253- case lengthPrefixSize == tpm20PrefixSize :
289+ case enc . lengthPrefixSize == tpm20PrefixSize :
254290 var tmpSize uint16
255291 if err := binary .Read (buf , binary .BigEndian , & tmpSize ); err != nil {
256292 return err
257293 }
258294 size = int (tmpSize )
259295 // TPM 1.2
260- case lengthPrefixSize == tpm12PrefixSize :
296+ case enc . lengthPrefixSize == tpm12PrefixSize :
261297 var tmpSize uint32
262298 if err := binary .Read (buf , binary .BigEndian , & tmpSize ); err != nil {
263299 return err
264300 }
265301 size = int (tmpSize )
266302 default :
267- return fmt .Errorf ("lengthPrefixSize is %d, must be either 2 or 4" , lengthPrefixSize )
303+ return fmt .Errorf ("lengthPrefixSize is %d, must be either 2 or 4" , enc . lengthPrefixSize )
268304 }
269305
270306 // A zero size is used by the TPM to signal that certain elements
0 commit comments