aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/contentenc/offsets.go15
1 files changed, 14 insertions, 1 deletions
diff --git a/internal/contentenc/offsets.go b/internal/contentenc/offsets.go
index fdeb583..7487baf 100644
--- a/internal/contentenc/offsets.go
+++ b/internal/contentenc/offsets.go
@@ -31,7 +31,11 @@ func (be *ContentEnc) BlockNoToPlainOff(blockNo uint64) uint64 {
return blockNo * be.plainBS
}
-// CipherSizeToPlainSize calculates the plaintext size from a ciphertext size
+// CipherSizeToPlainSize calculates the plaintext size `plainSize` from a
+// ciphertext size `cipherSize` (in bytes).
+//
+// Not all ciphertext sizes are legal due to the per-block overheads.
+// For an illegal cipherSize, we return a best guess plainSize.
func (be *ContentEnc) CipherSizeToPlainSize(cipherSize uint64) uint64 {
// Zero-sized files stay zero-sized
if cipherSize == 0 {
@@ -49,6 +53,15 @@ func (be *ContentEnc) CipherSizeToPlainSize(cipherSize uint64) uint64 {
return 0
}
+ // If the last block is incomplete, pad it to 1 byte of plaintext
+ // (= 33 bytes of ciphertext).
+ lastBlockSize := (cipherSize - HeaderLen) % be.cipherBS
+ if lastBlockSize > 0 && lastBlockSize <= be.BlockOverhead() {
+ tmp := cipherSize - lastBlockSize + be.BlockOverhead() + 1
+ tlog.Warn.Printf("cipherSize %d: incomplete last block (%d bytes), padding to %d bytes", cipherSize, lastBlockSize, tmp)
+ cipherSize = tmp
+ }
+
// Block number at last byte
blockNo := be.CipherOffToBlockNo(cipherSize - 1)
blockCount := blockNo + 1