diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb7d7d5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.build/ + +.idea/ +.vscode/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..51326eb --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +PROJECT ?= $(notdir $(patsubst %/,%,$(CURDIR))) +PACKAGE ?= github.com/andlabs/$(PROJECT) + +GO_SOURCES = $(shell find . -type f \( -iname '*.go' \) \ + -not \( -path "./vendor/*" -path ".*" \) \ + -not \( -path "./_notes/*" -path ".*" \) \ + -not \( -path "./_pre/*" -path ".*" \) \ + -not \( -path "./_sectors/*" -path ".*" \) \ + -not \( -path "./_try/*" -path ".*" \)) + +export GO111MODULE = on + +fmt: $(GO_SOURCES) # format go sources + gofmt -w -s -l $^ + +.build/$(PROJECT).%: $(GO_SOURCES) go.mod + mkdir -p $(@D) + CGO_ENABLED=0 GOOS=$(basename $*) GOARCH=$(patsubst .%,%,$(suffix $*)) go build -o $@ $(PACKAGE) + +.BIN_LOCAL = $(PROJECT).$(shell go env GOOS).$(shell go env GOARCH) + +build: .build/$(.BIN_LOCAL) diff --git a/ata/ata.go b/ata/ata.go index bc88a3b..a34e5fd 100644 --- a/ata/ata.go +++ b/ata/ata.go @@ -11,7 +11,7 @@ func DrivespecUsage() string { } type ATA struct { - s *sysATA + s *sysATA } func Open(drivespec string) (*ATA, error) { @@ -23,30 +23,30 @@ func (a *ATA) Close() error { } type Command28 struct { - Features byte - Count byte - LBALow byte - LBAMid byte - LBAHigh byte - Device byte - Command byte + Features byte + Count byte + LBALow byte + LBAMid byte + LBAHigh byte + Device byte + Command byte } type Response28 struct { - Error byte - Count byte - LBALow byte - LBAMid byte - LBAHigh byte - Device byte - Status byte + Error byte + Count byte + LBALow byte + LBAMid byte + LBAHigh byte + Device byte + Status byte } func (a *ATA) Read28(c *Command28, b []byte) (resp *Response28, n int, err error) { return a.s.Read28(c, b) } -func (a *ATA) Write28(c *Command28, b []byte) (resp *Response28, err eror) { +func (a *ATA) Write28(c *Command28, b []byte) (resp *Response28, err error) { return a.s.Write28(c, b) } diff --git a/ata/ata_default.go b/ata/ata_default.go index ba28e13..f890763 100644 --- a/ata/ata_default.go +++ b/ata/ata_default.go @@ -13,7 +13,7 @@ func sysDrivespecUsage() string { return "This OS does not support sending arbitrary ATA commands to a disk; consequently, there are no valid drivespecs and any command requiring a drivespec will fail." } -type sysATA struct {} +type sysATA struct{} func sysOpen(drivespec string) (*ATA, error) { return nil, ErrUnsupportedOS diff --git a/ata/ata_windows.go b/ata/ata_windows.go index b2aa7bb..3ca9843 100644 --- a/ata/ata_windows.go +++ b/ata/ata_windows.go @@ -2,9 +2,9 @@ package ata import ( - "regexp" "bytes" "encoding/binary" + "regexp" "golang.org/x/sys/windows" ) @@ -36,7 +36,7 @@ func validDrivespec(drivespec string) bool { } type sysATA struct { - handle windows.Handle + handle windows.Handle } func sysOpen(drivespec string) (*ATA, error) { @@ -50,8 +50,8 @@ func sysOpen(drivespec string) (*ATA, error) { } a := new(sysATA) a.handle, err = windows.CreateFile(wdrivespec, - windows.GENERIC_READ | windows.GENERIC_WRITE, - windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE, + windows.GENERIC_READ|windows.GENERIC_WRITE, + windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE, nil, windows.OPEN_EXISTING, 0, nil) @@ -66,24 +66,24 @@ func (a *sysATA) Close() error { } type _ATA_PASS_THROUGH_EX struct { - Length uint16 - AtaFlags uint16 - PathId uint8 - TargetId uint8 - Lun uint8 - ReservedAsUchar uint8 - DataTransferLength uint32 - TimeOutValue uint32 - ReservedAsUlong uint32 - DataBufferOffset _ULONG_PTR - PreviousTaskFile [8]uint8 - CurrentTaskFile [8]uint8 + Length uint16 + AtaFlags uint16 + PathId uint8 + TargetId uint8 + Lun uint8 + ReservedAsUchar uint8 + DataTransferLength uint32 + TimeOutValue uint32 + ReservedAsUlong uint32 + DataBufferOffset _ULONG_PTR + PreviousTaskFile [8]uint8 + CurrentTaskFile [8]uint8 } const ( _ATA_FLAGS_DRDY_REQUIRED = 0x01 - _ATA_FLAGS_DATA_IN =0x02 - _ATA_FLAGS_DATA_OUT = 0x04 + _ATA_FLAGS_DATA_IN = 0x02 + _ATA_FLAGS_DATA_OUT = 0x04 _ATA_FLAGS_48BIT_COMMAND = 0x08 _IOCTL_ATA_PASS_THROUGH = 0x04D02C @@ -98,7 +98,7 @@ func (c *Command28) toNT(flags uint16, buf []byte) (send []byte, err error) { // TODO _ATA_FLAGS_DRDY_REQUIRED? pte.AtaFlags = flags pte.DataTransferLength = uint32(len(buf)) - pte.TimeOutValue = ^uint32(0) // TODO + pte.TimeOutValue = ^uint32(0) // TODO pte.DataBufferOffset = _ULONG_PTR(sizeofPTE) pte.CurrentTaskFile[0] = c.Features pte.CurrentTaskFile[1] = c.Count @@ -121,7 +121,7 @@ func (c *Command28) toNTRead(outbuf []byte) (send []byte, recv []byte, err error if err != nil { return nil, nil, err } - recv = make([]byte, sizeofPTE + len(outbuf)) + recv = make([]byte, sizeofPTE+len(outbuf)) return send, recv, nil } @@ -130,7 +130,7 @@ func (c *Command28) toNTWrite(inbuf []byte) (send []byte, recv []byte, err error if err != nil { return nil, nil, err } - send = make([]byte, len(s) + len(inbuf)) + send = make([]byte, len(s)+len(inbuf)) copy(send[:len(s)], s) copy(send[len(s):], inbuf) recv = make([]byte, sizeofPTE) @@ -138,9 +138,9 @@ func (c *Command28) toNTWrite(inbuf []byte) (send []byte, recv []byte, err error } type out struct { - recv []byte - pte _ATA_PASS_THROUGH_EX - resp *Response28 + recv []byte + pte _ATA_PASS_THROUGH_EX + resp *Response28 } func (a *sysATA) perform(send []byte, recv []byte, err error) (o *out, err error) { @@ -180,9 +180,9 @@ func (a *sysATA) perform(send []byte, recv []byte, err error) (o *out, err error resp.Status = pte.CurrentTaskFile[6] return &out{ - recv: recv[pte.DataBufferOffset:], - pte: pte, - resp: resp, + recv: recv[pte.DataBufferOffset:], + pte: pte, + resp: resp, }, nil } diff --git a/bridge/initio.go b/bridge/initio.go index 32ffc40..9ad7751 100644 --- a/bridge/initio.go +++ b/bridge/initio.go @@ -28,8 +28,8 @@ func (Initio) NeedsKEK() bool { } type InitioKeySector struct { - raw []byte - d struct { // d for "DEK block" + raw []byte + d struct { // d for "DEK block" Magic [4]byte // 27 5D BA 35 Unknown [8]byte Key [32]byte // stored as little-endian longs @@ -55,7 +55,7 @@ func (Initio) DecryptKeySector(keySector []byte, kek []byte) (KeySector, error) } return &InitioKeySector{ - raw: keySector, + raw: keySector, }, nil } diff --git a/bridge/jmicron.go b/bridge/jmicron.go index 9b4f5eb..bfc0af9 100644 --- a/bridge/jmicron.go +++ b/bridge/jmicron.go @@ -28,16 +28,16 @@ func (JMicron) NeedsKEK() bool { } type JMicronKeySector struct { - raw []byte + raw []byte // The names Key3EE2, Key3EF2, and Key3F02 are from the // paper. But I recognize the hex numbers as addresses in the // JMicron chip's RAM. These RAM addresses followed me // around throughout disassembly, and I *knew* they were // suspicious, damnit! - d struct { // d for "DEK block" + d struct { // d for "DEK block" Magic [4]byte // 'DEK1' - Checksum uint16 // TODO check this too? + Checksum uint16 // TODO check this too? Unknown uint16 Random1 uint32 Key3EE2 [16]byte // This is the first half of the AES-256 key. @@ -69,7 +69,7 @@ func (JMicron) DecryptKeySector(keySector []byte, kek []byte) (KeySector, error) } return &JMicronKeySector{ - raw: keySector, + raw: keySector, }, nil } diff --git a/bridge/plx.go b/bridge/plx.go index 805cb6f..413ef02 100644 --- a/bridge/plx.go +++ b/bridge/plx.go @@ -3,8 +3,8 @@ package bridge import ( "bytes" - "encoding/binary" "crypto/aes" + "encoding/binary" "github.com/andlabs/reallymine/byteops" "github.com/andlabs/reallymine/decryptloop" @@ -28,13 +28,13 @@ func (PLX) NeedsKEK() bool { } type PLXKeySector struct { - raw []byte - d struct { - Magic [4]byte - Unknown [0x10]byte - EncryptedDEK [32]byte + raw []byte + d struct { + Magic [4]byte + Unknown [0x10]byte + EncryptedDEK [32]byte } - dek []byte + dek []byte } // MAJOR TODO diff --git a/bridge/symwave.go b/bridge/symwave.go index bd16506..a491295 100644 --- a/bridge/symwave.go +++ b/bridge/symwave.go @@ -29,16 +29,16 @@ func (Symwave) NeedsKEK() bool { } type SymwaveKeySector struct { - raw []byte + raw []byte // The DEK is stored as two separately-wrapped halves. // The KEK is only stored as one. - d struct { - Magic [4]byte - Unknown [0xC]byte - WrappedDEK1 [0x28]byte - WrappedDEK2 [0x28]byte - WrappedKEK [0x28]byte + d struct { + Magic [4]byte + Unknown [0xC]byte + WrappedDEK1 [0x28]byte + WrappedDEK2 [0x28]byte + WrappedKEK [0x28]byte } } @@ -56,7 +56,7 @@ var symwaveKEKWrappingKey = []byte{ func (Symwave) DecryptKeySector(keySector []byte, kek []byte) (KeySector, error) { return &SymwaveKeySector{ - raw: byteops.DupBytes(keySector), + raw: byteops.DupBytes(keySector), }, nil } @@ -95,7 +95,7 @@ func (ks *SymwaveKeySector) DEK() (dek []byte, err error) { } dek = byteops.DupBytes(dek1) - _ = dek2 // doesn't seem to be used + _ = dek2 // doesn't seem to be used // And finally we just need one last endian correction... byteops.SwapLongs(dek) return dek, nil diff --git a/byteops/byteops_test.go b/byteops/byteops_test.go index 33c81ee..6f54db0 100644 --- a/byteops/byteops_test.go +++ b/byteops/byteops_test.go @@ -18,48 +18,48 @@ func runOne(t *testing.T, input []byte, expected []byte, name string, op func([] } type testset []struct { - Input []byte - Reverse []byte - SwapWords []byte - SwapLongs []byte - SwapHalves []byte + Input []byte + Reverse []byte + SwapWords []byte + SwapLongs []byte + SwapHalves []byte } var tests = testset{ { - Input: []byte{}, - Reverse: []byte{}, - SwapWords: []byte{}, - SwapLongs: []byte{}, - SwapHalves: []byte{}, + Input: []byte{}, + Reverse: []byte{}, + SwapWords: []byte{}, + SwapLongs: []byte{}, + SwapHalves: []byte{}, }, { - Input: []byte{ 0xEE, 0xFF }, - Reverse: []byte{ 0xFF, 0xEE }, - SwapWords: []byte{ 0xFF, 0xEE }, - SwapLongs: nil, // not an even number of longs - SwapHalves: []byte{ 0xFF, 0xEE }, + Input: []byte{0xEE, 0xFF}, + Reverse: []byte{0xFF, 0xEE}, + SwapWords: []byte{0xFF, 0xEE}, + SwapLongs: nil, // not an even number of longs + SwapHalves: []byte{0xFF, 0xEE}, }, { - Input: []byte{ 0xCC, 0xDD, 0xEE, 0xFF }, - Reverse: []byte{ 0xFF, 0xEE, 0xDD, 0xCC }, - SwapWords: []byte{ 0xDD, 0xCC, 0xFF, 0xEE }, - SwapLongs: []byte{ 0xFF, 0xEE, 0xDD, 0xCC }, - SwapHalves: []byte{ 0xEE, 0xFF, 0xCC, 0xDD }, + Input: []byte{0xCC, 0xDD, 0xEE, 0xFF}, + Reverse: []byte{0xFF, 0xEE, 0xDD, 0xCC}, + SwapWords: []byte{0xDD, 0xCC, 0xFF, 0xEE}, + SwapLongs: []byte{0xFF, 0xEE, 0xDD, 0xCC}, + SwapHalves: []byte{0xEE, 0xFF, 0xCC, 0xDD}, }, { - Input: []byte{ 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, - Reverse: []byte{ 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA }, - SwapWords: []byte{ 0xBB, 0xAA, 0xDD, 0xCC, 0xFF, 0xEE }, - SwapLongs: nil, // not an even number of longs - SwapHalves: []byte{ 0xDD, 0xEE, 0xFF, 0xAA, 0xBB, 0xCC }, + Input: []byte{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, + Reverse: []byte{0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA}, + SwapWords: []byte{0xBB, 0xAA, 0xDD, 0xCC, 0xFF, 0xEE}, + SwapLongs: nil, // not an even number of longs + SwapHalves: []byte{0xDD, 0xEE, 0xFF, 0xAA, 0xBB, 0xCC}, }, { - Input: []byte{ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, - Reverse: []byte{ 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88 }, - SwapWords: []byte{ 0x99, 0x88, 0xBB, 0xAA, 0xDD, 0xCC, 0xFF, 0xEE }, - SwapLongs: []byte{ 0xBB, 0xAA, 0x99, 0x88, 0xFF, 0xEE, 0xDD, 0xCC }, - SwapHalves: []byte{ 0xCC, 0xDD, 0xEE, 0xFF, 0x88, 0x99, 0xAA, 0xBB }, + Input: []byte{0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, + Reverse: []byte{0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88}, + SwapWords: []byte{0x99, 0x88, 0xBB, 0xAA, 0xDD, 0xCC, 0xFF, 0xEE}, + SwapLongs: []byte{0xBB, 0xAA, 0x99, 0x88, 0xFF, 0xEE, 0xDD, 0xCC}, + SwapHalves: []byte{0xCC, 0xDD, 0xEE, 0xFF, 0x88, 0x99, 0xAA, 0xBB}, }, // TODO more tests } diff --git a/command/args.go b/command/args.go index 2cd2143..e4e0f6f 100644 --- a/command/args.go +++ b/command/args.go @@ -1,39 +1,44 @@ -// 22 october 2015 +// 08 March 2021 package command import ( + "bufio" + "encoding/hex" "fmt" - "os" "io" "io/ioutil" + "os" "reflect" - "encoding/hex" + "github.com/andlabs/reallymine/decryptloop" "github.com/andlabs/reallymine/disk" "github.com/andlabs/reallymine/kek" - "github.com/andlabs/reallymine/decryptloop" ) // DiskSize is passed as the size parameter to disk.Open() when an // argument of type ArgDisk is processed. var DiskSize int64 = -1 -type argout struct { - obj reflect.Value - deferfunc func() +// Size of the write buffer, that would accumulate the data before writing it onto the destination. +// 10MB is a reasonable default. +var WriteBufSize = 10 * 1024 * 1024 + +type argOut struct { + obj reflect.Value + deferFunc func() } // This complicated structure allows us to define a fixed set of Arg objects and disallow nil at the same time, reducing the number of things that need validation. -type argiface interface { +type argInterface interface { name() string desc() string - argtype() reflect.Type - prepare(arg string) (out *argout, err error) + argType() reflect.Type + prepare(arg string) (out *argOut, err error) } type arg struct { - a argiface + a argInterface } type Arg arg @@ -42,20 +47,20 @@ type Arg arg var validArgs []Arg // TODO complain if any arguments have duplicated names -func addarg(a argiface) Arg { +func addarg(a argInterface) Arg { aa := Arg{a} validArgs = append(validArgs, aa) return aa } var ( - typeDisk = reflect.TypeOf((*disk.Disk)(nil)) - typeWriter = reflect.TypeOf((*io.Writer)(nil)).Elem() - typeFile = reflect.TypeOf((*os.File)(nil)) - typeAsker = reflect.TypeOf((*kek.Asker)(nil)) + typeDisk = reflect.TypeOf((*disk.Disk)(nil)) + typeWriter = reflect.TypeOf((*io.Writer)(nil)).Elem() + typeFile = reflect.TypeOf((*os.File)(nil)) + typeAsker = reflect.TypeOf((*kek.Asker)(nil)) typeByteSlice = reflect.TypeOf([]byte(nil)) - typeReader = reflect.TypeOf((*io.Reader)(nil)).Elem() - typeStepList = reflect.TypeOf(decryptloop.StepList(nil)) + typeReader = reflect.TypeOf((*io.Reader)(nil)).Elem() + typeStepList = reflect.TypeOf(decryptloop.StepList(nil)) ) type argDiskType struct{} @@ -68,18 +73,18 @@ func (argDiskType) desc() string { return fmt.Sprintf("The filename of a disk device or disk image. The file must exist and must have a size which is a multiple of the sector size (%d bytes).", disk.SectorSize) } -func (argDiskType) argtype() reflect.Type { +func (argDiskType) argType() reflect.Type { return typeDisk } -func (argDiskType) prepare(arg string) (out *argout, err error) { +func (argDiskType) prepare(arg string) (out *argOut, err error) { d, err := disk.Open(arg, DiskSize) if err != nil { return nil, err } - out = new(argout) + out = new(argOut) out.obj = reflect.ValueOf(d) - out.deferfunc = func() { + out.deferFunc = func() { d.Close() } return out, nil @@ -98,11 +103,11 @@ func (argOutFileType) desc() string { return "Either the name of a file to dump the raw data to or - to perform a hexdump on stdout." } -func (argOutFileType) argtype() reflect.Type { +func (argOutFileType) argType() reflect.Type { return typeWriter } -func (argOutFileType) prepare(arg string) (out *argout, err error) { +func (argOutFileType) prepare(arg string) (out *argOut, err error) { var of io.WriteCloser if arg == "-" { @@ -114,9 +119,9 @@ func (argOutFileType) prepare(arg string) (out *argout, err error) { } of = f } - out = new(argout) + out = new(argOut) out.obj = reflect.ValueOf(of) - out.deferfunc = func() { + out.deferFunc = func() { // TODO catch the error in the case of stdout? // TODO we need to worry about multiplexing then of.Close() @@ -138,18 +143,22 @@ func (argOutImageType) desc() string { } // TODO use typeFile? -func (argOutImageType) argtype() reflect.Type { +func (argOutImageType) argType() reflect.Type { return typeWriter } -func (argOutImageType) prepare(arg string) (out *argout, err error) { - f, err := os.OpenFile(arg, os.O_WRONLY | os.O_CREATE | os.O_EXCL, 0644) +func (argOutImageType) prepare(arg string) (out *argOut, err error) { + f, err := os.OpenFile(arg, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) if err != nil { return nil, err } - out = new(argout) - out.obj = reflect.ValueOf(f) - out.deferfunc = func() { + + writer := bufio.NewWriterSize(f, WriteBufSize) + + out = new(argOut) + out.obj = reflect.ValueOf(writer) + out.deferFunc = func() { + writer.Flush() f.Close() } return out, nil @@ -168,18 +177,18 @@ func (argKEKType) desc() string { return kek.AskerDescription } -func (argKEKType) argtype() reflect.Type { +func (argKEKType) argType() reflect.Type { return typeAsker } -func (argKEKType) prepare(arg string) (out *argout, err error) { +func (argKEKType) prepare(arg string) (out *argOut, err error) { asker, err := kek.NewAsker(arg) if err != nil { return nil, err } - out = new(argout) + out = new(argOut) out.obj = reflect.ValueOf(asker) - out.deferfunc = func() {} + out.deferFunc = func() {} return out, nil } @@ -196,18 +205,18 @@ func (argDEKType) desc() string { return "A hexadecimal string to use as the DEK." } -func (argDEKType) argtype() reflect.Type { +func (argDEKType) argType() reflect.Type { return typeByteSlice } -func (argDEKType) prepare(arg string) (out *argout, err error) { +func (argDEKType) prepare(arg string) (out *argOut, err error) { b, err := hex.DecodeString(arg) if err != nil { return nil, err } - out = new(argout) + out = new(argOut) out.obj = reflect.ValueOf(b) - out.deferfunc = func() {} + out.deferFunc = func() {} return out, nil } @@ -224,11 +233,11 @@ func (argInFileType) desc() string { return "Either the name of a file to read from or - to read from stdin." } -func (argInFileType) argtype() reflect.Type { +func (argInFileType) argType() reflect.Type { return typeReader } -func (argInFileType) prepare(arg string) (out *argout, err error) { +func (argInFileType) prepare(arg string) (out *argOut, err error) { var inf io.ReadCloser if arg == "-" { @@ -241,9 +250,9 @@ func (argInFileType) prepare(arg string) (out *argout, err error) { } inf = f } - out = new(argout) + out = new(argOut) out.obj = reflect.ValueOf(inf) - out.deferfunc = func() { + out.deferFunc = func() { inf.Close() } return out, nil @@ -262,18 +271,18 @@ func (argDecryptionStepsType) desc() string { return "A space-delimited list of decryption steps. Must not be empty. Because this is space-delimited, wrap this argument in quotes to have your shell treat the list as one argument." } -func (argDecryptionStepsType) argtype() reflect.Type { +func (argDecryptionStepsType) argType() reflect.Type { return typeStepList } -func (argDecryptionStepsType) prepare(arg string) (out *argout, err error) { +func (argDecryptionStepsType) prepare(arg string) (out *argOut, err error) { steps, err := decryptloop.StepListFromString(arg) if err != nil { return nil, err } - out = new(argout) + out = new(argOut) out.obj = reflect.ValueOf(steps) - out.deferfunc = func() {} + out.deferFunc = func() {} return out, nil } @@ -283,11 +292,11 @@ var ArgDecryptionSteps Arg = argDecryptionSteps // for command.go func (a Arg) argtype() reflect.Type { - return a.a.argtype() + return a.a.argType() } -// TODO rename argout and fields to something more sane for command.go -func (a Arg) prepare(arg string) (*argout, error) { +// TODO rename argOut and fields to something more sane for command.go +func (a Arg) prepare(arg string) (*argOut, error) { return a.a.prepare(arg) } diff --git a/command/command.go b/command/command.go index 95ddcea..ac58710 100644 --- a/command/command.go +++ b/command/command.go @@ -3,15 +3,15 @@ package command import ( "fmt" - "strings" "reflect" + "strings" ) type Command struct { - Name string - Args []Arg - Description string - Do interface{} + Name string + Args []Arg + Description string + Do interface{} } var ( @@ -93,7 +93,7 @@ func (c *Command) Invoke(args []string) error { if err != nil { return err } - defer out.deferfunc() + defer out.deferFunc() fa[i] = out.obj } out := fv.Call(fa) @@ -112,7 +112,7 @@ func Validate(commands []*Command) (problems []string) { for _, c := range commands { problems = append(problems, c.validate()...) if seen[c.Name] { - problems = append(problems, c.Name + " declared more than once") + problems = append(problems, c.Name+" declared more than once") } seen[c.Name] = true } diff --git a/command/usage.go b/command/usage.go index f5417e5..1aefd99 100644 --- a/command/usage.go +++ b/command/usage.go @@ -49,7 +49,7 @@ func wrapL2(s string) (wrapped []string) { } wrappedLine = candidate } - if wrappedLine != "" { // add the last line + if wrappedLine != "" { // add the last line wrapped = append(wrapped, wrappedLine) } } @@ -58,5 +58,5 @@ func wrapL2(s string) (wrapped []string) { func ToFlagUsage(s string) string { wrapped := wrapL2(s) - return strings.Join(wrapped, "\n" + prefixL2) + return strings.Join(wrapped, "\n"+prefixL2) } diff --git a/decrypter.go b/decrypter.go index a58e416..14557d7 100644 --- a/decrypter.go +++ b/decrypter.go @@ -2,28 +2,28 @@ package main import ( + "crypto/aes" "fmt" "io" - "crypto/aes" - "github.com/andlabs/reallymine/disk" "github.com/andlabs/reallymine/bridge" - "github.com/andlabs/reallymine/kek" "github.com/andlabs/reallymine/decryptloop" + "github.com/andlabs/reallymine/disk" + "github.com/andlabs/reallymine/kek" ) // TODO rename this type type Decrypter struct { - Disk *disk.Disk - Out io.Writer + Disk *disk.Disk + Out io.Writer - EncryptedKeySector []byte - KeySectorPos int64 - Bridge bridge.Bridge + EncryptedKeySector []byte + KeySectorPos int64 + Bridge bridge.Bridge - KEK []byte - KeySector bridge.KeySector - DEK []byte + KEK []byte + KeySector bridge.KeySector + DEK []byte } func (d *Decrypter) FindKeySector() error { diff --git a/decryptloop/decryptloop.go b/decryptloop/decryptloop.go index 8f3449a..c7538df 100644 --- a/decryptloop/decryptloop.go +++ b/decryptloop/decryptloop.go @@ -2,24 +2,24 @@ package decryptloop import ( - "io" "crypto/cipher" + "io" ) type DecryptLoop struct { - steps StepList - c cipher.Block - buf []byte - pos int - out io.Writer + steps StepList + c cipher.Block + buf []byte + pos int + out io.Writer } func New(steps StepList, c cipher.Block, out io.Writer) *DecryptLoop { return &DecryptLoop{ - steps: steps, - c: c, - buf: make([]byte, c.BlockSize()), - out: out, + steps: steps, + c: c, + buf: make([]byte, c.BlockSize()), + out: out, } } diff --git a/decryptloop/steps.go b/decryptloop/steps.go index 45f9300..b013241 100644 --- a/decryptloop/steps.go +++ b/decryptloop/steps.go @@ -2,8 +2,8 @@ package decryptloop import ( - "fmt" "crypto/cipher" + "fmt" "strings" "github.com/andlabs/reallymine/byteops" @@ -12,13 +12,13 @@ import ( // This complicated structure allows us to define a fixed set of Step objects and disallow nil at the same time, reducing the number of things that need validation. type stepiface interface { - name() string - desc() string + name() string + desc() string do(c cipher.Block, b []byte) } type step struct { - s stepiface + s stepiface } type Step step diff --git a/disk/disk.go b/disk/disk.go index 6d17f94..22515f9 100644 --- a/disk/disk.go +++ b/disk/disk.go @@ -3,16 +3,16 @@ package disk import ( "fmt" - "os" "io" + "os" ) const SectorSize = 512 // Disk is currently not safe for concurrent use. type Disk struct { - r *io.SectionReader - close func() error + r *io.SectionReader + close func() error } func Open(filename string, size int64) (d *Disk, err error) { @@ -33,12 +33,12 @@ func Open(filename string, size int64) (d *Disk, err error) { } else if size > realsize { return errfail(fmt.Errorf("requested disk size larger than actual disk size")) } - if size % SectorSize != 0 { + if size%SectorSize != 0 { return errfail(fmt.Errorf("disk size is not a multiple of the sector size; this is likely not a disk")) } return &Disk{ - r: io.NewSectionReader(f, 0, size), - close: f.Close, + r: io.NewSectionReader(f, 0, size), + close: f.Close, }, nil } @@ -51,15 +51,15 @@ func (d *Disk) Size() int64 { } func (d *Disk) ReadSectorsAt(sectors []byte, pos int64) (int, error) { - if len(sectors) % SectorSize != 0 { - return 0, io.ErrShortBuffer // TODO better error? + if len(sectors)%SectorSize != 0 { + return 0, io.ErrShortBuffer // TODO better error? } n, err := d.r.ReadAt(sectors, pos) if err == io.EOF { - if n == 0 { // this is truly the end of the disk + if n == 0 { // this is truly the end of the disk return 0, io.EOF } - if n % SectorSize != 0 { + if n%SectorSize != 0 { return n, io.ErrUnexpectedEOF } // Allow a short read at the end of the disk; the next call @@ -78,21 +78,21 @@ func (d *Disk) ReadSectorsAt(sectors []byte, pos int64) (int, error) { } type SectorIter struct { - d *Disk - sectors []byte - pos int64 - incr int // in units of len(sectors) - eof bool - err error + d *Disk + sectors []byte + pos int64 + incr int // in units of len(sectors) + eof bool + err error } func (d *Disk) mkiter(startAt int64, countPer int, reverse bool) (*SectorIter, error) { - if startAt % SectorSize != 0 { + if startAt%SectorSize != 0 { return nil, fmt.Errorf("startAt must be sector-aligned") } s := new(SectorIter) s.d = d - s.sectors = make([]byte, countPer * SectorSize) + s.sectors = make([]byte, countPer*SectorSize) if reverse { // The first call to Next() will push s.pos to the last block. s.pos = startAt @@ -128,7 +128,7 @@ func (s *SectorIter) Next() bool { s.err = err return false } - s.sectors = s.sectors[:n] // trim short last read + s.sectors = s.sectors[:n] // trim short last read return true } diff --git a/format.go b/format.go index c60e7fb..85e38dc 100644 --- a/format.go +++ b/format.go @@ -2,8 +2,8 @@ package main import ( - "fmt" "encoding/hex" + "fmt" "strings" "github.com/andlabs/reallymine/bridge" diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..38978ff --- /dev/null +++ b/go.mod @@ -0,0 +1,11 @@ +module github.com/andlabs/reallymine + +go 1.15 + +require ( + github.com/hashicorp/vault/sdk v0.1.13 + github.com/mendsley/gojwe v0.0.0-20140920044104-be41449a9adb + golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect + golang.org/x/sys v0.0.0-20210303074136-134d130e1a04 + golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..0b88478 --- /dev/null +++ b/go.sum @@ -0,0 +1,106 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= +github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/vault/sdk v0.1.13 h1:mOEPeOhT7jl0J4AMl1E705+BcmeRs1VmKNb9F0sMLy8= +github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mendsley/gojwe v0.0.0-20140920044104-be41449a9adb h1:xYLj/OPCHZ3fOshFlr0RBkzNILGKQYerpoofuz1Qm0w= +github.com/mendsley/gojwe v0.0.0-20140920044104-be41449a9adb/go.mod h1:9yr/ISU7qJ8QYGhlZZEfA/fKvdhdRcc5IXfMSx21TpI= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04 h1:cEhElsAv9LUt9ZUUocxzWe05oFLVd+AA2nstydTeI8g= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/kek/asker.go b/kek/asker.go index 685e32d..c6a525a 100644 --- a/kek/asker.go +++ b/kek/asker.go @@ -2,9 +2,9 @@ package kek import ( + "encoding/hex" "fmt" "os" - "encoding/hex" "github.com/hashicorp/vault/sdk/helper/password" ) @@ -27,14 +27,14 @@ func askUser(note string, repeat bool) askfn { } type Asker struct { - fns []askfn - kek []byte - err error + fns []askfn + kek []byte + err error } func mkasker(fns ...askfn) (*Asker, error) { return &Asker{ - fns: fns, + fns: fns, }, nil } @@ -63,9 +63,9 @@ func NewAsker(cmdstr string) (a *Asker, err error) { } const ( - AskReal = "-real" - AskOnce = "-askonce" - AskOnly = "-onlyask" + AskReal = "-real" + AskOnce = "-askonce" + AskOnly = "-onlyask" AskDefault = "-default" ) @@ -81,8 +81,8 @@ func realAskUser(note string) (kek []byte, err error) { } fmt.Print("Enter WD password: ") pw, err := password.Read(os.Stdin) - fmt.Println() // because password.Read() doesn't - if err != nil { // including cancelled + fmt.Println() // because password.Read() doesn't + if err != nil { // including cancelled return nil, err } return FromPassword(pw), nil @@ -101,7 +101,7 @@ func (a *Asker) Ask() bool { if a.err != nil { return false } - if !repeat { // no more from this one, advance to the next one + if !repeat { // no more from this one, advance to the next one a.fns = a.fns[1:] } return true diff --git a/main.go b/main.go index 1ce5def..4658e29 100644 --- a/main.go +++ b/main.go @@ -1,15 +1,15 @@ -// 22 october 2015 +// 8 March 2021 package main import ( + "flag" "fmt" "os" - "flag" "strings" "github.com/andlabs/reallymine/command" - "github.com/andlabs/reallymine/disk" "github.com/andlabs/reallymine/decryptloop" + "github.com/andlabs/reallymine/disk" ) func errf(format string, args ...interface{}) { @@ -44,8 +44,30 @@ func init() { } func init() { - flag.Int64Var(&command.DiskSize, "disk-size", -1, - command.ToFlagUsage(fmt.Sprintf("Overrides the size of the disk to use, allowing you to pretend the disk is smaller than it is. This value must be less than or equal to the disk's actual size, and must be a multiple of the sector size (%d bytes). If the size is -1, the disk's actual size is used.", disk.SectorSize))) + flag.Int64Var( + &command.DiskSize, + "disk-size", + -1, + command.ToFlagUsage( + fmt.Sprintf( + "Overrides the size of the disk to use, allowing you to pretend the disk is smaller than it "+ + "is. This value must be less than or equal to the disk's actual size, and must be a multiple of "+ + "the sector size (%d bytes). If the size is -1, the disk's actual size is used.", + disk.SectorSize, + ), + ), + ) + flag.IntVar( + &command.WriteBufSize, + "write-buf-size", + 10*1024*1024, + command.ToFlagUsage( + "Overrides the size of write buffer to be used during the encryption. The bigger the buffer, the "+ + "bigger chunks would be first decrypted into memory and then written to disk. You might want to set "+ + "the value higher, if the destination device is slow, to minimize the number of writes, else it "+ + "would not make much of a difference.", + ), + ) } func usage() { diff --git a/researchcommands.go b/researchcommands.go index f882c77..68d731a 100644 --- a/researchcommands.go +++ b/researchcommands.go @@ -2,16 +2,16 @@ package main import ( - "fmt" - "io" "bytes" "crypto/aes" + "fmt" + "io" + "github.com/andlabs/reallymine/bridge" "github.com/andlabs/reallymine/command" + "github.com/andlabs/reallymine/decryptloop" "github.com/andlabs/reallymine/disk" - "github.com/andlabs/reallymine/bridge" "github.com/andlabs/reallymine/kek" - "github.com/andlabs/reallymine/decryptloop" ) var zeroSector [disk.SectorSize]byte @@ -47,16 +47,16 @@ func cDumpLast(d *disk.Disk, out io.Writer) error { } var dumplast = &command.Command{ - Name: "dumplast", - Args: []command.Arg{command.ArgDisk, command.ArgOutFile}, - Description: "Dumps the last non-zero sector on %s to %s.", - Do: cDumpLast, + Name: "dumplast", + Args: []command.Arg{command.ArgDisk, command.ArgOutFile}, + Description: "Dumps the last non-zero sector on %s to %s.", + Do: cDumpLast, } func cDecryptKeySector(d *disk.Disk, out io.Writer, a *kek.Asker) error { dec := &Decrypter{ - Disk: d, - Out: out, + Disk: d, + Out: out, } err := dec.FindKeySector() if err != nil { @@ -85,17 +85,17 @@ func cDumpKeySector(d *disk.Disk, out io.Writer) error { } var dumpkeysector = &command.Command{ - Name: "dumpkeysector", - Args: []command.Arg{command.ArgDisk, command.ArgOutFile}, - Description: "Identifies and dumps the key sector on %s to %s.", - Do: cDumpKeySector, + Name: "dumpkeysector", + Args: []command.Arg{command.ArgDisk, command.ArgOutFile}, + Description: "Identifies and dumps the key sector on %s to %s.", + Do: cDumpKeySector, } var decryptkeysector = &command.Command{ - Name: "decryptkeysector", - Args: []command.Arg{command.ArgDisk, command.ArgOutFile, command.ArgKEK}, - Description: "Identifies, decrypts, and dumps the key sector on %s to %s using %s.", - Do: cDecryptKeySector, + Name: "decryptkeysector", + Args: []command.Arg{command.ArgDisk, command.ArgOutFile, command.ArgKEK}, + Description: "Identifies, decrypts, and dumps the key sector on %s to %s using %s.", + Do: cDecryptKeySector, } const firstSectorsCount = 64 @@ -114,12 +114,12 @@ func cDumpFirst(d *disk.Disk, out io.Writer) error { } var dumpfirst = &command.Command{ - Name: "dumpfirst", - Args: []command.Arg{command.ArgDisk, command.ArgOutFile}, - Description: "Dumps the first " + - fmt.Sprintf("%d sectors (%d bytes)", firstSectorsCount, firstSectorsCount * disk.SectorSize) + + Name: "dumpfirst", + Args: []command.Arg{command.ArgDisk, command.ArgOutFile}, + Description: "Dumps the first " + + fmt.Sprintf("%d sectors (%d bytes)", firstSectorsCount, firstSectorsCount*disk.SectorSize) + " on %s to %s without decrypting.", - Do: cDumpFirst, + Do: cDumpFirst, } func cDecryptFile(in io.Reader, out io.Writer, dek []byte, steps decryptloop.StepList) error { @@ -139,8 +139,8 @@ func cDecryptFile(in io.Reader, out io.Writer, dek []byte, steps decryptloop.Ste } var decryptfile = &command.Command{ - Name: "decryptfile", - Args: []command.Arg{command.ArgInFile, command.ArgOutFile, command.ArgDEK, command.ArgDecryptionSteps}, - Description: "Decrypts %s to %s using the provided %s and %s.", - Do: cDecryptFile, + Name: "decryptfile", + Args: []command.Arg{command.ArgInFile, command.ArgOutFile, command.ArgDEK, command.ArgDecryptionSteps}, + Description: "Decrypts %s to %s using the provided %s and %s.", + Do: cDecryptFile, } diff --git a/usercommands.go b/usercommands.go index 40febfa..0ef8c8c 100644 --- a/usercommands.go +++ b/usercommands.go @@ -12,8 +12,8 @@ import ( func runUntilDEK(d *disk.Disk, out io.Writer) (dec *Decrypter, err error) { dec = &Decrypter{ - Disk: d, - Out: out, + Disk: d, + Out: out, } err = dec.FindKeySector() if err != nil { @@ -44,10 +44,10 @@ func cGetDEK(d *disk.Disk) error { } var getdek = &command.Command{ - Name: "getdek", - Args: []command.Arg{command.ArgDisk}, - Description: "Gets the DEK and decryption steps to use on %s and prints it on stdout.", - Do: cGetDEK, + Name: "getdek", + Args: []command.Arg{command.ArgDisk}, + Description: "Gets the DEK and decryption steps to use on %s and prints it on stdout.", + Do: cGetDEK, } func cDecrypt(d *disk.Disk, out io.Writer) error { @@ -59,8 +59,8 @@ func cDecrypt(d *disk.Disk, out io.Writer) error { } var decrypt = &command.Command{ - Name: "decrypt", - Args: []command.Arg{command.ArgDisk, command.ArgOutImage}, - Description: "Decrypts the entire disk %s to %s.", - Do: cDecrypt, + Name: "decrypt", + Args: []command.Arg{command.ArgDisk, command.ArgOutImage}, + Description: "Decrypts the entire disk %s to %s.", + Do: cDecrypt, }