aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2016-09-25 11:20:10 +0200
committerJakob Unterwurzacher2016-09-25 16:43:17 +0200
commit7bbf6ad6eae47974b1162af13915785a541b9bb9 (patch)
tree88371ab9828c0dd415d78db1999267afd5432913
parent3a9bd92754e3b6984c97f7012fd5f030d7f8e46c (diff)
reverse: derive file ID and block IVs from file paths
-rw-r--r--internal/contentenc/content.go19
-rw-r--r--internal/fusefrontend_reverse/reverse_diriv.go9
-rw-r--r--internal/fusefrontend_reverse/reverse_longnames.go2
-rw-r--r--internal/fusefrontend_reverse/rfile.go34
-rw-r--r--internal/fusefrontend_reverse/rfs.go12
-rw-r--r--internal/fusefrontend_reverse/rpath.go2
6 files changed, 41 insertions, 37 deletions
diff --git a/internal/contentenc/content.go b/internal/contentenc/content.go
index c638221..98037d0 100644
--- a/internal/contentenc/content.go
+++ b/internal/contentenc/content.go
@@ -19,9 +19,9 @@ const (
// We always use 128-bit IVs for file content encryption
IVBitLen = 128
- _ = iota // skip zero
- RandomNonce NonceMode = iota
- ReverseDummyNonce NonceMode = iota
+ _ = iota // skip zero
+ RandomNonce NonceMode = iota
+ ReverseDeterministicNonce NonceMode = iota
)
type ContentEnc struct {
@@ -147,12 +147,17 @@ func (be *ContentEnc) EncryptBlock(plaintext []byte, blockNo uint64, fileID []by
var nonce []byte
switch nMode {
- case ReverseDummyNonce:
+ case ReverseDeterministicNonce:
if be.cryptoCore.AEADBackend != cryptocore.BackendGCMSIV {
- panic("MUST NOT use dummy nonces unless in GCMSIV mode!")
+ panic("MUST NOT use deterministic nonces unless in GCMSIV mode!")
}
- nonce = make([]byte, IVBitLen/8)
- binary.BigEndian.PutUint64(nonce, blockNo)
+ l := IVBitLen / 8
+ nonce = make([]byte, l)
+ copy(nonce, fileID)
+ // Add the block number to the last 8 byte. Plus one so the block-zero
+ // IV is distinct from the fileID.
+ counter := binary.BigEndian.Uint64(nonce[l-8 : l])
+ binary.BigEndian.PutUint64(nonce[l-8:l], counter+blockNo+1)
case RandomNonce:
// Get a fresh random nonce
nonce = be.cryptoCore.IVGenerator.Get()
diff --git a/internal/fusefrontend_reverse/reverse_diriv.go b/internal/fusefrontend_reverse/reverse_diriv.go
index df3a4d1..88d0680 100644
--- a/internal/fusefrontend_reverse/reverse_diriv.go
+++ b/internal/fusefrontend_reverse/reverse_diriv.go
@@ -9,10 +9,9 @@ import (
"github.com/rfjakob/gocryptfs/internal/nametransform"
)
-// deriveDirIV derives the DirIV from the encrypted directory path by
-// hashing it
-func deriveDirIV(dirPath string) []byte {
- hash := sha256.Sum256([]byte(dirPath))
+// derivePathIV derives an IV from an encrypted path by hashing it
+func derivePathIV(path string) []byte {
+ hash := sha256.Sum256([]byte(path))
return hash[:nametransform.DirIVLen]
}
@@ -22,5 +21,5 @@ func (rfs *reverseFS) newDirIVFile(cRelPath string) (nodefs.File, fuse.Status) {
if err != nil {
return nil, fuse.ToStatus(err)
}
- return rfs.NewVirtualFile(deriveDirIV(cDir), absDir)
+ return rfs.NewVirtualFile(derivePathIV(cDir), absDir)
}
diff --git a/internal/fusefrontend_reverse/reverse_longnames.go b/internal/fusefrontend_reverse/reverse_longnames.go
index 487802f..9c45fe8 100644
--- a/internal/fusefrontend_reverse/reverse_longnames.go
+++ b/internal/fusefrontend_reverse/reverse_longnames.go
@@ -89,7 +89,7 @@ func (rfs *reverseFS) newNameFile(relPath string) (nodefs.File, fuse.Status) {
if err != nil {
return nil, fuse.ToStatus(err)
}
- dirIV := deriveDirIV(cDir)
+ dirIV := derivePathIV(cDir)
e, err := rfs.findLongnameParent(pDir, dirIV, longname)
if err != nil {
return nil, fuse.ToStatus(err)
diff --git a/internal/fusefrontend_reverse/rfile.go b/internal/fusefrontend_reverse/rfile.go
index 7e54b17..4e9b5ba 100644
--- a/internal/fusefrontend_reverse/rfile.go
+++ b/internal/fusefrontend_reverse/rfile.go
@@ -13,29 +13,32 @@ import (
"github.com/rfjakob/gocryptfs/internal/tlog"
)
-// File header that contains an all-zero File ID
-var zeroFileHeader *contentenc.FileHeader
-
-func init() {
- zeroFileHeader = contentenc.RandomHeader()
- // Overwrite with zeros
- zeroFileHeader.Id = make([]byte, contentenc.HEADER_ID_LEN)
-}
-
type reverseFile struct {
// Embed nodefs.defaultFile for a ENOSYS implementation of all methods
nodefs.File
// Backing FD
fd *os.File
+ // File header (contains the IV)
+ header contentenc.FileHeader
// Content encryption helper
contentEnc *contentenc.ContentEnc
}
-func NewFile(fd *os.File, contentEnc *contentenc.ContentEnc) (nodefs.File, fuse.Status) {
+func (rfs *reverseFS) NewFile(relPath string, flags uint32) (nodefs.File, fuse.Status) {
+ absPath, err := rfs.abs(rfs.decryptPath(relPath))
+ if err != nil {
+ return nil, fuse.ToStatus(err)
+ }
+ fd, err := os.OpenFile(absPath, int(flags), 0666)
+ if err != nil {
+ return nil, fuse.ToStatus(err)
+ }
+ id := derivePathIV(relPath)
return &reverseFile{
File: nodefs.NewDefaultFile(),
fd: fd,
- contentEnc: contentEnc,
+ header: contentenc.FileHeader{contentenc.CurrentVersion, id},
+ contentEnc: rfs.contentEnc,
}, fuse.OK
}
@@ -64,7 +67,7 @@ func (rf *reverseFile) readBackingFile(off uint64, length uint64) (out []byte, e
plaintext = plaintext[0:n]
// Encrypt blocks
- ciphertext := rf.contentEnc.EncryptBlocks(plaintext, blocks[0].BlockNo, zeroFileHeader.Id, contentenc.ReverseDummyNonce)
+ ciphertext := rf.contentEnc.EncryptBlocks(plaintext, blocks[0].BlockNo, rf.header.Id, contentenc.ReverseDeterministicNonce)
// Crop down to the relevant part
lenHave := len(ciphertext)
@@ -88,7 +91,7 @@ func (rf *reverseFile) Read(buf []byte, ioff int64) (resultData fuse.ReadResult,
// Synthesize file header
if off < contentenc.HEADER_LEN {
- header = zeroFileHeader.Pack()
+ header = rf.header.Pack()
// Truncate to requested part
end := int(off) + len(buf)
if end > len(header) {
@@ -119,3 +122,8 @@ func (rf *reverseFile) Read(buf []byte, ioff int64) (resultData fuse.ReadResult,
return fuse.ReadResultData(out.Bytes()), fuse.OK
}
+
+// Release - FUSE call, close file
+func (rf *reverseFile) Release() {
+ rf.fd.Close()
+}
diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go
index 9ebf91c..6089d41 100644
--- a/internal/fusefrontend_reverse/rfs.go
+++ b/internal/fusefrontend_reverse/rfs.go
@@ -226,15 +226,7 @@ func (rfs *reverseFS) Open(relPath string, flags uint32, context *fuse.Context)
if rfs.isFiltered(relPath) {
return nil, fuse.EPERM
}
- absPath, err := rfs.abs(rfs.decryptPath(relPath))
- if err != nil {
- return nil, fuse.ToStatus(err)
- }
- f, err := os.OpenFile(absPath, int(flags), 0666)
- if err != nil {
- return nil, fuse.ToStatus(err)
- }
- return NewFile(f, rfs.contentEnc)
+ return rfs.NewFile(relPath, flags)
}
// OpenDir - FUSE readdir call
@@ -258,7 +250,7 @@ func (rfs *reverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse.
nVirtual := 1
// Encrypt names
- dirIV := deriveDirIV(cipherPath)
+ dirIV := derivePathIV(cipherPath)
for i := range entries {
var cName string
// ".gocryptfs.reverse.conf" in the root directory is mapped to "gocryptfs.conf"
diff --git a/internal/fusefrontend_reverse/rpath.go b/internal/fusefrontend_reverse/rpath.go
index 19539bb..c603cad 100644
--- a/internal/fusefrontend_reverse/rpath.go
+++ b/internal/fusefrontend_reverse/rpath.go
@@ -36,7 +36,7 @@ func (rfs *reverseFS) decryptPath(relPath string) (string, error) {
// Start at the top and recurse
currentDir := filepath.Join(parts[:i]...)
nameType := nametransform.NameType(part)
- dirIV := deriveDirIV(currentDir)
+ dirIV := derivePathIV(currentDir)
var transformedPart string
if nameType == nametransform.LongNameNone {
transformedPart, err = rfs.nameTransform.DecryptName(part, dirIV)