summaryrefslogtreecommitdiff
path: root/cryptfs
diff options
context:
space:
mode:
Diffstat (limited to 'cryptfs')
-rw-r--r--cryptfs/address_translation.go79
-rw-r--r--cryptfs/config_file.go2
-rw-r--r--cryptfs/content_test.go22
-rw-r--r--cryptfs/cryptfs.go7
-rw-r--r--cryptfs/cryptfs_content.go115
-rw-r--r--cryptfs/file_header.go10
-rw-r--r--cryptfs/intrablock.go16
7 files changed, 113 insertions, 138 deletions
diff --git a/cryptfs/address_translation.go b/cryptfs/address_translation.go
new file mode 100644
index 0000000..dfc6ef9
--- /dev/null
+++ b/cryptfs/address_translation.go
@@ -0,0 +1,79 @@
+package cryptfs
+
+// CryptFS methods that translate offsets between ciphertext and plaintext
+
+// get the block number at plain-text offset
+func (be *CryptFS) PlainOffToBlockNo(plainOffset uint64) uint64 {
+ return plainOffset / be.plainBS
+}
+
+// get the block number at ciphter-text offset
+func (be *CryptFS) CipherOffToBlockNo(cipherOffset uint64) uint64 {
+ return (cipherOffset - HEADER_LEN) / be.cipherBS
+}
+
+// get ciphertext offset of block "blockNo"
+func (be *CryptFS) BlockNoToCipherOff(blockNo uint64) uint64 {
+ return HEADER_LEN + blockNo*be.cipherBS
+}
+
+// get plaintext offset of block "blockNo"
+func (be *CryptFS) BlockNoToPlainOff(blockNo uint64) uint64 {
+ return blockNo * be.plainBS
+}
+
+// PlainSize - calculate plaintext size from ciphertext size
+func (be *CryptFS) CipherSizeToPlainSize(cipherSize uint64) uint64 {
+
+ // Zero sized files stay zero-sized
+ if cipherSize == 0 {
+ return 0
+ }
+
+ // Block number at last byte
+ blockNo := be.CipherOffToBlockNo(cipherSize - 1)
+ blockCount := blockNo + 1
+
+ overhead := BLOCK_OVERHEAD*blockCount + HEADER_LEN
+
+ return cipherSize - overhead
+}
+
+// CipherSize - calculate ciphertext size from plaintext size
+func (be *CryptFS) PlainSizeToCipherSize(plainSize uint64) uint64 {
+
+ // Block number at last byte
+ blockNo := be.PlainOffToBlockNo(plainSize - 1)
+ blockCount := blockNo + 1
+
+ overhead := BLOCK_OVERHEAD*blockCount + HEADER_LEN
+
+ return plainSize + overhead
+}
+
+// Split a plaintext byte range into (possibly partial) blocks
+func (be *CryptFS) ExplodePlainRange(offset uint64, length uint64) []intraBlock {
+ var blocks []intraBlock
+ var nextBlock intraBlock
+ nextBlock.fs = be
+
+ for length > 0 {
+ nextBlock.BlockNo = be.PlainOffToBlockNo(offset)
+ nextBlock.Skip = offset - be.BlockNoToPlainOff(nextBlock.BlockNo)
+
+ // Minimum of remaining data and remaining space in the block
+ nextBlock.Length = MinUint64(length, be.plainBS-nextBlock.Skip)
+
+ blocks = append(blocks, nextBlock)
+ offset += nextBlock.Length
+ length -= nextBlock.Length
+ }
+ return blocks
+}
+
+func MinUint64(x uint64, y uint64) uint64 {
+ if x < y {
+ return x
+ }
+ return y
+}
diff --git a/cryptfs/config_file.go b/cryptfs/config_file.go
index 7e762ad..16a3eec 100644
--- a/cryptfs/config_file.go
+++ b/cryptfs/config_file.go
@@ -1,8 +1,8 @@
package cryptfs
import (
- "fmt"
"encoding/json"
+ "fmt"
"io/ioutil"
)
import "os"
diff --git a/cryptfs/content_test.go b/cryptfs/content_test.go
index 4e1b447..37635f0 100644
--- a/cryptfs/content_test.go
+++ b/cryptfs/content_test.go
@@ -16,7 +16,7 @@ func TestSplitRange(t *testing.T) {
testRange{0, 10},
testRange{234, 6511},
testRange{65444, 54},
- testRange{0, 1024*1024},
+ testRange{0, 1024 * 1024},
testRange{0, 65536},
testRange{6654, 8945})
@@ -24,8 +24,8 @@ func TestSplitRange(t *testing.T) {
f := NewCryptFS(key, true)
for _, r := range ranges {
- parts := f.SplitRange(r.offset, r.length)
- var lastBlockNo uint64 = 1<<63
+ parts := f.ExplodePlainRange(r.offset, r.length)
+ var lastBlockNo uint64 = 1 << 63
for _, p := range parts {
if p.BlockNo == lastBlockNo {
t.Errorf("Duplicate block number %d", p.BlockNo)
@@ -51,11 +51,15 @@ func TestCiphertextRange(t *testing.T) {
f := NewCryptFS(key, true)
for _, r := range ranges {
- alignedOffset, alignedLength, skipBytes := f.CiphertextRange(r.offset, r.length)
+
+ blocks := f.ExplodePlainRange(r.offset, r.length)
+ alignedOffset, alignedLength := blocks[0].JointCiphertextRange(blocks)
+ skipBytes := blocks[0].Skip
+
if alignedLength < r.length {
t.Errorf("alignedLength=%s is smaller than length=%d", alignedLength, r.length)
}
- if (alignedOffset - HEADER_LEN)%f.cipherBS != 0 {
+ if (alignedOffset-HEADER_LEN)%f.cipherBS != 0 {
t.Errorf("alignedOffset=%d is not aligned", alignedOffset)
}
if r.offset%f.plainBS != 0 && skipBytes == 0 {
@@ -68,19 +72,19 @@ func TestBlockNo(t *testing.T) {
key := make([]byte, KEY_LEN)
f := NewCryptFS(key, true)
- b := f.BlockNoCipherOff(788)
+ b := f.CipherOffToBlockNo(788)
if b != 0 {
t.Errorf("actual: %d", b)
}
- b = f.BlockNoCipherOff(HEADER_LEN + f.CipherBS())
+ b = f.CipherOffToBlockNo(HEADER_LEN + f.cipherBS)
if b != 1 {
t.Errorf("actual: %d", b)
}
- b = f.BlockNoPlainOff(788)
+ b = f.PlainOffToBlockNo(788)
if b != 0 {
t.Errorf("actual: %d", b)
}
- b = f.BlockNoPlainOff(f.PlainBS())
+ b = f.PlainOffToBlockNo(f.plainBS)
if b != 1 {
t.Errorf("actual: %d", b)
}
diff --git a/cryptfs/cryptfs.go b/cryptfs/cryptfs.go
index 0593214..9fe492d 100644
--- a/cryptfs/cryptfs.go
+++ b/cryptfs/cryptfs.go
@@ -13,7 +13,7 @@ const (
KEY_LEN = 32 // AES-256
NONCE_LEN = 12
AUTH_TAG_LEN = 16
- BLOCK_OVERHEAD = NONCE_LEN + AUTH_TAG_LEN
+ BLOCK_OVERHEAD = NONCE_LEN + AUTH_TAG_LEN
)
type CryptFS struct {
@@ -61,8 +61,3 @@ func NewCryptFS(key []byte, useOpenssl bool) *CryptFS {
func (be *CryptFS) PlainBS() uint64 {
return be.plainBS
}
-
-// Get ciphertext block size
-func (be *CryptFS) CipherBS() uint64 {
- return be.cipherBS
-}
diff --git a/cryptfs/cryptfs_content.go b/cryptfs/cryptfs_content.go
index 03253d3..d74570f 100644
--- a/cryptfs/cryptfs_content.go
+++ b/cryptfs/cryptfs_content.go
@@ -12,11 +12,6 @@ import (
"os"
)
-const (
- // A block of 4124 zero bytes has this md5
- ZeroBlockMd5 = "64331af89bd15a987b39855338336237"
-)
-
// md5sum - debug helper, return md5 hex string
func md5sum(buf []byte) string {
rawHash := md5.Sum(buf)
@@ -110,106 +105,6 @@ func (be *CryptFS) EncryptBlock(plaintext []byte, blockNo uint64, fileId []byte)
return ciphertext
}
-// Split a plaintext byte range into (possibly partial) blocks
-func (be *CryptFS) SplitRange(offset uint64, length uint64) []intraBlock {
- var b intraBlock
- var parts []intraBlock
-
- b.fs = be
-
- for length > 0 {
- b.BlockNo = offset / be.plainBS
- b.Skip = offset % be.plainBS
- // Minimum of remaining data and remaining space in the block
- b.Length = be.minu64(length, be.plainBS-b.Skip)
- parts = append(parts, b)
- offset += b.Length
- length -= b.Length
- }
- return parts
-}
-
-// PlainSize - calculate plaintext size from ciphertext size
-func (be *CryptFS) PlainSize(size uint64) uint64 {
-
- // Zero sized files stay zero-sized
- if size == 0 {
- return 0
- }
-
- // Account for header
- size -= HEADER_LEN
-
- overhead := be.cipherBS - be.plainBS
- nBlocks := (size + be.cipherBS - 1) / be.cipherBS
- if nBlocks*overhead > size {
- Warn.Printf("PlainSize: Negative size, returning 0 instead\n")
- return 0
- }
- size -= nBlocks * overhead
-
- return size
-}
-
-// CipherSize - calculate ciphertext size from plaintext size
-func (be *CryptFS) CipherSize(size uint64) uint64 {
- overhead := be.cipherBS - be.plainBS
- nBlocks := (size + be.plainBS - 1) / be.plainBS
- size += nBlocks * overhead
-
- return size
-}
-
-func (be *CryptFS) minu64(x uint64, y uint64) uint64 {
- if x < y {
- return x
- }
- return y
-}
-
-// CiphertextRange - Get byte range in backing ciphertext corresponding
-// to plaintext range. Returns a range aligned to ciphertext blocks.
-func (be *CryptFS) CiphertextRange(offset uint64, length uint64) (alignedOffset uint64, alignedLength uint64, skipBytes int) {
- // Decrypting the ciphertext will yield too many plaintext bytes. Skip this number
- // of bytes from the front.
- skip := offset % be.plainBS
-
- firstBlockNo := offset / be.plainBS
- lastBlockNo := (offset + length - 1) / be.plainBS
-
- alignedOffset = HEADER_LEN + firstBlockNo * be.cipherBS
- alignedLength = (lastBlockNo - firstBlockNo + 1) * be.cipherBS
-
- skipBytes = int(skip)
- return alignedOffset, alignedLength, skipBytes
-}
-
-// Get the byte range in the ciphertext corresponding to blocks
-// (full blocks!)
-func (be *CryptFS) JoinCiphertextRange(blocks []intraBlock) (uint64, uint64) {
-
- offset, _ := blocks[0].CiphertextRange()
- last := blocks[len(blocks)-1]
- length := (last.BlockNo - blocks[0].BlockNo + 1) * be.cipherBS
-
- return offset, length
-}
-
-// Crop plaintext that correspons to complete cipher blocks down to what is
-// requested according to "iblocks"
-func (be *CryptFS) CropPlaintext(plaintext []byte, blocks []intraBlock) []byte {
- offset := blocks[0].Skip
- last := blocks[len(blocks)-1]
- length := (last.BlockNo - blocks[0].BlockNo + 1) * be.plainBS
- var cropped []byte
- if offset+length > uint64(len(plaintext)) {
- cropped = plaintext[offset:]
- } else {
- cropped = plaintext[offset : offset+length]
- }
- return cropped
-}
-
// MergeBlocks - Merge newData into oldData at offset
// New block may be bigger than both newData and oldData
func (be *CryptFS) MergeBlocks(oldData []byte, newData []byte, offset int) []byte {
@@ -230,13 +125,3 @@ func (be *CryptFS) MergeBlocks(oldData []byte, newData []byte, offset int) []byt
}
return out[0:outLen]
}
-
-// Get the block number at plain-text offset
-func (be *CryptFS) BlockNoPlainOff(plainOffset uint64) uint64 {
- return plainOffset / be.plainBS
-}
-
-// Get the block number at ciphter-text offset
-func (be *CryptFS) BlockNoCipherOff(cipherOffset uint64) uint64 {
- return (cipherOffset - HEADER_LEN) / be.cipherBS
-}
diff --git a/cryptfs/file_header.go b/cryptfs/file_header.go
index 3fd7266..e16cbab 100644
--- a/cryptfs/file_header.go
+++ b/cryptfs/file_header.go
@@ -10,15 +10,15 @@ import (
)
const (
- HEADER_CURRENT_VERSION = 1 // Current on-disk-format version
- 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
+ HEADER_CURRENT_VERSION = 1 // Current on-disk-format version
+ 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
)
type FileHeader struct {
Version uint16
- Id []byte
+ Id []byte
}
// Pack - serialize fileHeader object
diff --git a/cryptfs/intrablock.go b/cryptfs/intrablock.go
index c83976c..faff471 100644
--- a/cryptfs/intrablock.go
+++ b/cryptfs/intrablock.go
@@ -19,13 +19,13 @@ func (ib *intraBlock) IsPartial() bool {
// CiphertextRange - get byte range in ciphertext file corresponding to BlockNo
// (complete block)
func (ib *intraBlock) CiphertextRange() (offset uint64, length uint64) {
- return HEADER_LEN + ib.BlockNo * ib.fs.cipherBS, ib.fs.cipherBS
+ return ib.fs.BlockNoToCipherOff(ib.BlockNo), ib.fs.cipherBS
}
// PlaintextRange - get byte range in plaintext corresponding to BlockNo
// (complete block)
func (ib *intraBlock) PlaintextRange() (offset uint64, length uint64) {
- return ib.BlockNo * ib.fs.plainBS, ib.fs.plainBS
+ return ib.fs.BlockNoToPlainOff(ib.BlockNo), ib.fs.plainBS
}
// CropBlock - crop a potentially larger plaintext block down to the relevant part
@@ -37,3 +37,15 @@ 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) {
+ firstBlock := blocks[0]
+ lastBlock := blocks[len(blocks)-1]
+
+ offset = ib.fs.BlockNoToCipherOff(firstBlock.BlockNo)
+ offsetLast := ib.fs.BlockNoToCipherOff(lastBlock.BlockNo)
+ length = offsetLast + ib.fs.cipherBS - offset
+
+ return offset, length
+}