diff options
Diffstat (limited to '')
-rw-r--r-- | verifysetup/cmd/setup.go | 21 | ||||
-rw-r--r-- | verifysetup/core/crypt.go | 3 | ||||
-rw-r--r-- | verifysetup/core/storage.go | 10 | ||||
-rw-r--r-- | verifysetup/go.sum | 8 |
4 files changed, 39 insertions, 3 deletions
diff --git a/verifysetup/cmd/setup.go b/verifysetup/cmd/setup.go index c2ba790..e946dd7 100644 --- a/verifysetup/cmd/setup.go +++ b/verifysetup/cmd/setup.go @@ -28,12 +28,15 @@ func NewSetupCommand() *cobra.Command { return cmd } +// checksumBlock is a function to create a chain of Nodes to verify an area of a block device. +// It is meant to be run as a goroutine, taking a waitGroup as a parameter. func checksumBlock(blockStart int, blockEnd int, bundleSize int, diskBytes []byte, nodeChannel chan verify.Node, n int, waitGroup *sync.WaitGroup) { defer waitGroup.Done() defer close(nodeChannel) var reader *bytes.Reader node := verify.Node{} + // A block is 2000 bytes big blockCount := math.Floor(float64(bundleSize / 2000)) for i := 0; i < int(blockCount); i++ { @@ -51,6 +54,8 @@ func checksumBlock(blockStart int, blockEnd int, bundleSize int, diskBytes []byt nodeChannel <- node } + // Since it is unlikely that the bundleSize is perfectly divisible by 2000 + // a final node has to be created that includes the last amount of bytes block, err := core.ReadBlock(int(blockCount*2000), len(diskBytes), reader) if err != nil { fmt.Printf("%d:: final attempted reading from %d to %d. Error %s\n", blockStart, int(blockCount*2000)+2000, len(diskBytes), err) @@ -65,6 +70,10 @@ func SetupCommand(_ *cobra.Command, args []string) error { if len(args) != 3 && len(args) != 4 { return fmt.Errorf("Usage: verifysetup setup [partition] [procCount] [fsverify partition output] <minisign directory>") } + + // The minisign directory argument is optional + // which is why the existence of the argument is checked + // before minisignDir is set to a directory var minisignDir string if len(args) != 4 { minisignDir = "./minisign/" @@ -75,6 +84,7 @@ func SetupCommand(_ *cobra.Command, args []string) error { if err != nil { return err } + fmt.Println("Using partition: ", args[0]) disk, err := os.Open(args[0]) if err != nil { @@ -86,6 +96,7 @@ func SetupCommand(_ *cobra.Command, args []string) error { if err != nil { return err } + diskSize := diskInfo.Size() bundleSize := math.Floor(float64(diskSize / int64(procCount))) blockCount := math.Ceil(float64(bundleSize / 2000)) @@ -95,10 +106,14 @@ func SetupCommand(_ *cobra.Command, args []string) error { return err } + // To decrease the amount of file operations + // a single reader is created that gets used for the goroutines reader := bytes.NewReader(diskBytes) var waitGroup sync.WaitGroup nodeChannels := make([]chan verify.Node, procCount+1) for i := 0; i < procCount; i++ { + // Ensuring that each thread only reads the area it is meant to read + // by making a copy of the area which it gets access to diskBytesCopy, err := verify.CopyByteArea(i*(int(bundleSize)), (i+1)*(int(bundleSize)), reader) if err != nil { return err @@ -115,6 +130,10 @@ func SetupCommand(_ *cobra.Command, args []string) error { return err } + // All generated nodes are written to the database at once + // while this is worse for the speed of verifysetup. + // it ensures that no write conflicts happen + // which could be caused by multiple threads accessing the same database for i := 0; i < procCount; i++ { channel := nodeChannels[i] err = db.Batch(func(tx *bolt.Tx) error { @@ -141,6 +160,8 @@ func SetupCommand(_ *cobra.Command, args []string) error { return err } + // The untrusted Signature is stored in a special way + // requiring special decoding of it to represent it as a string var UntrustedSignature [2 + 8 + ed25519.SignatureSize]byte binary.LittleEndian.PutUint16(UntrustedSignature[:2], sig.Algorithm) binary.LittleEndian.PutUint64(UntrustedSignature[2:10], sig.KeyID) diff --git a/verifysetup/core/crypt.go b/verifysetup/core/crypt.go index 4658641..1307bd3 100644 --- a/verifysetup/core/crypt.go +++ b/verifysetup/core/crypt.go @@ -11,6 +11,7 @@ import ( "strings" ) +// CalculateBlockHash calculates the sha1 checksum of a byte slice. func CalculateBlockHash(block []byte) (string, error) { hash := sha1.New() if _, err := io.Copy(hash, bytes.NewReader(block)); err != nil { @@ -20,6 +21,8 @@ func CalculateBlockHash(block []byte) (string, error) { return strings.TrimSpace(fmt.Sprintf("%x", hashInBytes)), nil } +// SignDatabase generates a minisign signature of the database using given keys. +// The minisign signature uses "fsverify" as the comments to ensure predictability when fsverify verifies the signature. func SignDatabase(database string, minisignKeys string) ([]byte, error) { fmt.Print("Enter your password (will not echo): ") p, err := term.ReadPassword(int(os.Stdin.Fd())) diff --git a/verifysetup/core/storage.go b/verifysetup/core/storage.go index 64b06a1..a4fc66d 100644 --- a/verifysetup/core/storage.go +++ b/verifysetup/core/storage.go @@ -10,8 +10,8 @@ import ( bolt "go.etcd.io/bbolt" ) -var TotalReadBlocks = 0 - +// ReadBlock reads the bytes in a specified ranges from a bytes.Reader. +// It additionally verifies that the amount of bytes read match with the size of the area and fails if the they do not match. func ReadBlock(start int, end int, device *bytes.Reader) ([]byte, error) { if end-start < 0 { return []byte{}, fmt.Errorf("tried creating byte slice with negative length. %d to %d total %d\n", start, end, end-start) @@ -24,10 +24,11 @@ func ReadBlock(start int, end int, device *bytes.Reader) ([]byte, error) { return []byte{}, err } _, err = device.Read(block) - TotalReadBlocks = TotalReadBlocks + (end - start) return block, err } +// CreateNode creates a Node based on given parameters. +// If prevNode is set to nil, meaning this node is the first node in a verification chain, prevNodeHash is set to "EntrypointN" with N being the number of entrypoint. func CreateNode(blockStart int, blockEnd int, block []byte, prevNode *verify.Node, n string) (verify.Node, error) { node := verify.Node{} node.BlockStart = blockStart @@ -50,6 +51,8 @@ func CreateNode(blockStart int, blockEnd int, block []byte, prevNode *verify.Nod return node, nil } +// AddNode adds a node to the bucket "Nodes" in the database. +// It assumes that a database transaction has already been started and takes bolt.Tx as an argument. func AddNode(node verify.Node, tx *bolt.Tx) error { if node.BlockStart == node.BlockEnd { return nil @@ -66,6 +69,7 @@ func AddNode(node verify.Node, tx *bolt.Tx) error { return nil } +// CreateHeader creates a header to be used in an fsverify partition containing all necessary information. func CreateHeader(unsignedHash string, signedHash string, diskSize int, tableSize int) ([]byte, error) { header := make([]byte, 200) header[0] = 0xAC diff --git a/verifysetup/go.sum b/verifysetup/go.sum index debe9f9..be58f96 100644 --- a/verifysetup/go.sum +++ b/verifysetup/go.sum @@ -14,15 +14,23 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |