From a3d286069f989dd16c6f91930a0df9fedfa2dd64 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Tue, 6 Oct 2015 22:27:37 +0200 Subject: [PATCH] Use block number as authentication data --- cryptfs/config_file.go | 4 ++-- cryptfs/cryptfs.go | 1 - cryptfs/cryptfs_content.go | 15 ++++++++++----- cryptfs/openssl_aead.go | 12 ++++-------- pathfs_frontend/file.go | 11 +++++------ 5 files changed, 21 insertions(+), 22 deletions(-) diff --git a/cryptfs/config_file.go b/cryptfs/config_file.go index 74eb3b2..82f7e72 100644 --- a/cryptfs/config_file.go +++ b/cryptfs/config_file.go @@ -39,7 +39,7 @@ func CreateConfFile(filename string, password string) error { // Lock master key using password-based key cfs := NewCryptFS(scryptHash, false) - cf.EncryptedKey = cfs.EncryptBlock(key) + cf.EncryptedKey = cfs.EncryptBlock(key, 0) // Write file to disk err := cf.WriteFile() @@ -73,7 +73,7 @@ func LoadConfFile(filename string, password string) ([]byte, error) { // We use stock go GCM instead of OpenSSL here as speed is not important // and we get better error messages cfs := NewCryptFS(scryptHash, false) - key, err := cfs.DecryptBlock(cf.EncryptedKey) + key, err := cfs.DecryptBlock(cf.EncryptedKey, 0) if err != nil { Warn.Printf("Failed to unlock master key: %s\n", err.Error()) return nil, err diff --git a/cryptfs/cryptfs.go b/cryptfs/cryptfs.go index d7d1516..1556757 100644 --- a/cryptfs/cryptfs.go +++ b/cryptfs/cryptfs.go @@ -13,7 +13,6 @@ const ( KEY_LEN = 32 // AES-256 NONCE_LEN = 12 AUTH_TAG_LEN = 16 - FILEID_LEN = 16 ) type CryptFS struct { diff --git a/cryptfs/cryptfs_content.go b/cryptfs/cryptfs_content.go index 6444b8b..cb309ea 100644 --- a/cryptfs/cryptfs_content.go +++ b/cryptfs/cryptfs_content.go @@ -3,6 +3,7 @@ package cryptfs // File content encryption / decryption import ( + "encoding/binary" "bytes" "crypto/cipher" "crypto/md5" @@ -29,18 +30,19 @@ type CryptFile struct { } // DecryptBlocks - Decrypt a number of blocks -func (be *CryptFS) DecryptBlocks(ciphertext []byte) ([]byte, error) { +func (be *CryptFS) DecryptBlocks(ciphertext []byte, firstBlockNo uint64) ([]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) + pBlock, err = be.DecryptBlock(cBlock, firstBlockNo) if err != nil { break } pBuf.Write(pBlock) + firstBlockNo++ } return pBuf.Bytes(), err } @@ -49,7 +51,7 @@ func (be *CryptFS) DecryptBlocks(ciphertext []byte) ([]byte, error) { // // 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) ([]byte, error) { +func (be *CryptFS) DecryptBlock(ciphertext []byte, blockNo uint64) ([]byte, error) { // Empty block? if len(ciphertext) == 0 { @@ -74,7 +76,8 @@ func (be *CryptFS) DecryptBlock(ciphertext []byte) ([]byte, error) { // Decrypt var plaintext []byte - + aData := make([]byte, 8) + binary.BigEndian.PutUint64(aData, blockNo) plaintext, err := be.gcm.Open(plaintext, nonce, ciphertext, nil) if err != nil { @@ -87,7 +90,7 @@ func (be *CryptFS) DecryptBlock(ciphertext []byte) ([]byte, error) { } // encryptBlock - Encrypt and add MAC using GCM -func (be *CryptFS) EncryptBlock(plaintext []byte) []byte { +func (be *CryptFS) EncryptBlock(plaintext []byte, blockNo uint64) []byte { // Empty block? if len(plaintext) == 0 { @@ -98,6 +101,8 @@ func (be *CryptFS) EncryptBlock(plaintext []byte) []byte { nonce := gcmNonce.Get() // Encrypt plaintext and append to nonce + aData := make([]byte, 8) + binary.BigEndian.PutUint64(aData, blockNo) ciphertext := be.gcm.Seal(nonce, nonce, plaintext, nil) return ciphertext diff --git a/cryptfs/openssl_aead.go b/cryptfs/openssl_aead.go index 9baa6d5..1ec7c48 100644 --- a/cryptfs/openssl_aead.go +++ b/cryptfs/openssl_aead.go @@ -63,10 +63,6 @@ func (be opensslGCM) Seal(dst, nonce, plaintext, data []byte) []byte { // The ciphertext and dst may alias exactly or not at all. func (be opensslGCM) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { - if len(data) > 0 { - panic("Extra data is not supported") - } - l := len(ciphertext) tag := ciphertext[l-AUTH_TAG_LEN : l] ciphertext = ciphertext[0 : l-AUTH_TAG_LEN] @@ -76,6 +72,10 @@ func (be opensslGCM) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { if err != nil { return nil, err } + err = dctx.ExtraData(data) + if err != nil { + return nil, err + } part, err := dctx.DecryptUpdate(ciphertext) if err != nil { return nil, err @@ -90,10 +90,6 @@ func (be opensslGCM) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { return nil, err } plainBuf.Write(part) - err = dctx.ExtraData(data) - if err != nil { - return nil, err - } return plainBuf.Bytes(), nil } diff --git a/pathfs_frontend/file.go b/pathfs_frontend/file.go index 7f5cc90..3304267 100644 --- a/pathfs_frontend/file.go +++ b/pathfs_frontend/file.go @@ -80,13 +80,12 @@ func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) { } // Truncate ciphertext buffer down to actually read bytes ciphertext = ciphertext[0:n] - { - blockNo := alignedOffset / f.cfs.CipherBS() - cryptfs.Debug.Printf("ReadAt offset=%d bytes (%d blocks), want=%d, got=%d\n", alignedOffset, blockNo, alignedLength, n) - } + + blockNo := alignedOffset / f.cfs.CipherBS() + cryptfs.Debug.Printf("ReadAt offset=%d bytes (%d blocks), want=%d, got=%d\n", alignedOffset, blockNo, alignedLength, n) // Decrypt it - plaintext, err := f.cfs.DecryptBlocks(ciphertext) + plaintext, err := f.cfs.DecryptBlocks(ciphertext, blockNo) if err != nil { blockNo := (alignedOffset + uint64(len(plaintext))) / f.cfs.PlainBS() cipherOff := blockNo * f.cfs.CipherBS() @@ -159,7 +158,7 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) { // Write blockOffset, _ := b.CiphertextRange() - blockData = f.cfs.EncryptBlock(blockData) + blockData = f.cfs.EncryptBlock(blockData, b.BlockNo) cryptfs.Debug.Printf("ino%d: Writing %d bytes to block #%d, md5=%s\n", f.ino, len(blockData), b.BlockNo, cryptfs.Debug.Md5sum(blockData)) if len(blockData) != int(f.cfs.CipherBS()) { cryptfs.Debug.Printf("ino%d: Writing partial block #%d (%d bytes)\n", f.ino, b.BlockNo, len(blockData))