contentenc: add "ExternalNonce" mode

This will be used for strong symlink encryption in reverse mode.
This commit is contained in:
Jakob Unterwurzacher 2016-09-25 17:42:59 +02:00
parent 32e55261ca
commit 12808138ef
4 changed files with 16 additions and 7 deletions

View File

@ -168,7 +168,7 @@ func (cf *ConfFile) EncryptKey(key []byte, password string, logN int) {
// Lock master key using password-based key // Lock master key using password-based key
cc := cryptocore.New(scryptHash, cryptocore.BackendGoGCM, 96) cc := cryptocore.New(scryptHash, cryptocore.BackendGoGCM, 96)
ce := contentenc.New(cc, 4096) ce := contentenc.New(cc, 4096)
cf.EncryptedKey = ce.EncryptBlock(key, 0, nil, contentenc.RandomNonce) cf.EncryptedKey = ce.EncryptBlock(key, 0, nil, contentenc.RandomNonce, nil)
} }
// WriteFile - write out config in JSON format to file "filename.tmp" // WriteFile - write out config in JSON format to file "filename.tmp"

View File

@ -22,6 +22,7 @@ const (
_ = iota // skip zero _ = iota // skip zero
RandomNonce NonceMode = iota RandomNonce NonceMode = iota
ReverseDeterministicNonce NonceMode = iota ReverseDeterministicNonce NonceMode = iota
ExternalNonce NonceMode = iota
) )
type ContentEnc struct { type ContentEnc struct {
@ -46,7 +47,7 @@ func New(cc *cryptocore.CryptoCore, plainBS uint64) *ContentEnc {
plainBS: plainBS, plainBS: plainBS,
cipherBS: cipherBS, cipherBS: cipherBS,
allZeroBlock: make([]byte, cipherBS), allZeroBlock: make([]byte, cipherBS),
allZeroNonce: make([]byte, IVBitLen/8), allZeroNonce: make([]byte, cc.IVLen),
} }
} }
@ -132,14 +133,14 @@ func (be *ContentEnc) EncryptBlocks(plaintext []byte, firstBlockNo uint64, fileI
var outBuf bytes.Buffer var outBuf bytes.Buffer
for blockNo := firstBlockNo; inBuf.Len() > 0; blockNo++ { for blockNo := firstBlockNo; inBuf.Len() > 0; blockNo++ {
inBlock := inBuf.Next(int(be.plainBS)) inBlock := inBuf.Next(int(be.plainBS))
outBlock := be.EncryptBlock(inBlock, blockNo, fileId, nMode) outBlock := be.EncryptBlock(inBlock, blockNo, fileId, nMode, nil)
outBuf.Write(outBlock) outBuf.Write(outBlock)
} }
return outBuf.Bytes() return outBuf.Bytes()
} }
// encryptBlock - Encrypt and add IV and MAC // encryptBlock - Encrypt and add IV and MAC
func (be *ContentEnc) EncryptBlock(plaintext []byte, blockNo uint64, fileID []byte, nMode NonceMode) []byte { func (be *ContentEnc) EncryptBlock(plaintext []byte, blockNo uint64, fileID []byte, nMode NonceMode, externalNonce []byte) []byte {
// Empty block? // Empty block?
if len(plaintext) == 0 { if len(plaintext) == 0 {
return plaintext return plaintext
@ -147,11 +148,16 @@ func (be *ContentEnc) EncryptBlock(plaintext []byte, blockNo uint64, fileID []by
var nonce []byte var nonce []byte
switch nMode { switch nMode {
case ExternalNonce:
if be.cryptoCore.AEADBackend != cryptocore.BackendGCMSIV {
panic("MUST NOT use deterministic nonces unless in GCMSIV mode!")
}
nonce = externalNonce
case ReverseDeterministicNonce: case ReverseDeterministicNonce:
if be.cryptoCore.AEADBackend != cryptocore.BackendGCMSIV { if be.cryptoCore.AEADBackend != cryptocore.BackendGCMSIV {
panic("MUST NOT use deterministic nonces unless in GCMSIV mode!") panic("MUST NOT use deterministic nonces unless in GCMSIV mode!")
} }
l := IVBitLen / 8 l := be.cryptoCore.IVLen
nonce = make([]byte, l) nonce = make([]byte, l)
copy(nonce, fileID) copy(nonce, fileID)
// Add the block number to the last 8 byte. Plus one so the block-zero // Add the block number to the last 8 byte. Plus one so the block-zero
@ -164,6 +170,9 @@ func (be *ContentEnc) EncryptBlock(plaintext []byte, blockNo uint64, fileID []by
default: default:
panic("invalid nonce mode") panic("invalid nonce mode")
} }
if len(nonce) != be.cryptoCore.IVLen {
panic("wrong nonce length")
}
// Authenticate block with block number and file ID // Authenticate block with block number and file ID
aData := make([]byte, 8) aData := make([]byte, 8)

View File

@ -256,7 +256,7 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {
// Encrypt // Encrypt
blockOffset := b.BlockCipherOff() blockOffset := b.BlockCipherOff()
blockData = f.contentEnc.EncryptBlock(blockData, b.BlockNo, f.header.Id, contentenc.RandomNonce) blockData = f.contentEnc.EncryptBlock(blockData, b.BlockNo, f.header.Id, contentenc.RandomNonce, nil)
tlog.Debug.Printf("ino%d: Writing %d bytes to block #%d", tlog.Debug.Printf("ino%d: Writing %d bytes to block #%d",
f.ino, uint64(len(blockData))-f.contentEnc.BlockOverhead(), b.BlockNo) f.ino, uint64(len(blockData))-f.contentEnc.BlockOverhead(), b.BlockNo)

View File

@ -326,7 +326,7 @@ func (fs *FS) Symlink(target string, linkName string, context *fuse.Context) (co
return fuse.ToStatus(err) return fuse.ToStatus(err)
} }
// Symlinks are encrypted like file contents (GCM) and base64-encoded // Symlinks are encrypted like file contents (GCM) and base64-encoded
cBinTarget := fs.contentEnc.EncryptBlock([]byte(target), 0, nil, contentenc.RandomNonce) cBinTarget := fs.contentEnc.EncryptBlock([]byte(target), 0, nil, contentenc.RandomNonce, nil)
cTarget := base64.URLEncoding.EncodeToString(cBinTarget) cTarget := base64.URLEncoding.EncodeToString(cBinTarget)
// Handle long file name // Handle long file name