diff --git a/types/logroot.go b/types/logroot.go index 2648a36166..7ef3988e05 100644 --- a/types/logroot.go +++ b/types/logroot.go @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// Package types defines serialization and parsing functions for SignedLogRoot +// and SignedMapRoot fields. package types import ( @@ -23,7 +25,15 @@ import ( "github.com/google/trillian" ) -// LogRootV1 contains the fields used by clients to verify Trillian Log behavior. +// LogRootV1 holds the TLS-deserializtion of the following structure +// (described in RFC5246 section 4 notation): +// struct { +// uint64 tree_size; +// opaque root_hash<0..128>; +// uint64 timestamp_nanos; +// uint64 revision; +// opaque metadata<0..65535>; +// } LogRootV1; type LogRootV1 struct { TreeSize uint64 RootHash []byte `tls:"minlen:0,maxlen:128"` @@ -32,26 +42,34 @@ type LogRootV1 struct { Metadata []byte `tls:"minlen:0,maxlen:65535"` } -// LogRoot contains the fields serialized into SignedLogRoot.LogRoot +// LogRoot holds the TLS-deserializtion of the following structure +// (described in RFC5246 section 4 notation): +// enum { v1(1), (65535)} Version; +// struct { +// Version version; +// select(version) { +// case v1: LogRootV1; +// } +// } LogRoot; type LogRoot struct { Version tls.Enum `tls:"size:2"` V1 *LogRootV1 `tls:"selector:Version,val:1"` } -// ParseLogRoot verifies that b has the LOG_ROOT_FORMAT_V1 tag and returns a *LogRootV1 -func ParseLogRoot(b []byte) (*LogRootV1, error) { - if b == nil { +// ParseLogRoot verifies that logRootBytes is a TLS serialized LogRoot, +// has the LOG_ROOT_FORMAT_V1 tag, and returns the deserialized *LogRootV1. +func ParseLogRoot(logRootBytes []byte) (*LogRootV1, error) { + if logRootBytes == nil { return nil, fmt.Errorf("nil log root") } - // Verify version - version := binary.BigEndian.Uint16(b) + version := binary.BigEndian.Uint16(logRootBytes) if version != uint16(trillian.LogRootFormat_LOG_ROOT_FORMAT_V1) { return nil, fmt.Errorf("invalid LogRoot.Version: %v, want %v", version, trillian.LogRootFormat_LOG_ROOT_FORMAT_V1) } var logRoot LogRoot - if _, err := tls.Unmarshal(b, &logRoot); err != nil { + if _, err := tls.Unmarshal(logRootBytes, &logRoot); err != nil { return nil, err } return logRoot.V1, nil diff --git a/types/logroot_test.go b/types/logroot_test.go index c3a4567d07..0f7f425d85 100644 --- a/types/logroot_test.go +++ b/types/logroot_test.go @@ -60,13 +60,12 @@ func TestParseLogRoot(t *testing.T) { wantErr: true, }, { - logRoot: []byte("foo"), - wantErr: true, - }, - { - logRoot: nil, + // Correct type, but junk afterwards. + logRoot: []byte{0, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}, wantErr: true, }, + {logRoot: []byte("foo"), wantErr: true}, + {logRoot: nil, wantErr: true}, } { _, err := ParseLogRoot(tc.logRoot) if got, want := err != nil, tc.wantErr; got != want { diff --git a/types/maproot.go b/types/maproot.go index 65d976f531..048d4ade10 100644 --- a/types/maproot.go +++ b/types/maproot.go @@ -22,7 +22,14 @@ import ( "github.com/google/trillian" ) -// MapRootV1 contains the fields verified by SignedMapRoot +// MapRootV1 holds the TLS-deserializtion of the following structure +// (described in RFC5246 section 4 notation): +// struct { +// opaque root_hash<0..128>; +// uint64 timestamp_nanos; +// uint64 revision; +// opaque metadata<0..65535>; +// } MapRootV1; type MapRootV1 struct { RootHash []byte `tls:"minlen:0,maxlen:128"` TimestampNanos uint64 @@ -30,29 +37,37 @@ type MapRootV1 struct { Metadata []byte `tls:"minlen:0,maxlen:65535"` } -// MapRoot contains the fields serialized into SignedMapRoot.MapRoot +// MapRoot holds the TLS-deserializtion of the following structure +// (described in RFC5246 section 4 notation): +// enum { v1(1), (65535)} Version; +// struct { +// Version version; +// select(version) { +// case v1: MapRootV1; +// } +// } MapRoot; type MapRoot struct { Version tls.Enum `tls:"size:2"` V1 *MapRootV1 `tls:"selector:Version,val:1"` } -// ParseMapRoot verifies that b has the MAP_ROOT_FORMAT_V1 tag and returns a *MapRootV1 -func ParseMapRoot(b []byte) (*MapRootV1, error) { - if b == nil { +// ParseMapRoot verifies that mapRootBytes is a TLS serialized MapRoot, +// has the MAP_ROOT_FORMAT_V1 tag, and returns the deserialized *MapRootV1. +func ParseMapRoot(mapRootBytes []byte) (*MapRootV1, error) { + if mapRootBytes == nil { return nil, fmt.Errorf("nil map root") } - // Verify version - version := binary.BigEndian.Uint16(b) + version := binary.BigEndian.Uint16(mapRootBytes) if version != uint16(trillian.MapRootFormat_MAP_ROOT_FORMAT_V1) { return nil, fmt.Errorf("invalid MapRoot.Version: %v, want %v", version, trillian.MapRootFormat_MAP_ROOT_FORMAT_V1) } - var logRoot MapRoot - if _, err := tls.Unmarshal(b, &logRoot); err != nil { + var mapRoot MapRoot + if _, err := tls.Unmarshal(mapRootBytes, &mapRoot); err != nil { return nil, err } - return logRoot.V1, nil + return mapRoot.V1, nil } // SerializeMapRoot returns a canonical TLS serialization of the map root. diff --git a/types/maproot_test.go b/types/maproot_test.go index 6fe4b67d23..6e69b43477 100644 --- a/types/maproot_test.go +++ b/types/maproot_test.go @@ -68,6 +68,11 @@ func TestParseMapRoot(t *testing.T) { Metadata: []byte{}, }), }, + { + // Correct type, but junk afterwards. + mapRoot: []byte{0, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}, + wantErr: true, + }, {mapRoot: []byte("foo"), wantErr: true}, {mapRoot: nil, wantErr: true}, } {