diff options
Diffstat (limited to 'pkg/merkletree/merkletree.go')
-rw-r--r-- | pkg/merkletree/merkletree.go | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/pkg/merkletree/merkletree.go b/pkg/merkletree/merkletree.go index e0a9e56c5..aea7dde38 100644 --- a/pkg/merkletree/merkletree.go +++ b/pkg/merkletree/merkletree.go @@ -19,6 +19,7 @@ import ( "bytes" "crypto/sha256" "crypto/sha512" + "encoding/gob" "fmt" "io" @@ -151,11 +152,15 @@ type VerityDescriptor struct { Mode uint32 UID uint32 GID uint32 + Children map[string]struct{} RootHash []byte } func (d *VerityDescriptor) String() string { - return fmt.Sprintf("Name: %s, Size: %d, Mode: %d, UID: %d, GID: %d, RootHash: %v", d.Name, d.FileSize, d.Mode, d.UID, d.GID, d.RootHash) + b := new(bytes.Buffer) + e := gob.NewEncoder(b) + e.Encode(d.Children) + return fmt.Sprintf("Name: %s, Size: %d, Mode: %d, UID: %d, GID: %d, Children: %v, RootHash: %v", d.Name, d.FileSize, d.Mode, d.UID, d.GID, b.Bytes(), d.RootHash) } // verify generates a hash from d, and compares it with expected. @@ -202,6 +207,9 @@ type GenerateParams struct { UID uint32 // GID is the group ID of the target file. GID uint32 + // Children is a map of children names for a directory. It should be + // empty for a regular file. + Children map[string]struct{} // HashAlgorithms is the algorithms used to hash data. HashAlgorithms int // TreeReader is a reader for the Merkle tree. @@ -294,6 +302,7 @@ func Generate(params *GenerateParams) ([]byte, error) { Mode: params.Mode, UID: params.UID, GID: params.GID, + Children: params.Children, RootHash: root, } return hashData([]byte(descriptor.String()), params.HashAlgorithms) @@ -318,6 +327,9 @@ type VerifyParams struct { UID uint32 // GID is the group ID of the target file. GID uint32 + // Children is a map of children names for a directory. It should be + // empty for a regular file. + Children map[string]struct{} // HashAlgorithms is the algorithms used to hash data. HashAlgorithms int // ReadOffset is the offset of the data range to be verified. @@ -338,9 +350,13 @@ type VerifyParams struct { // For verifyMetadata, params.data is not needed. It only accesses params.tree // for the raw root hash. func verifyMetadata(params *VerifyParams, layout *Layout) error { - root := make([]byte, layout.digestSize) - if _, err := params.Tree.ReadAt(root, layout.blockOffset(layout.rootLevel(), 0 /* index */)); err != nil { - return fmt.Errorf("failed to read root hash: %w", err) + var root []byte + // Only read the root hash if we expect that the Merkle tree file is non-empty. + if params.Size != 0 { + root = make([]byte, layout.digestSize) + if _, err := params.Tree.ReadAt(root, layout.blockOffset(layout.rootLevel(), 0 /* index */)); err != nil { + return fmt.Errorf("failed to read root hash: %w", err) + } } descriptor := VerityDescriptor{ Name: params.Name, @@ -348,6 +364,7 @@ func verifyMetadata(params *VerifyParams, layout *Layout) error { Mode: params.Mode, UID: params.UID, GID: params.GID, + Children: params.Children, RootHash: root, } return descriptor.verify(params.Expected, params.HashAlgorithms) @@ -409,6 +426,7 @@ func Verify(params *VerifyParams) (int64, error) { Mode: params.Mode, UID: params.UID, GID: params.GID, + Children: params.Children, } if err := verifyBlock(params.Tree, &descriptor, &layout, buf, i, params.HashAlgorithms, params.Expected); err != nil { return 0, err |