From 791c78b203be199960274053ea2b1d44c63b07c6 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sun, 28 May 2017 20:44:54 +0200 Subject: fusefrontend: aessiv: enable deterministiv file id and block iv 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 --- internal/contentenc/content.go | 5 +++++ internal/fusefrontend/file.go | 27 ++++++++++++++++++++++----- internal/fusefrontend/fs.go | 13 +++++++------ 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. -- cgit v1.2.3