Skip to content

Commit

Permalink
Add documentation and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gdbelvin committed Mar 8, 2018
1 parent e8cf97c commit 42bf9b0
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 23 deletions.
34 changes: 26 additions & 8 deletions types/logroot.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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"`
Expand All @@ -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
Expand Down
9 changes: 4 additions & 5 deletions types/logroot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
35 changes: 25 additions & 10 deletions types/maproot.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,52 @@ 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
Revision uint64
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.
Expand Down
5 changes: 5 additions & 0 deletions types/maproot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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},
} {
Expand Down

0 comments on commit 42bf9b0

Please sign in to comment.