diff --git a/internal/fusefrontend_reverse/rfile.go b/internal/fusefrontend_reverse/rfile.go index 530547a..742d697 100644 --- a/internal/fusefrontend_reverse/rfile.go +++ b/internal/fusefrontend_reverse/rfile.go @@ -2,7 +2,6 @@ package fusefrontend_reverse import ( "bytes" - "encoding/binary" "io" "os" "syscall" @@ -95,18 +94,13 @@ 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 { - nonce := make([]byte, len(block0IV)) - copy(nonce, block0IV) - block0IVlow := binary.BigEndian.Uint64(block0IV[8:]) - nonceLow := nonce[8:] - inBuf := bytes.NewBuffer(plaintext) var outBuf bytes.Buffer bs := int(rf.contentEnc.PlainBS()) 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) + iv := pathiv.BlockIV(block0IV, blockNo) + outBlock := rf.contentEnc.EncryptBlockNonce(inBlock, blockNo, fileID, iv) outBuf.Write(outBlock) } return outBuf.Bytes() diff --git a/internal/pathiv/pathiv.go b/internal/pathiv/pathiv.go index aa11b75..08042e9 100644 --- a/internal/pathiv/pathiv.go +++ b/internal/pathiv/pathiv.go @@ -2,6 +2,7 @@ package pathiv import ( "crypto/sha256" + "encoding/binary" "github.com/rfjakob/gocryptfs/internal/nametransform" ) @@ -42,3 +43,15 @@ func DeriveFile(path string) (fileIVs FileIVs) { fileIVs.Block0IV = Derive(path, PurposeBlock0IV) return fileIVs } + +// BlockIV returns the block IV for block number "blockNo". "block0iv" is the block +// IV of block #0. +func BlockIV(block0iv []byte, blockNo uint64) []byte { + iv := make([]byte, len(block0iv)) + copy(iv, block0iv) + // Add blockNo to one half of the iv + lowBytes := iv[8:] + lowInt := binary.BigEndian.Uint64(lowBytes) + binary.BigEndian.PutUint64(lowBytes, lowInt+blockNo) + return iv +} diff --git a/internal/pathiv/pathiv_test.go b/internal/pathiv/pathiv_test.go new file mode 100644 index 0000000..0cecba1 --- /dev/null +++ b/internal/pathiv/pathiv_test.go @@ -0,0 +1,28 @@ +package pathiv + +import ( + "bytes" + "encoding/hex" + "testing" +) + +// TestBlockIV makes sure we don't change the block iv derivation algorithm "BlockIV()" +// inadvertedly. +func TestBlockIV(t *testing.T) { + b0 := make([]byte, 16) + b0x := BlockIV(b0, 0) + if !bytes.Equal(b0, b0x) { + t.Errorf("b0x should be equal to b0") + } + b27 := BlockIV(b0, 0x27) + expected, _ := hex.DecodeString("00000000000000000000000000000027") + if !bytes.Equal(b27, expected) { + t.Error() + } + bff := bytes.Repeat([]byte{0xff}, 16) + b28 := BlockIV(bff, 0x28) + expected, _ = hex.DecodeString("ffffffffffffffff0000000000000027") + if !bytes.Equal(b28, expected) { + t.Errorf("\nhave=%s\nwant=%s", hex.EncodeToString(b28), hex.EncodeToString(expected)) + } +}