aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/configfile/config_file.go24
-rw-r--r--internal/configfile/feature_flags.go18
-rw-r--r--internal/configfile/kdf.go14
-rw-r--r--internal/configfile/kdf_test.go2
-rw-r--r--internal/contentenc/content.go27
-rw-r--r--internal/contentenc/content_test.go4
-rw-r--r--internal/contentenc/file_header.go30
-rw-r--r--internal/contentenc/intrablock.go28
-rw-r--r--internal/contentenc/offsets.go48
-rw-r--r--internal/cryptocore/cryptocore.go17
-rw-r--r--internal/cryptocore/nonce.go4
-rw-r--r--internal/fusefrontend/args.go2
-rw-r--r--internal/fusefrontend/file.go9
-rw-r--r--internal/fusefrontend/file_allocate_truncate.go76
-rw-r--r--internal/fusefrontend/fs.go24
-rw-r--r--internal/fusefrontend/fs_dir.go3
-rw-r--r--internal/fusefrontend_reverse/ino_map.go2
-rw-r--r--internal/fusefrontend_reverse/reverse_longnames.go4
-rw-r--r--internal/fusefrontend_reverse/rfile.go10
-rw-r--r--internal/fusefrontend_reverse/rfs.go9
-rw-r--r--internal/nametransform/diriv.go6
-rw-r--r--internal/nametransform/longnames.go6
-rw-r--r--internal/nametransform/names.go6
-rw-r--r--internal/prefer_openssl/prefer_go1.5.go1
-rw-r--r--internal/readpassword/read.go8
-rw-r--r--internal/siv_aead/siv_aead.go11
-rw-r--r--internal/stupidgcm/stupidgcm.go10
-rw-r--r--internal/syscallcompat/sys_linux.go5
-rw-r--r--internal/tlog/log.go19
29 files changed, 264 insertions, 163 deletions
diff --git a/internal/configfile/config_file.go b/internal/configfile/config_file.go
index 9152523..79960e4 100644
--- a/internal/configfile/config_file.go
+++ b/internal/configfile/config_file.go
@@ -14,31 +14,35 @@ import (
import "os"
const (
+ // ConfDefaultName is the default configuration file name.
// The dot "." is not used in base64url (RFC4648), hence
// we can never clash with an encrypted file.
ConfDefaultName = "gocryptfs.conf"
- // In reverse mode, the config file gets stored next to the plain-text
- // files. Make it hidden (start with dot) to not annoy the user.
+ // ConfReverseName is the default configuration file name in reverse mode,
+ // the config file gets stored next to the plain-text files. Make it hidden
+ // (start with dot) to not annoy the user.
ConfReverseName = ".gocryptfs.reverse.conf"
)
+// ConfFile is the content of a config file.
type ConfFile struct {
- // gocryptfs version string
+ // Creator is the gocryptfs version string.
// This only documents the config file for humans who look at it. The actual
// technical info is contained in FeatureFlags.
Creator string
- // Encrypted AES key, unlocked using a password hashed with scrypt
+ // EncryptedKey holds an encrypted AES key, unlocked using a password
+ // hashed with scrypt
EncryptedKey []byte
- // Stores parameters for scrypt hashing (key derivation)
- ScryptObject scryptKdf
- // The On-Disk-Format version this filesystem uses
+ // ScryptObject stores parameters for scrypt hashing (key derivation)
+ ScryptObject ScryptKDF
+ // Version is the On-Disk-Format version this filesystem uses
Version uint16
- // List of feature flags this filesystem has enabled.
+ // FeatureFlags is a list of feature flags this filesystem has enabled.
// If gocryptfs encounters a feature flag it does not support, it will refuse
// mounting. This mechanism is analogous to the ext4 feature flags that are
// stored in the superblock.
FeatureFlags []string
- // File the config is saved to. Not exported to JSON.
+ // Filename is the name of the config file. Not exported to JSON.
filename string
}
@@ -162,7 +166,7 @@ func LoadConfFile(filename string, password string) ([]byte, *ConfFile, error) {
// cf.ScryptObject.
func (cf *ConfFile) EncryptKey(key []byte, password string, logN int) {
// Generate derived key from password
- cf.ScryptObject = NewScryptKdf(logN)
+ cf.ScryptObject = NewScryptKDF(logN)
scryptHash := cf.ScryptObject.DeriveKey(password)
// Lock master key using password-based key
diff --git a/internal/configfile/feature_flags.go b/internal/configfile/feature_flags.go
index ad7bec1..d3601b1 100644
--- a/internal/configfile/feature_flags.go
+++ b/internal/configfile/feature_flags.go
@@ -3,16 +3,24 @@ package configfile
type flagIota int
const (
+ // FlagPlaintextNames indicates that filenames are unencrypted.
FlagPlaintextNames flagIota = iota
+ // FlagDirIV indicates that a per-directory IV file is used.
FlagDirIV
+ // FlagEMENames indicates EME (ECB-Mix-ECB) filename encryption.
+ // This flag is mandatory since gocryptfs v1.0.
FlagEMENames
+ // FlagGCMIV128 indicates 128-bit GCM IVs.
+ // This flag is mandatory since gocryptfs v1.0.
FlagGCMIV128
+ // FlagLongNames allows file names longer than 176 bytes.
FlagLongNames
+ // FlagAESSIV selects an AES-SIV based crypto backend.
FlagAESSIV
)
// knownFlags stores the known feature flags and their string representation
-var knownFlags map[flagIota]string = map[flagIota]string{
+var knownFlags = map[flagIota]string{
FlagPlaintextNames: "PlaintextNames",
FlagDirIV: "DirIV",
FlagEMENames: "EMENames",
@@ -22,7 +30,7 @@ var knownFlags map[flagIota]string = map[flagIota]string{
}
// Filesystems that do not have these feature flags set are deprecated.
-var requiredFlagsNormal []flagIota = []flagIota{
+var requiredFlagsNormal = []flagIota{
FlagDirIV,
FlagEMENames,
FlagGCMIV128,
@@ -30,11 +38,11 @@ var requiredFlagsNormal []flagIota = []flagIota{
// Filesystems without filename encryption obviously don't have or need the
// filename related feature flags.
-var requiredFlagsPlaintextNames []flagIota = []flagIota{
+var requiredFlagsPlaintextNames = []flagIota{
FlagGCMIV128,
}
-// isFeatureFlagKnown verifies that we understand a feature flag
+// isFeatureFlagKnown verifies that we understand a feature flag.
func (cf *ConfFile) isFeatureFlagKnown(flag string) bool {
for _, knownFlag := range knownFlags {
if knownFlag == flag {
@@ -44,7 +52,7 @@ func (cf *ConfFile) isFeatureFlagKnown(flag string) bool {
return false
}
-// isFeatureFlagSet - is the feature flag "flagWant" enabled?
+// IsFeatureFlagSet returns true if the feature flag "flagWant" is enabled.
func (cf *ConfFile) IsFeatureFlagSet(flagWant flagIota) bool {
flagString := knownFlags[flagWant]
for _, flag := range cf.FeatureFlags {
diff --git a/internal/configfile/kdf.go b/internal/configfile/kdf.go
index ca87975..31bcbe4 100644
--- a/internal/configfile/kdf.go
+++ b/internal/configfile/kdf.go
@@ -12,12 +12,14 @@ import (
)
const (
+ // ScryptDefaultLogN is the default scrypt logN configuration parameter.
// 1 << 16 uses 64MB of memory,
// takes 4 seconds on my Atom Z3735F netbook
ScryptDefaultLogN = 16
)
-type scryptKdf struct {
+// ScryptKDF is an instance of the scrypt key deriviation function.
+type ScryptKDF struct {
Salt []byte
N int
R int
@@ -25,8 +27,9 @@ type scryptKdf struct {
KeyLen int
}
-func NewScryptKdf(logN int) scryptKdf {
- var s scryptKdf
+// NewScryptKDF returns a new instance of ScryptKDF.
+func NewScryptKDF(logN int) ScryptKDF {
+ var s ScryptKDF
s.Salt = cryptocore.RandBytes(cryptocore.KeyLen)
if logN <= 0 {
s.N = 1 << ScryptDefaultLogN
@@ -43,7 +46,8 @@ func NewScryptKdf(logN int) scryptKdf {
return s
}
-func (s *scryptKdf) DeriveKey(pw string) []byte {
+// DeriveKey returns a new key from a supplied password.
+func (s *ScryptKDF) DeriveKey(pw string) []byte {
k, err := scrypt.Key([]byte(pw), s.Salt, s.N, s.R, s.P, s.KeyLen)
if err != nil {
log.Panicf("DeriveKey failed: %v", err)
@@ -53,6 +57,6 @@ func (s *scryptKdf) DeriveKey(pw string) []byte {
// LogN - N is saved as 2^LogN, but LogN is much easier to work with.
// This function gives you LogN = Log2(N).
-func (s *scryptKdf) LogN() int {
+func (s *ScryptKDF) LogN() int {
return int(math.Log2(float64(s.N)) + 0.5)
}
diff --git a/internal/configfile/kdf_test.go b/internal/configfile/kdf_test.go
index bc095ab..c1a656a 100644
--- a/internal/configfile/kdf_test.go
+++ b/internal/configfile/kdf_test.go
@@ -21,7 +21,7 @@ ok github.com/rfjakob/gocryptfs/cryptfs 18.772s
*/
func benchmarkScryptN(n int, b *testing.B) {
- kdf := NewScryptKdf(n)
+ kdf := NewScryptKDF(n)
for i := 0; i < b.N; i++ {
kdf.DeriveKey("test")
}
diff --git a/internal/contentenc/content.go b/internal/contentenc/content.go
index ac2e8de..dd3b77a 100644
--- a/internal/contentenc/content.go
+++ b/internal/contentenc/content.go
@@ -11,21 +11,28 @@ import (
"github.com/rfjakob/gocryptfs/internal/tlog"
)
+// NonceMode determines how nonces are created.
type NonceMode int
const (
- // Default plaintext block size
+ // DefaultBS is the default plaintext block size
DefaultBS = 4096
+ // DefaultIVBits is the default length of IV, in bits.
// We always use 128-bit IVs for file content, but the
// key in the config file is encrypted with a 96-bit IV.
DefaultIVBits = 128
- _ = iota // skip zero
- RandomNonce NonceMode = iota
+ _ = iota // skip zero
+ // RandomNonce chooses a random nonce.
+ RandomNonce NonceMode = iota
+ // ReverseDeterministicNonce chooses a deterministic nonce, suitable for
+ // use in reverse mode.
ReverseDeterministicNonce NonceMode = iota
- ExternalNonce NonceMode = iota
+ // ExternalNonce derives a nonce from external sources.
+ ExternalNonce NonceMode = iota
)
+// ContentEnc is used to encipher and decipher file content.
type ContentEnc struct {
// Cryptographic primitives
cryptoCore *cryptocore.CryptoCore
@@ -39,8 +46,8 @@ type ContentEnc struct {
allZeroNonce []byte
}
+// New returns an initialized ContentEnc instance.
func New(cc *cryptocore.CryptoCore, plainBS uint64) *ContentEnc {
-
cipherBS := plainBS + uint64(cc.IVLen) + cryptocore.AuthTagLen
return &ContentEnc{
@@ -62,16 +69,16 @@ func (be *ContentEnc) CipherBS() uint64 {
return be.cipherBS
}
-// DecryptBlocks - Decrypt a number of blocks
+// DecryptBlocks decrypts a number of blocks
// TODO refactor to three-param for
-func (be *ContentEnc) DecryptBlocks(ciphertext []byte, firstBlockNo uint64, fileId []byte) ([]byte, error) {
+func (be *ContentEnc) DecryptBlocks(ciphertext []byte, firstBlockNo uint64, fileID []byte) ([]byte, error) {
cBuf := bytes.NewBuffer(ciphertext)
var err error
var pBuf bytes.Buffer
for cBuf.Len() > 0 {
cBlock := cBuf.Next(int(be.cipherBS))
var pBlock []byte
- pBlock, err = be.DecryptBlock(cBlock, firstBlockNo, fileId)
+ pBlock, err = be.DecryptBlock(cBlock, firstBlockNo, fileID)
if err != nil {
break
}
@@ -85,7 +92,7 @@ func (be *ContentEnc) DecryptBlocks(ciphertext []byte, firstBlockNo uint64, file
//
// Corner case: A full-sized block of all-zero ciphertext bytes is translated
// to an all-zero plaintext block, i.e. file hole passtrough.
-func (be *ContentEnc) DecryptBlock(ciphertext []byte, blockNo uint64, fileId []byte) ([]byte, error) {
+func (be *ContentEnc) DecryptBlock(ciphertext []byte, blockNo uint64, fileID []byte) ([]byte, error) {
// Empty block?
if len(ciphertext) == 0 {
@@ -114,7 +121,7 @@ func (be *ContentEnc) DecryptBlock(ciphertext []byte, blockNo uint64, fileId []b
// Decrypt
var plaintext []byte
aData := make([]byte, 8)
- aData = append(aData, fileId...)
+ aData = append(aData, fileID...)
binary.BigEndian.PutUint64(aData, blockNo)
plaintext, err := be.cryptoCore.AEADCipher.Open(plaintext, nonce, ciphertext, aData)
diff --git a/internal/contentenc/content_test.go b/internal/contentenc/content_test.go
index 70b71fe..e6c610c 100644
--- a/internal/contentenc/content_test.go
+++ b/internal/contentenc/content_test.go
@@ -63,7 +63,7 @@ func TestCiphertextRange(t *testing.T) {
if alignedLength < r.length {
t.Errorf("alignedLength=%d is smaller than length=%d", alignedLength, r.length)
}
- if (alignedOffset-HEADER_LEN)%f.cipherBS != 0 {
+ if (alignedOffset-HeaderLen)%f.cipherBS != 0 {
t.Errorf("alignedOffset=%d is not aligned", alignedOffset)
}
if r.offset%f.plainBS != 0 && skipBytes == 0 {
@@ -81,7 +81,7 @@ func TestBlockNo(t *testing.T) {
if b != 0 {
t.Errorf("actual: %d", b)
}
- b = f.CipherOffToBlockNo(HEADER_LEN + f.cipherBS)
+ b = f.CipherOffToBlockNo(HeaderLen + f.cipherBS)
if b != 1 {
t.Errorf("actual: %d", b)
}
diff --git a/internal/contentenc/file_header.go b/internal/contentenc/file_header.go
index 1463773..9ae5ae9 100644
--- a/internal/contentenc/file_header.go
+++ b/internal/contentenc/file_header.go
@@ -12,42 +12,44 @@ import (
)
const (
- // Current On-Disk-Format version
+ // CurrentVersion is the current On-Disk-Format version
CurrentVersion = 2
- HEADER_VERSION_LEN = 2 // uint16
- HEADER_ID_LEN = 16 // 128 bit random file id
- HEADER_LEN = HEADER_VERSION_LEN + HEADER_ID_LEN // Total header length
+ headerVersionLen = 2 // uint16
+ headerIDLen = 16 // 128 bit random file id
+ // HeaderLen is the total header length
+ HeaderLen = headerVersionLen + headerIDLen
)
+// FileHeader represents the header stored on each non-empty file.
type FileHeader struct {
Version uint16
- Id []byte
+ ID []byte
}
// Pack - serialize fileHeader object
func (h *FileHeader) Pack() []byte {
- if len(h.Id) != HEADER_ID_LEN || h.Version != CurrentVersion {
+ if len(h.ID) != headerIDLen || h.Version != CurrentVersion {
panic("FileHeader object not properly initialized")
}
- buf := make([]byte, HEADER_LEN)
- binary.BigEndian.PutUint16(buf[0:HEADER_VERSION_LEN], h.Version)
- copy(buf[HEADER_VERSION_LEN:], h.Id)
+ buf := make([]byte, HeaderLen)
+ binary.BigEndian.PutUint16(buf[0:headerVersionLen], h.Version)
+ copy(buf[headerVersionLen:], h.ID)
return buf
}
// ParseHeader - parse "buf" into fileHeader object
func ParseHeader(buf []byte) (*FileHeader, error) {
- if len(buf) != HEADER_LEN {
- return nil, fmt.Errorf("ParseHeader: invalid length: got %d, want %d", len(buf), HEADER_LEN)
+ if len(buf) != HeaderLen {
+ return nil, fmt.Errorf("ParseHeader: invalid length: got %d, want %d", len(buf), HeaderLen)
}
var h FileHeader
- h.Version = binary.BigEndian.Uint16(buf[0:HEADER_VERSION_LEN])
+ h.Version = binary.BigEndian.Uint16(buf[0:headerVersionLen])
if h.Version != CurrentVersion {
return nil, fmt.Errorf("ParseHeader: invalid version: got %d, want %d", h.Version, CurrentVersion)
}
- h.Id = buf[HEADER_VERSION_LEN:]
+ h.ID = buf[headerVersionLen:]
return &h, nil
}
@@ -55,6 +57,6 @@ func ParseHeader(buf []byte) (*FileHeader, error) {
func RandomHeader() *FileHeader {
var h FileHeader
h.Version = CurrentVersion
- h.Id = cryptocore.RandBytes(HEADER_ID_LEN)
+ h.ID = cryptocore.RandBytes(headerIDLen)
return &h
}
diff --git a/internal/contentenc/intrablock.go b/internal/contentenc/intrablock.go
index 632e76b..3714e37 100644
--- a/internal/contentenc/intrablock.go
+++ b/internal/contentenc/intrablock.go
@@ -1,10 +1,10 @@
package contentenc
-// intraBlock identifies a part of a file block
-type intraBlock struct {
- // Block number in the file
+// IntraBlock identifies a part of a file block
+type IntraBlock struct {
+ // BlockNo is the block number in the file
BlockNo uint64
- // Offset into block payload
+ // Skip is an offset into the block payload
// In forwared mode: block plaintext
// In reverse mode: offset into block ciphertext. Takes the header into
// account.
@@ -17,8 +17,8 @@ type intraBlock struct {
fs *ContentEnc
}
-// isPartial - is the block partial? This means we have to do read-modify-write.
-func (ib *intraBlock) IsPartial() bool {
+// IsPartial - is the block partial? This means we have to do read-modify-write.
+func (ib *IntraBlock) IsPartial() bool {
if ib.Skip > 0 || ib.Length < ib.fs.plainBS {
return true
}
@@ -26,17 +26,17 @@ func (ib *intraBlock) IsPartial() bool {
}
// BlockCipherOff returns the ciphertext offset corresponding to BlockNo
-func (ib *intraBlock) BlockCipherOff() (offset uint64) {
+func (ib *IntraBlock) BlockCipherOff() (offset uint64) {
return ib.fs.BlockNoToCipherOff(ib.BlockNo)
}
// BlockPlainOff returns the plaintext offset corresponding to BlockNo
-func (ib *intraBlock) BlockPlainOff() (offset uint64) {
+func (ib *IntraBlock) BlockPlainOff() (offset uint64) {
return ib.fs.BlockNoToPlainOff(ib.BlockNo)
}
// CropBlock - crop a potentially larger plaintext block down to the relevant part
-func (ib *intraBlock) CropBlock(d []byte) []byte {
+func (ib *IntraBlock) CropBlock(d []byte) []byte {
lenHave := len(d)
lenWant := int(ib.Skip + ib.Length)
if lenHave < lenWant {
@@ -45,8 +45,9 @@ func (ib *intraBlock) CropBlock(d []byte) []byte {
return d[ib.Skip:lenWant]
}
-// Ciphertext range corresponding to the sum of all "blocks" (complete blocks)
-func (ib *intraBlock) JointCiphertextRange(blocks []intraBlock) (offset uint64, length uint64) {
+// JointCiphertextRange is the ciphertext range corresponding to the sum of all
+// "blocks" (complete blocks)
+func (ib *IntraBlock) JointCiphertextRange(blocks []IntraBlock) (offset uint64, length uint64) {
firstBlock := blocks[0]
lastBlock := blocks[len(blocks)-1]
@@ -57,8 +58,9 @@ func (ib *intraBlock) JointCiphertextRange(blocks []intraBlock) (offset uint64,
return offset, length
}
-// Plaintext range corresponding to the sum of all "blocks" (complete blocks)
-func JointPlaintextRange(blocks []intraBlock) (offset uint64, length uint64) {
+// JointPlaintextRange is the plaintext range corresponding to the sum of all
+// "blocks" (complete blocks)
+func JointPlaintextRange(blocks []IntraBlock) (offset uint64, length uint64) {
firstBlock := blocks[0]
lastBlock := blocks[len(blocks)-1]
diff --git a/internal/contentenc/offsets.go b/internal/contentenc/offsets.go
index 61939a9..97d7116 100644
--- a/internal/contentenc/offsets.go
+++ b/internal/contentenc/offsets.go
@@ -8,43 +8,43 @@ import (
// Contentenc methods that translate offsets between ciphertext and plaintext
-// get the block number at plain-text offset
+// PlainOffToBlockNo converts a plaintext offset to the ciphertext block number.
func (be *ContentEnc) PlainOffToBlockNo(plainOffset uint64) uint64 {
return plainOffset / be.plainBS
}
-// get the block number at cipher-text offset
+// CipherOffToBlockNo converts the ciphertext offset to the plaintext block number.
func (be *ContentEnc) CipherOffToBlockNo(cipherOffset uint64) uint64 {
- if cipherOffset < HEADER_LEN {
+ if cipherOffset < HeaderLen {
log.Panicf("BUG: offset %d is inside the file header", cipherOffset)
}
- return (cipherOffset - HEADER_LEN) / be.cipherBS
+ return (cipherOffset - HeaderLen) / be.cipherBS
}
-// get ciphertext offset of block "blockNo"
+// BlockNoToCipherOff gets the ciphertext offset of block "blockNo"
func (be *ContentEnc) BlockNoToCipherOff(blockNo uint64) uint64 {
- return HEADER_LEN + blockNo*be.cipherBS
+ return HeaderLen + blockNo*be.cipherBS
}
-// get plaintext offset of block "blockNo"
+// BlockNoToPlainOff gets the plaintext offset of block "blockNo"
func (be *ContentEnc) BlockNoToPlainOff(blockNo uint64) uint64 {
return blockNo * be.plainBS
}
-// PlainSize - calculate plaintext size from ciphertext size
+// CipherSizeToPlainSize calculates the plaintext size from a ciphertext size
func (be *ContentEnc) CipherSizeToPlainSize(cipherSize uint64) uint64 {
// Zero-sized files stay zero-sized
if cipherSize == 0 {
return 0
}
- if cipherSize == HEADER_LEN {
+ if cipherSize == HeaderLen {
tlog.Warn.Printf("cipherSize %d == header size: interrupted write?\n", cipherSize)
return 0
}
- if cipherSize < HEADER_LEN {
- tlog.Warn.Printf("cipherSize %d < header size %d: corrupt file\n", cipherSize, HEADER_LEN)
+ if cipherSize < HeaderLen {
+ tlog.Warn.Printf("cipherSize %d < header size %d: corrupt file\n", cipherSize, HeaderLen)
return 0
}
@@ -52,12 +52,12 @@ func (be *ContentEnc) CipherSizeToPlainSize(cipherSize uint64) uint64 {
blockNo := be.CipherOffToBlockNo(cipherSize - 1)
blockCount := blockNo + 1
- overhead := be.BlockOverhead()*blockCount + HEADER_LEN
+ overhead := be.BlockOverhead()*blockCount + HeaderLen
return cipherSize - overhead
}
-// CipherSize - calculate ciphertext size from plaintext size
+// PlainSizeToCipherSize calculates the ciphertext size from a plaintext size
func (be *ContentEnc) PlainSizeToCipherSize(plainSize uint64) uint64 {
// Zero-sized files stay zero-sized
if plainSize == 0 {
@@ -68,16 +68,16 @@ func (be *ContentEnc) PlainSizeToCipherSize(plainSize uint64) uint64 {
blockNo := be.PlainOffToBlockNo(plainSize - 1)
blockCount := blockNo + 1
- overhead := be.BlockOverhead()*blockCount + HEADER_LEN
+ overhead := be.BlockOverhead()*blockCount + HeaderLen
return plainSize + overhead
}
-// Split a plaintext byte range into (possibly partial) blocks
+// ExplodePlainRange splits a plaintext byte range into (possibly partial) blocks
// Returns an empty slice if length == 0.
-func (be *ContentEnc) ExplodePlainRange(offset uint64, length uint64) []intraBlock {
- var blocks []intraBlock
- var nextBlock intraBlock
+func (be *ContentEnc) ExplodePlainRange(offset uint64, length uint64) []IntraBlock {
+ var blocks []IntraBlock
+ var nextBlock IntraBlock
nextBlock.fs = be
for length > 0 {
@@ -94,11 +94,11 @@ func (be *ContentEnc) ExplodePlainRange(offset uint64, length uint64) []intraBlo
return blocks
}
-// Split a ciphertext byte range into (possibly partial) blocks
-// This is used in reverse mode when reading files
-func (be *ContentEnc) ExplodeCipherRange(offset uint64, length uint64) []intraBlock {
- var blocks []intraBlock
- var nextBlock intraBlock
+// ExplodeCipherRange splits a ciphertext byte range into (possibly partial)
+// blocks This is used in reverse mode when reading files
+func (be *ContentEnc) ExplodeCipherRange(offset uint64, length uint64) []IntraBlock {
+ var blocks []IntraBlock
+ var nextBlock IntraBlock
nextBlock.fs = be
for length > 0 {
@@ -120,10 +120,12 @@ func (be *ContentEnc) ExplodeCipherRange(offset uint64, length uint64) []intraBl
return blocks
}
+// BlockOverhead returns the per-block overhead.
func (be *ContentEnc) BlockOverhead() uint64 {
return be.cipherBS - be.plainBS
}
+// MinUint64 returns the minimum of two uint64 values.
func MinUint64(x uint64, y uint64) uint64 {
if x < y {
return x
diff --git a/internal/cryptocore/cryptocore.go b/internal/cryptocore/cryptocore.go
index 05c0704..7cb5c95 100644
--- a/internal/cryptocore/cryptocore.go
+++ b/internal/cryptocore/cryptocore.go
@@ -12,18 +12,25 @@ import (
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
)
+// BackendTypeEnum indicates the type of backend in use.
type BackendTypeEnum int
const (
- KeyLen = 32 // AES-256
+ // KeyLen is the cipher key length in bytes. 32 for AES-256.
+ KeyLen = 32
+ // AuthTagLen is the length of a GCM auth tag in bytes.
AuthTagLen = 16
- _ = iota // Skip zero
+ _ = iota // Skip zero
+ // BackendOpenSSL specifies the OpenSSL backend.
BackendOpenSSL BackendTypeEnum = iota
- BackendGoGCM BackendTypeEnum = iota
- BackendAESSIV BackendTypeEnum = iota
+ // BackendGoGCM specifies the Go based GCM backend.
+ BackendGoGCM BackendTypeEnum = iota
+ // BackendAESSIV specifies an AESSIV backend.
+ BackendAESSIV BackendTypeEnum = iota
)
+// CryptoCore is the low level crypto implementation.
type CryptoCore struct {
// AES-256 block cipher. This is used for EME filename encryption.
BlockCipher cipher.Block
@@ -36,7 +43,7 @@ type CryptoCore struct {
IVLen int
}
-// "New" returns a new CryptoCore object or panics.
+// New returns a new CryptoCore object or panics.
//
// Even though the "GCMIV128" feature flag is now mandatory, we must still
// support 96-bit IVs here because they are used for encrypting the master
diff --git a/internal/cryptocore/nonce.go b/internal/cryptocore/nonce.go
index 6b0c31d..973d2d8 100644
--- a/internal/cryptocore/nonce.go
+++ b/internal/cryptocore/nonce.go
@@ -10,7 +10,7 @@ import (
"github.com/rfjakob/gocryptfs/internal/tlog"
)
-// Get "n" random bytes from /dev/urandom or panic
+// RandBytes gets "n" random bytes from /dev/urandom or panics
func RandBytes(n int) []byte {
b := make([]byte, n)
_, err := rand.Read(b)
@@ -20,7 +20,7 @@ func RandBytes(n int) []byte {
return b
}
-// Return a secure random uint64
+// RandUint64 returns a secure random uint64
func RandUint64() uint64 {
b := RandBytes(8)
return binary.BigEndian.Uint64(b)
diff --git a/internal/fusefrontend/args.go b/internal/fusefrontend/args.go
index d0e1835..64ca899 100644
--- a/internal/fusefrontend/args.go
+++ b/internal/fusefrontend/args.go
@@ -4,7 +4,7 @@ import (
"github.com/rfjakob/gocryptfs/internal/cryptocore"
)
-// Container for arguments that are passed from main() to fusefrontend
+// Args is a container for arguments that are passed from main() to fusefrontend
type Args struct {
Masterkey []byte
Cipherdir string
diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go
index a04b6af..ab025d3 100644
--- a/internal/fusefrontend/file.go
+++ b/internal/fusefrontend/file.go
@@ -45,6 +45,7 @@ type file struct {
loopbackFile nodefs.File
}
+// NewFile returns a new go-fuse File instance.
func NewFile(fd *os.File, writeOnly bool, contentEnc *contentenc.ContentEnc) (nodefs.File, fuse.Status) {
var st syscall.Stat_t
err := syscall.Fstat(int(fd.Fd()), &st)
@@ -80,7 +81,7 @@ func (f *file) SetInode(n *nodefs.Inode) {
//
// Returns io.EOF if the file is empty
func (f *file) readHeader() error {
- buf := make([]byte, contentenc.HEADER_LEN)
+ buf := make([]byte, contentenc.HeaderLen)
_, err := f.fd.ReadAt(buf, 0)
if err != nil {
return err
@@ -100,7 +101,7 @@ func (f *file) createHeader() error {
buf := h.Pack()
// Prevent partially written (=corrupt) header by preallocating the space beforehand
- err := syscallcompat.EnospcPrealloc(int(f.fd.Fd()), 0, contentenc.HEADER_LEN)
+ err := syscallcompat.EnospcPrealloc(int(f.fd.Fd()), 0, contentenc.HeaderLen)
if err != nil {
tlog.Warn.Printf("ino%d: createHeader: prealloc failed: %s\n", f.ino, err.Error())
return err
@@ -159,7 +160,7 @@ func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) {
tlog.Debug.Printf("ReadAt offset=%d bytes (%d blocks), want=%d, got=%d", alignedOffset, firstBlockNo, alignedLength, n)
// Decrypt it
- plaintext, err := f.contentEnc.DecryptBlocks(ciphertext, firstBlockNo, f.header.Id)
+ plaintext, err := f.contentEnc.DecryptBlocks(ciphertext, firstBlockNo, f.header.ID)
if err != nil {
curruptBlockNo := firstBlockNo + f.contentEnc.PlainOffToBlockNo(uint64(len(plaintext)))
cipherOff := f.contentEnc.BlockNoToCipherOff(curruptBlockNo)
@@ -256,7 +257,7 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {
// Encrypt
blockOffset := b.BlockCipherOff()
- blockData = f.contentEnc.EncryptBlock(blockData, b.BlockNo, f.header.Id)
+ blockData = f.contentEnc.EncryptBlock(blockData, b.BlockNo, f.header.ID)
tlog.Debug.Printf("ino%d: Writing %d bytes to block #%d",
f.ino, uint64(len(blockData))-f.contentEnc.BlockOverhead(), b.BlockNo)
diff --git a/internal/fusefrontend/file_allocate_truncate.go b/internal/fusefrontend/file_allocate_truncate.go
index f22fa4b..650e1db 100644
--- a/internal/fusefrontend/file_allocate_truncate.go
+++ b/internal/fusefrontend/file_allocate_truncate.go
@@ -14,7 +14,10 @@ import (
"github.com/rfjakob/gocryptfs/internal/tlog"
)
+// FALLOC_DEFAULT is a "normal" fallocate operation
const FALLOC_DEFAULT = 0x00
+
+// FALLOC_FL_KEEP_SIZE allocates disk space while not modifying the file size
const FALLOC_FL_KEEP_SIZE = 0x01
// Only warn once
@@ -116,11 +119,12 @@ func (f *file) Truncate(newSize uint64) fuse.Status {
oldSize, err := f.statPlainSize()
if err != nil {
return fuse.ToStatus(err)
- } else {
- oldB := float32(oldSize) / float32(f.contentEnc.PlainBS())
- newB := float32(newSize) / float32(f.contentEnc.PlainBS())
- tlog.Debug.Printf("ino%d: FUSE Truncate from %.2f to %.2f blocks (%d to %d bytes)", f.ino, oldB, newB, oldSize, newSize)
}
+
+ oldB := float32(oldSize) / float32(f.contentEnc.PlainBS())
+ newB := float32(newSize) / float32(f.contentEnc.PlainBS())
+ tlog.Debug.Printf("ino%d: FUSE Truncate from %.2f to %.2f blocks (%d to %d bytes)", f.ino, oldB, newB, oldSize, newSize)
+
// File size stays the same - nothing to do
if newSize == oldSize {
return fuse.OK
@@ -128,34 +132,34 @@ func (f *file) Truncate(newSize uint64) fuse.Status {
// File grows
if newSize > oldSize {
return f.truncateGrowFile(oldSize, newSize)
- } else {
- // File shrinks
- blockNo := f.contentEnc.PlainOffToBlockNo(newSize)
- cipherOff := f.contentEnc.BlockNoToCipherOff(blockNo)
- plainOff := f.contentEnc.BlockNoToPlainOff(blockNo)
- lastBlockLen := newSize - plainOff
- var data []byte
- if lastBlockLen > 0 {
- var status fuse.Status
- data, status = f.doRead(plainOff, lastBlockLen)
- if status != fuse.OK {
- tlog.Warn.Printf("Truncate: shrink doRead returned error: %v", err)
- return status
- }
- }
- // Truncate down to the last complete block
- err = syscall.Ftruncate(int(f.fd.Fd()), int64(cipherOff))
- if err != nil {
- tlog.Warn.Printf("Truncate: shrink Ftruncate returned error: %v", err)
- return fuse.ToStatus(err)
- }
- // Append partial block
- if lastBlockLen > 0 {
- _, status := f.doWrite(data, int64(plainOff))
+ }
+
+ // File shrinks
+ blockNo := f.contentEnc.PlainOffToBlockNo(newSize)
+ cipherOff := f.contentEnc.BlockNoToCipherOff(blockNo)
+ plainOff := f.contentEnc.BlockNoToPlainOff(blockNo)
+ lastBlockLen := newSize - plainOff
+ var data []byte
+ if lastBlockLen > 0 {
+ var status fuse.Status
+ data, status = f.doRead(plainOff, lastBlockLen)
+ if status != fuse.OK {
+ tlog.Warn.Printf("Truncate: shrink doRead returned error: %v", err)
return status
}
- return fuse.OK
}
+ // Truncate down to the last complete block
+ err = syscall.Ftruncate(int(f.fd.Fd()), int64(cipherOff))
+ if err != nil {
+ tlog.Warn.Printf("Truncate: shrink Ftruncate returned error: %v", err)
+ return fuse.ToStatus(err)
+ }
+ // Append partial block
+ if lastBlockLen > 0 {
+ _, status := f.doWrite(data, int64(plainOff))
+ return status
+ }
+ return fuse.OK
}
// statPlainSize stats the file and returns the plaintext size
@@ -198,12 +202,12 @@ func (f *file) truncateGrowFile(oldPlainSz uint64, newPlainSz uint64) fuse.Statu
off := lastBlock.BlockPlainOff()
_, status := f.doWrite(make([]byte, lastBlock.Length), int64(off+lastBlock.Skip))
return status
- } else {
- off := lastBlock.BlockCipherOff()
- err = syscall.Ftruncate(f.intFd(), int64(off+f.contentEnc.CipherBS()))
- if err != nil {
- tlog.Warn.Printf("Truncate: grow Ftruncate returned error: %v", err)
- }
- return fuse.ToStatus(err)
}
+
+ off := lastBlock.BlockCipherOff()
+ err = syscall.Ftruncate(f.intFd(), int64(off+f.contentEnc.CipherBS()))
+ if err != nil {
+ tlog.Warn.Printf("Truncate: grow Ftruncate returned error: %v", err)
+ }
+ return fuse.ToStatus(err)
}
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go
index 62146a2..26a5b5e 100644
--- a/internal/fusefrontend/fs.go
+++ b/internal/fusefrontend/fs.go
@@ -22,6 +22,7 @@ import (
"github.com/rfjakob/gocryptfs/internal/tlog"
)
+// FS implements the go-fuse virtual filesystem interface.
type FS struct {
pathfs.FileSystem // loopbackFileSystem, see go-fuse/fuse/pathfs/loopback.go
args Args // Stores configuration arguments
@@ -35,7 +36,9 @@ type FS struct {
contentEnc *contentenc.ContentEnc
}
-// Encrypted FUSE overlay filesystem
+var _ pathfs.FileSystem = &FS{} // Verify that interface is implemented.
+
+// NewFS returns a new encrypted FUSE overlay filesystem.
func NewFS(args Args) *FS {
cryptoCore := cryptocore.New(args.Masterkey, args.CryptoBackend, contentenc.DefaultIVBits)
contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS)
@@ -49,6 +52,7 @@ func NewFS(args Args) *FS {
}
}
+// GetAttr implements pathfs.Filesystem.
func (fs *FS) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
tlog.Debug.Printf("FS.GetAttr('%s')", name)
if fs.isFiltered(name) {
@@ -85,6 +89,7 @@ func (fs *FS) mangleOpenFlags(flags uint32) (newFlags int, writeOnly bool) {
return newFlags, writeOnly
}
+// Open implements pathfs.Filesystem.
func (fs *FS) Open(path string, flags uint32, context *fuse.Context) (fuseFile nodefs.File, status fuse.Status) {
if fs.isFiltered(path) {
return nil, fuse.EPERM
@@ -104,6 +109,7 @@ func (fs *FS) Open(path string, flags uint32, context *fuse.Context) (fuseFile n
return NewFile(f, writeOnly, fs.contentEnc)
}
+// Create implements pathfs.Filesystem.
func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Context) (fuseFile nodefs.File, code fuse.Status) {
if fs.isFiltered(path) {
return nil, fuse.EPERM
@@ -156,6 +162,7 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte
return NewFile(fd, writeOnly, fs.contentEnc)
}
+// Chmod implements pathfs.Filesystem.
func (fs *FS) Chmod(path string, mode uint32, context *fuse.Context) (code fuse.Status) {
if fs.isFiltered(path) {
return fuse.EPERM
@@ -170,6 +177,7 @@ func (fs *FS) Chmod(path string, mode uint32, context *fuse.Context) (code fuse.
return fuse.ToStatus(err)
}
+// Chown implements pathfs.Filesystem.
func (fs *FS) Chown(path string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
if fs.isFiltered(path) {
return fuse.EPERM
@@ -181,6 +189,7 @@ func (fs *FS) Chown(path string, uid uint32, gid uint32, context *fuse.Context)
return fuse.ToStatus(os.Lchown(cPath, int(uid), int(gid)))
}
+// Mknod implements pathfs.Filesystem.
func (fs *FS) Mknod(path string, mode uint32, dev uint32, context *fuse.Context) (code fuse.Status) {
if fs.isFiltered(path) {
return fuse.EPERM
@@ -217,6 +226,7 @@ func (fs *FS) Mknod(path string, mode uint32, dev uint32, context *fuse.Context)
return fs.FileSystem.Mknod(cPath, mode, dev, context)
}
+// Truncate implements pathfs.Filesystem.
// Support truncate(2) by opening the file and calling ftruncate(2)
// While the glibc "truncate" wrapper seems to always use ftruncate, fsstress from
// xfstests uses this a lot by calling "truncate64" directly.
@@ -230,6 +240,7 @@ func (fs *FS) Truncate(path string, offset uint64, context *fuse.Context) (code
return code
}
+// Utimens implements pathfs.Filesystem.
func (fs *FS) Utimens(path string, a *time.Time, m *time.Time, context *fuse.Context) (code fuse.Status) {
if fs.isFiltered(path) {
return fuse.EPERM
@@ -241,6 +252,7 @@ func (fs *FS) Utimens(path string, a *time.Time, m *time.Time, context *fuse.Con
return fs.FileSystem.Utimens(cPath, a, m, context)
}
+// StatFs implements pathfs.Filesystem.
func (fs *FS) StatFs(path string) *fuse.StatfsOut {
if fs.isFiltered(path) {
return nil
@@ -252,6 +264,7 @@ func (fs *FS) StatFs(path string) *fuse.StatfsOut {
return fs.FileSystem.StatFs(cPath)
}
+// Readlink implements pathfs.Filesystem.
func (fs *FS) Readlink(path string, context *fuse.Context) (out string, status fuse.Status) {
cPath, err := fs.getBackingPath(path)
if err != nil {
@@ -278,6 +291,7 @@ func (fs *FS) Readlink(path string, context *fuse.Context) (out string, status f
return string(target), fuse.OK
}
+// Unlink implements pathfs.Filesystem.
func (fs *FS) Unlink(path string, context *fuse.Context) (code fuse.Status) {
if fs.isFiltered(path) {
return fuse.EPERM
@@ -312,6 +326,7 @@ func (fs *FS) Unlink(path string, context *fuse.Context) (code fuse.Status) {
return fuse.ToStatus(err)
}
+// Symlink implements pathfs.Filesystem.
func (fs *FS) Symlink(target string, linkName string, context *fuse.Context) (code fuse.Status) {
tlog.Debug.Printf("Symlink(\"%s\", \"%s\")", target, linkName)
if fs.isFiltered(linkName) {
@@ -359,6 +374,7 @@ func (fs *FS) Symlink(target string, linkName string, context *fuse.Context) (co
return fuse.ToStatus(err)
}
+// Rename implements pathfs.Filesystem.
func (fs *FS) Rename(oldPath string, newPath string, context *fuse.Context) (code fuse.Status) {
if fs.isFiltered(newPath) {
return fuse.EPERM
@@ -437,6 +453,7 @@ func (fs *FS) Rename(oldPath string, newPath string, context *fuse.Context) (cod
return fuse.OK
}
+// Link implements pathfs.Filesystem.
func (fs *FS) Link(oldPath string, newPath string, context *fuse.Context) (code fuse.Status) {
if fs.isFiltered(newPath) {
return fuse.EPERM
@@ -474,6 +491,7 @@ func (fs *FS) Link(oldPath string, newPath string, context *fuse.Context) (code
return fuse.ToStatus(os.Link(cOldPath, cNewPath))
}
+// Access implements pathfs.Filesystem.
func (fs *FS) Access(path string, mode uint32, context *fuse.Context) (code fuse.Status) {
if fs.isFiltered(path) {
return fuse.EPERM
@@ -485,18 +503,22 @@ func (fs *FS) Access(path string, mode uint32, context *fuse.Context) (code fuse
return fuse.ToStatus(syscall.Access(cPath, mode))
}
+// GetXAttr implements pathfs.Filesystem.
func (fs *FS) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
return nil, fuse.ENOSYS
}
+// SetXAttr implements pathfs.Filesystem.
func (fs *FS) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
return fuse.ENOSYS
}
+// ListXAttr implements pathfs.Filesystem.
func (fs *FS) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
return nil, fuse.ENOSYS
}
+// RemoveXAttr implements pathfs.Filesystem.
func (fs *FS) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
return fuse.ENOSYS
}
diff --git a/internal/fusefrontend/fs_dir.go b/internal/fusefrontend/fs_dir.go
index ab97932..a3b2ccf 100644
--- a/internal/fusefrontend/fs_dir.go
+++ b/internal/fusefrontend/fs_dir.go
@@ -40,6 +40,7 @@ func (fs *FS) mkdirWithIv(cPath string, mode uint32) error {
return err
}
+// Mkdir implements pathfs.FileSystem
func (fs *FS) Mkdir(newPath string, mode uint32, context *fuse.Context) (code fuse.Status) {
if fs.isFiltered(newPath) {
return fuse.EPERM
@@ -97,6 +98,7 @@ func (fs *FS) Mkdir(newPath string, mode uint32, context *fuse.Context) (code fu
return fuse.OK
}
+// Rmdir implements pathfs.FileSystem
func (fs *FS) Rmdir(path string, context *fuse.Context) (code fuse.Status) {
cPath, err := fs.getBackingPath(path)
if err != nil {
@@ -215,6 +217,7 @@ func (fs *FS) Rmdir(path string, context *fuse.Context) (code fuse.Status) {
return fuse.OK
}
+// OpenDir implements pathfs.FileSystem
func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
tlog.Debug.Printf("OpenDir(%s)", dirName)
cDirName, err := fs.encryptPath(dirName)
diff --git a/internal/fusefrontend_reverse/ino_map.go b/internal/fusefrontend_reverse/ino_map.go
index 5217732..9412343 100644
--- a/internal/fusefrontend_reverse/ino_map.go
+++ b/internal/fusefrontend_reverse/ino_map.go
@@ -4,7 +4,7 @@ import (
"sync/atomic"
)
-func NewInoGen() *inoGenT {
+func newInoGen() *inoGenT {
var ino uint64 = 1
return &inoGenT{&ino}
}
diff --git a/internal/fusefrontend_reverse/reverse_longnames.go b/internal/fusefrontend_reverse/reverse_longnames.go
index b3d21c9..5ad95b1 100644
--- a/internal/fusefrontend_reverse/reverse_longnames.go
+++ b/internal/fusefrontend_reverse/reverse_longnames.go
@@ -70,9 +70,9 @@ func (rfs *reverseFS) findLongnameParent(dir string, dirIV []byte, longname stri
}
if hit == "" {
return "", syscall.ENOENT
- } else {
- return hit, nil
}
+
+ return hit, nil
}
func (rfs *reverseFS) newNameFile(relPath string) (nodefs.File, fuse.Status) {
diff --git a/internal/fusefrontend_reverse/rfile.go b/internal/fusefrontend_reverse/rfile.go
index 2656b7b..5606e70 100644
--- a/internal/fusefrontend_reverse/rfile.go
+++ b/internal/fusefrontend_reverse/rfile.go
@@ -39,7 +39,7 @@ func (rfs *reverseFS) NewFile(relPath string, flags uint32) (nodefs.File, fuse.S
id := derivePathIV(relPath, ivPurposeFileID)
header := contentenc.FileHeader{
Version: contentenc.CurrentVersion,
- Id: id,
+ ID: id,
}
return &reverseFile{
File: nodefs.NewDefaultFile(),
@@ -58,7 +58,7 @@ func (rf *reverseFile) GetAttr(*fuse.Attr) fuse.Status {
// encryptBlocks - encrypt "plaintext" into a number of ciphertext blocks.
// "plaintext" must already be block-aligned.
-func (rf *reverseFile) encryptBlocks(plaintext []byte, firstBlockNo uint64, fileId []byte, block0IV []byte) []byte {
+func (rf *reverseFile) encryptBlocks(plaintext []byte, firstBlockNo uint64, fileID []byte, block0IV []byte) []byte {
nonce := make([]byte, len(block0IV))
copy(nonce, block0IV)
block0IVlow := binary.BigEndian.Uint64(block0IV[8:])
@@ -70,7 +70,7 @@ func (rf *reverseFile) encryptBlocks(plaintext []byte, firstBlockNo uint64, file
for blockNo := firstBlockNo; inBuf.Len() > 0; blockNo++ {
binary.BigEndian.PutUint64(nonceLow, block0IVlow+blockNo)
inBlock := inBuf.Next(bs)
- outBlock := rf.contentEnc.EncryptBlockNonce(inBlock, blockNo, fileId, nonce)
+ outBlock := rf.contentEnc.EncryptBlockNonce(inBlock, blockNo, fileID, nonce)
outBuf.Write(outBlock)
}
return outBuf.Bytes()
@@ -95,7 +95,7 @@ func (rf *reverseFile) readBackingFile(off uint64, length uint64) (out []byte, e
plaintext = plaintext[0:n]
// Encrypt blocks
- ciphertext := rf.encryptBlocks(plaintext, blocks[0].BlockNo, rf.header.Id, rf.block0IV)
+ ciphertext := rf.encryptBlocks(plaintext, blocks[0].BlockNo, rf.header.ID, rf.block0IV)
// Crop down to the relevant part
lenHave := len(ciphertext)
@@ -118,7 +118,7 @@ func (rf *reverseFile) Read(buf []byte, ioff int64) (resultData fuse.ReadResult,
var header []byte
// Synthesize file header
- if off < contentenc.HEADER_LEN {
+ if off < contentenc.HeaderLen {
header = rf.header.Pack()
// Truncate to requested part
end := int(off) + len(buf)
diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go
index e49807b..ab65ba3 100644
--- a/internal/fusefrontend_reverse/rfs.go
+++ b/internal/fusefrontend_reverse/rfs.go
@@ -20,6 +20,7 @@ import (
)
const (
+ // DirIVMode is the mode to use for Dir IV files.
DirIVMode = syscall.S_IFREG | 0400
)
@@ -42,8 +43,10 @@ type reverseFS struct {
inoMapLock sync.Mutex
}
-// Encrypted FUSE overlay filesystem
-func NewFS(args fusefrontend.Args) *reverseFS {
+var _ pathfs.FileSystem = &reverseFS{}
+
+// NewFS returns an encrypted FUSE overlay filesystem
+func NewFS(args fusefrontend.Args) pathfs.FileSystem {
cryptoCore := cryptocore.New(args.Masterkey, args.CryptoBackend, contentenc.DefaultIVBits)
contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS)
nameTransform := nametransform.New(cryptoCore, args.LongNames)
@@ -55,7 +58,7 @@ func NewFS(args fusefrontend.Args) *reverseFS {
args: args,
nameTransform: nameTransform,
contentEnc: contentEnc,
- inoGen: NewInoGen(),
+ inoGen: newInoGen(),
inoMap: map[devIno]uint64{},
}
}
diff --git a/internal/nametransform/diriv.go b/internal/nametransform/diriv.go
index 9c3c1d1..6687b40 100644
--- a/internal/nametransform/diriv.go
+++ b/internal/nametransform/diriv.go
@@ -14,10 +14,10 @@ import (
)
const (
- // identical to AES block size
+ // DirIVLen is identical to AES block size
DirIVLen = 16
- // dirIV is stored in this file. Exported because we have to ignore this
- // name in directory listing.
+ // DirIVFilename is the filename used to store directory IV.
+ // Exported because we have to ignore this name in directory listing.
DirIVFilename = "gocryptfs.diriv"
)
diff --git a/internal/nametransform/longnames.go b/internal/nametransform/longnames.go
index e61e21b..be00bb4 100644
--- a/internal/nametransform/longnames.go
+++ b/internal/nametransform/longnames.go
@@ -14,6 +14,7 @@ import (
)
const (
+ // LongNameSuffix is the suffix used for files with long names.
// Files with long names are stored in two files:
// gocryptfs.longname.[sha256] <--- File content, prefix = gocryptfs.longname.
// gocryptfs.longname.[sha256].name <--- File name, suffix = .name
@@ -31,12 +32,13 @@ func HashLongName(name string) string {
// Values returned by IsLongName
const (
- // File that stores the file content.
+ // LongNameContent is the file that stores the file content.
// Example: gocryptfs.longname.URrM8kgxTKYMgCk4hKk7RO9Lcfr30XQof4L_5bD9Iro=
LongNameContent = iota
- // File that stores the full encrypted filename.
+ // LongNameFilename is the file that stores the full encrypted filename.
// Example: gocryptfs.longname.URrM8kgxTKYMgCk4hKk7RO9Lcfr30XQof4L_5bD9Iro=.name
LongNameFilename = iota
+ // LongNameNone is used when the file does not have a long name.
// Example: i1bpTaVLZq7sRNA9mL_2Ig==
LongNameNone = iota
)
diff --git a/internal/nametransform/names.go b/internal/nametransform/names.go
index 4850138..05ae75e 100644
--- a/internal/nametransform/names.go
+++ b/internal/nametransform/names.go
@@ -1,4 +1,4 @@
-// Package namtransforms encrypts and decrypts filenames.
+// Package nametransform encrypts and decrypts filenames.
package nametransform
import (
@@ -12,12 +12,14 @@ import (
"github.com/rfjakob/gocryptfs/internal/tlog"
)
+// NameTransform is used to transform filenames.
type NameTransform struct {
cryptoCore *cryptocore.CryptoCore
longNames bool
DirIVCache dirIVCache
}
+// New returns a new NameTransform instance.
func New(c *cryptocore.CryptoCore, longNames bool) *NameTransform {
return &NameTransform{
cryptoCore: c,
@@ -51,7 +53,7 @@ func (n *NameTransform) DecryptName(cipherName string, iv []byte) (string, error
return plain, err
}
-// encryptName - encrypt "plainName", return base64-encoded "cipherName64".
+// EncryptName encrypts "plainName", returns a base64-encoded "cipherName64".
// Used internally by EncryptPathDirIV().
// The encryption is either CBC or EME, depending on "useEME".
//
diff --git a/internal/prefer_openssl/prefer_go1.5.go b/internal/prefer_openssl/prefer_go1.5.go
index 7095314..b89e495 100644
--- a/internal/prefer_openssl/prefer_go1.5.go
+++ b/internal/prefer_openssl/prefer_go1.5.go
@@ -7,6 +7,7 @@ import (
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
)
+// PreferOpenSSL returns true if OpenSSL should be used.
func PreferOpenSSL() bool {
if stupidgcm.BuiltWithoutOpenssl {
return false
diff --git a/internal/readpassword/read.go b/internal/readpassword/read.go
index 653868e..c1fc3de 100644
--- a/internal/readpassword/read.go
+++ b/internal/readpassword/read.go
@@ -17,8 +17,8 @@ const (
exitCode = 9
)
-// Once() tries to get a password from the user, either from the terminal,
-// extpass or stdin.
+// Once tries to get a password from the user, either from the terminal, extpass
+// or stdin.
func Once(extpass string) string {
if extpass != "" {
return readPasswordExtpass(extpass)
@@ -29,8 +29,8 @@ func Once(extpass string) string {
return readPasswordTerminal("Password: ")
}
-// Twice() is the same as Once but will prompt twice if we get
-// the password from the terminal.
+// Twice is the same as Once but will prompt twice if we get the password from
+// the terminal.
func Twice(extpass string) string {
if extpass != "" {
return readPasswordExtpass(extpass)
diff --git a/internal/siv_aead/siv_aead.go b/internal/siv_aead/siv_aead.go
index a0ed882..c68ecdb 100644
--- a/internal/siv_aead/siv_aead.go
+++ b/internal/siv_aead/siv_aead.go
@@ -3,6 +3,8 @@
package siv_aead
import (
+ "crypto/cipher"
+
"github.com/jacobsa/crypto/siv"
)
@@ -10,7 +12,10 @@ type sivAead struct {
key []byte
}
-func New(key []byte) *sivAead {
+var _ cipher.AEAD = &sivAead{}
+
+// New returns a new cipher.AEAD implementation.
+func New(key []byte) cipher.AEAD {
return &sivAead{
key: key,
}
@@ -25,7 +30,7 @@ func (s *sivAead) Overhead() int {
return 16
}
-// Seal - encrypt "in" using "nonce" and "authData" and append the result to "dst"
+// Seal encrypts "in" using "nonce" and "authData" and append the result to "dst"
func (s *sivAead) Seal(dst, nonce, plaintext, authData []byte) []byte {
if len(nonce) != 16 {
// SIV supports any nonce size, but in gocryptfs we exclusively use 16.
@@ -43,7 +48,7 @@ func (s *sivAead) Seal(dst, nonce, plaintext, authData []byte) []byte {
return out
}
-// Open - decrypt "in" using "nonce" and "authData" and append the result to "dst"
+// Open decrypts "in" using "nonce" and "authData" and append the result to "dst"
func (s *sivAead) Open(dst, nonce, ciphertext, authData []byte) ([]byte, error) {
if len(nonce) != 16 {
// SIV supports any nonce size, but in gocryptfs we exclusively use 16.
diff --git a/internal/stupidgcm/stupidgcm.go b/internal/stupidgcm/stupidgcm.go
index db9e6ef..58027f8 100644
--- a/internal/stupidgcm/stupidgcm.go
+++ b/internal/stupidgcm/stupidgcm.go
@@ -9,6 +9,7 @@ package stupidgcm
import "C"
import (
+ "crypto/cipher"
"fmt"
"log"
"unsafe"
@@ -28,7 +29,10 @@ type stupidGCM struct {
key []byte
}
-func New(key []byte) stupidGCM {
+var _ cipher.AEAD = &stupidGCM{}
+
+// New returns a new cipher.AEAD implementation..
+func New(key []byte) cipher.AEAD {
if len(key) != keyLen {
log.Panicf("Only %d-byte keys are supported", keyLen)
}
@@ -43,7 +47,7 @@ func (g stupidGCM) Overhead() int {
return tagLen
}
-// Seal - encrypt "in" using "iv" and "authData" and append the result to "dst"
+// Seal encrypts "in" using "iv" and "authData" and append the result to "dst"
func (g stupidGCM) Seal(dst, iv, in, authData []byte) []byte {
if len(iv) != ivLen {
log.Panicf("Only %d-byte IVs are supported", ivLen)
@@ -114,7 +118,7 @@ func (g stupidGCM) Seal(dst, iv, in, authData []byte) []byte {
return append(dst, buf...)
}
-// Open - decrypt "in" using "iv" and "authData" and append the result to "dst"
+// Open decrypts "in" using "iv" and "authData" and append the result to "dst"
func (g stupidGCM) Open(dst, iv, in, authData []byte) ([]byte, error) {
if len(iv) != ivLen {
log.Panicf("Only %d-byte IVs are supported", ivLen)
diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go
index 646dfc3..c9f6ee0 100644
--- a/internal/syscallcompat/sys_linux.go
+++ b/internal/syscallcompat/sys_linux.go
@@ -38,22 +38,27 @@ func EnospcPrealloc(fd int, off int64, len int64) (err error) {
}
}
+// Fallocate wraps the Fallocate syscall.
func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
return syscall.Fallocate(fd, mode, off, len)
}
+// Openat wraps the Openat syscall.
func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
return syscall.Openat(dirfd, path, flags, mode)
}
+// Renameat wraps the Renameat syscall.
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
return syscall.Renameat(olddirfd, oldpath, newdirfd, newpath)
}
+// Unlinkat wraps the Unlinkat syscall.
func Unlinkat(dirfd int, path string) error {
return syscall.Unlinkat(dirfd, path)
}
+// Mknodat wraps the Mknodat syscall.
func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
return syscall.Mknodat(dirfd, path, mode, dev)
}
diff --git a/internal/tlog/log.go b/internal/tlog/log.go
index a770df8..8db3de2 100644
--- a/internal/tlog/log.go
+++ b/internal/tlog/log.go
@@ -12,21 +12,34 @@ import (
)
const (
+ // ProgramName is used in log reports.
ProgramName = "gocryptfs"
wpanicMsg = "-wpanic turns this warning into a panic: "
)
// Escape sequences for terminal colors. These will be empty strings if stdout
// is not a terminal.
-var ColorReset, ColorGrey, ColorRed, ColorGreen, ColorYellow string
+var (
+ // ColorReset is used to reset terminal colors.
+ ColorReset string
+ // ColorGrey is a terminal color setting string.
+ ColorGrey string
+ // ColorRed is a terminal color setting string.
+ ColorRed string
+ // ColorGreen is a terminal color setting string.
+ ColorGreen string
+ // ColorYellow is a terminal color setting string.
+ ColorYellow string
+)
+// JSONDump writes the object in json form.
func JSONDump(obj interface{}) string {
b, err := json.MarshalIndent(obj, "", "\t")
if err != nil {
return err.Error()
- } else {
- return string(b)
}
+
+ return string(b)
}
// toggledLogger - a Logger than can be enabled and disabled