Use block number as authentication data
This commit is contained in:
parent
45ea8aa546
commit
a3d286069f
|
@ -39,7 +39,7 @@ func CreateConfFile(filename string, password string) error {
|
||||||
|
|
||||||
// Lock master key using password-based key
|
// Lock master key using password-based key
|
||||||
cfs := NewCryptFS(scryptHash, false)
|
cfs := NewCryptFS(scryptHash, false)
|
||||||
cf.EncryptedKey = cfs.EncryptBlock(key)
|
cf.EncryptedKey = cfs.EncryptBlock(key, 0)
|
||||||
|
|
||||||
// Write file to disk
|
// Write file to disk
|
||||||
err := cf.WriteFile()
|
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
|
// We use stock go GCM instead of OpenSSL here as speed is not important
|
||||||
// and we get better error messages
|
// and we get better error messages
|
||||||
cfs := NewCryptFS(scryptHash, false)
|
cfs := NewCryptFS(scryptHash, false)
|
||||||
key, err := cfs.DecryptBlock(cf.EncryptedKey)
|
key, err := cfs.DecryptBlock(cf.EncryptedKey, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Warn.Printf("Failed to unlock master key: %s\n", err.Error())
|
Warn.Printf("Failed to unlock master key: %s\n", err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -13,7 +13,6 @@ const (
|
||||||
KEY_LEN = 32 // AES-256
|
KEY_LEN = 32 // AES-256
|
||||||
NONCE_LEN = 12
|
NONCE_LEN = 12
|
||||||
AUTH_TAG_LEN = 16
|
AUTH_TAG_LEN = 16
|
||||||
FILEID_LEN = 16
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type CryptFS struct {
|
type CryptFS struct {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package cryptfs
|
||||||
// File content encryption / decryption
|
// File content encryption / decryption
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
@ -29,18 +30,19 @@ type CryptFile struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptBlocks - Decrypt a number of blocks
|
// 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)
|
cBuf := bytes.NewBuffer(ciphertext)
|
||||||
var err error
|
var err error
|
||||||
var pBuf bytes.Buffer
|
var pBuf bytes.Buffer
|
||||||
for cBuf.Len() > 0 {
|
for cBuf.Len() > 0 {
|
||||||
cBlock := cBuf.Next(int(be.cipherBS))
|
cBlock := cBuf.Next(int(be.cipherBS))
|
||||||
var pBlock []byte
|
var pBlock []byte
|
||||||
pBlock, err = be.DecryptBlock(cBlock)
|
pBlock, err = be.DecryptBlock(cBlock, firstBlockNo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
pBuf.Write(pBlock)
|
pBuf.Write(pBlock)
|
||||||
|
firstBlockNo++
|
||||||
}
|
}
|
||||||
return pBuf.Bytes(), err
|
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
|
// Corner case: A full-sized block of all-zero ciphertext bytes is translated
|
||||||
// to an all-zero plaintext block, i.e. file hole passtrough.
|
// 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?
|
// Empty block?
|
||||||
if len(ciphertext) == 0 {
|
if len(ciphertext) == 0 {
|
||||||
|
@ -74,7 +76,8 @@ func (be *CryptFS) DecryptBlock(ciphertext []byte) ([]byte, error) {
|
||||||
|
|
||||||
// Decrypt
|
// Decrypt
|
||||||
var plaintext []byte
|
var plaintext []byte
|
||||||
|
aData := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(aData, blockNo)
|
||||||
plaintext, err := be.gcm.Open(plaintext, nonce, ciphertext, nil)
|
plaintext, err := be.gcm.Open(plaintext, nonce, ciphertext, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -87,7 +90,7 @@ func (be *CryptFS) DecryptBlock(ciphertext []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// encryptBlock - Encrypt and add MAC using GCM
|
// 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?
|
// Empty block?
|
||||||
if len(plaintext) == 0 {
|
if len(plaintext) == 0 {
|
||||||
|
@ -98,6 +101,8 @@ func (be *CryptFS) EncryptBlock(plaintext []byte) []byte {
|
||||||
nonce := gcmNonce.Get()
|
nonce := gcmNonce.Get()
|
||||||
|
|
||||||
// Encrypt plaintext and append to nonce
|
// Encrypt plaintext and append to nonce
|
||||||
|
aData := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(aData, blockNo)
|
||||||
ciphertext := be.gcm.Seal(nonce, nonce, plaintext, nil)
|
ciphertext := be.gcm.Seal(nonce, nonce, plaintext, nil)
|
||||||
|
|
||||||
return ciphertext
|
return ciphertext
|
||||||
|
|
|
@ -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.
|
// The ciphertext and dst may alias exactly or not at all.
|
||||||
func (be opensslGCM) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
func (be opensslGCM) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
||||||
|
|
||||||
if len(data) > 0 {
|
|
||||||
panic("Extra data is not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
l := len(ciphertext)
|
l := len(ciphertext)
|
||||||
tag := ciphertext[l-AUTH_TAG_LEN : l]
|
tag := ciphertext[l-AUTH_TAG_LEN : l]
|
||||||
ciphertext = ciphertext[0 : l-AUTH_TAG_LEN]
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
err = dctx.ExtraData(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
part, err := dctx.DecryptUpdate(ciphertext)
|
part, err := dctx.DecryptUpdate(ciphertext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -90,10 +90,6 @@ func (be opensslGCM) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
plainBuf.Write(part)
|
plainBuf.Write(part)
|
||||||
err = dctx.ExtraData(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return plainBuf.Bytes(), nil
|
return plainBuf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,13 +80,12 @@ func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) {
|
||||||
}
|
}
|
||||||
// Truncate ciphertext buffer down to actually read bytes
|
// Truncate ciphertext buffer down to actually read bytes
|
||||||
ciphertext = ciphertext[0:n]
|
ciphertext = ciphertext[0:n]
|
||||||
{
|
|
||||||
blockNo := alignedOffset / f.cfs.CipherBS()
|
blockNo := alignedOffset / f.cfs.CipherBS()
|
||||||
cryptfs.Debug.Printf("ReadAt offset=%d bytes (%d blocks), want=%d, got=%d\n", alignedOffset, blockNo, alignedLength, n)
|
cryptfs.Debug.Printf("ReadAt offset=%d bytes (%d blocks), want=%d, got=%d\n", alignedOffset, blockNo, alignedLength, n)
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt it
|
// Decrypt it
|
||||||
plaintext, err := f.cfs.DecryptBlocks(ciphertext)
|
plaintext, err := f.cfs.DecryptBlocks(ciphertext, blockNo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
blockNo := (alignedOffset + uint64(len(plaintext))) / f.cfs.PlainBS()
|
blockNo := (alignedOffset + uint64(len(plaintext))) / f.cfs.PlainBS()
|
||||||
cipherOff := blockNo * f.cfs.CipherBS()
|
cipherOff := blockNo * f.cfs.CipherBS()
|
||||||
|
@ -159,7 +158,7 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
blockOffset, _ := b.CiphertextRange()
|
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))
|
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()) {
|
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))
|
cryptfs.Debug.Printf("ino%d: Writing partial block #%d (%d bytes)\n", f.ino, b.BlockNo, len(blockData))
|
||||||
|
|
Loading…
Reference in New Issue