@@ -10,6 +10,8 @@ import (
10
10
"runtime"
11
11
"sync"
12
12
13
+ "github.com/hanwen/go-fuse/fuse"
14
+
13
15
"github.com/rfjakob/gocryptfs/internal/cryptocore"
14
16
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
15
17
"github.com/rfjakob/gocryptfs/internal/tlog"
@@ -51,20 +53,43 @@ type ContentEnc struct {
51
53
allZeroNonce []byte
52
54
// Force decode even if integrity check fails (openSSL only)
53
55
forceDecode bool
56
+ // Ciphertext block pool. Always returns cipherBS-sized byte slices.
57
+ cBlockPool sync.Pool
58
+ // Ciphertext write pool. Always returns byte slices of size
59
+ // fuse.MAX_KERNEL_WRITE + overhead.
60
+ cWritePool sync.Pool
61
+ cWriteSize int
54
62
}
55
63
56
64
// New returns an initialized ContentEnc instance.
57
65
func New (cc * cryptocore.CryptoCore , plainBS uint64 , forceDecode bool ) * ContentEnc {
58
66
cipherBS := plainBS + uint64 (cc .IVLen ) + cryptocore .AuthTagLen
59
-
60
- return & ContentEnc {
67
+ // Take IV and GHASH overhead into account.
68
+ cWriteSize := int (fuse .MAX_KERNEL_WRITE / plainBS * cipherBS )
69
+ if fuse .MAX_KERNEL_WRITE % plainBS != 0 {
70
+ log .Panicf ("unaligned MAX_KERNEL_WRITE=%d" , fuse .MAX_KERNEL_WRITE )
71
+ }
72
+ c := & ContentEnc {
61
73
cryptoCore : cc ,
62
74
plainBS : plainBS ,
63
75
cipherBS : cipherBS ,
64
76
allZeroBlock : make ([]byte , cipherBS ),
65
77
allZeroNonce : make ([]byte , cc .IVLen ),
66
78
forceDecode : forceDecode ,
79
+ cWriteSize : cWriteSize ,
80
+ }
81
+ c .cBlockPool .New = func () interface {} { return make ([]byte , cipherBS ) }
82
+ c .cWritePool .New = func () interface {} { return make ([]byte , cWriteSize ) }
83
+ return c
84
+ }
85
+
86
+ // CWritePut puts "buf" back into the cWritePool.
87
+ func (be * ContentEnc ) CWritePut (buf []byte ) {
88
+ buf = buf [:cap (buf )]
89
+ if len (buf ) != be .cWriteSize {
90
+ log .Panicf ("wrong len=%d, want=%d" , len (buf ), be .cWriteSize )
67
91
}
92
+ be .cWritePool .Put (buf )
68
93
}
69
94
70
95
// PlainBS returns the plaintext block size
@@ -185,12 +210,16 @@ func (be *ContentEnc) EncryptBlocks(plaintextBlocks [][]byte, firstBlockNo uint6
185
210
be .doEncryptBlocks (plaintextBlocks , ciphertextBlocks , firstBlockNo , fileID )
186
211
}
187
212
// Concatenate ciphertext into a single byte array.
188
- // Size the output buffer for the maximum possible size (all blocks complete)
189
- // to prevent further allocations in out.Write()
190
- tmp := make ([]byte , len (plaintextBlocks )* int (be .CipherBS ()))
213
+ tmp := be .cWritePool .Get ().([]byte )
191
214
out := bytes .NewBuffer (tmp [:0 ])
192
215
for _ , v := range ciphertextBlocks {
193
216
out .Write (v )
217
+ // Return the memory to cBlockPool
218
+ cBlock := v [:cap (v )]
219
+ if len (cBlock ) != int (be .cipherBS ) {
220
+ log .Panicf ("unexpected cBlock length: len=%d cipherBS=%d" , len (cBlock ), be .cipherBS )
221
+ }
222
+ be .cBlockPool .Put (cBlock )
194
223
}
195
224
return out .Bytes ()
196
225
}
@@ -233,15 +262,22 @@ func (be *ContentEnc) doEncryptBlock(plaintext []byte, blockNo uint64, fileID []
233
262
if len (nonce ) != be .cryptoCore .IVLen {
234
263
log .Panic ("wrong nonce length" )
235
264
}
236
-
237
- // Authenticate block with block number and file ID
265
+ // Block is authenticated with block number and file ID
238
266
aData := make ([]byte , 8 )
239
267
binary .BigEndian .PutUint64 (aData , blockNo )
240
268
aData = append (aData , fileID ... )
241
-
269
+ // Get a cipherBS-sized block of memory, copy the nonce into it and truncate to
270
+ // nonce length
271
+ cBlock := be .cBlockPool .Get ().([]byte )
272
+ copy (cBlock , nonce )
273
+ cBlock = cBlock [0 :len (nonce )]
242
274
// Encrypt plaintext and append to nonce
243
- ciphertext := be .cryptoCore .AEADCipher .Seal (nonce , nonce , plaintext , aData )
244
-
275
+ ciphertext := be .cryptoCore .AEADCipher .Seal (cBlock , nonce , plaintext , aData )
276
+ overhead := int (be .cipherBS - be .plainBS )
277
+ if len (plaintext )+ overhead != len (ciphertext ) {
278
+ log .Panicf ("unexpected ciphertext length: plaintext=%d, overhead=%d, ciphertext=%d" ,
279
+ len (plaintext ), overhead , len (ciphertext ))
280
+ }
245
281
return ciphertext
246
282
}
247
283
0 commit comments