A bunch of changes

Signed-off-by: Dave Henderson <dhenderson@gmail.com>
This commit is contained in:
Dave Henderson
2018-08-20 20:06:33 -04:00
parent 16a4d2826c
commit a1879b1eb0
16 changed files with 274 additions and 203 deletions

10
cmd/onerng/doc.go Normal file
View File

@ -0,0 +1,10 @@
/*
onerng is a OneRNG hardware random number generation utility.
Usage
TODO...
*/
package main

20
cmd/onerng/flush.go Normal file
View File

@ -0,0 +1,20 @@
package main
import (
"context"
"github.com/hairyhenderson/go-onerng"
"github.com/spf13/cobra"
)
// flushCmd represents the flush command
func flushCmd(ctx context.Context) *cobra.Command {
return &cobra.Command{
Use: "flush",
Short: "Flush the OneRNG's entropy pool",
RunE: func(cmd *cobra.Command, args []string) error {
o := onerng.OneRNG{Path: opts.Device}
return o.Flush(ctx)
},
}
}

26
cmd/onerng/id.go Normal file
View File

@ -0,0 +1,26 @@
package main
import (
"context"
"fmt"
"github.com/hairyhenderson/go-onerng"
"github.com/spf13/cobra"
)
// idCmd represents the id command
func idCmd(ctx context.Context) *cobra.Command {
return &cobra.Command{
Use: "id",
Short: "Display the OneRNG's hardware id",
RunE: func(cmd *cobra.Command, args []string) error {
o := onerng.OneRNG{Path: opts.Device}
id, err := o.Identify(ctx)
if err != nil {
return err
}
fmt.Printf("OneRNG Hardware ID: %s\n", id)
return nil
},
}
}

46
cmd/onerng/image.go Normal file
View File

@ -0,0 +1,46 @@
package main
import (
"context"
"fmt"
"os"
"github.com/pkg/errors"
"github.com/hairyhenderson/go-onerng"
"github.com/spf13/cobra"
)
// imageCmd represents the image command
func imageCmd(ctx context.Context) *cobra.Command {
var imgOut string
cmd := &cobra.Command{
Use: "image",
Short: "Dump the OneRNG's firmware image",
RunE: func(cmd *cobra.Command, args []string) error {
o := onerng.OneRNG{Path: opts.Device}
err := o.Init(ctx)
if err != nil {
return errors.Wrapf(err, "init failed before image extraction")
}
image, err := o.Image(ctx)
if err != nil {
return err
}
var out *os.File
if imgOut == "-" {
out = os.Stdout
} else {
out, err = os.OpenFile(imgOut, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
return err
}
}
n, err := out.Write(image)
fmt.Fprintf(os.Stderr, "Wrote %db to %s\n", n, imgOut)
return err
},
}
cmd.Flags().StringVarP(&imgOut, "out", "o", "onerng.img", "output file for image (use - for stdout)")
return cmd
}

21
cmd/onerng/init.go Normal file
View File

@ -0,0 +1,21 @@
package main
import (
"context"
"github.com/hairyhenderson/go-onerng"
"github.com/spf13/cobra"
)
// initCmd represents the init command
func initCmd(ctx context.Context) *cobra.Command {
return &cobra.Command{
Use: "init",
Short: "Initialize the RNG",
RunE: func(cmd *cobra.Command, args []string) error {
o := onerng.OneRNG{Path: opts.Device}
err := o.Init(ctx)
return err
},
}
}

View File

@ -1,11 +1,12 @@
// onerng: OneRNG hardware random number generation utility
package main
import (
"context"
"fmt"
"os"
"os/signal"
"github.com/hairyhenderson/go-onerng/cmd"
)
func main() {
@ -26,5 +27,10 @@ func main() {
}
}()
cmd.Execute(ctx)
cmd := rootCmd(ctx)
initConfig(ctx, cmd)
if err := cmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

89
cmd/onerng/read.go Normal file
View File

@ -0,0 +1,89 @@
package main
import (
"context"
"fmt"
"io"
"os"
"time"
"github.com/pkg/errors"
"github.com/dustin/go-humanize"
"github.com/hairyhenderson/go-onerng"
"github.com/spf13/cobra"
)
func readCmd(ctx context.Context) *cobra.Command {
readOut := ""
disableAvalanche := false
enableRF := false
disableWhitener := false
enableAESWhiten := true
count := int64(-1)
cmd := &cobra.Command{
Use: "read",
Short: "read some random data from the OneRNG",
RunE: func(cmd *cobra.Command, args []string) error {
o := &onerng.OneRNG{Path: opts.Device}
err := o.Init(ctx)
if err != nil {
return errors.Wrapf(err, "init failed")
}
// set flags based on commandline options
flags := onerng.Default
if disableAvalanche {
flags |= onerng.DisableAvalanche
}
if enableRF {
flags |= onerng.EnableRF
}
if disableWhitener {
flags |= onerng.DisableWhitener
}
// waste some entropy...
devNull, err := os.OpenFile("/dev/null", os.O_WRONLY, 0200)
if err != nil {
return err
}
_, err = o.Read(ctx, devNull, 10*1024, flags)
if err != nil {
fmt.Fprintf(os.Stderr, "warning: entropy wasteage failed or incomplete, continuing anyway\n")
}
var out io.WriteCloser
if readOut == "-" {
out = os.Stdout
} else {
out, err = os.OpenFile(readOut, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
return err
}
}
if enableAESWhiten {
out, err = o.AESWhitener(ctx, out)
if err != nil {
return err
}
}
start := time.Now()
written, err := o.Read(ctx, out, count, flags)
delta := time.Since(start)
rate := float64(written) / delta.Seconds()
fmt.Fprintf(os.Stderr, "%s written in %s (%s/s)\n", humanize.Bytes(uint64(written)), delta, humanize.Bytes(uint64(rate)))
return err
},
}
cmd.Flags().StringVarP(&readOut, "out", "o", "-", "output file for data (use - for stdout)")
cmd.Flags().BoolVar(&disableAvalanche, "disable-avalanche", false, "Disable noise generation from the Avalanche Diode")
cmd.Flags().BoolVar(&enableRF, "enable-rf", false, "Enable noise generation from RF")
cmd.Flags().BoolVar(&disableWhitener, "disable-whitener", false, "Disable the on-board CRC16 generator")
cmd.Flags().Int64VarP(&count, "count", "n", -1, "Read only N bytes (use -1 for unlimited)")
cmd.Flags().BoolVar(&enableAESWhiten, "aes-whitener", true, "encrypt with AES-128 to 'whiten' the input stream with a random key obtained from the OneRNG")
return cmd
}

64
cmd/onerng/root.go Normal file
View File

@ -0,0 +1,64 @@
package main
import (
"context"
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
cfgFile string
opts config
)
func rootCmd(ctx context.Context) *cobra.Command {
return &cobra.Command{
Use: "onerng [opts] COMMAND",
Short: "Tool for the OneRNG open source hardware entropy generator",
Long: `OneRNG is an open source hardware entropy generator in a USB dongle.
This tool can be used to verify that the OneRNG device operates
correctly, and that the firmware has not been tampered with.`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
cmd.SilenceErrors = true
cmd.SilenceUsage = true
return nil
},
}
}
func initConfig(ctx context.Context, cmd *cobra.Command) {
cmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.go-onerng.yaml)")
opts = config{}
cmd.PersistentFlags().StringVarP(&opts.Device, "device", "d", "/dev/ttyACM0", "the OneRNG device")
cmd.AddCommand(
verifyCmd(ctx),
versionCmd(ctx),
idCmd(ctx),
flushCmd(ctx),
imageCmd(ctx),
initCmd(ctx),
readCmd(ctx),
)
if cfgFile != "" { // enable ability to specify config file via flag
viper.SetConfigFile(cfgFile)
}
viper.SetConfigName(".go-onerng") // name of config file (without extension)
viper.AddConfigPath(os.Getenv("HOME")) // adding home directory as first search path
viper.AutomaticEnv() // read in environment variables that match
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
}
}
type config struct {
Device string
}

98
cmd/onerng/verify.go Normal file
View File

@ -0,0 +1,98 @@
package main
import (
"bytes"
"context"
"github.com/pkg/errors"
"github.com/hairyhenderson/go-onerng"
"github.com/spf13/cobra"
)
const (
publicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
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
=IjnI
-----END PGP PUBLIC KEY BLOCK-----
`
)
func verifyCmd(ctx context.Context) *cobra.Command {
return &cobra.Command{
Use: "verify",
Short: "Verify that OneRNG's firmware has not been tampered with.",
RunE: func(cmd *cobra.Command, args []string) error {
o := onerng.OneRNG{Path: opts.Device}
err := o.Init(ctx)
if err != nil {
return errors.Wrapf(err, "init failed before image verification")
}
image, err := o.Image(ctx)
if err != nil {
return errors.Wrapf(err, "image extraction failed before verification")
}
err = onerng.Verify(ctx, bytes.NewBuffer(image), publicKey)
return err
},
}
}

26
cmd/onerng/version.go Normal file
View File

@ -0,0 +1,26 @@
package main
import (
"context"
"fmt"
"github.com/hairyhenderson/go-onerng"
"github.com/spf13/cobra"
)
// versionCmd represents the version command
func versionCmd(ctx context.Context) *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Display the OneRNG's hardware version",
RunE: func(cmd *cobra.Command, args []string) error {
o := &onerng.OneRNG{Path: opts.Device}
version, err := o.Version(ctx)
if err != nil {
return err
}
fmt.Printf("OneRNG Hardware Version: %d\n", version)
return nil
},
}
}