@@ -16,23 +16,29 @@ import (
16
16
)
17
17
18
18
const (
19
- ivLen = contentenc .DefaultIVBits / 8
20
- blockSize = contentenc .DefaultBS + ivLen + cryptocore .AuthTagLen
21
- myName = "gocryptfs-xray"
19
+ ivLen = contentenc .DefaultIVBits / 8
20
+ authTagLen = cryptocore .AuthTagLen
21
+ blockSize = contentenc .DefaultBS + ivLen + cryptocore .AuthTagLen
22
+ myName = "gocryptfs-xray"
22
23
)
23
24
24
25
func errExit (err error ) {
25
26
fmt .Println (err )
26
27
os .Exit (1 )
27
28
}
28
29
29
- func prettyPrintHeader (h * contentenc.FileHeader ) {
30
+ func prettyPrintHeader (h * contentenc.FileHeader , aessiv bool ) {
30
31
id := hex .EncodeToString (h .ID )
31
- fmt .Printf ("Header: Version: %d, Id: %s\n " , h .Version , id )
32
+ msg := "Header: Version: %d, Id: %s"
33
+ if aessiv {
34
+ msg += ", assuming AES-SIV mode"
35
+ }
36
+ fmt .Printf (msg + "\n " , h .Version , id )
32
37
}
33
38
34
39
func main () {
35
40
dumpmasterkey := flag .Bool ("dumpmasterkey" , false , "Decrypt and dump the master key" )
41
+ aessiv := flag .Bool ("aessiv" , false , "Assume AES-SIV mode instead of AES-GCM" )
36
42
flag .Parse ()
37
43
if flag .NArg () != 1 {
38
44
fmt .Fprintf (os .Stderr , "Usage: %s [OPTIONS] FILE\n " +
@@ -54,7 +60,7 @@ func main() {
54
60
if * dumpmasterkey {
55
61
dumpMasterKey (fn )
56
62
} else {
57
- inspectCiphertext (fd )
63
+ inspectCiphertext (fd , * aessiv )
58
64
}
59
65
}
60
66
@@ -72,7 +78,7 @@ func dumpMasterKey(fn string) {
72
78
}
73
79
}
74
80
75
- func inspectCiphertext (fd * os.File ) {
81
+ func inspectCiphertext (fd * os.File , aessiv bool ) {
76
82
headerBytes := make ([]byte , contentenc .HeaderLen )
77
83
n , err := fd .ReadAt (headerBytes , 0 )
78
84
if err == io .EOF && n == 0 {
@@ -88,34 +94,30 @@ func inspectCiphertext(fd *os.File) {
88
94
if err != nil {
89
95
errExit (err )
90
96
}
91
- prettyPrintHeader (header )
97
+ prettyPrintHeader (header , aessiv )
92
98
var i int64
99
+ buf := make ([]byte , blockSize )
93
100
for i = 0 ; ; i ++ {
94
- blockLen := int64 (blockSize )
95
101
off := contentenc .HeaderLen + i * blockSize
96
- iv := make ([]byte , ivLen )
97
- _ , err := fd .ReadAt (iv , off )
98
- if err == io .EOF {
99
- break
100
- } else if err != nil {
102
+ n , err := fd .ReadAt (buf , off )
103
+ if err != nil && err != io .EOF {
101
104
errExit (err )
102
105
}
103
- tag := make ([]byte , cryptocore .AuthTagLen )
104
- _ , err = fd .ReadAt (tag , off + blockSize - cryptocore .AuthTagLen )
105
- if err == io .EOF {
106
- fi , err2 := fd .Stat ()
107
- if err2 != nil {
108
- errExit (err2 )
109
- }
110
- _ , err2 = fd .ReadAt (tag , fi .Size ()- cryptocore .AuthTagLen )
111
- if err2 != nil {
112
- errExit (err2 )
113
- }
114
- blockLen = (fi .Size () - contentenc .HeaderLen ) % blockSize
115
- } else if err != nil {
116
- errExit (err )
106
+ if n == 0 && err == io .EOF {
107
+ break
108
+ }
109
+ // A block contains at least the IV, the Auth Tag and 1 data byte
110
+ if n < ivLen + authTagLen + 1 {
111
+ errExit (fmt .Errorf ("corrupt block: truncated data, len=%d" , n ))
112
+ }
113
+ data := buf [:n ]
114
+ // Parse block data
115
+ iv := data [:ivLen ]
116
+ tag := data [len (data )- authTagLen :]
117
+ if aessiv {
118
+ tag = data [ivLen : ivLen + authTagLen ]
117
119
}
118
120
fmt .Printf ("Block %2d: IV: %s, Tag: %s, Offset: %5d Len: %d\n " ,
119
- i , hex .EncodeToString (iv ), hex .EncodeToString (tag ), off , blockLen )
121
+ i , hex .EncodeToString (iv ), hex .EncodeToString (tag ), off , len ( data ) )
120
122
}
121
123
}
0 commit comments