diff options
author | Jakob Unterwurzacher | 2015-11-01 01:32:33 +0100 |
---|---|---|
committer | Jakob Unterwurzacher | 2015-11-01 01:38:27 +0100 |
commit | 76311b60f2e208dbd93e1e7b6e9794770c14fede (patch) | |
tree | fa71d48744fd1ad6de26aaadd03f2440e4d4103d /cryptfs/cryptfs_content.go | |
parent | 73fa8efdb27172210b9751eb86689287db0b1170 (diff) |
Add file header (on-disk-format change)
Format: [ "Version" uint16 big endian ] [ "Id" 16 random bytes ]
Quoting SECURITY.md:
* Every file has a header that contains a 16-byte random *file id*
* Each block uses the file id and its block number as GCM *authentication data*
* This means the position of the blocks is protected as well. The blocks
can not be reordered or copied between different files without
causing an decryption error.
Diffstat (limited to 'cryptfs/cryptfs_content.go')
-rw-r--r-- | cryptfs/cryptfs_content.go | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/cryptfs/cryptfs_content.go b/cryptfs/cryptfs_content.go index 7a1859a..03253d3 100644 --- a/cryptfs/cryptfs_content.go +++ b/cryptfs/cryptfs_content.go @@ -30,14 +30,14 @@ type CryptFile struct { } // DecryptBlocks - Decrypt a number of blocks -func (be *CryptFS) DecryptBlocks(ciphertext []byte, firstBlockNo uint64) ([]byte, error) { +func (be *CryptFS) 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) + pBlock, err = be.DecryptBlock(cBlock, firstBlockNo, fileId) if err != nil { break } @@ -51,7 +51,7 @@ func (be *CryptFS) DecryptBlocks(ciphertext []byte, firstBlockNo uint64) ([]byte // // 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 *CryptFS) DecryptBlock(ciphertext []byte, blockNo uint64) ([]byte, error) { +func (be *CryptFS) DecryptBlock(ciphertext []byte, blockNo uint64, fileId []byte) ([]byte, error) { // Empty block? if len(ciphertext) == 0 { @@ -77,6 +77,7 @@ func (be *CryptFS) DecryptBlock(ciphertext []byte, blockNo uint64) ([]byte, erro // Decrypt var plaintext []byte aData := make([]byte, 8) + aData = append(aData, fileId...) binary.BigEndian.PutUint64(aData, blockNo) plaintext, err := be.gcm.Open(plaintext, nonce, ciphertext, aData) @@ -89,8 +90,8 @@ func (be *CryptFS) DecryptBlock(ciphertext []byte, blockNo uint64) ([]byte, erro return plaintext, nil } -// encryptBlock - Encrypt and add MAC using GCM -func (be *CryptFS) EncryptBlock(plaintext []byte, blockNo uint64) []byte { +// encryptBlock - Encrypt and add IV and MAC +func (be *CryptFS) EncryptBlock(plaintext []byte, blockNo uint64, fileId []byte) []byte { // Empty block? if len(plaintext) == 0 { @@ -103,6 +104,7 @@ func (be *CryptFS) EncryptBlock(plaintext []byte, blockNo uint64) []byte { // Encrypt plaintext and append to nonce aData := make([]byte, 8) binary.BigEndian.PutUint64(aData, blockNo) + aData = append(aData, fileId...) ciphertext := be.gcm.Seal(nonce, nonce, plaintext, aData) return ciphertext @@ -118,6 +120,7 @@ func (be *CryptFS) SplitRange(offset uint64, length uint64) []intraBlock { 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 @@ -134,6 +137,9 @@ func (be *CryptFS) PlainSize(size uint64) uint64 { return 0 } + // Account for header + size -= HEADER_LEN + overhead := be.cipherBS - be.plainBS nBlocks := (size + be.cipherBS - 1) / be.cipherBS if nBlocks*overhead > size { @@ -171,7 +177,7 @@ func (be *CryptFS) CiphertextRange(offset uint64, length uint64) (alignedOffset firstBlockNo := offset / be.plainBS lastBlockNo := (offset + length - 1) / be.plainBS - alignedOffset = firstBlockNo * be.cipherBS + alignedOffset = HEADER_LEN + firstBlockNo * be.cipherBS alignedLength = (lastBlockNo - firstBlockNo + 1) * be.cipherBS skipBytes = int(skip) @@ -232,5 +238,5 @@ func (be *CryptFS) BlockNoPlainOff(plainOffset uint64) uint64 { // Get the block number at ciphter-text offset func (be *CryptFS) BlockNoCipherOff(cipherOffset uint64) uint64 { - return cipherOffset / be.cipherBS + return (cipherOffset - HEADER_LEN) / be.cipherBS } |