aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2017-05-28 20:44:54 +0200
committerJakob Unterwurzacher2017-05-28 20:44:54 +0200
commit791c78b203be199960274053ea2b1d44c63b07c6 (patch)
tree82ad692eb25336802edf10f83528182772771df7
parente2341c93d5b113457905b338b414e41892113ec4 (diff)
fusefrontend: aessiv: enable deterministiv file id and block ivdet
Seems to work ok: $ echo aaaaaaaaaaaaaaaaaaa > b/foo $ gocryptfs-xray a/LAh7EiK-kjleJhStVZ1JGg Header: Version: 2, Id: 8d76d368438112fb00cb807fa8210a74 Block 0: IV: b05bb152f77816678230885d09a4a596, Tag: c1c7d580fe01dd1eb543efd9d8eda8ad, Offset: 18 Len: 52 $ > b/foo $ echo aaaaaaaaaaaaaaaaaaa > b/foo $ gocryptfs-xray a/LAh7EiK-kjleJhStVZ1JGg Header: Version: 2, Id: 8d76d368438112fb00cb807fa8210a74 Block 0: IV: b05bb152f77816678230885d09a4a596, Tag: c1c7d580fe01dd1eb543efd9d8eda8ad, Offset: 18 Len: 52 Deterministic diriv generation is still missing. Part of https://github.com/rfjakob/gocryptfs/issues/108
-rw-r--r--internal/contentenc/content.go5
-rw-r--r--internal/fusefrontend/file.go27
-rw-r--r--internal/fusefrontend/fs.go13
3 files changed, 34 insertions, 11 deletions
diff --git a/internal/contentenc/content.go b/internal/contentenc/content.go
index 8220d89..2a5ddbb 100644
--- a/internal/contentenc/content.go
+++ b/internal/contentenc/content.go
@@ -75,6 +75,11 @@ func (be *ContentEnc) CipherBS() uint64 {
return be.cipherBS
}
+// UsingSIV returns true if we are using AES-SIV for file content encryption.
+func (be *ContentEnc) UsingSIV() bool {
+ return be.cryptoCore.AEADBackend == cryptocore.BackendAESSIV
+}
+
// DecryptBlocks decrypts a number of blocks
// TODO refactor to three-param for
func (be *ContentEnc) DecryptBlocks(ciphertext []byte, firstBlockNo uint64, fileID []byte) ([]byte, error) {
diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go
index 57ec9ba..27c8f70 100644
--- a/internal/fusefrontend/file.go
+++ b/internal/fusefrontend/file.go
@@ -16,6 +16,7 @@ import (
"github.com/rfjakob/gocryptfs/internal/contentenc"
"github.com/rfjakob/gocryptfs/internal/openfiletable"
+ "github.com/rfjakob/gocryptfs/internal/pathiv"
"github.com/rfjakob/gocryptfs/internal/serialize_reads"
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
@@ -56,10 +57,13 @@ type file struct {
// have not implemented. This prevents build breakage when the go-fuse library
// adds new methods to the nodefs.File interface.
nodefs.File
+ // In AES-SIV mode, file ID and block IVs are deterministically derived from
+ // the path that was used to open the file.
+ pathIVs pathiv.FileIVs
}
// NewFile returns a new go-fuse File instance.
-func NewFile(fd *os.File, fs *FS) (nodefs.File, fuse.Status) {
+func NewFile(fd *os.File, fs *FS, relPath string) (nodefs.File, fuse.Status) {
var st syscall.Stat_t
err := syscall.Fstat(int(fd.Fd()), &st)
if err != nil {
@@ -68,8 +72,7 @@ func NewFile(fd *os.File, fs *FS) (nodefs.File, fuse.Status) {
}
qi := openfiletable.QInoFromStat(&st)
e := openfiletable.Register(qi)
-
- return &file{
+ f := &file{
fd: fd,
contentEnc: fs.contentEnc,
qIno: qi,
@@ -77,7 +80,11 @@ func NewFile(fd *os.File, fs *FS) (nodefs.File, fuse.Status) {
loopbackFile: nodefs.NewLoopbackFile(fd),
fs: fs,
File: nodefs.NewDefaultFile(),
- }, fuse.OK
+ }
+ if fs.contentEnc.UsingSIV() {
+ f.pathIVs = pathiv.DeriveFile(relPath)
+ }
+ return f, fuse.OK
}
// intFd - return the backing file descriptor as an integer. Used for debug
@@ -115,6 +122,10 @@ func (f *file) readFileID() ([]byte, error) {
// The caller must hold fileIDLock.Lock().
func (f *file) createHeader() (fileID []byte, err error) {
h := contentenc.RandomHeader()
+ if f.contentEnc.UsingSIV() {
+ // We use a deterministic file ID in SIV mode.
+ h.ID = f.pathIVs.ID
+ }
buf := h.Pack()
// Prevent partially written (=corrupt) header by preallocating the space beforehand
if !f.fs.args.NoPrealloc {
@@ -297,7 +308,13 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {
tlog.Debug.Printf("len(oldData)=%d len(blockData)=%d", len(oldData), len(blockData))
}
// Encrypt
- blockData = f.contentEnc.EncryptBlock(blockData, b.BlockNo, fileID)
+ if f.fs.contentEnc.UsingSIV() {
+ // We use a deterministic block IV in SIV mode.
+ iv := pathiv.BlockIV(f.pathIVs.Block0IV, b.BlockNo)
+ blockData = f.contentEnc.EncryptBlockNonce(blockData, b.BlockNo, fileID, iv)
+ } else {
+ blockData = f.contentEnc.EncryptBlock(blockData, b.BlockNo, fileID)
+ }
tlog.Debug.Printf("ino%d: Writing %d bytes to block #%d",
f.qIno.Ino, uint64(len(blockData))-f.contentEnc.BlockOverhead(), b.BlockNo)
// Store output data in the writeChain
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go
index c589302..40b6d2d 100644
--- a/internal/fusefrontend/fs.go
+++ b/internal/fusefrontend/fs.go
@@ -100,11 +100,12 @@ func (fs *FS) Open(path string, flags uint32, context *fuse.Context) (fuseFile n
return nil, fuse.EPERM
}
newFlags := fs.mangleOpenFlags(flags)
- cPath, err := fs.getBackingPath(path)
+ cRelPath, err := fs.encryptPath(path)
if err != nil {
- tlog.Debug.Printf("Open: getBackingPath: %v", err)
+ tlog.Debug.Printf("Open: encryptPath: %v", err)
return nil, fuse.ToStatus(err)
}
+ cPath := filepath.Join(fs.args.Cipherdir, cRelPath)
tlog.Debug.Printf("Open: %s", cPath)
f, err := os.OpenFile(cPath, newFlags, 0666)
if err != nil {
@@ -116,8 +117,7 @@ func (fs *FS) Open(path string, flags uint32, context *fuse.Context) (fuseFile n
}
return nil, fuse.ToStatus(err)
}
-
- return NewFile(f, fs)
+ return NewFile(f, fs, cRelPath)
}
// Create implements pathfs.Filesystem.
@@ -126,10 +126,11 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte
return nil, fuse.EPERM
}
newFlags := fs.mangleOpenFlags(flags)
- cPath, err := fs.getBackingPath(path)
+ cRelPath, err := fs.encryptPath(path)
if err != nil {
return nil, fuse.ToStatus(err)
}
+ cPath := filepath.Join(fs.args.Cipherdir, cRelPath)
var fd *os.File
cName := filepath.Base(cPath)
@@ -171,7 +172,7 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte
tlog.Warn.Printf("Create: fd.Chown failed: %v", err)
}
}
- return NewFile(fd, fs)
+ return NewFile(fd, fs, path)
}
// Chmod implements pathfs.Filesystem.