diff options
-rw-r--r-- | cmd/verify.go | 15 | ||||
-rw-r--r-- | config/config.go | 8 | ||||
-rw-r--r-- | core/storage.go | 8 | ||||
-rw-r--r-- | core/verification.go | 108 | ||||
-rw-r--r-- | go.mod | 5 | ||||
-rw-r--r-- | go.sum | 8 | ||||
-rw-r--r-- | part.fsverify | bin | 32968 -> 32200 bytes | |||
-rw-r--r-- | verifysetup/cmd/root.go | 22 | ||||
-rw-r--r-- | verifysetup/cmd/setup.go | 20 | ||||
-rw-r--r-- | verifysetup/go.mod | 3 |
10 files changed, 194 insertions, 3 deletions
diff --git a/cmd/verify.go b/cmd/verify.go index 2f18d34..2afb354 100644 --- a/cmd/verify.go +++ b/cmd/verify.go @@ -79,5 +79,20 @@ func ValidateCommand(_ *cobra.Command, args []string) error { return err } fmt.Printf("Block '%s' ranging from %d to %d matches!\n", getnode.PrevNodeSum, getnode.BlockStart, getnode.BlockEnd) + + fmt.Println("----") + + key, err := core.ReadKey() + if err != nil { + return err + } + fmt.Println("Key: " + key) + + err = core.VerifySignature(key, header.Signature, dbfile) + if err != nil { + return err + } else { + fmt.Println("Signtaure success") + } return nil } diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..ac732af --- /dev/null +++ b/config/config.go @@ -0,0 +1,8 @@ +package config + +// How the public key is stored +// 0: external file, 1: external storage device, 2: tpm2, 3: usb serial +var KeyStore = 0 + +// Where the public key is stored, only applies for 0, 1 and 3 +var KeyLocation = "./publickey" diff --git a/core/storage.go b/core/storage.go index f6f1ffd..8346c12 100644 --- a/core/storage.go +++ b/core/storage.go @@ -99,7 +99,7 @@ func ReadHeader(partition string) (Header, error) { return Header{}, err } - header.Signature = fmt.Sprintf("untrusted comment: signature from minisign secret key\r\n%s\r\ntrusted comment: timestamp:0\tfile:fsverify\thashed\r\n%s\r\n", UntrustedHash, TrustedHash) + header.Signature = fmt.Sprintf("untrusted comment: fsverify\r\n%s\r\ntrusted comment: fsverify\r\n%s\r\n", UntrustedHash, TrustedHash) header.FilesystemSize = int(binary.BigEndian.Uint16(FilesystemSize)) header.TableSize = int(binary.BigEndian.Uint32(TableSize)) header.FilesystemUnit = parseUnitSpec(FilesystemUnit) @@ -135,10 +135,14 @@ func ReadDB(partition string) (string, error) { } db := make([]byte, header.TableSize*header.TableUnit) - _, err = io.ReadFull(reader, db) + n, err := io.ReadFull(reader, db) if err != nil { return "", err } + if n != header.TableSize*header.TableUnit { + return "", fmt.Errorf("Error: Database is not expected size. Got: %d, expected %d", n, header.TableSize*header.TableUnit) + } + fmt.Printf("db: %d\n", n) temp, err := os.MkdirTemp("", "*-fsverify") if err != nil { diff --git a/core/verification.go b/core/verification.go index 5023d06..b48c0b7 100644 --- a/core/verification.go +++ b/core/verification.go @@ -3,9 +3,93 @@ package core import ( "bufio" "fmt" + "os" "strings" + + "github.com/axtloss/fsverify/config" + "github.com/jedisct1/go-minisign" + "github.com/tarm/serial" ) +func fileReadKey() (string, error) { + if _, err := os.Stat(config.KeyLocation); os.IsNotExist(err) { + return "", fmt.Errorf("Key location %s does not exist", config.KeyLocation) + } + file, err := os.Open(config.KeyLocation) + if err != nil { + return "", err + } + defer file.Close() + key := make([]byte, 56) + reader := bufio.NewReader(file) + n, err := reader.Read(key) + if n != 56 { + return "", fmt.Errorf("Error: Key does not match expected key size. expected 56, got %d", n) + } + if err != nil { + return "", err + } + return string(key), nil +} + +func serialReadKey() (string, error) { + if _, err := os.Stat(config.KeyLocation); !os.IsNotExist(err) { + fmt.Println("Reconnect arduino now") + for true { + if _, err := os.Stat(config.KeyLocation); os.IsNotExist(err) { + break + } + } + } else { + fmt.Println("Connect arduino now") + } + for true { + if _, err := os.Stat(config.KeyLocation); !os.IsNotExist(err) { + break + } + } + fmt.Println("Arduino connected") + c := &serial.Config{Name: config.KeyLocation, Baud: 9600} + s, err := serial.OpenPort(c) + if err != nil { + return "", err + } + + key := "" + for true { + buf := make([]byte, 128) + n, err := s.Read(buf) + if err != nil { + return "", err + } + defer s.Close() + key = key + fmt.Sprintf("%q", buf[:n]) + if strings.Count(key, "\\t") == 2 { + break + } + } + key = strings.ReplaceAll(key, "\\t", "") + key = strings.ReplaceAll(key, "\"", "") + if len(key) != 56 { + return "", fmt.Errorf("Error: Key does not match expected key size. expected 56, got %d", len(key)) + } + return key, nil +} + +func ReadKey() (string, error) { + switch config.KeyStore { + case 0: + return fileReadKey() + case 1: + return fileReadKey() + case 2: + return "", nil + case 3: + return serialReadKey() + } + return "", nil +} + func ReadBlock(node Node, part *bufio.Reader) ([]byte, error) { block := make([]byte, node.BlockEnd-node.BlockStart) blockSize := node.BlockEnd - node.BlockStart @@ -17,6 +101,30 @@ func ReadBlock(node Node, part *bufio.Reader) ([]byte, error) { return block, err } +func VerifySignature(key string, signature string, database string) error { + pk, err := minisign.NewPublicKey(key) + if err != nil { + return err + } + + sig, err := minisign.DecodeSignature(signature) + if err != nil { + return err + } + + data, err := os.ReadFile(database) + if err != nil { + return err + } + + verified, err := pk.Verify(data, sig) + if err != nil || !verified { + return err + } + + return nil +} + func VerifyBlock(block []byte, node Node) error { calculatedBlockHash, err := CalculateBlockHash(block) if err != nil { @@ -4,8 +4,11 @@ go 1.21.6 require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 // indirect go.etcd.io/bbolt v1.3.8 // indirect - golang.org/x/sys v0.4.0 // indirect + golang.org/x/crypto v0.12.0 // indirect + golang.org/x/sys v0.11.0 // indirect ) @@ -1,14 +1,22 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY= +github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= 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= 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.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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= diff --git a/part.fsverify b/part.fsverify Binary files differindex cca63e4..202acd1 100644 --- a/part.fsverify +++ b/part.fsverify diff --git a/verifysetup/cmd/root.go b/verifysetup/cmd/root.go new file mode 100644 index 0000000..edcb250 --- /dev/null +++ b/verifysetup/cmd/root.go @@ -0,0 +1,22 @@ +package cmd + +import ( + "github.com/spf13/cobra" + "os" +) + +var rootCmd = &cobra.Command{ + Use: "verifysetup", +} + +func init() { + rootCmd.AddCommand(NewSetupCommand()) +} + +func Execute() { + // cobra does not exit with a non-zero return code when failing + // solution from https://github.com/spf13/cobra/issues/221 + if err := rootCmd.Execute(); err != nil { + os.Exit(1) + } +} diff --git a/verifysetup/cmd/setup.go b/verifysetup/cmd/setup.go new file mode 100644 index 0000000..3897903 --- /dev/null +++ b/verifysetup/cmd/setup.go @@ -0,0 +1,20 @@ +package cmd + +import ( + "github.com/spf13/cobra" +) + +func NewVerifyCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "setup", + Short: "Set up fsverify", + RunE: SetupCommand, + SilenceUsage: true, + } + + return cmd +} + +func SetupCommand(_ *cobra.Command, args []string) error { + return nil +} diff --git a/verifysetup/go.mod b/verifysetup/go.mod new file mode 100644 index 0000000..25642c6 --- /dev/null +++ b/verifysetup/go.mod @@ -0,0 +1,3 @@ +module github.com/axtloss/fsverify/verifysetup + +go 1.21.6 |