aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2017-06-29 22:05:23 +0200
committerJakob Unterwurzacher2017-06-29 23:44:32 +0200
commit80676c685fe2b52ce0c48a7d9d922895d0c583b8 (patch)
treebb88c7335bf96ba8e61a42f136241bfc687053cd
parent3d32bcd37b751a1ed089bbe07c1341ab8d7b9773 (diff)
contentenc: add safer "bPool" pool variant; add pBlockPool
bPool verifies the lengths of slices going in and out. Also, add a plaintext block pool - pBlockPool - and use it for decryption.
-rw-r--r--internal/contentenc/bpool.go39
-rw-r--r--internal/contentenc/content.go40
-rw-r--r--internal/fusefrontend/file.go4
3 files changed, 56 insertions, 27 deletions
diff --git a/internal/contentenc/bpool.go b/internal/contentenc/bpool.go
new file mode 100644
index 0000000..c4517d3
--- /dev/null
+++ b/internal/contentenc/bpool.go
@@ -0,0 +1,39 @@
+package contentenc
+
+import (
+ "log"
+ "sync"
+)
+
+// bPool is a byte slice pool
+type bPool struct {
+ sync.Pool
+ sliceLen int
+}
+
+func newBPool(sliceLen int) bPool {
+ return bPool{
+ Pool: sync.Pool{
+ New: func() interface{} { return make([]byte, sliceLen) },
+ },
+ sliceLen: sliceLen,
+ }
+}
+
+// Put grows the slice "s" to its maximum capacity and puts it into the pool.
+func (b *bPool) Put(s []byte) {
+ s = s[:cap(s)]
+ if len(s) != b.sliceLen {
+ log.Panicf("wrong len=%d, want=%d", len(s), b.sliceLen)
+ }
+ b.Pool.Put(s)
+}
+
+// Get returns a byte slice from the pool.
+func (b *bPool) Get() (s []byte) {
+ s = b.Pool.Get().([]byte)
+ if len(s) != b.sliceLen {
+ log.Panicf("wrong len=%d, want=%d", len(s), b.sliceLen)
+ }
+ return s
+}
diff --git a/internal/contentenc/content.go b/internal/contentenc/content.go
index 9bc1c50..238683c 100644
--- a/internal/contentenc/content.go
+++ b/internal/contentenc/content.go
@@ -54,18 +54,19 @@ type ContentEnc struct {
// Force decode even if integrity check fails (openSSL only)
forceDecode bool
// Ciphertext block pool. Always returns cipherBS-sized byte slices.
- cBlockPool sync.Pool
- // Ciphertext write pool. Always returns byte slices of size
+ cBlockPool bPool
+ // Ciphertext request data pool. Always returns byte slices of size
// fuse.MAX_KERNEL_WRITE + overhead.
- cWritePool sync.Pool
- cWriteSize int
+ CReqPool bPool
+ // Plaintext block pool. Always returns plainBS-sized byte slices.
+ pBlockPool bPool
}
// New returns an initialized ContentEnc instance.
func New(cc *cryptocore.CryptoCore, plainBS uint64, forceDecode bool) *ContentEnc {
cipherBS := plainBS + uint64(cc.IVLen) + cryptocore.AuthTagLen
// Take IV and GHASH overhead into account.
- cWriteSize := int(fuse.MAX_KERNEL_WRITE / plainBS * cipherBS)
+ cReqSize := int(fuse.MAX_KERNEL_WRITE / plainBS * cipherBS)
if fuse.MAX_KERNEL_WRITE%plainBS != 0 {
log.Panicf("unaligned MAX_KERNEL_WRITE=%d", fuse.MAX_KERNEL_WRITE)
}
@@ -76,22 +77,13 @@ func New(cc *cryptocore.CryptoCore, plainBS uint64, forceDecode bool) *ContentEn
allZeroBlock: make([]byte, cipherBS),
allZeroNonce: make([]byte, cc.IVLen),
forceDecode: forceDecode,
- cWriteSize: cWriteSize,
+ cBlockPool: newBPool(int(cipherBS)),
+ CReqPool: newBPool(cReqSize),
+ pBlockPool: newBPool(int(plainBS)),
}
- c.cBlockPool.New = func() interface{} { return make([]byte, cipherBS) }
- c.cWritePool.New = func() interface{} { return make([]byte, cWriteSize) }
return c
}
-// CWritePut puts "buf" back into the cWritePool.
-func (be *ContentEnc) CWritePut(buf []byte) {
- buf = buf[:cap(buf)]
- if len(buf) != be.cWriteSize {
- log.Panicf("wrong len=%d, want=%d", len(buf), be.cWriteSize)
- }
- be.cWritePool.Put(buf)
-}
-
// PlainBS returns the plaintext block size
func (be *ContentEnc) PlainBS() uint64 {
return be.plainBS
@@ -119,6 +111,7 @@ func (be *ContentEnc) DecryptBlocks(ciphertext []byte, firstBlockNo uint64, file
}
}
pBuf.Write(pBlock)
+ be.pBlockPool.Put(pBlock)
firstBlockNo++
}
return pBuf.Bytes(), err
@@ -158,7 +151,8 @@ func (be *ContentEnc) DecryptBlock(ciphertext []byte, blockNo uint64, fileID []b
ciphertext = ciphertext[be.cryptoCore.IVLen:]
// Decrypt
- var plaintext []byte
+ plaintext := be.pBlockPool.Get()
+ plaintext = plaintext[:0]
aData := make([]byte, 8)
aData = append(aData, fileID...)
binary.BigEndian.PutUint64(aData, blockNo)
@@ -210,16 +204,12 @@ func (be *ContentEnc) EncryptBlocks(plaintextBlocks [][]byte, firstBlockNo uint6
be.doEncryptBlocks(plaintextBlocks, ciphertextBlocks, firstBlockNo, fileID)
}
// Concatenate ciphertext into a single byte array.
- tmp := be.cWritePool.Get().([]byte)
+ tmp := be.CReqPool.Get()
out := bytes.NewBuffer(tmp[:0])
for _, v := range ciphertextBlocks {
out.Write(v)
// Return the memory to cBlockPool
- cBlock := v[:cap(v)]
- if len(cBlock) != int(be.cipherBS) {
- log.Panicf("unexpected cBlock length: len=%d cipherBS=%d", len(cBlock), be.cipherBS)
- }
- be.cBlockPool.Put(cBlock)
+ be.cBlockPool.Put(v)
}
return out.Bytes()
}
@@ -268,7 +258,7 @@ func (be *ContentEnc) doEncryptBlock(plaintext []byte, blockNo uint64, fileID []
aData = append(aData, fileID...)
// Get a cipherBS-sized block of memory, copy the nonce into it and truncate to
// nonce length
- cBlock := be.cBlockPool.Get().([]byte)
+ cBlock := be.cBlockPool.Get()
copy(cBlock, nonce)
cBlock = cBlock[0:len(nonce)]
// Encrypt plaintext and append to nonce
diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go
index f70c9a5..277a71e 100644
--- a/internal/fusefrontend/file.go
+++ b/internal/fusefrontend/file.go
@@ -311,8 +311,8 @@ func (f *file) doWrite(data []byte, off int64) (uint32, fuse.Status) {
}
// Write
_, err = f.fd.WriteAt(ciphertext, cOff)
- // Return memory to cWritePool
- f.fs.contentEnc.CWritePut(ciphertext)
+ // Return memory to CReqPool
+ f.fs.contentEnc.CReqPool.Put(ciphertext)
if err != nil {
tlog.Warn.Printf("doWrite: Write failed: %s", err.Error())
return 0, fuse.ToStatus(err)